From 65ee3e3e03426c5d0325b1e178a0923a52f88484 Mon Sep 17 00:00:00 2001 From: vteague Date: Sun, 14 Jul 2024 12:27:07 +1000 Subject: [PATCH 01/21] Reading IRV ContestResult winners from database; stubs for test classes. --- .../endpoint/AbstractAllIrvEndpoint.java | 36 +++++++++++++++++-- .../corla/endpoint/GetAssertions.java | 11 +++--- .../controller/ComparisonAuditController.java | 2 ++ .../corla/controller/ContestCounter.java | 1 + .../corla/model/ComparisonAudit.java | 4 +-- .../corla/persistence/entity_classes | 1 + ...ny_IRV_Boulder2023_Test_Canonical_List.csv | 8 ++--- 7 files changed, 48 insertions(+), 15 deletions(-) diff --git a/server/eclipse-project/src/main/java/au/org/democracydevelopers/corla/endpoint/AbstractAllIrvEndpoint.java b/server/eclipse-project/src/main/java/au/org/democracydevelopers/corla/endpoint/AbstractAllIrvEndpoint.java index eef1ac42..4fcb9d76 100644 --- a/server/eclipse-project/src/main/java/au/org/democracydevelopers/corla/endpoint/AbstractAllIrvEndpoint.java +++ b/server/eclipse-project/src/main/java/au/org/democracydevelopers/corla/endpoint/AbstractAllIrvEndpoint.java @@ -22,6 +22,8 @@ package au.org.democracydevelopers.corla.endpoint; import au.org.democracydevelopers.corla.model.ContestType; +import au.org.democracydevelopers.corla.model.GenerateAssertionsSummary; +import au.org.democracydevelopers.corla.query.GenerateAssertionsSummaryQueries; import com.google.gson.Gson; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClients; @@ -31,7 +33,11 @@ import us.freeandfair.corla.controller.ContestCounter; import us.freeandfair.corla.endpoint.AbstractDoSDashboardEndpoint; import us.freeandfair.corla.model.*; +import us.freeandfair.corla.persistence.Persistence; + import java.util.List; +import java.util.Optional; +import java.util.Set; /** * An abstract endpoint for communicating with raire. Includes all the information for collecting IRV contests @@ -101,11 +107,11 @@ public static List getIRVContestResults() { .filter(cr -> cr.getContests().stream().map(Contest::description) .anyMatch(d -> d.equalsIgnoreCase(ContestType.IRV.toString()))).toList(); - // The above should be sufficient, but just in case, check that each contest we found _all_ matches IRV, and - // throw a RuntimeException if not. + // The above should be sufficient, but just in case, check that each contest we found _all_ + // matches IRV, and throw a RuntimeException if not. for (final ContestResult cr : results) { if (cr.getContests().stream().map(Contest::description) - .anyMatch(d -> !d.equalsIgnoreCase(ContestType.IRV.toString()))) { + .anyMatch(d -> !d.equalsIgnoreCase(ContestType.IRV.toString()))) { LOGGER.error(String.format("%s %s %s", prefix, msg, cr.getContestName())); throw new RuntimeException(msg + cr.getContestName()); } @@ -113,4 +119,28 @@ public static List getIRVContestResults() { return results; } + + /** + * Use the summaries from the GenerateAssertionsResponseSummary table to update IRV contest + * results. This should be run before anything that needs to know an IRV winner. + * It updates most of the same data as ContestCounter.CountAllContests(), but assumes that + * the contests, counties and contest name are already properly set, along with ballotCount, + * auditReason and winnersAllowed. + * Losers, vote totals and (min, max and diluted) margins remain wrong, and are never used. + * @return the IRV contest results, with winners updated from the database. + */ + public static List getAndUpdateIRVContestResults() { + + final List results = getIRVContestResults(); + + for(ContestResult cr : results) { + Optional optSummary + = GenerateAssertionsSummaryQueries.matching(cr.getContestName()); + optSummary.ifPresent(generateAssertionsSummary + -> cr.setWinners(Set.of(generateAssertionsSummary.winner))); + } + + Persistence.flush(); + return results; + } } diff --git a/server/eclipse-project/src/main/java/au/org/democracydevelopers/corla/endpoint/GetAssertions.java b/server/eclipse-project/src/main/java/au/org/democracydevelopers/corla/endpoint/GetAssertions.java index caab46b0..11abfb4c 100644 --- a/server/eclipse-project/src/main/java/au/org/democracydevelopers/corla/endpoint/GetAssertions.java +++ b/server/eclipse-project/src/main/java/au/org/democracydevelopers/corla/endpoint/GetAssertions.java @@ -50,6 +50,8 @@ import us.freeandfair.corla.model.DoSDashboard; import us.freeandfair.corla.util.SparkHelper; +import static au.org.democracydevelopers.corla.endpoint.GenerateAssertions.UNKNOWN_WINNER; + /** * The Get Assertions endpoint. Takes a GetAssertionsRequest, and an optional format parameter specifying CSV or JSON, * defaulting to json. Returns a zip of all assertions for all IRV contests, in the requested format. @@ -165,14 +167,11 @@ public void getAssertions(final ZipOutputStream zos, final BigDecimal riskLimit, // Iterate through all IRV Contests, sending a request to the raire-service for each one's assertions and // collating the responses. - final List IRVContestResults = AbstractAllIrvEndpoint.getIRVContestResults(); - for (final ContestResult cr : IRVContestResults) { + final List updatedIRVContestResults = AbstractAllIrvEndpoint.getAndUpdateIRVContestResults(); + for (final ContestResult cr : updatedIRVContestResults) { // Find the winner (there should only be one), candidates and contest name. - // TODO At the moment, the winner isn't yet set properly - will be set in the GenerateAssertions Endpoint. - // See https://github.com/DemocracyDevelopers/colorado-rla/issues/73 - // For now, tolerate > 1; later, check. - final String winner = cr.getWinners().stream().findAny().orElse("UNKNOWN"); + final String winner = cr.getWinners().stream().findAny().orElse(UNKNOWN_WINNER); final List candidates = cr.getContests().stream().findAny().orElseThrow().choices().stream() .map(Choice::name).toList(); diff --git a/server/eclipse-project/src/main/java/us/freeandfair/corla/controller/ComparisonAuditController.java b/server/eclipse-project/src/main/java/us/freeandfair/corla/controller/ComparisonAuditController.java index 84ccc09e..06fb4929 100644 --- a/server/eclipse-project/src/main/java/us/freeandfair/corla/controller/ComparisonAuditController.java +++ b/server/eclipse-project/src/main/java/us/freeandfair/corla/controller/ComparisonAuditController.java @@ -173,6 +173,7 @@ public static ComparisonAudit createAuditOfCorrectType(final ContestResult conte if (contestResult.getContests().stream().map(Contest::description).allMatch(d -> d.equals(ContestType.PLURALITY.toString()))) { return new ComparisonAudit(contestResult, riskLimit, contestResult.getDilutedMargin(), Audit.GAMMA, contestResult.getAuditReason()); } + // If it is all IRV, make an IRVComparisonAudit. if (contestResult.getContests().stream().map(Contest::description).allMatch(d -> d.equals(ContestType.IRV.toString()))) { return new IRVComparisonAudit(contestResult, riskLimit, contestResult.getAuditReason()); @@ -198,6 +199,7 @@ public static ComparisonAudit createAudit(final ContestResult contestResult, Persistence.save(ca); LOGGER.debug(String.format("[createAudit: contestResult=%s, ComparisonAudit=%s]", contestResult, ca)); + return ca; } diff --git a/server/eclipse-project/src/main/java/us/freeandfair/corla/controller/ContestCounter.java b/server/eclipse-project/src/main/java/us/freeandfair/corla/controller/ContestCounter.java index 6494e792..63c4b3c9 100644 --- a/server/eclipse-project/src/main/java/us/freeandfair/corla/controller/ContestCounter.java +++ b/server/eclipse-project/src/main/java/us/freeandfair/corla/controller/ContestCounter.java @@ -12,6 +12,7 @@ import java.util.Set; import java.util.stream.Collectors; +import au.org.democracydevelopers.corla.model.ContestType; import org.apache.log4j.LogManager; import org.apache.log4j.Logger; diff --git a/server/eclipse-project/src/main/java/us/freeandfair/corla/model/ComparisonAudit.java b/server/eclipse-project/src/main/java/us/freeandfair/corla/model/ComparisonAudit.java index d5801885..3ad49674 100644 --- a/server/eclipse-project/src/main/java/us/freeandfair/corla/model/ComparisonAudit.java +++ b/server/eclipse-project/src/main/java/us/freeandfair/corla/model/ComparisonAudit.java @@ -797,10 +797,10 @@ public int multiplicity(final Long cvrId) { /** * Records the specified discrepancy. If the discrepancy is for this Contest * but from a CVR/ballot that was not selected for this Contest (selected for - * another Contest), is does not contribute to the counts and calculations. It + * another Contest), it does not contribute to the counts and calculations. It * is still recorded, though, for informational purposes. The valid range is * -2 .. 2: -2 and -1 are understatements, 0 is a discrepancy that doesn't - * affect the RLA calculations, and 1 and 2 are overstatements). + * affect the RLA calculations, and 1 and 2 are overstatements. * * @param the_record The CVRAuditInfo record that generated the discrepancy. * @param the_type The type of discrepancy to add. diff --git a/server/eclipse-project/src/main/resources/us/freeandfair/corla/persistence/entity_classes b/server/eclipse-project/src/main/resources/us/freeandfair/corla/persistence/entity_classes index d84c4842..fa854c4b 100644 --- a/server/eclipse-project/src/main/resources/us/freeandfair/corla/persistence/entity_classes +++ b/server/eclipse-project/src/main/resources/us/freeandfair/corla/persistence/entity_classes @@ -24,3 +24,4 @@ au.org.democracydevelopers.corla.model.assertion.Assertion au.org.democracydevelopers.corla.model.assertion.NEBAssertion au.org.democracydevelopers.corla.model.assertion.NENAssertion au.org.democracydevelopers.corla.model.IRVComparisonAudit +au.org.democracydevelopers.corla.model.GenerateAssertionsSummary diff --git a/server/eclipse-project/src/test/resources/CSVs/Tiny-IRV-Examples/Tiny_IRV_Boulder2023_Test_Canonical_List.csv b/server/eclipse-project/src/test/resources/CSVs/Tiny-IRV-Examples/Tiny_IRV_Boulder2023_Test_Canonical_List.csv index 51cf432e..b265e683 100644 --- a/server/eclipse-project/src/test/resources/CSVs/Tiny-IRV-Examples/Tiny_IRV_Boulder2023_Test_Canonical_List.csv +++ b/server/eclipse-project/src/test/resources/CSVs/Tiny-IRV-Examples/Tiny_IRV_Boulder2023_Test_Canonical_List.csv @@ -1,6 +1,6 @@ CountyName,ContestName,ContestChoices Boulder,City of Boulder Mayoral,"Aaron Brockett,Nicole Speer,Bob Yates,Paul Tweedlie," -Arapahoe,TinyExample1,"Alice, Bob, Chuan" -Arapahoe,PluralityExample1,"Diego, Eli, Farhad" -Arapahoe,PluralityExample2,"Gertrude, Ho, Imogen" -Arapahoe,Example3,"A,B,C,D" +Adams,TinyExample1,"Alice, Bob, Chuan" +Adams,PluralityExample1,"Diego, Eli, Farhad" +Adams,PluralityExample2,"Gertrude, Ho, Imogen" +Adams,Example3,"A,B,C,D" From 60438fe2eb1a39af78d47f7893180081355700c1 Mon Sep 17 00:00:00 2001 From: vteague Date: Sun, 14 Jul 2024 16:46:18 +1000 Subject: [PATCH 02/21] Correct winners in GetAssertions. --- .../corla/endpoint/AbstractAllIrvEndpoint.java | 14 ++++++++++---- .../corla/endpoint/GenerateAssertions.java | 2 +- .../corla/endpoint/GetAssertions.java | 5 +++-- .../corla/model/IRVComparisonAudit.java | 15 ++++++--------- 4 files changed, 20 insertions(+), 16 deletions(-) diff --git a/server/eclipse-project/src/main/java/au/org/democracydevelopers/corla/endpoint/AbstractAllIrvEndpoint.java b/server/eclipse-project/src/main/java/au/org/democracydevelopers/corla/endpoint/AbstractAllIrvEndpoint.java index 4fcb9d76..7a6cfce5 100644 --- a/server/eclipse-project/src/main/java/au/org/democracydevelopers/corla/endpoint/AbstractAllIrvEndpoint.java +++ b/server/eclipse-project/src/main/java/au/org/democracydevelopers/corla/endpoint/AbstractAllIrvEndpoint.java @@ -134,13 +134,19 @@ public static List getAndUpdateIRVContestResults() { final List results = getIRVContestResults(); for(ContestResult cr : results) { - Optional optSummary - = GenerateAssertionsSummaryQueries.matching(cr.getContestName()); - optSummary.ifPresent(generateAssertionsSummary - -> cr.setWinners(Set.of(generateAssertionsSummary.winner))); + updateIRVContestWinner(cr); } Persistence.flush(); return results; } + + // FIXME check for IRV, deal with absent winners (set to UNKNOWN?) + public static ContestResult updateIRVContestWinner(ContestResult cr) { + + Optional optSummary + = GenerateAssertionsSummaryQueries.matching(cr.getContestName()); + optSummary.ifPresent(generateAssertionsSummary + -> cr.setWinners(Set.of(generateAssertionsSummary.winner))); + } } diff --git a/server/eclipse-project/src/main/java/au/org/democracydevelopers/corla/endpoint/GenerateAssertions.java b/server/eclipse-project/src/main/java/au/org/democracydevelopers/corla/endpoint/GenerateAssertions.java index d1350e04..fa7d3896 100644 --- a/server/eclipse-project/src/main/java/au/org/democracydevelopers/corla/endpoint/GenerateAssertions.java +++ b/server/eclipse-project/src/main/java/au/org/democracydevelopers/corla/endpoint/GenerateAssertions.java @@ -94,7 +94,7 @@ public class GenerateAssertions extends AbstractAllIrvEndpoint { /** * Default winner to be used in the case where winner is unknown. */ - protected static final String UNKNOWN_WINNER = "Unknown"; + public static final String UNKNOWN_WINNER = "Unknown"; /** * {@inheritDoc} diff --git a/server/eclipse-project/src/main/java/au/org/democracydevelopers/corla/endpoint/GetAssertions.java b/server/eclipse-project/src/main/java/au/org/democracydevelopers/corla/endpoint/GetAssertions.java index 11abfb4c..ba328908 100644 --- a/server/eclipse-project/src/main/java/au/org/democracydevelopers/corla/endpoint/GetAssertions.java +++ b/server/eclipse-project/src/main/java/au/org/democracydevelopers/corla/endpoint/GetAssertions.java @@ -167,8 +167,9 @@ public void getAssertions(final ZipOutputStream zos, final BigDecimal riskLimit, // Iterate through all IRV Contests, sending a request to the raire-service for each one's assertions and // collating the responses. - final List updatedIRVContestResults = AbstractAllIrvEndpoint.getAndUpdateIRVContestResults(); - for (final ContestResult cr : updatedIRVContestResults) { + final List IRVContestResults = AbstractAllIrvEndpoint.getIRVContestResults(); + final List correctWinnersIRVContestResults = IRVContestResults.stream().map(AbstractAllIrvEndpoint::updateIRVContestWinner).toList(); + for (final ContestResult cr : correctWinnersIRVContestResults) { // Find the winner (there should only be one), candidates and contest name. final String winner = cr.getWinners().stream().findAny().orElse(UNKNOWN_WINNER); diff --git a/server/eclipse-project/src/main/java/au/org/democracydevelopers/corla/model/IRVComparisonAudit.java b/server/eclipse-project/src/main/java/au/org/democracydevelopers/corla/model/IRVComparisonAudit.java index 027bdf87..22a23097 100644 --- a/server/eclipse-project/src/main/java/au/org/democracydevelopers/corla/model/IRVComparisonAudit.java +++ b/server/eclipse-project/src/main/java/au/org/democracydevelopers/corla/model/IRVComparisonAudit.java @@ -22,23 +22,20 @@ package au.org.democracydevelopers.corla.model; import au.org.democracydevelopers.corla.query.AssertionQueries; +import au.org.democracydevelopers.corla.query.GenerateAssertionsSummaryQueries; import com.google.inject.internal.util.ImmutableList; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import javax.persistence.DiscriminatorValue; -import javax.persistence.Entity; -import javax.persistence.JoinColumn; -import javax.persistence.JoinTable; -import javax.persistence.ManyToMany; + +import java.util.*; +import javax.persistence.*; + import us.freeandfair.corla.math.Audit; import us.freeandfair.corla.model.*; import java.math.BigDecimal; -import java.util.OptionalInt; import au.org.democracydevelopers.corla.model.assertion.Assertion; +import static au.org.democracydevelopers.corla.endpoint.GenerateAssertions.UNKNOWN_WINNER; import static java.util.Collections.max; /** From 919b9945387a8771db4c88848c8fd9db89fe76ec Mon Sep 17 00:00:00 2001 From: vteague Date: Sun, 14 Jul 2024 17:01:22 +1000 Subject: [PATCH 03/21] Set winner from database read in GetAssertions. --- .../democracydevelopers/corla/endpoint/GetAssertions.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/server/eclipse-project/src/main/java/au/org/democracydevelopers/corla/endpoint/GetAssertions.java b/server/eclipse-project/src/main/java/au/org/democracydevelopers/corla/endpoint/GetAssertions.java index ba328908..e76e749f 100644 --- a/server/eclipse-project/src/main/java/au/org/democracydevelopers/corla/endpoint/GetAssertions.java +++ b/server/eclipse-project/src/main/java/au/org/democracydevelopers/corla/endpoint/GetAssertions.java @@ -33,6 +33,7 @@ import au.org.democracydevelopers.corla.communication.requestToRaire.GetAssertionsRequest; import au.org.democracydevelopers.corla.communication.responseFromRaire.RaireServiceErrors; +import au.org.democracydevelopers.corla.query.GenerateAssertionsSummaryQueries; import org.apache.commons.io.IOUtils; import org.apache.http.HttpResponse; import org.apache.http.HttpStatus; @@ -168,11 +169,10 @@ public void getAssertions(final ZipOutputStream zos, final BigDecimal riskLimit, // Iterate through all IRV Contests, sending a request to the raire-service for each one's assertions and // collating the responses. final List IRVContestResults = AbstractAllIrvEndpoint.getIRVContestResults(); - final List correctWinnersIRVContestResults = IRVContestResults.stream().map(AbstractAllIrvEndpoint::updateIRVContestWinner).toList(); - for (final ContestResult cr : correctWinnersIRVContestResults) { + for (final ContestResult cr : IRVContestResults) { - // Find the winner (there should only be one), candidates and contest name. - final String winner = cr.getWinners().stream().findAny().orElse(UNKNOWN_WINNER); + // Find the winner, candidates and contest name. + final String winner = GenerateAssertionsSummaryQueries.matchingWinner(cr.getContestName()); final List candidates = cr.getContests().stream().findAny().orElseThrow().choices().stream() .map(Choice::name).toList(); From 805c96bc9652641f7fb66458ce3e4713ee458675 Mon Sep 17 00:00:00 2001 From: vteague Date: Sun, 14 Jul 2024 17:15:07 +1000 Subject: [PATCH 04/21] Edited ReportRows::getResultsReport to include the right data for IRV. --- .../endpoint/AbstractAllIrvEndpoint.java | 30 ------------ .../freeandfair/corla/report/ReportRows.java | 47 ++++++++++++------- 2 files changed, 31 insertions(+), 46 deletions(-) diff --git a/server/eclipse-project/src/main/java/au/org/democracydevelopers/corla/endpoint/AbstractAllIrvEndpoint.java b/server/eclipse-project/src/main/java/au/org/democracydevelopers/corla/endpoint/AbstractAllIrvEndpoint.java index 7a6cfce5..5fbbb21d 100644 --- a/server/eclipse-project/src/main/java/au/org/democracydevelopers/corla/endpoint/AbstractAllIrvEndpoint.java +++ b/server/eclipse-project/src/main/java/au/org/democracydevelopers/corla/endpoint/AbstractAllIrvEndpoint.java @@ -119,34 +119,4 @@ public static List getIRVContestResults() { return results; } - - /** - * Use the summaries from the GenerateAssertionsResponseSummary table to update IRV contest - * results. This should be run before anything that needs to know an IRV winner. - * It updates most of the same data as ContestCounter.CountAllContests(), but assumes that - * the contests, counties and contest name are already properly set, along with ballotCount, - * auditReason and winnersAllowed. - * Losers, vote totals and (min, max and diluted) margins remain wrong, and are never used. - * @return the IRV contest results, with winners updated from the database. - */ - public static List getAndUpdateIRVContestResults() { - - final List results = getIRVContestResults(); - - for(ContestResult cr : results) { - updateIRVContestWinner(cr); - } - - Persistence.flush(); - return results; - } - - // FIXME check for IRV, deal with absent winners (set to UNKNOWN?) - public static ContestResult updateIRVContestWinner(ContestResult cr) { - - Optional optSummary - = GenerateAssertionsSummaryQueries.matching(cr.getContestName()); - optSummary.ifPresent(generateAssertionsSummary - -> cr.setWinners(Set.of(generateAssertionsSummary.winner))); - } } diff --git a/server/eclipse-project/src/main/java/us/freeandfair/corla/report/ReportRows.java b/server/eclipse-project/src/main/java/us/freeandfair/corla/report/ReportRows.java index f05cda9a..7ccba69f 100644 --- a/server/eclipse-project/src/main/java/us/freeandfair/corla/report/ReportRows.java +++ b/server/eclipse-project/src/main/java/us/freeandfair/corla/report/ReportRows.java @@ -13,6 +13,8 @@ import java.math.BigDecimal; +import au.org.democracydevelopers.corla.model.IRVComparisonAudit; +import au.org.democracydevelopers.corla.query.GenerateAssertionsSummaryQueries; import org.apache.commons.lang3.ArrayUtils; import java.time.Instant; @@ -357,6 +359,9 @@ public static BigDecimal percentage(final BigDecimal num) { /** * for each contest(per row), show all the variables that are interesting or * needed to perform the risk limit calculation + * This checks whether the contest is IRV and makes two modifications: + * 1. it takes the winner from the GenerateAssertionsSummary table, rather than the ComparisonAudit, + * 2. it omits the candidate tallies (for winner and runner-up), which are not meaningful for IRV. **/ public static List> genSumResultsReport() { final List> rows = new ArrayList(); @@ -371,10 +376,17 @@ public static List> genSumResultsReport() { row.put("Contest", ca.contestResult().getContestName()); row.put("targeted", yesNo(ca.isTargeted())); - if (ca.contestResult().getWinners() == null || ca.contestResult().getWinners().isEmpty()) { - LOGGER.info("no winner!!! " + ca); + if(ca instanceof IRVComparisonAudit) { + // If IRV, get the winner's name from the GenerateAssertionsSummary. + row.put("Winner", GenerateAssertionsSummaryQueries.matchingWinner(ca.getContestName())); + } else { + // Must be a plurality audit. ContestResult.winner is correct. + if (ca.contestResult().getWinners() == null || ca.contestResult().getWinners().isEmpty()) { + LOGGER.info("no winner!!! " + ca); + } + row.put("Winner", toString(ca.contestResult().getWinners().iterator().next())); } - row.put("Winner", toString(ca.contestResult().getWinners().iterator().next())); + // All this data makes sense for both IRV and plurality. row.put("Risk Limit met?", yesNo(riskLimitMet(ca.getRiskLimit(), riskMsmnt))); row.put("Risk measurement %", sigFig(percentage(riskMsmnt), 1).toString()); row.put("Audit Risk Limit %", sigFig(percentage(ca.getRiskLimit()),1).toString()); @@ -390,19 +402,22 @@ public static List> genSumResultsReport() { row.put("ballot count", toString(ca.contestResult().getBallotCount())); row.put("min margin", toString(ca.contestResult().getMinMargin())); - final List> rankedTotals = - ContestCounter.rankTotals(ca.contestResult().getVoteTotals()); - - try { - row.put("votes for winner", toString(rankedTotals.get(0).getValue())); - } catch (IndexOutOfBoundsException e) { - row.put("votes for winner", ""); - } - - try { - row.put("votes for runner up", toString(rankedTotals.get(1).getValue())); - } catch (IndexOutOfBoundsException e) { - row.put("votes for runner up", ""); + // These totals make sense only for plurality. + if(! (ca instanceof IRVComparisonAudit)) { + final List> rankedTotals = + ContestCounter.rankTotals(ca.contestResult().getVoteTotals()); + + try { + row.put("votes for winner", toString(rankedTotals.get(0).getValue())); + } catch (IndexOutOfBoundsException e) { + row.put("votes for winner", ""); + } + + try { + row.put("votes for runner up", toString(rankedTotals.get(1).getValue())); + } catch (IndexOutOfBoundsException e) { + row.put("votes for runner up", ""); + } } row.put("total votes", toString(ca.contestResult().totalVotes())); From 06cc257d0bcad73921fbef572cedb65ad43dcbaa Mon Sep 17 00:00:00 2001 From: vteague Date: Sun, 14 Jul 2024 17:45:21 +1000 Subject: [PATCH 05/21] Set up GetAssertionsTest for proper database retrieval. --- .../corla/endpoint/GetAssertionsTests.java | 18 +++++++++++++++++- .../src/test/resources/SQL/corla.sql | 14 ++++++++++++++ 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/server/eclipse-project/src/test/java/au/org/democracydevelopers/corla/endpoint/GetAssertionsTests.java b/server/eclipse-project/src/test/java/au/org/democracydevelopers/corla/endpoint/GetAssertionsTests.java index dbc0ba96..4aab8a81 100644 --- a/server/eclipse-project/src/test/java/au/org/democracydevelopers/corla/endpoint/GetAssertionsTests.java +++ b/server/eclipse-project/src/test/java/au/org/democracydevelopers/corla/endpoint/GetAssertionsTests.java @@ -21,6 +21,7 @@ package au.org.democracydevelopers.corla.endpoint; +import au.org.democracydevelopers.corla.util.TestClassWithDatabase; import au.org.democracydevelopers.corla.util.testUtils; import org.apache.http.HttpStatus; import org.apache.log4j.LogManager; @@ -28,6 +29,7 @@ import org.mockito.MockedStatic; import org.mockito.Mockito; import org.mockito.MockitoAnnotations; +import org.testcontainers.containers.PostgreSQLContainer; import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeClass; import org.testng.annotations.DataProvider; @@ -44,6 +46,7 @@ import java.util.zip.ZipInputStream; import com.github.tomakehurst.wiremock.WireMockServer; +import us.freeandfair.corla.persistence.Persistence; import static au.org.democracydevelopers.corla.util.testUtils.*; import static com.github.tomakehurst.wiremock.client.WireMock.*; @@ -61,10 +64,15 @@ * - Testing that the service throws appropriate exceptions if the raire service connection isn't set up properly. * See ... */ -public class GetAssertionsTests { +public class GetAssertionsTests extends TestClassWithDatabase { private static final Logger LOGGER = LogManager.getLogger(GetAssertionsTests.class); + /** + * Container for the mock-up database. + */ + private final static PostgreSQLContainer postgres = createTestContainer(); + /** * Endpoint for getting assertions. */ @@ -92,6 +100,14 @@ public class GetAssertionsTests { */ static String baseUrl; + /** + * Database init. + */ + @BeforeClass + public static void beforeAll() { + postgres.start(); + Persistence.setProperties(createHibernateProperties(postgres)); + } /** * Initialise mocked objects prior to the first test. */ diff --git a/server/eclipse-project/src/test/resources/SQL/corla.sql b/server/eclipse-project/src/test/resources/SQL/corla.sql index 3a9c80a9..f1f1e0ed 100644 --- a/server/eclipse-project/src/test/resources/SQL/corla.sql +++ b/server/eclipse-project/src/test/resources/SQL/corla.sql @@ -465,6 +465,20 @@ create table dos_dashboard alter table dos_dashboard owner to corlaadmin; +create table generate_assertions_summary +( + id bigserial + primary key, + contest_name varchar(255) not null + constraint uk_g5q4xm0ga61nbiccn44irhivx + unique, + error varchar(255) not null, + message varchar(255) not null, + version bigint not null, + warning varchar(255) not null, + winner varchar(255) not null +); + create table contest_to_audit ( dashboard_id bigint not null From 024254c6c062a5b5138bb686ac04796f5b6ea607 Mon Sep 17 00:00:00 2001 From: vteague Date: Sun, 14 Jul 2024 17:57:10 +1000 Subject: [PATCH 06/21] Deleted unused database setup scripts. --- .../src/test/resources/SQL/corlaInit.sql | 1928 ----------------- .../src/test/resources/SQL/corlaInitEmpty.sql | 647 ------ 2 files changed, 2575 deletions(-) delete mode 100644 server/eclipse-project/src/test/resources/SQL/corlaInit.sql delete mode 100644 server/eclipse-project/src/test/resources/SQL/corlaInitEmpty.sql diff --git a/server/eclipse-project/src/test/resources/SQL/corlaInit.sql b/server/eclipse-project/src/test/resources/SQL/corlaInit.sql deleted file mode 100644 index 050b5941..00000000 --- a/server/eclipse-project/src/test/resources/SQL/corlaInit.sql +++ /dev/null @@ -1,1928 +0,0 @@ --- --- PostgreSQL database dump --- - --- Dumped from database version 14.12 (Ubuntu 14.12-0ubuntu0.22.04.1) --- Dumped by pg_dump version 14.12 (Ubuntu 14.12-0ubuntu0.22.04.1) - -SET statement_timeout = 0; -SET lock_timeout = 0; -SET idle_in_transaction_session_timeout = 0; -SET client_encoding = 'UTF8'; -SET standard_conforming_strings = on; -SELECT pg_catalog.set_config('search_path', '', false); -SET check_function_bodies = false; -SET xmloption = content; -SET client_min_messages = warning; -SET row_security = off; - --- --- Name: public; Type: SCHEMA; Schema: -; Owner: postgres --- - --- CREATE SCHEMA public; - - --- ALTER SCHEMA public OWNER TO postgres; - --- --- Name: SCHEMA public; Type: COMMENT; Schema: -; Owner: postgres --- - -COMMENT ON SCHEMA public IS 'standard public schema'; - - -SET default_tablespace = ''; - -SET default_table_access_method = heap; - --- --- Name: administrator; Type: TABLE; Schema: public; Owner: corlaadmin --- - -CREATE TABLE public.administrator ( - id bigint NOT NULL, - full_name character varying(255) NOT NULL, - last_login_time timestamp without time zone, - last_logout_time timestamp without time zone, - type character varying(255) NOT NULL, - username character varying(255) NOT NULL, - version bigint, - county_id bigint -); - - -ALTER TABLE public.administrator OWNER TO corlaadmin; - --- --- Name: asm_state; Type: TABLE; Schema: public; Owner: corlaadmin --- - -CREATE TABLE public.asm_state ( - id bigint NOT NULL, - asm_class character varying(255) NOT NULL, - asm_identity character varying(255), - state_class character varying(255), - state_value character varying(255), - version bigint -); - - -ALTER TABLE public.asm_state OWNER TO corlaadmin; - --- --- Name: assertion_seq; Type: SEQUENCE; Schema: public; Owner: corlaadmin --- - -CREATE SEQUENCE public.assertion_seq - START WITH 1 - INCREMENT BY 50 - NO MINVALUE - NO MAXVALUE - CACHE 1; - - -ALTER TABLE public.assertion_seq OWNER TO corlaadmin; - --- --- Name: audit_board; Type: TABLE; Schema: public; Owner: corlaadmin --- - -CREATE TABLE public.audit_board ( - dashboard_id bigint NOT NULL, - members text, - sign_in_time timestamp without time zone NOT NULL, - sign_out_time timestamp without time zone, - index integer NOT NULL -); - - -ALTER TABLE public.audit_board OWNER TO corlaadmin; - --- --- Name: audit_intermediate_report; Type: TABLE; Schema: public; Owner: corlaadmin --- - -CREATE TABLE public.audit_intermediate_report ( - dashboard_id bigint NOT NULL, - report character varying(255), - "timestamp" timestamp without time zone, - index integer NOT NULL -); - - -ALTER TABLE public.audit_intermediate_report OWNER TO corlaadmin; - --- --- Name: audit_investigation_report; Type: TABLE; Schema: public; Owner: corlaadmin --- - -CREATE TABLE public.audit_investigation_report ( - dashboard_id bigint NOT NULL, - name character varying(255), - report character varying(255), - "timestamp" timestamp without time zone, - index integer NOT NULL -); - - -ALTER TABLE public.audit_investigation_report OWNER TO corlaadmin; - --- --- Name: ballot_manifest_info; Type: TABLE; Schema: public; Owner: corlaadmin --- - -CREATE TABLE public.ballot_manifest_info ( - id bigint NOT NULL, - batch_id character varying(255) NOT NULL, - batch_size integer NOT NULL, - county_id bigint NOT NULL, - scanner_id integer NOT NULL, - sequence_end bigint NOT NULL, - sequence_start bigint NOT NULL, - storage_location character varying(255) NOT NULL, - version bigint, - ultimate_sequence_end bigint, - ultimate_sequence_start bigint, - uri character varying(255) -); - - -ALTER TABLE public.ballot_manifest_info OWNER TO corlaadmin; - --- --- Name: cast_vote_record; Type: TABLE; Schema: public; Owner: corlaadmin --- - -CREATE TABLE public.cast_vote_record ( - id bigint NOT NULL, - audit_board_index integer, - comment character varying(255), - cvr_id bigint, - ballot_type character varying(255) NOT NULL, - batch_id character varying(255) NOT NULL, - county_id bigint NOT NULL, - cvr_number integer NOT NULL, - imprinted_id character varying(255) NOT NULL, - record_id integer NOT NULL, - record_type character varying(255) NOT NULL, - scanner_id integer NOT NULL, - sequence_number integer, - "timestamp" timestamp without time zone, - version bigint, - rand integer, - revision bigint, - round_number integer, - uri character varying(255) -); - - -ALTER TABLE public.cast_vote_record OWNER TO corlaadmin; - --- --- Name: comparison_audit; Type: TABLE; Schema: public; Owner: corlaadmin --- - -CREATE TABLE public.comparison_audit ( - id bigint NOT NULL, - contest_cvr_ids text, - diluted_margin numeric(10,8) NOT NULL, - audit_reason character varying(255) NOT NULL, - audit_status character varying(255) NOT NULL, - audited_sample_count integer NOT NULL, - disagreement_count integer NOT NULL, - estimated_recalculate_needed boolean NOT NULL, - estimated_samples_to_audit integer NOT NULL, - gamma numeric(10,8) NOT NULL, - one_vote_over_count integer NOT NULL, - one_vote_under_count integer NOT NULL, - optimistic_recalculate_needed boolean NOT NULL, - optimistic_samples_to_audit integer NOT NULL, - other_count integer NOT NULL, - risk_limit numeric(10,8) NOT NULL, - two_vote_over_count integer NOT NULL, - two_vote_under_count integer NOT NULL, - version bigint, - overstatements numeric(19,2), - contest_result_id bigint NOT NULL -); - - -ALTER TABLE public.comparison_audit OWNER TO corlaadmin; - --- --- Name: contest; Type: TABLE; Schema: public; Owner: corlaadmin --- - -CREATE TABLE public.contest ( - id bigint NOT NULL, - description character varying(255) NOT NULL, - name character varying(255) NOT NULL, - sequence_number integer NOT NULL, - version bigint, - votes_allowed integer NOT NULL, - winners_allowed integer NOT NULL, - county_id bigint NOT NULL -); - - -ALTER TABLE public.contest OWNER TO corlaadmin; - --- --- Name: contest_choice; Type: TABLE; Schema: public; Owner: corlaadmin --- - -CREATE TABLE public.contest_choice ( - contest_id bigint NOT NULL, - description character varying(255), - fictitious boolean NOT NULL, - name character varying(255), - qualified_write_in boolean NOT NULL, - index integer NOT NULL -); - - -ALTER TABLE public.contest_choice OWNER TO corlaadmin; - --- --- Name: contest_comparison_audit_disagreement; Type: TABLE; Schema: public; Owner: corlaadmin --- - -CREATE TABLE public.contest_comparison_audit_disagreement ( - contest_comparison_audit_id bigint NOT NULL, - cvr_audit_info_id bigint NOT NULL -); - - -ALTER TABLE public.contest_comparison_audit_disagreement OWNER TO corlaadmin; - --- --- Name: contest_comparison_audit_discrepancy; Type: TABLE; Schema: public; Owner: corlaadmin --- - -CREATE TABLE public.contest_comparison_audit_discrepancy ( - contest_comparison_audit_id bigint NOT NULL, - discrepancy integer, - cvr_audit_info_id bigint NOT NULL -); - - -ALTER TABLE public.contest_comparison_audit_discrepancy OWNER TO corlaadmin; - --- --- Name: contest_result; Type: TABLE; Schema: public; Owner: corlaadmin --- - -CREATE TABLE public.contest_result ( - id bigint NOT NULL, - audit_reason integer, - ballot_count bigint, - contest_name character varying(255) NOT NULL, - diluted_margin numeric(19,2), - losers text, - max_margin integer, - min_margin integer, - version bigint, - winners text, - winners_allowed integer -); - - -ALTER TABLE public.contest_result OWNER TO corlaadmin; - --- --- Name: contest_to_audit; Type: TABLE; Schema: public; Owner: corlaadmin --- - -CREATE TABLE public.contest_to_audit ( - dashboard_id bigint NOT NULL, - audit character varying(255), - contest_id bigint NOT NULL, - reason character varying(255) -); - - -ALTER TABLE public.contest_to_audit OWNER TO corlaadmin; - --- --- Name: contest_vote_total; Type: TABLE; Schema: public; Owner: corlaadmin --- - -CREATE TABLE public.contest_vote_total ( - result_id bigint NOT NULL, - vote_total integer, - choice character varying(255) NOT NULL -); - - -ALTER TABLE public.contest_vote_total OWNER TO corlaadmin; - --- --- Name: contests_to_contest_results; Type: TABLE; Schema: public; Owner: corlaadmin --- - -CREATE TABLE public.contests_to_contest_results ( - contest_result_id bigint NOT NULL, - contest_id bigint NOT NULL -); - - -ALTER TABLE public.contests_to_contest_results OWNER TO corlaadmin; - --- --- Name: counties_to_contest_results; Type: TABLE; Schema: public; Owner: corlaadmin --- - -CREATE TABLE public.counties_to_contest_results ( - contest_result_id bigint NOT NULL, - county_id bigint NOT NULL -); - - -ALTER TABLE public.counties_to_contest_results OWNER TO corlaadmin; - --- --- Name: county; Type: TABLE; Schema: public; Owner: corlaadmin --- - -CREATE TABLE public.county ( - id bigint NOT NULL, - name character varying(255) NOT NULL, - version bigint -); - - -ALTER TABLE public.county OWNER TO corlaadmin; - --- --- Name: county_contest_comparison_audit; Type: TABLE; Schema: public; Owner: corlaadmin --- - -CREATE TABLE public.county_contest_comparison_audit ( - id bigint NOT NULL, - diluted_margin numeric(10,8) NOT NULL, - audit_reason character varying(255) NOT NULL, - audit_status character varying(255) NOT NULL, - audited_sample_count integer NOT NULL, - disagreement_count integer NOT NULL, - estimated_recalculate_needed boolean NOT NULL, - estimated_samples_to_audit integer NOT NULL, - gamma numeric(10,8) NOT NULL, - one_vote_over_count integer NOT NULL, - one_vote_under_count integer NOT NULL, - optimistic_recalculate_needed boolean NOT NULL, - optimistic_samples_to_audit integer NOT NULL, - other_count integer NOT NULL, - risk_limit numeric(10,8) NOT NULL, - two_vote_over_count integer NOT NULL, - two_vote_under_count integer NOT NULL, - version bigint, - contest_id bigint NOT NULL, - contest_result_id bigint NOT NULL, - dashboard_id bigint NOT NULL -); - - -ALTER TABLE public.county_contest_comparison_audit OWNER TO corlaadmin; - --- --- Name: county_contest_comparison_audit_disagreement; Type: TABLE; Schema: public; Owner: corlaadmin --- - -CREATE TABLE public.county_contest_comparison_audit_disagreement ( - county_contest_comparison_audit_id bigint NOT NULL, - cvr_audit_info_id bigint NOT NULL -); - - -ALTER TABLE public.county_contest_comparison_audit_disagreement OWNER TO corlaadmin; - --- --- Name: county_contest_comparison_audit_discrepancy; Type: TABLE; Schema: public; Owner: corlaadmin --- - -CREATE TABLE public.county_contest_comparison_audit_discrepancy ( - county_contest_comparison_audit_id bigint NOT NULL, - discrepancy integer, - cvr_audit_info_id bigint NOT NULL -); - - -ALTER TABLE public.county_contest_comparison_audit_discrepancy OWNER TO corlaadmin; - --- --- Name: county_contest_result; Type: TABLE; Schema: public; Owner: corlaadmin --- - -CREATE TABLE public.county_contest_result ( - id bigint NOT NULL, - contest_ballot_count integer, - county_ballot_count integer, - losers text, - max_margin integer, - min_margin integer, - version bigint, - winners text, - winners_allowed integer NOT NULL, - contest_id bigint NOT NULL, - county_id bigint NOT NULL -); - - -ALTER TABLE public.county_contest_result OWNER TO corlaadmin; - --- --- Name: county_contest_vote_total; Type: TABLE; Schema: public; Owner: corlaadmin --- - -CREATE TABLE public.county_contest_vote_total ( - result_id bigint NOT NULL, - vote_total integer, - choice character varying(255) NOT NULL -); - - -ALTER TABLE public.county_contest_vote_total OWNER TO corlaadmin; - --- --- Name: county_dashboard; Type: TABLE; Schema: public; Owner: corlaadmin --- - -CREATE TABLE public.county_dashboard ( - id bigint NOT NULL, - audit_board_count integer, - driving_contests text, - audit_timestamp timestamp without time zone, - audited_prefix_length integer, - audited_sample_count integer, - ballots_audited integer NOT NULL, - ballots_in_manifest integer NOT NULL, - current_round_index integer, - cvr_import_error_message character varying(255), - cvr_import_state character varying(255), - cvr_import_timestamp timestamp without time zone, - cvrs_imported integer NOT NULL, - disagreements text NOT NULL, - discrepancies text NOT NULL, - version bigint, - county_id bigint NOT NULL, - cvr_file_id bigint, - manifest_file_id bigint -); - - -ALTER TABLE public.county_dashboard OWNER TO corlaadmin; - --- --- Name: county_dashboard_to_comparison_audit; Type: TABLE; Schema: public; Owner: corlaadmin --- - -CREATE TABLE public.county_dashboard_to_comparison_audit ( - dashboard_id bigint NOT NULL, - comparison_audit_id bigint NOT NULL -); - - -ALTER TABLE public.county_dashboard_to_comparison_audit OWNER TO corlaadmin; - --- --- Name: cvr_audit_info; Type: TABLE; Schema: public; Owner: corlaadmin --- - -CREATE TABLE public.cvr_audit_info ( - id bigint NOT NULL, - count_by_contest text, - multiplicity_by_contest text, - disagreement text NOT NULL, - discrepancy text NOT NULL, - version bigint, - acvr_id bigint, - cvr_id bigint NOT NULL -); - - -ALTER TABLE public.cvr_audit_info OWNER TO corlaadmin; - --- --- Name: cvr_contest_info; Type: TABLE; Schema: public; Owner: corlaadmin --- - -CREATE TABLE public.cvr_contest_info ( - cvr_id bigint NOT NULL, - county_id bigint, - choices character varying(1024), - comment character varying(255), - consensus character varying(255), - contest_id bigint NOT NULL, - index integer NOT NULL -); - - -ALTER TABLE public.cvr_contest_info OWNER TO corlaadmin; - --- --- Name: dos_dashboard; Type: TABLE; Schema: public; Owner: corlaadmin --- - -CREATE TABLE public.dos_dashboard ( - id bigint NOT NULL, - canonical_choices text, - canonical_contests text, - election_date timestamp without time zone, - election_type character varying(255), - public_meeting_date timestamp without time zone, - risk_limit numeric(10,8), - seed character varying(255), - version bigint -); - - -ALTER TABLE public.dos_dashboard OWNER TO corlaadmin; - --- --- Name: hibernate_sequence; Type: SEQUENCE; Schema: public; Owner: corlaadmin --- - -CREATE SEQUENCE public.hibernate_sequence - START WITH 1 - INCREMENT BY 1 - NO MINVALUE - NO MAXVALUE - CACHE 1; - - -ALTER TABLE public.hibernate_sequence OWNER TO corlaadmin; - --- --- Name: log; Type: TABLE; Schema: public; Owner: corlaadmin --- - -CREATE TABLE public.log ( - id bigint NOT NULL, - authentication_data character varying(255), - client_host character varying(255), - hash character varying(255) NOT NULL, - information character varying(255) NOT NULL, - result_code integer, - "timestamp" timestamp without time zone NOT NULL, - version bigint, - previous_entry bigint -); - - -ALTER TABLE public.log OWNER TO corlaadmin; - --- --- Name: round; Type: TABLE; Schema: public; Owner: corlaadmin --- - -CREATE TABLE public.round ( - dashboard_id bigint NOT NULL, - ballot_sequence_assignment text NOT NULL, - actual_audited_prefix_length integer, - actual_count integer NOT NULL, - audit_subsequence text NOT NULL, - ballot_sequence text NOT NULL, - disagreements text NOT NULL, - discrepancies text NOT NULL, - end_time timestamp without time zone, - expected_audited_prefix_length integer NOT NULL, - expected_count integer NOT NULL, - number integer NOT NULL, - previous_ballots_audited integer NOT NULL, - signatories text, - start_audited_prefix_length integer NOT NULL, - start_time timestamp without time zone NOT NULL, - index integer NOT NULL -); - - -ALTER TABLE public.round OWNER TO corlaadmin; - --- --- Name: tribute; Type: TABLE; Schema: public; Owner: corlaadmin --- - -CREATE TABLE public.tribute ( - id bigint NOT NULL, - ballot_position integer, - batch_id character varying(255), - contest_name character varying(255), - county_id bigint, - rand integer, - rand_sequence_position integer, - scanner_id integer, - uri character varying(255), - version bigint -); - - -ALTER TABLE public.tribute OWNER TO corlaadmin; - --- --- Name: uploaded_file; Type: TABLE; Schema: public; Owner: corlaadmin --- - -CREATE TABLE public.uploaded_file ( - id bigint NOT NULL, - computed_hash character varying(255) NOT NULL, - approximate_record_count integer NOT NULL, - file oid NOT NULL, - filename character varying(255), - size bigint NOT NULL, - "timestamp" timestamp without time zone NOT NULL, - version bigint, - result text, - status character varying(255) NOT NULL, - submitted_hash character varying(255) NOT NULL, - county_id bigint NOT NULL -); - - -ALTER TABLE public.uploaded_file OWNER TO corlaadmin; - --- --- Data for Name: administrator; Type: TABLE DATA; Schema: public; Owner: corlaadmin --- - -INSERT INTO public.administrator (id, full_name, last_login_time, last_logout_time, type, username, version, county_id) VALUES (-1, 'State Administrator 1', NULL, NULL, 'STATE', 'stateadmin1', 0, NULL); -INSERT INTO public.administrator (id, full_name, last_login_time, last_logout_time, type, username, version, county_id) VALUES (-2, 'State Administrator 2', NULL, NULL, 'STATE', 'stateadmin2', 0, NULL); -INSERT INTO public.administrator (id, full_name, last_login_time, last_logout_time, type, username, version, county_id) VALUES (-3, 'State Administrator 3', NULL, NULL, 'STATE', 'stateadmin3', 0, NULL); -INSERT INTO public.administrator (id, full_name, last_login_time, last_logout_time, type, username, version, county_id) VALUES (-4, 'State Administrator 4', NULL, NULL, 'STATE', 'stateadmin4', 0, NULL); -INSERT INTO public.administrator (id, full_name, last_login_time, last_logout_time, type, username, version, county_id) VALUES (-5, 'State Administrator 5', NULL, NULL, 'STATE', 'stateadmin5', 0, NULL); -INSERT INTO public.administrator (id, full_name, last_login_time, last_logout_time, type, username, version, county_id) VALUES (-6, 'State Administrator 6', NULL, NULL, 'STATE', 'stateadmin6', 0, NULL); -INSERT INTO public.administrator (id, full_name, last_login_time, last_logout_time, type, username, version, county_id) VALUES (-7, 'State Administrator 7', NULL, NULL, 'STATE', 'stateadmin7', 0, NULL); -INSERT INTO public.administrator (id, full_name, last_login_time, last_logout_time, type, username, version, county_id) VALUES (-8, 'State Administrator 8', NULL, NULL, 'STATE', 'stateadmin8', 0, NULL); -INSERT INTO public.administrator (id, full_name, last_login_time, last_logout_time, type, username, version, county_id) VALUES (-101, 'County Administrator 1', NULL, NULL, 'COUNTY', 'countyadmin1', 0, 1); -INSERT INTO public.administrator (id, full_name, last_login_time, last_logout_time, type, username, version, county_id) VALUES (-102, 'County Administrator 2', NULL, NULL, 'COUNTY', 'countyadmin2', 0, 2); -INSERT INTO public.administrator (id, full_name, last_login_time, last_logout_time, type, username, version, county_id) VALUES (-103, 'County Administrator 3', NULL, NULL, 'COUNTY', 'countyadmin3', 0, 3); -INSERT INTO public.administrator (id, full_name, last_login_time, last_logout_time, type, username, version, county_id) VALUES (-104, 'County Administrator 4', NULL, NULL, 'COUNTY', 'countyadmin4', 0, 4); -INSERT INTO public.administrator (id, full_name, last_login_time, last_logout_time, type, username, version, county_id) VALUES (-105, 'County Administrator 5', NULL, NULL, 'COUNTY', 'countyadmin5', 0, 5); -INSERT INTO public.administrator (id, full_name, last_login_time, last_logout_time, type, username, version, county_id) VALUES (-106, 'County Administrator 6', NULL, NULL, 'COUNTY', 'countyadmin6', 0, 6); -INSERT INTO public.administrator (id, full_name, last_login_time, last_logout_time, type, username, version, county_id) VALUES (-107, 'County Administrator 7', NULL, NULL, 'COUNTY', 'countyadmin7', 0, 7); -INSERT INTO public.administrator (id, full_name, last_login_time, last_logout_time, type, username, version, county_id) VALUES (-108, 'County Administrator 8', NULL, NULL, 'COUNTY', 'countyadmin8', 0, 8); -INSERT INTO public.administrator (id, full_name, last_login_time, last_logout_time, type, username, version, county_id) VALUES (-109, 'County Administrator 9', NULL, NULL, 'COUNTY', 'countyadmin9', 0, 9); -INSERT INTO public.administrator (id, full_name, last_login_time, last_logout_time, type, username, version, county_id) VALUES (-110, 'County Administrator 10', NULL, NULL, 'COUNTY', 'countyadmin10', 0, 10); -INSERT INTO public.administrator (id, full_name, last_login_time, last_logout_time, type, username, version, county_id) VALUES (-111, 'County Administrator 11', NULL, NULL, 'COUNTY', 'countyadmin11', 0, 11); -INSERT INTO public.administrator (id, full_name, last_login_time, last_logout_time, type, username, version, county_id) VALUES (-112, 'County Administrator 12', NULL, NULL, 'COUNTY', 'countyadmin12', 0, 12); -INSERT INTO public.administrator (id, full_name, last_login_time, last_logout_time, type, username, version, county_id) VALUES (-113, 'County Administrator 13', NULL, NULL, 'COUNTY', 'countyadmin13', 0, 13); -INSERT INTO public.administrator (id, full_name, last_login_time, last_logout_time, type, username, version, county_id) VALUES (-114, 'County Administrator 14', NULL, NULL, 'COUNTY', 'countyadmin14', 0, 14); -INSERT INTO public.administrator (id, full_name, last_login_time, last_logout_time, type, username, version, county_id) VALUES (-115, 'County Administrator 15', NULL, NULL, 'COUNTY', 'countyadmin15', 0, 15); -INSERT INTO public.administrator (id, full_name, last_login_time, last_logout_time, type, username, version, county_id) VALUES (-116, 'County Administrator 16', NULL, NULL, 'COUNTY', 'countyadmin16', 0, 16); -INSERT INTO public.administrator (id, full_name, last_login_time, last_logout_time, type, username, version, county_id) VALUES (-117, 'County Administrator 17', NULL, NULL, 'COUNTY', 'countyadmin17', 0, 17); -INSERT INTO public.administrator (id, full_name, last_login_time, last_logout_time, type, username, version, county_id) VALUES (-118, 'County Administrator 18', NULL, NULL, 'COUNTY', 'countyadmin18', 0, 18); -INSERT INTO public.administrator (id, full_name, last_login_time, last_logout_time, type, username, version, county_id) VALUES (-119, 'County Administrator 19', NULL, NULL, 'COUNTY', 'countyadmin19', 0, 19); -INSERT INTO public.administrator (id, full_name, last_login_time, last_logout_time, type, username, version, county_id) VALUES (-120, 'County Administrator 20', NULL, NULL, 'COUNTY', 'countyadmin20', 0, 20); -INSERT INTO public.administrator (id, full_name, last_login_time, last_logout_time, type, username, version, county_id) VALUES (-121, 'County Administrator 21', NULL, NULL, 'COUNTY', 'countyadmin21', 0, 21); -INSERT INTO public.administrator (id, full_name, last_login_time, last_logout_time, type, username, version, county_id) VALUES (-122, 'County Administrator 22', NULL, NULL, 'COUNTY', 'countyadmin22', 0, 22); -INSERT INTO public.administrator (id, full_name, last_login_time, last_logout_time, type, username, version, county_id) VALUES (-123, 'County Administrator 23', NULL, NULL, 'COUNTY', 'countyadmin23', 0, 23); -INSERT INTO public.administrator (id, full_name, last_login_time, last_logout_time, type, username, version, county_id) VALUES (-124, 'County Administrator 24', NULL, NULL, 'COUNTY', 'countyadmin24', 0, 24); -INSERT INTO public.administrator (id, full_name, last_login_time, last_logout_time, type, username, version, county_id) VALUES (-125, 'County Administrator 25', NULL, NULL, 'COUNTY', 'countyadmin25', 0, 25); -INSERT INTO public.administrator (id, full_name, last_login_time, last_logout_time, type, username, version, county_id) VALUES (-126, 'County Administrator 26', NULL, NULL, 'COUNTY', 'countyadmin26', 0, 26); -INSERT INTO public.administrator (id, full_name, last_login_time, last_logout_time, type, username, version, county_id) VALUES (-127, 'County Administrator 27', NULL, NULL, 'COUNTY', 'countyadmin27', 0, 27); -INSERT INTO public.administrator (id, full_name, last_login_time, last_logout_time, type, username, version, county_id) VALUES (-128, 'County Administrator 28', NULL, NULL, 'COUNTY', 'countyadmin28', 0, 28); -INSERT INTO public.administrator (id, full_name, last_login_time, last_logout_time, type, username, version, county_id) VALUES (-129, 'County Administrator 29', NULL, NULL, 'COUNTY', 'countyadmin29', 0, 29); -INSERT INTO public.administrator (id, full_name, last_login_time, last_logout_time, type, username, version, county_id) VALUES (-130, 'County Administrator 30', NULL, NULL, 'COUNTY', 'countyadmin30', 0, 30); -INSERT INTO public.administrator (id, full_name, last_login_time, last_logout_time, type, username, version, county_id) VALUES (-131, 'County Administrator 31', NULL, NULL, 'COUNTY', 'countyadmin31', 0, 31); -INSERT INTO public.administrator (id, full_name, last_login_time, last_logout_time, type, username, version, county_id) VALUES (-132, 'County Administrator 32', NULL, NULL, 'COUNTY', 'countyadmin32', 0, 32); -INSERT INTO public.administrator (id, full_name, last_login_time, last_logout_time, type, username, version, county_id) VALUES (-133, 'County Administrator 33', NULL, NULL, 'COUNTY', 'countyadmin33', 0, 33); -INSERT INTO public.administrator (id, full_name, last_login_time, last_logout_time, type, username, version, county_id) VALUES (-134, 'County Administrator 34', NULL, NULL, 'COUNTY', 'countyadmin34', 0, 34); -INSERT INTO public.administrator (id, full_name, last_login_time, last_logout_time, type, username, version, county_id) VALUES (-135, 'County Administrator 35', NULL, NULL, 'COUNTY', 'countyadmin35', 0, 35); -INSERT INTO public.administrator (id, full_name, last_login_time, last_logout_time, type, username, version, county_id) VALUES (-136, 'County Administrator 36', NULL, NULL, 'COUNTY', 'countyadmin36', 0, 36); -INSERT INTO public.administrator (id, full_name, last_login_time, last_logout_time, type, username, version, county_id) VALUES (-137, 'County Administrator 37', NULL, NULL, 'COUNTY', 'countyadmin37', 0, 37); -INSERT INTO public.administrator (id, full_name, last_login_time, last_logout_time, type, username, version, county_id) VALUES (-138, 'County Administrator 38', NULL, NULL, 'COUNTY', 'countyadmin38', 0, 38); -INSERT INTO public.administrator (id, full_name, last_login_time, last_logout_time, type, username, version, county_id) VALUES (-139, 'County Administrator 39', NULL, NULL, 'COUNTY', 'countyadmin39', 0, 39); -INSERT INTO public.administrator (id, full_name, last_login_time, last_logout_time, type, username, version, county_id) VALUES (-140, 'County Administrator 40', NULL, NULL, 'COUNTY', 'countyadmin40', 0, 40); -INSERT INTO public.administrator (id, full_name, last_login_time, last_logout_time, type, username, version, county_id) VALUES (-141, 'County Administrator 41', NULL, NULL, 'COUNTY', 'countyadmin41', 0, 41); -INSERT INTO public.administrator (id, full_name, last_login_time, last_logout_time, type, username, version, county_id) VALUES (-142, 'County Administrator 42', NULL, NULL, 'COUNTY', 'countyadmin42', 0, 42); -INSERT INTO public.administrator (id, full_name, last_login_time, last_logout_time, type, username, version, county_id) VALUES (-143, 'County Administrator 43', NULL, NULL, 'COUNTY', 'countyadmin43', 0, 43); -INSERT INTO public.administrator (id, full_name, last_login_time, last_logout_time, type, username, version, county_id) VALUES (-144, 'County Administrator 44', NULL, NULL, 'COUNTY', 'countyadmin44', 0, 44); -INSERT INTO public.administrator (id, full_name, last_login_time, last_logout_time, type, username, version, county_id) VALUES (-145, 'County Administrator 45', NULL, NULL, 'COUNTY', 'countyadmin45', 0, 45); -INSERT INTO public.administrator (id, full_name, last_login_time, last_logout_time, type, username, version, county_id) VALUES (-146, 'County Administrator 46', NULL, NULL, 'COUNTY', 'countyadmin46', 0, 46); -INSERT INTO public.administrator (id, full_name, last_login_time, last_logout_time, type, username, version, county_id) VALUES (-147, 'County Administrator 47', NULL, NULL, 'COUNTY', 'countyadmin47', 0, 47); -INSERT INTO public.administrator (id, full_name, last_login_time, last_logout_time, type, username, version, county_id) VALUES (-148, 'County Administrator 48', NULL, NULL, 'COUNTY', 'countyadmin48', 0, 48); -INSERT INTO public.administrator (id, full_name, last_login_time, last_logout_time, type, username, version, county_id) VALUES (-149, 'County Administrator 49', NULL, NULL, 'COUNTY', 'countyadmin49', 0, 49); -INSERT INTO public.administrator (id, full_name, last_login_time, last_logout_time, type, username, version, county_id) VALUES (-150, 'County Administrator 10', NULL, NULL, 'COUNTY', 'countyadmin50', 0, 50); -INSERT INTO public.administrator (id, full_name, last_login_time, last_logout_time, type, username, version, county_id) VALUES (-151, 'County Administrator 51', NULL, NULL, 'COUNTY', 'countyadmin51', 0, 51); -INSERT INTO public.administrator (id, full_name, last_login_time, last_logout_time, type, username, version, county_id) VALUES (-152, 'County Administrator 52', NULL, NULL, 'COUNTY', 'countyadmin52', 0, 52); -INSERT INTO public.administrator (id, full_name, last_login_time, last_logout_time, type, username, version, county_id) VALUES (-153, 'County Administrator 53', NULL, NULL, 'COUNTY', 'countyadmin53', 0, 53); -INSERT INTO public.administrator (id, full_name, last_login_time, last_logout_time, type, username, version, county_id) VALUES (-154, 'County Administrator 54', NULL, NULL, 'COUNTY', 'countyadmin54', 0, 54); -INSERT INTO public.administrator (id, full_name, last_login_time, last_logout_time, type, username, version, county_id) VALUES (-155, 'County Administrator 55', NULL, NULL, 'COUNTY', 'countyadmin55', 0, 55); -INSERT INTO public.administrator (id, full_name, last_login_time, last_logout_time, type, username, version, county_id) VALUES (-156, 'County Administrator 56', NULL, NULL, 'COUNTY', 'countyadmin56', 0, 56); -INSERT INTO public.administrator (id, full_name, last_login_time, last_logout_time, type, username, version, county_id) VALUES (-157, 'County Administrator 57', NULL, NULL, 'COUNTY', 'countyadmin57', 0, 57); -INSERT INTO public.administrator (id, full_name, last_login_time, last_logout_time, type, username, version, county_id) VALUES (-158, 'County Administrator 58', NULL, NULL, 'COUNTY', 'countyadmin58', 0, 58); -INSERT INTO public.administrator (id, full_name, last_login_time, last_logout_time, type, username, version, county_id) VALUES (-159, 'County Administrator 59', NULL, NULL, 'COUNTY', 'countyadmin59', 0, 59); -INSERT INTO public.administrator (id, full_name, last_login_time, last_logout_time, type, username, version, county_id) VALUES (-160, 'County Administrator 60', NULL, NULL, 'COUNTY', 'countyadmin60', 0, 60); -INSERT INTO public.administrator (id, full_name, last_login_time, last_logout_time, type, username, version, county_id) VALUES (-161, 'County Administrator 61', NULL, NULL, 'COUNTY', 'countyadmin61', 0, 61); -INSERT INTO public.administrator (id, full_name, last_login_time, last_logout_time, type, username, version, county_id) VALUES (-162, 'County Administrator 62', NULL, NULL, 'COUNTY', 'countyadmin62', 0, 62); -INSERT INTO public.administrator (id, full_name, last_login_time, last_logout_time, type, username, version, county_id) VALUES (-163, 'County Administrator 63', NULL, NULL, 'COUNTY', 'countyadmin63', 0, 63); -INSERT INTO public.administrator (id, full_name, last_login_time, last_logout_time, type, username, version, county_id) VALUES (-164, 'County Administrator 64', NULL, NULL, 'COUNTY', 'countyadmin64', 0, 64); - - --- --- Data for Name: asm_state; Type: TABLE DATA; Schema: public; Owner: corlaadmin --- - -INSERT INTO public.asm_state (id, asm_class, asm_identity, state_class, state_value, version) VALUES (44639, 'us.freeandfair.corla.asm.DoSDashboardASM', 'DoS', 'us.freeandfair.corla.asm.ASMState$DoSDashboardState', 'DOS_INITIAL_STATE', 0); -INSERT INTO public.asm_state (id, asm_class, asm_identity, state_class, state_value, version) VALUES (44640, 'us.freeandfair.corla.asm.CountyDashboardASM', '44', 'us.freeandfair.corla.asm.ASMState$CountyDashboardState', 'COUNTY_INITIAL_STATE', 0); -INSERT INTO public.asm_state (id, asm_class, asm_identity, state_class, state_value, version) VALUES (44641, 'us.freeandfair.corla.asm.AuditBoardDashboardASM', '44', 'us.freeandfair.corla.asm.ASMState$AuditBoardDashboardState', 'AUDIT_INITIAL_STATE', 0); -INSERT INTO public.asm_state (id, asm_class, asm_identity, state_class, state_value, version) VALUES (44642, 'us.freeandfair.corla.asm.CountyDashboardASM', '45', 'us.freeandfair.corla.asm.ASMState$CountyDashboardState', 'COUNTY_INITIAL_STATE', 0); -INSERT INTO public.asm_state (id, asm_class, asm_identity, state_class, state_value, version) VALUES (44643, 'us.freeandfair.corla.asm.AuditBoardDashboardASM', '45', 'us.freeandfair.corla.asm.ASMState$AuditBoardDashboardState', 'AUDIT_INITIAL_STATE', 0); -INSERT INTO public.asm_state (id, asm_class, asm_identity, state_class, state_value, version) VALUES (44644, 'us.freeandfair.corla.asm.CountyDashboardASM', '46', 'us.freeandfair.corla.asm.ASMState$CountyDashboardState', 'COUNTY_INITIAL_STATE', 0); -INSERT INTO public.asm_state (id, asm_class, asm_identity, state_class, state_value, version) VALUES (44645, 'us.freeandfair.corla.asm.AuditBoardDashboardASM', '46', 'us.freeandfair.corla.asm.ASMState$AuditBoardDashboardState', 'AUDIT_INITIAL_STATE', 0); -INSERT INTO public.asm_state (id, asm_class, asm_identity, state_class, state_value, version) VALUES (44646, 'us.freeandfair.corla.asm.CountyDashboardASM', '47', 'us.freeandfair.corla.asm.ASMState$CountyDashboardState', 'COUNTY_INITIAL_STATE', 0); -INSERT INTO public.asm_state (id, asm_class, asm_identity, state_class, state_value, version) VALUES (44647, 'us.freeandfair.corla.asm.AuditBoardDashboardASM', '47', 'us.freeandfair.corla.asm.ASMState$AuditBoardDashboardState', 'AUDIT_INITIAL_STATE', 0); -INSERT INTO public.asm_state (id, asm_class, asm_identity, state_class, state_value, version) VALUES (44648, 'us.freeandfair.corla.asm.CountyDashboardASM', '48', 'us.freeandfair.corla.asm.ASMState$CountyDashboardState', 'COUNTY_INITIAL_STATE', 0); -INSERT INTO public.asm_state (id, asm_class, asm_identity, state_class, state_value, version) VALUES (44649, 'us.freeandfair.corla.asm.AuditBoardDashboardASM', '48', 'us.freeandfair.corla.asm.ASMState$AuditBoardDashboardState', 'AUDIT_INITIAL_STATE', 0); -INSERT INTO public.asm_state (id, asm_class, asm_identity, state_class, state_value, version) VALUES (44650, 'us.freeandfair.corla.asm.CountyDashboardASM', '49', 'us.freeandfair.corla.asm.ASMState$CountyDashboardState', 'COUNTY_INITIAL_STATE', 0); -INSERT INTO public.asm_state (id, asm_class, asm_identity, state_class, state_value, version) VALUES (44651, 'us.freeandfair.corla.asm.AuditBoardDashboardASM', '49', 'us.freeandfair.corla.asm.ASMState$AuditBoardDashboardState', 'AUDIT_INITIAL_STATE', 0); -INSERT INTO public.asm_state (id, asm_class, asm_identity, state_class, state_value, version) VALUES (44652, 'us.freeandfair.corla.asm.CountyDashboardASM', '50', 'us.freeandfair.corla.asm.ASMState$CountyDashboardState', 'COUNTY_INITIAL_STATE', 0); -INSERT INTO public.asm_state (id, asm_class, asm_identity, state_class, state_value, version) VALUES (44653, 'us.freeandfair.corla.asm.AuditBoardDashboardASM', '50', 'us.freeandfair.corla.asm.ASMState$AuditBoardDashboardState', 'AUDIT_INITIAL_STATE', 0); -INSERT INTO public.asm_state (id, asm_class, asm_identity, state_class, state_value, version) VALUES (44654, 'us.freeandfair.corla.asm.CountyDashboardASM', '51', 'us.freeandfair.corla.asm.ASMState$CountyDashboardState', 'COUNTY_INITIAL_STATE', 0); -INSERT INTO public.asm_state (id, asm_class, asm_identity, state_class, state_value, version) VALUES (44655, 'us.freeandfair.corla.asm.AuditBoardDashboardASM', '51', 'us.freeandfair.corla.asm.ASMState$AuditBoardDashboardState', 'AUDIT_INITIAL_STATE', 0); -INSERT INTO public.asm_state (id, asm_class, asm_identity, state_class, state_value, version) VALUES (44656, 'us.freeandfair.corla.asm.CountyDashboardASM', '52', 'us.freeandfair.corla.asm.ASMState$CountyDashboardState', 'COUNTY_INITIAL_STATE', 0); -INSERT INTO public.asm_state (id, asm_class, asm_identity, state_class, state_value, version) VALUES (44657, 'us.freeandfair.corla.asm.AuditBoardDashboardASM', '52', 'us.freeandfair.corla.asm.ASMState$AuditBoardDashboardState', 'AUDIT_INITIAL_STATE', 0); -INSERT INTO public.asm_state (id, asm_class, asm_identity, state_class, state_value, version) VALUES (44658, 'us.freeandfair.corla.asm.CountyDashboardASM', '53', 'us.freeandfair.corla.asm.ASMState$CountyDashboardState', 'COUNTY_INITIAL_STATE', 0); -INSERT INTO public.asm_state (id, asm_class, asm_identity, state_class, state_value, version) VALUES (44659, 'us.freeandfair.corla.asm.AuditBoardDashboardASM', '53', 'us.freeandfair.corla.asm.ASMState$AuditBoardDashboardState', 'AUDIT_INITIAL_STATE', 0); -INSERT INTO public.asm_state (id, asm_class, asm_identity, state_class, state_value, version) VALUES (44660, 'us.freeandfair.corla.asm.CountyDashboardASM', '10', 'us.freeandfair.corla.asm.ASMState$CountyDashboardState', 'COUNTY_INITIAL_STATE', 0); -INSERT INTO public.asm_state (id, asm_class, asm_identity, state_class, state_value, version) VALUES (44661, 'us.freeandfair.corla.asm.AuditBoardDashboardASM', '10', 'us.freeandfair.corla.asm.ASMState$AuditBoardDashboardState', 'AUDIT_INITIAL_STATE', 0); -INSERT INTO public.asm_state (id, asm_class, asm_identity, state_class, state_value, version) VALUES (44662, 'us.freeandfair.corla.asm.CountyDashboardASM', '54', 'us.freeandfair.corla.asm.ASMState$CountyDashboardState', 'COUNTY_INITIAL_STATE', 0); -INSERT INTO public.asm_state (id, asm_class, asm_identity, state_class, state_value, version) VALUES (44663, 'us.freeandfair.corla.asm.AuditBoardDashboardASM', '54', 'us.freeandfair.corla.asm.ASMState$AuditBoardDashboardState', 'AUDIT_INITIAL_STATE', 0); -INSERT INTO public.asm_state (id, asm_class, asm_identity, state_class, state_value, version) VALUES (44664, 'us.freeandfair.corla.asm.CountyDashboardASM', '11', 'us.freeandfair.corla.asm.ASMState$CountyDashboardState', 'COUNTY_INITIAL_STATE', 0); -INSERT INTO public.asm_state (id, asm_class, asm_identity, state_class, state_value, version) VALUES (44665, 'us.freeandfair.corla.asm.AuditBoardDashboardASM', '11', 'us.freeandfair.corla.asm.ASMState$AuditBoardDashboardState', 'AUDIT_INITIAL_STATE', 0); -INSERT INTO public.asm_state (id, asm_class, asm_identity, state_class, state_value, version) VALUES (44666, 'us.freeandfair.corla.asm.CountyDashboardASM', '55', 'us.freeandfair.corla.asm.ASMState$CountyDashboardState', 'COUNTY_INITIAL_STATE', 0); -INSERT INTO public.asm_state (id, asm_class, asm_identity, state_class, state_value, version) VALUES (44667, 'us.freeandfair.corla.asm.AuditBoardDashboardASM', '55', 'us.freeandfair.corla.asm.ASMState$AuditBoardDashboardState', 'AUDIT_INITIAL_STATE', 0); -INSERT INTO public.asm_state (id, asm_class, asm_identity, state_class, state_value, version) VALUES (44668, 'us.freeandfair.corla.asm.CountyDashboardASM', '12', 'us.freeandfair.corla.asm.ASMState$CountyDashboardState', 'COUNTY_INITIAL_STATE', 0); -INSERT INTO public.asm_state (id, asm_class, asm_identity, state_class, state_value, version) VALUES (44669, 'us.freeandfair.corla.asm.AuditBoardDashboardASM', '12', 'us.freeandfair.corla.asm.ASMState$AuditBoardDashboardState', 'AUDIT_INITIAL_STATE', 0); -INSERT INTO public.asm_state (id, asm_class, asm_identity, state_class, state_value, version) VALUES (44670, 'us.freeandfair.corla.asm.CountyDashboardASM', '56', 'us.freeandfair.corla.asm.ASMState$CountyDashboardState', 'COUNTY_INITIAL_STATE', 0); -INSERT INTO public.asm_state (id, asm_class, asm_identity, state_class, state_value, version) VALUES (44671, 'us.freeandfair.corla.asm.AuditBoardDashboardASM', '56', 'us.freeandfair.corla.asm.ASMState$AuditBoardDashboardState', 'AUDIT_INITIAL_STATE', 0); -INSERT INTO public.asm_state (id, asm_class, asm_identity, state_class, state_value, version) VALUES (44672, 'us.freeandfair.corla.asm.CountyDashboardASM', '13', 'us.freeandfair.corla.asm.ASMState$CountyDashboardState', 'COUNTY_INITIAL_STATE', 0); -INSERT INTO public.asm_state (id, asm_class, asm_identity, state_class, state_value, version) VALUES (44673, 'us.freeandfair.corla.asm.AuditBoardDashboardASM', '13', 'us.freeandfair.corla.asm.ASMState$AuditBoardDashboardState', 'AUDIT_INITIAL_STATE', 0); -INSERT INTO public.asm_state (id, asm_class, asm_identity, state_class, state_value, version) VALUES (44674, 'us.freeandfair.corla.asm.CountyDashboardASM', '57', 'us.freeandfair.corla.asm.ASMState$CountyDashboardState', 'COUNTY_INITIAL_STATE', 0); -INSERT INTO public.asm_state (id, asm_class, asm_identity, state_class, state_value, version) VALUES (44675, 'us.freeandfair.corla.asm.AuditBoardDashboardASM', '57', 'us.freeandfair.corla.asm.ASMState$AuditBoardDashboardState', 'AUDIT_INITIAL_STATE', 0); -INSERT INTO public.asm_state (id, asm_class, asm_identity, state_class, state_value, version) VALUES (44676, 'us.freeandfair.corla.asm.CountyDashboardASM', '14', 'us.freeandfair.corla.asm.ASMState$CountyDashboardState', 'COUNTY_INITIAL_STATE', 0); -INSERT INTO public.asm_state (id, asm_class, asm_identity, state_class, state_value, version) VALUES (44677, 'us.freeandfair.corla.asm.AuditBoardDashboardASM', '14', 'us.freeandfair.corla.asm.ASMState$AuditBoardDashboardState', 'AUDIT_INITIAL_STATE', 0); -INSERT INTO public.asm_state (id, asm_class, asm_identity, state_class, state_value, version) VALUES (44678, 'us.freeandfair.corla.asm.CountyDashboardASM', '58', 'us.freeandfair.corla.asm.ASMState$CountyDashboardState', 'COUNTY_INITIAL_STATE', 0); -INSERT INTO public.asm_state (id, asm_class, asm_identity, state_class, state_value, version) VALUES (44679, 'us.freeandfair.corla.asm.AuditBoardDashboardASM', '58', 'us.freeandfair.corla.asm.ASMState$AuditBoardDashboardState', 'AUDIT_INITIAL_STATE', 0); -INSERT INTO public.asm_state (id, asm_class, asm_identity, state_class, state_value, version) VALUES (44680, 'us.freeandfair.corla.asm.CountyDashboardASM', '15', 'us.freeandfair.corla.asm.ASMState$CountyDashboardState', 'COUNTY_INITIAL_STATE', 0); -INSERT INTO public.asm_state (id, asm_class, asm_identity, state_class, state_value, version) VALUES (44681, 'us.freeandfair.corla.asm.AuditBoardDashboardASM', '15', 'us.freeandfair.corla.asm.ASMState$AuditBoardDashboardState', 'AUDIT_INITIAL_STATE', 0); -INSERT INTO public.asm_state (id, asm_class, asm_identity, state_class, state_value, version) VALUES (44682, 'us.freeandfair.corla.asm.CountyDashboardASM', '59', 'us.freeandfair.corla.asm.ASMState$CountyDashboardState', 'COUNTY_INITIAL_STATE', 0); -INSERT INTO public.asm_state (id, asm_class, asm_identity, state_class, state_value, version) VALUES (44683, 'us.freeandfair.corla.asm.AuditBoardDashboardASM', '59', 'us.freeandfair.corla.asm.ASMState$AuditBoardDashboardState', 'AUDIT_INITIAL_STATE', 0); -INSERT INTO public.asm_state (id, asm_class, asm_identity, state_class, state_value, version) VALUES (44684, 'us.freeandfair.corla.asm.CountyDashboardASM', '16', 'us.freeandfair.corla.asm.ASMState$CountyDashboardState', 'COUNTY_INITIAL_STATE', 0); -INSERT INTO public.asm_state (id, asm_class, asm_identity, state_class, state_value, version) VALUES (44685, 'us.freeandfair.corla.asm.AuditBoardDashboardASM', '16', 'us.freeandfair.corla.asm.ASMState$AuditBoardDashboardState', 'AUDIT_INITIAL_STATE', 0); -INSERT INTO public.asm_state (id, asm_class, asm_identity, state_class, state_value, version) VALUES (44686, 'us.freeandfair.corla.asm.CountyDashboardASM', '17', 'us.freeandfair.corla.asm.ASMState$CountyDashboardState', 'COUNTY_INITIAL_STATE', 0); -INSERT INTO public.asm_state (id, asm_class, asm_identity, state_class, state_value, version) VALUES (44687, 'us.freeandfair.corla.asm.AuditBoardDashboardASM', '17', 'us.freeandfair.corla.asm.ASMState$AuditBoardDashboardState', 'AUDIT_INITIAL_STATE', 0); -INSERT INTO public.asm_state (id, asm_class, asm_identity, state_class, state_value, version) VALUES (44688, 'us.freeandfair.corla.asm.CountyDashboardASM', '18', 'us.freeandfair.corla.asm.ASMState$CountyDashboardState', 'COUNTY_INITIAL_STATE', 0); -INSERT INTO public.asm_state (id, asm_class, asm_identity, state_class, state_value, version) VALUES (44689, 'us.freeandfair.corla.asm.AuditBoardDashboardASM', '18', 'us.freeandfair.corla.asm.ASMState$AuditBoardDashboardState', 'AUDIT_INITIAL_STATE', 0); -INSERT INTO public.asm_state (id, asm_class, asm_identity, state_class, state_value, version) VALUES (44690, 'us.freeandfair.corla.asm.CountyDashboardASM', '19', 'us.freeandfair.corla.asm.ASMState$CountyDashboardState', 'COUNTY_INITIAL_STATE', 0); -INSERT INTO public.asm_state (id, asm_class, asm_identity, state_class, state_value, version) VALUES (44691, 'us.freeandfair.corla.asm.AuditBoardDashboardASM', '19', 'us.freeandfair.corla.asm.ASMState$AuditBoardDashboardState', 'AUDIT_INITIAL_STATE', 0); -INSERT INTO public.asm_state (id, asm_class, asm_identity, state_class, state_value, version) VALUES (44692, 'us.freeandfair.corla.asm.CountyDashboardASM', '1', 'us.freeandfair.corla.asm.ASMState$CountyDashboardState', 'COUNTY_INITIAL_STATE', 0); -INSERT INTO public.asm_state (id, asm_class, asm_identity, state_class, state_value, version) VALUES (44693, 'us.freeandfair.corla.asm.AuditBoardDashboardASM', '1', 'us.freeandfair.corla.asm.ASMState$AuditBoardDashboardState', 'AUDIT_INITIAL_STATE', 0); -INSERT INTO public.asm_state (id, asm_class, asm_identity, state_class, state_value, version) VALUES (44694, 'us.freeandfair.corla.asm.CountyDashboardASM', '2', 'us.freeandfair.corla.asm.ASMState$CountyDashboardState', 'COUNTY_INITIAL_STATE', 0); -INSERT INTO public.asm_state (id, asm_class, asm_identity, state_class, state_value, version) VALUES (44695, 'us.freeandfair.corla.asm.AuditBoardDashboardASM', '2', 'us.freeandfair.corla.asm.ASMState$AuditBoardDashboardState', 'AUDIT_INITIAL_STATE', 0); -INSERT INTO public.asm_state (id, asm_class, asm_identity, state_class, state_value, version) VALUES (44696, 'us.freeandfair.corla.asm.CountyDashboardASM', '3', 'us.freeandfair.corla.asm.ASMState$CountyDashboardState', 'COUNTY_INITIAL_STATE', 0); -INSERT INTO public.asm_state (id, asm_class, asm_identity, state_class, state_value, version) VALUES (44697, 'us.freeandfair.corla.asm.AuditBoardDashboardASM', '3', 'us.freeandfair.corla.asm.ASMState$AuditBoardDashboardState', 'AUDIT_INITIAL_STATE', 0); -INSERT INTO public.asm_state (id, asm_class, asm_identity, state_class, state_value, version) VALUES (44698, 'us.freeandfair.corla.asm.CountyDashboardASM', '4', 'us.freeandfair.corla.asm.ASMState$CountyDashboardState', 'COUNTY_INITIAL_STATE', 0); -INSERT INTO public.asm_state (id, asm_class, asm_identity, state_class, state_value, version) VALUES (44699, 'us.freeandfair.corla.asm.AuditBoardDashboardASM', '4', 'us.freeandfair.corla.asm.ASMState$AuditBoardDashboardState', 'AUDIT_INITIAL_STATE', 0); -INSERT INTO public.asm_state (id, asm_class, asm_identity, state_class, state_value, version) VALUES (44700, 'us.freeandfair.corla.asm.CountyDashboardASM', '5', 'us.freeandfair.corla.asm.ASMState$CountyDashboardState', 'COUNTY_INITIAL_STATE', 0); -INSERT INTO public.asm_state (id, asm_class, asm_identity, state_class, state_value, version) VALUES (44701, 'us.freeandfair.corla.asm.AuditBoardDashboardASM', '5', 'us.freeandfair.corla.asm.ASMState$AuditBoardDashboardState', 'AUDIT_INITIAL_STATE', 0); -INSERT INTO public.asm_state (id, asm_class, asm_identity, state_class, state_value, version) VALUES (44702, 'us.freeandfair.corla.asm.CountyDashboardASM', '6', 'us.freeandfair.corla.asm.ASMState$CountyDashboardState', 'COUNTY_INITIAL_STATE', 0); -INSERT INTO public.asm_state (id, asm_class, asm_identity, state_class, state_value, version) VALUES (44703, 'us.freeandfair.corla.asm.AuditBoardDashboardASM', '6', 'us.freeandfair.corla.asm.ASMState$AuditBoardDashboardState', 'AUDIT_INITIAL_STATE', 0); -INSERT INTO public.asm_state (id, asm_class, asm_identity, state_class, state_value, version) VALUES (44704, 'us.freeandfair.corla.asm.CountyDashboardASM', '7', 'us.freeandfair.corla.asm.ASMState$CountyDashboardState', 'COUNTY_INITIAL_STATE', 0); -INSERT INTO public.asm_state (id, asm_class, asm_identity, state_class, state_value, version) VALUES (44705, 'us.freeandfair.corla.asm.AuditBoardDashboardASM', '7', 'us.freeandfair.corla.asm.ASMState$AuditBoardDashboardState', 'AUDIT_INITIAL_STATE', 0); -INSERT INTO public.asm_state (id, asm_class, asm_identity, state_class, state_value, version) VALUES (44706, 'us.freeandfair.corla.asm.CountyDashboardASM', '8', 'us.freeandfair.corla.asm.ASMState$CountyDashboardState', 'COUNTY_INITIAL_STATE', 0); -INSERT INTO public.asm_state (id, asm_class, asm_identity, state_class, state_value, version) VALUES (44707, 'us.freeandfair.corla.asm.AuditBoardDashboardASM', '8', 'us.freeandfair.corla.asm.ASMState$AuditBoardDashboardState', 'AUDIT_INITIAL_STATE', 0); -INSERT INTO public.asm_state (id, asm_class, asm_identity, state_class, state_value, version) VALUES (44708, 'us.freeandfair.corla.asm.CountyDashboardASM', '9', 'us.freeandfair.corla.asm.ASMState$CountyDashboardState', 'COUNTY_INITIAL_STATE', 0); -INSERT INTO public.asm_state (id, asm_class, asm_identity, state_class, state_value, version) VALUES (44709, 'us.freeandfair.corla.asm.AuditBoardDashboardASM', '9', 'us.freeandfair.corla.asm.ASMState$AuditBoardDashboardState', 'AUDIT_INITIAL_STATE', 0); -INSERT INTO public.asm_state (id, asm_class, asm_identity, state_class, state_value, version) VALUES (44710, 'us.freeandfair.corla.asm.CountyDashboardASM', '60', 'us.freeandfair.corla.asm.ASMState$CountyDashboardState', 'COUNTY_INITIAL_STATE', 0); -INSERT INTO public.asm_state (id, asm_class, asm_identity, state_class, state_value, version) VALUES (44711, 'us.freeandfair.corla.asm.AuditBoardDashboardASM', '60', 'us.freeandfair.corla.asm.ASMState$AuditBoardDashboardState', 'AUDIT_INITIAL_STATE', 0); -INSERT INTO public.asm_state (id, asm_class, asm_identity, state_class, state_value, version) VALUES (44712, 'us.freeandfair.corla.asm.CountyDashboardASM', '61', 'us.freeandfair.corla.asm.ASMState$CountyDashboardState', 'COUNTY_INITIAL_STATE', 0); -INSERT INTO public.asm_state (id, asm_class, asm_identity, state_class, state_value, version) VALUES (44713, 'us.freeandfair.corla.asm.AuditBoardDashboardASM', '61', 'us.freeandfair.corla.asm.ASMState$AuditBoardDashboardState', 'AUDIT_INITIAL_STATE', 0); -INSERT INTO public.asm_state (id, asm_class, asm_identity, state_class, state_value, version) VALUES (44714, 'us.freeandfair.corla.asm.CountyDashboardASM', '62', 'us.freeandfair.corla.asm.ASMState$CountyDashboardState', 'COUNTY_INITIAL_STATE', 0); -INSERT INTO public.asm_state (id, asm_class, asm_identity, state_class, state_value, version) VALUES (44715, 'us.freeandfair.corla.asm.AuditBoardDashboardASM', '62', 'us.freeandfair.corla.asm.ASMState$AuditBoardDashboardState', 'AUDIT_INITIAL_STATE', 0); -INSERT INTO public.asm_state (id, asm_class, asm_identity, state_class, state_value, version) VALUES (44716, 'us.freeandfair.corla.asm.CountyDashboardASM', '63', 'us.freeandfair.corla.asm.ASMState$CountyDashboardState', 'COUNTY_INITIAL_STATE', 0); -INSERT INTO public.asm_state (id, asm_class, asm_identity, state_class, state_value, version) VALUES (44717, 'us.freeandfair.corla.asm.AuditBoardDashboardASM', '63', 'us.freeandfair.corla.asm.ASMState$AuditBoardDashboardState', 'AUDIT_INITIAL_STATE', 0); -INSERT INTO public.asm_state (id, asm_class, asm_identity, state_class, state_value, version) VALUES (44718, 'us.freeandfair.corla.asm.CountyDashboardASM', '20', 'us.freeandfair.corla.asm.ASMState$CountyDashboardState', 'COUNTY_INITIAL_STATE', 0); -INSERT INTO public.asm_state (id, asm_class, asm_identity, state_class, state_value, version) VALUES (44719, 'us.freeandfair.corla.asm.AuditBoardDashboardASM', '20', 'us.freeandfair.corla.asm.ASMState$AuditBoardDashboardState', 'AUDIT_INITIAL_STATE', 0); -INSERT INTO public.asm_state (id, asm_class, asm_identity, state_class, state_value, version) VALUES (44720, 'us.freeandfair.corla.asm.CountyDashboardASM', '64', 'us.freeandfair.corla.asm.ASMState$CountyDashboardState', 'COUNTY_INITIAL_STATE', 0); -INSERT INTO public.asm_state (id, asm_class, asm_identity, state_class, state_value, version) VALUES (44721, 'us.freeandfair.corla.asm.AuditBoardDashboardASM', '64', 'us.freeandfair.corla.asm.ASMState$AuditBoardDashboardState', 'AUDIT_INITIAL_STATE', 0); -INSERT INTO public.asm_state (id, asm_class, asm_identity, state_class, state_value, version) VALUES (44722, 'us.freeandfair.corla.asm.CountyDashboardASM', '21', 'us.freeandfair.corla.asm.ASMState$CountyDashboardState', 'COUNTY_INITIAL_STATE', 0); -INSERT INTO public.asm_state (id, asm_class, asm_identity, state_class, state_value, version) VALUES (44723, 'us.freeandfair.corla.asm.AuditBoardDashboardASM', '21', 'us.freeandfair.corla.asm.ASMState$AuditBoardDashboardState', 'AUDIT_INITIAL_STATE', 0); -INSERT INTO public.asm_state (id, asm_class, asm_identity, state_class, state_value, version) VALUES (44724, 'us.freeandfair.corla.asm.CountyDashboardASM', '22', 'us.freeandfair.corla.asm.ASMState$CountyDashboardState', 'COUNTY_INITIAL_STATE', 0); -INSERT INTO public.asm_state (id, asm_class, asm_identity, state_class, state_value, version) VALUES (44725, 'us.freeandfair.corla.asm.AuditBoardDashboardASM', '22', 'us.freeandfair.corla.asm.ASMState$AuditBoardDashboardState', 'AUDIT_INITIAL_STATE', 0); -INSERT INTO public.asm_state (id, asm_class, asm_identity, state_class, state_value, version) VALUES (44726, 'us.freeandfair.corla.asm.CountyDashboardASM', '23', 'us.freeandfair.corla.asm.ASMState$CountyDashboardState', 'COUNTY_INITIAL_STATE', 0); -INSERT INTO public.asm_state (id, asm_class, asm_identity, state_class, state_value, version) VALUES (44727, 'us.freeandfair.corla.asm.AuditBoardDashboardASM', '23', 'us.freeandfair.corla.asm.ASMState$AuditBoardDashboardState', 'AUDIT_INITIAL_STATE', 0); -INSERT INTO public.asm_state (id, asm_class, asm_identity, state_class, state_value, version) VALUES (44728, 'us.freeandfair.corla.asm.CountyDashboardASM', '24', 'us.freeandfair.corla.asm.ASMState$CountyDashboardState', 'COUNTY_INITIAL_STATE', 0); -INSERT INTO public.asm_state (id, asm_class, asm_identity, state_class, state_value, version) VALUES (44729, 'us.freeandfair.corla.asm.AuditBoardDashboardASM', '24', 'us.freeandfair.corla.asm.ASMState$AuditBoardDashboardState', 'AUDIT_INITIAL_STATE', 0); -INSERT INTO public.asm_state (id, asm_class, asm_identity, state_class, state_value, version) VALUES (44730, 'us.freeandfair.corla.asm.CountyDashboardASM', '25', 'us.freeandfair.corla.asm.ASMState$CountyDashboardState', 'COUNTY_INITIAL_STATE', 0); -INSERT INTO public.asm_state (id, asm_class, asm_identity, state_class, state_value, version) VALUES (44731, 'us.freeandfair.corla.asm.AuditBoardDashboardASM', '25', 'us.freeandfair.corla.asm.ASMState$AuditBoardDashboardState', 'AUDIT_INITIAL_STATE', 0); -INSERT INTO public.asm_state (id, asm_class, asm_identity, state_class, state_value, version) VALUES (44732, 'us.freeandfair.corla.asm.CountyDashboardASM', '26', 'us.freeandfair.corla.asm.ASMState$CountyDashboardState', 'COUNTY_INITIAL_STATE', 0); -INSERT INTO public.asm_state (id, asm_class, asm_identity, state_class, state_value, version) VALUES (44733, 'us.freeandfair.corla.asm.AuditBoardDashboardASM', '26', 'us.freeandfair.corla.asm.ASMState$AuditBoardDashboardState', 'AUDIT_INITIAL_STATE', 0); -INSERT INTO public.asm_state (id, asm_class, asm_identity, state_class, state_value, version) VALUES (44734, 'us.freeandfair.corla.asm.CountyDashboardASM', '27', 'us.freeandfair.corla.asm.ASMState$CountyDashboardState', 'COUNTY_INITIAL_STATE', 0); -INSERT INTO public.asm_state (id, asm_class, asm_identity, state_class, state_value, version) VALUES (44735, 'us.freeandfair.corla.asm.AuditBoardDashboardASM', '27', 'us.freeandfair.corla.asm.ASMState$AuditBoardDashboardState', 'AUDIT_INITIAL_STATE', 0); -INSERT INTO public.asm_state (id, asm_class, asm_identity, state_class, state_value, version) VALUES (44736, 'us.freeandfair.corla.asm.CountyDashboardASM', '28', 'us.freeandfair.corla.asm.ASMState$CountyDashboardState', 'COUNTY_INITIAL_STATE', 0); -INSERT INTO public.asm_state (id, asm_class, asm_identity, state_class, state_value, version) VALUES (44737, 'us.freeandfair.corla.asm.AuditBoardDashboardASM', '28', 'us.freeandfair.corla.asm.ASMState$AuditBoardDashboardState', 'AUDIT_INITIAL_STATE', 0); -INSERT INTO public.asm_state (id, asm_class, asm_identity, state_class, state_value, version) VALUES (44738, 'us.freeandfair.corla.asm.CountyDashboardASM', '29', 'us.freeandfair.corla.asm.ASMState$CountyDashboardState', 'COUNTY_INITIAL_STATE', 0); -INSERT INTO public.asm_state (id, asm_class, asm_identity, state_class, state_value, version) VALUES (44739, 'us.freeandfair.corla.asm.AuditBoardDashboardASM', '29', 'us.freeandfair.corla.asm.ASMState$AuditBoardDashboardState', 'AUDIT_INITIAL_STATE', 0); -INSERT INTO public.asm_state (id, asm_class, asm_identity, state_class, state_value, version) VALUES (44740, 'us.freeandfair.corla.asm.CountyDashboardASM', '30', 'us.freeandfair.corla.asm.ASMState$CountyDashboardState', 'COUNTY_INITIAL_STATE', 0); -INSERT INTO public.asm_state (id, asm_class, asm_identity, state_class, state_value, version) VALUES (44741, 'us.freeandfair.corla.asm.AuditBoardDashboardASM', '30', 'us.freeandfair.corla.asm.ASMState$AuditBoardDashboardState', 'AUDIT_INITIAL_STATE', 0); -INSERT INTO public.asm_state (id, asm_class, asm_identity, state_class, state_value, version) VALUES (44742, 'us.freeandfair.corla.asm.CountyDashboardASM', '31', 'us.freeandfair.corla.asm.ASMState$CountyDashboardState', 'COUNTY_INITIAL_STATE', 0); -INSERT INTO public.asm_state (id, asm_class, asm_identity, state_class, state_value, version) VALUES (44743, 'us.freeandfair.corla.asm.AuditBoardDashboardASM', '31', 'us.freeandfair.corla.asm.ASMState$AuditBoardDashboardState', 'AUDIT_INITIAL_STATE', 0); -INSERT INTO public.asm_state (id, asm_class, asm_identity, state_class, state_value, version) VALUES (44744, 'us.freeandfair.corla.asm.CountyDashboardASM', '32', 'us.freeandfair.corla.asm.ASMState$CountyDashboardState', 'COUNTY_INITIAL_STATE', 0); -INSERT INTO public.asm_state (id, asm_class, asm_identity, state_class, state_value, version) VALUES (44745, 'us.freeandfair.corla.asm.AuditBoardDashboardASM', '32', 'us.freeandfair.corla.asm.ASMState$AuditBoardDashboardState', 'AUDIT_INITIAL_STATE', 0); -INSERT INTO public.asm_state (id, asm_class, asm_identity, state_class, state_value, version) VALUES (44746, 'us.freeandfair.corla.asm.CountyDashboardASM', '33', 'us.freeandfair.corla.asm.ASMState$CountyDashboardState', 'COUNTY_INITIAL_STATE', 0); -INSERT INTO public.asm_state (id, asm_class, asm_identity, state_class, state_value, version) VALUES (44747, 'us.freeandfair.corla.asm.AuditBoardDashboardASM', '33', 'us.freeandfair.corla.asm.ASMState$AuditBoardDashboardState', 'AUDIT_INITIAL_STATE', 0); -INSERT INTO public.asm_state (id, asm_class, asm_identity, state_class, state_value, version) VALUES (44748, 'us.freeandfair.corla.asm.CountyDashboardASM', '34', 'us.freeandfair.corla.asm.ASMState$CountyDashboardState', 'COUNTY_INITIAL_STATE', 0); -INSERT INTO public.asm_state (id, asm_class, asm_identity, state_class, state_value, version) VALUES (44749, 'us.freeandfair.corla.asm.AuditBoardDashboardASM', '34', 'us.freeandfair.corla.asm.ASMState$AuditBoardDashboardState', 'AUDIT_INITIAL_STATE', 0); -INSERT INTO public.asm_state (id, asm_class, asm_identity, state_class, state_value, version) VALUES (44750, 'us.freeandfair.corla.asm.CountyDashboardASM', '35', 'us.freeandfair.corla.asm.ASMState$CountyDashboardState', 'COUNTY_INITIAL_STATE', 0); -INSERT INTO public.asm_state (id, asm_class, asm_identity, state_class, state_value, version) VALUES (44751, 'us.freeandfair.corla.asm.AuditBoardDashboardASM', '35', 'us.freeandfair.corla.asm.ASMState$AuditBoardDashboardState', 'AUDIT_INITIAL_STATE', 0); -INSERT INTO public.asm_state (id, asm_class, asm_identity, state_class, state_value, version) VALUES (44752, 'us.freeandfair.corla.asm.CountyDashboardASM', '36', 'us.freeandfair.corla.asm.ASMState$CountyDashboardState', 'COUNTY_INITIAL_STATE', 0); -INSERT INTO public.asm_state (id, asm_class, asm_identity, state_class, state_value, version) VALUES (44753, 'us.freeandfair.corla.asm.AuditBoardDashboardASM', '36', 'us.freeandfair.corla.asm.ASMState$AuditBoardDashboardState', 'AUDIT_INITIAL_STATE', 0); -INSERT INTO public.asm_state (id, asm_class, asm_identity, state_class, state_value, version) VALUES (44754, 'us.freeandfair.corla.asm.CountyDashboardASM', '37', 'us.freeandfair.corla.asm.ASMState$CountyDashboardState', 'COUNTY_INITIAL_STATE', 0); -INSERT INTO public.asm_state (id, asm_class, asm_identity, state_class, state_value, version) VALUES (44755, 'us.freeandfair.corla.asm.AuditBoardDashboardASM', '37', 'us.freeandfair.corla.asm.ASMState$AuditBoardDashboardState', 'AUDIT_INITIAL_STATE', 0); -INSERT INTO public.asm_state (id, asm_class, asm_identity, state_class, state_value, version) VALUES (44756, 'us.freeandfair.corla.asm.CountyDashboardASM', '38', 'us.freeandfair.corla.asm.ASMState$CountyDashboardState', 'COUNTY_INITIAL_STATE', 0); -INSERT INTO public.asm_state (id, asm_class, asm_identity, state_class, state_value, version) VALUES (44757, 'us.freeandfair.corla.asm.AuditBoardDashboardASM', '38', 'us.freeandfair.corla.asm.ASMState$AuditBoardDashboardState', 'AUDIT_INITIAL_STATE', 0); -INSERT INTO public.asm_state (id, asm_class, asm_identity, state_class, state_value, version) VALUES (44758, 'us.freeandfair.corla.asm.CountyDashboardASM', '39', 'us.freeandfair.corla.asm.ASMState$CountyDashboardState', 'COUNTY_INITIAL_STATE', 0); -INSERT INTO public.asm_state (id, asm_class, asm_identity, state_class, state_value, version) VALUES (44759, 'us.freeandfair.corla.asm.AuditBoardDashboardASM', '39', 'us.freeandfair.corla.asm.ASMState$AuditBoardDashboardState', 'AUDIT_INITIAL_STATE', 0); -INSERT INTO public.asm_state (id, asm_class, asm_identity, state_class, state_value, version) VALUES (44760, 'us.freeandfair.corla.asm.CountyDashboardASM', '40', 'us.freeandfair.corla.asm.ASMState$CountyDashboardState', 'COUNTY_INITIAL_STATE', 0); -INSERT INTO public.asm_state (id, asm_class, asm_identity, state_class, state_value, version) VALUES (44761, 'us.freeandfair.corla.asm.AuditBoardDashboardASM', '40', 'us.freeandfair.corla.asm.ASMState$AuditBoardDashboardState', 'AUDIT_INITIAL_STATE', 0); -INSERT INTO public.asm_state (id, asm_class, asm_identity, state_class, state_value, version) VALUES (44762, 'us.freeandfair.corla.asm.CountyDashboardASM', '41', 'us.freeandfair.corla.asm.ASMState$CountyDashboardState', 'COUNTY_INITIAL_STATE', 0); -INSERT INTO public.asm_state (id, asm_class, asm_identity, state_class, state_value, version) VALUES (44763, 'us.freeandfair.corla.asm.AuditBoardDashboardASM', '41', 'us.freeandfair.corla.asm.ASMState$AuditBoardDashboardState', 'AUDIT_INITIAL_STATE', 0); -INSERT INTO public.asm_state (id, asm_class, asm_identity, state_class, state_value, version) VALUES (44764, 'us.freeandfair.corla.asm.CountyDashboardASM', '42', 'us.freeandfair.corla.asm.ASMState$CountyDashboardState', 'COUNTY_INITIAL_STATE', 0); -INSERT INTO public.asm_state (id, asm_class, asm_identity, state_class, state_value, version) VALUES (44765, 'us.freeandfair.corla.asm.AuditBoardDashboardASM', '42', 'us.freeandfair.corla.asm.ASMState$AuditBoardDashboardState', 'AUDIT_INITIAL_STATE', 0); -INSERT INTO public.asm_state (id, asm_class, asm_identity, state_class, state_value, version) VALUES (44766, 'us.freeandfair.corla.asm.CountyDashboardASM', '43', 'us.freeandfair.corla.asm.ASMState$CountyDashboardState', 'COUNTY_INITIAL_STATE', 0); -INSERT INTO public.asm_state (id, asm_class, asm_identity, state_class, state_value, version) VALUES (44767, 'us.freeandfair.corla.asm.AuditBoardDashboardASM', '43', 'us.freeandfair.corla.asm.ASMState$AuditBoardDashboardState', 'AUDIT_INITIAL_STATE', 0); - - --- --- Data for Name: audit_board; Type: TABLE DATA; Schema: public; Owner: corlaadmin --- - - - --- --- Data for Name: audit_intermediate_report; Type: TABLE DATA; Schema: public; Owner: corlaadmin --- - - - --- --- Data for Name: audit_investigation_report; Type: TABLE DATA; Schema: public; Owner: corlaadmin --- - - - --- --- Data for Name: ballot_manifest_info; Type: TABLE DATA; Schema: public; Owner: corlaadmin --- - - - --- --- Data for Name: cast_vote_record; Type: TABLE DATA; Schema: public; Owner: corlaadmin --- - - - --- --- Data for Name: comparison_audit; Type: TABLE DATA; Schema: public; Owner: corlaadmin --- - - - --- --- Data for Name: contest; Type: TABLE DATA; Schema: public; Owner: corlaadmin --- - - - --- --- Data for Name: contest_choice; Type: TABLE DATA; Schema: public; Owner: corlaadmin --- - - - --- --- Data for Name: contest_comparison_audit_disagreement; Type: TABLE DATA; Schema: public; Owner: corlaadmin --- - - - --- --- Data for Name: contest_comparison_audit_discrepancy; Type: TABLE DATA; Schema: public; Owner: corlaadmin --- - - - --- --- Data for Name: contest_result; Type: TABLE DATA; Schema: public; Owner: corlaadmin --- - - - --- --- Data for Name: contest_to_audit; Type: TABLE DATA; Schema: public; Owner: corlaadmin --- - - - --- --- Data for Name: contest_vote_total; Type: TABLE DATA; Schema: public; Owner: corlaadmin --- - - - --- --- Data for Name: contests_to_contest_results; Type: TABLE DATA; Schema: public; Owner: corlaadmin --- - - - --- --- Data for Name: counties_to_contest_results; Type: TABLE DATA; Schema: public; Owner: corlaadmin --- - - - --- --- Data for Name: county; Type: TABLE DATA; Schema: public; Owner: corlaadmin --- - -INSERT INTO public.county (id, name, version) VALUES (44, 'Morgan', 0); -INSERT INTO public.county (id, name, version) VALUES (45, 'Otero', 0); -INSERT INTO public.county (id, name, version) VALUES (46, 'Ouray', 0); -INSERT INTO public.county (id, name, version) VALUES (47, 'Park', 0); -INSERT INTO public.county (id, name, version) VALUES (48, 'Phillips', 0); -INSERT INTO public.county (id, name, version) VALUES (49, 'Pitkin', 0); -INSERT INTO public.county (id, name, version) VALUES (50, 'Prowers', 0); -INSERT INTO public.county (id, name, version) VALUES (51, 'Pueblo', 0); -INSERT INTO public.county (id, name, version) VALUES (52, 'Rio Blanco', 0); -INSERT INTO public.county (id, name, version) VALUES (53, 'Rio Grande', 0); -INSERT INTO public.county (id, name, version) VALUES (10, 'Clear Creek', 0); -INSERT INTO public.county (id, name, version) VALUES (54, 'Routt', 0); -INSERT INTO public.county (id, name, version) VALUES (11, 'Conejos', 0); -INSERT INTO public.county (id, name, version) VALUES (55, 'Saguache', 0); -INSERT INTO public.county (id, name, version) VALUES (12, 'Costilla', 0); -INSERT INTO public.county (id, name, version) VALUES (56, 'San Juan', 0); -INSERT INTO public.county (id, name, version) VALUES (13, 'Crowley', 0); -INSERT INTO public.county (id, name, version) VALUES (57, 'San Miguel', 0); -INSERT INTO public.county (id, name, version) VALUES (14, 'Custer', 0); -INSERT INTO public.county (id, name, version) VALUES (58, 'Sedgwick', 0); -INSERT INTO public.county (id, name, version) VALUES (15, 'Delta', 0); -INSERT INTO public.county (id, name, version) VALUES (59, 'Summit', 0); -INSERT INTO public.county (id, name, version) VALUES (16, 'Denver', 0); -INSERT INTO public.county (id, name, version) VALUES (17, 'Dolores', 0); -INSERT INTO public.county (id, name, version) VALUES (18, 'Douglas', 0); -INSERT INTO public.county (id, name, version) VALUES (19, 'Eagle', 0); -INSERT INTO public.county (id, name, version) VALUES (1, 'Adams', 0); -INSERT INTO public.county (id, name, version) VALUES (2, 'Alamosa', 0); -INSERT INTO public.county (id, name, version) VALUES (3, 'Arapahoe', 0); -INSERT INTO public.county (id, name, version) VALUES (4, 'Archuleta', 0); -INSERT INTO public.county (id, name, version) VALUES (5, 'Baca', 0); -INSERT INTO public.county (id, name, version) VALUES (6, 'Bent', 0); -INSERT INTO public.county (id, name, version) VALUES (7, 'Boulder', 0); -INSERT INTO public.county (id, name, version) VALUES (8, 'Chaffee', 0); -INSERT INTO public.county (id, name, version) VALUES (9, 'Cheyenne', 0); -INSERT INTO public.county (id, name, version) VALUES (60, 'Teller', 0); -INSERT INTO public.county (id, name, version) VALUES (61, 'Washington', 0); -INSERT INTO public.county (id, name, version) VALUES (62, 'Weld', 0); -INSERT INTO public.county (id, name, version) VALUES (63, 'Yuma', 0); -INSERT INTO public.county (id, name, version) VALUES (20, 'Elbert', 0); -INSERT INTO public.county (id, name, version) VALUES (64, 'Broomfield', 0); -INSERT INTO public.county (id, name, version) VALUES (21, 'El Paso', 0); -INSERT INTO public.county (id, name, version) VALUES (22, 'Fremont', 0); -INSERT INTO public.county (id, name, version) VALUES (23, 'Garfield', 0); -INSERT INTO public.county (id, name, version) VALUES (24, 'Gilpin', 0); -INSERT INTO public.county (id, name, version) VALUES (25, 'Grand', 0); -INSERT INTO public.county (id, name, version) VALUES (26, 'Gunnison', 0); -INSERT INTO public.county (id, name, version) VALUES (27, 'Hinsdale', 0); -INSERT INTO public.county (id, name, version) VALUES (28, 'Huerfano', 0); -INSERT INTO public.county (id, name, version) VALUES (29, 'Jackson', 0); -INSERT INTO public.county (id, name, version) VALUES (30, 'Jefferson', 0); -INSERT INTO public.county (id, name, version) VALUES (31, 'Kiowa', 0); -INSERT INTO public.county (id, name, version) VALUES (32, 'Kit Carson', 0); -INSERT INTO public.county (id, name, version) VALUES (33, 'Lake', 0); -INSERT INTO public.county (id, name, version) VALUES (34, 'La Plata', 0); -INSERT INTO public.county (id, name, version) VALUES (35, 'Larimer', 0); -INSERT INTO public.county (id, name, version) VALUES (36, 'Las Animas', 0); -INSERT INTO public.county (id, name, version) VALUES (37, 'Lincoln', 0); -INSERT INTO public.county (id, name, version) VALUES (38, 'Logan', 0); -INSERT INTO public.county (id, name, version) VALUES (39, 'Mesa', 0); -INSERT INTO public.county (id, name, version) VALUES (40, 'Mineral', 0); -INSERT INTO public.county (id, name, version) VALUES (41, 'Moffat', 0); -INSERT INTO public.county (id, name, version) VALUES (42, 'Montezuma', 0); -INSERT INTO public.county (id, name, version) VALUES (43, 'Montrose', 0); - - --- --- Data for Name: county_contest_comparison_audit; Type: TABLE DATA; Schema: public; Owner: corlaadmin --- - - - --- --- Data for Name: county_contest_comparison_audit_disagreement; Type: TABLE DATA; Schema: public; Owner: corlaadmin --- - - - --- --- Data for Name: county_contest_comparison_audit_discrepancy; Type: TABLE DATA; Schema: public; Owner: corlaadmin --- - - - --- --- Data for Name: county_contest_result; Type: TABLE DATA; Schema: public; Owner: corlaadmin --- - - - --- --- Data for Name: county_contest_vote_total; Type: TABLE DATA; Schema: public; Owner: corlaadmin --- - - - --- --- Data for Name: county_dashboard; Type: TABLE DATA; Schema: public; Owner: corlaadmin --- - -INSERT INTO public.county_dashboard (id, audit_board_count, driving_contests, audit_timestamp, audited_prefix_length, audited_sample_count, ballots_audited, ballots_in_manifest, current_round_index, cvr_import_error_message, cvr_import_state, cvr_import_timestamp, cvrs_imported, disagreements, discrepancies, version, county_id, cvr_file_id, manifest_file_id) VALUES (44, NULL, '[]', NULL, NULL, NULL, 0, 0, NULL, NULL, 'NOT_ATTEMPTED', '2024-06-05 16:10:01.872368', 0, '{}', '{}', 0, 44, NULL, NULL); -INSERT INTO public.county_dashboard (id, audit_board_count, driving_contests, audit_timestamp, audited_prefix_length, audited_sample_count, ballots_audited, ballots_in_manifest, current_round_index, cvr_import_error_message, cvr_import_state, cvr_import_timestamp, cvrs_imported, disagreements, discrepancies, version, county_id, cvr_file_id, manifest_file_id) VALUES (45, NULL, '[]', NULL, NULL, NULL, 0, 0, NULL, NULL, 'NOT_ATTEMPTED', '2024-06-05 16:10:01.882501', 0, '{}', '{}', 0, 45, NULL, NULL); -INSERT INTO public.county_dashboard (id, audit_board_count, driving_contests, audit_timestamp, audited_prefix_length, audited_sample_count, ballots_audited, ballots_in_manifest, current_round_index, cvr_import_error_message, cvr_import_state, cvr_import_timestamp, cvrs_imported, disagreements, discrepancies, version, county_id, cvr_file_id, manifest_file_id) VALUES (46, NULL, '[]', NULL, NULL, NULL, 0, 0, NULL, NULL, 'NOT_ATTEMPTED', '2024-06-05 16:10:01.888767', 0, '{}', '{}', 0, 46, NULL, NULL); -INSERT INTO public.county_dashboard (id, audit_board_count, driving_contests, audit_timestamp, audited_prefix_length, audited_sample_count, ballots_audited, ballots_in_manifest, current_round_index, cvr_import_error_message, cvr_import_state, cvr_import_timestamp, cvrs_imported, disagreements, discrepancies, version, county_id, cvr_file_id, manifest_file_id) VALUES (47, NULL, '[]', NULL, NULL, NULL, 0, 0, NULL, NULL, 'NOT_ATTEMPTED', '2024-06-05 16:10:01.894559', 0, '{}', '{}', 0, 47, NULL, NULL); -INSERT INTO public.county_dashboard (id, audit_board_count, driving_contests, audit_timestamp, audited_prefix_length, audited_sample_count, ballots_audited, ballots_in_manifest, current_round_index, cvr_import_error_message, cvr_import_state, cvr_import_timestamp, cvrs_imported, disagreements, discrepancies, version, county_id, cvr_file_id, manifest_file_id) VALUES (48, NULL, '[]', NULL, NULL, NULL, 0, 0, NULL, NULL, 'NOT_ATTEMPTED', '2024-06-05 16:10:01.900234', 0, '{}', '{}', 0, 48, NULL, NULL); -INSERT INTO public.county_dashboard (id, audit_board_count, driving_contests, audit_timestamp, audited_prefix_length, audited_sample_count, ballots_audited, ballots_in_manifest, current_round_index, cvr_import_error_message, cvr_import_state, cvr_import_timestamp, cvrs_imported, disagreements, discrepancies, version, county_id, cvr_file_id, manifest_file_id) VALUES (49, NULL, '[]', NULL, NULL, NULL, 0, 0, NULL, NULL, 'NOT_ATTEMPTED', '2024-06-05 16:10:01.905729', 0, '{}', '{}', 0, 49, NULL, NULL); -INSERT INTO public.county_dashboard (id, audit_board_count, driving_contests, audit_timestamp, audited_prefix_length, audited_sample_count, ballots_audited, ballots_in_manifest, current_round_index, cvr_import_error_message, cvr_import_state, cvr_import_timestamp, cvrs_imported, disagreements, discrepancies, version, county_id, cvr_file_id, manifest_file_id) VALUES (50, NULL, '[]', NULL, NULL, NULL, 0, 0, NULL, NULL, 'NOT_ATTEMPTED', '2024-06-05 16:10:01.911399', 0, '{}', '{}', 0, 50, NULL, NULL); -INSERT INTO public.county_dashboard (id, audit_board_count, driving_contests, audit_timestamp, audited_prefix_length, audited_sample_count, ballots_audited, ballots_in_manifest, current_round_index, cvr_import_error_message, cvr_import_state, cvr_import_timestamp, cvrs_imported, disagreements, discrepancies, version, county_id, cvr_file_id, manifest_file_id) VALUES (51, NULL, '[]', NULL, NULL, NULL, 0, 0, NULL, NULL, 'NOT_ATTEMPTED', '2024-06-05 16:10:01.916735', 0, '{}', '{}', 0, 51, NULL, NULL); -INSERT INTO public.county_dashboard (id, audit_board_count, driving_contests, audit_timestamp, audited_prefix_length, audited_sample_count, ballots_audited, ballots_in_manifest, current_round_index, cvr_import_error_message, cvr_import_state, cvr_import_timestamp, cvrs_imported, disagreements, discrepancies, version, county_id, cvr_file_id, manifest_file_id) VALUES (52, NULL, '[]', NULL, NULL, NULL, 0, 0, NULL, NULL, 'NOT_ATTEMPTED', '2024-06-05 16:10:01.922152', 0, '{}', '{}', 0, 52, NULL, NULL); -INSERT INTO public.county_dashboard (id, audit_board_count, driving_contests, audit_timestamp, audited_prefix_length, audited_sample_count, ballots_audited, ballots_in_manifest, current_round_index, cvr_import_error_message, cvr_import_state, cvr_import_timestamp, cvrs_imported, disagreements, discrepancies, version, county_id, cvr_file_id, manifest_file_id) VALUES (53, NULL, '[]', NULL, NULL, NULL, 0, 0, NULL, NULL, 'NOT_ATTEMPTED', '2024-06-05 16:10:01.927412', 0, '{}', '{}', 0, 53, NULL, NULL); -INSERT INTO public.county_dashboard (id, audit_board_count, driving_contests, audit_timestamp, audited_prefix_length, audited_sample_count, ballots_audited, ballots_in_manifest, current_round_index, cvr_import_error_message, cvr_import_state, cvr_import_timestamp, cvrs_imported, disagreements, discrepancies, version, county_id, cvr_file_id, manifest_file_id) VALUES (10, NULL, '[]', NULL, NULL, NULL, 0, 0, NULL, NULL, 'NOT_ATTEMPTED', '2024-06-05 16:10:01.93256', 0, '{}', '{}', 0, 10, NULL, NULL); -INSERT INTO public.county_dashboard (id, audit_board_count, driving_contests, audit_timestamp, audited_prefix_length, audited_sample_count, ballots_audited, ballots_in_manifest, current_round_index, cvr_import_error_message, cvr_import_state, cvr_import_timestamp, cvrs_imported, disagreements, discrepancies, version, county_id, cvr_file_id, manifest_file_id) VALUES (54, NULL, '[]', NULL, NULL, NULL, 0, 0, NULL, NULL, 'NOT_ATTEMPTED', '2024-06-05 16:10:01.937945', 0, '{}', '{}', 0, 54, NULL, NULL); -INSERT INTO public.county_dashboard (id, audit_board_count, driving_contests, audit_timestamp, audited_prefix_length, audited_sample_count, ballots_audited, ballots_in_manifest, current_round_index, cvr_import_error_message, cvr_import_state, cvr_import_timestamp, cvrs_imported, disagreements, discrepancies, version, county_id, cvr_file_id, manifest_file_id) VALUES (11, NULL, '[]', NULL, NULL, NULL, 0, 0, NULL, NULL, 'NOT_ATTEMPTED', '2024-06-05 16:10:01.943517', 0, '{}', '{}', 0, 11, NULL, NULL); -INSERT INTO public.county_dashboard (id, audit_board_count, driving_contests, audit_timestamp, audited_prefix_length, audited_sample_count, ballots_audited, ballots_in_manifest, current_round_index, cvr_import_error_message, cvr_import_state, cvr_import_timestamp, cvrs_imported, disagreements, discrepancies, version, county_id, cvr_file_id, manifest_file_id) VALUES (55, NULL, '[]', NULL, NULL, NULL, 0, 0, NULL, NULL, 'NOT_ATTEMPTED', '2024-06-05 16:10:01.948438', 0, '{}', '{}', 0, 55, NULL, NULL); -INSERT INTO public.county_dashboard (id, audit_board_count, driving_contests, audit_timestamp, audited_prefix_length, audited_sample_count, ballots_audited, ballots_in_manifest, current_round_index, cvr_import_error_message, cvr_import_state, cvr_import_timestamp, cvrs_imported, disagreements, discrepancies, version, county_id, cvr_file_id, manifest_file_id) VALUES (12, NULL, '[]', NULL, NULL, NULL, 0, 0, NULL, NULL, 'NOT_ATTEMPTED', '2024-06-05 16:10:01.953269', 0, '{}', '{}', 0, 12, NULL, NULL); -INSERT INTO public.county_dashboard (id, audit_board_count, driving_contests, audit_timestamp, audited_prefix_length, audited_sample_count, ballots_audited, ballots_in_manifest, current_round_index, cvr_import_error_message, cvr_import_state, cvr_import_timestamp, cvrs_imported, disagreements, discrepancies, version, county_id, cvr_file_id, manifest_file_id) VALUES (56, NULL, '[]', NULL, NULL, NULL, 0, 0, NULL, NULL, 'NOT_ATTEMPTED', '2024-06-05 16:10:01.957856', 0, '{}', '{}', 0, 56, NULL, NULL); -INSERT INTO public.county_dashboard (id, audit_board_count, driving_contests, audit_timestamp, audited_prefix_length, audited_sample_count, ballots_audited, ballots_in_manifest, current_round_index, cvr_import_error_message, cvr_import_state, cvr_import_timestamp, cvrs_imported, disagreements, discrepancies, version, county_id, cvr_file_id, manifest_file_id) VALUES (13, NULL, '[]', NULL, NULL, NULL, 0, 0, NULL, NULL, 'NOT_ATTEMPTED', '2024-06-05 16:10:01.962357', 0, '{}', '{}', 0, 13, NULL, NULL); -INSERT INTO public.county_dashboard (id, audit_board_count, driving_contests, audit_timestamp, audited_prefix_length, audited_sample_count, ballots_audited, ballots_in_manifest, current_round_index, cvr_import_error_message, cvr_import_state, cvr_import_timestamp, cvrs_imported, disagreements, discrepancies, version, county_id, cvr_file_id, manifest_file_id) VALUES (57, NULL, '[]', NULL, NULL, NULL, 0, 0, NULL, NULL, 'NOT_ATTEMPTED', '2024-06-05 16:10:01.96651', 0, '{}', '{}', 0, 57, NULL, NULL); -INSERT INTO public.county_dashboard (id, audit_board_count, driving_contests, audit_timestamp, audited_prefix_length, audited_sample_count, ballots_audited, ballots_in_manifest, current_round_index, cvr_import_error_message, cvr_import_state, cvr_import_timestamp, cvrs_imported, disagreements, discrepancies, version, county_id, cvr_file_id, manifest_file_id) VALUES (14, NULL, '[]', NULL, NULL, NULL, 0, 0, NULL, NULL, 'NOT_ATTEMPTED', '2024-06-05 16:10:01.970294', 0, '{}', '{}', 0, 14, NULL, NULL); -INSERT INTO public.county_dashboard (id, audit_board_count, driving_contests, audit_timestamp, audited_prefix_length, audited_sample_count, ballots_audited, ballots_in_manifest, current_round_index, cvr_import_error_message, cvr_import_state, cvr_import_timestamp, cvrs_imported, disagreements, discrepancies, version, county_id, cvr_file_id, manifest_file_id) VALUES (58, NULL, '[]', NULL, NULL, NULL, 0, 0, NULL, NULL, 'NOT_ATTEMPTED', '2024-06-05 16:10:01.974075', 0, '{}', '{}', 0, 58, NULL, NULL); -INSERT INTO public.county_dashboard (id, audit_board_count, driving_contests, audit_timestamp, audited_prefix_length, audited_sample_count, ballots_audited, ballots_in_manifest, current_round_index, cvr_import_error_message, cvr_import_state, cvr_import_timestamp, cvrs_imported, disagreements, discrepancies, version, county_id, cvr_file_id, manifest_file_id) VALUES (15, NULL, '[]', NULL, NULL, NULL, 0, 0, NULL, NULL, 'NOT_ATTEMPTED', '2024-06-05 16:10:01.978389', 0, '{}', '{}', 0, 15, NULL, NULL); -INSERT INTO public.county_dashboard (id, audit_board_count, driving_contests, audit_timestamp, audited_prefix_length, audited_sample_count, ballots_audited, ballots_in_manifest, current_round_index, cvr_import_error_message, cvr_import_state, cvr_import_timestamp, cvrs_imported, disagreements, discrepancies, version, county_id, cvr_file_id, manifest_file_id) VALUES (59, NULL, '[]', NULL, NULL, NULL, 0, 0, NULL, NULL, 'NOT_ATTEMPTED', '2024-06-05 16:10:01.982609', 0, '{}', '{}', 0, 59, NULL, NULL); -INSERT INTO public.county_dashboard (id, audit_board_count, driving_contests, audit_timestamp, audited_prefix_length, audited_sample_count, ballots_audited, ballots_in_manifest, current_round_index, cvr_import_error_message, cvr_import_state, cvr_import_timestamp, cvrs_imported, disagreements, discrepancies, version, county_id, cvr_file_id, manifest_file_id) VALUES (16, NULL, '[]', NULL, NULL, NULL, 0, 0, NULL, NULL, 'NOT_ATTEMPTED', '2024-06-05 16:10:01.9864', 0, '{}', '{}', 0, 16, NULL, NULL); -INSERT INTO public.county_dashboard (id, audit_board_count, driving_contests, audit_timestamp, audited_prefix_length, audited_sample_count, ballots_audited, ballots_in_manifest, current_round_index, cvr_import_error_message, cvr_import_state, cvr_import_timestamp, cvrs_imported, disagreements, discrepancies, version, county_id, cvr_file_id, manifest_file_id) VALUES (17, NULL, '[]', NULL, NULL, NULL, 0, 0, NULL, NULL, 'NOT_ATTEMPTED', '2024-06-05 16:10:01.990747', 0, '{}', '{}', 0, 17, NULL, NULL); -INSERT INTO public.county_dashboard (id, audit_board_count, driving_contests, audit_timestamp, audited_prefix_length, audited_sample_count, ballots_audited, ballots_in_manifest, current_round_index, cvr_import_error_message, cvr_import_state, cvr_import_timestamp, cvrs_imported, disagreements, discrepancies, version, county_id, cvr_file_id, manifest_file_id) VALUES (18, NULL, '[]', NULL, NULL, NULL, 0, 0, NULL, NULL, 'NOT_ATTEMPTED', '2024-06-05 16:10:01.994852', 0, '{}', '{}', 0, 18, NULL, NULL); -INSERT INTO public.county_dashboard (id, audit_board_count, driving_contests, audit_timestamp, audited_prefix_length, audited_sample_count, ballots_audited, ballots_in_manifest, current_round_index, cvr_import_error_message, cvr_import_state, cvr_import_timestamp, cvrs_imported, disagreements, discrepancies, version, county_id, cvr_file_id, manifest_file_id) VALUES (19, NULL, '[]', NULL, NULL, NULL, 0, 0, NULL, NULL, 'NOT_ATTEMPTED', '2024-06-05 16:10:01.998974', 0, '{}', '{}', 0, 19, NULL, NULL); -INSERT INTO public.county_dashboard (id, audit_board_count, driving_contests, audit_timestamp, audited_prefix_length, audited_sample_count, ballots_audited, ballots_in_manifest, current_round_index, cvr_import_error_message, cvr_import_state, cvr_import_timestamp, cvrs_imported, disagreements, discrepancies, version, county_id, cvr_file_id, manifest_file_id) VALUES (1, NULL, '[]', NULL, NULL, NULL, 0, 0, NULL, NULL, 'NOT_ATTEMPTED', '2024-06-05 16:10:02.003174', 0, '{}', '{}', 0, 1, NULL, NULL); -INSERT INTO public.county_dashboard (id, audit_board_count, driving_contests, audit_timestamp, audited_prefix_length, audited_sample_count, ballots_audited, ballots_in_manifest, current_round_index, cvr_import_error_message, cvr_import_state, cvr_import_timestamp, cvrs_imported, disagreements, discrepancies, version, county_id, cvr_file_id, manifest_file_id) VALUES (2, NULL, '[]', NULL, NULL, NULL, 0, 0, NULL, NULL, 'NOT_ATTEMPTED', '2024-06-05 16:10:02.007701', 0, '{}', '{}', 0, 2, NULL, NULL); -INSERT INTO public.county_dashboard (id, audit_board_count, driving_contests, audit_timestamp, audited_prefix_length, audited_sample_count, ballots_audited, ballots_in_manifest, current_round_index, cvr_import_error_message, cvr_import_state, cvr_import_timestamp, cvrs_imported, disagreements, discrepancies, version, county_id, cvr_file_id, manifest_file_id) VALUES (3, NULL, '[]', NULL, NULL, NULL, 0, 0, NULL, NULL, 'NOT_ATTEMPTED', '2024-06-05 16:10:02.011965', 0, '{}', '{}', 0, 3, NULL, NULL); -INSERT INTO public.county_dashboard (id, audit_board_count, driving_contests, audit_timestamp, audited_prefix_length, audited_sample_count, ballots_audited, ballots_in_manifest, current_round_index, cvr_import_error_message, cvr_import_state, cvr_import_timestamp, cvrs_imported, disagreements, discrepancies, version, county_id, cvr_file_id, manifest_file_id) VALUES (4, NULL, '[]', NULL, NULL, NULL, 0, 0, NULL, NULL, 'NOT_ATTEMPTED', '2024-06-05 16:10:02.016309', 0, '{}', '{}', 0, 4, NULL, NULL); -INSERT INTO public.county_dashboard (id, audit_board_count, driving_contests, audit_timestamp, audited_prefix_length, audited_sample_count, ballots_audited, ballots_in_manifest, current_round_index, cvr_import_error_message, cvr_import_state, cvr_import_timestamp, cvrs_imported, disagreements, discrepancies, version, county_id, cvr_file_id, manifest_file_id) VALUES (5, NULL, '[]', NULL, NULL, NULL, 0, 0, NULL, NULL, 'NOT_ATTEMPTED', '2024-06-05 16:10:02.020429', 0, '{}', '{}', 0, 5, NULL, NULL); -INSERT INTO public.county_dashboard (id, audit_board_count, driving_contests, audit_timestamp, audited_prefix_length, audited_sample_count, ballots_audited, ballots_in_manifest, current_round_index, cvr_import_error_message, cvr_import_state, cvr_import_timestamp, cvrs_imported, disagreements, discrepancies, version, county_id, cvr_file_id, manifest_file_id) VALUES (6, NULL, '[]', NULL, NULL, NULL, 0, 0, NULL, NULL, 'NOT_ATTEMPTED', '2024-06-05 16:10:02.025741', 0, '{}', '{}', 0, 6, NULL, NULL); -INSERT INTO public.county_dashboard (id, audit_board_count, driving_contests, audit_timestamp, audited_prefix_length, audited_sample_count, ballots_audited, ballots_in_manifest, current_round_index, cvr_import_error_message, cvr_import_state, cvr_import_timestamp, cvrs_imported, disagreements, discrepancies, version, county_id, cvr_file_id, manifest_file_id) VALUES (7, NULL, '[]', NULL, NULL, NULL, 0, 0, NULL, NULL, 'NOT_ATTEMPTED', '2024-06-05 16:10:02.029951', 0, '{}', '{}', 0, 7, NULL, NULL); -INSERT INTO public.county_dashboard (id, audit_board_count, driving_contests, audit_timestamp, audited_prefix_length, audited_sample_count, ballots_audited, ballots_in_manifest, current_round_index, cvr_import_error_message, cvr_import_state, cvr_import_timestamp, cvrs_imported, disagreements, discrepancies, version, county_id, cvr_file_id, manifest_file_id) VALUES (8, NULL, '[]', NULL, NULL, NULL, 0, 0, NULL, NULL, 'NOT_ATTEMPTED', '2024-06-05 16:10:02.034429', 0, '{}', '{}', 0, 8, NULL, NULL); -INSERT INTO public.county_dashboard (id, audit_board_count, driving_contests, audit_timestamp, audited_prefix_length, audited_sample_count, ballots_audited, ballots_in_manifest, current_round_index, cvr_import_error_message, cvr_import_state, cvr_import_timestamp, cvrs_imported, disagreements, discrepancies, version, county_id, cvr_file_id, manifest_file_id) VALUES (9, NULL, '[]', NULL, NULL, NULL, 0, 0, NULL, NULL, 'NOT_ATTEMPTED', '2024-06-05 16:10:02.038766', 0, '{}', '{}', 0, 9, NULL, NULL); -INSERT INTO public.county_dashboard (id, audit_board_count, driving_contests, audit_timestamp, audited_prefix_length, audited_sample_count, ballots_audited, ballots_in_manifest, current_round_index, cvr_import_error_message, cvr_import_state, cvr_import_timestamp, cvrs_imported, disagreements, discrepancies, version, county_id, cvr_file_id, manifest_file_id) VALUES (60, NULL, '[]', NULL, NULL, NULL, 0, 0, NULL, NULL, 'NOT_ATTEMPTED', '2024-06-05 16:10:02.042957', 0, '{}', '{}', 0, 60, NULL, NULL); -INSERT INTO public.county_dashboard (id, audit_board_count, driving_contests, audit_timestamp, audited_prefix_length, audited_sample_count, ballots_audited, ballots_in_manifest, current_round_index, cvr_import_error_message, cvr_import_state, cvr_import_timestamp, cvrs_imported, disagreements, discrepancies, version, county_id, cvr_file_id, manifest_file_id) VALUES (61, NULL, '[]', NULL, NULL, NULL, 0, 0, NULL, NULL, 'NOT_ATTEMPTED', '2024-06-05 16:10:02.047306', 0, '{}', '{}', 0, 61, NULL, NULL); -INSERT INTO public.county_dashboard (id, audit_board_count, driving_contests, audit_timestamp, audited_prefix_length, audited_sample_count, ballots_audited, ballots_in_manifest, current_round_index, cvr_import_error_message, cvr_import_state, cvr_import_timestamp, cvrs_imported, disagreements, discrepancies, version, county_id, cvr_file_id, manifest_file_id) VALUES (62, NULL, '[]', NULL, NULL, NULL, 0, 0, NULL, NULL, 'NOT_ATTEMPTED', '2024-06-05 16:10:02.051943', 0, '{}', '{}', 0, 62, NULL, NULL); -INSERT INTO public.county_dashboard (id, audit_board_count, driving_contests, audit_timestamp, audited_prefix_length, audited_sample_count, ballots_audited, ballots_in_manifest, current_round_index, cvr_import_error_message, cvr_import_state, cvr_import_timestamp, cvrs_imported, disagreements, discrepancies, version, county_id, cvr_file_id, manifest_file_id) VALUES (63, NULL, '[]', NULL, NULL, NULL, 0, 0, NULL, NULL, 'NOT_ATTEMPTED', '2024-06-05 16:10:02.056411', 0, '{}', '{}', 0, 63, NULL, NULL); -INSERT INTO public.county_dashboard (id, audit_board_count, driving_contests, audit_timestamp, audited_prefix_length, audited_sample_count, ballots_audited, ballots_in_manifest, current_round_index, cvr_import_error_message, cvr_import_state, cvr_import_timestamp, cvrs_imported, disagreements, discrepancies, version, county_id, cvr_file_id, manifest_file_id) VALUES (20, NULL, '[]', NULL, NULL, NULL, 0, 0, NULL, NULL, 'NOT_ATTEMPTED', '2024-06-05 16:10:02.060835', 0, '{}', '{}', 0, 20, NULL, NULL); -INSERT INTO public.county_dashboard (id, audit_board_count, driving_contests, audit_timestamp, audited_prefix_length, audited_sample_count, ballots_audited, ballots_in_manifest, current_round_index, cvr_import_error_message, cvr_import_state, cvr_import_timestamp, cvrs_imported, disagreements, discrepancies, version, county_id, cvr_file_id, manifest_file_id) VALUES (64, NULL, '[]', NULL, NULL, NULL, 0, 0, NULL, NULL, 'NOT_ATTEMPTED', '2024-06-05 16:10:02.064731', 0, '{}', '{}', 0, 64, NULL, NULL); -INSERT INTO public.county_dashboard (id, audit_board_count, driving_contests, audit_timestamp, audited_prefix_length, audited_sample_count, ballots_audited, ballots_in_manifest, current_round_index, cvr_import_error_message, cvr_import_state, cvr_import_timestamp, cvrs_imported, disagreements, discrepancies, version, county_id, cvr_file_id, manifest_file_id) VALUES (21, NULL, '[]', NULL, NULL, NULL, 0, 0, NULL, NULL, 'NOT_ATTEMPTED', '2024-06-05 16:10:02.068753', 0, '{}', '{}', 0, 21, NULL, NULL); -INSERT INTO public.county_dashboard (id, audit_board_count, driving_contests, audit_timestamp, audited_prefix_length, audited_sample_count, ballots_audited, ballots_in_manifest, current_round_index, cvr_import_error_message, cvr_import_state, cvr_import_timestamp, cvrs_imported, disagreements, discrepancies, version, county_id, cvr_file_id, manifest_file_id) VALUES (22, NULL, '[]', NULL, NULL, NULL, 0, 0, NULL, NULL, 'NOT_ATTEMPTED', '2024-06-05 16:10:02.073424', 0, '{}', '{}', 0, 22, NULL, NULL); -INSERT INTO public.county_dashboard (id, audit_board_count, driving_contests, audit_timestamp, audited_prefix_length, audited_sample_count, ballots_audited, ballots_in_manifest, current_round_index, cvr_import_error_message, cvr_import_state, cvr_import_timestamp, cvrs_imported, disagreements, discrepancies, version, county_id, cvr_file_id, manifest_file_id) VALUES (23, NULL, '[]', NULL, NULL, NULL, 0, 0, NULL, NULL, 'NOT_ATTEMPTED', '2024-06-05 16:10:02.078047', 0, '{}', '{}', 0, 23, NULL, NULL); -INSERT INTO public.county_dashboard (id, audit_board_count, driving_contests, audit_timestamp, audited_prefix_length, audited_sample_count, ballots_audited, ballots_in_manifest, current_round_index, cvr_import_error_message, cvr_import_state, cvr_import_timestamp, cvrs_imported, disagreements, discrepancies, version, county_id, cvr_file_id, manifest_file_id) VALUES (24, NULL, '[]', NULL, NULL, NULL, 0, 0, NULL, NULL, 'NOT_ATTEMPTED', '2024-06-05 16:10:02.082284', 0, '{}', '{}', 0, 24, NULL, NULL); -INSERT INTO public.county_dashboard (id, audit_board_count, driving_contests, audit_timestamp, audited_prefix_length, audited_sample_count, ballots_audited, ballots_in_manifest, current_round_index, cvr_import_error_message, cvr_import_state, cvr_import_timestamp, cvrs_imported, disagreements, discrepancies, version, county_id, cvr_file_id, manifest_file_id) VALUES (25, NULL, '[]', NULL, NULL, NULL, 0, 0, NULL, NULL, 'NOT_ATTEMPTED', '2024-06-05 16:10:02.08637', 0, '{}', '{}', 0, 25, NULL, NULL); -INSERT INTO public.county_dashboard (id, audit_board_count, driving_contests, audit_timestamp, audited_prefix_length, audited_sample_count, ballots_audited, ballots_in_manifest, current_round_index, cvr_import_error_message, cvr_import_state, cvr_import_timestamp, cvrs_imported, disagreements, discrepancies, version, county_id, cvr_file_id, manifest_file_id) VALUES (26, NULL, '[]', NULL, NULL, NULL, 0, 0, NULL, NULL, 'NOT_ATTEMPTED', '2024-06-05 16:10:02.090554', 0, '{}', '{}', 0, 26, NULL, NULL); -INSERT INTO public.county_dashboard (id, audit_board_count, driving_contests, audit_timestamp, audited_prefix_length, audited_sample_count, ballots_audited, ballots_in_manifest, current_round_index, cvr_import_error_message, cvr_import_state, cvr_import_timestamp, cvrs_imported, disagreements, discrepancies, version, county_id, cvr_file_id, manifest_file_id) VALUES (27, NULL, '[]', NULL, NULL, NULL, 0, 0, NULL, NULL, 'NOT_ATTEMPTED', '2024-06-05 16:10:02.094556', 0, '{}', '{}', 0, 27, NULL, NULL); -INSERT INTO public.county_dashboard (id, audit_board_count, driving_contests, audit_timestamp, audited_prefix_length, audited_sample_count, ballots_audited, ballots_in_manifest, current_round_index, cvr_import_error_message, cvr_import_state, cvr_import_timestamp, cvrs_imported, disagreements, discrepancies, version, county_id, cvr_file_id, manifest_file_id) VALUES (28, NULL, '[]', NULL, NULL, NULL, 0, 0, NULL, NULL, 'NOT_ATTEMPTED', '2024-06-05 16:10:02.098595', 0, '{}', '{}', 0, 28, NULL, NULL); -INSERT INTO public.county_dashboard (id, audit_board_count, driving_contests, audit_timestamp, audited_prefix_length, audited_sample_count, ballots_audited, ballots_in_manifest, current_round_index, cvr_import_error_message, cvr_import_state, cvr_import_timestamp, cvrs_imported, disagreements, discrepancies, version, county_id, cvr_file_id, manifest_file_id) VALUES (29, NULL, '[]', NULL, NULL, NULL, 0, 0, NULL, NULL, 'NOT_ATTEMPTED', '2024-06-05 16:10:02.102622', 0, '{}', '{}', 0, 29, NULL, NULL); -INSERT INTO public.county_dashboard (id, audit_board_count, driving_contests, audit_timestamp, audited_prefix_length, audited_sample_count, ballots_audited, ballots_in_manifest, current_round_index, cvr_import_error_message, cvr_import_state, cvr_import_timestamp, cvrs_imported, disagreements, discrepancies, version, county_id, cvr_file_id, manifest_file_id) VALUES (30, NULL, '[]', NULL, NULL, NULL, 0, 0, NULL, NULL, 'NOT_ATTEMPTED', '2024-06-05 16:10:02.106647', 0, '{}', '{}', 0, 30, NULL, NULL); -INSERT INTO public.county_dashboard (id, audit_board_count, driving_contests, audit_timestamp, audited_prefix_length, audited_sample_count, ballots_audited, ballots_in_manifest, current_round_index, cvr_import_error_message, cvr_import_state, cvr_import_timestamp, cvrs_imported, disagreements, discrepancies, version, county_id, cvr_file_id, manifest_file_id) VALUES (31, NULL, '[]', NULL, NULL, NULL, 0, 0, NULL, NULL, 'NOT_ATTEMPTED', '2024-06-05 16:10:02.110718', 0, '{}', '{}', 0, 31, NULL, NULL); -INSERT INTO public.county_dashboard (id, audit_board_count, driving_contests, audit_timestamp, audited_prefix_length, audited_sample_count, ballots_audited, ballots_in_manifest, current_round_index, cvr_import_error_message, cvr_import_state, cvr_import_timestamp, cvrs_imported, disagreements, discrepancies, version, county_id, cvr_file_id, manifest_file_id) VALUES (32, NULL, '[]', NULL, NULL, NULL, 0, 0, NULL, NULL, 'NOT_ATTEMPTED', '2024-06-05 16:10:02.114617', 0, '{}', '{}', 0, 32, NULL, NULL); -INSERT INTO public.county_dashboard (id, audit_board_count, driving_contests, audit_timestamp, audited_prefix_length, audited_sample_count, ballots_audited, ballots_in_manifest, current_round_index, cvr_import_error_message, cvr_import_state, cvr_import_timestamp, cvrs_imported, disagreements, discrepancies, version, county_id, cvr_file_id, manifest_file_id) VALUES (33, NULL, '[]', NULL, NULL, NULL, 0, 0, NULL, NULL, 'NOT_ATTEMPTED', '2024-06-05 16:10:02.118543', 0, '{}', '{}', 0, 33, NULL, NULL); -INSERT INTO public.county_dashboard (id, audit_board_count, driving_contests, audit_timestamp, audited_prefix_length, audited_sample_count, ballots_audited, ballots_in_manifest, current_round_index, cvr_import_error_message, cvr_import_state, cvr_import_timestamp, cvrs_imported, disagreements, discrepancies, version, county_id, cvr_file_id, manifest_file_id) VALUES (34, NULL, '[]', NULL, NULL, NULL, 0, 0, NULL, NULL, 'NOT_ATTEMPTED', '2024-06-05 16:10:02.122478', 0, '{}', '{}', 0, 34, NULL, NULL); -INSERT INTO public.county_dashboard (id, audit_board_count, driving_contests, audit_timestamp, audited_prefix_length, audited_sample_count, ballots_audited, ballots_in_manifest, current_round_index, cvr_import_error_message, cvr_import_state, cvr_import_timestamp, cvrs_imported, disagreements, discrepancies, version, county_id, cvr_file_id, manifest_file_id) VALUES (35, NULL, '[]', NULL, NULL, NULL, 0, 0, NULL, NULL, 'NOT_ATTEMPTED', '2024-06-05 16:10:02.126505', 0, '{}', '{}', 0, 35, NULL, NULL); -INSERT INTO public.county_dashboard (id, audit_board_count, driving_contests, audit_timestamp, audited_prefix_length, audited_sample_count, ballots_audited, ballots_in_manifest, current_round_index, cvr_import_error_message, cvr_import_state, cvr_import_timestamp, cvrs_imported, disagreements, discrepancies, version, county_id, cvr_file_id, manifest_file_id) VALUES (36, NULL, '[]', NULL, NULL, NULL, 0, 0, NULL, NULL, 'NOT_ATTEMPTED', '2024-06-05 16:10:02.130361', 0, '{}', '{}', 0, 36, NULL, NULL); -INSERT INTO public.county_dashboard (id, audit_board_count, driving_contests, audit_timestamp, audited_prefix_length, audited_sample_count, ballots_audited, ballots_in_manifest, current_round_index, cvr_import_error_message, cvr_import_state, cvr_import_timestamp, cvrs_imported, disagreements, discrepancies, version, county_id, cvr_file_id, manifest_file_id) VALUES (37, NULL, '[]', NULL, NULL, NULL, 0, 0, NULL, NULL, 'NOT_ATTEMPTED', '2024-06-05 16:10:02.134456', 0, '{}', '{}', 0, 37, NULL, NULL); -INSERT INTO public.county_dashboard (id, audit_board_count, driving_contests, audit_timestamp, audited_prefix_length, audited_sample_count, ballots_audited, ballots_in_manifest, current_round_index, cvr_import_error_message, cvr_import_state, cvr_import_timestamp, cvrs_imported, disagreements, discrepancies, version, county_id, cvr_file_id, manifest_file_id) VALUES (38, NULL, '[]', NULL, NULL, NULL, 0, 0, NULL, NULL, 'NOT_ATTEMPTED', '2024-06-05 16:10:02.138468', 0, '{}', '{}', 0, 38, NULL, NULL); -INSERT INTO public.county_dashboard (id, audit_board_count, driving_contests, audit_timestamp, audited_prefix_length, audited_sample_count, ballots_audited, ballots_in_manifest, current_round_index, cvr_import_error_message, cvr_import_state, cvr_import_timestamp, cvrs_imported, disagreements, discrepancies, version, county_id, cvr_file_id, manifest_file_id) VALUES (39, NULL, '[]', NULL, NULL, NULL, 0, 0, NULL, NULL, 'NOT_ATTEMPTED', '2024-06-05 16:10:02.14244', 0, '{}', '{}', 0, 39, NULL, NULL); -INSERT INTO public.county_dashboard (id, audit_board_count, driving_contests, audit_timestamp, audited_prefix_length, audited_sample_count, ballots_audited, ballots_in_manifest, current_round_index, cvr_import_error_message, cvr_import_state, cvr_import_timestamp, cvrs_imported, disagreements, discrepancies, version, county_id, cvr_file_id, manifest_file_id) VALUES (40, NULL, '[]', NULL, NULL, NULL, 0, 0, NULL, NULL, 'NOT_ATTEMPTED', '2024-06-05 16:10:02.146486', 0, '{}', '{}', 0, 40, NULL, NULL); -INSERT INTO public.county_dashboard (id, audit_board_count, driving_contests, audit_timestamp, audited_prefix_length, audited_sample_count, ballots_audited, ballots_in_manifest, current_round_index, cvr_import_error_message, cvr_import_state, cvr_import_timestamp, cvrs_imported, disagreements, discrepancies, version, county_id, cvr_file_id, manifest_file_id) VALUES (41, NULL, '[]', NULL, NULL, NULL, 0, 0, NULL, NULL, 'NOT_ATTEMPTED', '2024-06-05 16:10:02.150592', 0, '{}', '{}', 0, 41, NULL, NULL); -INSERT INTO public.county_dashboard (id, audit_board_count, driving_contests, audit_timestamp, audited_prefix_length, audited_sample_count, ballots_audited, ballots_in_manifest, current_round_index, cvr_import_error_message, cvr_import_state, cvr_import_timestamp, cvrs_imported, disagreements, discrepancies, version, county_id, cvr_file_id, manifest_file_id) VALUES (42, NULL, '[]', NULL, NULL, NULL, 0, 0, NULL, NULL, 'NOT_ATTEMPTED', '2024-06-05 16:10:02.154801', 0, '{}', '{}', 0, 42, NULL, NULL); -INSERT INTO public.county_dashboard (id, audit_board_count, driving_contests, audit_timestamp, audited_prefix_length, audited_sample_count, ballots_audited, ballots_in_manifest, current_round_index, cvr_import_error_message, cvr_import_state, cvr_import_timestamp, cvrs_imported, disagreements, discrepancies, version, county_id, cvr_file_id, manifest_file_id) VALUES (43, NULL, '[]', NULL, NULL, NULL, 0, 0, NULL, NULL, 'NOT_ATTEMPTED', '2024-06-05 16:10:02.159136', 0, '{}', '{}', 0, 43, NULL, NULL); - - --- --- Data for Name: county_dashboard_to_comparison_audit; Type: TABLE DATA; Schema: public; Owner: corlaadmin --- - - - --- --- Data for Name: cvr_audit_info; Type: TABLE DATA; Schema: public; Owner: corlaadmin --- - - - --- --- Data for Name: cvr_contest_info; Type: TABLE DATA; Schema: public; Owner: corlaadmin --- - - - --- --- Data for Name: dos_dashboard; Type: TABLE DATA; Schema: public; Owner: corlaadmin --- - -INSERT INTO public.dos_dashboard (id, canonical_choices, canonical_contests, election_date, election_type, public_meeting_date, risk_limit, seed, version) VALUES (0, '{}', '{}', NULL, NULL, NULL, NULL, NULL, 0); - - --- --- Data for Name: log; Type: TABLE DATA; Schema: public; Owner: corlaadmin --- - - - --- --- Data for Name: round; Type: TABLE DATA; Schema: public; Owner: corlaadmin --- - - - --- --- Data for Name: tribute; Type: TABLE DATA; Schema: public; Owner: corlaadmin --- - - - --- --- Data for Name: uploaded_file; Type: TABLE DATA; Schema: public; Owner: corlaadmin --- - - - --- --- Name: assertion_seq; Type: SEQUENCE SET; Schema: public; Owner: corlaadmin --- - -SELECT pg_catalog.setval('public.assertion_seq', 1, false); - - --- --- Name: hibernate_sequence; Type: SEQUENCE SET; Schema: public; Owner: corlaadmin --- - -SELECT pg_catalog.setval('public.hibernate_sequence', 44767, true); - - --- --- Name: administrator administrator_pkey; Type: CONSTRAINT; Schema: public; Owner: corlaadmin --- - -ALTER TABLE ONLY public.administrator - ADD CONSTRAINT administrator_pkey PRIMARY KEY (id); - - --- --- Name: asm_state asm_state_pkey; Type: CONSTRAINT; Schema: public; Owner: corlaadmin --- - -ALTER TABLE ONLY public.asm_state - ADD CONSTRAINT asm_state_pkey PRIMARY KEY (id); - - --- --- Name: audit_board audit_board_pkey; Type: CONSTRAINT; Schema: public; Owner: corlaadmin --- - -ALTER TABLE ONLY public.audit_board - ADD CONSTRAINT audit_board_pkey PRIMARY KEY (dashboard_id, index); - - --- --- Name: audit_intermediate_report audit_intermediate_report_pkey; Type: CONSTRAINT; Schema: public; Owner: corlaadmin --- - -ALTER TABLE ONLY public.audit_intermediate_report - ADD CONSTRAINT audit_intermediate_report_pkey PRIMARY KEY (dashboard_id, index); - - --- --- Name: audit_investigation_report audit_investigation_report_pkey; Type: CONSTRAINT; Schema: public; Owner: corlaadmin --- - -ALTER TABLE ONLY public.audit_investigation_report - ADD CONSTRAINT audit_investigation_report_pkey PRIMARY KEY (dashboard_id, index); - - --- --- Name: ballot_manifest_info ballot_manifest_info_pkey; Type: CONSTRAINT; Schema: public; Owner: corlaadmin --- - -ALTER TABLE ONLY public.ballot_manifest_info - ADD CONSTRAINT ballot_manifest_info_pkey PRIMARY KEY (id); - - --- --- Name: cast_vote_record cast_vote_record_pkey; Type: CONSTRAINT; Schema: public; Owner: corlaadmin --- - -ALTER TABLE ONLY public.cast_vote_record - ADD CONSTRAINT cast_vote_record_pkey PRIMARY KEY (id); - - --- --- Name: comparison_audit comparison_audit_pkey; Type: CONSTRAINT; Schema: public; Owner: corlaadmin --- - -ALTER TABLE ONLY public.comparison_audit - ADD CONSTRAINT comparison_audit_pkey PRIMARY KEY (id); - - --- --- Name: contest_choice contest_choice_pkey; Type: CONSTRAINT; Schema: public; Owner: corlaadmin --- - -ALTER TABLE ONLY public.contest_choice - ADD CONSTRAINT contest_choice_pkey PRIMARY KEY (contest_id, index); - - --- --- Name: contest_comparison_audit_disagreement contest_comparison_audit_disagreement_pkey; Type: CONSTRAINT; Schema: public; Owner: corlaadmin --- - -ALTER TABLE ONLY public.contest_comparison_audit_disagreement - ADD CONSTRAINT contest_comparison_audit_disagreement_pkey PRIMARY KEY (contest_comparison_audit_id, cvr_audit_info_id); - - --- --- Name: contest_comparison_audit_discrepancy contest_comparison_audit_discrepancy_pkey; Type: CONSTRAINT; Schema: public; Owner: corlaadmin --- - -ALTER TABLE ONLY public.contest_comparison_audit_discrepancy - ADD CONSTRAINT contest_comparison_audit_discrepancy_pkey PRIMARY KEY (contest_comparison_audit_id, cvr_audit_info_id); - - --- --- Name: contest contest_pkey; Type: CONSTRAINT; Schema: public; Owner: corlaadmin --- - -ALTER TABLE ONLY public.contest - ADD CONSTRAINT contest_pkey PRIMARY KEY (id); - - --- --- Name: contest_result contest_result_pkey; Type: CONSTRAINT; Schema: public; Owner: corlaadmin --- - -ALTER TABLE ONLY public.contest_result - ADD CONSTRAINT contest_result_pkey PRIMARY KEY (id); - - --- --- Name: contest_vote_total contest_vote_total_pkey; Type: CONSTRAINT; Schema: public; Owner: corlaadmin --- - -ALTER TABLE ONLY public.contest_vote_total - ADD CONSTRAINT contest_vote_total_pkey PRIMARY KEY (result_id, choice); - - --- --- Name: contests_to_contest_results contests_to_contest_results_pkey; Type: CONSTRAINT; Schema: public; Owner: corlaadmin --- - -ALTER TABLE ONLY public.contests_to_contest_results - ADD CONSTRAINT contests_to_contest_results_pkey PRIMARY KEY (contest_result_id, contest_id); - - --- --- Name: counties_to_contest_results counties_to_contest_results_pkey; Type: CONSTRAINT; Schema: public; Owner: corlaadmin --- - -ALTER TABLE ONLY public.counties_to_contest_results - ADD CONSTRAINT counties_to_contest_results_pkey PRIMARY KEY (contest_result_id, county_id); - - --- --- Name: county_contest_comparison_audit_disagreement county_contest_comparison_audit_disagreement_pkey; Type: CONSTRAINT; Schema: public; Owner: corlaadmin --- - -ALTER TABLE ONLY public.county_contest_comparison_audit_disagreement - ADD CONSTRAINT county_contest_comparison_audit_disagreement_pkey PRIMARY KEY (county_contest_comparison_audit_id, cvr_audit_info_id); - - --- --- Name: county_contest_comparison_audit_discrepancy county_contest_comparison_audit_discrepancy_pkey; Type: CONSTRAINT; Schema: public; Owner: corlaadmin --- - -ALTER TABLE ONLY public.county_contest_comparison_audit_discrepancy - ADD CONSTRAINT county_contest_comparison_audit_discrepancy_pkey PRIMARY KEY (county_contest_comparison_audit_id, cvr_audit_info_id); - - --- --- Name: county_contest_comparison_audit county_contest_comparison_audit_pkey; Type: CONSTRAINT; Schema: public; Owner: corlaadmin --- - -ALTER TABLE ONLY public.county_contest_comparison_audit - ADD CONSTRAINT county_contest_comparison_audit_pkey PRIMARY KEY (id); - - --- --- Name: county_contest_result county_contest_result_pkey; Type: CONSTRAINT; Schema: public; Owner: corlaadmin --- - -ALTER TABLE ONLY public.county_contest_result - ADD CONSTRAINT county_contest_result_pkey PRIMARY KEY (id); - - --- --- Name: county_contest_vote_total county_contest_vote_total_pkey; Type: CONSTRAINT; Schema: public; Owner: corlaadmin --- - -ALTER TABLE ONLY public.county_contest_vote_total - ADD CONSTRAINT county_contest_vote_total_pkey PRIMARY KEY (result_id, choice); - - --- --- Name: county_dashboard county_dashboard_pkey; Type: CONSTRAINT; Schema: public; Owner: corlaadmin --- - -ALTER TABLE ONLY public.county_dashboard - ADD CONSTRAINT county_dashboard_pkey PRIMARY KEY (id); - - --- --- Name: county_dashboard_to_comparison_audit county_dashboard_to_comparison_audit_pkey; Type: CONSTRAINT; Schema: public; Owner: corlaadmin --- - -ALTER TABLE ONLY public.county_dashboard_to_comparison_audit - ADD CONSTRAINT county_dashboard_to_comparison_audit_pkey PRIMARY KEY (dashboard_id, comparison_audit_id); - - --- --- Name: county county_pkey; Type: CONSTRAINT; Schema: public; Owner: corlaadmin --- - -ALTER TABLE ONLY public.county - ADD CONSTRAINT county_pkey PRIMARY KEY (id); - - --- --- Name: cvr_audit_info cvr_audit_info_pkey; Type: CONSTRAINT; Schema: public; Owner: corlaadmin --- - -ALTER TABLE ONLY public.cvr_audit_info - ADD CONSTRAINT cvr_audit_info_pkey PRIMARY KEY (id); - - --- --- Name: cvr_contest_info cvr_contest_info_pkey; Type: CONSTRAINT; Schema: public; Owner: corlaadmin --- - -ALTER TABLE ONLY public.cvr_contest_info - ADD CONSTRAINT cvr_contest_info_pkey PRIMARY KEY (cvr_id, index); - - --- --- Name: dos_dashboard dos_dashboard_pkey; Type: CONSTRAINT; Schema: public; Owner: corlaadmin --- - -ALTER TABLE ONLY public.dos_dashboard - ADD CONSTRAINT dos_dashboard_pkey PRIMARY KEY (id); - - --- --- Name: county_contest_result idx_ccr_county_contest; Type: CONSTRAINT; Schema: public; Owner: corlaadmin --- - -ALTER TABLE ONLY public.county_contest_result - ADD CONSTRAINT idx_ccr_county_contest UNIQUE (county_id, contest_id); - - --- --- Name: contest_result idx_cr_contest; Type: CONSTRAINT; Schema: public; Owner: corlaadmin --- - -ALTER TABLE ONLY public.contest_result - ADD CONSTRAINT idx_cr_contest UNIQUE (contest_name); - - --- --- Name: log log_pkey; Type: CONSTRAINT; Schema: public; Owner: corlaadmin --- - -ALTER TABLE ONLY public.log - ADD CONSTRAINT log_pkey PRIMARY KEY (id); - - --- --- Name: round round_pkey; Type: CONSTRAINT; Schema: public; Owner: corlaadmin --- - -ALTER TABLE ONLY public.round - ADD CONSTRAINT round_pkey PRIMARY KEY (dashboard_id, index); - - --- --- Name: tribute tribute_pkey; Type: CONSTRAINT; Schema: public; Owner: corlaadmin --- - -ALTER TABLE ONLY public.tribute - ADD CONSTRAINT tribute_pkey PRIMARY KEY (id); - - --- --- Name: county_dashboard uk_6lcjowb4rw9xav8nqnf5v2klk; Type: CONSTRAINT; Schema: public; Owner: corlaadmin --- - -ALTER TABLE ONLY public.county_dashboard - ADD CONSTRAINT uk_6lcjowb4rw9xav8nqnf5v2klk UNIQUE (county_id); - - --- --- Name: administrator uk_esogmqxeek1uwdyhxvubme3qf; Type: CONSTRAINT; Schema: public; Owner: corlaadmin --- - -ALTER TABLE ONLY public.administrator - ADD CONSTRAINT uk_esogmqxeek1uwdyhxvubme3qf UNIQUE (username); - - --- --- Name: county uk_npkepig28dujo4w98bkmaclhp; Type: CONSTRAINT; Schema: public; Owner: corlaadmin --- - -ALTER TABLE ONLY public.county - ADD CONSTRAINT uk_npkepig28dujo4w98bkmaclhp UNIQUE (name); - - --- --- Name: contests_to_contest_results uk_t1qahmm5y32ovxtqxne8i7ou0; Type: CONSTRAINT; Schema: public; Owner: corlaadmin --- - -ALTER TABLE ONLY public.contests_to_contest_results - ADD CONSTRAINT uk_t1qahmm5y32ovxtqxne8i7ou0 UNIQUE (contest_id); - - --- --- Name: contest_choice uka8o6q5yeepuy2cgnrbx3l1rka; Type: CONSTRAINT; Schema: public; Owner: corlaadmin --- - -ALTER TABLE ONLY public.contest_choice - ADD CONSTRAINT uka8o6q5yeepuy2cgnrbx3l1rka UNIQUE (contest_id, name); - - --- --- Name: contest ukdv45ptogm326acwp45hm46uaf; Type: CONSTRAINT; Schema: public; Owner: corlaadmin --- - -ALTER TABLE ONLY public.contest - ADD CONSTRAINT ukdv45ptogm326acwp45hm46uaf UNIQUE (name, county_id, description, votes_allowed); - - --- --- Name: cast_vote_record uniquecvr; Type: CONSTRAINT; Schema: public; Owner: corlaadmin --- - -ALTER TABLE ONLY public.cast_vote_record - ADD CONSTRAINT uniquecvr UNIQUE (county_id, imprinted_id, record_type, revision); - - --- --- Name: uploaded_file uploaded_file_pkey; Type: CONSTRAINT; Schema: public; Owner: corlaadmin --- - -ALTER TABLE ONLY public.uploaded_file - ADD CONSTRAINT uploaded_file_pkey PRIMARY KEY (id); - - --- --- Name: idx_bmi_county; Type: INDEX; Schema: public; Owner: corlaadmin --- - -CREATE INDEX idx_bmi_county ON public.ballot_manifest_info USING btree (county_id); - - --- --- Name: idx_bmi_seqs; Type: INDEX; Schema: public; Owner: corlaadmin --- - -CREATE INDEX idx_bmi_seqs ON public.ballot_manifest_info USING btree (sequence_start, sequence_end); - - --- --- Name: idx_ccca_dashboard; Type: INDEX; Schema: public; Owner: corlaadmin --- - -CREATE INDEX idx_ccca_dashboard ON public.county_contest_comparison_audit USING btree (dashboard_id); - - --- --- Name: idx_ccr_contest; Type: INDEX; Schema: public; Owner: corlaadmin --- - -CREATE INDEX idx_ccr_contest ON public.county_contest_result USING btree (contest_id); - - --- --- Name: idx_ccr_county; Type: INDEX; Schema: public; Owner: corlaadmin --- - -CREATE INDEX idx_ccr_county ON public.county_contest_result USING btree (county_id); - - --- --- Name: idx_contest_name; Type: INDEX; Schema: public; Owner: corlaadmin --- - -CREATE INDEX idx_contest_name ON public.contest USING btree (name); - - --- --- Name: idx_contest_name_county_description_votes_allowed; Type: INDEX; Schema: public; Owner: corlaadmin --- - -CREATE INDEX idx_contest_name_county_description_votes_allowed ON public.contest USING btree (name, county_id, description, votes_allowed); - - --- --- Name: idx_cvr_county_cvr_number; Type: INDEX; Schema: public; Owner: corlaadmin --- - -CREATE INDEX idx_cvr_county_cvr_number ON public.cast_vote_record USING btree (county_id, cvr_number); - - --- --- Name: idx_cvr_county_cvr_number_type; Type: INDEX; Schema: public; Owner: corlaadmin --- - -CREATE INDEX idx_cvr_county_cvr_number_type ON public.cast_vote_record USING btree (county_id, cvr_number, record_type); - - --- --- Name: idx_cvr_county_imprinted_id_type; Type: INDEX; Schema: public; Owner: corlaadmin --- - -CREATE INDEX idx_cvr_county_imprinted_id_type ON public.cast_vote_record USING btree (county_id, imprinted_id, record_type); - - --- --- Name: idx_cvr_county_sequence_number_type; Type: INDEX; Schema: public; Owner: corlaadmin --- - -CREATE INDEX idx_cvr_county_sequence_number_type ON public.cast_vote_record USING btree (county_id, sequence_number, record_type); - - --- --- Name: idx_cvr_county_type; Type: INDEX; Schema: public; Owner: corlaadmin --- - -CREATE INDEX idx_cvr_county_type ON public.cast_vote_record USING btree (county_id, record_type); - - --- --- Name: idx_cvr_uri; Type: INDEX; Schema: public; Owner: corlaadmin --- - -CREATE INDEX idx_cvr_uri ON public.cast_vote_record USING btree (uri); - - --- --- Name: idx_cvrci_uri; Type: INDEX; Schema: public; Owner: corlaadmin --- - -CREATE INDEX idx_cvrci_uri ON public.cvr_contest_info USING btree (county_id, contest_id); - - --- --- Name: idx_uploaded_file_county; Type: INDEX; Schema: public; Owner: corlaadmin --- - -CREATE INDEX idx_uploaded_file_county ON public.uploaded_file USING btree (county_id); - - --- --- Name: county_dashboard fk1bg939xcuwen7fohfkdx10ueb; Type: FK CONSTRAINT; Schema: public; Owner: corlaadmin --- - -ALTER TABLE ONLY public.county_dashboard - ADD CONSTRAINT fk1bg939xcuwen7fohfkdx10ueb FOREIGN KEY (county_id) REFERENCES public.county(id); - - --- --- Name: counties_to_contest_results fk1ke574b6yqdc8ylu5xyqrounp; Type: FK CONSTRAINT; Schema: public; Owner: corlaadmin --- - -ALTER TABLE ONLY public.counties_to_contest_results - ADD CONSTRAINT fk1ke574b6yqdc8ylu5xyqrounp FOREIGN KEY (county_id) REFERENCES public.county(id); - - --- --- Name: counties_to_contest_results fk2h2muw290os109yqar5p4onms; Type: FK CONSTRAINT; Schema: public; Owner: corlaadmin --- - -ALTER TABLE ONLY public.counties_to_contest_results - ADD CONSTRAINT fk2h2muw290os109yqar5p4onms FOREIGN KEY (contest_result_id) REFERENCES public.contest_result(id); - - --- --- Name: cvr_audit_info fk2n0rxgwa4njtnsm8l4hwc8khy; Type: FK CONSTRAINT; Schema: public; Owner: corlaadmin --- - -ALTER TABLE ONLY public.cvr_audit_info - ADD CONSTRAINT fk2n0rxgwa4njtnsm8l4hwc8khy FOREIGN KEY (acvr_id) REFERENCES public.cast_vote_record(id); - - --- --- Name: county_contest_comparison_audit_discrepancy fk39q8rjoa19c4fdjmv4m9iir06; Type: FK CONSTRAINT; Schema: public; Owner: corlaadmin --- - -ALTER TABLE ONLY public.county_contest_comparison_audit_discrepancy - ADD CONSTRAINT fk39q8rjoa19c4fdjmv4m9iir06 FOREIGN KEY (county_contest_comparison_audit_id) REFERENCES public.county_contest_comparison_audit(id); - - --- --- Name: contest_comparison_audit_discrepancy fk3la5frd86i29mlwjd8akjgpwp; Type: FK CONSTRAINT; Schema: public; Owner: corlaadmin --- - -ALTER TABLE ONLY public.contest_comparison_audit_discrepancy - ADD CONSTRAINT fk3la5frd86i29mlwjd8akjgpwp FOREIGN KEY (cvr_audit_info_id) REFERENCES public.cvr_audit_info(id); - - --- --- Name: county_dashboard fk6rb04heyw700ep1ynn0r31xv3; Type: FK CONSTRAINT; Schema: public; Owner: corlaadmin --- - -ALTER TABLE ONLY public.county_dashboard - ADD CONSTRAINT fk6rb04heyw700ep1ynn0r31xv3 FOREIGN KEY (cvr_file_id) REFERENCES public.uploaded_file(id); - - --- --- Name: county_contest_comparison_audit_disagreement fk7yt9a4fjcdctwmftwwsksdnma; Type: FK CONSTRAINT; Schema: public; Owner: corlaadmin --- - -ALTER TABLE ONLY public.county_contest_comparison_audit_disagreement - ADD CONSTRAINT fk7yt9a4fjcdctwmftwwsksdnma FOREIGN KEY (county_contest_comparison_audit_id) REFERENCES public.county_contest_comparison_audit(id); - - --- --- Name: uploaded_file fk8gh92iwaes042cc1uvi6714yj; Type: FK CONSTRAINT; Schema: public; Owner: corlaadmin --- - -ALTER TABLE ONLY public.uploaded_file - ADD CONSTRAINT fk8gh92iwaes042cc1uvi6714yj FOREIGN KEY (county_id) REFERENCES public.county(id); - - --- --- Name: county_contest_comparison_audit fk8te9gv7q10wxbhg5pgttbj3mv; Type: FK CONSTRAINT; Schema: public; Owner: corlaadmin --- - -ALTER TABLE ONLY public.county_contest_comparison_audit - ADD CONSTRAINT fk8te9gv7q10wxbhg5pgttbj3mv FOREIGN KEY (contest_id) REFERENCES public.contest(id); - - --- --- Name: contest fk932jeyl0hqd21fmakkco5tfa3; Type: FK CONSTRAINT; Schema: public; Owner: corlaadmin --- - -ALTER TABLE ONLY public.contest - ADD CONSTRAINT fk932jeyl0hqd21fmakkco5tfa3 FOREIGN KEY (county_id) REFERENCES public.county(id); - - --- --- Name: county_contest_comparison_audit_disagreement fk9lhehe4o2dgqde06pxycydlu6; Type: FK CONSTRAINT; Schema: public; Owner: corlaadmin --- - -ALTER TABLE ONLY public.county_contest_comparison_audit_disagreement - ADD CONSTRAINT fk9lhehe4o2dgqde06pxycydlu6 FOREIGN KEY (cvr_audit_info_id) REFERENCES public.cvr_audit_info(id); - - --- --- Name: county_contest_comparison_audit fkag9u8fyqni2ehb2dtqop4pox8; Type: FK CONSTRAINT; Schema: public; Owner: corlaadmin --- - -ALTER TABLE ONLY public.county_contest_comparison_audit - ADD CONSTRAINT fkag9u8fyqni2ehb2dtqop4pox8 FOREIGN KEY (contest_result_id) REFERENCES public.contest_result(id); - - --- --- Name: audit_board fkai07es6t6bdw8hidapxxa5xnp; Type: FK CONSTRAINT; Schema: public; Owner: corlaadmin --- - -ALTER TABLE ONLY public.audit_board - ADD CONSTRAINT fkai07es6t6bdw8hidapxxa5xnp FOREIGN KEY (dashboard_id) REFERENCES public.county_dashboard(id); - - --- --- Name: contest_comparison_audit_discrepancy fkcajmftu1xv4jehnm5qhc35j9n; Type: FK CONSTRAINT; Schema: public; Owner: corlaadmin --- - -ALTER TABLE ONLY public.contest_comparison_audit_discrepancy - ADD CONSTRAINT fkcajmftu1xv4jehnm5qhc35j9n FOREIGN KEY (contest_comparison_audit_id) REFERENCES public.comparison_audit(id); - - --- --- Name: county_contest_result fkcuw4fb39imk9pyw360bixorm3; Type: FK CONSTRAINT; Schema: public; Owner: corlaadmin --- - -ALTER TABLE ONLY public.county_contest_result - ADD CONSTRAINT fkcuw4fb39imk9pyw360bixorm3 FOREIGN KEY (county_id) REFERENCES public.county(id); - - --- --- Name: cvr_audit_info fkdks3q3g0srpa44rkkoj3ilve6; Type: FK CONSTRAINT; Schema: public; Owner: corlaadmin --- - -ALTER TABLE ONLY public.cvr_audit_info - ADD CONSTRAINT fkdks3q3g0srpa44rkkoj3ilve6 FOREIGN KEY (cvr_id) REFERENCES public.cast_vote_record(id); - - --- --- Name: audit_investigation_report fkdox65w3y11hyhtcba5hrekq9u; Type: FK CONSTRAINT; Schema: public; Owner: corlaadmin --- - -ALTER TABLE ONLY public.audit_investigation_report - ADD CONSTRAINT fkdox65w3y11hyhtcba5hrekq9u FOREIGN KEY (dashboard_id) REFERENCES public.county_dashboard(id); - - --- --- Name: county_dashboard_to_comparison_audit fkds9j4o8el1f4nepf2677hvs5o; Type: FK CONSTRAINT; Schema: public; Owner: corlaadmin --- - -ALTER TABLE ONLY public.county_dashboard_to_comparison_audit - ADD CONSTRAINT fkds9j4o8el1f4nepf2677hvs5o FOREIGN KEY (dashboard_id) REFERENCES public.county_dashboard(id); - - --- --- Name: cvr_contest_info fke2fqsfmj0uqq311l4c3i0nt7r; Type: FK CONSTRAINT; Schema: public; Owner: corlaadmin --- - -ALTER TABLE ONLY public.cvr_contest_info - ADD CONSTRAINT fke2fqsfmj0uqq311l4c3i0nt7r FOREIGN KEY (contest_id) REFERENCES public.contest(id); - - --- --- Name: round fke3kvxe5r43a4xmeugp8lnme9e; Type: FK CONSTRAINT; Schema: public; Owner: corlaadmin --- - -ALTER TABLE ONLY public.round - ADD CONSTRAINT fke3kvxe5r43a4xmeugp8lnme9e FOREIGN KEY (dashboard_id) REFERENCES public.county_dashboard(id); - - --- --- Name: contest_vote_total fkfjk25vmtng6dv2ejlp8eopy34; Type: FK CONSTRAINT; Schema: public; Owner: corlaadmin --- - -ALTER TABLE ONLY public.contest_vote_total - ADD CONSTRAINT fkfjk25vmtng6dv2ejlp8eopy34 FOREIGN KEY (result_id) REFERENCES public.contest_result(id); - - --- --- Name: log fkfw6ikly73lha9g9em13n3kat4; Type: FK CONSTRAINT; Schema: public; Owner: corlaadmin --- - -ALTER TABLE ONLY public.log - ADD CONSTRAINT fkfw6ikly73lha9g9em13n3kat4 FOREIGN KEY (previous_entry) REFERENCES public.log(id); - - --- --- Name: administrator fkh6rcfib1ishmhry9ctgm16gie; Type: FK CONSTRAINT; Schema: public; Owner: corlaadmin --- - -ALTER TABLE ONLY public.administrator - ADD CONSTRAINT fkh6rcfib1ishmhry9ctgm16gie FOREIGN KEY (county_id) REFERENCES public.county(id); - - --- --- Name: contests_to_contest_results fki7qed7v0pkbi2bnd5fvujtp7; Type: FK CONSTRAINT; Schema: public; Owner: corlaadmin --- - -ALTER TABLE ONLY public.contests_to_contest_results - ADD CONSTRAINT fki7qed7v0pkbi2bnd5fvujtp7 FOREIGN KEY (contest_id) REFERENCES public.contest(id); - - --- --- Name: contest_to_audit fkid09bdp5ifs6m4cnyw3ycyo1s; Type: FK CONSTRAINT; Schema: public; Owner: corlaadmin --- - -ALTER TABLE ONLY public.contest_to_audit - ADD CONSTRAINT fkid09bdp5ifs6m4cnyw3ycyo1s FOREIGN KEY (contest_id) REFERENCES public.contest(id); - - --- --- Name: county_contest_vote_total fkip5dfccmp5x5ubssgar17qpwk; Type: FK CONSTRAINT; Schema: public; Owner: corlaadmin --- - -ALTER TABLE ONLY public.county_contest_vote_total - ADD CONSTRAINT fkip5dfccmp5x5ubssgar17qpwk FOREIGN KEY (result_id) REFERENCES public.county_contest_result(id); - - --- --- Name: contest_to_audit fkjlw9bpyarqou0j26hq7mmq8qm; Type: FK CONSTRAINT; Schema: public; Owner: corlaadmin --- - -ALTER TABLE ONLY public.contest_to_audit - ADD CONSTRAINT fkjlw9bpyarqou0j26hq7mmq8qm FOREIGN KEY (dashboard_id) REFERENCES public.dos_dashboard(id); - - --- --- Name: audit_intermediate_report fkmvj30ou8ik3u7avvycsw0vjx8; Type: FK CONSTRAINT; Schema: public; Owner: corlaadmin --- - -ALTER TABLE ONLY public.audit_intermediate_report - ADD CONSTRAINT fkmvj30ou8ik3u7avvycsw0vjx8 FOREIGN KEY (dashboard_id) REFERENCES public.county_dashboard(id); - - --- --- Name: comparison_audit fkn14qkca2ilirtpr4xctw960pe; Type: FK CONSTRAINT; Schema: public; Owner: corlaadmin --- - -ALTER TABLE ONLY public.comparison_audit - ADD CONSTRAINT fkn14qkca2ilirtpr4xctw960pe FOREIGN KEY (contest_result_id) REFERENCES public.contest_result(id); - - --- --- Name: contest_choice fknsr30axyiavqhyupxohtfy0sl; Type: FK CONSTRAINT; Schema: public; Owner: corlaadmin --- - -ALTER TABLE ONLY public.contest_choice - ADD CONSTRAINT fknsr30axyiavqhyupxohtfy0sl FOREIGN KEY (contest_id) REFERENCES public.contest(id); - - --- --- Name: county_contest_result fkon2wldpt0279jqex3pjx1mhm7; Type: FK CONSTRAINT; Schema: public; Owner: corlaadmin --- - -ALTER TABLE ONLY public.county_contest_result - ADD CONSTRAINT fkon2wldpt0279jqex3pjx1mhm7 FOREIGN KEY (contest_id) REFERENCES public.contest(id); - - --- --- Name: county_contest_comparison_audit_discrepancy fkpe25737bc4mpt170y53ba7il2; Type: FK CONSTRAINT; Schema: public; Owner: corlaadmin --- - -ALTER TABLE ONLY public.county_contest_comparison_audit_discrepancy - ADD CONSTRAINT fkpe25737bc4mpt170y53ba7il2 FOREIGN KEY (cvr_audit_info_id) REFERENCES public.cvr_audit_info(id); - - --- --- Name: contest_comparison_audit_disagreement fkpfdns930t0qv905vbwhgcxnl2; Type: FK CONSTRAINT; Schema: public; Owner: corlaadmin --- - -ALTER TABLE ONLY public.contest_comparison_audit_disagreement - ADD CONSTRAINT fkpfdns930t0qv905vbwhgcxnl2 FOREIGN KEY (cvr_audit_info_id) REFERENCES public.cvr_audit_info(id); - - --- --- Name: contests_to_contest_results fkr1jgmnxu2fbbvujdh3srjmot9; Type: FK CONSTRAINT; Schema: public; Owner: corlaadmin --- - -ALTER TABLE ONLY public.contests_to_contest_results - ADD CONSTRAINT fkr1jgmnxu2fbbvujdh3srjmot9 FOREIGN KEY (contest_result_id) REFERENCES public.contest_result(id); - - --- --- Name: county_dashboard fkrs4q3gwfv0up7swx7q1q6xlwo; Type: FK CONSTRAINT; Schema: public; Owner: corlaadmin --- - -ALTER TABLE ONLY public.county_dashboard - ADD CONSTRAINT fkrs4q3gwfv0up7swx7q1q6xlwo FOREIGN KEY (manifest_file_id) REFERENCES public.uploaded_file(id); - - --- --- Name: cvr_contest_info fkrsovkqe4e839e0aels78u7a3g; Type: FK CONSTRAINT; Schema: public; Owner: corlaadmin --- - -ALTER TABLE ONLY public.cvr_contest_info - ADD CONSTRAINT fkrsovkqe4e839e0aels78u7a3g FOREIGN KEY (cvr_id) REFERENCES public.cast_vote_record(id); - - --- --- Name: county_dashboard_to_comparison_audit fksliko6ckjcr7wvmicuqyreopl; Type: FK CONSTRAINT; Schema: public; Owner: corlaadmin --- - -ALTER TABLE ONLY public.county_dashboard_to_comparison_audit - ADD CONSTRAINT fksliko6ckjcr7wvmicuqyreopl FOREIGN KEY (comparison_audit_id) REFERENCES public.comparison_audit(id); - - --- --- Name: county_contest_comparison_audit fksycb9uto400qabgb97d4ihbat; Type: FK CONSTRAINT; Schema: public; Owner: corlaadmin --- - -ALTER TABLE ONLY public.county_contest_comparison_audit - ADD CONSTRAINT fksycb9uto400qabgb97d4ihbat FOREIGN KEY (dashboard_id) REFERENCES public.county_dashboard(id); - - --- --- Name: contest_comparison_audit_disagreement fkt490by57jb58ubropwn7kmadi; Type: FK CONSTRAINT; Schema: public; Owner: corlaadmin --- - -ALTER TABLE ONLY public.contest_comparison_audit_disagreement - ADD CONSTRAINT fkt490by57jb58ubropwn7kmadi FOREIGN KEY (contest_comparison_audit_id) REFERENCES public.comparison_audit(id); - - --- --- PostgreSQL database dump complete --- - diff --git a/server/eclipse-project/src/test/resources/SQL/corlaInitEmpty.sql b/server/eclipse-project/src/test/resources/SQL/corlaInitEmpty.sql deleted file mode 100644 index dd8f64b5..00000000 --- a/server/eclipse-project/src/test/resources/SQL/corlaInitEmpty.sql +++ /dev/null @@ -1,647 +0,0 @@ --- --- PostgreSQL database dump --- - --- Dumped from database version 14.12 (Ubuntu 14.12-0ubuntu0.22.04.1) --- Dumped by pg_dump version 14.12 (Ubuntu 14.12-0ubuntu0.22.04.1) - -SET statement_timeout = 0; -SET lock_timeout = 0; -SET idle_in_transaction_session_timeout = 0; -SET client_encoding = 'UTF8'; -SET standard_conforming_strings = on; -SELECT pg_catalog.set_config('search_path', '', false); -SET check_function_bodies = false; -SET xmloption = content; -SET client_min_messages = warning; -SET row_security = off; - --- --- Name: public; Type: SCHEMA; Schema: -; Owner: postgres --- - --- CREATE SCHEMA public; - - --- ALTER SCHEMA public OWNER TO postgres; - --- --- Name: SCHEMA public; Type: COMMENT; Schema: -; Owner: postgres --- - -COMMENT ON SCHEMA public IS 'standard public schema'; - - -SET default_tablespace = ''; - -SET default_table_access_method = heap; - --- --- Name: administrator; Type: TABLE; Schema: public; Owner: corlaadmin --- - -CREATE TABLE public.administrator ( - id bigint NOT NULL, - full_name character varying(255) NOT NULL, - last_login_time timestamp without time zone, - last_logout_time timestamp without time zone, - type character varying(255) NOT NULL, - username character varying(255) NOT NULL, - version bigint, - county_id bigint -); - - -ALTER TABLE public.administrator OWNER TO corlaadmin; - --- --- Name: asm_state; Type: TABLE; Schema: public; Owner: corlaadmin --- - -CREATE TABLE public.asm_state ( - id bigint NOT NULL, - asm_class character varying(255) NOT NULL, - asm_identity character varying(255), - state_class character varying(255), - state_value character varying(255), - version bigint -); - - -ALTER TABLE public.asm_state OWNER TO corlaadmin; - --- --- Name: assertion_seq; Type: SEQUENCE; Schema: public; Owner: corlaadmin --- - -CREATE SEQUENCE public.assertion_seq - START WITH 1 - INCREMENT BY 50 - NO MINVALUE - NO MAXVALUE - CACHE 1; - - -ALTER TABLE public.assertion_seq OWNER TO corlaadmin; - --- --- Name: audit_board; Type: TABLE; Schema: public; Owner: corlaadmin --- - -CREATE TABLE public.audit_board ( - dashboard_id bigint NOT NULL, - members text, - sign_in_time timestamp without time zone NOT NULL, - sign_out_time timestamp without time zone, - index integer NOT NULL -); - - -ALTER TABLE public.audit_board OWNER TO corlaadmin; - --- --- Name: audit_intermediate_report; Type: TABLE; Schema: public; Owner: corlaadmin --- - -CREATE TABLE public.audit_intermediate_report ( - dashboard_id bigint NOT NULL, - report character varying(255), - "timestamp" timestamp without time zone, - index integer NOT NULL -); - - -ALTER TABLE public.audit_intermediate_report OWNER TO corlaadmin; - --- --- Name: audit_investigation_report; Type: TABLE; Schema: public; Owner: corlaadmin --- - -CREATE TABLE public.audit_investigation_report ( - dashboard_id bigint NOT NULL, - name character varying(255), - report character varying(255), - "timestamp" timestamp without time zone, - index integer NOT NULL -); - - -ALTER TABLE public.audit_investigation_report OWNER TO corlaadmin; - --- --- Name: ballot_manifest_info; Type: TABLE; Schema: public; Owner: corlaadmin --- - -CREATE TABLE public.ballot_manifest_info ( - id bigint NOT NULL, - batch_id character varying(255) NOT NULL, - batch_size integer NOT NULL, - county_id bigint NOT NULL, - scanner_id integer NOT NULL, - sequence_end bigint NOT NULL, - sequence_start bigint NOT NULL, - storage_location character varying(255) NOT NULL, - version bigint, - ultimate_sequence_end bigint, - ultimate_sequence_start bigint, - uri character varying(255) -); - - -ALTER TABLE public.ballot_manifest_info OWNER TO corlaadmin; - --- --- Name: cast_vote_record; Type: TABLE; Schema: public; Owner: corlaadmin --- - -CREATE TABLE public.cast_vote_record ( - id bigint NOT NULL, - audit_board_index integer, - comment character varying(255), - cvr_id bigint, - ballot_type character varying(255) NOT NULL, - batch_id character varying(255) NOT NULL, - county_id bigint NOT NULL, - cvr_number integer NOT NULL, - imprinted_id character varying(255) NOT NULL, - record_id integer NOT NULL, - record_type character varying(255) NOT NULL, - scanner_id integer NOT NULL, - sequence_number integer, - "timestamp" timestamp without time zone, - version bigint, - rand integer, - revision bigint, - round_number integer, - uri character varying(255) -); - - -ALTER TABLE public.cast_vote_record OWNER TO corlaadmin; - --- --- Name: comparison_audit; Type: TABLE; Schema: public; Owner: corlaadmin --- - -CREATE TABLE public.comparison_audit ( - id bigint NOT NULL, - contest_cvr_ids text, - diluted_margin numeric(10,8) NOT NULL, - audit_reason character varying(255) NOT NULL, - audit_status character varying(255) NOT NULL, - audited_sample_count integer NOT NULL, - disagreement_count integer NOT NULL, - estimated_recalculate_needed boolean NOT NULL, - estimated_samples_to_audit integer NOT NULL, - gamma numeric(10,8) NOT NULL, - one_vote_over_count integer NOT NULL, - one_vote_under_count integer NOT NULL, - optimistic_recalculate_needed boolean NOT NULL, - optimistic_samples_to_audit integer NOT NULL, - other_count integer NOT NULL, - risk_limit numeric(10,8) NOT NULL, - two_vote_over_count integer NOT NULL, - two_vote_under_count integer NOT NULL, - version bigint, - overstatements numeric(19,2), - contest_result_id bigint NOT NULL -); - - -ALTER TABLE public.comparison_audit OWNER TO corlaadmin; - --- --- Name: contest; Type: TABLE; Schema: public; Owner: corlaadmin --- - -CREATE TABLE public.contest ( - id bigint NOT NULL, - description character varying(255) NOT NULL, - name character varying(255) NOT NULL, - sequence_number integer NOT NULL, - version bigint, - votes_allowed integer NOT NULL, - winners_allowed integer NOT NULL, - county_id bigint NOT NULL -); - - -ALTER TABLE public.contest OWNER TO corlaadmin; - --- --- Name: contest_choice; Type: TABLE; Schema: public; Owner: corlaadmin --- - -CREATE TABLE public.contest_choice ( - contest_id bigint NOT NULL, - description character varying(255), - fictitious boolean NOT NULL, - name character varying(255), - qualified_write_in boolean NOT NULL, - index integer NOT NULL -); - - -ALTER TABLE public.contest_choice OWNER TO corlaadmin; - --- --- Name: contest_comparison_audit_disagreement; Type: TABLE; Schema: public; Owner: corlaadmin --- - -CREATE TABLE public.contest_comparison_audit_disagreement ( - contest_comparison_audit_id bigint NOT NULL, - cvr_audit_info_id bigint NOT NULL -); - - -ALTER TABLE public.contest_comparison_audit_disagreement OWNER TO corlaadmin; - --- --- Name: contest_comparison_audit_discrepancy; Type: TABLE; Schema: public; Owner: corlaadmin --- - -CREATE TABLE public.contest_comparison_audit_discrepancy ( - contest_comparison_audit_id bigint NOT NULL, - discrepancy integer, - cvr_audit_info_id bigint NOT NULL -); - - -ALTER TABLE public.contest_comparison_audit_discrepancy OWNER TO corlaadmin; - --- --- Name: contest_result; Type: TABLE; Schema: public; Owner: corlaadmin --- - -CREATE TABLE public.contest_result ( - id bigint NOT NULL, - audit_reason integer, - ballot_count bigint, - contest_name character varying(255) NOT NULL, - diluted_margin numeric(19,2), - losers text, - max_margin integer, - min_margin integer, - version bigint, - winners text, - winners_allowed integer -); - - -ALTER TABLE public.contest_result OWNER TO corlaadmin; - --- --- Name: contest_to_audit; Type: TABLE; Schema: public; Owner: corlaadmin --- - -CREATE TABLE public.contest_to_audit ( - dashboard_id bigint NOT NULL, - audit character varying(255), - contest_id bigint NOT NULL, - reason character varying(255) -); - - -ALTER TABLE public.contest_to_audit OWNER TO corlaadmin; - --- --- Name: contest_vote_total; Type: TABLE; Schema: public; Owner: corlaadmin --- - -CREATE TABLE public.contest_vote_total ( - result_id bigint NOT NULL, - vote_total integer, - choice character varying(255) NOT NULL -); - - -ALTER TABLE public.contest_vote_total OWNER TO corlaadmin; - --- --- Name: contests_to_contest_results; Type: TABLE; Schema: public; Owner: corlaadmin --- - -CREATE TABLE public.contests_to_contest_results ( - contest_result_id bigint NOT NULL, - contest_id bigint NOT NULL -); - - -ALTER TABLE public.contests_to_contest_results OWNER TO corlaadmin; - --- --- Name: counties_to_contest_results; Type: TABLE; Schema: public; Owner: corlaadmin --- - -CREATE TABLE public.counties_to_contest_results ( - contest_result_id bigint NOT NULL, - county_id bigint NOT NULL -); - - -ALTER TABLE public.counties_to_contest_results OWNER TO corlaadmin; - --- --- Name: county; Type: TABLE; Schema: public; Owner: corlaadmin --- - -CREATE TABLE public.county ( - id bigint NOT NULL, - name character varying(255) NOT NULL, - version bigint -); - - -ALTER TABLE public.county OWNER TO corlaadmin; - --- --- Name: county_contest_comparison_audit; Type: TABLE; Schema: public; Owner: corlaadmin --- - -CREATE TABLE public.county_contest_comparison_audit ( - id bigint NOT NULL, - diluted_margin numeric(10,8) NOT NULL, - audit_reason character varying(255) NOT NULL, - audit_status character varying(255) NOT NULL, - audited_sample_count integer NOT NULL, - disagreement_count integer NOT NULL, - estimated_recalculate_needed boolean NOT NULL, - estimated_samples_to_audit integer NOT NULL, - gamma numeric(10,8) NOT NULL, - one_vote_over_count integer NOT NULL, - one_vote_under_count integer NOT NULL, - optimistic_recalculate_needed boolean NOT NULL, - optimistic_samples_to_audit integer NOT NULL, - other_count integer NOT NULL, - risk_limit numeric(10,8) NOT NULL, - two_vote_over_count integer NOT NULL, - two_vote_under_count integer NOT NULL, - version bigint, - contest_id bigint NOT NULL, - contest_result_id bigint NOT NULL, - dashboard_id bigint NOT NULL -); - - -ALTER TABLE public.county_contest_comparison_audit OWNER TO corlaadmin; - --- --- Name: county_contest_comparison_audit_disagreement; Type: TABLE; Schema: public; Owner: corlaadmin --- - -CREATE TABLE public.county_contest_comparison_audit_disagreement ( - county_contest_comparison_audit_id bigint NOT NULL, - cvr_audit_info_id bigint NOT NULL -); - - -ALTER TABLE public.county_contest_comparison_audit_disagreement OWNER TO corlaadmin; - --- --- Name: county_contest_comparison_audit_discrepancy; Type: TABLE; Schema: public; Owner: corlaadmin --- - -CREATE TABLE public.county_contest_comparison_audit_discrepancy ( - county_contest_comparison_audit_id bigint NOT NULL, - discrepancy integer, - cvr_audit_info_id bigint NOT NULL -); - - -ALTER TABLE public.county_contest_comparison_audit_discrepancy OWNER TO corlaadmin; - --- --- Name: county_contest_result; Type: TABLE; Schema: public; Owner: corlaadmin --- - -CREATE TABLE public.county_contest_result ( - id bigint NOT NULL, - contest_ballot_count integer, - county_ballot_count integer, - losers text, - max_margin integer, - min_margin integer, - version bigint, - winners text, - winners_allowed integer NOT NULL, - contest_id bigint NOT NULL, - county_id bigint NOT NULL -); - - -ALTER TABLE public.county_contest_result OWNER TO corlaadmin; - --- --- Name: county_contest_vote_total; Type: TABLE; Schema: public; Owner: corlaadmin --- - -CREATE TABLE public.county_contest_vote_total ( - result_id bigint NOT NULL, - vote_total integer, - choice character varying(255) NOT NULL -); - - -ALTER TABLE public.county_contest_vote_total OWNER TO corlaadmin; - --- --- Name: county_dashboard; Type: TABLE; Schema: public; Owner: corlaadmin --- - -CREATE TABLE public.county_dashboard ( - id bigint NOT NULL, - audit_board_count integer, - driving_contests text, - audit_timestamp timestamp without time zone, - audited_prefix_length integer, - audited_sample_count integer, - ballots_audited integer NOT NULL, - ballots_in_manifest integer NOT NULL, - current_round_index integer, - cvr_import_error_message character varying(255), - cvr_import_state character varying(255), - cvr_import_timestamp timestamp without time zone, - cvrs_imported integer NOT NULL, - disagreements text NOT NULL, - discrepancies text NOT NULL, - version bigint, - county_id bigint NOT NULL, - cvr_file_id bigint, - manifest_file_id bigint -); - - -ALTER TABLE public.county_dashboard OWNER TO corlaadmin; - --- --- Name: county_dashboard_to_comparison_audit; Type: TABLE; Schema: public; Owner: corlaadmin --- - -CREATE TABLE public.county_dashboard_to_comparison_audit ( - dashboard_id bigint NOT NULL, - comparison_audit_id bigint NOT NULL -); - - -ALTER TABLE public.county_dashboard_to_comparison_audit OWNER TO corlaadmin; - --- --- Name: cvr_audit_info; Type: TABLE; Schema: public; Owner: corlaadmin --- - -CREATE TABLE public.cvr_audit_info ( - id bigint NOT NULL, - count_by_contest text, - multiplicity_by_contest text, - disagreement text NOT NULL, - discrepancy text NOT NULL, - version bigint, - acvr_id bigint, - cvr_id bigint NOT NULL -); - - -ALTER TABLE public.cvr_audit_info OWNER TO corlaadmin; - --- --- Name: cvr_contest_info; Type: TABLE; Schema: public; Owner: corlaadmin --- - -CREATE TABLE public.cvr_contest_info ( - cvr_id bigint NOT NULL, - county_id bigint, - choices character varying(1024), - comment character varying(255), - consensus character varying(255), - contest_id bigint NOT NULL, - index integer NOT NULL -); - - -ALTER TABLE public.cvr_contest_info OWNER TO corlaadmin; - --- --- Name: dos_dashboard; Type: TABLE; Schema: public; Owner: corlaadmin --- - -CREATE TABLE public.dos_dashboard ( - id bigint NOT NULL, - canonical_choices text, - canonical_contests text, - election_date timestamp without time zone, - election_type character varying(255), - public_meeting_date timestamp without time zone, - risk_limit numeric(10,8), - seed character varying(255), - version bigint -); - - -ALTER TABLE public.dos_dashboard OWNER TO corlaadmin; - --- --- Name: hibernate_sequence; Type: SEQUENCE; Schema: public; Owner: corlaadmin --- - -CREATE SEQUENCE public.hibernate_sequence - START WITH 1 - INCREMENT BY 1 - NO MINVALUE - NO MAXVALUE - CACHE 1; - - -ALTER TABLE public.hibernate_sequence OWNER TO corlaadmin; - --- --- Name: log; Type: TABLE; Schema: public; Owner: corlaadmin --- - -CREATE TABLE public.log ( - id bigint NOT NULL, - authentication_data character varying(255), - client_host character varying(255), - hash character varying(255) NOT NULL, - information character varying(255) NOT NULL, - result_code integer, - "timestamp" timestamp without time zone NOT NULL, - version bigint, - previous_entry bigint -); - - -ALTER TABLE public.log OWNER TO corlaadmin; - --- --- Name: round; Type: TABLE; Schema: public; Owner: corlaadmin --- - -CREATE TABLE public.round ( - dashboard_id bigint NOT NULL, - ballot_sequence_assignment text NOT NULL, - actual_audited_prefix_length integer, - actual_count integer NOT NULL, - audit_subsequence text NOT NULL, - ballot_sequence text NOT NULL, - disagreements text NOT NULL, - discrepancies text NOT NULL, - end_time timestamp without time zone, - expected_audited_prefix_length integer NOT NULL, - expected_count integer NOT NULL, - number integer NOT NULL, - previous_ballots_audited integer NOT NULL, - signatories text, - start_audited_prefix_length integer NOT NULL, - start_time timestamp without time zone NOT NULL, - index integer NOT NULL -); - - -ALTER TABLE public.round OWNER TO corlaadmin; - --- --- Name: tribute; Type: TABLE; Schema: public; Owner: corlaadmin --- - -CREATE TABLE public.tribute ( - id bigint NOT NULL, - ballot_position integer, - batch_id character varying(255), - contest_name character varying(255), - county_id bigint, - rand integer, - rand_sequence_position integer, - scanner_id integer, - uri character varying(255), - version bigint -); - - -ALTER TABLE public.tribute OWNER TO corlaadmin; - --- --- Name: uploaded_file; Type: TABLE; Schema: public; Owner: corlaadmin --- - -CREATE TABLE public.uploaded_file ( - id bigint NOT NULL, - computed_hash character varying(255) NOT NULL, - approximate_record_count integer NOT NULL, - file oid NOT NULL, - filename character varying(255), - size bigint NOT NULL, - "timestamp" timestamp without time zone NOT NULL, - version bigint, - result text, - status character varying(255) NOT NULL, - submitted_hash character varying(255) NOT NULL, - county_id bigint NOT NULL -); - - -ALTER TABLE public.uploaded_file OWNER TO corlaadmin; - --- --- PostgreSQL database dump complete --- - From 0569b6db9c2116d8ab6133c141598f076bef25c4 Mon Sep 17 00:00:00 2001 From: vteague Date: Mon, 15 Jul 2024 16:21:28 +1000 Subject: [PATCH 07/21] Removed winner from GetAssertionsRequest. --- .../requestToRaire/GetAssertionsRequest.java | 10 +--------- .../corla/endpoint/GetAssertions.java | 4 +--- .../requestToRaire/GetAssertionsRequestTests.java | 2 +- 3 files changed, 3 insertions(+), 13 deletions(-) diff --git a/server/eclipse-project/src/main/java/au/org/democracydevelopers/corla/communication/requestToRaire/GetAssertionsRequest.java b/server/eclipse-project/src/main/java/au/org/democracydevelopers/corla/communication/requestToRaire/GetAssertionsRequest.java index a3cfe7cd..53d0285c 100644 --- a/server/eclipse-project/src/main/java/au/org/democracydevelopers/corla/communication/requestToRaire/GetAssertionsRequest.java +++ b/server/eclipse-project/src/main/java/au/org/democracydevelopers/corla/communication/requestToRaire/GetAssertionsRequest.java @@ -47,12 +47,6 @@ public class GetAssertionsRequest extends ContestRequest { private static final org.apache.log4j.Logger LOGGER = LogManager.getLogger(GetAssertionsRequest.class); - /** - * The winner, as stated by the request. This is written into response metadata - * _without_ being checked. - */ - public final String winner; - /** * The risk limit for the audit, expected to be in the range [0,1]. Defaults to zero, because * then we know we will never mistakenly claim the risk limit has been met. @@ -64,19 +58,17 @@ public class GetAssertionsRequest extends ContestRequest { * @param contestName the name of the contest * @param totalAuditableBallots the total number of ballots in the universe. * @param candidates a list of candidates by name - * @param winner the winner's name * @param riskLimit the risk limit for the audit, expected to be in the range [0,1]. */ @ConstructorProperties({"contestName", "totalAuditableBallots", "candidates", "winner", "riskLimit"}) public GetAssertionsRequest(String contestName, int totalAuditableBallots, List candidates, - String winner, BigDecimal riskLimit) { + BigDecimal riskLimit) { super(contestName, totalAuditableBallots, candidates); final String prefix = "[GetAssertionsRequest constructor]"; LOGGER.debug(String.format("%s Making GetAssertionsRequest for contest %s", prefix, contestName)); - this.winner = winner; this.riskLimit = riskLimit; } } diff --git a/server/eclipse-project/src/main/java/au/org/democracydevelopers/corla/endpoint/GetAssertions.java b/server/eclipse-project/src/main/java/au/org/democracydevelopers/corla/endpoint/GetAssertions.java index e76e749f..33d11be3 100644 --- a/server/eclipse-project/src/main/java/au/org/democracydevelopers/corla/endpoint/GetAssertions.java +++ b/server/eclipse-project/src/main/java/au/org/democracydevelopers/corla/endpoint/GetAssertions.java @@ -171,8 +171,7 @@ public void getAssertions(final ZipOutputStream zos, final BigDecimal riskLimit, final List IRVContestResults = AbstractAllIrvEndpoint.getIRVContestResults(); for (final ContestResult cr : IRVContestResults) { - // Find the winner, candidates and contest name. - final String winner = GenerateAssertionsSummaryQueries.matchingWinner(cr.getContestName()); + // Find the candidates and contest name. final List candidates = cr.getContests().stream().findAny().orElseThrow().choices().stream() .map(Choice::name).toList(); @@ -185,7 +184,6 @@ public void getAssertions(final ZipOutputStream zos, final BigDecimal riskLimit, cr.getContestName(), cr.getBallotCount().intValue(), candidates, - winner, riskLimit ); diff --git a/server/eclipse-project/src/test/java/au/org/democracydevelopers/corla/communication/requestToRaire/GetAssertionsRequestTests.java b/server/eclipse-project/src/test/java/au/org/democracydevelopers/corla/communication/requestToRaire/GetAssertionsRequestTests.java index ec3d41ba..79d07b52 100644 --- a/server/eclipse-project/src/test/java/au/org/democracydevelopers/corla/communication/requestToRaire/GetAssertionsRequestTests.java +++ b/server/eclipse-project/src/test/java/au/org/democracydevelopers/corla/communication/requestToRaire/GetAssertionsRequestTests.java @@ -55,7 +55,7 @@ public class GetAssertionsRequestTests { public void testSerialization() { testUtils.log(LOGGER, "testSerialization"); GetAssertionsRequest request = new GetAssertionsRequest("Test Contest", 50000, - List.of("Alice", "Bob", "Chuan", "Diego"), "Diego", BigDecimal.valueOf(0.05)); + List.of("Alice", "Bob", "Chuan", "Diego"), BigDecimal.valueOf(0.05)); String json = gson.toJson(request); From c1e4983cb27b73c8c46e4559c9c5dc8a2f9b5897 Mon Sep 17 00:00:00 2001 From: vteague Date: Mon, 15 Jul 2024 16:23:07 +1000 Subject: [PATCH 08/21] Remove winner from tests. --- .../communication/requestToRaire/GetAssertionsRequestTests.java | 1 - 1 file changed, 1 deletion(-) diff --git a/server/eclipse-project/src/test/java/au/org/democracydevelopers/corla/communication/requestToRaire/GetAssertionsRequestTests.java b/server/eclipse-project/src/test/java/au/org/democracydevelopers/corla/communication/requestToRaire/GetAssertionsRequestTests.java index 79d07b52..993aa16d 100644 --- a/server/eclipse-project/src/test/java/au/org/democracydevelopers/corla/communication/requestToRaire/GetAssertionsRequestTests.java +++ b/server/eclipse-project/src/test/java/au/org/democracydevelopers/corla/communication/requestToRaire/GetAssertionsRequestTests.java @@ -62,7 +62,6 @@ public void testSerialization() { assertTrue(json.contains("\"contestName\":\"Test Contest\"")); assertTrue(json.contains("\"totalAuditableBallots\":50000")); assertTrue(json.contains("\"candidates\":[\"Alice\",\"Bob\",\"Chuan\",\"Diego\"]")); - assertTrue(json.contains("\"winner\":\"Diego\"")); assertTrue(json.contains("\"riskLimit\":0.05")); } From 267bbd1307fc6f86dad93ab00ef3e10128bfc71b Mon Sep 17 00:00:00 2001 From: vteague Date: Fri, 19 Jul 2024 13:05:54 +1000 Subject: [PATCH 09/21] Improved tests. --- .../corla/endpoint/AbstractAllIrvEndpoint.java | 2 +- .../corla/endpoint/GenerateAssertions.java | 2 +- .../org/democracydevelopers/corla/endpoint/GetAssertions.java | 2 +- .../corla/endpoint/GenerateAssertionsTests.java | 2 ++ .../corla/endpoint/GetAssertionsTests.java | 2 ++ .../corla/model/IRVComparisonAuditTests.java | 3 +++ .../src/test/resources/SQL/simple-assertions.sql | 4 ++++ 7 files changed, 14 insertions(+), 3 deletions(-) diff --git a/server/eclipse-project/src/main/java/au/org/democracydevelopers/corla/endpoint/AbstractAllIrvEndpoint.java b/server/eclipse-project/src/main/java/au/org/democracydevelopers/corla/endpoint/AbstractAllIrvEndpoint.java index 5fbbb21d..f4c4d1d5 100644 --- a/server/eclipse-project/src/main/java/au/org/democracydevelopers/corla/endpoint/AbstractAllIrvEndpoint.java +++ b/server/eclipse-project/src/main/java/au/org/democracydevelopers/corla/endpoint/AbstractAllIrvEndpoint.java @@ -98,7 +98,7 @@ protected void reset() { * @return A list of all ContestResults for IRV contests. * @throws RuntimeException if it encounters contests with a mix of IRV and any other contest type. */ - public static List getIRVContestResults() { + protected static List getIRVContestResults() { final String prefix = "[getIRVContestResults]"; final String msg = "Inconsistent contest types:"; diff --git a/server/eclipse-project/src/main/java/au/org/democracydevelopers/corla/endpoint/GenerateAssertions.java b/server/eclipse-project/src/main/java/au/org/democracydevelopers/corla/endpoint/GenerateAssertions.java index fa7d3896..ed4a0acb 100644 --- a/server/eclipse-project/src/main/java/au/org/democracydevelopers/corla/endpoint/GenerateAssertions.java +++ b/server/eclipse-project/src/main/java/au/org/democracydevelopers/corla/endpoint/GenerateAssertions.java @@ -133,7 +133,7 @@ public String endpointBody(final Request the_request, final Response the_respons final String contestName = the_request.queryParamOrDefault(CONTEST_NAME, ""); // Get all the IRV contest results. - final List IRVContestResults = AbstractAllIrvEndpoint.getIRVContestResults(); + final List IRVContestResults = getIRVContestResults(); try { if(validateParameters(the_request)) { diff --git a/server/eclipse-project/src/main/java/au/org/democracydevelopers/corla/endpoint/GetAssertions.java b/server/eclipse-project/src/main/java/au/org/democracydevelopers/corla/endpoint/GetAssertions.java index 33d11be3..f419319b 100644 --- a/server/eclipse-project/src/main/java/au/org/democracydevelopers/corla/endpoint/GetAssertions.java +++ b/server/eclipse-project/src/main/java/au/org/democracydevelopers/corla/endpoint/GetAssertions.java @@ -168,7 +168,7 @@ public void getAssertions(final ZipOutputStream zos, final BigDecimal riskLimit, // Iterate through all IRV Contests, sending a request to the raire-service for each one's assertions and // collating the responses. - final List IRVContestResults = AbstractAllIrvEndpoint.getIRVContestResults(); + final List IRVContestResults = getIRVContestResults(); for (final ContestResult cr : IRVContestResults) { // Find the candidates and contest name. diff --git a/server/eclipse-project/src/test/java/au/org/democracydevelopers/corla/endpoint/GenerateAssertionsTests.java b/server/eclipse-project/src/test/java/au/org/democracydevelopers/corla/endpoint/GenerateAssertionsTests.java index 4901dcdd..d14e4158 100644 --- a/server/eclipse-project/src/test/java/au/org/democracydevelopers/corla/endpoint/GenerateAssertionsTests.java +++ b/server/eclipse-project/src/test/java/au/org/democracydevelopers/corla/endpoint/GenerateAssertionsTests.java @@ -54,6 +54,8 @@ /** * Test the GetAssertions endpoint, both CSV and JSON versions. The response is supposed to be a zip file containing * the assertions. + * Includes tests that AbstractAllIrvEndpoint::getIRVContestResults returns the correct values and + * throws the correct exceptions. * TODO This really isn't a completely comprehensive set of tests yet. We also need: * - API testing * - Testing that the service throws appropriate exceptions if the raire service connection isn't set up properly. diff --git a/server/eclipse-project/src/test/java/au/org/democracydevelopers/corla/endpoint/GetAssertionsTests.java b/server/eclipse-project/src/test/java/au/org/democracydevelopers/corla/endpoint/GetAssertionsTests.java index 4aab8a81..a9d80105 100644 --- a/server/eclipse-project/src/test/java/au/org/democracydevelopers/corla/endpoint/GetAssertionsTests.java +++ b/server/eclipse-project/src/test/java/au/org/democracydevelopers/corla/endpoint/GetAssertionsTests.java @@ -57,6 +57,8 @@ /** * Test the GetAssertions endpoint, both CSV and JSON versions. The response is supposed to be a zip file containing * the assertions. + * Includes tests that AbstractAllIrvEndpoint::getIRVContestResults returns the correct values and + * throws the correct exceptions. * TODO This really isn't a completely comprehensive set of tests yet. We also need: * - API testing * - Testing for retrieving the data from the zip. diff --git a/server/eclipse-project/src/test/java/au/org/democracydevelopers/corla/model/IRVComparisonAuditTests.java b/server/eclipse-project/src/test/java/au/org/democracydevelopers/corla/model/IRVComparisonAuditTests.java index 168c48c1..553e669e 100644 --- a/server/eclipse-project/src/test/java/au/org/democracydevelopers/corla/model/IRVComparisonAuditTests.java +++ b/server/eclipse-project/src/test/java/au/org/democracydevelopers/corla/model/IRVComparisonAuditTests.java @@ -56,6 +56,9 @@ * TODO: tests for risk measurement. * TODO: tests of the reaudit ballot workflow. * TODO: tests for remaining error modes. + * TODO: tests for when there are no assertions, but there are some assertion generation summaries. + * TODO: tests for when there are neither assertions nor assertion generation summaries (at this + * stage, just throw an exception). */ @Transactional public class IRVComparisonAuditTests extends AssertionTests { diff --git a/server/eclipse-project/src/test/resources/SQL/simple-assertions.sql b/server/eclipse-project/src/test/resources/SQL/simple-assertions.sql index faf48a12..eee075fb 100644 --- a/server/eclipse-project/src/test/resources/SQL/simple-assertions.sql +++ b/server/eclipse-project/src/test/resources/SQL/simple-assertions.sql @@ -1,10 +1,12 @@ -- Simple Assertions for testing Retrieval/Deletion INSERT INTO county (id, name) VALUES (1,'One NEB Assertion County'); INSERT INTO contest (county_id, id, version, description, name, sequence_number, votes_allowed, winners_allowed) VALUES (1,1,0,'IRV','One NEB Assertion Contest',1,5,1); +INSERT INTO generate_assertions_summary (contest_name, error, message, version, warning, winner) VALUES ('One NEB Assertion Contest', '','',0,'', 'Alice'); INSERT INTO assertion (assertion_type, contest_name, difficulty, diluted_margin, loser, margin, current_risk, estimated_samples_to_audit, one_vote_over_count, one_vote_under_count, optimistic_samples_to_audit, other_count, two_vote_over_count, two_vote_under_count, version, winner) values ('NEB', 'One NEB Assertion Contest', 3.125, 0.32, 'Bob', 320, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Alice'); INSERT INTO county (id, name) VALUES (2,'One NEN Assertion County'); INSERT INTO contest (county_id, id, version, description, name, sequence_number, votes_allowed, winners_allowed) VALUES (2,2,0,'IRV','One NEN Assertion Contest',2,4,1); +INSERT INTO generate_assertions_summary (contest_name, error, message, version, warning, winner) VALUES ('One NEN Assertion Contest', '','',0,'', 'Alice'); INSERT INTO assertion (assertion_type, contest_name, difficulty, diluted_margin, loser, margin, current_risk, estimated_samples_to_audit, one_vote_over_count, one_vote_under_count, optimistic_samples_to_audit, other_count, two_vote_over_count, two_vote_under_count, version, winner) values ('NEN', 'One NEN Assertion Contest', 8.33, 0.12, 'Charlie', 240, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Alice'); INSERT INTO assertion_assumed_continuing values (2, 'Alice'); INSERT INTO assertion_assumed_continuing values (2, 'Charlie'); @@ -13,6 +15,7 @@ INSERT INTO assertion_assumed_continuing values (2, 'Bob'); INSERT INTO county (id, name) VALUES (3,'One NEN NEB Assertion County'); INSERT INTO contest (county_id, id, version, description, name, sequence_number, votes_allowed, winners_allowed) VALUES (3,3,0,'IRV','One NEN NEB Assertion Contest',3,4,1); +INSERT INTO generate_assertions_summary (contest_name, error, message, version, warning, winner) VALUES ('One NEN NEB Assertion Contest', '','',0,'', 'Amanda'); INSERT INTO assertion (assertion_type, contest_name, difficulty, diluted_margin, loser, margin, current_risk, estimated_samples_to_audit, one_vote_over_count, one_vote_under_count, optimistic_samples_to_audit, other_count, two_vote_over_count, two_vote_under_count, version, winner) values ('NEB', 'One NEN NEB Assertion Contest', 10, 0.1, 'Liesl', 112, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Amanda'); INSERT INTO assertion (assertion_type, contest_name, difficulty, diluted_margin, loser, margin, current_risk, estimated_samples_to_audit, one_vote_over_count, one_vote_under_count, optimistic_samples_to_audit, other_count, two_vote_over_count, two_vote_under_count, version, winner) values ('NEN', 'One NEN NEB Assertion Contest', 2, 0.5, 'Wendell', 560, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Amanda'); @@ -23,6 +26,7 @@ INSERT INTO assertion_assumed_continuing values (4, 'Amanda'); INSERT INTO contest (county_id, id, version, description, name, sequence_number, votes_allowed, winners_allowed) VALUES (2,4,0,'IRV','Multi-County Contest 1',4,4,1); INSERT INTO contest (county_id, id, version, description, name, sequence_number, votes_allowed, winners_allowed) VALUES (3,5,0,'IRV','Multi-County Contest 1',5,4,1); +INSERT INTO generate_assertions_summary (contest_name, error, message, version, warning, winner) VALUES ('Multi-County Contest 1', '','',0,'', 'Charlie C. Chaplin'); INSERT INTO assertion (assertion_type, contest_name, difficulty, diluted_margin, loser, margin, current_risk, estimated_samples_to_audit, one_vote_over_count, one_vote_under_count, optimistic_samples_to_audit, other_count, two_vote_over_count, two_vote_under_count, version, winner) values ('NEB', 'Multi-County Contest 1', 100, 0.01, 'Alice P. Mangrove', 310, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Charlie C. Chaplin'); INSERT INTO assertion (assertion_type, contest_name, difficulty, diluted_margin, loser, margin, current_risk, estimated_samples_to_audit, one_vote_over_count, one_vote_under_count, optimistic_samples_to_audit, other_count, two_vote_over_count, two_vote_under_count, version, winner) values ('NEB', 'Multi-County Contest 1', 14.3, 0.07, 'Al (Bob) Jones', 2170, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Alice P. Mangrove'); From 48d7811769bf599c04e260febec6522f699ac1d9 Mon Sep 17 00:00:00 2001 From: vteague Date: Fri, 19 Jul 2024 13:06:22 +1000 Subject: [PATCH 10/21] Added tests for assertion generation summary errors. --- .../SQL/summaries-generation-errors.sql | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 server/eclipse-project/src/test/resources/SQL/summaries-generation-errors.sql diff --git a/server/eclipse-project/src/test/resources/SQL/summaries-generation-errors.sql b/server/eclipse-project/src/test/resources/SQL/summaries-generation-errors.sql new file mode 100644 index 00000000..db244aec --- /dev/null +++ b/server/eclipse-project/src/test/resources/SQL/summaries-generation-errors.sql @@ -0,0 +1,38 @@ +-- Assertion Generation summaries for testing retrieval. +INSERT INTO county (id, name) VALUES (1,'Test County'); + +-- Neither a summary nor assertions +INSERT INTO contest (county_id, id, version, description, name, sequence_number, votes_allowed, winners_allowed) + VALUES (1,1,0,'IRV','No summary and no assertions Contest',1,5,1); + +-- A success summary with no assertions +-- This is not supposed to be a reachable state. We just need to check that we fail gracefully. +INSERT INTO contest (county_id, id, version, description, name, sequence_number, votes_allowed, winners_allowed) + VALUES (1,2,0,'IRV','Summary but no assertions Contest',1,5,1); +INSERT INTO generate_assertions_summary (contest_name, error, message, version, warning, winner) + VALUES ('Summary but no assertions Contest', '','',0,'', 'Bob'); + +-- Assertions with no summary +-- This is not supposed to be a reachable state. We just need to check that we fail gracefully. +INSERT INTO contest (county_id, id, version, description, name, sequence_number, votes_allowed, winners_allowed) + VALUES (1,3,0,'IRV','No summary but some assertions Contest',1,5,1); +INSERT INTO assertion (assertion_type, contest_name, difficulty, diluted_margin, loser, margin, current_risk, estimated_samples_to_audit, one_vote_over_count, one_vote_under_count, optimistic_samples_to_audit, other_count, two_vote_over_count, two_vote_under_count, version, winner) + VALUES ('NEN', 'No summary but some assertions Contest', 3.01, 0.12, 'Charlie', 240, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Alice'); + +-- A summary of successful assertion generation, with a TIMEOUT_TRIMMING_ASSERTIONS warning. +INSERT INTO contest (county_id, id, version, description, name, sequence_number, votes_allowed, winners_allowed) + VALUES (1,4,0,'IRV','Timeout trimming assertions Contest',1,5,1); +INSERT INTO generate_assertions_summary (contest_name, error, message, version, warning, winner) + VALUES ('Timeout trimming assertions Contest', '','',0,'TIMEOUT_TRIMMING_ASSERTIONS','Bob'); + +-- A summary of unsuccessful assertion generation, with a TIED_WINNERS error. +INSERT INTO contest (county_id, id, version, description, name, sequence_number, votes_allowed, winners_allowed) + VALUES (1,5,0,'IRV','Tied winners Contest',1,5,1); +INSERT INTO generate_assertions_summary (contest_name, error, message, version, warning, winner) + VALUES ('Tied winners Contest', 'TIED_WINNERS','Tied winners: Alice, Bob',0,'',''); + +-- A summary of unsuccessful assertion generation, with a TIMEOUT_FINDING_ASSERTIONS error. +INSERT INTO contest (county_id, id, version, description, name, sequence_number, votes_allowed, winners_allowed) + VALUES (1,6,0,'IRV','Time out finding Contest',1,5,1); +INSERT INTO generate_assertions_summary (contest_name, error, message, version, warning, winner) + VALUES ('Time out finding Contest', 'TIME_OUT_FINDING_ASSERTIONS','Time out finding assertions',0,'',''); From 2725a27a291b1748a16a202236ef8c4102fc4af9 Mon Sep 17 00:00:00 2001 From: vteague Date: Fri, 19 Jul 2024 13:40:16 +1000 Subject: [PATCH 11/21] Remove updating of contestrequests. --- .../corla/endpoint/GenerateAssertions.java | 18 ------------------ .../corla/model/IRVComparisonAuditTests.java | 2 ++ .../SQL/summaries-generation-errors.sql | 14 +++++++------- 3 files changed, 9 insertions(+), 25 deletions(-) diff --git a/server/eclipse-project/src/main/java/au/org/democracydevelopers/corla/endpoint/GenerateAssertions.java b/server/eclipse-project/src/main/java/au/org/democracydevelopers/corla/endpoint/GenerateAssertions.java index ed4a0acb..081af226 100644 --- a/server/eclipse-project/src/main/java/au/org/democracydevelopers/corla/endpoint/GenerateAssertions.java +++ b/server/eclipse-project/src/main/java/au/org/democracydevelopers/corla/endpoint/GenerateAssertions.java @@ -255,8 +255,6 @@ protected GenerateAssertionsResponseWithErrors generateAssertionsUpdateWinners(L GenerateAssertionsResponse responseFromRaire = Main.GSON.fromJson(EntityUtils.toString(raireResponse.getEntity()), GenerateAssertionsResponse.class); - updateWinnersAndLosers(cr, candidates, responseFromRaire.winner); - LOGGER.debug(String.format("%s %s %s.", prefix, "Completed assertion generation for contest", contestName)); return new GenerateAssertionsResponseWithErrors(contestName, responseFromRaire.winner, ""); @@ -269,8 +267,6 @@ protected GenerateAssertionsResponseWithErrors generateAssertionsUpdateWinners(L LOGGER.debug(String.format("%s %s %s.", prefix, "Error response " + code, "received from RAIRE for " + contestName)); - updateWinnersAndLosers(cr, candidates, UNKNOWN_WINNER); - LOGGER.debug(String.format("%s %s %s.", prefix, "Error response for assertion generation for contest ", contestName)); return new GenerateAssertionsResponseWithErrors(cr.getContestName(), UNKNOWN_WINNER, code); @@ -325,20 +321,6 @@ protected GenerateAssertionsResponseWithErrors generateAssertionsUpdateWinners(L } } - /** - * Update the contestresults in the database according to RAIRE's assessed winners. Set all - * non-winners to be losers, which means all candidates if the contest is un-auditable. - * - * @param cr the contest result, i.e. aggregaged (possibly cross-county) IRV contest. - * @param candidates the list of candidate names. - * @param winner the winner, as determined by raire. - * TODO This is currently non-functional - see Issue #136 ... - */ - private void updateWinnersAndLosers(ContestResult cr, List candidates, String winner) { - cr.setWinners(Set.of(winner)); - cr.setLosers(candidates.stream().filter(c -> !c.equalsIgnoreCase(winner)).collect(Collectors.toSet())); - } - /** * Validates the parameters of a request. For this endpoint, the query parameters are optional, * but if the contest is present it should be non-null, and if a time limit is present it should diff --git a/server/eclipse-project/src/test/java/au/org/democracydevelopers/corla/model/IRVComparisonAuditTests.java b/server/eclipse-project/src/test/java/au/org/democracydevelopers/corla/model/IRVComparisonAuditTests.java index 553e669e..866dac06 100644 --- a/server/eclipse-project/src/test/java/au/org/democracydevelopers/corla/model/IRVComparisonAuditTests.java +++ b/server/eclipse-project/src/test/java/au/org/democracydevelopers/corla/model/IRVComparisonAuditTests.java @@ -59,6 +59,8 @@ * TODO: tests for when there are no assertions, but there are some assertion generation summaries. * TODO: tests for when there are neither assertions nor assertion generation summaries (at this * stage, just throw an exception). + * (These may both be irrelevant depending on how we resolve the construction of IRVComparisonAudits - + * see issue ...) */ @Transactional public class IRVComparisonAuditTests extends AssertionTests { diff --git a/server/eclipse-project/src/test/resources/SQL/summaries-generation-errors.sql b/server/eclipse-project/src/test/resources/SQL/summaries-generation-errors.sql index db244aec..b1b0396e 100644 --- a/server/eclipse-project/src/test/resources/SQL/summaries-generation-errors.sql +++ b/server/eclipse-project/src/test/resources/SQL/summaries-generation-errors.sql @@ -1,38 +1,38 @@ -- Assertion Generation summaries for testing retrieval. -INSERT INTO county (id, name) VALUES (1,'Test County'); +INSERT INTO county (id, name) VALUES (1001,'Test County'); -- Neither a summary nor assertions INSERT INTO contest (county_id, id, version, description, name, sequence_number, votes_allowed, winners_allowed) - VALUES (1,1,0,'IRV','No summary and no assertions Contest',1,5,1); + VALUES (1001,1001,0,'IRV','No summary and no assertions Contest',1,5,1); -- A success summary with no assertions -- This is not supposed to be a reachable state. We just need to check that we fail gracefully. INSERT INTO contest (county_id, id, version, description, name, sequence_number, votes_allowed, winners_allowed) - VALUES (1,2,0,'IRV','Summary but no assertions Contest',1,5,1); + VALUES (1001,1002,0,'IRV','Summary but no assertions Contest',1,5,1); INSERT INTO generate_assertions_summary (contest_name, error, message, version, warning, winner) VALUES ('Summary but no assertions Contest', '','',0,'', 'Bob'); -- Assertions with no summary -- This is not supposed to be a reachable state. We just need to check that we fail gracefully. INSERT INTO contest (county_id, id, version, description, name, sequence_number, votes_allowed, winners_allowed) - VALUES (1,3,0,'IRV','No summary but some assertions Contest',1,5,1); + VALUES (1001,1003,0,'IRV','No summary but some assertions Contest',1,5,1); INSERT INTO assertion (assertion_type, contest_name, difficulty, diluted_margin, loser, margin, current_risk, estimated_samples_to_audit, one_vote_over_count, one_vote_under_count, optimistic_samples_to_audit, other_count, two_vote_over_count, two_vote_under_count, version, winner) VALUES ('NEN', 'No summary but some assertions Contest', 3.01, 0.12, 'Charlie', 240, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Alice'); -- A summary of successful assertion generation, with a TIMEOUT_TRIMMING_ASSERTIONS warning. INSERT INTO contest (county_id, id, version, description, name, sequence_number, votes_allowed, winners_allowed) - VALUES (1,4,0,'IRV','Timeout trimming assertions Contest',1,5,1); + VALUES (1001,1004,0,'IRV','Timeout trimming assertions Contest',1,5,1); INSERT INTO generate_assertions_summary (contest_name, error, message, version, warning, winner) VALUES ('Timeout trimming assertions Contest', '','',0,'TIMEOUT_TRIMMING_ASSERTIONS','Bob'); -- A summary of unsuccessful assertion generation, with a TIED_WINNERS error. INSERT INTO contest (county_id, id, version, description, name, sequence_number, votes_allowed, winners_allowed) - VALUES (1,5,0,'IRV','Tied winners Contest',1,5,1); + VALUES (1001,1005,0,'IRV','Tied winners Contest',1,5,1); INSERT INTO generate_assertions_summary (contest_name, error, message, version, warning, winner) VALUES ('Tied winners Contest', 'TIED_WINNERS','Tied winners: Alice, Bob',0,'',''); -- A summary of unsuccessful assertion generation, with a TIMEOUT_FINDING_ASSERTIONS error. INSERT INTO contest (county_id, id, version, description, name, sequence_number, votes_allowed, winners_allowed) - VALUES (1,6,0,'IRV','Time out finding Contest',1,5,1); + VALUES (1001,1006,0,'IRV','Time out finding Contest',1,5,1); INSERT INTO generate_assertions_summary (contest_name, error, message, version, warning, winner) VALUES ('Time out finding Contest', 'TIME_OUT_FINDING_ASSERTIONS','Time out finding assertions',0,'',''); From a52a58170ae0daf840528e0528a3829a9a6b5606 Mon Sep 17 00:00:00 2001 From: vteague Date: Fri, 19 Jul 2024 13:47:00 +1000 Subject: [PATCH 12/21] Remove junit. --- .../requestToRaire/GenerateAssertionsRequestTests.java | 2 +- .../requestToRaire/GetAssertionsRequestTests.java | 2 +- .../corla/endpoint/GetAssertionsTests.java | 4 ++-- .../corla/model/IRVComparisonAuditTests.java | 2 +- .../corla/model/assertion/NEBAssertionTests.java | 4 ++-- .../corla/model/assertion/NENAssertionTests.java | 4 ++-- .../freeandfair/corla/query/AdministratorQueriesTest.java | 7 ++----- .../corla/query/BallotManifestInfoQueriesTest.java | 2 +- 8 files changed, 12 insertions(+), 15 deletions(-) diff --git a/server/eclipse-project/src/test/java/au/org/democracydevelopers/corla/communication/requestToRaire/GenerateAssertionsRequestTests.java b/server/eclipse-project/src/test/java/au/org/democracydevelopers/corla/communication/requestToRaire/GenerateAssertionsRequestTests.java index d6498ec1..28598cf1 100644 --- a/server/eclipse-project/src/test/java/au/org/democracydevelopers/corla/communication/requestToRaire/GenerateAssertionsRequestTests.java +++ b/server/eclipse-project/src/test/java/au/org/democracydevelopers/corla/communication/requestToRaire/GenerateAssertionsRequestTests.java @@ -29,7 +29,7 @@ import java.util.List; -import static org.testng.AssertJUnit.assertTrue; +import static org.testng.Assert.assertTrue; /** * A very basic test class that constructs a ContestRequest and checks that it serializes correctly. diff --git a/server/eclipse-project/src/test/java/au/org/democracydevelopers/corla/communication/requestToRaire/GetAssertionsRequestTests.java b/server/eclipse-project/src/test/java/au/org/democracydevelopers/corla/communication/requestToRaire/GetAssertionsRequestTests.java index 993aa16d..862dd8b3 100644 --- a/server/eclipse-project/src/test/java/au/org/democracydevelopers/corla/communication/requestToRaire/GetAssertionsRequestTests.java +++ b/server/eclipse-project/src/test/java/au/org/democracydevelopers/corla/communication/requestToRaire/GetAssertionsRequestTests.java @@ -30,7 +30,7 @@ import java.math.BigDecimal; import java.util.List; -import static org.testng.AssertJUnit.assertTrue; +import static org.testng.Assert.assertTrue; /** * A very basic test class that constructs a GetAssertionsRequest and checks that it serializes diff --git a/server/eclipse-project/src/test/java/au/org/democracydevelopers/corla/endpoint/GetAssertionsTests.java b/server/eclipse-project/src/test/java/au/org/democracydevelopers/corla/endpoint/GetAssertionsTests.java index a9d80105..1fefb9c2 100644 --- a/server/eclipse-project/src/test/java/au/org/democracydevelopers/corla/endpoint/GetAssertionsTests.java +++ b/server/eclipse-project/src/test/java/au/org/democracydevelopers/corla/endpoint/GetAssertionsTests.java @@ -50,9 +50,9 @@ import static au.org.democracydevelopers.corla.util.testUtils.*; import static com.github.tomakehurst.wiremock.client.WireMock.*; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertNull; +import static org.testng.Assert.assertNotNull; /** * Test the GetAssertions endpoint, both CSV and JSON versions. The response is supposed to be a zip file containing diff --git a/server/eclipse-project/src/test/java/au/org/democracydevelopers/corla/model/IRVComparisonAuditTests.java b/server/eclipse-project/src/test/java/au/org/democracydevelopers/corla/model/IRVComparisonAuditTests.java index 866dac06..91280b4c 100644 --- a/server/eclipse-project/src/test/java/au/org/democracydevelopers/corla/model/IRVComparisonAuditTests.java +++ b/server/eclipse-project/src/test/java/au/org/democracydevelopers/corla/model/IRVComparisonAuditTests.java @@ -23,7 +23,7 @@ import static au.org.democracydevelopers.corla.util.testUtils.log; import static org.mockito.Mockito.when; -import static org.testng.AssertJUnit.assertEquals; +import static org.testng.Assert.assertEquals; import au.org.democracydevelopers.corla.model.assertion.Assertion; import au.org.democracydevelopers.corla.model.assertion.AssertionTests; diff --git a/server/eclipse-project/src/test/java/au/org/democracydevelopers/corla/model/assertion/NEBAssertionTests.java b/server/eclipse-project/src/test/java/au/org/democracydevelopers/corla/model/assertion/NEBAssertionTests.java index 4520b239..396ecdf1 100644 --- a/server/eclipse-project/src/test/java/au/org/democracydevelopers/corla/model/assertion/NEBAssertionTests.java +++ b/server/eclipse-project/src/test/java/au/org/democracydevelopers/corla/model/assertion/NEBAssertionTests.java @@ -25,8 +25,8 @@ import static java.lang.Math.ceil; import static org.mockito.Mockito.when; import static org.testng.Assert.assertEquals; -import static org.testng.AssertJUnit.assertFalse; -import static org.testng.AssertJUnit.assertTrue; +import static org.testng.Assert.assertFalse; +import static org.testng.Assert.assertTrue; import java.math.BigDecimal; import java.util.List; diff --git a/server/eclipse-project/src/test/java/au/org/democracydevelopers/corla/model/assertion/NENAssertionTests.java b/server/eclipse-project/src/test/java/au/org/democracydevelopers/corla/model/assertion/NENAssertionTests.java index b03ed053..16beba3c 100644 --- a/server/eclipse-project/src/test/java/au/org/democracydevelopers/corla/model/assertion/NENAssertionTests.java +++ b/server/eclipse-project/src/test/java/au/org/democracydevelopers/corla/model/assertion/NENAssertionTests.java @@ -25,8 +25,8 @@ import static java.lang.Math.ceil; import static org.mockito.Mockito.when; import static org.testng.Assert.assertEquals; -import static org.testng.AssertJUnit.assertFalse; -import static org.testng.AssertJUnit.assertTrue; +import static org.testng.Assert.assertFalse; +import static org.testng.Assert.assertTrue; import java.math.BigDecimal; import java.util.List; diff --git a/server/eclipse-project/src/test/java/us/freeandfair/corla/query/AdministratorQueriesTest.java b/server/eclipse-project/src/test/java/us/freeandfair/corla/query/AdministratorQueriesTest.java index 241ee9c0..503ed8dd 100644 --- a/server/eclipse-project/src/test/java/us/freeandfair/corla/query/AdministratorQueriesTest.java +++ b/server/eclipse-project/src/test/java/us/freeandfair/corla/query/AdministratorQueriesTest.java @@ -1,16 +1,13 @@ package us.freeandfair.corla.query; -import org.testcontainers.containers.PostgreSQLContainer; import org.testng.annotations.*; import us.freeandfair.corla.model.Administrator; import us.freeandfair.corla.model.County; import us.freeandfair.corla.persistence.Persistence; import us.freeandfair.corla.util.TestClassWithDatabase; -import java.util.Properties; - -import static org.testng.AssertJUnit.assertEquals; -import static org.testng.AssertJUnit.assertNull; +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertNull; @Test public class AdministratorQueriesTest extends TestClassWithDatabase { diff --git a/server/eclipse-project/src/test/java/us/freeandfair/corla/query/BallotManifestInfoQueriesTest.java b/server/eclipse-project/src/test/java/us/freeandfair/corla/query/BallotManifestInfoQueriesTest.java index c51a0812..17fdfa9c 100644 --- a/server/eclipse-project/src/test/java/us/freeandfair/corla/query/BallotManifestInfoQueriesTest.java +++ b/server/eclipse-project/src/test/java/us/freeandfair/corla/query/BallotManifestInfoQueriesTest.java @@ -12,7 +12,7 @@ import java.util.*; import java.util.Optional; -import static org.testng.AssertJUnit.assertEquals; +import static org.testng.Assert.assertEquals; @Test public class BallotManifestInfoQueriesTest extends TestClassWithDatabase { From 24504c819c2bcc1e0a18b1731bae83b3c62ede59 Mon Sep 17 00:00:00 2001 From: vteague Date: Fri, 19 Jul 2024 16:35:56 +1000 Subject: [PATCH 13/21] Add missing files. --- .../corla/endpoint/GenerateAssertions.java | 33 ++++++ .../model/GenerateAssertionsSummary.java | 102 ++++++++++++++++ .../corla/model/IRVComparisonAudit.java | 3 +- .../GenerateAssertionsSummaryQueries.java | 109 ++++++++++++++++++ .../freeandfair/corla/report/ReportRows.java | 13 +-- 5 files changed, 251 insertions(+), 9 deletions(-) create mode 100644 server/eclipse-project/src/main/java/au/org/democracydevelopers/corla/model/GenerateAssertionsSummary.java create mode 100644 server/eclipse-project/src/main/java/au/org/democracydevelopers/corla/query/GenerateAssertionsSummaryQueries.java diff --git a/server/eclipse-project/src/main/java/au/org/democracydevelopers/corla/endpoint/GenerateAssertions.java b/server/eclipse-project/src/main/java/au/org/democracydevelopers/corla/endpoint/GenerateAssertions.java index 081af226..e5de070b 100644 --- a/server/eclipse-project/src/main/java/au/org/democracydevelopers/corla/endpoint/GenerateAssertions.java +++ b/server/eclipse-project/src/main/java/au/org/democracydevelopers/corla/endpoint/GenerateAssertions.java @@ -39,6 +39,7 @@ import us.freeandfair.corla.Main; import us.freeandfair.corla.model.Choice; import us.freeandfair.corla.model.ContestResult; +import us.freeandfair.corla.persistence.Persistence; import java.io.IOException; import java.io.UnsupportedEncodingException; @@ -166,6 +167,9 @@ public String endpointBody(final Request the_request, final Response the_respons serverError(the_response, e.getMessage()); } + // The only change is updating the winners in the IRV ContestResults. + Persistence.flush(); + return my_endpoint_result.get(); } @@ -255,6 +259,9 @@ protected GenerateAssertionsResponseWithErrors generateAssertionsUpdateWinners(L GenerateAssertionsResponse responseFromRaire = Main.GSON.fromJson(EntityUtils.toString(raireResponse.getEntity()), GenerateAssertionsResponse.class); + // Update the contestRequest with a winner from raire. + updateWinnerAndLosers(cr, candidates, responseFromRaire.winner); + LOGGER.debug(String.format("%s %s %s.", prefix, "Completed assertion generation for contest", contestName)); return new GenerateAssertionsResponseWithErrors(contestName, responseFromRaire.winner, ""); @@ -267,6 +274,9 @@ protected GenerateAssertionsResponseWithErrors generateAssertionsUpdateWinners(L LOGGER.debug(String.format("%s %s %s.", prefix, "Error response " + code, "received from RAIRE for " + contestName)); + // Update the contestRequest with a blank winner. + updateNoWinnerAndAllLosers(cr, candidates); + LOGGER.debug(String.format("%s %s %s.", prefix, "Error response for assertion generation for contest ", contestName)); return new GenerateAssertionsResponseWithErrors(cr.getContestName(), UNKNOWN_WINNER, code); @@ -321,6 +331,29 @@ protected GenerateAssertionsResponseWithErrors generateAssertionsUpdateWinners(L } } + /** + * Update the contestResults in the database for failed assertion generation: no winners. + * Set all candidates as losers. + * @param cr the contestResult to be updated. + * @param candidates the candidates. + */ + private void updateNoWinnerAndAllLosers(ContestResult cr, List candidates) { + cr.setWinners(Set.of()); + cr.setLosers(new HashSet<>(candidates)); + } + + /** + * Update the contestResults in the database according to RAIRE's assessed winners. Set all + * non-winners to be losers. + * @param cr the contest result, i.e. aggregated (possibly cross-county) IRV contest. + * @param candidates the list of candidate names. + * @param winner the winner, as determined by raire. + */ + private void updateWinnerAndLosers(ContestResult cr, List candidates, String winner) { + cr.setWinners(Set.of(winner)); + cr.setLosers(candidates.stream().filter(c -> !c.equalsIgnoreCase(winner)).collect(Collectors.toSet())); + } + /** * Validates the parameters of a request. For this endpoint, the query parameters are optional, * but if the contest is present it should be non-null, and if a time limit is present it should diff --git a/server/eclipse-project/src/main/java/au/org/democracydevelopers/corla/model/GenerateAssertionsSummary.java b/server/eclipse-project/src/main/java/au/org/democracydevelopers/corla/model/GenerateAssertionsSummary.java new file mode 100644 index 00000000..08afe85b --- /dev/null +++ b/server/eclipse-project/src/main/java/au/org/democracydevelopers/corla/model/GenerateAssertionsSummary.java @@ -0,0 +1,102 @@ +/* +Democracy Developers IRV extensions to colorado-rla. + +@copyright 2024 Colorado Department of State + +These IRV extensions are designed to connect to a running instance of the raire +service (https://github.com/DemocracyDevelopers/raire-service), in order to +generate assertions that can be audited using colorado-rla. + +The colorado-rla IRV extensions are free software: you can redistribute it and/or modify it under the terms +of the GNU Affero General Public License as published by the Free Software Foundation, either +version 3 of the License, or (at your option) any later version. + +The colorado-rla IRV extensions are distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the GNU Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License along with +raire-service. If not, see . +*/ + +package au.org.democracydevelopers.corla.model; + +import org.apache.log4j.LogManager; +import org.apache.log4j.Logger; + +import javax.persistence.*; + +import static java.util.Collections.min; + + +/** + * RAIRE (raire-java) generates a set of assertions for a given IRV contest, but it also returns + * the winner and (possibly) an informative error. These are stored in the database, which + * colorado-rla needs to read in order to produce IRV reports. This is read-only table here, with + * data identical to the corresponding class in raire-service. + */ +@Entity +@Table(name = "generate_assertions_summary") +public class GenerateAssertionsSummary { + + /** + * Class-wide logger. + */ + private static final Logger LOGGER = LogManager.getLogger(GenerateAssertionsSummary.class); + + /** + * ID. + */ + @Id + @Column(updatable = false, nullable = false) + @GeneratedValue(strategy = GenerationType.IDENTITY) + private long id; + + /** + * Version. Used for optimistic locking. + */ + @Version + @Column(name = "version", updatable = false, nullable = false) + private long version; + + /** + * Name of the contest. + */ + @Column(name = "contest_name", unique = true, updatable = false, nullable = false) + public String contestName; + + /** + * Name of the winner of the contest, as determined by raire-java. + */ + @Column(name = "winner", updatable = false, nullable = false) + public String winner; + + /** + * An error (matching one of the RaireServiceErrors.RaireErrorCodes), if there was one. Errors + * mean there are no assertions (nor winner), but some warnings + * (e.g. TIME_OUT_TRIMMING_ASSERTIONS) do have assertions and a winner, and allow the audit to + * continue. + */ + @Column(name = "error", updatable = false, nullable = false) + public String error; + + /** + * A warning, if there was one, or emptystring if none. Warnings (e.g. TIME_OUT_TRIMMING_ASSERTIONS) + * mean that assertion generation succeeded and the audit can continue, but re-running with longer + * time allowed might be beneficial. + */ + @Column(name = "warning", updatable = false, nullable = false) + public String warning; + + /** + * The message associated with the error, for example the names of the tied winners. + */ + @Column(name = "message", updatable = false, nullable = false) + public String message; + + /** + * Default no-args constructor (required for persistence). + */ + public GenerateAssertionsSummary() { + } +} \ No newline at end of file diff --git a/server/eclipse-project/src/main/java/au/org/democracydevelopers/corla/model/IRVComparisonAudit.java b/server/eclipse-project/src/main/java/au/org/democracydevelopers/corla/model/IRVComparisonAudit.java index 22a23097..3c33ecfc 100644 --- a/server/eclipse-project/src/main/java/au/org/democracydevelopers/corla/model/IRVComparisonAudit.java +++ b/server/eclipse-project/src/main/java/au/org/democracydevelopers/corla/model/IRVComparisonAudit.java @@ -106,7 +106,8 @@ public IRVComparisonAudit() { * thrown if an unexpected error arises when retrieving assertions from the database, or in the * computation of optimistic and estimated sample sizes. * - * @param contestResult The contest result (identifies the contest under audit). + * @param contestResult The contest result (identifies the contest under audit). This is updated + * with the winner returned * @param riskLimit The risk limit. * @param auditReason The audit reason. */ diff --git a/server/eclipse-project/src/main/java/au/org/democracydevelopers/corla/query/GenerateAssertionsSummaryQueries.java b/server/eclipse-project/src/main/java/au/org/democracydevelopers/corla/query/GenerateAssertionsSummaryQueries.java new file mode 100644 index 00000000..0a0cb4fd --- /dev/null +++ b/server/eclipse-project/src/main/java/au/org/democracydevelopers/corla/query/GenerateAssertionsSummaryQueries.java @@ -0,0 +1,109 @@ +/* +Democracy Developers IRV extensions to colorado-rla. + +@copyright 2024 Colorado Department of State + +These IRV extensions are designed to connect to a running instance of the raire +service (https://github.com/DemocracyDevelopers/raire-service), in order to +generate assertions that can be audited using colorado-rla. + +The colorado-rla IRV extensions are free software: you can redistribute it and/or modify it under the terms +of the GNU Affero General Public License as published by the Free Software Foundation, either +version 3 of the License, or (at your option) any later version. + +The colorado-rla IRV extensions are distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the GNU Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License along with +raire-service. If not, see . +*/ + +package au.org.democracydevelopers.corla.query; + +import au.org.democracydevelopers.corla.model.GenerateAssertionsSummary; +import au.org.democracydevelopers.corla.model.assertion.Assertion; +import org.apache.log4j.LogManager; +import org.apache.log4j.Logger; +import org.hibernate.Session; +import us.freeandfair.corla.persistence.Persistence; + +import javax.persistence.TypedQuery; +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; + +import static au.org.democracydevelopers.corla.endpoint.GenerateAssertions.UNKNOWN_WINNER; + +/** + * Database queries relating to the retrieval of Assertion Generation Summaries from the + * database. It contains a method that executes a query to retrieval all GenerateAssertionsSummaries + * belonging to a specific contest, identified by name. + * Also includes a shortcut function to get the winner, which inserts UNKNOWN_WINNER if either the + * record is absent, or the winner is blank. + * TODO Currently these queries have no uses outside testing - if they are not needed for the UI, + * (e.g. giving feedback about assertion generation) they can be safely deleted. + */ +public class GenerateAssertionsSummaryQueries { + + /** + * Class-wide logger. + */ + public static final Logger LOGGER = LogManager.getLogger(GenerateAssertionsSummaryQueries.class); + + /** + * Retrieve the winner of an IRV contest matching the given contestName, or UNKNOWN_WINNER if + * there is no record, or no winner in the record. + * @param contestName the name of the contest. + */ + public static String matchingWinner(final String contestName) { + Optional optSummary = matching(contestName); + if(optSummary.isPresent() && !optSummary.get().winner.isBlank()) { + return optSummary.get().winner; + } else { + return UNKNOWN_WINNER; + } + } + + /** + * Retrieve all summaries in the database belonging to the contest with the given name. + * @param contestName The contest name. + * @return the (optional) summary of assertions defined for the contest. + * @throws RuntimeException when an unexpected error arose in assertion retrieval (not including + * a NoResultException, which is handled by returning an empty optional item). + */ + public static Optional matching(final String contestName) throws RuntimeException { + final String prefix = "[matching]"; + try { + LOGGER.debug(String.format("%s Select query on generate assertions summary table, retrieving " + + "summary for contest with name %s.", prefix, contestName)); + + final Session s = Persistence.currentSession(); + final TypedQuery q = s.createQuery("select ca from GenerateAssertionsSummary ca " + + " where ca.contestName = :contestName", GenerateAssertionsSummary.class); + q.setParameter("contestName", contestName); + + List result = q.getResultList(); + LOGGER.debug(String.format("%s %d summary results retrieved for contest %s.", prefix, + result.size(), contestName)); + if(result.isEmpty()) { + // No summary was present for this contest. This is expected if GenerateAssertions has not run. + return Optional.empty(); + } else if(result.size() == 1) { + // Expected unique summary, after a run of GenerateAssertions. + return Optional.of(result.get(0)); + } else { + // Duplicate summaries - not expected, since contestName should be unique in the Generate + // Assertions Summary table. + throw new RuntimeException("Duplicate summaries for contest " + contestName); + } + } + catch(Exception e){ + final String msg = String.format("%s An error arose when attempting to retrieve summary data" + + "for contest %s: %s", prefix, contestName, e.getMessage()); + LOGGER.error(msg); + throw new RuntimeException(msg); + } + } + +} diff --git a/server/eclipse-project/src/main/java/us/freeandfair/corla/report/ReportRows.java b/server/eclipse-project/src/main/java/us/freeandfair/corla/report/ReportRows.java index 7ccba69f..253eb96a 100644 --- a/server/eclipse-project/src/main/java/us/freeandfair/corla/report/ReportRows.java +++ b/server/eclipse-project/src/main/java/us/freeandfair/corla/report/ReportRows.java @@ -40,6 +40,8 @@ import us.freeandfair.corla.util.SuppressFBWarnings; +import static au.org.democracydevelopers.corla.endpoint.GenerateAssertions.UNKNOWN_WINNER; + /** * Contains the query-ing and processing of two report types: * activity and results @@ -376,17 +378,12 @@ public static List> genSumResultsReport() { row.put("Contest", ca.contestResult().getContestName()); row.put("targeted", yesNo(ca.isTargeted())); - if(ca instanceof IRVComparisonAudit) { - // If IRV, get the winner's name from the GenerateAssertionsSummary. - row.put("Winner", GenerateAssertionsSummaryQueries.matchingWinner(ca.getContestName())); + if (ca.contestResult().getWinners() == null || ca.contestResult().getWinners().isEmpty()) { + LOGGER.info("no winner!!! " + ca); + row.put("Winner", UNKNOWN_WINNER); } else { - // Must be a plurality audit. ContestResult.winner is correct. - if (ca.contestResult().getWinners() == null || ca.contestResult().getWinners().isEmpty()) { - LOGGER.info("no winner!!! " + ca); - } row.put("Winner", toString(ca.contestResult().getWinners().iterator().next())); } - // All this data makes sense for both IRV and plurality. row.put("Risk Limit met?", yesNo(riskLimitMet(ca.getRiskLimit(), riskMsmnt))); row.put("Risk measurement %", sigFig(percentage(riskMsmnt), 1).toString()); row.put("Audit Risk Limit %", sigFig(percentage(ca.getRiskLimit()),1).toString()); From 908e92bdb17c55d631ea52315d0c8e7bcb921eff Mon Sep 17 00:00:00 2001 From: vteague Date: Fri, 19 Jul 2024 22:00:54 +1000 Subject: [PATCH 14/21] Results Report now has correct IRV winners. --- .../corla/endpoint/GenerateAssertions.java | 36 ++----------------- .../GenerateAssertionsSummaryQueries.java | 3 -- .../freeandfair/corla/report/ReportRows.java | 11 ++++-- 3 files changed, 10 insertions(+), 40 deletions(-) diff --git a/server/eclipse-project/src/main/java/au/org/democracydevelopers/corla/endpoint/GenerateAssertions.java b/server/eclipse-project/src/main/java/au/org/democracydevelopers/corla/endpoint/GenerateAssertions.java index e5de070b..ba884292 100644 --- a/server/eclipse-project/src/main/java/au/org/democracydevelopers/corla/endpoint/GenerateAssertions.java +++ b/server/eclipse-project/src/main/java/au/org/democracydevelopers/corla/endpoint/GenerateAssertions.java @@ -47,7 +47,6 @@ import java.net.URISyntaxException; import java.net.URL; import java.util.*; -import java.util.stream.Collectors; /** * The Generate Assertions endpoint. Takes a GenerateAssertionsRequest, and optional parameters @@ -252,31 +251,24 @@ protected GenerateAssertionsResponseWithErrors generateAssertionsUpdateWinners(L final boolean gotRaireError = raireResponse.containsHeader(RaireServiceErrors.ERROR_CODE_KEY); if (statusCode == HttpStatus.SC_OK && !gotRaireError) { - // OK response. Update the stored winner and return it. + // OK response. Return the winner. LOGGER.debug(String.format("%s %s %s.", prefix, "OK response received from RAIRE for", contestName)); GenerateAssertionsResponse responseFromRaire = Main.GSON.fromJson(EntityUtils.toString(raireResponse.getEntity()), GenerateAssertionsResponse.class); - // Update the contestRequest with a winner from raire. - updateWinnerAndLosers(cr, candidates, responseFromRaire.winner); - LOGGER.debug(String.format("%s %s %s.", prefix, "Completed assertion generation for contest", contestName)); return new GenerateAssertionsResponseWithErrors(contestName, responseFromRaire.winner, ""); } else if (statusCode == HttpStatus.SC_INTERNAL_SERVER_ERROR && gotRaireError) { - // Error response about a specific contest, e.g. "TIED_WINNERS". - // Return the error, record it. + // Error response about a specific contest, e.g. "TIED_WINNERS". Return the error. final String code = raireResponse.getFirstHeader(RaireServiceErrors.ERROR_CODE_KEY).getValue(); LOGGER.debug(String.format("%s %s %s.", prefix, "Error response " + code, "received from RAIRE for " + contestName)); - // Update the contestRequest with a blank winner. - updateNoWinnerAndAllLosers(cr, candidates); - LOGGER.debug(String.format("%s %s %s.", prefix, "Error response for assertion generation for contest ", contestName)); return new GenerateAssertionsResponseWithErrors(cr.getContestName(), UNKNOWN_WINNER, code); @@ -288,7 +280,6 @@ protected GenerateAssertionsResponseWithErrors generateAssertionsUpdateWinners(L LOGGER.error(String.format("%s %s", prefix, msg)); throw new RuntimeException(msg); } - } catch (URISyntaxException | MalformedURLException e) { // The raire service url is malformed, probably a config error. final String msg = "Bad configuration of Raire service url: " + raireUrl + ". Check your config file."; @@ -331,29 +322,6 @@ protected GenerateAssertionsResponseWithErrors generateAssertionsUpdateWinners(L } } - /** - * Update the contestResults in the database for failed assertion generation: no winners. - * Set all candidates as losers. - * @param cr the contestResult to be updated. - * @param candidates the candidates. - */ - private void updateNoWinnerAndAllLosers(ContestResult cr, List candidates) { - cr.setWinners(Set.of()); - cr.setLosers(new HashSet<>(candidates)); - } - - /** - * Update the contestResults in the database according to RAIRE's assessed winners. Set all - * non-winners to be losers. - * @param cr the contest result, i.e. aggregated (possibly cross-county) IRV contest. - * @param candidates the list of candidate names. - * @param winner the winner, as determined by raire. - */ - private void updateWinnerAndLosers(ContestResult cr, List candidates, String winner) { - cr.setWinners(Set.of(winner)); - cr.setLosers(candidates.stream().filter(c -> !c.equalsIgnoreCase(winner)).collect(Collectors.toSet())); - } - /** * Validates the parameters of a request. For this endpoint, the query parameters are optional, * but if the contest is present it should be non-null, and if a time limit is present it should diff --git a/server/eclipse-project/src/main/java/au/org/democracydevelopers/corla/query/GenerateAssertionsSummaryQueries.java b/server/eclipse-project/src/main/java/au/org/democracydevelopers/corla/query/GenerateAssertionsSummaryQueries.java index 0a0cb4fd..8a21b69e 100644 --- a/server/eclipse-project/src/main/java/au/org/democracydevelopers/corla/query/GenerateAssertionsSummaryQueries.java +++ b/server/eclipse-project/src/main/java/au/org/democracydevelopers/corla/query/GenerateAssertionsSummaryQueries.java @@ -22,14 +22,12 @@ package au.org.democracydevelopers.corla.query; import au.org.democracydevelopers.corla.model.GenerateAssertionsSummary; -import au.org.democracydevelopers.corla.model.assertion.Assertion; import org.apache.log4j.LogManager; import org.apache.log4j.Logger; import org.hibernate.Session; import us.freeandfair.corla.persistence.Persistence; import javax.persistence.TypedQuery; -import java.util.ArrayList; import java.util.List; import java.util.Optional; @@ -41,7 +39,6 @@ * belonging to a specific contest, identified by name. * Also includes a shortcut function to get the winner, which inserts UNKNOWN_WINNER if either the * record is absent, or the winner is blank. - * TODO Currently these queries have no uses outside testing - if they are not needed for the UI, * (e.g. giving feedback about assertion generation) they can be safely deleted. */ public class GenerateAssertionsSummaryQueries { diff --git a/server/eclipse-project/src/main/java/us/freeandfair/corla/report/ReportRows.java b/server/eclipse-project/src/main/java/us/freeandfair/corla/report/ReportRows.java index 253eb96a..23f1003e 100644 --- a/server/eclipse-project/src/main/java/us/freeandfair/corla/report/ReportRows.java +++ b/server/eclipse-project/src/main/java/us/freeandfair/corla/report/ReportRows.java @@ -378,12 +378,17 @@ public static List> genSumResultsReport() { row.put("Contest", ca.contestResult().getContestName()); row.put("targeted", yesNo(ca.isTargeted())); - if (ca.contestResult().getWinners() == null || ca.contestResult().getWinners().isEmpty()) { - LOGGER.info("no winner!!! " + ca); - row.put("Winner", UNKNOWN_WINNER); + if(ca instanceof IRVComparisonAudit) { + // If IRV, get the winner's name from the GenerateAssertionsSummary. + row.put("Winner", GenerateAssertionsSummaryQueries.matchingWinner(ca.getContestName())); } else { + // Must be a plurality audit. ContestResult.winner is correct. + if (ca.contestResult().getWinners() == null || ca.contestResult().getWinners().isEmpty()) { + LOGGER.info("no winner!!! " + ca); + } row.put("Winner", toString(ca.contestResult().getWinners().iterator().next())); } + // All this data makes sense for both IRV and plurality. row.put("Risk Limit met?", yesNo(riskLimitMet(ca.getRiskLimit(), riskMsmnt))); row.put("Risk measurement %", sigFig(percentage(riskMsmnt), 1).toString()); row.put("Audit Risk Limit %", sigFig(percentage(ca.getRiskLimit()),1).toString()); From 4b4eceba976abe27028f7e837e16445200d2bfd2 Mon Sep 17 00:00:00 2001 From: vteague Date: Sat, 20 Jul 2024 15:01:51 +1000 Subject: [PATCH 15/21] Basic IRV ballot interpretation for database storage. --- .../model/vote/IRVBallotInterpretation.java | 167 ++++++++++++++++-- .../corla/persistence/entity_classes | 2 + 2 files changed, 151 insertions(+), 18 deletions(-) diff --git a/server/eclipse-project/src/main/java/au/org/democracydevelopers/corla/model/vote/IRVBallotInterpretation.java b/server/eclipse-project/src/main/java/au/org/democracydevelopers/corla/model/vote/IRVBallotInterpretation.java index b0f8762e..f0f48ccf 100644 --- a/server/eclipse-project/src/main/java/au/org/democracydevelopers/corla/model/vote/IRVBallotInterpretation.java +++ b/server/eclipse-project/src/main/java/au/org/democracydevelopers/corla/model/vote/IRVBallotInterpretation.java @@ -1,25 +1,156 @@ -/* -Democracy Developers IRV extensions to colorado-rla. +package au.org.democracydevelopers.corla.model.vote; -@copyright 2024 Colorado Department of State +import org.apache.commons.lang.StringEscapeUtils; +import us.freeandfair.corla.model.CastVoteRecord; +import us.freeandfair.corla.model.Contest; +import us.freeandfair.corla.persistence.PersistentEntity; +import us.freeandfair.corla.persistence.StringListConverter; -These IRV extensions are designed to connect to a running instance of the raire -service (https://github.com/DemocracyDevelopers/raire-service), in order to -generate assertions that can be audited using colorado-rla. +import javax.persistence.*; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Stream; -The colorado-rla IRV extensions are free software: you can redistribute it and/or modify it under the terms -of the GNU Affero General Public License as published by the Free Software Foundation, either -version 3 of the License, or (at your option) any later version. +/** + * A record of the interpretation of invalid IRV ballots. Used for reporting, not for the actual + * auditing logic. Every time an invalid IRV vote is encountered, whether in the initial upload or + * during the auditing steps, a record is made of the CVR ID, the county, contest name, raw vote, + * and our interpretation of that vote as an ordered list of candidate names. + * This is output as a report called IRVBallotInterpretationReport. + */ +@Entity +@Table(name = "irv_ballot_interpretation") +public class IRVBallotInterpretation implements PersistentEntity, Serializable { -The colorado-rla IRV extensions are distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; -without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -See the GNU Affero General Public License for more details. + /** + * ID for interpretation record (for persistence). + */ + @Id + @Column(updatable = false, nullable = false) + @GeneratedValue(strategy = GenerationType.SEQUENCE) + private Long id; -You should have received a copy of the GNU Affero General Public License along with -raire-service. If not, see . -*/ + /** + * The version (for optimistic locking). + */ + @Version + private Long version; -package au.org.democracydevelopers.corla.model.vote; + /** + * The CVR, which is a different object for the uploaded and audited versions of the same vote. + * There may be multiple IRVBallotInterpretations for the same CVR, because one CVR may have + * many different IRV contests. + */ + @ManyToOne(optional = false, fetch = FetchType.LAZY) + private CastVoteRecord cvr; + + /** + * The contest to which the interpreted vote belongs. + * TODO This could be a string because we really never need to use the Contest object. + */ + @ManyToOne(optional = false, fetch = FetchType.LAZY) + private Contest contest; + + /** + * List of candidate names with ranks in parentheses representing a raw vote in an IRV contest. + * Order is not important. + */ + @Column(name = "raw_choices", columnDefinition = "character varying (1024)") + @Convert(converter = StringListConverter.class) + private List rawChoices = new ArrayList<>(); + + /** + * List of candidates names, in order of rank, representing a valid vote in an IRV contest. + */ + @Column(name = "valid_choices", columnDefinition = "character varying (1024)") + @Convert(converter = StringListConverter.class) + private List validChoices = new ArrayList<>(); + + + public static String invalidIRVTitle = "Invalid IRV choices."; + private static String countyHeader = "County"; + private static String contestHeader = "Contest"; + private static String cvrIDHeader = "CVR ID"; + private static String imprintedIDHeader = "Imprinted ID"; + private static String rawChoicesHeader = "Raw choices"; + private static String validChoicesHeader = "Interpreted as"; + public static final List csvHeaders = List.of(countyHeader, contestHeader, + cvrIDHeader, rawChoicesHeader, validChoicesHeader); + + /** + * Construct an empty IRVBallotInterpretation (for persistence). + */ + public IRVBallotInterpretation() { + } + + /** + * Create a record of an IRV vote interpretation for a given contest and a given ballot (identified by the + * CVR ID). + * + * @param theCVR Ballot identifier + * @param theContest Name of the contest whose vote is being interpreted. + * @param theRawChoices Raw choices on the ballot for the contest, as identified by an auditor. + * @param theValidChoices Valid interpretation of the vote on the ballot. + */ + public IRVBallotInterpretation(final CastVoteRecord theCVR, final Contest theContest, final List theRawChoices, + final List theValidChoices) { + cvr = theCVR; + contest = theContest; + rawChoices = theRawChoices; + validChoices = theValidChoices; + } + + /** + * Output contents as a CSV row, CSV-escaped and comma-delimited, in the same order as csvHeaders. + * @return the data as a CSV row. + */ + public String getCSVRow() { + return String.join(",", (Stream.of( + contest.county().name(), + contest.name(), + cvr.getCvrId().toString(), + cvr.imprintedID(), + String.join(",", rawChoices), + String.join(",", validChoices) + ).map(StringEscapeUtils::escapeCsv).toList())); + } + + /** + * Output contents as a String appropriate for a log message. + * @return the data with headers incorporated. + */ + public String logMessage() { + return String.join(",", (List.of( + countyHeader + " " + contest.county().name(), + contestHeader + " " + contest.name(), + cvrIDHeader + " " + cvr.getCvrId().toString(), + imprintedIDHeader + " " + cvr.imprintedID(), + rawChoicesHeader + " " + String.join(",", rawChoices), + validChoicesHeader + " " + String.join(",", validChoices) + ))) + "."; + } + /** + * {@inheritDoc} + */ + @Override + public Long id() { + return id; + } + + /** + * {@inheritDoc} + */ + @Override + public void setID(Long the_id) { + id = the_id; + } -public class IRVBallotInterpretation { -} + /** + * {@inheritDoc} + */ + @Override + public Long version() { + return version; + } +} \ No newline at end of file diff --git a/server/eclipse-project/src/main/resources/us/freeandfair/corla/persistence/entity_classes b/server/eclipse-project/src/main/resources/us/freeandfair/corla/persistence/entity_classes index d84c4842..973b93ca 100644 --- a/server/eclipse-project/src/main/resources/us/freeandfair/corla/persistence/entity_classes +++ b/server/eclipse-project/src/main/resources/us/freeandfair/corla/persistence/entity_classes @@ -24,3 +24,5 @@ au.org.democracydevelopers.corla.model.assertion.Assertion au.org.democracydevelopers.corla.model.assertion.NEBAssertion au.org.democracydevelopers.corla.model.assertion.NENAssertion au.org.democracydevelopers.corla.model.IRVComparisonAudit +au.org.democracydevelopers.corla.model.vote.IRVBallotInterpretation +au.org.democracydevelopers.corla.model.GenerateAssertionsSummary From 049dac5571e7487c75e29a1639b9c0b45cfc6f4a Mon Sep 17 00:00:00 2001 From: vteague Date: Sat, 20 Jul 2024 16:43:08 +1000 Subject: [PATCH 16/21] IRV Ballot interpretation incorporated into DominionCVRExportParser. --- .../model/vote/IRVBallotInterpretation.java | 75 ++++++++++++------- .../corla/csv/DominionCVRExportParser.java | 19 ++--- 2 files changed, 56 insertions(+), 38 deletions(-) diff --git a/server/eclipse-project/src/main/java/au/org/democracydevelopers/corla/model/vote/IRVBallotInterpretation.java b/server/eclipse-project/src/main/java/au/org/democracydevelopers/corla/model/vote/IRVBallotInterpretation.java index f0f48ccf..fb9210ea 100644 --- a/server/eclipse-project/src/main/java/au/org/democracydevelopers/corla/model/vote/IRVBallotInterpretation.java +++ b/server/eclipse-project/src/main/java/au/org/democracydevelopers/corla/model/vote/IRVBallotInterpretation.java @@ -37,37 +37,51 @@ public class IRVBallotInterpretation implements PersistentEntity, Serializable { @Version private Long version; - /** - * The CVR, which is a different object for the uploaded and audited versions of the same vote. - * There may be multiple IRVBallotInterpretations for the same CVR, because one CVR may have - * many different IRV contests. - */ - @ManyToOne(optional = false, fetch = FetchType.LAZY) - private CastVoteRecord cvr; /** * The contest to which the interpreted vote belongs. - * TODO This could be a string because we really never need to use the Contest object. */ @ManyToOne(optional = false, fetch = FetchType.LAZY) private Contest contest; + /** + * The record type, either UPLOADED or AUDITOR_ENTERED. + */ + @Column(name = "record_type", nullable = false) + @Enumerated(EnumType.STRING) + private CastVoteRecord.RecordType recordType; + + /** + * ID of the CVR being audited, and whose paper ballot is being interpreted. + * There may be multiple records with the same CVR ID, if one ballot contains multiple IRV contests. + */ + @Column(name = "cvr_id", nullable = false) + private int cvrID; + + /** + * The imprinted ID, generally tabulator_id-batch_id-record_id. + */ + @Column(name = "imprinted_id", nullable = false) + @Convert(converter = StringListConverter.class) + private String imprintedID; + /** * List of candidate names with ranks in parentheses representing a raw vote in an IRV contest. * Order is not important. */ - @Column(name = "raw_choices", columnDefinition = "character varying (1024)") + @Column(name = "raw_choices", columnDefinition = "character varying (1024)", nullable = false) @Convert(converter = StringListConverter.class) private List rawChoices = new ArrayList<>(); /** * List of candidates names, in order of rank, representing a valid vote in an IRV contest. */ - @Column(name = "valid_choices", columnDefinition = "character varying (1024)") + @Column(name = "valid_choices", columnDefinition = "character varying (1024)", nullable = false) @Convert(converter = StringListConverter.class) private List validChoices = new ArrayList<>(); + // TODO Actually these headers are all in DominionCVRExportParser. Try to put them in the same place. public static String invalidIRVTitle = "Invalid IRV choices."; private static String countyHeader = "County"; private static String contestHeader = "Contest"; @@ -85,20 +99,22 @@ public IRVBallotInterpretation() { } /** - * Create a record of an IRV vote interpretation for a given contest and a given ballot (identified by the - * CVR ID). - * - * @param theCVR Ballot identifier - * @param theContest Name of the contest whose vote is being interpreted. - * @param theRawChoices Raw choices on the ballot for the contest, as identified by an auditor. - * @param theValidChoices Valid interpretation of the vote on the ballot. + * Create a record of an IRV vote interpretation for a given contest and a given ballot + * (identified by the CVR ID). + * @param contest the Contest + * @param recordType the type, expected to be either UPLOADED, AUDITOR_ENTERED, or REAUDITED. + * @param cvrId the cvrId. + * @param imprintedId the imprinted ID, i.e. tabulator_id-batch_id-record_id. + * @param rawChoices the (invalid) raw IRV choices, e.g. [Bob(1),Alice(3),Chuan(4)]. + * @param orderedChoices the way colorado-rla interpreted the raw choices, as an order list of names. */ - public IRVBallotInterpretation(final CastVoteRecord theCVR, final Contest theContest, final List theRawChoices, - final List theValidChoices) { - cvr = theCVR; - contest = theContest; - rawChoices = theRawChoices; - validChoices = theValidChoices; + public IRVBallotInterpretation(Contest contest, CastVoteRecord.RecordType recordType, int cvrId, String imprintedId, List rawChoices, List orderedChoices) { + this.contest = contest; + this.recordType = recordType; + this.cvrID = cvrId; + this.imprintedID = imprintedId; + this.rawChoices = rawChoices; + this.validChoices = orderedChoices; } /** @@ -109,10 +125,10 @@ public String getCSVRow() { return String.join(",", (Stream.of( contest.county().name(), contest.name(), - cvr.getCvrId().toString(), - cvr.imprintedID(), + String.valueOf(cvrID), + imprintedID, String.join(",", rawChoices), - String.join(",", validChoices) + "[" + String.join(",", validChoices) + "]" ).map(StringEscapeUtils::escapeCsv).toList())); } @@ -124,12 +140,13 @@ public String logMessage() { return String.join(",", (List.of( countyHeader + " " + contest.county().name(), contestHeader + " " + contest.name(), - cvrIDHeader + " " + cvr.getCvrId().toString(), - imprintedIDHeader + " " + cvr.imprintedID(), + cvrIDHeader + " " + cvrID, + imprintedIDHeader + " " + imprintedID, rawChoicesHeader + " " + String.join(",", rawChoices), - validChoicesHeader + " " + String.join(",", validChoices) + validChoicesHeader + " [" + String.join(",", validChoices) + "]" ))) + "."; } + /** * {@inheritDoc} */ diff --git a/server/eclipse-project/src/main/java/us/freeandfair/corla/csv/DominionCVRExportParser.java b/server/eclipse-project/src/main/java/us/freeandfair/corla/csv/DominionCVRExportParser.java index bfbb2a37..a10e2a3f 100644 --- a/server/eclipse-project/src/main/java/us/freeandfair/corla/csv/DominionCVRExportParser.java +++ b/server/eclipse-project/src/main/java/us/freeandfair/corla/csv/DominionCVRExportParser.java @@ -21,6 +21,7 @@ import au.org.democracydevelopers.corla.model.vote.IRVChoices; import au.org.democracydevelopers.corla.model.vote.IRVParsingException; import au.org.democracydevelopers.corla.model.vote.IRVPreference; +import au.org.democracydevelopers.corla.model.vote.IRVBallotInterpretation; import org.apache.commons.csv.CSVFormat; import org.apache.commons.csv.CSVParser; import org.apache.commons.csv.CSVRecord; @@ -667,21 +668,21 @@ private CastVoteRecord extractCVR(final CSVRecord the_line) { if (present) { if(isIRV) { // If it is IRV, convert it into an ordered list of names (without parentheses), then - // store. If it was not valid, make a warning log message and keep going. + // store. final IRVChoices irvVotes = new IRVChoices(votes); List orderedChoices = irvVotes.getValidIntentAsOrderedList(); if(!irvVotes.isValid()) { - String msg = "Interpretation of invalid IRV choices: "; - LOGGER.warn(String.format("%s %s", prefix, msg + irvVotes + " to " + orderedChoices)); + // IRV preferences were invalid. Store a record of the raw votes for debugging/record- + // keeping purposes, but use the valid interpretation as the choices in the audit. + IRVBallotInterpretation irvInterpretation = new IRVBallotInterpretation(co, + RecordType.UPLOADED, cvr_id, imprinted_id, votes, orderedChoices); + Persistence.save(irvInterpretation); + String msg = "Interpretation of invalid IRV choices. "; + LOGGER.warn(String.format("%s %s %s.", prefix, msg, irvInterpretation.logMessage())); } contest_info.add(new CVRContestInfo(co, null, null, orderedChoices)); - - // TODO think about whether we should also store the raw vote in the database if applicable. - // See Issue https://github.com/DemocracyDevelopers/colorado-rla/issues/100 - // TODO refine this part when we know whether we should reject csvs with invalid IRV - // votes. - // See Issue https://github.com/DemocracyDevelopers/colorado-rla/issues/106 } else { + // Store plurality vote. contest_info.add(new CVRContestInfo(co, null, null, votes)); } } From d39939892c1706911e765b5122d23635849670d1 Mon Sep 17 00:00:00 2001 From: vteague Date: Sat, 20 Jul 2024 17:37:54 +1000 Subject: [PATCH 17/21] IRV ballot interpretation incorporated into reports. --- client/src/component/AuditReportForm.tsx | 3 ++- .../model/vote/IRVBallotInterpretation.java | 5 ++--- .../corla/csv/DominionCVRExportParser.java | 2 +- .../freeandfair/corla/query/ExportQueries.java | 3 ++- .../sql/ranked_ballot_interpretation.sql | 17 +++++++++++++++++ 5 files changed, 24 insertions(+), 6 deletions(-) create mode 100644 server/eclipse-project/src/main/resources/sql/ranked_ballot_interpretation.sql diff --git a/client/src/component/AuditReportForm.tsx b/client/src/component/AuditReportForm.tsx index 68418bb9..48b142f0 100644 --- a/client/src/component/AuditReportForm.tsx +++ b/client/src/component/AuditReportForm.tsx @@ -30,7 +30,8 @@ const REPORT_TYPES: ReportType[] = [ {key:'ResultReport', label:'Result Report'}, {key:'ActivityReport', label:'Activity Report'}, {key:'StateReport', label:'State Report'}, - {key:'JSON', label:'Json Reports'} + {key:'JSON', label:'Json Reports'}, + {key:'ranked_ballot_interpretation', label:'Ranked vote interpretation'} ]; diff --git a/server/eclipse-project/src/main/java/au/org/democracydevelopers/corla/model/vote/IRVBallotInterpretation.java b/server/eclipse-project/src/main/java/au/org/democracydevelopers/corla/model/vote/IRVBallotInterpretation.java index fb9210ea..39e1a067 100644 --- a/server/eclipse-project/src/main/java/au/org/democracydevelopers/corla/model/vote/IRVBallotInterpretation.java +++ b/server/eclipse-project/src/main/java/au/org/democracydevelopers/corla/model/vote/IRVBallotInterpretation.java @@ -62,7 +62,6 @@ public class IRVBallotInterpretation implements PersistentEntity, Serializable { * The imprinted ID, generally tabulator_id-batch_id-record_id. */ @Column(name = "imprinted_id", nullable = false) - @Convert(converter = StringListConverter.class) private String imprintedID; /** @@ -137,14 +136,14 @@ public String getCSVRow() { * @return the data with headers incorporated. */ public String logMessage() { - return String.join(",", (List.of( + return String.join(", ", (List.of( countyHeader + " " + contest.county().name(), contestHeader + " " + contest.name(), cvrIDHeader + " " + cvrID, imprintedIDHeader + " " + imprintedID, rawChoicesHeader + " " + String.join(",", rawChoices), validChoicesHeader + " [" + String.join(",", validChoices) + "]" - ))) + "."; + ))); } /** diff --git a/server/eclipse-project/src/main/java/us/freeandfair/corla/csv/DominionCVRExportParser.java b/server/eclipse-project/src/main/java/us/freeandfair/corla/csv/DominionCVRExportParser.java index a10e2a3f..58510420 100644 --- a/server/eclipse-project/src/main/java/us/freeandfair/corla/csv/DominionCVRExportParser.java +++ b/server/eclipse-project/src/main/java/us/freeandfair/corla/csv/DominionCVRExportParser.java @@ -677,7 +677,7 @@ private CastVoteRecord extractCVR(final CSVRecord the_line) { IRVBallotInterpretation irvInterpretation = new IRVBallotInterpretation(co, RecordType.UPLOADED, cvr_id, imprinted_id, votes, orderedChoices); Persistence.save(irvInterpretation); - String msg = "Interpretation of invalid IRV choices. "; + String msg = "Interpretation of invalid IRV choices."; LOGGER.warn(String.format("%s %s %s.", prefix, msg, irvInterpretation.logMessage())); } contest_info.add(new CVRContestInfo(co, null, null, orderedChoices)); diff --git a/server/eclipse-project/src/main/java/us/freeandfair/corla/query/ExportQueries.java b/server/eclipse-project/src/main/java/us/freeandfair/corla/query/ExportQueries.java index 4b358d96..4d2ad2d3 100644 --- a/server/eclipse-project/src/main/java/us/freeandfair/corla/query/ExportQueries.java +++ b/server/eclipse-project/src/main/java/us/freeandfair/corla/query/ExportQueries.java @@ -171,7 +171,8 @@ public static List getSqlFolderFiles() { final String folder = "sql"; final String[] fileNames = {"batch_count_comparison.sql", "contest.sql", "contest_comparison.sql", "contest_selection.sql", "contests_by_county.sql", - "tabulate.sql", "tabulate_county.sql", "upload_status.sql", "seed.sql"}; + "tabulate.sql", "tabulate_county.sql", "upload_status.sql", "seed.sql", + "ranked_ballot_interpretation.sql"}; for (final String f : fileNames) { paths.add(String.format("%s/%s", folder, f)); } diff --git a/server/eclipse-project/src/main/resources/sql/ranked_ballot_interpretation.sql b/server/eclipse-project/src/main/resources/sql/ranked_ballot_interpretation.sql new file mode 100644 index 00000000..40a86d13 --- /dev/null +++ b/server/eclipse-project/src/main/resources/sql/ranked_ballot_interpretation.sql @@ -0,0 +1,17 @@ +-- List of invalid ranked (IRV) ballots, and their valid interpretation as an order list of choices. +-- correlated with cvr_id in contest_comparison export, and with audited_cvr_count. + +SELECT + -- cou.name, + -- con.name, + irv.record_type, + irv.cvr_id, + irv.imprinted_id, + irv.raw_choices, + irv.valid_choices +FROM + irv_ballot_interpretation AS irv; +-- LEFT JOIN +-- contest AS con +-- ON irv.contest_id = con.id +-- LEFT JOIN county as cou ON con.county_d = cou.id; From d9e8b10427b9d09396b01d0719c57657329a962e Mon Sep 17 00:00:00 2001 From: vteague Date: Sat, 20 Jul 2024 17:43:05 +1000 Subject: [PATCH 18/21] IRV ballot interpretation includes contest name. --- .../resources/sql/ranked_ballot_interpretation.sql | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/server/eclipse-project/src/main/resources/sql/ranked_ballot_interpretation.sql b/server/eclipse-project/src/main/resources/sql/ranked_ballot_interpretation.sql index 40a86d13..4185430c 100644 --- a/server/eclipse-project/src/main/resources/sql/ranked_ballot_interpretation.sql +++ b/server/eclipse-project/src/main/resources/sql/ranked_ballot_interpretation.sql @@ -3,15 +3,17 @@ SELECT -- cou.name, - -- con.name, + con.name, irv.record_type, irv.cvr_id, irv.imprinted_id, irv.raw_choices, irv.valid_choices FROM - irv_ballot_interpretation AS irv; + irv_ballot_interpretation AS irv +LEFT JOIN + contest AS con + ON irv.contest_id = con.id; -- LEFT JOIN --- contest AS con --- ON irv.contest_id = con.id --- LEFT JOIN county as cou ON con.county_d = cou.id; + -- county as cou + -- ON con.county_d = cou.id; From 53020f46d4885ab21360870479945814146c2bb9 Mon Sep 17 00:00:00 2001 From: vteague Date: Sat, 20 Jul 2024 22:43:30 +1000 Subject: [PATCH 19/21] IRV ballot interpretation report for uploaded cvrs. --- .../model/vote/IRVBallotInterpretation.java | 56 +++++-------------- .../corla/csv/DominionCVRExportParser.java | 3 +- .../sql/ranked_ballot_interpretation.sql | 16 +++--- 3 files changed, 25 insertions(+), 50 deletions(-) diff --git a/server/eclipse-project/src/main/java/au/org/democracydevelopers/corla/model/vote/IRVBallotInterpretation.java b/server/eclipse-project/src/main/java/au/org/democracydevelopers/corla/model/vote/IRVBallotInterpretation.java index 39e1a067..a9c450a6 100644 --- a/server/eclipse-project/src/main/java/au/org/democracydevelopers/corla/model/vote/IRVBallotInterpretation.java +++ b/server/eclipse-project/src/main/java/au/org/democracydevelopers/corla/model/vote/IRVBallotInterpretation.java @@ -55,8 +55,8 @@ public class IRVBallotInterpretation implements PersistentEntity, Serializable { * ID of the CVR being audited, and whose paper ballot is being interpreted. * There may be multiple records with the same CVR ID, if one ballot contains multiple IRV contests. */ - @Column(name = "cvr_id", nullable = false) - private int cvrID; + @Column(name = "cvr_number", nullable = false) + private int cvrNumber; /** * The imprinted ID, generally tabulator_id-batch_id-record_id. @@ -75,21 +75,9 @@ public class IRVBallotInterpretation implements PersistentEntity, Serializable { /** * List of candidates names, in order of rank, representing a valid vote in an IRV contest. */ - @Column(name = "valid_choices", columnDefinition = "character varying (1024)", nullable = false) + @Column(name = "interpretation", columnDefinition = "character varying (1024)", nullable = false) @Convert(converter = StringListConverter.class) - private List validChoices = new ArrayList<>(); - - - // TODO Actually these headers are all in DominionCVRExportParser. Try to put them in the same place. - public static String invalidIRVTitle = "Invalid IRV choices."; - private static String countyHeader = "County"; - private static String contestHeader = "Contest"; - private static String cvrIDHeader = "CVR ID"; - private static String imprintedIDHeader = "Imprinted ID"; - private static String rawChoicesHeader = "Raw choices"; - private static String validChoicesHeader = "Interpreted as"; - public static final List csvHeaders = List.of(countyHeader, contestHeader, - cvrIDHeader, rawChoicesHeader, validChoicesHeader); + private List interpretation = new ArrayList<>(); /** * Construct an empty IRVBallotInterpretation (for persistence). @@ -102,47 +90,33 @@ public IRVBallotInterpretation() { * (identified by the CVR ID). * @param contest the Contest * @param recordType the type, expected to be either UPLOADED, AUDITOR_ENTERED, or REAUDITED. - * @param cvrId the cvrId. + * @param cvrNumber the cvr Number, which appears in the csv file (not to be confused with the cvr_id, which the + * database makes). * @param imprintedId the imprinted ID, i.e. tabulator_id-batch_id-record_id. * @param rawChoices the (invalid) raw IRV choices, e.g. [Bob(1),Alice(3),Chuan(4)]. * @param orderedChoices the way colorado-rla interpreted the raw choices, as an order list of names. */ - public IRVBallotInterpretation(Contest contest, CastVoteRecord.RecordType recordType, int cvrId, String imprintedId, List rawChoices, List orderedChoices) { + public IRVBallotInterpretation(Contest contest, CastVoteRecord.RecordType recordType, int cvrNumber, String imprintedId, List rawChoices, List orderedChoices) { this.contest = contest; this.recordType = recordType; - this.cvrID = cvrId; + this.cvrNumber = cvrNumber; this.imprintedID = imprintedId; this.rawChoices = rawChoices; - this.validChoices = orderedChoices; - } - - /** - * Output contents as a CSV row, CSV-escaped and comma-delimited, in the same order as csvHeaders. - * @return the data as a CSV row. - */ - public String getCSVRow() { - return String.join(",", (Stream.of( - contest.county().name(), - contest.name(), - String.valueOf(cvrID), - imprintedID, - String.join(",", rawChoices), - "[" + String.join(",", validChoices) + "]" - ).map(StringEscapeUtils::escapeCsv).toList())); + this.interpretation = orderedChoices; } /** * Output contents as a String appropriate for a log message. * @return the data with headers incorporated. */ - public String logMessage() { + public String logMessage(String cvrNumberHeader, String imprintedIDHeader) { return String.join(", ", (List.of( - countyHeader + " " + contest.county().name(), - contestHeader + " " + contest.name(), - cvrIDHeader + " " + cvrID, + "County " + contest.county().name(), + "Contest " + contest.name(), + cvrNumberHeader + " " + cvrNumber, imprintedIDHeader + " " + imprintedID, - rawChoicesHeader + " " + String.join(",", rawChoices), - validChoicesHeader + " [" + String.join(",", validChoices) + "]" + "Choices " + String.join(",", rawChoices), + "Interpretation [" + String.join(",", interpretation) + "]" ))); } diff --git a/server/eclipse-project/src/main/java/us/freeandfair/corla/csv/DominionCVRExportParser.java b/server/eclipse-project/src/main/java/us/freeandfair/corla/csv/DominionCVRExportParser.java index 58510420..a3d61dce 100644 --- a/server/eclipse-project/src/main/java/us/freeandfair/corla/csv/DominionCVRExportParser.java +++ b/server/eclipse-project/src/main/java/us/freeandfair/corla/csv/DominionCVRExportParser.java @@ -678,7 +678,8 @@ private CastVoteRecord extractCVR(final CSVRecord the_line) { RecordType.UPLOADED, cvr_id, imprinted_id, votes, orderedChoices); Persistence.save(irvInterpretation); String msg = "Interpretation of invalid IRV choices."; - LOGGER.warn(String.format("%s %s %s.", prefix, msg, irvInterpretation.logMessage())); + LOGGER.warn(String.format("%s %s %s.", prefix, msg, + irvInterpretation.logMessage(CVR_NUMBER_HEADER, IMPRINTED_ID_HEADER))); } contest_info.add(new CVRContestInfo(co, null, null, orderedChoices)); } else { diff --git a/server/eclipse-project/src/main/resources/sql/ranked_ballot_interpretation.sql b/server/eclipse-project/src/main/resources/sql/ranked_ballot_interpretation.sql index 4185430c..ff9df41c 100644 --- a/server/eclipse-project/src/main/resources/sql/ranked_ballot_interpretation.sql +++ b/server/eclipse-project/src/main/resources/sql/ranked_ballot_interpretation.sql @@ -2,18 +2,18 @@ -- correlated with cvr_id in contest_comparison export, and with audited_cvr_count. SELECT - -- cou.name, - con.name, + cou.name AS County, + con.name AS Contest, irv.record_type, - irv.cvr_id, + irv.cvr_number, irv.imprinted_id, irv.raw_choices, - irv.valid_choices + irv.interpretation FROM irv_ballot_interpretation AS irv LEFT JOIN contest AS con - ON irv.contest_id = con.id; --- LEFT JOIN - -- county as cou - -- ON con.county_d = cou.id; + ON irv.contest_id = con.id +LEFT JOIN + county as cou + ON con.county_id = cou.id; From b99de19f2d17c410ed3a730dec89ff665b6c2370 Mon Sep 17 00:00:00 2001 From: vteague Date: Sun, 21 Jul 2024 10:21:52 +1000 Subject: [PATCH 20/21] Test report generation for Ranked ballot interpretations. --- .../csv/DominionCVRExportParserTests.java | 5 +- ...RankedBallotInterpretationReportTests.java | 505 ++++++++++++++++++ .../src/test/resources/SQL/corla.sql | 18 + 3 files changed, 524 insertions(+), 4 deletions(-) create mode 100644 server/eclipse-project/src/test/java/au/org/democracydevelopers/corla/report/RankedBallotInterpretationReportTests.java diff --git a/server/eclipse-project/src/test/java/au/org/democracydevelopers/corla/csv/DominionCVRExportParserTests.java b/server/eclipse-project/src/test/java/au/org/democracydevelopers/corla/csv/DominionCVRExportParserTests.java index 95072453..f90b6ea5 100644 --- a/server/eclipse-project/src/test/java/au/org/democracydevelopers/corla/csv/DominionCVRExportParserTests.java +++ b/server/eclipse-project/src/test/java/au/org/democracydevelopers/corla/csv/DominionCVRExportParserTests.java @@ -206,10 +206,7 @@ public void parseGuideToRaireExample3() throws IOException { /** * Test of successful parsing of a file with valid headers but invalid IRV votes - it includes * duplicate candidates and skipped or repeated ranks. - * TODO Clarify whether we should reject or interpret invalid IRV CVR uploads. - * See Issue ... - * It's possible that this should reject, rather than interpret, these invalid IRV ballots. - * At the moment, this checks for correct metadata and correct valid interpretation of all votes. + * This checks for correct metadata and correct valid interpretation of all votes. * @throws IOException if there are file I/O issues. */ @Test diff --git a/server/eclipse-project/src/test/java/au/org/democracydevelopers/corla/report/RankedBallotInterpretationReportTests.java b/server/eclipse-project/src/test/java/au/org/democracydevelopers/corla/report/RankedBallotInterpretationReportTests.java new file mode 100644 index 00000000..b0bc7aca --- /dev/null +++ b/server/eclipse-project/src/test/java/au/org/democracydevelopers/corla/report/RankedBallotInterpretationReportTests.java @@ -0,0 +1,505 @@ +/* +Democracy Developers IRV extensions to colorado-rla. + +@copyright 2024 Colorado Department of State + +These IRV extensions are designed to connect to a running instance of the raire +service (https://github.com/DemocracyDevelopers/raire-service), in order to +generate assertions that can be audited using colorado-rla. + +The colorado-rla IRV extensions are free software: you can redistribute it and/or modify it under the terms +of the GNU Affero General Public License as published by the Free Software Foundation, either +version 3 of the License, or (at your option) any later version. + +The colorado-rla IRV extensions are distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the GNU Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License along with +raire-service. If not, see . +*/ + +package au.org.democracydevelopers.corla.report; + +import au.org.democracydevelopers.corla.model.ContestType; +import au.org.democracydevelopers.corla.util.TestClassWithDatabase; +import au.org.democracydevelopers.corla.util.testUtils; + +import org.apache.log4j.LogManager; +import org.apache.log4j.Logger; +import org.testcontainers.containers.PostgreSQLContainer; +import org.testcontainers.ext.ScriptUtils; +import org.testcontainers.jdbc.JdbcDatabaseDelegate; +import org.testcontainers.shaded.org.apache.commons.lang3.StringUtils; +import us.freeandfair.corla.controller.AuditReport; +import us.freeandfair.corla.csv.DominionCVRExportParser; +import us.freeandfair.corla.model.*; +import us.freeandfair.corla.persistence.Persistence; + +import java.io.*; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.*; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import org.testng.annotations.*; +import us.freeandfair.corla.query.ExportQueries; + +import javax.transaction.Transactional; + +import static au.org.democracydevelopers.corla.util.testUtils.*; +import static org.testng.Assert.*; + +import static us.freeandfair.corla.query.CastVoteRecordQueries.getMatching; +import static us.freeandfair.corla.query.ContestQueries.forCounties; +import static us.freeandfair.corla.query.CountyQueries.fromString; + +/** + * Test that a correct ranked vote interpretation report is produced, for a variety of IRV-related + * parsing examples, including: + * - some basic small test cases that can be verified by eye, + * - a constructed test with invalid IRV ballots to check they are accepted and properly + * interpreted. + * - a real example from Boulder '23, with a mix of IRV and plurality contests + * - some examples with invalid headers, to ensure they are rejected (though most of these are + * tested in IRVHeadersParserTests.java and are not repeated here), + * plus a bad plurality "Vote For= " with a non-integer. + * - an examples to test the broader class of Write In strings. + * Test csvs are the same as in DominionCVRExportParserTests. + */ +public class RankedBallotInterpretationReportTests extends TestClassWithDatabase { + + /** + * Class-wide logger + */ + private static final Logger LOGGER = LogManager.getLogger( + au.org.democracydevelopers.corla.report.RankedBallotInterpretationReportTests.class); + + /** + * Container for the mock-up database. + */ + static PostgreSQLContainer postgres = createTestContainer(); + + /** + * Error message to match. + */ + private static final String badNumsRegexp = "Unexpected or uninterpretable numbers in header:.*"; + + /** + * Blank properties for submitting to the DominionCVRExportParser instance. + */ + private static final Properties blank = new Properties(); + + @BeforeClass + public static void beforeAll() { + postgres.start(); + Persistence.setProperties(createHibernateProperties(postgres)); + + var containerDelegate = new JdbcDatabaseDelegate(postgres, ""); + ScriptUtils.runInitScript(containerDelegate, "SQL/co-counties.sql"); + } + + @AfterClass + public static void afterAll() { + postgres.stop(); + } + + /** + * Simple test of successful parsing of a tiny IRV test example, ThreeCandidatesTenVotes.csv. + * Tests that all the metadata and all the votes are correct. + * @throws IOException never. + */ + @Test + @Transactional + public void parseThreeCandidatesTenVotesSucceeds() throws IOException { + testUtils.log(LOGGER, "parseThreeCandidatesTenVotesSucceeds"); + + // Parse the file. + Path path = Paths.get(TINY_CSV_PATH + "ThreeCandidatesTenVotes.csv"); + Reader reader = Files.newBufferedReader(path); + DominionCVRExportParser parser = new DominionCVRExportParser(reader, fromString("Saguache"), blank, true); + assertTrue(parser.parse().success); + + // Make the ranked_ballot_interpretation report. + final Map files = ExportQueries.sqlFiles(); + final ByteArrayOutputStream os = new ByteArrayOutputStream(); + String q = files.get("ranked_ballot_interpretation"); + ExportQueries.csvOut(q, os); + + // There should be no data, only headers, because all the IRV votes are valid. + assertEquals(os.toString(), "county,contest,record_type,cvr_number,imprinted_id,raw_choices,interpretation\n"); + } + + /** + * Test of successful parsing of a file with valid headers but invalid IRV votes - it includes + * duplicate candidates and skipped or repeated ranks. + * This checks for correct storage of valid interpretation of all votes. + * @throws IOException if there are file I/O issues. + */ + @Test + @Transactional + public void parseThreeCandidatesTenInvalidVotesSucceeds() throws IOException { + testUtils.log(LOGGER, "parseThreeCandidatesTenInvalidVotesSucceeds"); + Path path = Paths.get(TINY_CSV_PATH + "ThreeCandidatesTenInvalidVotes.csv"); + Reader reader = Files.newBufferedReader(path); + + DominionCVRExportParser parser = new DominionCVRExportParser(reader, fromString("Gilpin"), blank, true); + assertTrue(parser.parse().success); + + + // Make the ranked_ballot_interpretation report. + final Map files = ExportQueries.sqlFiles(); + final ByteArrayOutputStream os = new ByteArrayOutputStream(); + String q = files.get("ranked_ballot_interpretation"); + ExportQueries.csvOut(q, os); + + // There should be headers and 10 records matching the valid interpretations of all those invalid votes. + String cvr = os.toString(); + assertTrue(StringUtils.contains(cvr, "county,contest,record_type,cvr_number,imprinted_id,raw_choices,interpretation\n")); + + /* TODO: check for the presence of all these as rows. + + // Raw: "Alice(1),Alice(2),Bob(2),Chuan(3) + assertEquals(List.of("Alice", "Bob", "Chuan"), cvrs.get(0).choices()); + // Raw: "Alice(1),Bob(2),Alice(3),Chuan(3) + assertEquals(List.of("Alice", "Bob", "Chuan"), cvrs.get(1).choices()); + // Raw: "Alice(1),Alice(2),Bob(2),Alice(3),Chuan(3) + assertEquals(List.of("Alice", "Bob", "Chuan"), cvrs.get(2).choices()); + // Raw: "Alice(1),Alice(2),Bob(2),Bob(3),Chuan(3) + assertEquals(List.of("Alice", "Bob", "Chuan"), cvrs.get(3).choices()); + // Raw: "Alice(1),Bob(2),Chuan(2),Bob(3) + assertEquals(List.of("Alice"), cvrs.get(4).choices()); + // Raw: "Alice(1),Alice(2),Bob(2),Chuan(2),Bob(3) + assertEquals(List.of("Alice"), cvrs.get(5).choices()); + // Raw: "Alice(1),Chuan(3)" + assertEquals(List.of("Alice"), cvrs.get(6).choices()); + // Raw: "Alice(1),Alice(2), Bob(3)" + assertEquals(List.of("Alice"), cvrs.get(7).choices()); + // Raw: "Alice(1),Chuan(1),Alice(2),Bob(3) + assertTrue(cvrs.get(8).choices().isEmpty()); + // Raw: "Bob(1),Chuan(1),Alice(2),Bob(3) + assertTrue(cvrs.get(9).choices().isEmpty()); + + */ + } + + /** + * Test of successful parsing of data from Boulder '23, which contains a mix of IRV and plurality + * contests. Check all their metadata. + * Check correct parsing of the first vote. + */ + @Test + @Transactional + public void parseBoulder23Succeeds() throws IOException { + testUtils.log(LOGGER, "parseBoulder23Succeeds"); + Path path = Paths.get(BOULDER_CSV_PATH + "Boulder-2023-Coordinated-CVR-Redactions-removed.csv"); + Reader reader = Files.newBufferedReader(path); + + DominionCVRExportParser parser = new DominionCVRExportParser(reader, fromString("Boulder"), + blank, true); + assertTrue(parser.parse().success); + + // There should be 38 contests. Check their metadata. + List contests = forCounties(Set.of(fromString("Boulder"))); + assertEquals(38, contests.size()); + + Contest boulderMayoral = contests.get(0); + assertEquals(boulderMayoral.name(), "City of Boulder Mayoral Candidates"); + assertEquals((int) boulderMayoral.votesAllowed(), 4); + assertEquals((int) boulderMayoral.winnersAllowed(), 1); + + Contest boulderCouncil = contests.get(1); + assertEquals(boulderCouncil.name(), "City of Boulder Council Candidates"); + assertEquals((int) boulderCouncil.votesAllowed(), 4); + assertEquals((int) boulderCouncil.winnersAllowed(), 4); + + + Contest lafayetteCouncil = contests.get(2); + assertEquals(lafayetteCouncil.name(), "City of Lafayette City Council Candidates"); + assertEquals((int) lafayetteCouncil.votesAllowed(), 4); + assertEquals((int) lafayetteCouncil.winnersAllowed(), 4); + + Contest longmontMayor = contests.get(3); + assertEquals(longmontMayor.name(),"City of Longmont - Mayor"); + assertEquals((int) longmontMayor.votesAllowed(), 1); + assertEquals((int) longmontMayor.winnersAllowed(), 1); + + Contest longmontCouncillorAtLarge = contests.get(4); + assertEquals(longmontCouncillorAtLarge.name(), + "City of Longmont - City Council Member At-Large"); + assertEquals((int) longmontCouncillorAtLarge.votesAllowed(), 1); + assertEquals((int) longmontCouncillorAtLarge.winnersAllowed(), 1); + + Contest longmontCouncillorWard1 = contests.get(5); + assertEquals(longmontCouncillorWard1.name(),"City of Longmont - Council Member Ward 1"); + assertEquals((int) longmontCouncillorWard1.votesAllowed(), 1); + assertEquals((int) longmontCouncillorWard1.winnersAllowed(), 1); + + Contest longmontCouncillorWard3 = contests.get(6); + assertEquals(longmontCouncillorWard3.name(),"City of Longmont - Council Member Ward 3"); + assertEquals((int) longmontCouncillorWard3.votesAllowed(), 1); + assertEquals((int) longmontCouncillorWard3.winnersAllowed(), 1); + + Contest louisvilleMayor = contests.get(7); + assertEquals(louisvilleMayor.name(),"City of Louisville Mayor At-Large (4 Year Term)"); + assertEquals((int) louisvilleMayor.votesAllowed(), 1); + assertEquals((int) louisvilleMayor.winnersAllowed(), 1); + + Contest louisvilleCouncilWard1 = contests.get(8); + assertEquals(louisvilleCouncilWard1.name(), + "City of Louisville City Council Ward 1 (4-year term)"); + assertEquals((int) louisvilleCouncilWard1.votesAllowed(), 1); + assertEquals((int) louisvilleCouncilWard1.winnersAllowed(), 1); + + Contest louisvilleCouncilWard2 = contests.get(9); + assertEquals(louisvilleCouncilWard2.name(), + "City of Louisville City Council Ward 2 (4-year term)"); + assertEquals((int) louisvilleCouncilWard2.votesAllowed(), 1); + assertEquals((int) louisvilleCouncilWard2.winnersAllowed(), 1); + + Contest louisvilleCouncilWard3 = contests.get(10); + assertEquals( louisvilleCouncilWard3.name(), + "City of Louisville City Council Ward 3"); + assertEquals((int) louisvilleCouncilWard3.votesAllowed(), 2); + assertEquals((int) louisvilleCouncilWard3.winnersAllowed(), 2); + + Contest boulderValleySchoolDirectorA = contests.get(11); + assertEquals( boulderValleySchoolDirectorA.name(), + "Boulder Valley School District RE-2 Director District A (4 Years)"); + assertEquals((int) boulderValleySchoolDirectorA.votesAllowed(), 1); + assertEquals((int) boulderValleySchoolDirectorA.winnersAllowed(), 1); + + Contest boulderValleySchoolDirectorC = contests.get(12); + assertEquals(boulderValleySchoolDirectorC.name(), + "Boulder Valley School District RE-2 Director District C (4 Years)"); + assertEquals((int) boulderValleySchoolDirectorC.votesAllowed(), 1); + assertEquals((int) boulderValleySchoolDirectorC.winnersAllowed(), 1); + + Contest boulderValleySchoolDirectorD = contests.get(13); + assertEquals(boulderValleySchoolDirectorD.name(), + "Boulder Valley School District RE-2 Director District D (4 Years)"); + assertEquals((int) boulderValleySchoolDirectorD.votesAllowed(), 1); + assertEquals((int) boulderValleySchoolDirectorD.winnersAllowed(), 1); + + Contest boulderValleySchoolDirectorG = contests.get(14); + assertEquals(boulderValleySchoolDirectorG.name(), + "Boulder Valley School District RE-2 Director District G (4 Years)"); + assertEquals((int) boulderValleySchoolDirectorG.votesAllowed(), 1); + assertEquals((int) boulderValleySchoolDirectorG.winnersAllowed(), 1); + + Contest estesParkSchoolDirectorAtLarge = contests.get(15); + assertEquals(estesParkSchoolDirectorAtLarge.name(), + "Estes Park School District R-3 School Board Director At Large (4 Year)"); + assertEquals((int) estesParkSchoolDirectorAtLarge.votesAllowed(), 2); + assertEquals((int) estesParkSchoolDirectorAtLarge.winnersAllowed(), 2); + + Contest thompsonSchoolDirectorA = contests.get(16); + assertEquals(thompsonSchoolDirectorA.name(), + "Thompson R2-J School District Board of Education Director District A (4 Year Term)"); + assertEquals((int) thompsonSchoolDirectorA.votesAllowed(), 1); + assertEquals((int) thompsonSchoolDirectorA.winnersAllowed(), 1); + + Contest thompsonSchoolDirectorC = contests.get(17); + assertEquals(thompsonSchoolDirectorC.name(), + "Thompson R2-J School District Board of Education Director District C (4 Year Term)"); + assertEquals((int) thompsonSchoolDirectorC.votesAllowed(), 1); + assertEquals((int) thompsonSchoolDirectorC.winnersAllowed(), 1); + + Contest thompsonSchoolDirectorD = contests.get(18); + assertEquals( thompsonSchoolDirectorD.name(), + "Thompson R2-J School District Board of Education Director District D (4 Year Term)"); + assertEquals((int) thompsonSchoolDirectorD.votesAllowed(), 1); + assertEquals((int) thompsonSchoolDirectorD.winnersAllowed(), 1); + + Contest thompsonSchoolDirectorG = contests.get(19); + assertEquals(thompsonSchoolDirectorG.name(), + "Thompson R2-J School District Board of Education Director District G (4 Year Term)"); + assertEquals((int) thompsonSchoolDirectorG.votesAllowed(), 1); + assertEquals((int) thompsonSchoolDirectorG.winnersAllowed(), 1); + + Contest cityOfLongmontJudge = contests.get(20); + assertEquals(cityOfLongmontJudge.name(), "City of Longmont Municipal Court Judge - Frick"); + assertEquals((int) cityOfLongmontJudge.votesAllowed(), 1); + assertEquals((int) cityOfLongmontJudge.winnersAllowed(), 1); + + Contest propHH = contests.get(21); + assertEquals(propHH.name(),"Proposition HH (Statutory)"); + assertEquals((int) propHH.votesAllowed(), 1); + assertEquals((int) propHH.winnersAllowed(), 1); + + Contest propII = contests.get(22); + assertEquals(propII.name(),"Proposition II (Statutory)"); + assertEquals((int) propII.votesAllowed(), 1); + assertEquals((int) propII.winnersAllowed(), 1); + + Contest boulder1A = contests.get(23); + assertEquals(boulder1A.name(),"Boulder County Ballot Issue 1A"); + assertEquals((int) boulder1A.votesAllowed(), 1); + assertEquals((int) boulder1A.winnersAllowed(), 1); + + Contest boulder1B = contests.get(24); + assertEquals(boulder1B.name(),"Boulder County Ballot Issue 1B"); + assertEquals((int) boulder1B.votesAllowed(), 1); + assertEquals((int) boulder1B.winnersAllowed(), 1); + + Contest boulder2A = contests.get(25); + assertEquals(boulder2A.name(), "City of Boulder Ballot Issue 2A"); + assertEquals((int) boulder2A.votesAllowed(), 1); + assertEquals((int) boulder2A.winnersAllowed(), 1); + + Contest boulder2B = contests.get(26); + assertEquals(boulder2B.name(), "City of Boulder Ballot Question 2B"); + assertEquals((int) boulder2B.votesAllowed(), 1); + assertEquals((int) boulder2B.winnersAllowed(), 1); + + Contest boulder302 = contests.get(27); + assertEquals(boulder302.name(), "City of Boulder Ballot Question 302"); + assertEquals((int) boulder302.votesAllowed(), 1); + assertEquals((int) boulder302.winnersAllowed(), 1); + + Contest erie3A = contests.get(28); + assertEquals(erie3A.name(), "Town of Erie Ballot Question 3A"); + assertEquals((int) erie3A.votesAllowed(), 1); + assertEquals((int) erie3A.winnersAllowed(), 1); + + Contest erie3B = contests.get(29); + assertEquals(erie3B.name(), "Town of Erie Ballot Question 3B"); + assertEquals((int) erie3B.votesAllowed(), 1); + assertEquals((int) erie3B.winnersAllowed(), 1); + + Contest longmont3C = contests.get(30); + assertEquals(longmont3C.name(), "City of Longmont Ballot Issue 3C"); + assertEquals((int) longmont3C.votesAllowed(), 1); + assertEquals((int) longmont3C.winnersAllowed(), 1); + + Contest longmont3D = contests.get(31); + assertEquals(longmont3D.name(), "City of Longmont Ballot Issue 3D"); + assertEquals((int) longmont3D.votesAllowed(), 1); + assertEquals((int) longmont3D.winnersAllowed(), 1); + + Contest longmont3E = contests.get(32); + assertEquals(longmont3E.name(), "City of Longmont Ballot Issue 3E"); + assertEquals((int) longmont3E.votesAllowed(), 1); + assertEquals((int) longmont3E.winnersAllowed(), 1); + + Contest louisville2C = contests.get(33); + assertEquals(louisville2C.name(), "City of Louisville Ballot Issue 2C"); + assertEquals((int) louisville2C.votesAllowed(), 1); + assertEquals((int) louisville2C.winnersAllowed(), 1); + + Contest superior301 = contests.get(34); + assertEquals(superior301.name(), "Town of Superior Ballot Question 301"); + assertEquals((int) superior301.votesAllowed(), 1); + assertEquals((int) superior301.winnersAllowed(), 1); + + Contest superiorHomeRule = contests.get(35); + assertEquals(superiorHomeRule.name(), "Town of Superior - Home Rule Charter Commission"); + assertEquals((int) superiorHomeRule.votesAllowed(), 9); + assertEquals((int) superiorHomeRule.winnersAllowed(), 9); + + Contest nederlandEcoPass6A = contests.get(36); + assertEquals(nederlandEcoPass6A.name(), + "Nederland Eco Pass Public Improvement District Ballot Issue 6A"); + assertEquals((int) nederlandEcoPass6A.votesAllowed(), 1); + assertEquals((int) nederlandEcoPass6A.winnersAllowed(), 1); + + Contest northMetroFire7A = contests.get(37); + assertEquals(northMetroFire7A.name(), "North Metro Fire Rescue District Ballot Issue 7A"); + assertEquals((int) northMetroFire7A.votesAllowed(), 1); + assertEquals((int) northMetroFire7A.winnersAllowed(), 1); + + // Check that the number of cvrs is correct. We have redacted CVRs, so the total is slightly + // less than the actual official count of 119757. + List cvrs = getMatching(fromString("Boulder").id(), + CastVoteRecord.RecordType.UPLOADED).toList(); + assertEquals(cvrs.size(), 118669); + CastVoteRecord cvr1 = cvrs.get(0); + + // Check that the first cvr was correctly parsed. + // We expect the first cvr to have voted on 13 contests (all Boulder), as follows: + assertEquals(Objects.requireNonNull(cvr1.contestInfoForContest(boulderMayoral)).choices(), + List.of("Aaron Brockett", "Nicole Speer", "Bob Yates", "Paul Tweedlie")); + assertNotNull(cvr1.contestInfoForContest(boulderCouncil)); + assertEquals(Objects.requireNonNull(cvr1.contestInfoForContest(boulderCouncil)).choices(), + List.of("Silas Atkins", "Ryan Schuchard", "Tara Winer", "Taishya Adams")); + assertEquals(Objects.requireNonNull(cvr1.contestInfoForContest(boulderValleySchoolDirectorA)).choices(), + List.of("Jason Unger")); + assertEquals(Objects.requireNonNull(cvr1.contestInfoForContest(boulderValleySchoolDirectorC)).choices(), + List.of("Alex Medler")); + assertEquals(Objects.requireNonNull(cvr1.contestInfoForContest(boulderValleySchoolDirectorD)).choices(), + List.of("Andrew Brandt")); + assertEquals(Objects.requireNonNull(cvr1.contestInfoForContest(boulderValleySchoolDirectorG)).choices(), + List.of("Jorge Chávez")); + assertEquals(Objects.requireNonNull(cvr1.contestInfoForContest(propHH)).choices(), + List.of("Yes/For")); + assertEquals(Objects.requireNonNull(cvr1.contestInfoForContest(propII)).choices(), + List.of("Yes/For")); + assertEquals(Objects.requireNonNull(cvr1.contestInfoForContest(boulder1A)).choices(), + List.of("Yes/For")); + assertEquals(Objects.requireNonNull(cvr1.contestInfoForContest(boulder1B)).choices(), + List.of("Yes/For")); + assertEquals(Objects.requireNonNull(cvr1.contestInfoForContest(boulder2A)).choices(), + List.of("Yes/For")); + assertEquals(Objects.requireNonNull(cvr1.contestInfoForContest(boulder2B)).choices(), + List.of("Yes/For")); + assertEquals(Objects.requireNonNull(cvr1.contestInfoForContest(boulder302)).choices(), + List.of("No/Against")); + } + + /** + * A plurality cvr with a "Vote for=2.0". This is an error. + * Note different behaviour from earlier parsing, which simply assumed 1. + * @throws RuntimeException always, + */ + @Test(expectedExceptions = RuntimeException.class, + expectedExceptionsMessageRegExp = badNumsRegexp) + @Transactional + public void parseBadVoteForPluralityError() throws IOException { + testUtils.log(LOGGER, "parseBadVoteForPluralityError"); + Path path = Paths.get(BAD_CSV_PATH + "badVoteForPlurality.csv"); + Reader reader = Files.newBufferedReader(path); + // County sedgwick = fromString("Sedgwick"); + + DominionCVRExportParser parser = new DominionCVRExportParser(reader, fromString("Sedgwick"), blank, true); + assertTrue(parser.parse().success); + } + + /** + * Test for correct interpretation of a variety of different write-in strings, including + * "WRITEIN", "WRITE-in" etc. + * The regexp should match any whitespace, followed by any capitalization of "write", followed + * by -, _, space or no space, followed by any capitalization of "in", followed by any whitespace. + */ + @Test + @Transactional + public void parseWriteIns() throws IOException { + testUtils.log(LOGGER, "parseWriteIns"); + Path path = Paths.get(WRITEIN_CSV_PATH + "WriteIns.csv"); + Reader reader = Files.newBufferedReader(path); + + DominionCVRExportParser parser = new DominionCVRExportParser(reader, fromString("Las Animas"), blank, true); + assertTrue(parser.parse().success); + + // There should be seven contests, one for each example way of writing write-in: + // "Write-in", "Write-In", "Write in", "Write_in", "writeIn", "WRITEIN", "WRITE_IN" + List contests = forCounties(Set.of(fromString("Las Animas"))); + assertEquals(7, contests.size()); + + for(int i=0 ; i < contests.size() ; i++) { + Contest contest = contests.get(i); + List choices = contest.choices(); + + // Check basic data + assertEquals(contest.name(), String.format("Contest %d", i+1)); + assertEquals(contest.description(), ContestType.PLURALITY.toString()); + + assertEquals(choices.size(), 3); + assertFalse(choices.get(0).qualifiedWriteIn()); + assertTrue(choices.get(1).fictitious()); + assertTrue(contest.choices().get(2).qualifiedWriteIn()); + } + } +} + diff --git a/server/eclipse-project/src/test/resources/SQL/corla.sql b/server/eclipse-project/src/test/resources/SQL/corla.sql index f1f1e0ed..c513322a 100644 --- a/server/eclipse-project/src/test/resources/SQL/corla.sql +++ b/server/eclipse-project/src/test/resources/SQL/corla.sql @@ -479,6 +479,24 @@ create table generate_assertions_summary winner varchar(255) not null ); +create table irv_ballot_interpretation +( + id bigint not null + primary key, + cvr_number integer not null, + imprinted_id varchar(255) not null, + interpretation varchar(1024) not null, + raw_choices varchar(1024) not null, + record_type varchar(255) not null, + version bigint, + contest_id bigint not null + constraint fkinw3u6cigskdttcwqosnsl98e + references contest +); + +alter table irv_ballot_interpretation + owner to corlaadmin; + create table contest_to_audit ( dashboard_id bigint not null From ac7802e05da923ca0578ef8cb2e39a2bd78937c7 Mon Sep 17 00:00:00 2001 From: vteague Date: Sun, 21 Jul 2024 21:47:33 +1000 Subject: [PATCH 21/21] Added tests for reports of IRV Ballot interpretations. --- .../sql/ranked_ballot_interpretation.sql | 5 +- .../csv/DominionCVRExportParserTests.java | 32 +- ...RankedBallotInterpretationReportTests.java | 401 ++---------------- 3 files changed, 62 insertions(+), 376 deletions(-) diff --git a/server/eclipse-project/src/main/resources/sql/ranked_ballot_interpretation.sql b/server/eclipse-project/src/main/resources/sql/ranked_ballot_interpretation.sql index ff9df41c..c54d7282 100644 --- a/server/eclipse-project/src/main/resources/sql/ranked_ballot_interpretation.sql +++ b/server/eclipse-project/src/main/resources/sql/ranked_ballot_interpretation.sql @@ -7,8 +7,9 @@ SELECT irv.record_type, irv.cvr_number, irv.imprinted_id, - irv.raw_choices, - irv.interpretation + -- prettier printing by removing the enclosing []. + SUBSTRING(irv.raw_choices, 2, LENGTH(irv.raw_choices) - 2) AS raw_vote, + SUBSTRING(irv.interpretation, 2, LENGTH(irv.interpretation) - 2) AS valid_interpretation FROM irv_ballot_interpretation AS irv LEFT JOIN diff --git a/server/eclipse-project/src/test/java/au/org/democracydevelopers/corla/csv/DominionCVRExportParserTests.java b/server/eclipse-project/src/test/java/au/org/democracydevelopers/corla/csv/DominionCVRExportParserTests.java index f90b6ea5..6170f994 100644 --- a/server/eclipse-project/src/test/java/au/org/democracydevelopers/corla/csv/DominionCVRExportParserTests.java +++ b/server/eclipse-project/src/test/java/au/org/democracydevelopers/corla/csv/DominionCVRExportParserTests.java @@ -30,22 +30,22 @@ import org.testcontainers.containers.PostgreSQLContainer; import org.testcontainers.ext.ScriptUtils; import org.testcontainers.jdbc.JdbcDatabaseDelegate; +import org.testcontainers.shaded.org.apache.commons.lang3.StringUtils; import us.freeandfair.corla.csv.DominionCVRExportParser; import us.freeandfair.corla.model.*; import us.freeandfair.corla.persistence.Persistence; +import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.Reader; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; -import java.util.List; -import java.util.Objects; -import java.util.Properties; -import java.util.Set; +import java.util.*; import java.util.stream.Collectors; import org.testng.annotations.*; +import us.freeandfair.corla.query.ExportQueries; import javax.transaction.Transactional; @@ -65,6 +65,10 @@ * - some examples with invalid headers, to ensure they are rejected (though most of these are * tested in IRVHeadersParserTests.java and are not repeated here), * plus a bad plurality "Vote For= " with a non-integer. + * This example includes a test that IRV ballot interpretation report contains the right valid + * interpretation, for a small selection of known invalid votes. (This really belongs logically + * in RankedBallotInterpretationReportTests, but is included here so the Boulder data only has to + * be loaded once.) * - an examples to test the broader class of Write In strings. */ public class DominionCVRExportParserTests extends TestClassWithDatabase { @@ -265,6 +269,7 @@ public void parseThreeCandidatesTenInvalidVotesSucceeds() throws IOException { * Test of successful parsing of data from Boulder '23, which contains a mix of IRV and plurality * contests. Check all their metadata. * Check correct parsing of the first vote. + * Check proper reporting of valid interpretation of some invalid IRV votes. */ @Test @Transactional @@ -522,6 +527,25 @@ public void parseBoulder23Succeeds() throws IOException { List.of("Yes/For")); assertEquals(Objects.requireNonNull(cvr1.contestInfoForContest(boulder302)).choices(), List.of("No/Against")); + + // Make the ranked_ballot_interpretation report. + final Map files = ExportQueries.sqlFiles(); + final ByteArrayOutputStream os = new ByteArrayOutputStream(); + String q = files.get("ranked_ballot_interpretation"); + ExportQueries.csvOut(q, os); + + // Test for the proper reporting of some known invalid votes. + String boulderMayoralName = "City of Boulder Mayoral Candidates"; + String cvr = os.toString(); + assertTrue(StringUtils.contains(cvr, "county,contest,record_type,cvr_number,imprinted_id,raw_vote,valid_interpretation\n")); + assertTrue(StringUtils.contains(cvr, + "Boulder,"+boulderMayoralName+",UPLOADED,140,108-1-32,\"\"\"Bob Yates(1)\"\",\"\"Bob Yates(2)\"\",\"\"Bob Yates(3)\"\",\"\"Bob Yates(4)\"\"\",\"\"\"Bob Yates\"\"")); + assertTrue(StringUtils.contains(cvr, + "Boulder,"+boulderMayoralName+",UPLOADED,112680,108-100-48,\"\"\"Bob Yates(1)\"\",\"\"Nicole Speer(2)\"\",\"\"Aaron Brockett(3)\"\",\"\"Bob Yates(3)\"\",\"\"Paul Tweedlie(4)\"\"\",\"\"\"Bob Yates\"\",\"\"Nicole Speer\"\",\"\"Aaron Brockett\"\",\"\"Paul Tweedlie\"\"")); + assertTrue(StringUtils.contains(cvr, + "Boulder,"+boulderMayoralName+",UPLOADED,107599,101-178-114,\"\"\"Bob Yates(1)\"\",\"\"Paul Tweedlie(1)\"\",\"\"Aaron Brockett(2)\"\",\"\"Paul Tweedlie(2)\"\",\"\"Paul Tweedlie(3)\"\",\"\"Paul Tweedlie(4)\"\"\",")); + assertTrue(StringUtils.contains(cvr, + "Boulder,"+boulderMayoralName+",UPLOADED,118738,101-190-124,\"\"\"Aaron Brockett(1)\"\",\"\"Bob Yates(1)\"\"\",")); } /** diff --git a/server/eclipse-project/src/test/java/au/org/democracydevelopers/corla/report/RankedBallotInterpretationReportTests.java b/server/eclipse-project/src/test/java/au/org/democracydevelopers/corla/report/RankedBallotInterpretationReportTests.java index b0bc7aca..e5ea6ade 100644 --- a/server/eclipse-project/src/test/java/au/org/democracydevelopers/corla/report/RankedBallotInterpretationReportTests.java +++ b/server/eclipse-project/src/test/java/au/org/democracydevelopers/corla/report/RankedBallotInterpretationReportTests.java @@ -21,7 +21,6 @@ package au.org.democracydevelopers.corla.report; -import au.org.democracydevelopers.corla.model.ContestType; import au.org.democracydevelopers.corla.util.TestClassWithDatabase; import au.org.democracydevelopers.corla.util.testUtils; @@ -31,9 +30,7 @@ import org.testcontainers.ext.ScriptUtils; import org.testcontainers.jdbc.JdbcDatabaseDelegate; import org.testcontainers.shaded.org.apache.commons.lang3.StringUtils; -import us.freeandfair.corla.controller.AuditReport; import us.freeandfair.corla.csv.DominionCVRExportParser; -import us.freeandfair.corla.model.*; import us.freeandfair.corla.persistence.Persistence; import java.io.*; @@ -41,8 +38,6 @@ import java.nio.file.Path; import java.nio.file.Paths; import java.util.*; -import java.util.stream.Collectors; -import java.util.stream.Stream; import org.testng.annotations.*; import us.freeandfair.corla.query.ExportQueries; @@ -52,22 +47,16 @@ import static au.org.democracydevelopers.corla.util.testUtils.*; import static org.testng.Assert.*; -import static us.freeandfair.corla.query.CastVoteRecordQueries.getMatching; -import static us.freeandfair.corla.query.ContestQueries.forCounties; import static us.freeandfair.corla.query.CountyQueries.fromString; /** * Test that a correct ranked vote interpretation report is produced, for a variety of IRV-related * parsing examples, including: - * - some basic small test cases that can be verified by eye, - * - a constructed test with invalid IRV ballots to check they are accepted and properly + * ThreeCandidatesTenVotes - a constructed test file will all-valid IRV votes. + * ThreeCandidatesTenInvalidVotes - a constructed test with invalid IRV ballots to check they are accepted and properly * interpreted. - * - a real example from Boulder '23, with a mix of IRV and plurality contests - * - some examples with invalid headers, to ensure they are rejected (though most of these are - * tested in IRVHeadersParserTests.java and are not repeated here), - * plus a bad plurality "Vote For= " with a non-integer. - * - an examples to test the broader class of Write In strings. - * Test csvs are the same as in DominionCVRExportParserTests. + * An equivalent test using real data from Boulder '23 is in DominionCVRExportParserTests. + * Test csvs are a subset of those in DominionCVRExportParserTests. */ public class RankedBallotInterpretationReportTests extends TestClassWithDatabase { @@ -82,11 +71,6 @@ public class RankedBallotInterpretationReportTests extends TestClassWithDatabase */ static PostgreSQLContainer postgres = createTestContainer(); - /** - * Error message to match. - */ - private static final String badNumsRegexp = "Unexpected or uninterpretable numbers in header:.*"; - /** * Blank properties for submitting to the DominionCVRExportParser instance. */ @@ -113,11 +97,11 @@ public static void afterAll() { */ @Test @Transactional - public void parseThreeCandidatesTenVotesSucceeds() throws IOException { - testUtils.log(LOGGER, "parseThreeCandidatesTenVotesSucceeds"); + public void parseGuideToRaireExample3Succeeds() throws IOException { + testUtils.log(LOGGER, "parseGuideToRaireExample3Succeeds"); // Parse the file. - Path path = Paths.get(TINY_CSV_PATH + "ThreeCandidatesTenVotes.csv"); + Path path = Paths.get(TINY_CSV_PATH + "GuideToRAIREExample3.csv"); Reader reader = Files.newBufferedReader(path); DominionCVRExportParser parser = new DominionCVRExportParser(reader, fromString("Saguache"), blank, true); assertTrue(parser.parse().success); @@ -129,13 +113,13 @@ public void parseThreeCandidatesTenVotesSucceeds() throws IOException { ExportQueries.csvOut(q, os); // There should be no data, only headers, because all the IRV votes are valid. - assertEquals(os.toString(), "county,contest,record_type,cvr_number,imprinted_id,raw_choices,interpretation\n"); + assertEquals(os.toString(), "county,contest,record_type,cvr_number,imprinted_id,raw_vote,valid_interpretation\n"); } /** * Test of successful parsing of a file with valid headers but invalid IRV votes - it includes * duplicate candidates and skipped or repeated ranks. - * This checks for correct storage of valid interpretation of all votes. + * This checks for correct reports of valid interpretation of all invalid votes. * @throws IOException if there are file I/O issues. */ @Test @@ -148,7 +132,6 @@ public void parseThreeCandidatesTenInvalidVotesSucceeds() throws IOException { DominionCVRExportParser parser = new DominionCVRExportParser(reader, fromString("Gilpin"), blank, true); assertTrue(parser.parse().success); - // Make the ranked_ballot_interpretation report. final Map files = ExportQueries.sqlFiles(); final ByteArrayOutputStream os = new ByteArrayOutputStream(); @@ -157,349 +140,27 @@ public void parseThreeCandidatesTenInvalidVotesSucceeds() throws IOException { // There should be headers and 10 records matching the valid interpretations of all those invalid votes. String cvr = os.toString(); - assertTrue(StringUtils.contains(cvr, "county,contest,record_type,cvr_number,imprinted_id,raw_choices,interpretation\n")); - - /* TODO: check for the presence of all these as rows. - - // Raw: "Alice(1),Alice(2),Bob(2),Chuan(3) - assertEquals(List.of("Alice", "Bob", "Chuan"), cvrs.get(0).choices()); - // Raw: "Alice(1),Bob(2),Alice(3),Chuan(3) - assertEquals(List.of("Alice", "Bob", "Chuan"), cvrs.get(1).choices()); - // Raw: "Alice(1),Alice(2),Bob(2),Alice(3),Chuan(3) - assertEquals(List.of("Alice", "Bob", "Chuan"), cvrs.get(2).choices()); - // Raw: "Alice(1),Alice(2),Bob(2),Bob(3),Chuan(3) - assertEquals(List.of("Alice", "Bob", "Chuan"), cvrs.get(3).choices()); - // Raw: "Alice(1),Bob(2),Chuan(2),Bob(3) - assertEquals(List.of("Alice"), cvrs.get(4).choices()); - // Raw: "Alice(1),Alice(2),Bob(2),Chuan(2),Bob(3) - assertEquals(List.of("Alice"), cvrs.get(5).choices()); - // Raw: "Alice(1),Chuan(3)" - assertEquals(List.of("Alice"), cvrs.get(6).choices()); - // Raw: "Alice(1),Alice(2), Bob(3)" - assertEquals(List.of("Alice"), cvrs.get(7).choices()); - // Raw: "Alice(1),Chuan(1),Alice(2),Bob(3) - assertTrue(cvrs.get(8).choices().isEmpty()); - // Raw: "Bob(1),Chuan(1),Alice(2),Bob(3) - assertTrue(cvrs.get(9).choices().isEmpty()); - - */ - } - - /** - * Test of successful parsing of data from Boulder '23, which contains a mix of IRV and plurality - * contests. Check all their metadata. - * Check correct parsing of the first vote. - */ - @Test - @Transactional - public void parseBoulder23Succeeds() throws IOException { - testUtils.log(LOGGER, "parseBoulder23Succeeds"); - Path path = Paths.get(BOULDER_CSV_PATH + "Boulder-2023-Coordinated-CVR-Redactions-removed.csv"); - Reader reader = Files.newBufferedReader(path); - - DominionCVRExportParser parser = new DominionCVRExportParser(reader, fromString("Boulder"), - blank, true); - assertTrue(parser.parse().success); - - // There should be 38 contests. Check their metadata. - List contests = forCounties(Set.of(fromString("Boulder"))); - assertEquals(38, contests.size()); - - Contest boulderMayoral = contests.get(0); - assertEquals(boulderMayoral.name(), "City of Boulder Mayoral Candidates"); - assertEquals((int) boulderMayoral.votesAllowed(), 4); - assertEquals((int) boulderMayoral.winnersAllowed(), 1); - - Contest boulderCouncil = contests.get(1); - assertEquals(boulderCouncil.name(), "City of Boulder Council Candidates"); - assertEquals((int) boulderCouncil.votesAllowed(), 4); - assertEquals((int) boulderCouncil.winnersAllowed(), 4); - - - Contest lafayetteCouncil = contests.get(2); - assertEquals(lafayetteCouncil.name(), "City of Lafayette City Council Candidates"); - assertEquals((int) lafayetteCouncil.votesAllowed(), 4); - assertEquals((int) lafayetteCouncil.winnersAllowed(), 4); - - Contest longmontMayor = contests.get(3); - assertEquals(longmontMayor.name(),"City of Longmont - Mayor"); - assertEquals((int) longmontMayor.votesAllowed(), 1); - assertEquals((int) longmontMayor.winnersAllowed(), 1); - - Contest longmontCouncillorAtLarge = contests.get(4); - assertEquals(longmontCouncillorAtLarge.name(), - "City of Longmont - City Council Member At-Large"); - assertEquals((int) longmontCouncillorAtLarge.votesAllowed(), 1); - assertEquals((int) longmontCouncillorAtLarge.winnersAllowed(), 1); - - Contest longmontCouncillorWard1 = contests.get(5); - assertEquals(longmontCouncillorWard1.name(),"City of Longmont - Council Member Ward 1"); - assertEquals((int) longmontCouncillorWard1.votesAllowed(), 1); - assertEquals((int) longmontCouncillorWard1.winnersAllowed(), 1); - - Contest longmontCouncillorWard3 = contests.get(6); - assertEquals(longmontCouncillorWard3.name(),"City of Longmont - Council Member Ward 3"); - assertEquals((int) longmontCouncillorWard3.votesAllowed(), 1); - assertEquals((int) longmontCouncillorWard3.winnersAllowed(), 1); - - Contest louisvilleMayor = contests.get(7); - assertEquals(louisvilleMayor.name(),"City of Louisville Mayor At-Large (4 Year Term)"); - assertEquals((int) louisvilleMayor.votesAllowed(), 1); - assertEquals((int) louisvilleMayor.winnersAllowed(), 1); - - Contest louisvilleCouncilWard1 = contests.get(8); - assertEquals(louisvilleCouncilWard1.name(), - "City of Louisville City Council Ward 1 (4-year term)"); - assertEquals((int) louisvilleCouncilWard1.votesAllowed(), 1); - assertEquals((int) louisvilleCouncilWard1.winnersAllowed(), 1); - - Contest louisvilleCouncilWard2 = contests.get(9); - assertEquals(louisvilleCouncilWard2.name(), - "City of Louisville City Council Ward 2 (4-year term)"); - assertEquals((int) louisvilleCouncilWard2.votesAllowed(), 1); - assertEquals((int) louisvilleCouncilWard2.winnersAllowed(), 1); - - Contest louisvilleCouncilWard3 = contests.get(10); - assertEquals( louisvilleCouncilWard3.name(), - "City of Louisville City Council Ward 3"); - assertEquals((int) louisvilleCouncilWard3.votesAllowed(), 2); - assertEquals((int) louisvilleCouncilWard3.winnersAllowed(), 2); - - Contest boulderValleySchoolDirectorA = contests.get(11); - assertEquals( boulderValleySchoolDirectorA.name(), - "Boulder Valley School District RE-2 Director District A (4 Years)"); - assertEquals((int) boulderValleySchoolDirectorA.votesAllowed(), 1); - assertEquals((int) boulderValleySchoolDirectorA.winnersAllowed(), 1); - - Contest boulderValleySchoolDirectorC = contests.get(12); - assertEquals(boulderValleySchoolDirectorC.name(), - "Boulder Valley School District RE-2 Director District C (4 Years)"); - assertEquals((int) boulderValleySchoolDirectorC.votesAllowed(), 1); - assertEquals((int) boulderValleySchoolDirectorC.winnersAllowed(), 1); - - Contest boulderValleySchoolDirectorD = contests.get(13); - assertEquals(boulderValleySchoolDirectorD.name(), - "Boulder Valley School District RE-2 Director District D (4 Years)"); - assertEquals((int) boulderValleySchoolDirectorD.votesAllowed(), 1); - assertEquals((int) boulderValleySchoolDirectorD.winnersAllowed(), 1); - - Contest boulderValleySchoolDirectorG = contests.get(14); - assertEquals(boulderValleySchoolDirectorG.name(), - "Boulder Valley School District RE-2 Director District G (4 Years)"); - assertEquals((int) boulderValleySchoolDirectorG.votesAllowed(), 1); - assertEquals((int) boulderValleySchoolDirectorG.winnersAllowed(), 1); - - Contest estesParkSchoolDirectorAtLarge = contests.get(15); - assertEquals(estesParkSchoolDirectorAtLarge.name(), - "Estes Park School District R-3 School Board Director At Large (4 Year)"); - assertEquals((int) estesParkSchoolDirectorAtLarge.votesAllowed(), 2); - assertEquals((int) estesParkSchoolDirectorAtLarge.winnersAllowed(), 2); - - Contest thompsonSchoolDirectorA = contests.get(16); - assertEquals(thompsonSchoolDirectorA.name(), - "Thompson R2-J School District Board of Education Director District A (4 Year Term)"); - assertEquals((int) thompsonSchoolDirectorA.votesAllowed(), 1); - assertEquals((int) thompsonSchoolDirectorA.winnersAllowed(), 1); - - Contest thompsonSchoolDirectorC = contests.get(17); - assertEquals(thompsonSchoolDirectorC.name(), - "Thompson R2-J School District Board of Education Director District C (4 Year Term)"); - assertEquals((int) thompsonSchoolDirectorC.votesAllowed(), 1); - assertEquals((int) thompsonSchoolDirectorC.winnersAllowed(), 1); - - Contest thompsonSchoolDirectorD = contests.get(18); - assertEquals( thompsonSchoolDirectorD.name(), - "Thompson R2-J School District Board of Education Director District D (4 Year Term)"); - assertEquals((int) thompsonSchoolDirectorD.votesAllowed(), 1); - assertEquals((int) thompsonSchoolDirectorD.winnersAllowed(), 1); - - Contest thompsonSchoolDirectorG = contests.get(19); - assertEquals(thompsonSchoolDirectorG.name(), - "Thompson R2-J School District Board of Education Director District G (4 Year Term)"); - assertEquals((int) thompsonSchoolDirectorG.votesAllowed(), 1); - assertEquals((int) thompsonSchoolDirectorG.winnersAllowed(), 1); - - Contest cityOfLongmontJudge = contests.get(20); - assertEquals(cityOfLongmontJudge.name(), "City of Longmont Municipal Court Judge - Frick"); - assertEquals((int) cityOfLongmontJudge.votesAllowed(), 1); - assertEquals((int) cityOfLongmontJudge.winnersAllowed(), 1); - - Contest propHH = contests.get(21); - assertEquals(propHH.name(),"Proposition HH (Statutory)"); - assertEquals((int) propHH.votesAllowed(), 1); - assertEquals((int) propHH.winnersAllowed(), 1); - - Contest propII = contests.get(22); - assertEquals(propII.name(),"Proposition II (Statutory)"); - assertEquals((int) propII.votesAllowed(), 1); - assertEquals((int) propII.winnersAllowed(), 1); - - Contest boulder1A = contests.get(23); - assertEquals(boulder1A.name(),"Boulder County Ballot Issue 1A"); - assertEquals((int) boulder1A.votesAllowed(), 1); - assertEquals((int) boulder1A.winnersAllowed(), 1); - - Contest boulder1B = contests.get(24); - assertEquals(boulder1B.name(),"Boulder County Ballot Issue 1B"); - assertEquals((int) boulder1B.votesAllowed(), 1); - assertEquals((int) boulder1B.winnersAllowed(), 1); - - Contest boulder2A = contests.get(25); - assertEquals(boulder2A.name(), "City of Boulder Ballot Issue 2A"); - assertEquals((int) boulder2A.votesAllowed(), 1); - assertEquals((int) boulder2A.winnersAllowed(), 1); - - Contest boulder2B = contests.get(26); - assertEquals(boulder2B.name(), "City of Boulder Ballot Question 2B"); - assertEquals((int) boulder2B.votesAllowed(), 1); - assertEquals((int) boulder2B.winnersAllowed(), 1); - - Contest boulder302 = contests.get(27); - assertEquals(boulder302.name(), "City of Boulder Ballot Question 302"); - assertEquals((int) boulder302.votesAllowed(), 1); - assertEquals((int) boulder302.winnersAllowed(), 1); - - Contest erie3A = contests.get(28); - assertEquals(erie3A.name(), "Town of Erie Ballot Question 3A"); - assertEquals((int) erie3A.votesAllowed(), 1); - assertEquals((int) erie3A.winnersAllowed(), 1); - - Contest erie3B = contests.get(29); - assertEquals(erie3B.name(), "Town of Erie Ballot Question 3B"); - assertEquals((int) erie3B.votesAllowed(), 1); - assertEquals((int) erie3B.winnersAllowed(), 1); - - Contest longmont3C = contests.get(30); - assertEquals(longmont3C.name(), "City of Longmont Ballot Issue 3C"); - assertEquals((int) longmont3C.votesAllowed(), 1); - assertEquals((int) longmont3C.winnersAllowed(), 1); - - Contest longmont3D = contests.get(31); - assertEquals(longmont3D.name(), "City of Longmont Ballot Issue 3D"); - assertEquals((int) longmont3D.votesAllowed(), 1); - assertEquals((int) longmont3D.winnersAllowed(), 1); - - Contest longmont3E = contests.get(32); - assertEquals(longmont3E.name(), "City of Longmont Ballot Issue 3E"); - assertEquals((int) longmont3E.votesAllowed(), 1); - assertEquals((int) longmont3E.winnersAllowed(), 1); - - Contest louisville2C = contests.get(33); - assertEquals(louisville2C.name(), "City of Louisville Ballot Issue 2C"); - assertEquals((int) louisville2C.votesAllowed(), 1); - assertEquals((int) louisville2C.winnersAllowed(), 1); - - Contest superior301 = contests.get(34); - assertEquals(superior301.name(), "Town of Superior Ballot Question 301"); - assertEquals((int) superior301.votesAllowed(), 1); - assertEquals((int) superior301.winnersAllowed(), 1); - - Contest superiorHomeRule = contests.get(35); - assertEquals(superiorHomeRule.name(), "Town of Superior - Home Rule Charter Commission"); - assertEquals((int) superiorHomeRule.votesAllowed(), 9); - assertEquals((int) superiorHomeRule.winnersAllowed(), 9); - - Contest nederlandEcoPass6A = contests.get(36); - assertEquals(nederlandEcoPass6A.name(), - "Nederland Eco Pass Public Improvement District Ballot Issue 6A"); - assertEquals((int) nederlandEcoPass6A.votesAllowed(), 1); - assertEquals((int) nederlandEcoPass6A.winnersAllowed(), 1); - - Contest northMetroFire7A = contests.get(37); - assertEquals(northMetroFire7A.name(), "North Metro Fire Rescue District Ballot Issue 7A"); - assertEquals((int) northMetroFire7A.votesAllowed(), 1); - assertEquals((int) northMetroFire7A.winnersAllowed(), 1); - - // Check that the number of cvrs is correct. We have redacted CVRs, so the total is slightly - // less than the actual official count of 119757. - List cvrs = getMatching(fromString("Boulder").id(), - CastVoteRecord.RecordType.UPLOADED).toList(); - assertEquals(cvrs.size(), 118669); - CastVoteRecord cvr1 = cvrs.get(0); - - // Check that the first cvr was correctly parsed. - // We expect the first cvr to have voted on 13 contests (all Boulder), as follows: - assertEquals(Objects.requireNonNull(cvr1.contestInfoForContest(boulderMayoral)).choices(), - List.of("Aaron Brockett", "Nicole Speer", "Bob Yates", "Paul Tweedlie")); - assertNotNull(cvr1.contestInfoForContest(boulderCouncil)); - assertEquals(Objects.requireNonNull(cvr1.contestInfoForContest(boulderCouncil)).choices(), - List.of("Silas Atkins", "Ryan Schuchard", "Tara Winer", "Taishya Adams")); - assertEquals(Objects.requireNonNull(cvr1.contestInfoForContest(boulderValleySchoolDirectorA)).choices(), - List.of("Jason Unger")); - assertEquals(Objects.requireNonNull(cvr1.contestInfoForContest(boulderValleySchoolDirectorC)).choices(), - List.of("Alex Medler")); - assertEquals(Objects.requireNonNull(cvr1.contestInfoForContest(boulderValleySchoolDirectorD)).choices(), - List.of("Andrew Brandt")); - assertEquals(Objects.requireNonNull(cvr1.contestInfoForContest(boulderValleySchoolDirectorG)).choices(), - List.of("Jorge Chávez")); - assertEquals(Objects.requireNonNull(cvr1.contestInfoForContest(propHH)).choices(), - List.of("Yes/For")); - assertEquals(Objects.requireNonNull(cvr1.contestInfoForContest(propII)).choices(), - List.of("Yes/For")); - assertEquals(Objects.requireNonNull(cvr1.contestInfoForContest(boulder1A)).choices(), - List.of("Yes/For")); - assertEquals(Objects.requireNonNull(cvr1.contestInfoForContest(boulder1B)).choices(), - List.of("Yes/For")); - assertEquals(Objects.requireNonNull(cvr1.contestInfoForContest(boulder2A)).choices(), - List.of("Yes/For")); - assertEquals(Objects.requireNonNull(cvr1.contestInfoForContest(boulder2B)).choices(), - List.of("Yes/For")); - assertEquals(Objects.requireNonNull(cvr1.contestInfoForContest(boulder302)).choices(), - List.of("No/Against")); - } - - /** - * A plurality cvr with a "Vote for=2.0". This is an error. - * Note different behaviour from earlier parsing, which simply assumed 1. - * @throws RuntimeException always, - */ - @Test(expectedExceptions = RuntimeException.class, - expectedExceptionsMessageRegExp = badNumsRegexp) - @Transactional - public void parseBadVoteForPluralityError() throws IOException { - testUtils.log(LOGGER, "parseBadVoteForPluralityError"); - Path path = Paths.get(BAD_CSV_PATH + "badVoteForPlurality.csv"); - Reader reader = Files.newBufferedReader(path); - // County sedgwick = fromString("Sedgwick"); - - DominionCVRExportParser parser = new DominionCVRExportParser(reader, fromString("Sedgwick"), blank, true); - assertTrue(parser.parse().success); - } - - /** - * Test for correct interpretation of a variety of different write-in strings, including - * "WRITEIN", "WRITE-in" etc. - * The regexp should match any whitespace, followed by any capitalization of "write", followed - * by -, _, space or no space, followed by any capitalization of "in", followed by any whitespace. - */ - @Test - @Transactional - public void parseWriteIns() throws IOException { - testUtils.log(LOGGER, "parseWriteIns"); - Path path = Paths.get(WRITEIN_CSV_PATH + "WriteIns.csv"); - Reader reader = Files.newBufferedReader(path); - - DominionCVRExportParser parser = new DominionCVRExportParser(reader, fromString("Las Animas"), blank, true); - assertTrue(parser.parse().success); - - // There should be seven contests, one for each example way of writing write-in: - // "Write-in", "Write-In", "Write in", "Write_in", "writeIn", "WRITEIN", "WRITE_IN" - List contests = forCounties(Set.of(fromString("Las Animas"))); - assertEquals(7, contests.size()); - - for(int i=0 ; i < contests.size() ; i++) { - Contest contest = contests.get(i); - List choices = contest.choices(); - - // Check basic data - assertEquals(contest.name(), String.format("Contest %d", i+1)); - assertEquals(contest.description(), ContestType.PLURALITY.toString()); - - assertEquals(choices.size(), 3); - assertFalse(choices.get(0).qualifiedWriteIn()); - assertTrue(choices.get(1).fictitious()); - assertTrue(contest.choices().get(2).qualifiedWriteIn()); - } + assertTrue(StringUtils.contains(cvr, "county,contest,record_type,cvr_number,imprinted_id,raw_vote,valid_interpretation\n")); + + assertTrue(StringUtils.contains(cvr, + "Gilpin,TinyInvalidExample1,UPLOADED,1,1-1-1,\"\"\"Alice(1)\"\",\"\"Alice(2)\"\",\"\"Bob(2)\"\",\"\"Chuan(3)\"\"\",\"\"\"Alice\"\",\"\"Bob\"\",\"\"Chuan\"\"")); + assertTrue(StringUtils.contains(cvr, + "Gilpin,TinyInvalidExample1,UPLOADED,2,1-1-2,\"\"\"Alice(1)\"\",\"\"Bob(2)\"\",\"\"Alice(3)\"\",\"\"Chuan(3)\"\"\",\"\"\"Alice\"\",\"\"Bob\"\",\"\"Chuan\"\"")); + assertTrue(StringUtils.contains(cvr, + "Gilpin,TinyInvalidExample1,UPLOADED,3,1-1-3,\"\"\"Alice(1)\"\",\"\"Alice(2)\"\",\"\"Bob(2)\"\",\"\"Alice(3)\"\",\"\"Chuan(3)\"\"\",\"\"\"Alice\"\",\"\"Bob\"\",\"\"Chuan\"\"")); + assertTrue(StringUtils.contains(cvr, + "Gilpin,TinyInvalidExample1,UPLOADED,4,1-1-4,\"\"\"Alice(1)\"\",\"\"Alice(2)\"\",\"\"Bob(2)\"\",\"\"Bob(3)\"\",\"\"Chuan(3)\"\"\",\"\"\"Alice\"\",\"\"Bob\"\",\"\"Chuan\"\"")); + assertTrue(StringUtils.contains(cvr, + "Gilpin,TinyInvalidExample1,UPLOADED,5,1-1-5,\"\"\"Alice(1)\"\",\"\"Bob(2)\"\",\"\"Chuan(2)\"\",\"\"Bob(3)\"\"\",\"\"\"Alice\"\"")); + assertTrue(StringUtils.contains(cvr, + "Gilpin,TinyInvalidExample1,UPLOADED,6,1-1-6,\"\"\"Alice(1)\"\",\"\"Alice(2)\"\",\"\"Bob(2)\"\",\"\"Chuan(2)\"\",\"\"Bob(3)\"\"\",\"\"\"Alice\"\"")); + assertTrue(StringUtils.contains(cvr, + "Gilpin,TinyInvalidExample1,UPLOADED,7,1-1-7,\"\"\"Alice(1)\"\",\"\"Chuan(3)\"\"\",\"\"\"Alice\"\"")); + assertTrue(StringUtils.contains(cvr, + "Gilpin,TinyInvalidExample1,UPLOADED,8,1-1-8,\"\"\"Alice(1)\"\",\"\"Alice(2)\"\",\"\"Bob(3)\"\"\",\"\"\"Alice\"\"")); + assertTrue(StringUtils.contains(cvr, + "Gilpin,TinyInvalidExample1,UPLOADED,9,1-1-9,\"\"\"Alice(1)\"\",\"\"Chuan(1)\"\",\"\"Alice(2)\"\",\"\"Bob(3)\"\"\",")); + assertTrue(StringUtils.contains(cvr, + "Gilpin,TinyInvalidExample1,UPLOADED,10,1-1-10,\"\"\"Bob(1)\"\",\"\"Chuan(1)\"\",\"\"Alice(2)\"\",\"\"Bob(3)\"\"\",")); } } -