Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Hart Auto-Load #919

Open
wants to merge 2 commits into
base: develop
Choose a base branch
from
Open

Hart Auto-Load #919

wants to merge 2 commits into from

Conversation

yezr
Copy link
Collaborator

@yezr yezr commented Feb 14, 2025

fixes #918

yezr added 2 commits February 14, 2025 15:06
…cords. Use that in overriden gatherUnknownCandidates for auto-loading.
@yezr
Copy link
Collaborator Author

yezr commented Feb 14, 2025

To facilitate getting v2.0 out the door, and with Armin out, I drafted a PR for #918. The logic works, but I would love a review of the code syntax.

candidateCode = Tabulator.UNDECLARED_WRITE_IN_OUTPUT_LABEL;
}
if (this.candidateCodesToCandidates.containsKey(candidateCode)) {
if (!this.candidateCodesToCandidates.get(candidateCode).Name.equals(candidateName)) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These two ifs can be simplified a bit:

Candidate existingCandidate = this.candidateCodesToCandidates.get(candidateCode);
if (existingCandidate != null && existingCandidate.Name.equals(candidateName)) {

Candidate Code %s associated with more than one candidate name.
Originally associated with name '%s'.
In CVR at '%s' it is associated with '%s'.
""".formatted(candidateCode,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This syntax will cause the error message to have a ton of spaces throughout the error message. Using +s will avoid that:

                String message =
                        "Candidate Code %s associated with more than one candidate name.  " +
                        "Originally associated with name '%s'. " + 
                        "In CVR at '%s' it is associated with '%s'."
                        .formatted(candidateCode,

throw new CastVoteRecord.CvrParseException();
}
} else {
if (!candidateCode.equals(Tabulator.UNDECLARED_WRITE_IN_OUTPUT_LABEL)) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Combine into else if { rather than else { if {

if (!candidateCode.equals(Tabulator.UNDECLARED_WRITE_IN_OUTPUT_LABEL)) {
this.candidateCodesToCandidates.put(candidateCode,
new Candidate(candidateName, candidateCode));
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you can simplify this whole block using computeIfAbsent:

          for (Option option : contest.Options) {
            final String candidateCode = option.Id;
            final String candidateName = option.Name;
            final boolean isUndeclaredWriteIn = candidateCode.equals(
                    source.getUndeclaredWriteInLabel());

            if (!isUndeclaredWriteIn) {
              this.candidateCodesToCandidates.computeIfAbsent(candidateCode, k ->
                      new Candidate(candidateName, candidateCode));

              String candidateNameFromMap = this.candidateCodesToCandidates.get(candidateCode).Name;
              if (!candidateNameFromMap.equals(candidateName)) {
                String message = String.format(
                        "Candidate Code %s associated with more than one candidate name. "
                                + "Originally associated with name '%s'. "
                                + "In CVR at '%s' it is associated with '%s'.",
                        candidateCode, candidateNameFromMap, path.getFileName(), candidateName
                );
                Logger.severe(message);
                throw new CastVoteRecord.CvrParseException();
              }
            }

            // Hart RCV election ranks are indicated by a string read left to right:
            // each digit corresponds to a rank and is set to 1 if that rank was voted:
            // 0100 indicates rank 2 was voted
            // 0000 indicates no rank was voted (undervote)
            // 0101 indicates ranks 2 and 4 are voted (overvote)
            for (int rank = 1; rank < option.Value.length() + 1; rank++) {
              String rankValue = option.Value.substring(rank - 1, rank);
              if (rankValue.equals("1")) {
                if (isUndeclaredWriteIn) {
                  rankings.add(new Pair<>(rank, UNDECLARED_WRITE_IN_OUTPUT_LABEL));
                } else {
                  rankings.add(new Pair<>(rank, candidateCode));
                }
              }
            }
          }

} catch (CastVoteRecord.CvrParseException e) {
Logger.severe("Error gathering Unknown Candidates\n%s", e);
return new HashSet<>();
} catch (IOException e) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can collapse the two catches into one:

      } catch (CastVoteRecord.CvrParseException | IOException e) {

Set<String> knownNames = config.getCandidateNames();
if (this.candidateCodesToCandidates.entrySet().isEmpty()) {
try {
//Reading the CVRs will load this.candidateCodestoCandidates
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
//Reading the CVRs will load this.candidateCodestoCandidates
// Reading the CVRs will load this.candidateCodestoCandidates

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Hart: Auto load candidate name and alias correctly
2 participants