Duplicate Vote Issue

1st Voter Scan their finger and cast vote if 1st voter scan the finger again it only then it detect duplicate vote.
If a second voter scan finger and cast vote and 1st voter come again and scan finger it register 1st one as a normal voter and add vote and Does not detect that 1st one is already cast the vote

`#include <Wire.h>
#include <Adafruit_Fingerprint.h>
#include <SoftwareSerial.h>
#include <LiquidCrystal_I2C.h>
#include <Adafruit_Thermal.h>
// Fingerprint Sensor Definitions
SoftwareSerial fingerSerial(2, 3); // RX, TX for fingerprint sensor
Adafruit_Fingerprint finger = Adafruit_Fingerprint(&fingerSerial);
// LCD Definitions
LiquidCrystal_I2C lcd(0x27, 20, 4);

// Thermal Printer Definitions
SoftwareSerial printerSerial(10, 11); // RX, TX for thermal printer
Adafruit_Thermal printer(&printerSerial);
const int buttonPin1 = 4;  
const int buttonPin2 = 5; 
const int buttonPin3 = 6; 
const int buzzer = 7;

int buttonState1 = 0;
int buttonState2 = 0;
int buttonState3 = 0;
int G_led = 8; // choose the pin for the Green LED
int R_led = 9; // choose the pin for the Red Led
int id = 0;
int previous_voter_id = 0;
vote_taken = 0;
int PTI = 0, PPP = 0, ANP = 0;

String winner_name = "";

void setup() {
  pinMode(buzzer, OUTPUT);
  pinMode(buttonPin1, INPUT);
  pinMode(buttonPin2, INPUT);
  pinMode(buttonPin3, INPUT);
  pinMode(G_led, OUTPUT);
  pinMode(R_led, OUTPUT);

  lcd.begin();
  lcd.backlight();
  Serial.begin(9600);

  while (!Serial);  // For Yun/Leo/Micro/Zero/...
  delay(100);

  finger.begin(57600);
  
  if (finger.verifyPassword()) {
    Serial.println("Found fingerprint sensor!");
  } else {
    Serial.println("Did not find fingerprint sensor :(");
    while (1) { delay(1); }
  }

  finger.getTemplateCount();
  Serial.print("Sensor contains "); Serial.print(finger.templateCount); 
  Serial.println(" templates");
  Serial.println("Waiting for valid finger...");

  displayWelcomeMessage();
}
void loop() {
  vote_taken = 0;
  displayScanPrompt();
  displayCandidates();
  enableButtons();

// Define a variable to keep track of the previous voter ID
int previous_voter_id = -1;
  id = getFingerprintIDez();
  if (id >= 0) {
    displayVoterID(id);
  
    lcd.setCursor(0, 1);
    if (id == 4) {
       determineWinner();
      displayWinner();
      printResults();
      
      while (1);
    }
    if (previous_voter_id != id) {
      processVote();
    } else {
      handleDuplicateVote();
    }
  }
}
void processVote() {

   // Check if the voter has already voted
   if (previous_voter_id != id) {
      processVote();
    } else {
      handleDuplicateVote();
    }
  do {
    displayVotePrompt();
    previous_voter_id = id;
    buttonState1 = digitalRead(buttonPin1);
    delay(10);
    buttonState2 = digitalRead(buttonPin2);
    delay(10);
    buttonState3 = digitalRead(buttonPin3);
    delay(10);
    if (buttonState1 == HIGH) {
      PTI++;
      vote_taken = 1;
      lcd.setCursor(0, 3);
      lcd.print("Receipt in Printing.");
      printReceipt("PTI");
      activateBuzzerAndLED(1);
    } 
    else if (buttonState2 == HIGH) {
      PPP++;
      lcd.setCursor(0, 3);
      lcd.print("Receipt in Printing.");
      printReceipt("PPP");
      activateBuzzerAndLED(1);
      vote_taken = 1;
    } 
    else if (buttonState3 == HIGH) {
      ANP++;
      lcd.setCursor(0, 3);
      lcd.print("Receipt in Printing.");
      printReceipt("ANP");
      activateBuzzerAndLED(1);
      vote_taken = 1;
    } 
    else {
      vote_taken = 0;
    }
    
    // Thank the voter if a vote was taken
    if (vote_taken)if (vote_taken == 1) {
      thankVoter();
    }
  } while (vote_taken == 0);
}

}
void determineWinner() {
 if ((PTI > PPP) && (PTI > ANP)) {
    winner_name = "PTI";
  } else if ((PPP > PTI) && (PPP > ANP)) {
    winner_name = "PPP";
  } else {
    winner_name = "ANP";
  }

}

void displayWelcomeMessage() {
 lcd.clear();
  lcd.print("Digital Electoral");
  lcd.setCursor(0, 1);
  lcd.print("System");
  delay(2000);
  lcd.clear();
}

void displayScanPrompt() {
  lcd.clear(); 
  lcd.setCursor(0, 0);  
  lcd.print("Please place your"); 
  lcd.setCursor(0, 1);
  lcd.print("finger");
}

void displayVoterID(int id) {
  lcd.clear();
  lcd.setCursor(0, 0);  
  lcd.print("Your Voter ID"); 
  lcd.setCursor(0, 1);
  lcd.print(id);
  delay(2000);
}
void displayCandidates() {
  
  lcd.clear();
  lcd.print("``CANDIDATES``");
  lcd.setCursor(0, 1);
  lcd.print("PTI:");
  lcd.print(PTI);
  lcd.setCursor(0, 2);
  lcd.print("PPP:");
  lcd.print(PPP);
  lcd.setCursor(0, 3);
  lcd.print("ANP:");
  lcd.print(ANP);
}

void enableButtons() {
  pinMode(buttonPin1, INPUT);
  pinMode(buttonPin2, INPUT);
  pinMode(buttonPin3, INPUT);
}

void displayVotePrompt() {
  lcd.clear();
  lcd.setCursor(0, 0);  
  lcd.print("Give Your vote"); 
  lcd.setCursor(0, 1);
  lcd.print("Press Button");
  delay(500);
}

void thankVoter() {
  lcd.clear();
  lcd.setCursor(0, 0);  
  lcd.print("Thanks for your"); 
  lcd.setCursor(0, 1);
  lcd.print("vote");
  delay(200);
  activateBuzzerAndLED(1);
}

void disableButtons() {
  pinMode(buttonPin1, OUTPUT);
  pinMode(buttonPin2, OUTPUT);
  pinMode(buttonPin3, OUTPUT);
}
void displayWinner() {
  lcd.clear();
  lcd.setCursor(0, 0);  
  lcd.print("Winner party"); 
  lcd.setCursor(0, 1);
  lcd.print(winner_name);
}
void handleDuplicateVote() {
  lcd.clear();
  lcd.setCursor(0, 0);  
  lcd.print("Duplicate Vote"); 
  lcd.setCursor(0, 1);
  lcd.print("Buttons disabled");
  delay(2000);
  
  // Disable voting buttons
  digitalWrite(buttonPin1, LOW);
  digitalWrite(buttonPin2, LOW);
  digitalWrite(buttonPin3, LOW);
  
  activateBuzzerAndLED(3);
}

void activateBuzzerAndLED(int times) {
  for (int i = 0; i < times; i++) {
    digitalWrite(buzzer, HIGH);
    digitalWrite(R_led, HIGH);
    digitalWrite(G_led, LOW);
    delay(1000);
    digitalWrite(buzzer, LOW);
    digitalWrite(R_led, LOW);
    digitalWrite(G_led, HIGH);
    delay(1000);
  }
}
void printReceipt(String candidate) {
  printer.println("Vote Casted:");
  printer.println(candidate);
  printer.feed(2);
}
void printResults() {
  lcd.clear();
  lcd.print("Results:");
  lcd.setCursor(0, 1);
  lcd.print("PTI:");
  lcd.print(PTI);
  lcd.setCursor(0, 1);
  lcd.print("PPP:");
  lcd.print(PPP);
  lcd.setCursor(0, 1);
  lcd.print("ANP:");
  lcd.print(ANP);
  lcd.setCursor(0, 3);
  lcd.print("Receipt in Printing.");

  printer.println("Election Results");
  printer.println("PTI: " + String(PTI));
  printer.println("PPP: " + String(PPP));
  printer.println("ANP: " + String(ANP));
  printer.feed(3);
 activateBuzzerAndLED(1);
}
uint8_t getFingerprintID() {
  uint8_t p = finger.getImage();
  if (p != FINGERPRINT_OK) return -1;

  p = finger.image2Tz();
  if (p != FINGERPRINT_OK) return -1;

  p = finger.fingerFastSearch();
  if (p != FINGERPRINT_OK) return -1;

  Serial.print("Found ID #"); Serial.print(finger.fingerID); 
  Serial.print(" with confidence of "); Serial.println(finger.confidence); 
  return finger.fingerID;
}

int getFingerprintIDez() {
  uint8_t p = finger.getImage();
  if (p != FINGERPRINT_OK) return -1;

  p = finger.image2Tz();
  if (p != FINGERPRINT_OK) return -1;

  p = finger.fingerFastSearch();
  if (p != FINGERPRINT_OK) return -1;

  Serial.print("Found ID #"); Serial.print(finger.fingerID); 
  Serial.print(" with confidence of "); Serial.println(finger.confidence);
  return finger.fingerID; 
}
`

Can you suggest some thing for determineWinner() Function.

Yours look close

void determineWinner() {
 if ((PTI > PPP) && (PTI > ANP)) {
    winner_name = "PTI";    // PTI wins, so we only need to look at the other two
  } else if (PPP > ANP) {
    winner_name = "PPP";
  } else {
    winner_name = "ANP";
  }
}

This works but has no logic for seven other possible outcomes involving cases where two parties receive identical number of votes, only three of which are cases winners. Without worrying further about whether by majority or plurality.

Have you considered the potential for paper ballots?

But you've asked about duplicate voting. Your logic only keeps a voter from voting twice in a row, do you understand @Delta_G's point and suggestions?

a7

Then you can try implementing the more complex rank choice voting.

It would help greatly if you could post the sketch as a single piece of code, not many are going to take the time to copy each individual function and recombine them into a single sketch for testing.

"Does anyone else have a reasonable suggestion?"

Although I take offense from these follow-up questions to my answers, I understand, most of the time (in every subject), the person asking the question only understands a response to their level of knowledge. Simply, "We only hear what we know." Your answer was precise. They did not understand their own question, much less the answer, or the precision of the answer. Learning requires the desire to correct our (lack of) knowledge. When you re-visit this topic, you will probably see that your information has become someone else's brilliant idea. Another, un-seen, un-heard person will read your information and click the "like" (dare I say heart) to let you know, it was worth your time.