From 8e3da5ef5b0ace9a30734ad2ae7fa270c72592f9 Mon Sep 17 00:00:00 2001 From: Armin Samii Date: Tue, 8 Oct 2024 18:33:41 -0400 Subject: [PATCH 01/17] refactor how filenames are chosen --- .../brightspots/rcv/AuditableFile.java | 5 + .../brightspots/rcv/ResultsWriter.java | 272 ++++++++++-------- .../brightspots/rcv/TabulatorTests.java | 101 ++++--- 3 files changed, 220 insertions(+), 158 deletions(-) diff --git a/src/main/java/network/brightspots/rcv/AuditableFile.java b/src/main/java/network/brightspots/rcv/AuditableFile.java index 1a56d1cc0..3464f3431 100644 --- a/src/main/java/network/brightspots/rcv/AuditableFile.java +++ b/src/main/java/network/brightspots/rcv/AuditableFile.java @@ -19,12 +19,17 @@ import java.io.File; import java.io.IOException; import java.nio.file.Files; +import java.nio.file.Path; final class AuditableFile extends File { public AuditableFile(String pathname) { super(pathname); } + public AuditableFile(Path pathname) { + super(pathname.toAbsolutePath().toString()); + } + public void finalizeAndHash() { String hash = Utils.bytesToHex(FileUtils.getHashBytes(this, "SHA-512")); diff --git a/src/main/java/network/brightspots/rcv/ResultsWriter.java b/src/main/java/network/brightspots/rcv/ResultsWriter.java index f138184a6..dfcabc37f 100644 --- a/src/main/java/network/brightspots/rcv/ResultsWriter.java +++ b/src/main/java/network/brightspots/rcv/ResultsWriter.java @@ -34,13 +34,15 @@ import java.math.BigDecimal; import java.math.MathContext; import java.nio.file.Files; -import java.nio.file.Paths; +import java.nio.file.Path; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Collections; import java.util.Date; +import java.util.Dictionary; import java.util.HashMap; import java.util.HashSet; +import java.util.Hashtable; import java.util.LinkedList; import java.util.List; import java.util.Map; @@ -87,33 +89,116 @@ class ResultsWriter { StatusForRound.EXHAUSTED_CHOICE, StatusForRound.INVALIDATED_BY_REPEATED_RANKING); + public enum ResultType { + SUMMARY_REPORT("summary"/*"summary_report"*/, "csv"), + DETAILED_REPORT("extended_summary"/*"detailed_report"*/, "csv"), + JSON("summary", "json"), + CDF("cvr_cdf", "json"), + RCTAB_CVR("rctab_cvr", "csv"); - // visible for testing - @SuppressWarnings("WeakerAccess") - static String sequentialSuffixForOutputPath(String sequentialTabulationId) { - return sequentialTabulationId != null ? "_" + sequentialTabulationId : ""; + private final String basename; + private final String extension; + + ResultType(String basename, String extension) { + this.basename = basename; + this.extension = extension; + } + + public String getBasename() { + return basename; + } + + public String getExtension() { + return extension; + } } - // visible for testing - @SuppressWarnings("WeakerAccess") - static String getOutputFilePath( - String outputDirectory, - String outputType, - String timestampString, - String sequentialTabulationId) { - outputType = sanitizeStringForOutput(outputType); - String fileName = - String.format( - "%s_%s%s", - timestampString, outputType, sequentialSuffixForOutputPath(sequentialTabulationId)); - return Paths.get(outputDirectory, fileName).toAbsolutePath().toString(); + public static class ResultFile { + // Since sanitizing Slice IDs can cause filename collisions, ensure each non-sanitized + // Slice ID is given a unique sanitized name. + private static final Dictionary sliceIdToUniqueSanitizedId = new Hashtable<>(); + // This is a set of the values in sanitizerCollisionResolution to ensure there are no collisions + // in the resulting sanitized names. + private static final HashSet uniqueSanitizedIds = new HashSet<>(); + private final ResultType resultType; + private final boolean isSlice; + private final TabulateBySlice slice; + private final String sliceId; + + ResultFile(ResultType resultType) { + this.resultType = resultType; + this.isSlice = false; + slice = null; + sliceId = null; + } + + ResultFile(ResultType resultType, TabulateBySlice slice, String sliceId) { + this.resultType = resultType; + this.isSlice = true; + this.slice = slice; + this.sliceId = sliceId; + } + + // getPath helper without the modifier argument + public Path getPath(String directory, String prefix, Integer sequentialId) { + return getPath(directory, prefix, null, sequentialId); + } + + // The filename is an underscore-separated string containing all components needed + // to create a unique output file. The modifier is likely only used in tests, where + // it is set to "expected" to distinguish expected output files from actual output files. + public Path getPath(String directory, String prefix, String modifier, Integer sequentialId) { + List parts = new ArrayList<>(); + parts.add(prefix); + if (sequentialId != null) { + parts.add(sequentialId.toString()); + } + if (modifier != null) { + parts.add(modifier); + } + if (isSlice) { + assert slice != null; + parts.add(sanitizeSliceWithoutCollisions(sliceId)); + parts.add(slice.toLowerString()); + } + parts.add(resultType.getBasename()); + + String filenameWithoutExt = String.join("_", parts); + return Path.of(directory, "%s.%s".formatted(filenameWithoutExt, resultType.getExtension())); + } + + private String sanitizeSliceWithoutCollisions(String sliceId) { + String previousSanitizedSliceId = sliceIdToUniqueSanitizedId.get(sliceId); + String sanitizedSliceId; + + if (previousSanitizedSliceId != null) { + sanitizedSliceId = previousSanitizedSliceId; + } else { + sanitizedSliceId = sanitizeStringForOutput(sliceId); + + // In most cases, sanitizedSliceId will be unique and we can use it as-is. + // Here, we handle the case where it is not unique. + int increment = 1; + while (uniqueSanitizedIds.contains(sanitizedSliceId)) { + sanitizedSliceId = String.format("%s_%d", sanitizeStringForOutput(sliceId), increment); + increment++; + } + + uniqueSanitizedIds.add(sanitizedSliceId); + sliceIdToUniqueSanitizedId.put(sliceId, sanitizedSliceId); + } + + return sanitizedSliceId; + } + } static String sanitizeStringForOutput(String s) { return s == null ? "" : s.replaceAll("[^a-zA-Z0-9_\\-.]", "_"); } - private static void generateJsonFile(String path, Map json) throws IOException { + private static void generateJsonFile(AuditableFile outFile, Map json) + throws IOException { ObjectMapper mapper = new ObjectMapper(); // for improved legibility we sort alphabetically on keys mapper.configure(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS, true); @@ -121,7 +206,6 @@ private static void generateJsonFile(String path, Map json) thro module.addSerializer(BigDecimal.class, new ToStringSerializer()); mapper.registerModule(module); ObjectWriter jsonWriter = mapper.writer(new DefaultPrettyPrinter()); - AuditableFile outFile = new AuditableFile(path); try { jsonWriter.writeValue(outFile, json); @@ -129,7 +213,7 @@ private static void generateJsonFile(String path, Map json) thro } catch (IOException exception) { Logger.severe( "Error writing to JSON file: %s\n%s\nCheck the file path and permissions!", - path, exception); + outFile.getAbsolutePath(), exception); throw exception; } Logger.info("JSON file generated successfully."); @@ -192,32 +276,6 @@ private static List>> getCandidatesWithRanksList return sortedCandidatesWithRanks; } - // return a unique, valid string for this slice's output spreadsheet filename - private static String getFileStringForSlice( - ContestConfig.TabulateBySlice slice, String sliceId, Set filenames) { - String sanitized = "%s_%s".formatted(sanitizeStringForOutput(sliceId), slice.toLowerString()); - String filename = sanitized; - // appendNumber is used to find a unique filename (in practice this really shouldn't be - // necessary because different slice IDs shouldn't have the same sanitized name, but we're - // doing it here to be safe) - int appendNumber = 2; - while (filenames.contains(filename)) { - filename = sanitized + "_" + appendNumber++; - } - filenames.add(filename); - return filename; - } - - private String getOutputFilePathFromInstance(String outputType) { - String tabulationSequenceId = null; - if (config.isMultiSeatSequentialWinnerTakesAllEnabled()) { - int sequence = config.getSequentialWinners().size() + 1; - tabulationSequenceId = Integer.toString(sequence); - } - return getOutputFilePath( - config.getOutputDirectory(), outputType, timestampString, tabulationSequenceId); - } - ResultsWriter setRoundToResidualSurplus(Map roundToResidualSurplus) { this.roundToResidualSurplus = roundToResidualSurplus; return this; @@ -274,38 +332,25 @@ void generateBySliceSummaryFiles( List candidateOrder) throws IOException { for (ContestConfig.TabulateBySlice slice : config.enabledSlices()) { - Set filenames = new HashSet<>(); for (var entry : roundTalliesBySlice.get(slice).entrySet()) { String sliceId = entry.getKey(); RoundTallies roundTallies = entry.getValue(); TallyTransfers tallyTransfers = tallyTransfersBySlice.get(slice, sliceId); - String sliceFileString = getFileStringForSlice(slice, sliceId, filenames); - String outputPathCsv = getOutputFilePathFromInstance( - String.format("%s_extended_summary", sliceFileString)); - String outputPathJson = getOutputFilePathFromInstance( - String.format("%s_summary", sliceFileString)); - generateSummaryExtendedCsv(roundTallies, candidateOrder, slice, sliceId, outputPathCsv); - generateSummaryJson(roundTallies, tallyTransfers, slice, sliceId, outputPathJson); + ResultFile resultFileCsv = new ResultFile(ResultType.DETAILED_REPORT, slice, sliceId); + ResultFile resultFileJson = new ResultFile(ResultType.JSON, slice, sliceId); + generateSummaryCsv(roundTallies, candidateOrder, resultFileCsv); + generateSummaryJson(roundTallies, tallyTransfers, resultFileJson); } } } - private void generateSummaryExtendedCsv( - RoundTallies roundTallies, - List candidateOrder, - TabulateBySlice slice, - String sliceId, - String outputPath) throws IOException { - generateSummaryCsvHelper(roundTallies, candidateOrder, slice, sliceId, outputPath, true); - } - - private void generateSummaryCsv( - RoundTallies roundTallies, - List candidateOrder, - TabulateBySlice slice, - String sliceId, - String outputPath) throws IOException { - generateSummaryCsvHelper(roundTallies, candidateOrder, slice, sliceId, outputPath, false); + private AuditableFile createAuditableFile(ResultFile resultFile) { + Integer sequentialId = null; + if (config.isMultiSeatSequentialWinnerTakesAllEnabled()) { + sequentialId = config.getSequentialWinners().size() + 1; + } + return new AuditableFile(resultFile.getPath( + config.getOutputDirectory(), timestampString, sequentialId)); } // create a summary spreadsheet .csv file @@ -315,13 +360,15 @@ private void generateSummaryCsv( // param: sliceId indicates the specific slice ID we're reporting results for (null means all) // param: outputPath is the path to the output file, minus its extension // param: extended include additional details in the output file? - private void generateSummaryCsvHelper( + private void generateSummaryCsv( RoundTallies roundTallies, List candidateOrder, - TabulateBySlice slice, - String sliceId, - String outputPath, - boolean extended) throws IOException { + ResultFile resultFile) throws IOException { + if (resultFile.resultType != ResultType.SUMMARY_REPORT + && resultFile.resultType != ResultType.DETAILED_REPORT) { + throw new IllegalArgumentException("ResultFile provided non-CSV type " + + resultFile.resultType); + } // Check that all candidates are included in the candidate order Set expectedCandidates = roundTallies.get(1).getCandidates(); Set providedCandidates = new HashSet<>(candidateOrder); @@ -332,7 +379,7 @@ private void generateSummaryCsvHelper( + "\nProvided: " + providedCandidates); } - AuditableFile csvFile = new AuditableFile(outputPath + ".csv"); + AuditableFile csvFile = createAuditableFile(resultFile); Logger.info("Generating summary spreadsheet: %s...", csvFile.getAbsolutePath()); CSVPrinter csvPrinter; @@ -347,7 +394,7 @@ private void generateSummaryCsvHelper( } BigDecimal winningThreshold = roundTallies.get(numRounds).getWinningThreshold(); - addContestInformationRows(csvPrinter, winningThreshold, slice, sliceId); + addContestInformationRows(csvPrinter, winningThreshold, resultFile.slice, resultFile.sliceId); addContestSummaryRows(csvPrinter, roundTallies.get(1)); csvPrinter.print("Rounds"); for (int round = 1; round <= numRounds; round++) { @@ -357,11 +404,10 @@ private void generateSummaryCsvHelper( } csvPrinter.println(); - final boolean isSlice = !isNullOrBlank(sliceId); - csvPrinter.print(isSlice ? "Eliminated*" : "Eliminated"); + csvPrinter.print(resultFile.isSlice ? "Eliminated*" : "Eliminated"); printActionSummary(csvPrinter, roundToEliminatedCandidates); - csvPrinter.print(isSlice ? "Elected*" : "Elected"); + csvPrinter.print(resultFile.isSlice ? "Elected*" : "Elected"); printActionSummary(csvPrinter, roundToWinningCandidates); // For each candidate: for each round: output total votes @@ -417,7 +463,7 @@ private void generateSummaryCsvHelper( } csvPrinter.println(); - if (!isSlice) { + if (!resultFile.isSlice) { csvPrinter.print("Current Round Threshold"); for (int round = 1; round <= numRounds; round++) { csvPrinter.print(roundTallies.get(round).getWinningThreshold()); @@ -427,7 +473,7 @@ private void generateSummaryCsvHelper( csvPrinter.println(); } - if (extended) { + if (resultFile.resultType == ResultType.DETAILED_REPORT) { for (StatusForRound status : STATUSES_TO_PRINT) { csvPrinter.print(status.getTitleCaseKey()); @@ -479,7 +525,7 @@ private void generateSummaryCsvHelper( // whether the value in the final round is positive. // Note that this concept only makes sense when we're reporting the overall tabulation, so we // omit it when generating results at the individual by-slice level. - if (!isSlice && roundToResidualSurplus.get(numRounds).signum() == 1) { + if (!resultFile.isSlice && roundToResidualSurplus.get(numRounds).signum() == 1) { csvPrinter.print("Residual surplus"); for (int round = 1; round <= numRounds; round++) { csvPrinter.print(roundToResidualSurplus.get(round)); @@ -506,10 +552,11 @@ private void generateSummaryCsvHelper( csvPrinter.println(); } - if (isSlice) { + if (resultFile.isSlice) { csvPrinter.println(); csvPrinter.print(String.format("*Elect/Eliminate decisions are from the full contest. " - + "All other results on this report are at the %s level.", slice.toLowerString())); + + "All other results on this report are at the %s level.", + resultFile.slice.toLowerString())); csvPrinter.println(); } @@ -518,7 +565,7 @@ private void generateSummaryCsvHelper( csvPrinter.close(); csvFile.finalizeAndHash(); } catch (IOException exception) { - Logger.severe("Error saving file: %s\n%s", outputPath, exception); + Logger.severe("Error saving file: %s\n%s", resultFile.resultType, exception); throw exception; } Logger.info("Summary spreadsheet generated successfully."); @@ -609,11 +656,9 @@ void generateOverallSummaryFiles( RoundTallies roundTallies, TallyTransfers tallyTransfers, List candidateOrder) throws IOException { - String outputPathSummary = getOutputFilePathFromInstance("summary"); - String outputPathExtended = getOutputFilePathFromInstance("extended_summary"); - generateSummaryExtendedCsv(roundTallies, candidateOrder, null, null, outputPathExtended); - generateSummaryCsv(roundTallies, candidateOrder, null, null, outputPathSummary); - generateSummaryJson(roundTallies, tallyTransfers, null, null, outputPathSummary); + generateSummaryCsv(roundTallies, candidateOrder, new ResultFile(ResultType.SUMMARY_REPORT)); + generateSummaryCsv(roundTallies, candidateOrder, new ResultFile(ResultType.DETAILED_REPORT)); + generateSummaryJson(roundTallies, tallyTransfers, new ResultFile(ResultType.JSON)); } // Write CastVoteRecords for the specified contest to the provided folder, @@ -630,18 +675,13 @@ String writeRcTabCvrCsv( // Put the input filename in the output filename in case contestId isn't unique -- // knowing that it's possible that if both the filename AND the contestId isn't unique, // this will fail. - AuditableFile outputFile = new AuditableFile( - getOutputFilePath( - csvOutputFolder, - "rctab_cvr", - timestampString, - null) - + ".csv"); + ResultFile resultFile = new ResultFile(ResultType.RCTAB_CVR); + AuditableFile auditableFile = createAuditableFile(resultFile); try { Logger.info("Writing cast vote records in generic format to file: %s...", - outputFile.getAbsolutePath()); + auditableFile.getAbsolutePath()); CSVPrinter csvPrinter; - BufferedWriter writer = Files.newBufferedWriter(outputFile.toPath()); + BufferedWriter writer = Files.newBufferedWriter(auditableFile.toPath()); CSVFormat format = CSVFormat.DEFAULT.builder().setNullString("").build(); csvPrinter = new CSVPrinter(writer, format); // print header: @@ -701,14 +741,14 @@ String writeRcTabCvrCsv( // finalize the file csvPrinter.flush(); csvPrinter.close(); - fileWritten = outputFile.getAbsolutePath(); - Logger.info("Successfully wrote: %s", outputFile.getAbsolutePath()); + fileWritten = auditableFile.getAbsolutePath(); + Logger.info("Successfully wrote: %s", auditableFile.getAbsolutePath()); - outputFile.finalizeAndHash(); + auditableFile.finalizeAndHash(); } catch (IOException exception) { Logger.severe( "Error writing cast vote records in generic format to output path: %s\n%s", - outputFile.getAbsolutePath(), exception); + auditableFile.getAbsolutePath(), exception); throw exception; } return fileWritten; @@ -755,8 +795,10 @@ void generateCdfJson(List castVoteRecords) // generate GpUnitIds for precincts "geopolitical units" (can be a precinct or jurisdiction) gpUnitIds = generateGpUnitIds(); - String outputPath = getOutputFilePathFromInstance("cvr_cdf") + ".json"; - Logger.info("Generating cast vote record CDF JSON file: %s...", outputPath); + ResultFile resultFile = new ResultFile(ResultType.CDF); + AuditableFile auditableFile = createAuditableFile(resultFile); + Logger.info("Generating cast vote record CDF JSON file: %s...", + auditableFile.getAbsolutePath()); HashMap outputJson = new HashMap<>(); outputJson.put("CVR", generateCdfMapForCvrs(castVoteRecords)); @@ -777,7 +819,7 @@ void generateCdfJson(List castVoteRecords) outputJson.put("Version", "1.0.0"); outputJson.put("@type", "CVR.CastVoteRecordReport"); - generateJsonFile(outputPath, outputJson); + generateJsonFile(auditableFile, outputJson); } // build map from precinctId => GpUnitId, as lookups are done by precinctId during cvr creation @@ -990,12 +1032,10 @@ private Map generateCdfMapForElection() { private void generateSummaryJson( RoundTallies roundTallies, TallyTransfers tallyTransfers, - TabulateBySlice slice, - String sliceId, - String outputPath) + ResultFile resultFile) throws IOException { - String jsonPath = outputPath + ".json"; - Logger.info("Generating summary JSON file: %s...", jsonPath); + AuditableFile jsonFile = createAuditableFile(resultFile); + Logger.info("Generating summary JSON file: %s...", jsonFile.getAbsolutePath()); // config will contain contest configuration info HashMap configData = new HashMap<>(); @@ -1004,8 +1044,8 @@ private void generateSummaryJson( configData.put("jurisdiction", config.getContestJurisdiction()); configData.put("office", config.getContestOffice()); configData.put("date", config.getContestDate()); - if (!isNullOrBlank(sliceId)) { - configData.put(slice.toLowerString(), sliceId); + if (resultFile.isSlice) { + configData.put(resultFile.slice.toLowerString(), resultFile.sliceId); } BigDecimal numNoRankings = @@ -1045,7 +1085,7 @@ private void generateSummaryJson( outputJson.put("config", configData); outputJson.put("results", results); - generateJsonFile(jsonPath, outputJson); + generateJsonFile(jsonFile, outputJson); } private Map updateCandidateNamesInTally(RoundTally roundSummary) { diff --git a/src/test/java/network/brightspots/rcv/TabulatorTests.java b/src/test/java/network/brightspots/rcv/TabulatorTests.java index d732d4f6a..8141f9406 100644 --- a/src/test/java/network/brightspots/rcv/TabulatorTests.java +++ b/src/test/java/network/brightspots/rcv/TabulatorTests.java @@ -34,10 +34,13 @@ import java.io.FileReader; import java.io.IOException; import java.nio.file.Files; +import java.nio.file.Path; import java.nio.file.Paths; import java.util.HashMap; import java.util.List; import java.util.Map; +import network.brightspots.rcv.ResultsWriter.ResultFile; +import network.brightspots.rcv.ResultsWriter.ResultType; import network.brightspots.rcv.Tabulator.TabulationAbortedException; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.DisplayName; @@ -187,11 +190,16 @@ private static boolean fileCompareLineByLine(String path1, String path2) { return result; } + // given stem and suffix returns path to file in test asset folder + private static Path getTestDirectory(String stem) { + return Paths.get(System.getProperty("user.dir"), TEST_ASSET_FOLDER, stem); + } + // given stem and suffix returns path to file in test asset folder private static String getTestFilePath(String stem, String suffix) { - return Paths.get(System.getProperty("user.dir"), TEST_ASSET_FOLDER, stem, stem + suffix) - .toAbsolutePath() - .toString(); + Path directory = getTestDirectory(stem); + String filename = stem + suffix; + return Paths.get(directory.toString(), filename).toAbsolutePath().toString(); } private static void runTabulationTest(String testStem) { @@ -224,7 +232,7 @@ private static void runTabulationTest(String stem, String expectedException, if (config.isMultiSeatSequentialWinnerTakesAllEnabled()) { for (int i = 1; i <= config.getNumberOfWinners(); i++) { - compareFiles(config, stem, timestampString, Integer.toString(i)); + compareFiles(config, stem, timestampString, i); } } else { compareFiles(config, stem, timestampString, null); @@ -233,14 +241,12 @@ private static void runTabulationTest(String stem, String expectedException, int numSlicedFilesChecked = 0; for (ContestConfig.TabulateBySlice slice : config.enabledSlices()) { for (String sliceName : session.loadSliceNamesFromCvrs(slice, config)) { - String outputTypeJson = ResultsWriter.sanitizeStringForOutput( - String.format("%s_%s_summary", sliceName, slice.toLowerString())); - String outputTypeCsv = ResultsWriter.sanitizeStringForOutput( - String.format("%s_%s_extended_summary", sliceName, slice.toLowerString())); - if (compareFiles(config, stem, outputTypeJson, ".json", timestampString, null, true)) { + ResultFile resultFileJson = new ResultFile(ResultType.JSON, slice, sliceName); + ResultFile resultFileCsv = new ResultFile(ResultType.DETAILED_REPORT, slice, sliceName); + if (compareFiles(config, stem, resultFileJson, timestampString, null, true)) { numSlicedFilesChecked++; } - if (compareFiles(config, stem, outputTypeCsv, ".csv", timestampString, null, true)) { + if (compareFiles(config, stem, resultFileCsv, timestampString, null, true)) { numSlicedFilesChecked++; } } @@ -259,7 +265,7 @@ private static void runConvertToCdfTest(String stem) { String timestampString = session.getTimestampString(); ContestConfig config = ContestConfig.loadContestConfig(configPath); - compareFiles(config, stem, "cvr_cdf", ".json", timestampString, null, false); + compareFiles(config, stem, ResultType.CDF, timestampString, null, false); cleanOutputFolder(session); } @@ -322,15 +328,35 @@ private static void cleanOutputFolder(TabulatorSession session) { } private static void compareFiles( - ContestConfig config, String stem, String timestampString, String sequentialId) { - compareFiles(config, stem, "summary", ".json", timestampString, sequentialId, false); - compareFiles(config, stem, "extended_summary", ".csv", timestampString, sequentialId, false); + ContestConfig config, String stem, String timestampString, Integer sequentialId) { + compareFiles(config, stem, ResultType.JSON, timestampString, sequentialId, false); + compareFiles(config, stem, ResultType.DETAILED_REPORT, timestampString, sequentialId, false); compareExtendedSummaryToSummary(config, timestampString, sequentialId); if (config.isGenerateCdfJsonEnabled()) { - compareFiles(config, stem, "cvr_cdf", ".json", timestampString, sequentialId, false); + compareFiles(config, stem, ResultType.CDF, timestampString, sequentialId, false); } } + /** + * Helper comparison for non-slice files. + */ + private static boolean compareFiles( + ContestConfig config, + String stem, + ResultType resultType, + String timestampString, + Integer sequentialId, + boolean onlyCheckIfExpectedFileExists) { + ResultFile actualResultFile = new ResultFile(resultType); + return compareFiles( + config, + stem, + actualResultFile, + timestampString, + sequentialId, + onlyCheckIfExpectedFileExists); + } + /** * Returns whether the files were compared at all. * If they were compared and not equal, the test will fail. @@ -338,22 +364,14 @@ private static void compareFiles( private static boolean compareFiles( ContestConfig config, String stem, - String outputType, - String extension, + ResultFile actualResultFile, String timestampString, - String sequentialId, + Integer sequentialId, boolean onlyCheckIfExpectedFileExists) { - String actualOutputPath = - ResultsWriter.getOutputFilePath( - config.getOutputDirectory(), outputType, timestampString, sequentialId) - + extension; - String expectedPath = - getTestFilePath( - stem, - ResultsWriter.sequentialSuffixForOutputPath(sequentialId) - + "_expected_" - + outputType - + extension); + String actualOutputPath = actualResultFile.getPath( + config.getOutputDirectory(), timestampString, sequentialId).toAbsolutePath().toString(); + String expectedPath = actualResultFile.getPath(getTestDirectory(stem).toString(), + stem, "expected", sequentialId).toString(); Logger.info("Comparing files:\nGenerated: %s\nReference: %s", actualOutputPath, expectedPath); boolean didCompare = true; @@ -375,20 +393,19 @@ private static boolean compareFiles( * extended file except for the inactive ballot breakdown. */ private static void compareExtendedSummaryToSummary( - ContestConfig config, String timestampString, String sequentialId) { - String summaryPath = ResultsWriter.getOutputFilePath( - config.getOutputDirectory(), "summary", timestampString, sequentialId) - + ".csv"; - String extendedPath = ResultsWriter.getOutputFilePath( - config.getOutputDirectory(), "extended_summary", timestampString, sequentialId) - + ".csv"; + ContestConfig config, String timestampString, Integer sequentialId) { + String dir = config.getOutputDirectory(); + String summaryPath = new ResultFile(ResultType.SUMMARY_REPORT).getPath( + dir, timestampString, sequentialId).toAbsolutePath().toString(); + String detailedPath = new ResultFile(ResultType.DETAILED_REPORT).getPath( + dir, timestampString, sequentialId).toAbsolutePath().toString(); try (BufferedReader brSummary = new BufferedReader(new FileReader(summaryPath, UTF_8)); - BufferedReader brExtended = new BufferedReader(new FileReader(extendedPath, UTF_8))) { + BufferedReader brDetailed = new BufferedReader(new FileReader(detailedPath, UTF_8))) { while (true) { - String lineExtended = brExtended.readLine(); + String lineDetailed = brDetailed.readLine(); // If the extended file has reached its end, then the non-extended file must have too - if (lineExtended == null) { + if (lineDetailed == null) { assertNull(brSummary.readLine(), "Extended file is missing a line"); return; } @@ -396,7 +413,7 @@ private static void compareExtendedSummaryToSummary( // If the extended file should be excluded, continue without moving the file pointer // in the non-extended file. For now, there's only one type of row excluded, and they // happen to all start with "Inactive Ballots by" - if (lineExtended.startsWith("Inactive Ballots by")) { + if (lineDetailed.startsWith("Inactive Ballots by")) { continue; } @@ -404,9 +421,9 @@ private static void compareExtendedSummaryToSummary( // in both files. String lineSummary = brSummary.readLine(); assertNotNull(lineSummary, "Summary file is missing a line"); - if (!lineSummary.equals(lineExtended)) { + if (!lineSummary.equals(lineDetailed)) { fail("Line differes in extended vs non-extended CSV: \n%s\n%s".formatted( - lineSummary, lineExtended)); + lineSummary, lineDetailed)); } } } catch (FileNotFoundException exception) { From b1c54a23d7d66d0ca30e217ff01a76b111a16e90 Mon Sep 17 00:00:00 2001 From: Armin Samii Date: Tue, 8 Oct 2024 19:01:21 -0400 Subject: [PATCH 02/17] move files to new recommended name --- .../brightspots/rcv/ResultsWriter.java | 22 +++++++++---------- .../brightspots/rcv/TabulatorTests.java | 12 +++++----- ...IS_W-13_P-09_precinct_detailed_report.csv} | 0 ...S_W-13_P-09_precinct_detailed_report.json} | 0 ...LIS_W-1_P-01_precinct_detailed_report.csv} | 0 ...IS_W-1_P-01_precinct_detailed_report.json} | 0 ...apolis_mayor_expected_detailed_report.csv} | 0 ...polis_mayor_expected_detailed_report.json} | 0 ..._mayor_scale_expected_detailed_report.csv} | 0 ...mayor_scale_expected_detailed_report.json} | 0 ...eapolis_park_expected_detailed_report.csv} | 0 ...apolis_park_expected_detailed_report.json} | 0 ...k_bottoms_up_expected_detailed_report.csv} | 0 ..._bottoms_up_expected_detailed_report.json} | 0 ...is_park_hare_expected_detailed_report.csv} | 0 ...s_park_hare_expected_detailed_report.json} | 0 ...sequential_1_expected_detailed_report.csv} | 0 ...equential_1_expected_detailed_report.json} | 0 ...sequential_2_expected_detailed_report.csv} | 0 ...equential_2_expected_detailed_report.json} | 0 ...sequential_3_expected_detailed_report.csv} | 0 ...equential_3_expected_detailed_report.json} | 0 ...rtland_mayor_expected_detailed_report.csv} | 0 ...tland_mayor_expected_detailed_report.json} | 0 ..._mayor_codes_expected_detailed_report.csv} | 0 ...mayor_codes_expected_detailed_report.json} | 0 ...IS_W-13_P-13_precinct_detailed_report.csv} | 0 ...S_W-13_P-13_precinct_detailed_report.json} | 0 ...LIS_W-1_P-01_precinct_detailed_report.csv} | 0 ...IS_W-1_P-01_precinct_detailed_report.json} | 0 ...apolis_mayor_expected_detailed_report.csv} | 0 ...polis_mayor_expected_detailed_report.json} | 0 ...rnor_primary_expected_detailed_report.csv} | 0 ...nor_primary_expected_detailed_report.json} | 0 ...ses_cdf_json_expected_detailed_report.csv} | 0 ...es_cdf_json_expected_detailed_report.json} | 0 ...ses_ess_xlsx_expected_detailed_report.csv} | 0 ...es_ess_xlsx_expected_detailed_report.json} | 0 ...APOLIS_W-1_P-02_batch_detailed_report.csv} | 0 ...POLIS_W-1_P-04_batch_detailed_report.json} | 0 ...atch_example_expected_detailed_report.csv} | 0 ...tch_example_expected_detailed_report.json} | 0 ...nsas_primary_expected_detailed_report.csv} | 0 ...sas_primary_expected_detailed_report.json} | 0 ...inline_comma_expected_detailed_report.csv} | 0 ...nline_comma_expected_detailed_report.json} | 0 ...ulation_test_expected_detailed_report.csv} | 0 ...lation_test_expected_detailed_report.json} | 0 ...ination_test_expected_detailed_report.csv} | 0 ...nation_test_expected_detailed_report.json} | 0 ..._header_test_expected_detailed_report.csv} | 0 ...header_test_expected_detailed_report.json} | 0 ...inion_alaska_expected_detailed_report.csv} | 0 ...nion_alaska_expected_detailed_report.json} | 0 ...inion_kansas_expected_detailed_report.csv} | 0 ...nion_kansas_expected_detailed_report.json} | 0 ...n_multi_file_expected_detailed_report.csv} | 0 ..._multi_file_expected_detailed_report.json} | 0 ...recinct_data_expected_detailed_report.csv} | 0 ...ecinct_data_expected_detailed_report.json} | 0 ...nion_wyoming_expected_detailed_report.csv} | 0 ...ion_wyoming_expected_detailed_report.json} | 0 ...plicate_test_expected_detailed_report.csv} | 0 ...licate_test_expected_detailed_report.json} | 0 ...xcluded_test_expected_detailed_report.csv} | 0 ...cluded_test_expected_detailed_report.json} | 0 ...e_continuing_expected_detailed_report.csv} | 0 ..._continuing_expected_detailed_report.json} | 0 ...reshold_test_expected_detailed_report.csv} | 0 ...eshold_test_expected_detailed_report.json} | 0 ...breaker_test_expected_detailed_report.csv} | 0 ...reaker_test_expected_detailed_report.json} | 0 ...ric_csv_test_expected_detailed_report.csv} | 0 ...ic_csv_test_expected_detailed_report.json} | 0 ...school_board_expected_detailed_report.csv} | 0 ...chool_board_expected_detailed_report.json} | 0 ...nty_officers_expected_detailed_report.csv} | 0 ...ty_officers_expected_detailed_report.json} | 0 ...reshold_test_expected_detailed_report.csv} | 0 ...eshold_test_expected_detailed_report.json} | 0 ...at_threshold_expected_detailed_report.csv} | 0 ...t_threshold_expected_detailed_report.json} | 0 ...expected_pc1_precinct_detailed_report.csv} | 0 ...expected_pc2_precinct_detailed_report.csv} | 0 ...xpected_pc2_precinct_detailed_report.json} | 0 ...IS_W-13_P-13_precinct_detailed_report.csv} | 0 ...S_W-13_P-13_precinct_detailed_report.json} | 0 ...inct_example_expected_detailed_report.csv} | 0 ...nct_example_expected_detailed_report.json} | 0 ..._precinct_id_precinct_detailed_report.csv} | 0 ...precinct_id_precinct_detailed_report.json} | 0 ...n_candidates_expected_detailed_report.csv} | 0 ..._candidates_expected_detailed_report.json} | 0 ...th_threshold_expected_detailed_report.csv} | 0 ...h_threshold_expected_detailed_report.json} | 0 ...eat_uwi_test_expected_detailed_report.csv} | 0 ...at_uwi_test_expected_detailed_report.json} | 0 ...st_xml_cdf_2_expected_detailed_report.csv} | 0 ...t_xml_cdf_2_expected_detailed_report.json} | 0 ...LIS_W-1_P-02_precinct_detailed_report.csv} | 0 ...IS_W-1_P-02_precinct_detailed_report.json} | 0 ...inct_example_expected_detailed_report.csv} | 0 ...nct_example_expected_detailed_report.json} | 0 ...with_batch_1_expected_detailed_report.csv} | 0 ...ith_batch_1_expected_detailed_report.json} | 0 ...with_batch_2_expected_detailed_report.csv} | 0 ...ith_batch_2_expected_detailed_report.json} | 0 ...with_batch_3_expected_detailed_report.csv} | 0 ...ith_batch_3_expected_detailed_report.json} | 0 ..._until_two_1_expected_detailed_report.csv} | 0 ...until_two_1_expected_detailed_report.json} | 0 ..._until_two_2_expected_detailed_report.csv} | 0 ...until_two_2_expected_detailed_report.json} | 0 ..._until_two_3_expected_detailed_report.csv} | 0 ...until_two_3_expected_detailed_report.json} | 0 ...to_next_test_expected_detailed_report.csv} | 0 ...o_next_test_expected_detailed_report.json} | 0 ...n_early_test_expected_detailed_report.csv} | 0 ..._early_test_expected_detailed_report.json} | 0 ...first_choice_expected_detailed_report.csv} | 0 ...irst_choice_expected_detailed_report.json} | 0 ..._at_overvote_expected_detailed_report.csv} | 0 ...at_overvote_expected_detailed_report.json} | 0 ...skip_to_next_expected_detailed_report.csv} | 0 ...kip_to_next_expected_detailed_report.json} | 0 ...oice_exhaust_expected_detailed_report.csv} | 0 ...ice_exhaust_expected_detailed_report.json} | 0 ..._choice_next_expected_detailed_report.csv} | 0 ...choice_next_expected_detailed_report.json} | 0 ...oice_exhaust_expected_detailed_report.csv} | 0 ...ice_exhaust_expected_detailed_report.json} | 0 ...cate_exhaust_expected_detailed_report.csv} | 0 ...ate_exhaust_expected_detailed_report.json} | 0 ...skip_to_next_expected_detailed_report.csv} | 0 ...kip_to_next_expected_detailed_report.json} | 0 ..._8_multi_cdf_expected_detailed_report.csv} | 0 ...8_multi_cdf_expected_detailed_report.json} | 0 ...er_per_round_expected_detailed_report.csv} | 0 ...r_per_round_expected_detailed_report.json} | 0 ...al_threshold_expected_detailed_report.csv} | 0 ...l_threshold_expected_detailed_report.json} | 0 ...le_threshold_expected_detailed_report.csv} | 0 ...e_threshold_expected_detailed_report.json} | 0 ...te_delimiter_expected_detailed_report.csv} | 0 ...e_delimiter_expected_detailed_report.json} | 0 ...red_write_in_expected_detailed_report.csv} | 0 ...ed_write_in_expected_detailed_report.json} | 0 ...utation_test_expected_detailed_report.csv} | 0 ...tation_test_expected_detailed_report.json} | 0 ..._random_test_expected_detailed_report.csv} | 0 ...random_test_expected_detailed_report.json} | 0 ...ak_seed_test_expected_detailed_report.csv} | 0 ...k_seed_test_expected_detailed_report.json} | 0 ..._config_test_expected_detailed_report.csv} | 0 ...config_test_expected_detailed_report.json} | 0 ...ef_of_police_expected_detailed_report.csv} | 0 ...f_of_police_expected_detailed_report.json} | 0 ...city_coroner_expected_detailed_report.csv} | 0 ...ity_coroner_expected_detailed_report.json} | 0 ...uncil_member_expected_detailed_report.csv} | 0 ...ncil_member_expected_detailed_report.json} | 0 ...f_city_mayor_expected_detailed_report.csv} | 0 ..._city_mayor_expected_detailed_report.json} | 0 ...ax_collector_expected_detailed_report.csv} | 0 ...x_collector_expected_detailed_report.json} | 0 ...unty_coroner_expected_detailed_report.csv} | 0 ...nty_coroner_expected_detailed_report.json} | 0 ...unty_sheriff_expected_detailed_report.csv} | 0 ...nty_sheriff_expected_detailed_report.json} | 0 ...not_win_test_expected_detailed_report.csv} | 0 ...ot_win_test_expected_detailed_report.json} | 0 171 files changed, 17 insertions(+), 17 deletions(-) rename src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_mayor/{2013_minneapolis_mayor_expected_MINNEAPOLIS_W-13_P-09_precinct_extended_summary.csv => 2013_minneapolis_mayor_expected_MINNEAPOLIS_W-13_P-09_precinct_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_mayor/{2013_minneapolis_mayor_expected_MINNEAPOLIS_W-13_P-09_precinct_summary.json => 2013_minneapolis_mayor_expected_MINNEAPOLIS_W-13_P-09_precinct_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_mayor/{2013_minneapolis_mayor_expected_MINNEAPOLIS_W-1_P-01_precinct_extended_summary.csv => 2013_minneapolis_mayor_expected_MINNEAPOLIS_W-1_P-01_precinct_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_mayor/{2013_minneapolis_mayor_expected_MINNEAPOLIS_W-1_P-01_precinct_summary.json => 2013_minneapolis_mayor_expected_MINNEAPOLIS_W-1_P-01_precinct_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_mayor/{2013_minneapolis_mayor_expected_extended_summary.csv => 2013_minneapolis_mayor_expected_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_mayor/{2013_minneapolis_mayor_expected_summary.json => 2013_minneapolis_mayor_expected_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_mayor_scale/{2013_minneapolis_mayor_scale_expected_extended_summary.csv => 2013_minneapolis_mayor_scale_expected_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_mayor_scale/{2013_minneapolis_mayor_scale_expected_summary.json => 2013_minneapolis_mayor_scale_expected_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_park/{2013_minneapolis_park_expected_extended_summary.csv => 2013_minneapolis_park_expected_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_park/{2013_minneapolis_park_expected_summary.json => 2013_minneapolis_park_expected_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_park_bottoms_up/{2013_minneapolis_park_bottoms_up_expected_extended_summary.csv => 2013_minneapolis_park_bottoms_up_expected_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_park_bottoms_up/{2013_minneapolis_park_bottoms_up_expected_summary.json => 2013_minneapolis_park_bottoms_up_expected_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_park_hare/{2013_minneapolis_park_hare_expected_extended_summary.csv => 2013_minneapolis_park_hare_expected_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_park_hare/{2013_minneapolis_park_hare_expected_summary.json => 2013_minneapolis_park_hare_expected_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_park_sequential/{2013_minneapolis_park_sequential_1_expected_extended_summary.csv => 2013_minneapolis_park_sequential_1_expected_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_park_sequential/{2013_minneapolis_park_sequential_1_expected_summary.json => 2013_minneapolis_park_sequential_1_expected_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_park_sequential/{2013_minneapolis_park_sequential_2_expected_extended_summary.csv => 2013_minneapolis_park_sequential_2_expected_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_park_sequential/{2013_minneapolis_park_sequential_2_expected_summary.json => 2013_minneapolis_park_sequential_2_expected_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_park_sequential/{2013_minneapolis_park_sequential_3_expected_extended_summary.csv => 2013_minneapolis_park_sequential_3_expected_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_park_sequential/{2013_minneapolis_park_sequential_3_expected_summary.json => 2013_minneapolis_park_sequential_3_expected_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/2015_portland_mayor/{2015_portland_mayor_expected_extended_summary.csv => 2015_portland_mayor_expected_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/2015_portland_mayor/{2015_portland_mayor_expected_summary.json => 2015_portland_mayor_expected_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/2015_portland_mayor_codes/{2015_portland_mayor_codes_expected_extended_summary.csv => 2015_portland_mayor_codes_expected_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/2015_portland_mayor_codes/{2015_portland_mayor_codes_expected_summary.json => 2015_portland_mayor_codes_expected_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/2017_minneapolis_mayor/{2017_minneapolis_mayor_expected_MINNEAPOLIS_W-13_P-13_precinct_extended_summary.csv => 2017_minneapolis_mayor_expected_MINNEAPOLIS_W-13_P-13_precinct_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/2017_minneapolis_mayor/{2017_minneapolis_mayor_expected_MINNEAPOLIS_W-13_P-13_precinct_summary.json => 2017_minneapolis_mayor_expected_MINNEAPOLIS_W-13_P-13_precinct_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/2017_minneapolis_mayor/{2017_minneapolis_mayor_expected_MINNEAPOLIS_W-1_P-01_precinct_extended_summary.csv => 2017_minneapolis_mayor_expected_MINNEAPOLIS_W-1_P-01_precinct_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/2017_minneapolis_mayor/{2017_minneapolis_mayor_expected_MINNEAPOLIS_W-1_P-01_precinct_summary.json => 2017_minneapolis_mayor_expected_MINNEAPOLIS_W-1_P-01_precinct_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/2017_minneapolis_mayor/{2017_minneapolis_mayor_expected_extended_summary.csv => 2017_minneapolis_mayor_expected_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/2017_minneapolis_mayor/{2017_minneapolis_mayor_expected_summary.json => 2017_minneapolis_mayor_expected_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/2018_maine_governor_primary/{2018_maine_governor_primary_expected_extended_summary.csv => 2018_maine_governor_primary_expected_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/2018_maine_governor_primary/{2018_maine_governor_primary_expected_summary.json => 2018_maine_governor_primary_expected_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/aliases_cdf_json/{aliases_cdf_json_expected_extended_summary.csv => aliases_cdf_json_expected_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/aliases_cdf_json/{aliases_cdf_json_expected_summary.json => aliases_cdf_json_expected_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/aliases_ess_xlsx/{aliases_ess_xlsx_expected_extended_summary.csv => aliases_ess_xlsx_expected_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/aliases_ess_xlsx/{aliases_ess_xlsx_expected_summary.json => aliases_ess_xlsx_expected_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/batch_example/{batch_example_expected_MINNEAPOLIS_W-1_P-02_batch_extended_summary.csv => batch_example_expected_MINNEAPOLIS_W-1_P-02_batch_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/batch_example/{batch_example_expected_MINNEAPOLIS_W-1_P-04_batch_summary.json => batch_example_expected_MINNEAPOLIS_W-1_P-04_batch_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/batch_example/{batch_example_expected_extended_summary.csv => batch_example_expected_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/batch_example/{batch_example_expected_summary.json => batch_example_expected_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/clear_ballot_kansas_primary/{clear_ballot_kansas_primary_expected_extended_summary.csv => clear_ballot_kansas_primary_expected_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/clear_ballot_kansas_primary/{clear_ballot_kansas_primary_expected_summary.json => clear_ballot_kansas_primary_expected_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/clear_ballot_with_inline_comma/{clear_ballot_with_inline_comma_expected_extended_summary.csv => clear_ballot_with_inline_comma_expected_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/clear_ballot_with_inline_comma/{clear_ballot_with_inline_comma_expected_summary.json => clear_ballot_with_inline_comma_expected_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/continue_tabulation_test/{continue_tabulation_test_expected_extended_summary.csv => continue_tabulation_test_expected_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/continue_tabulation_test/{continue_tabulation_test_expected_summary.json => continue_tabulation_test_expected_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/continue_until_two_with_batch_elimination_test/{continue_until_two_with_batch_elimination_test_expected_extended_summary.csv => continue_until_two_with_batch_elimination_test_expected_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/continue_until_two_with_batch_elimination_test/{continue_until_two_with_batch_elimination_test_expected_summary.json => continue_until_two_with_batch_elimination_test_expected_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/csv_missing_header_test/{csv_missing_header_test_expected_extended_summary.csv => csv_missing_header_test_expected_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/csv_missing_header_test/{csv_missing_header_test_expected_summary.json => csv_missing_header_test_expected_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/dominion_alaska/{dominion_alaska_expected_extended_summary.csv => dominion_alaska_expected_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/dominion_alaska/{dominion_alaska_expected_summary.json => dominion_alaska_expected_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/dominion_kansas/{dominion_kansas_expected_extended_summary.csv => dominion_kansas_expected_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/dominion_kansas/{dominion_kansas_expected_summary.json => dominion_kansas_expected_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/dominion_multi_file/{dominion_multi_file_expected_extended_summary.csv => dominion_multi_file_expected_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/dominion_multi_file/{dominion_multi_file_expected_summary.json => dominion_multi_file_expected_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/dominion_no_precinct_data/{dominion_no_precinct_data_expected_extended_summary.csv => dominion_no_precinct_data_expected_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/dominion_no_precinct_data/{dominion_no_precinct_data_expected_summary.json => dominion_no_precinct_data_expected_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/dominion_wyoming/{dominion_wyoming_expected_extended_summary.csv => dominion_wyoming_expected_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/dominion_wyoming/{dominion_wyoming_expected_summary.json => dominion_wyoming_expected_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/duplicate_test/{duplicate_test_expected_extended_summary.csv => duplicate_test_expected_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/duplicate_test/{duplicate_test_expected_summary.json => duplicate_test_expected_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/excluded_test/{excluded_test_expected_extended_summary.csv => excluded_test_expected_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/excluded_test/{excluded_test_expected_summary.json => excluded_test_expected_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/exhaust_if_multiple_continuing/{exhaust_if_multiple_continuing_expected_extended_summary.csv => exhaust_if_multiple_continuing_expected_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/exhaust_if_multiple_continuing/{exhaust_if_multiple_continuing_expected_summary.json => exhaust_if_multiple_continuing_expected_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/first_round_determines_threshold_test/{first_round_determines_threshold_test_expected_extended_summary.csv => first_round_determines_threshold_test_expected_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/first_round_determines_threshold_test/{first_round_determines_threshold_test_expected_summary.json => first_round_determines_threshold_test_expected_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/first_round_determines_threshold_tiebreaker_test/{first_round_determines_threshold_tiebreaker_test_expected_extended_summary.csv => first_round_determines_threshold_tiebreaker_test_expected_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/first_round_determines_threshold_tiebreaker_test/{first_round_determines_threshold_tiebreaker_test_expected_summary.json => first_round_determines_threshold_tiebreaker_test_expected_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/generic_csv_test/{generic_csv_test_expected_extended_summary.csv => generic_csv_test_expected_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/generic_csv_test/{generic_csv_test_expected_summary.json => generic_csv_test_expected_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/hart_cedar_park_school_board/{hart_cedar_park_school_board_expected_extended_summary.csv => hart_cedar_park_school_board_expected_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/hart_cedar_park_school_board/{hart_cedar_park_school_board_expected_summary.json => hart_cedar_park_school_board_expected_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/hart_travis_county_officers/{hart_travis_county_officers_expected_extended_summary.csv => hart_travis_county_officers_expected_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/hart_travis_county_officers/{hart_travis_county_officers_expected_summary.json => hart_travis_county_officers_expected_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/minimum_threshold_test/{minimum_threshold_test_expected_extended_summary.csv => minimum_threshold_test_expected_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/minimum_threshold_test/{minimum_threshold_test_expected_summary.json => minimum_threshold_test_expected_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/minneapolis_multi_seat_threshold/{minneapolis_multi_seat_threshold_expected_extended_summary.csv => minneapolis_multi_seat_threshold_expected_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/minneapolis_multi_seat_threshold/{minneapolis_multi_seat_threshold_expected_summary.json => minneapolis_multi_seat_threshold_expected_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/minneapolis_multi_seat_threshold/{minneapolis_multi_seat_threshold_expected_pc1_precinct_extended_summary.csv => minneapolis_multi_seat_threshold_expected_pc1_precinct_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/minneapolis_multi_seat_threshold/{minneapolis_multi_seat_threshold_expected_pc2_precinct_extended_summary.csv => minneapolis_multi_seat_threshold_expected_pc2_precinct_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/minneapolis_multi_seat_threshold/{minneapolis_multi_seat_threshold_expected_pc2_precinct_summary.json => minneapolis_multi_seat_threshold_expected_pc2_precinct_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/missing_precinct_example/{missing_precinct_example_expected_MINNEAPOLIS_W-13_P-13_precinct_extended_summary.csv => missing_precinct_example_expected_MINNEAPOLIS_W-13_P-13_precinct_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/missing_precinct_example/{missing_precinct_example_expected_MINNEAPOLIS_W-13_P-13_precinct_summary.json => missing_precinct_example_expected_MINNEAPOLIS_W-13_P-13_precinct_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/missing_precinct_example/{missing_precinct_example_expected_extended_summary.csv => missing_precinct_example_expected_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/missing_precinct_example/{missing_precinct_example_expected_summary.json => missing_precinct_example_expected_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/missing_precinct_example/{missing_precinct_example_expected_missing_precinct_id_precinct_extended_summary.csv => missing_precinct_example_expected_missing_precinct_id_precinct_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/missing_precinct_example/{missing_precinct_example_expected_missing_precinct_id_precinct_summary.json => missing_precinct_example_expected_missing_precinct_id_precinct_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/more_winners_than_candidates/{more_winners_than_candidates_expected_extended_summary.csv => more_winners_than_candidates_expected_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/more_winners_than_candidates/{more_winners_than_candidates_expected_summary.json => more_winners_than_candidates_expected_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/multi_seat_bottoms_up_with_threshold/{multi_seat_bottoms_up_with_threshold_expected_extended_summary.csv => multi_seat_bottoms_up_with_threshold_expected_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/multi_seat_bottoms_up_with_threshold/{multi_seat_bottoms_up_with_threshold_expected_summary.json => multi_seat_bottoms_up_with_threshold_expected_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/multi_seat_uwi_test/{multi_seat_uwi_test_expected_extended_summary.csv => multi_seat_uwi_test_expected_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/multi_seat_uwi_test/{multi_seat_uwi_test_expected_summary.json => multi_seat_uwi_test_expected_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/nist_xml_cdf_2/{nist_xml_cdf_2_expected_extended_summary.csv => nist_xml_cdf_2_expected_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/nist_xml_cdf_2/{nist_xml_cdf_2_expected_summary.json => nist_xml_cdf_2_expected_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/precinct_example/{precinct_example_expected_MINNEAPOLIS_W-1_P-02_precinct_extended_summary.csv => precinct_example_expected_MINNEAPOLIS_W-1_P-02_precinct_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/precinct_example/{precinct_example_expected_MINNEAPOLIS_W-1_P-02_precinct_summary.json => precinct_example_expected_MINNEAPOLIS_W-1_P-02_precinct_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/precinct_example/{precinct_example_expected_extended_summary.csv => precinct_example_expected_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/precinct_example/{precinct_example_expected_summary.json => precinct_example_expected_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/sequential_with_batch/{sequential_with_batch_1_expected_extended_summary.csv => sequential_with_batch_1_expected_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/sequential_with_batch/{sequential_with_batch_1_expected_summary.json => sequential_with_batch_1_expected_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/sequential_with_batch/{sequential_with_batch_2_expected_extended_summary.csv => sequential_with_batch_2_expected_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/sequential_with_batch/{sequential_with_batch_2_expected_summary.json => sequential_with_batch_2_expected_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/sequential_with_batch/{sequential_with_batch_3_expected_extended_summary.csv => sequential_with_batch_3_expected_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/sequential_with_batch/{sequential_with_batch_3_expected_summary.json => sequential_with_batch_3_expected_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/sequential_with_continue_until_two/{sequential_with_continue_until_two_1_expected_extended_summary.csv => sequential_with_continue_until_two_1_expected_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/sequential_with_continue_until_two/{sequential_with_continue_until_two_1_expected_summary.json => sequential_with_continue_until_two_1_expected_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/sequential_with_continue_until_two/{sequential_with_continue_until_two_2_expected_extended_summary.csv => sequential_with_continue_until_two_2_expected_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/sequential_with_continue_until_two/{sequential_with_continue_until_two_2_expected_summary.json => sequential_with_continue_until_two_2_expected_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/sequential_with_continue_until_two/{sequential_with_continue_until_two_3_expected_extended_summary.csv => sequential_with_continue_until_two_3_expected_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/sequential_with_continue_until_two/{sequential_with_continue_until_two_3_expected_summary.json => sequential_with_continue_until_two_3_expected_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/skip_to_next_test/{skip_to_next_test_expected_extended_summary.csv => skip_to_next_test_expected_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/skip_to_next_test/{skip_to_next_test_expected_summary.json => skip_to_next_test_expected_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/stop_tabulation_early_test/{stop_tabulation_early_test_expected_extended_summary.csv => stop_tabulation_early_test_expected_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/stop_tabulation_early_test/{stop_tabulation_early_test_expected_summary.json => stop_tabulation_early_test_expected_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/test_set_0_skipped_first_choice/{test_set_0_skipped_first_choice_expected_extended_summary.csv => test_set_0_skipped_first_choice_expected_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/test_set_0_skipped_first_choice/{test_set_0_skipped_first_choice_expected_summary.json => test_set_0_skipped_first_choice_expected_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/test_set_1_exhaust_at_overvote/{test_set_1_exhaust_at_overvote_expected_extended_summary.csv => test_set_1_exhaust_at_overvote_expected_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/test_set_1_exhaust_at_overvote/{test_set_1_exhaust_at_overvote_expected_summary.json => test_set_1_exhaust_at_overvote_expected_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/test_set_2_overvote_skip_to_next/{test_set_2_overvote_skip_to_next_expected_extended_summary.csv => test_set_2_overvote_skip_to_next_expected_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/test_set_2_overvote_skip_to_next/{test_set_2_overvote_skip_to_next_expected_summary.json => test_set_2_overvote_skip_to_next_expected_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/test_set_3_skipped_choice_exhaust/{test_set_3_skipped_choice_exhaust_expected_extended_summary.csv => test_set_3_skipped_choice_exhaust_expected_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/test_set_3_skipped_choice_exhaust/{test_set_3_skipped_choice_exhaust_expected_summary.json => test_set_3_skipped_choice_exhaust_expected_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/test_set_4_skipped_choice_next/{test_set_4_skipped_choice_next_expected_extended_summary.csv => test_set_4_skipped_choice_next_expected_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/test_set_4_skipped_choice_next/{test_set_4_skipped_choice_next_expected_summary.json => test_set_4_skipped_choice_next_expected_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/test_set_5_two_skipped_choice_exhaust/{test_set_5_two_skipped_choice_exhaust_expected_extended_summary.csv => test_set_5_two_skipped_choice_exhaust_expected_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/test_set_5_two_skipped_choice_exhaust/{test_set_5_two_skipped_choice_exhaust_expected_summary.json => test_set_5_two_skipped_choice_exhaust_expected_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/test_set_6_duplicate_exhaust/{test_set_6_duplicate_exhaust_expected_extended_summary.csv => test_set_6_duplicate_exhaust_expected_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/test_set_6_duplicate_exhaust/{test_set_6_duplicate_exhaust_expected_summary.json => test_set_6_duplicate_exhaust_expected_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/test_set_7_duplicate_skip_to_next/{test_set_7_duplicate_skip_to_next_expected_extended_summary.csv => test_set_7_duplicate_skip_to_next_expected_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/test_set_7_duplicate_skip_to_next/{test_set_7_duplicate_skip_to_next_expected_summary.json => test_set_7_duplicate_skip_to_next_expected_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/test_set_8_multi_cdf/{test_set_8_multi_cdf_expected_extended_summary.csv => test_set_8_multi_cdf_expected_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/test_set_8_multi_cdf/{test_set_8_multi_cdf_expected_summary.json => test_set_8_multi_cdf_expected_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/test_set_allow_only_one_winner_per_round/{test_set_allow_only_one_winner_per_round_expected_extended_summary.csv => test_set_allow_only_one_winner_per_round_expected_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/test_set_allow_only_one_winner_per_round/{test_set_allow_only_one_winner_per_round_expected_summary.json => test_set_allow_only_one_winner_per_round_expected_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/test_set_multi_winner_fractional_threshold/{test_set_multi_winner_fractional_threshold_expected_extended_summary.csv => test_set_multi_winner_fractional_threshold_expected_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/test_set_multi_winner_fractional_threshold/{test_set_multi_winner_fractional_threshold_expected_summary.json => test_set_multi_winner_fractional_threshold_expected_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/test_set_multi_winner_whole_threshold/{test_set_multi_winner_whole_threshold_expected_extended_summary.csv => test_set_multi_winner_whole_threshold_expected_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/test_set_multi_winner_whole_threshold/{test_set_multi_winner_whole_threshold_expected_summary.json => test_set_multi_winner_whole_threshold_expected_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/test_set_overvote_delimiter/{test_set_overvote_delimiter_expected_extended_summary.csv => test_set_overvote_delimiter_expected_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/test_set_overvote_delimiter/{test_set_overvote_delimiter_expected_summary.json => test_set_overvote_delimiter_expected_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/test_set_treat_blank_as_undeclared_write_in/{test_set_treat_blank_as_undeclared_write_in_expected_extended_summary.csv => test_set_treat_blank_as_undeclared_write_in_expected_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/test_set_treat_blank_as_undeclared_write_in/{test_set_treat_blank_as_undeclared_write_in_expected_summary.json => test_set_treat_blank_as_undeclared_write_in_expected_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/tiebreak_generate_permutation_test/{tiebreak_generate_permutation_test_expected_extended_summary.csv => tiebreak_generate_permutation_test_expected_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/tiebreak_generate_permutation_test/{tiebreak_generate_permutation_test_expected_summary.json => tiebreak_generate_permutation_test_expected_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/tiebreak_previous_round_counts_then_random_test/{tiebreak_previous_round_counts_then_random_test_expected_extended_summary.csv => tiebreak_previous_round_counts_then_random_test_expected_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/tiebreak_previous_round_counts_then_random_test/{tiebreak_previous_round_counts_then_random_test_expected_summary.json => tiebreak_previous_round_counts_then_random_test_expected_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/tiebreak_seed_test/{tiebreak_seed_test_expected_extended_summary.csv => tiebreak_seed_test_expected_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/tiebreak_seed_test/{tiebreak_seed_test_expected_summary.json => tiebreak_seed_test_expected_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/tiebreak_use_permutation_in_config_test/{tiebreak_use_permutation_in_config_test_expected_extended_summary.csv => tiebreak_use_permutation_in_config_test_expected_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/tiebreak_use_permutation_in_config_test/{tiebreak_use_permutation_in_config_test_expected_summary.json => tiebreak_use_permutation_in_config_test_expected_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/unisyn_xml_cdf_city_chief_of_police/{unisyn_xml_cdf_city_chief_of_police_expected_extended_summary.csv => unisyn_xml_cdf_city_chief_of_police_expected_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/unisyn_xml_cdf_city_chief_of_police/{unisyn_xml_cdf_city_chief_of_police_expected_summary.json => unisyn_xml_cdf_city_chief_of_police_expected_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/unisyn_xml_cdf_city_coroner/{unisyn_xml_cdf_city_coroner_expected_extended_summary.csv => unisyn_xml_cdf_city_coroner_expected_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/unisyn_xml_cdf_city_coroner/{unisyn_xml_cdf_city_coroner_expected_summary.json => unisyn_xml_cdf_city_coroner_expected_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/unisyn_xml_cdf_city_council_member/{unisyn_xml_cdf_city_council_member_expected_extended_summary.csv => unisyn_xml_cdf_city_council_member_expected_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/unisyn_xml_cdf_city_council_member/{unisyn_xml_cdf_city_council_member_expected_summary.json => unisyn_xml_cdf_city_council_member_expected_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/unisyn_xml_cdf_city_mayor/{unisyn_xml_cdf_city_mayor_expected_extended_summary.csv => unisyn_xml_cdf_city_mayor_expected_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/unisyn_xml_cdf_city_mayor/{unisyn_xml_cdf_city_mayor_expected_summary.json => unisyn_xml_cdf_city_mayor_expected_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/unisyn_xml_cdf_city_tax_collector/{unisyn_xml_cdf_city_tax_collector_expected_extended_summary.csv => unisyn_xml_cdf_city_tax_collector_expected_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/unisyn_xml_cdf_city_tax_collector/{unisyn_xml_cdf_city_tax_collector_expected_summary.json => unisyn_xml_cdf_city_tax_collector_expected_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/unisyn_xml_cdf_county_coroner/{unisyn_xml_cdf_county_coroner_expected_extended_summary.csv => unisyn_xml_cdf_county_coroner_expected_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/unisyn_xml_cdf_county_coroner/{unisyn_xml_cdf_county_coroner_expected_summary.json => unisyn_xml_cdf_county_coroner_expected_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/unisyn_xml_cdf_county_sheriff/{unisyn_xml_cdf_county_sheriff_expected_extended_summary.csv => unisyn_xml_cdf_county_sheriff_expected_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/unisyn_xml_cdf_county_sheriff/{unisyn_xml_cdf_county_sheriff_expected_summary.json => unisyn_xml_cdf_county_sheriff_expected_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/uwi_cannot_win_test/{uwi_cannot_win_test_expected_extended_summary.csv => uwi_cannot_win_test_expected_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/uwi_cannot_win_test/{uwi_cannot_win_test_expected_summary.json => uwi_cannot_win_test_expected_detailed_report.json} (100%) diff --git a/src/main/java/network/brightspots/rcv/ResultsWriter.java b/src/main/java/network/brightspots/rcv/ResultsWriter.java index dfcabc37f..f00b2668f 100644 --- a/src/main/java/network/brightspots/rcv/ResultsWriter.java +++ b/src/main/java/network/brightspots/rcv/ResultsWriter.java @@ -90,9 +90,9 @@ class ResultsWriter { StatusForRound.INVALIDATED_BY_REPEATED_RANKING); public enum ResultType { - SUMMARY_REPORT("summary"/*"summary_report"*/, "csv"), - DETAILED_REPORT("extended_summary"/*"detailed_report"*/, "csv"), - JSON("summary", "json"), + SUMMARY_CSV("summary_report", "csv"), + DETAILED_CSV("detailed_report", "csv"), + DETAILED_JSON("detailed_report", "json"), CDF("cvr_cdf", "json"), RCTAB_CVR("rctab_cvr", "csv"); @@ -336,8 +336,8 @@ void generateBySliceSummaryFiles( String sliceId = entry.getKey(); RoundTallies roundTallies = entry.getValue(); TallyTransfers tallyTransfers = tallyTransfersBySlice.get(slice, sliceId); - ResultFile resultFileCsv = new ResultFile(ResultType.DETAILED_REPORT, slice, sliceId); - ResultFile resultFileJson = new ResultFile(ResultType.JSON, slice, sliceId); + ResultFile resultFileCsv = new ResultFile(ResultType.DETAILED_CSV, slice, sliceId); + ResultFile resultFileJson = new ResultFile(ResultType.DETAILED_JSON, slice, sliceId); generateSummaryCsv(roundTallies, candidateOrder, resultFileCsv); generateSummaryJson(roundTallies, tallyTransfers, resultFileJson); } @@ -364,8 +364,8 @@ private void generateSummaryCsv( RoundTallies roundTallies, List candidateOrder, ResultFile resultFile) throws IOException { - if (resultFile.resultType != ResultType.SUMMARY_REPORT - && resultFile.resultType != ResultType.DETAILED_REPORT) { + if (resultFile.resultType != ResultType.SUMMARY_CSV + && resultFile.resultType != ResultType.DETAILED_CSV) { throw new IllegalArgumentException("ResultFile provided non-CSV type " + resultFile.resultType); } @@ -473,7 +473,7 @@ private void generateSummaryCsv( csvPrinter.println(); } - if (resultFile.resultType == ResultType.DETAILED_REPORT) { + if (resultFile.resultType == ResultType.DETAILED_CSV) { for (StatusForRound status : STATUSES_TO_PRINT) { csvPrinter.print(status.getTitleCaseKey()); @@ -656,9 +656,9 @@ void generateOverallSummaryFiles( RoundTallies roundTallies, TallyTransfers tallyTransfers, List candidateOrder) throws IOException { - generateSummaryCsv(roundTallies, candidateOrder, new ResultFile(ResultType.SUMMARY_REPORT)); - generateSummaryCsv(roundTallies, candidateOrder, new ResultFile(ResultType.DETAILED_REPORT)); - generateSummaryJson(roundTallies, tallyTransfers, new ResultFile(ResultType.JSON)); + generateSummaryCsv(roundTallies, candidateOrder, new ResultFile(ResultType.SUMMARY_CSV)); + generateSummaryCsv(roundTallies, candidateOrder, new ResultFile(ResultType.DETAILED_CSV)); + generateSummaryJson(roundTallies, tallyTransfers, new ResultFile(ResultType.DETAILED_JSON)); } // Write CastVoteRecords for the specified contest to the provided folder, diff --git a/src/test/java/network/brightspots/rcv/TabulatorTests.java b/src/test/java/network/brightspots/rcv/TabulatorTests.java index 8141f9406..3e19030a0 100644 --- a/src/test/java/network/brightspots/rcv/TabulatorTests.java +++ b/src/test/java/network/brightspots/rcv/TabulatorTests.java @@ -241,8 +241,8 @@ private static void runTabulationTest(String stem, String expectedException, int numSlicedFilesChecked = 0; for (ContestConfig.TabulateBySlice slice : config.enabledSlices()) { for (String sliceName : session.loadSliceNamesFromCvrs(slice, config)) { - ResultFile resultFileJson = new ResultFile(ResultType.JSON, slice, sliceName); - ResultFile resultFileCsv = new ResultFile(ResultType.DETAILED_REPORT, slice, sliceName); + ResultFile resultFileJson = new ResultFile(ResultType.DETAILED_JSON, slice, sliceName); + ResultFile resultFileCsv = new ResultFile(ResultType.DETAILED_CSV, slice, sliceName); if (compareFiles(config, stem, resultFileJson, timestampString, null, true)) { numSlicedFilesChecked++; } @@ -329,8 +329,8 @@ private static void cleanOutputFolder(TabulatorSession session) { private static void compareFiles( ContestConfig config, String stem, String timestampString, Integer sequentialId) { - compareFiles(config, stem, ResultType.JSON, timestampString, sequentialId, false); - compareFiles(config, stem, ResultType.DETAILED_REPORT, timestampString, sequentialId, false); + compareFiles(config, stem, ResultType.DETAILED_JSON, timestampString, sequentialId, false); + compareFiles(config, stem, ResultType.DETAILED_CSV, timestampString, sequentialId, false); compareExtendedSummaryToSummary(config, timestampString, sequentialId); if (config.isGenerateCdfJsonEnabled()) { compareFiles(config, stem, ResultType.CDF, timestampString, sequentialId, false); @@ -395,9 +395,9 @@ private static boolean compareFiles( private static void compareExtendedSummaryToSummary( ContestConfig config, String timestampString, Integer sequentialId) { String dir = config.getOutputDirectory(); - String summaryPath = new ResultFile(ResultType.SUMMARY_REPORT).getPath( + String summaryPath = new ResultFile(ResultType.SUMMARY_CSV).getPath( dir, timestampString, sequentialId).toAbsolutePath().toString(); - String detailedPath = new ResultFile(ResultType.DETAILED_REPORT).getPath( + String detailedPath = new ResultFile(ResultType.DETAILED_CSV).getPath( dir, timestampString, sequentialId).toAbsolutePath().toString(); try (BufferedReader brSummary = new BufferedReader(new FileReader(summaryPath, UTF_8)); diff --git a/src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_mayor/2013_minneapolis_mayor_expected_MINNEAPOLIS_W-13_P-09_precinct_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_mayor/2013_minneapolis_mayor_expected_MINNEAPOLIS_W-13_P-09_precinct_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_mayor/2013_minneapolis_mayor_expected_MINNEAPOLIS_W-13_P-09_precinct_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_mayor/2013_minneapolis_mayor_expected_MINNEAPOLIS_W-13_P-09_precinct_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_mayor/2013_minneapolis_mayor_expected_MINNEAPOLIS_W-13_P-09_precinct_summary.json b/src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_mayor/2013_minneapolis_mayor_expected_MINNEAPOLIS_W-13_P-09_precinct_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_mayor/2013_minneapolis_mayor_expected_MINNEAPOLIS_W-13_P-09_precinct_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_mayor/2013_minneapolis_mayor_expected_MINNEAPOLIS_W-13_P-09_precinct_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_mayor/2013_minneapolis_mayor_expected_MINNEAPOLIS_W-1_P-01_precinct_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_mayor/2013_minneapolis_mayor_expected_MINNEAPOLIS_W-1_P-01_precinct_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_mayor/2013_minneapolis_mayor_expected_MINNEAPOLIS_W-1_P-01_precinct_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_mayor/2013_minneapolis_mayor_expected_MINNEAPOLIS_W-1_P-01_precinct_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_mayor/2013_minneapolis_mayor_expected_MINNEAPOLIS_W-1_P-01_precinct_summary.json b/src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_mayor/2013_minneapolis_mayor_expected_MINNEAPOLIS_W-1_P-01_precinct_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_mayor/2013_minneapolis_mayor_expected_MINNEAPOLIS_W-1_P-01_precinct_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_mayor/2013_minneapolis_mayor_expected_MINNEAPOLIS_W-1_P-01_precinct_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_mayor/2013_minneapolis_mayor_expected_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_mayor/2013_minneapolis_mayor_expected_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_mayor/2013_minneapolis_mayor_expected_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_mayor/2013_minneapolis_mayor_expected_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_mayor/2013_minneapolis_mayor_expected_summary.json b/src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_mayor/2013_minneapolis_mayor_expected_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_mayor/2013_minneapolis_mayor_expected_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_mayor/2013_minneapolis_mayor_expected_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_mayor_scale/2013_minneapolis_mayor_scale_expected_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_mayor_scale/2013_minneapolis_mayor_scale_expected_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_mayor_scale/2013_minneapolis_mayor_scale_expected_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_mayor_scale/2013_minneapolis_mayor_scale_expected_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_mayor_scale/2013_minneapolis_mayor_scale_expected_summary.json b/src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_mayor_scale/2013_minneapolis_mayor_scale_expected_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_mayor_scale/2013_minneapolis_mayor_scale_expected_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_mayor_scale/2013_minneapolis_mayor_scale_expected_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_park/2013_minneapolis_park_expected_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_park/2013_minneapolis_park_expected_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_park/2013_minneapolis_park_expected_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_park/2013_minneapolis_park_expected_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_park/2013_minneapolis_park_expected_summary.json b/src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_park/2013_minneapolis_park_expected_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_park/2013_minneapolis_park_expected_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_park/2013_minneapolis_park_expected_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_park_bottoms_up/2013_minneapolis_park_bottoms_up_expected_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_park_bottoms_up/2013_minneapolis_park_bottoms_up_expected_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_park_bottoms_up/2013_minneapolis_park_bottoms_up_expected_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_park_bottoms_up/2013_minneapolis_park_bottoms_up_expected_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_park_bottoms_up/2013_minneapolis_park_bottoms_up_expected_summary.json b/src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_park_bottoms_up/2013_minneapolis_park_bottoms_up_expected_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_park_bottoms_up/2013_minneapolis_park_bottoms_up_expected_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_park_bottoms_up/2013_minneapolis_park_bottoms_up_expected_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_park_hare/2013_minneapolis_park_hare_expected_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_park_hare/2013_minneapolis_park_hare_expected_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_park_hare/2013_minneapolis_park_hare_expected_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_park_hare/2013_minneapolis_park_hare_expected_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_park_hare/2013_minneapolis_park_hare_expected_summary.json b/src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_park_hare/2013_minneapolis_park_hare_expected_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_park_hare/2013_minneapolis_park_hare_expected_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_park_hare/2013_minneapolis_park_hare_expected_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_park_sequential/2013_minneapolis_park_sequential_1_expected_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_park_sequential/2013_minneapolis_park_sequential_1_expected_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_park_sequential/2013_minneapolis_park_sequential_1_expected_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_park_sequential/2013_minneapolis_park_sequential_1_expected_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_park_sequential/2013_minneapolis_park_sequential_1_expected_summary.json b/src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_park_sequential/2013_minneapolis_park_sequential_1_expected_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_park_sequential/2013_minneapolis_park_sequential_1_expected_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_park_sequential/2013_minneapolis_park_sequential_1_expected_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_park_sequential/2013_minneapolis_park_sequential_2_expected_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_park_sequential/2013_minneapolis_park_sequential_2_expected_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_park_sequential/2013_minneapolis_park_sequential_2_expected_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_park_sequential/2013_minneapolis_park_sequential_2_expected_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_park_sequential/2013_minneapolis_park_sequential_2_expected_summary.json b/src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_park_sequential/2013_minneapolis_park_sequential_2_expected_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_park_sequential/2013_minneapolis_park_sequential_2_expected_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_park_sequential/2013_minneapolis_park_sequential_2_expected_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_park_sequential/2013_minneapolis_park_sequential_3_expected_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_park_sequential/2013_minneapolis_park_sequential_3_expected_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_park_sequential/2013_minneapolis_park_sequential_3_expected_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_park_sequential/2013_minneapolis_park_sequential_3_expected_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_park_sequential/2013_minneapolis_park_sequential_3_expected_summary.json b/src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_park_sequential/2013_minneapolis_park_sequential_3_expected_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_park_sequential/2013_minneapolis_park_sequential_3_expected_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_park_sequential/2013_minneapolis_park_sequential_3_expected_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/2015_portland_mayor/2015_portland_mayor_expected_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/2015_portland_mayor/2015_portland_mayor_expected_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/2015_portland_mayor/2015_portland_mayor_expected_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/2015_portland_mayor/2015_portland_mayor_expected_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/2015_portland_mayor/2015_portland_mayor_expected_summary.json b/src/test/resources/network/brightspots/rcv/test_data/2015_portland_mayor/2015_portland_mayor_expected_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/2015_portland_mayor/2015_portland_mayor_expected_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/2015_portland_mayor/2015_portland_mayor_expected_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/2015_portland_mayor_codes/2015_portland_mayor_codes_expected_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/2015_portland_mayor_codes/2015_portland_mayor_codes_expected_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/2015_portland_mayor_codes/2015_portland_mayor_codes_expected_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/2015_portland_mayor_codes/2015_portland_mayor_codes_expected_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/2015_portland_mayor_codes/2015_portland_mayor_codes_expected_summary.json b/src/test/resources/network/brightspots/rcv/test_data/2015_portland_mayor_codes/2015_portland_mayor_codes_expected_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/2015_portland_mayor_codes/2015_portland_mayor_codes_expected_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/2015_portland_mayor_codes/2015_portland_mayor_codes_expected_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/2017_minneapolis_mayor/2017_minneapolis_mayor_expected_MINNEAPOLIS_W-13_P-13_precinct_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/2017_minneapolis_mayor/2017_minneapolis_mayor_expected_MINNEAPOLIS_W-13_P-13_precinct_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/2017_minneapolis_mayor/2017_minneapolis_mayor_expected_MINNEAPOLIS_W-13_P-13_precinct_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/2017_minneapolis_mayor/2017_minneapolis_mayor_expected_MINNEAPOLIS_W-13_P-13_precinct_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/2017_minneapolis_mayor/2017_minneapolis_mayor_expected_MINNEAPOLIS_W-13_P-13_precinct_summary.json b/src/test/resources/network/brightspots/rcv/test_data/2017_minneapolis_mayor/2017_minneapolis_mayor_expected_MINNEAPOLIS_W-13_P-13_precinct_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/2017_minneapolis_mayor/2017_minneapolis_mayor_expected_MINNEAPOLIS_W-13_P-13_precinct_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/2017_minneapolis_mayor/2017_minneapolis_mayor_expected_MINNEAPOLIS_W-13_P-13_precinct_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/2017_minneapolis_mayor/2017_minneapolis_mayor_expected_MINNEAPOLIS_W-1_P-01_precinct_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/2017_minneapolis_mayor/2017_minneapolis_mayor_expected_MINNEAPOLIS_W-1_P-01_precinct_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/2017_minneapolis_mayor/2017_minneapolis_mayor_expected_MINNEAPOLIS_W-1_P-01_precinct_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/2017_minneapolis_mayor/2017_minneapolis_mayor_expected_MINNEAPOLIS_W-1_P-01_precinct_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/2017_minneapolis_mayor/2017_minneapolis_mayor_expected_MINNEAPOLIS_W-1_P-01_precinct_summary.json b/src/test/resources/network/brightspots/rcv/test_data/2017_minneapolis_mayor/2017_minneapolis_mayor_expected_MINNEAPOLIS_W-1_P-01_precinct_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/2017_minneapolis_mayor/2017_minneapolis_mayor_expected_MINNEAPOLIS_W-1_P-01_precinct_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/2017_minneapolis_mayor/2017_minneapolis_mayor_expected_MINNEAPOLIS_W-1_P-01_precinct_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/2017_minneapolis_mayor/2017_minneapolis_mayor_expected_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/2017_minneapolis_mayor/2017_minneapolis_mayor_expected_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/2017_minneapolis_mayor/2017_minneapolis_mayor_expected_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/2017_minneapolis_mayor/2017_minneapolis_mayor_expected_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/2017_minneapolis_mayor/2017_minneapolis_mayor_expected_summary.json b/src/test/resources/network/brightspots/rcv/test_data/2017_minneapolis_mayor/2017_minneapolis_mayor_expected_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/2017_minneapolis_mayor/2017_minneapolis_mayor_expected_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/2017_minneapolis_mayor/2017_minneapolis_mayor_expected_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/2018_maine_governor_primary/2018_maine_governor_primary_expected_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/2018_maine_governor_primary/2018_maine_governor_primary_expected_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/2018_maine_governor_primary/2018_maine_governor_primary_expected_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/2018_maine_governor_primary/2018_maine_governor_primary_expected_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/2018_maine_governor_primary/2018_maine_governor_primary_expected_summary.json b/src/test/resources/network/brightspots/rcv/test_data/2018_maine_governor_primary/2018_maine_governor_primary_expected_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/2018_maine_governor_primary/2018_maine_governor_primary_expected_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/2018_maine_governor_primary/2018_maine_governor_primary_expected_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/aliases_cdf_json/aliases_cdf_json_expected_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/aliases_cdf_json/aliases_cdf_json_expected_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/aliases_cdf_json/aliases_cdf_json_expected_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/aliases_cdf_json/aliases_cdf_json_expected_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/aliases_cdf_json/aliases_cdf_json_expected_summary.json b/src/test/resources/network/brightspots/rcv/test_data/aliases_cdf_json/aliases_cdf_json_expected_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/aliases_cdf_json/aliases_cdf_json_expected_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/aliases_cdf_json/aliases_cdf_json_expected_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/aliases_ess_xlsx/aliases_ess_xlsx_expected_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/aliases_ess_xlsx/aliases_ess_xlsx_expected_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/aliases_ess_xlsx/aliases_ess_xlsx_expected_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/aliases_ess_xlsx/aliases_ess_xlsx_expected_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/aliases_ess_xlsx/aliases_ess_xlsx_expected_summary.json b/src/test/resources/network/brightspots/rcv/test_data/aliases_ess_xlsx/aliases_ess_xlsx_expected_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/aliases_ess_xlsx/aliases_ess_xlsx_expected_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/aliases_ess_xlsx/aliases_ess_xlsx_expected_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/batch_example/batch_example_expected_MINNEAPOLIS_W-1_P-02_batch_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/batch_example/batch_example_expected_MINNEAPOLIS_W-1_P-02_batch_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/batch_example/batch_example_expected_MINNEAPOLIS_W-1_P-02_batch_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/batch_example/batch_example_expected_MINNEAPOLIS_W-1_P-02_batch_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/batch_example/batch_example_expected_MINNEAPOLIS_W-1_P-04_batch_summary.json b/src/test/resources/network/brightspots/rcv/test_data/batch_example/batch_example_expected_MINNEAPOLIS_W-1_P-04_batch_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/batch_example/batch_example_expected_MINNEAPOLIS_W-1_P-04_batch_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/batch_example/batch_example_expected_MINNEAPOLIS_W-1_P-04_batch_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/batch_example/batch_example_expected_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/batch_example/batch_example_expected_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/batch_example/batch_example_expected_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/batch_example/batch_example_expected_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/batch_example/batch_example_expected_summary.json b/src/test/resources/network/brightspots/rcv/test_data/batch_example/batch_example_expected_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/batch_example/batch_example_expected_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/batch_example/batch_example_expected_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/clear_ballot_kansas_primary/clear_ballot_kansas_primary_expected_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/clear_ballot_kansas_primary/clear_ballot_kansas_primary_expected_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/clear_ballot_kansas_primary/clear_ballot_kansas_primary_expected_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/clear_ballot_kansas_primary/clear_ballot_kansas_primary_expected_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/clear_ballot_kansas_primary/clear_ballot_kansas_primary_expected_summary.json b/src/test/resources/network/brightspots/rcv/test_data/clear_ballot_kansas_primary/clear_ballot_kansas_primary_expected_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/clear_ballot_kansas_primary/clear_ballot_kansas_primary_expected_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/clear_ballot_kansas_primary/clear_ballot_kansas_primary_expected_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/clear_ballot_with_inline_comma/clear_ballot_with_inline_comma_expected_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/clear_ballot_with_inline_comma/clear_ballot_with_inline_comma_expected_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/clear_ballot_with_inline_comma/clear_ballot_with_inline_comma_expected_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/clear_ballot_with_inline_comma/clear_ballot_with_inline_comma_expected_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/clear_ballot_with_inline_comma/clear_ballot_with_inline_comma_expected_summary.json b/src/test/resources/network/brightspots/rcv/test_data/clear_ballot_with_inline_comma/clear_ballot_with_inline_comma_expected_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/clear_ballot_with_inline_comma/clear_ballot_with_inline_comma_expected_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/clear_ballot_with_inline_comma/clear_ballot_with_inline_comma_expected_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/continue_tabulation_test/continue_tabulation_test_expected_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/continue_tabulation_test/continue_tabulation_test_expected_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/continue_tabulation_test/continue_tabulation_test_expected_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/continue_tabulation_test/continue_tabulation_test_expected_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/continue_tabulation_test/continue_tabulation_test_expected_summary.json b/src/test/resources/network/brightspots/rcv/test_data/continue_tabulation_test/continue_tabulation_test_expected_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/continue_tabulation_test/continue_tabulation_test_expected_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/continue_tabulation_test/continue_tabulation_test_expected_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/continue_until_two_with_batch_elimination_test/continue_until_two_with_batch_elimination_test_expected_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/continue_until_two_with_batch_elimination_test/continue_until_two_with_batch_elimination_test_expected_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/continue_until_two_with_batch_elimination_test/continue_until_two_with_batch_elimination_test_expected_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/continue_until_two_with_batch_elimination_test/continue_until_two_with_batch_elimination_test_expected_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/continue_until_two_with_batch_elimination_test/continue_until_two_with_batch_elimination_test_expected_summary.json b/src/test/resources/network/brightspots/rcv/test_data/continue_until_two_with_batch_elimination_test/continue_until_two_with_batch_elimination_test_expected_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/continue_until_two_with_batch_elimination_test/continue_until_two_with_batch_elimination_test_expected_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/continue_until_two_with_batch_elimination_test/continue_until_two_with_batch_elimination_test_expected_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/csv_missing_header_test/csv_missing_header_test_expected_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/csv_missing_header_test/csv_missing_header_test_expected_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/csv_missing_header_test/csv_missing_header_test_expected_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/csv_missing_header_test/csv_missing_header_test_expected_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/csv_missing_header_test/csv_missing_header_test_expected_summary.json b/src/test/resources/network/brightspots/rcv/test_data/csv_missing_header_test/csv_missing_header_test_expected_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/csv_missing_header_test/csv_missing_header_test_expected_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/csv_missing_header_test/csv_missing_header_test_expected_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/dominion_alaska/dominion_alaska_expected_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/dominion_alaska/dominion_alaska_expected_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/dominion_alaska/dominion_alaska_expected_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/dominion_alaska/dominion_alaska_expected_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/dominion_alaska/dominion_alaska_expected_summary.json b/src/test/resources/network/brightspots/rcv/test_data/dominion_alaska/dominion_alaska_expected_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/dominion_alaska/dominion_alaska_expected_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/dominion_alaska/dominion_alaska_expected_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/dominion_kansas/dominion_kansas_expected_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/dominion_kansas/dominion_kansas_expected_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/dominion_kansas/dominion_kansas_expected_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/dominion_kansas/dominion_kansas_expected_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/dominion_kansas/dominion_kansas_expected_summary.json b/src/test/resources/network/brightspots/rcv/test_data/dominion_kansas/dominion_kansas_expected_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/dominion_kansas/dominion_kansas_expected_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/dominion_kansas/dominion_kansas_expected_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/dominion_multi_file/dominion_multi_file_expected_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/dominion_multi_file/dominion_multi_file_expected_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/dominion_multi_file/dominion_multi_file_expected_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/dominion_multi_file/dominion_multi_file_expected_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/dominion_multi_file/dominion_multi_file_expected_summary.json b/src/test/resources/network/brightspots/rcv/test_data/dominion_multi_file/dominion_multi_file_expected_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/dominion_multi_file/dominion_multi_file_expected_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/dominion_multi_file/dominion_multi_file_expected_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/dominion_no_precinct_data/dominion_no_precinct_data_expected_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/dominion_no_precinct_data/dominion_no_precinct_data_expected_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/dominion_no_precinct_data/dominion_no_precinct_data_expected_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/dominion_no_precinct_data/dominion_no_precinct_data_expected_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/dominion_no_precinct_data/dominion_no_precinct_data_expected_summary.json b/src/test/resources/network/brightspots/rcv/test_data/dominion_no_precinct_data/dominion_no_precinct_data_expected_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/dominion_no_precinct_data/dominion_no_precinct_data_expected_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/dominion_no_precinct_data/dominion_no_precinct_data_expected_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/dominion_wyoming/dominion_wyoming_expected_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/dominion_wyoming/dominion_wyoming_expected_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/dominion_wyoming/dominion_wyoming_expected_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/dominion_wyoming/dominion_wyoming_expected_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/dominion_wyoming/dominion_wyoming_expected_summary.json b/src/test/resources/network/brightspots/rcv/test_data/dominion_wyoming/dominion_wyoming_expected_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/dominion_wyoming/dominion_wyoming_expected_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/dominion_wyoming/dominion_wyoming_expected_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/duplicate_test/duplicate_test_expected_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/duplicate_test/duplicate_test_expected_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/duplicate_test/duplicate_test_expected_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/duplicate_test/duplicate_test_expected_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/duplicate_test/duplicate_test_expected_summary.json b/src/test/resources/network/brightspots/rcv/test_data/duplicate_test/duplicate_test_expected_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/duplicate_test/duplicate_test_expected_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/duplicate_test/duplicate_test_expected_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/excluded_test/excluded_test_expected_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/excluded_test/excluded_test_expected_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/excluded_test/excluded_test_expected_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/excluded_test/excluded_test_expected_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/excluded_test/excluded_test_expected_summary.json b/src/test/resources/network/brightspots/rcv/test_data/excluded_test/excluded_test_expected_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/excluded_test/excluded_test_expected_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/excluded_test/excluded_test_expected_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/exhaust_if_multiple_continuing/exhaust_if_multiple_continuing_expected_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/exhaust_if_multiple_continuing/exhaust_if_multiple_continuing_expected_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/exhaust_if_multiple_continuing/exhaust_if_multiple_continuing_expected_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/exhaust_if_multiple_continuing/exhaust_if_multiple_continuing_expected_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/exhaust_if_multiple_continuing/exhaust_if_multiple_continuing_expected_summary.json b/src/test/resources/network/brightspots/rcv/test_data/exhaust_if_multiple_continuing/exhaust_if_multiple_continuing_expected_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/exhaust_if_multiple_continuing/exhaust_if_multiple_continuing_expected_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/exhaust_if_multiple_continuing/exhaust_if_multiple_continuing_expected_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/first_round_determines_threshold_test/first_round_determines_threshold_test_expected_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/first_round_determines_threshold_test/first_round_determines_threshold_test_expected_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/first_round_determines_threshold_test/first_round_determines_threshold_test_expected_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/first_round_determines_threshold_test/first_round_determines_threshold_test_expected_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/first_round_determines_threshold_test/first_round_determines_threshold_test_expected_summary.json b/src/test/resources/network/brightspots/rcv/test_data/first_round_determines_threshold_test/first_round_determines_threshold_test_expected_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/first_round_determines_threshold_test/first_round_determines_threshold_test_expected_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/first_round_determines_threshold_test/first_round_determines_threshold_test_expected_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/first_round_determines_threshold_tiebreaker_test/first_round_determines_threshold_tiebreaker_test_expected_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/first_round_determines_threshold_tiebreaker_test/first_round_determines_threshold_tiebreaker_test_expected_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/first_round_determines_threshold_tiebreaker_test/first_round_determines_threshold_tiebreaker_test_expected_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/first_round_determines_threshold_tiebreaker_test/first_round_determines_threshold_tiebreaker_test_expected_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/first_round_determines_threshold_tiebreaker_test/first_round_determines_threshold_tiebreaker_test_expected_summary.json b/src/test/resources/network/brightspots/rcv/test_data/first_round_determines_threshold_tiebreaker_test/first_round_determines_threshold_tiebreaker_test_expected_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/first_round_determines_threshold_tiebreaker_test/first_round_determines_threshold_tiebreaker_test_expected_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/first_round_determines_threshold_tiebreaker_test/first_round_determines_threshold_tiebreaker_test_expected_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/generic_csv_test/generic_csv_test_expected_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/generic_csv_test/generic_csv_test_expected_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/generic_csv_test/generic_csv_test_expected_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/generic_csv_test/generic_csv_test_expected_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/generic_csv_test/generic_csv_test_expected_summary.json b/src/test/resources/network/brightspots/rcv/test_data/generic_csv_test/generic_csv_test_expected_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/generic_csv_test/generic_csv_test_expected_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/generic_csv_test/generic_csv_test_expected_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/hart_cedar_park_school_board/hart_cedar_park_school_board_expected_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/hart_cedar_park_school_board/hart_cedar_park_school_board_expected_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/hart_cedar_park_school_board/hart_cedar_park_school_board_expected_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/hart_cedar_park_school_board/hart_cedar_park_school_board_expected_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/hart_cedar_park_school_board/hart_cedar_park_school_board_expected_summary.json b/src/test/resources/network/brightspots/rcv/test_data/hart_cedar_park_school_board/hart_cedar_park_school_board_expected_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/hart_cedar_park_school_board/hart_cedar_park_school_board_expected_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/hart_cedar_park_school_board/hart_cedar_park_school_board_expected_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/hart_travis_county_officers/hart_travis_county_officers_expected_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/hart_travis_county_officers/hart_travis_county_officers_expected_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/hart_travis_county_officers/hart_travis_county_officers_expected_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/hart_travis_county_officers/hart_travis_county_officers_expected_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/hart_travis_county_officers/hart_travis_county_officers_expected_summary.json b/src/test/resources/network/brightspots/rcv/test_data/hart_travis_county_officers/hart_travis_county_officers_expected_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/hart_travis_county_officers/hart_travis_county_officers_expected_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/hart_travis_county_officers/hart_travis_county_officers_expected_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/minimum_threshold_test/minimum_threshold_test_expected_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/minimum_threshold_test/minimum_threshold_test_expected_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/minimum_threshold_test/minimum_threshold_test_expected_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/minimum_threshold_test/minimum_threshold_test_expected_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/minimum_threshold_test/minimum_threshold_test_expected_summary.json b/src/test/resources/network/brightspots/rcv/test_data/minimum_threshold_test/minimum_threshold_test_expected_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/minimum_threshold_test/minimum_threshold_test_expected_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/minimum_threshold_test/minimum_threshold_test_expected_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/minneapolis_multi_seat_threshold/minneapolis_multi_seat_threshold_expected_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/minneapolis_multi_seat_threshold/minneapolis_multi_seat_threshold_expected_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/minneapolis_multi_seat_threshold/minneapolis_multi_seat_threshold_expected_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/minneapolis_multi_seat_threshold/minneapolis_multi_seat_threshold_expected_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/minneapolis_multi_seat_threshold/minneapolis_multi_seat_threshold_expected_summary.json b/src/test/resources/network/brightspots/rcv/test_data/minneapolis_multi_seat_threshold/minneapolis_multi_seat_threshold_expected_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/minneapolis_multi_seat_threshold/minneapolis_multi_seat_threshold_expected_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/minneapolis_multi_seat_threshold/minneapolis_multi_seat_threshold_expected_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/minneapolis_multi_seat_threshold/minneapolis_multi_seat_threshold_expected_pc1_precinct_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/minneapolis_multi_seat_threshold/minneapolis_multi_seat_threshold_expected_pc1_precinct_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/minneapolis_multi_seat_threshold/minneapolis_multi_seat_threshold_expected_pc1_precinct_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/minneapolis_multi_seat_threshold/minneapolis_multi_seat_threshold_expected_pc1_precinct_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/minneapolis_multi_seat_threshold/minneapolis_multi_seat_threshold_expected_pc2_precinct_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/minneapolis_multi_seat_threshold/minneapolis_multi_seat_threshold_expected_pc2_precinct_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/minneapolis_multi_seat_threshold/minneapolis_multi_seat_threshold_expected_pc2_precinct_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/minneapolis_multi_seat_threshold/minneapolis_multi_seat_threshold_expected_pc2_precinct_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/minneapolis_multi_seat_threshold/minneapolis_multi_seat_threshold_expected_pc2_precinct_summary.json b/src/test/resources/network/brightspots/rcv/test_data/minneapolis_multi_seat_threshold/minneapolis_multi_seat_threshold_expected_pc2_precinct_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/minneapolis_multi_seat_threshold/minneapolis_multi_seat_threshold_expected_pc2_precinct_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/minneapolis_multi_seat_threshold/minneapolis_multi_seat_threshold_expected_pc2_precinct_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/missing_precinct_example/missing_precinct_example_expected_MINNEAPOLIS_W-13_P-13_precinct_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/missing_precinct_example/missing_precinct_example_expected_MINNEAPOLIS_W-13_P-13_precinct_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/missing_precinct_example/missing_precinct_example_expected_MINNEAPOLIS_W-13_P-13_precinct_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/missing_precinct_example/missing_precinct_example_expected_MINNEAPOLIS_W-13_P-13_precinct_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/missing_precinct_example/missing_precinct_example_expected_MINNEAPOLIS_W-13_P-13_precinct_summary.json b/src/test/resources/network/brightspots/rcv/test_data/missing_precinct_example/missing_precinct_example_expected_MINNEAPOLIS_W-13_P-13_precinct_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/missing_precinct_example/missing_precinct_example_expected_MINNEAPOLIS_W-13_P-13_precinct_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/missing_precinct_example/missing_precinct_example_expected_MINNEAPOLIS_W-13_P-13_precinct_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/missing_precinct_example/missing_precinct_example_expected_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/missing_precinct_example/missing_precinct_example_expected_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/missing_precinct_example/missing_precinct_example_expected_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/missing_precinct_example/missing_precinct_example_expected_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/missing_precinct_example/missing_precinct_example_expected_summary.json b/src/test/resources/network/brightspots/rcv/test_data/missing_precinct_example/missing_precinct_example_expected_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/missing_precinct_example/missing_precinct_example_expected_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/missing_precinct_example/missing_precinct_example_expected_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/missing_precinct_example/missing_precinct_example_expected_missing_precinct_id_precinct_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/missing_precinct_example/missing_precinct_example_expected_missing_precinct_id_precinct_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/missing_precinct_example/missing_precinct_example_expected_missing_precinct_id_precinct_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/missing_precinct_example/missing_precinct_example_expected_missing_precinct_id_precinct_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/missing_precinct_example/missing_precinct_example_expected_missing_precinct_id_precinct_summary.json b/src/test/resources/network/brightspots/rcv/test_data/missing_precinct_example/missing_precinct_example_expected_missing_precinct_id_precinct_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/missing_precinct_example/missing_precinct_example_expected_missing_precinct_id_precinct_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/missing_precinct_example/missing_precinct_example_expected_missing_precinct_id_precinct_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/more_winners_than_candidates/more_winners_than_candidates_expected_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/more_winners_than_candidates/more_winners_than_candidates_expected_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/more_winners_than_candidates/more_winners_than_candidates_expected_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/more_winners_than_candidates/more_winners_than_candidates_expected_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/more_winners_than_candidates/more_winners_than_candidates_expected_summary.json b/src/test/resources/network/brightspots/rcv/test_data/more_winners_than_candidates/more_winners_than_candidates_expected_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/more_winners_than_candidates/more_winners_than_candidates_expected_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/more_winners_than_candidates/more_winners_than_candidates_expected_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/multi_seat_bottoms_up_with_threshold/multi_seat_bottoms_up_with_threshold_expected_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/multi_seat_bottoms_up_with_threshold/multi_seat_bottoms_up_with_threshold_expected_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/multi_seat_bottoms_up_with_threshold/multi_seat_bottoms_up_with_threshold_expected_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/multi_seat_bottoms_up_with_threshold/multi_seat_bottoms_up_with_threshold_expected_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/multi_seat_bottoms_up_with_threshold/multi_seat_bottoms_up_with_threshold_expected_summary.json b/src/test/resources/network/brightspots/rcv/test_data/multi_seat_bottoms_up_with_threshold/multi_seat_bottoms_up_with_threshold_expected_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/multi_seat_bottoms_up_with_threshold/multi_seat_bottoms_up_with_threshold_expected_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/multi_seat_bottoms_up_with_threshold/multi_seat_bottoms_up_with_threshold_expected_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/multi_seat_uwi_test/multi_seat_uwi_test_expected_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/multi_seat_uwi_test/multi_seat_uwi_test_expected_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/multi_seat_uwi_test/multi_seat_uwi_test_expected_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/multi_seat_uwi_test/multi_seat_uwi_test_expected_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/multi_seat_uwi_test/multi_seat_uwi_test_expected_summary.json b/src/test/resources/network/brightspots/rcv/test_data/multi_seat_uwi_test/multi_seat_uwi_test_expected_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/multi_seat_uwi_test/multi_seat_uwi_test_expected_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/multi_seat_uwi_test/multi_seat_uwi_test_expected_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/nist_xml_cdf_2/nist_xml_cdf_2_expected_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/nist_xml_cdf_2/nist_xml_cdf_2_expected_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/nist_xml_cdf_2/nist_xml_cdf_2_expected_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/nist_xml_cdf_2/nist_xml_cdf_2_expected_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/nist_xml_cdf_2/nist_xml_cdf_2_expected_summary.json b/src/test/resources/network/brightspots/rcv/test_data/nist_xml_cdf_2/nist_xml_cdf_2_expected_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/nist_xml_cdf_2/nist_xml_cdf_2_expected_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/nist_xml_cdf_2/nist_xml_cdf_2_expected_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/precinct_example/precinct_example_expected_MINNEAPOLIS_W-1_P-02_precinct_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/precinct_example/precinct_example_expected_MINNEAPOLIS_W-1_P-02_precinct_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/precinct_example/precinct_example_expected_MINNEAPOLIS_W-1_P-02_precinct_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/precinct_example/precinct_example_expected_MINNEAPOLIS_W-1_P-02_precinct_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/precinct_example/precinct_example_expected_MINNEAPOLIS_W-1_P-02_precinct_summary.json b/src/test/resources/network/brightspots/rcv/test_data/precinct_example/precinct_example_expected_MINNEAPOLIS_W-1_P-02_precinct_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/precinct_example/precinct_example_expected_MINNEAPOLIS_W-1_P-02_precinct_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/precinct_example/precinct_example_expected_MINNEAPOLIS_W-1_P-02_precinct_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/precinct_example/precinct_example_expected_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/precinct_example/precinct_example_expected_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/precinct_example/precinct_example_expected_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/precinct_example/precinct_example_expected_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/precinct_example/precinct_example_expected_summary.json b/src/test/resources/network/brightspots/rcv/test_data/precinct_example/precinct_example_expected_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/precinct_example/precinct_example_expected_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/precinct_example/precinct_example_expected_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/sequential_with_batch/sequential_with_batch_1_expected_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/sequential_with_batch/sequential_with_batch_1_expected_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/sequential_with_batch/sequential_with_batch_1_expected_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/sequential_with_batch/sequential_with_batch_1_expected_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/sequential_with_batch/sequential_with_batch_1_expected_summary.json b/src/test/resources/network/brightspots/rcv/test_data/sequential_with_batch/sequential_with_batch_1_expected_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/sequential_with_batch/sequential_with_batch_1_expected_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/sequential_with_batch/sequential_with_batch_1_expected_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/sequential_with_batch/sequential_with_batch_2_expected_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/sequential_with_batch/sequential_with_batch_2_expected_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/sequential_with_batch/sequential_with_batch_2_expected_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/sequential_with_batch/sequential_with_batch_2_expected_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/sequential_with_batch/sequential_with_batch_2_expected_summary.json b/src/test/resources/network/brightspots/rcv/test_data/sequential_with_batch/sequential_with_batch_2_expected_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/sequential_with_batch/sequential_with_batch_2_expected_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/sequential_with_batch/sequential_with_batch_2_expected_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/sequential_with_batch/sequential_with_batch_3_expected_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/sequential_with_batch/sequential_with_batch_3_expected_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/sequential_with_batch/sequential_with_batch_3_expected_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/sequential_with_batch/sequential_with_batch_3_expected_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/sequential_with_batch/sequential_with_batch_3_expected_summary.json b/src/test/resources/network/brightspots/rcv/test_data/sequential_with_batch/sequential_with_batch_3_expected_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/sequential_with_batch/sequential_with_batch_3_expected_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/sequential_with_batch/sequential_with_batch_3_expected_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/sequential_with_continue_until_two/sequential_with_continue_until_two_1_expected_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/sequential_with_continue_until_two/sequential_with_continue_until_two_1_expected_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/sequential_with_continue_until_two/sequential_with_continue_until_two_1_expected_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/sequential_with_continue_until_two/sequential_with_continue_until_two_1_expected_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/sequential_with_continue_until_two/sequential_with_continue_until_two_1_expected_summary.json b/src/test/resources/network/brightspots/rcv/test_data/sequential_with_continue_until_two/sequential_with_continue_until_two_1_expected_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/sequential_with_continue_until_two/sequential_with_continue_until_two_1_expected_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/sequential_with_continue_until_two/sequential_with_continue_until_two_1_expected_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/sequential_with_continue_until_two/sequential_with_continue_until_two_2_expected_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/sequential_with_continue_until_two/sequential_with_continue_until_two_2_expected_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/sequential_with_continue_until_two/sequential_with_continue_until_two_2_expected_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/sequential_with_continue_until_two/sequential_with_continue_until_two_2_expected_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/sequential_with_continue_until_two/sequential_with_continue_until_two_2_expected_summary.json b/src/test/resources/network/brightspots/rcv/test_data/sequential_with_continue_until_two/sequential_with_continue_until_two_2_expected_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/sequential_with_continue_until_two/sequential_with_continue_until_two_2_expected_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/sequential_with_continue_until_two/sequential_with_continue_until_two_2_expected_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/sequential_with_continue_until_two/sequential_with_continue_until_two_3_expected_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/sequential_with_continue_until_two/sequential_with_continue_until_two_3_expected_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/sequential_with_continue_until_two/sequential_with_continue_until_two_3_expected_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/sequential_with_continue_until_two/sequential_with_continue_until_two_3_expected_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/sequential_with_continue_until_two/sequential_with_continue_until_two_3_expected_summary.json b/src/test/resources/network/brightspots/rcv/test_data/sequential_with_continue_until_two/sequential_with_continue_until_two_3_expected_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/sequential_with_continue_until_two/sequential_with_continue_until_two_3_expected_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/sequential_with_continue_until_two/sequential_with_continue_until_two_3_expected_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/skip_to_next_test/skip_to_next_test_expected_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/skip_to_next_test/skip_to_next_test_expected_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/skip_to_next_test/skip_to_next_test_expected_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/skip_to_next_test/skip_to_next_test_expected_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/skip_to_next_test/skip_to_next_test_expected_summary.json b/src/test/resources/network/brightspots/rcv/test_data/skip_to_next_test/skip_to_next_test_expected_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/skip_to_next_test/skip_to_next_test_expected_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/skip_to_next_test/skip_to_next_test_expected_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/stop_tabulation_early_test/stop_tabulation_early_test_expected_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/stop_tabulation_early_test/stop_tabulation_early_test_expected_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/stop_tabulation_early_test/stop_tabulation_early_test_expected_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/stop_tabulation_early_test/stop_tabulation_early_test_expected_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/stop_tabulation_early_test/stop_tabulation_early_test_expected_summary.json b/src/test/resources/network/brightspots/rcv/test_data/stop_tabulation_early_test/stop_tabulation_early_test_expected_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/stop_tabulation_early_test/stop_tabulation_early_test_expected_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/stop_tabulation_early_test/stop_tabulation_early_test_expected_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/test_set_0_skipped_first_choice/test_set_0_skipped_first_choice_expected_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/test_set_0_skipped_first_choice/test_set_0_skipped_first_choice_expected_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/test_set_0_skipped_first_choice/test_set_0_skipped_first_choice_expected_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/test_set_0_skipped_first_choice/test_set_0_skipped_first_choice_expected_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/test_set_0_skipped_first_choice/test_set_0_skipped_first_choice_expected_summary.json b/src/test/resources/network/brightspots/rcv/test_data/test_set_0_skipped_first_choice/test_set_0_skipped_first_choice_expected_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/test_set_0_skipped_first_choice/test_set_0_skipped_first_choice_expected_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/test_set_0_skipped_first_choice/test_set_0_skipped_first_choice_expected_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/test_set_1_exhaust_at_overvote/test_set_1_exhaust_at_overvote_expected_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/test_set_1_exhaust_at_overvote/test_set_1_exhaust_at_overvote_expected_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/test_set_1_exhaust_at_overvote/test_set_1_exhaust_at_overvote_expected_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/test_set_1_exhaust_at_overvote/test_set_1_exhaust_at_overvote_expected_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/test_set_1_exhaust_at_overvote/test_set_1_exhaust_at_overvote_expected_summary.json b/src/test/resources/network/brightspots/rcv/test_data/test_set_1_exhaust_at_overvote/test_set_1_exhaust_at_overvote_expected_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/test_set_1_exhaust_at_overvote/test_set_1_exhaust_at_overvote_expected_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/test_set_1_exhaust_at_overvote/test_set_1_exhaust_at_overvote_expected_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/test_set_2_overvote_skip_to_next/test_set_2_overvote_skip_to_next_expected_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/test_set_2_overvote_skip_to_next/test_set_2_overvote_skip_to_next_expected_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/test_set_2_overvote_skip_to_next/test_set_2_overvote_skip_to_next_expected_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/test_set_2_overvote_skip_to_next/test_set_2_overvote_skip_to_next_expected_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/test_set_2_overvote_skip_to_next/test_set_2_overvote_skip_to_next_expected_summary.json b/src/test/resources/network/brightspots/rcv/test_data/test_set_2_overvote_skip_to_next/test_set_2_overvote_skip_to_next_expected_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/test_set_2_overvote_skip_to_next/test_set_2_overvote_skip_to_next_expected_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/test_set_2_overvote_skip_to_next/test_set_2_overvote_skip_to_next_expected_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/test_set_3_skipped_choice_exhaust/test_set_3_skipped_choice_exhaust_expected_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/test_set_3_skipped_choice_exhaust/test_set_3_skipped_choice_exhaust_expected_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/test_set_3_skipped_choice_exhaust/test_set_3_skipped_choice_exhaust_expected_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/test_set_3_skipped_choice_exhaust/test_set_3_skipped_choice_exhaust_expected_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/test_set_3_skipped_choice_exhaust/test_set_3_skipped_choice_exhaust_expected_summary.json b/src/test/resources/network/brightspots/rcv/test_data/test_set_3_skipped_choice_exhaust/test_set_3_skipped_choice_exhaust_expected_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/test_set_3_skipped_choice_exhaust/test_set_3_skipped_choice_exhaust_expected_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/test_set_3_skipped_choice_exhaust/test_set_3_skipped_choice_exhaust_expected_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/test_set_4_skipped_choice_next/test_set_4_skipped_choice_next_expected_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/test_set_4_skipped_choice_next/test_set_4_skipped_choice_next_expected_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/test_set_4_skipped_choice_next/test_set_4_skipped_choice_next_expected_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/test_set_4_skipped_choice_next/test_set_4_skipped_choice_next_expected_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/test_set_4_skipped_choice_next/test_set_4_skipped_choice_next_expected_summary.json b/src/test/resources/network/brightspots/rcv/test_data/test_set_4_skipped_choice_next/test_set_4_skipped_choice_next_expected_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/test_set_4_skipped_choice_next/test_set_4_skipped_choice_next_expected_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/test_set_4_skipped_choice_next/test_set_4_skipped_choice_next_expected_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/test_set_5_two_skipped_choice_exhaust/test_set_5_two_skipped_choice_exhaust_expected_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/test_set_5_two_skipped_choice_exhaust/test_set_5_two_skipped_choice_exhaust_expected_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/test_set_5_two_skipped_choice_exhaust/test_set_5_two_skipped_choice_exhaust_expected_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/test_set_5_two_skipped_choice_exhaust/test_set_5_two_skipped_choice_exhaust_expected_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/test_set_5_two_skipped_choice_exhaust/test_set_5_two_skipped_choice_exhaust_expected_summary.json b/src/test/resources/network/brightspots/rcv/test_data/test_set_5_two_skipped_choice_exhaust/test_set_5_two_skipped_choice_exhaust_expected_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/test_set_5_two_skipped_choice_exhaust/test_set_5_two_skipped_choice_exhaust_expected_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/test_set_5_two_skipped_choice_exhaust/test_set_5_two_skipped_choice_exhaust_expected_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/test_set_6_duplicate_exhaust/test_set_6_duplicate_exhaust_expected_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/test_set_6_duplicate_exhaust/test_set_6_duplicate_exhaust_expected_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/test_set_6_duplicate_exhaust/test_set_6_duplicate_exhaust_expected_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/test_set_6_duplicate_exhaust/test_set_6_duplicate_exhaust_expected_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/test_set_6_duplicate_exhaust/test_set_6_duplicate_exhaust_expected_summary.json b/src/test/resources/network/brightspots/rcv/test_data/test_set_6_duplicate_exhaust/test_set_6_duplicate_exhaust_expected_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/test_set_6_duplicate_exhaust/test_set_6_duplicate_exhaust_expected_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/test_set_6_duplicate_exhaust/test_set_6_duplicate_exhaust_expected_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/test_set_7_duplicate_skip_to_next/test_set_7_duplicate_skip_to_next_expected_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/test_set_7_duplicate_skip_to_next/test_set_7_duplicate_skip_to_next_expected_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/test_set_7_duplicate_skip_to_next/test_set_7_duplicate_skip_to_next_expected_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/test_set_7_duplicate_skip_to_next/test_set_7_duplicate_skip_to_next_expected_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/test_set_7_duplicate_skip_to_next/test_set_7_duplicate_skip_to_next_expected_summary.json b/src/test/resources/network/brightspots/rcv/test_data/test_set_7_duplicate_skip_to_next/test_set_7_duplicate_skip_to_next_expected_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/test_set_7_duplicate_skip_to_next/test_set_7_duplicate_skip_to_next_expected_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/test_set_7_duplicate_skip_to_next/test_set_7_duplicate_skip_to_next_expected_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/test_set_8_multi_cdf/test_set_8_multi_cdf_expected_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/test_set_8_multi_cdf/test_set_8_multi_cdf_expected_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/test_set_8_multi_cdf/test_set_8_multi_cdf_expected_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/test_set_8_multi_cdf/test_set_8_multi_cdf_expected_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/test_set_8_multi_cdf/test_set_8_multi_cdf_expected_summary.json b/src/test/resources/network/brightspots/rcv/test_data/test_set_8_multi_cdf/test_set_8_multi_cdf_expected_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/test_set_8_multi_cdf/test_set_8_multi_cdf_expected_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/test_set_8_multi_cdf/test_set_8_multi_cdf_expected_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/test_set_allow_only_one_winner_per_round/test_set_allow_only_one_winner_per_round_expected_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/test_set_allow_only_one_winner_per_round/test_set_allow_only_one_winner_per_round_expected_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/test_set_allow_only_one_winner_per_round/test_set_allow_only_one_winner_per_round_expected_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/test_set_allow_only_one_winner_per_round/test_set_allow_only_one_winner_per_round_expected_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/test_set_allow_only_one_winner_per_round/test_set_allow_only_one_winner_per_round_expected_summary.json b/src/test/resources/network/brightspots/rcv/test_data/test_set_allow_only_one_winner_per_round/test_set_allow_only_one_winner_per_round_expected_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/test_set_allow_only_one_winner_per_round/test_set_allow_only_one_winner_per_round_expected_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/test_set_allow_only_one_winner_per_round/test_set_allow_only_one_winner_per_round_expected_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/test_set_multi_winner_fractional_threshold/test_set_multi_winner_fractional_threshold_expected_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/test_set_multi_winner_fractional_threshold/test_set_multi_winner_fractional_threshold_expected_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/test_set_multi_winner_fractional_threshold/test_set_multi_winner_fractional_threshold_expected_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/test_set_multi_winner_fractional_threshold/test_set_multi_winner_fractional_threshold_expected_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/test_set_multi_winner_fractional_threshold/test_set_multi_winner_fractional_threshold_expected_summary.json b/src/test/resources/network/brightspots/rcv/test_data/test_set_multi_winner_fractional_threshold/test_set_multi_winner_fractional_threshold_expected_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/test_set_multi_winner_fractional_threshold/test_set_multi_winner_fractional_threshold_expected_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/test_set_multi_winner_fractional_threshold/test_set_multi_winner_fractional_threshold_expected_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/test_set_multi_winner_whole_threshold/test_set_multi_winner_whole_threshold_expected_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/test_set_multi_winner_whole_threshold/test_set_multi_winner_whole_threshold_expected_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/test_set_multi_winner_whole_threshold/test_set_multi_winner_whole_threshold_expected_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/test_set_multi_winner_whole_threshold/test_set_multi_winner_whole_threshold_expected_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/test_set_multi_winner_whole_threshold/test_set_multi_winner_whole_threshold_expected_summary.json b/src/test/resources/network/brightspots/rcv/test_data/test_set_multi_winner_whole_threshold/test_set_multi_winner_whole_threshold_expected_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/test_set_multi_winner_whole_threshold/test_set_multi_winner_whole_threshold_expected_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/test_set_multi_winner_whole_threshold/test_set_multi_winner_whole_threshold_expected_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/test_set_overvote_delimiter/test_set_overvote_delimiter_expected_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/test_set_overvote_delimiter/test_set_overvote_delimiter_expected_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/test_set_overvote_delimiter/test_set_overvote_delimiter_expected_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/test_set_overvote_delimiter/test_set_overvote_delimiter_expected_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/test_set_overvote_delimiter/test_set_overvote_delimiter_expected_summary.json b/src/test/resources/network/brightspots/rcv/test_data/test_set_overvote_delimiter/test_set_overvote_delimiter_expected_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/test_set_overvote_delimiter/test_set_overvote_delimiter_expected_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/test_set_overvote_delimiter/test_set_overvote_delimiter_expected_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/test_set_treat_blank_as_undeclared_write_in/test_set_treat_blank_as_undeclared_write_in_expected_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/test_set_treat_blank_as_undeclared_write_in/test_set_treat_blank_as_undeclared_write_in_expected_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/test_set_treat_blank_as_undeclared_write_in/test_set_treat_blank_as_undeclared_write_in_expected_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/test_set_treat_blank_as_undeclared_write_in/test_set_treat_blank_as_undeclared_write_in_expected_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/test_set_treat_blank_as_undeclared_write_in/test_set_treat_blank_as_undeclared_write_in_expected_summary.json b/src/test/resources/network/brightspots/rcv/test_data/test_set_treat_blank_as_undeclared_write_in/test_set_treat_blank_as_undeclared_write_in_expected_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/test_set_treat_blank_as_undeclared_write_in/test_set_treat_blank_as_undeclared_write_in_expected_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/test_set_treat_blank_as_undeclared_write_in/test_set_treat_blank_as_undeclared_write_in_expected_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/tiebreak_generate_permutation_test/tiebreak_generate_permutation_test_expected_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/tiebreak_generate_permutation_test/tiebreak_generate_permutation_test_expected_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/tiebreak_generate_permutation_test/tiebreak_generate_permutation_test_expected_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/tiebreak_generate_permutation_test/tiebreak_generate_permutation_test_expected_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/tiebreak_generate_permutation_test/tiebreak_generate_permutation_test_expected_summary.json b/src/test/resources/network/brightspots/rcv/test_data/tiebreak_generate_permutation_test/tiebreak_generate_permutation_test_expected_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/tiebreak_generate_permutation_test/tiebreak_generate_permutation_test_expected_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/tiebreak_generate_permutation_test/tiebreak_generate_permutation_test_expected_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/tiebreak_previous_round_counts_then_random_test/tiebreak_previous_round_counts_then_random_test_expected_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/tiebreak_previous_round_counts_then_random_test/tiebreak_previous_round_counts_then_random_test_expected_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/tiebreak_previous_round_counts_then_random_test/tiebreak_previous_round_counts_then_random_test_expected_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/tiebreak_previous_round_counts_then_random_test/tiebreak_previous_round_counts_then_random_test_expected_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/tiebreak_previous_round_counts_then_random_test/tiebreak_previous_round_counts_then_random_test_expected_summary.json b/src/test/resources/network/brightspots/rcv/test_data/tiebreak_previous_round_counts_then_random_test/tiebreak_previous_round_counts_then_random_test_expected_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/tiebreak_previous_round_counts_then_random_test/tiebreak_previous_round_counts_then_random_test_expected_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/tiebreak_previous_round_counts_then_random_test/tiebreak_previous_round_counts_then_random_test_expected_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/tiebreak_seed_test/tiebreak_seed_test_expected_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/tiebreak_seed_test/tiebreak_seed_test_expected_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/tiebreak_seed_test/tiebreak_seed_test_expected_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/tiebreak_seed_test/tiebreak_seed_test_expected_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/tiebreak_seed_test/tiebreak_seed_test_expected_summary.json b/src/test/resources/network/brightspots/rcv/test_data/tiebreak_seed_test/tiebreak_seed_test_expected_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/tiebreak_seed_test/tiebreak_seed_test_expected_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/tiebreak_seed_test/tiebreak_seed_test_expected_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/tiebreak_use_permutation_in_config_test/tiebreak_use_permutation_in_config_test_expected_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/tiebreak_use_permutation_in_config_test/tiebreak_use_permutation_in_config_test_expected_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/tiebreak_use_permutation_in_config_test/tiebreak_use_permutation_in_config_test_expected_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/tiebreak_use_permutation_in_config_test/tiebreak_use_permutation_in_config_test_expected_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/tiebreak_use_permutation_in_config_test/tiebreak_use_permutation_in_config_test_expected_summary.json b/src/test/resources/network/brightspots/rcv/test_data/tiebreak_use_permutation_in_config_test/tiebreak_use_permutation_in_config_test_expected_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/tiebreak_use_permutation_in_config_test/tiebreak_use_permutation_in_config_test_expected_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/tiebreak_use_permutation_in_config_test/tiebreak_use_permutation_in_config_test_expected_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/unisyn_xml_cdf_city_chief_of_police/unisyn_xml_cdf_city_chief_of_police_expected_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/unisyn_xml_cdf_city_chief_of_police/unisyn_xml_cdf_city_chief_of_police_expected_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/unisyn_xml_cdf_city_chief_of_police/unisyn_xml_cdf_city_chief_of_police_expected_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/unisyn_xml_cdf_city_chief_of_police/unisyn_xml_cdf_city_chief_of_police_expected_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/unisyn_xml_cdf_city_chief_of_police/unisyn_xml_cdf_city_chief_of_police_expected_summary.json b/src/test/resources/network/brightspots/rcv/test_data/unisyn_xml_cdf_city_chief_of_police/unisyn_xml_cdf_city_chief_of_police_expected_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/unisyn_xml_cdf_city_chief_of_police/unisyn_xml_cdf_city_chief_of_police_expected_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/unisyn_xml_cdf_city_chief_of_police/unisyn_xml_cdf_city_chief_of_police_expected_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/unisyn_xml_cdf_city_coroner/unisyn_xml_cdf_city_coroner_expected_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/unisyn_xml_cdf_city_coroner/unisyn_xml_cdf_city_coroner_expected_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/unisyn_xml_cdf_city_coroner/unisyn_xml_cdf_city_coroner_expected_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/unisyn_xml_cdf_city_coroner/unisyn_xml_cdf_city_coroner_expected_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/unisyn_xml_cdf_city_coroner/unisyn_xml_cdf_city_coroner_expected_summary.json b/src/test/resources/network/brightspots/rcv/test_data/unisyn_xml_cdf_city_coroner/unisyn_xml_cdf_city_coroner_expected_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/unisyn_xml_cdf_city_coroner/unisyn_xml_cdf_city_coroner_expected_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/unisyn_xml_cdf_city_coroner/unisyn_xml_cdf_city_coroner_expected_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/unisyn_xml_cdf_city_council_member/unisyn_xml_cdf_city_council_member_expected_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/unisyn_xml_cdf_city_council_member/unisyn_xml_cdf_city_council_member_expected_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/unisyn_xml_cdf_city_council_member/unisyn_xml_cdf_city_council_member_expected_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/unisyn_xml_cdf_city_council_member/unisyn_xml_cdf_city_council_member_expected_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/unisyn_xml_cdf_city_council_member/unisyn_xml_cdf_city_council_member_expected_summary.json b/src/test/resources/network/brightspots/rcv/test_data/unisyn_xml_cdf_city_council_member/unisyn_xml_cdf_city_council_member_expected_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/unisyn_xml_cdf_city_council_member/unisyn_xml_cdf_city_council_member_expected_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/unisyn_xml_cdf_city_council_member/unisyn_xml_cdf_city_council_member_expected_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/unisyn_xml_cdf_city_mayor/unisyn_xml_cdf_city_mayor_expected_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/unisyn_xml_cdf_city_mayor/unisyn_xml_cdf_city_mayor_expected_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/unisyn_xml_cdf_city_mayor/unisyn_xml_cdf_city_mayor_expected_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/unisyn_xml_cdf_city_mayor/unisyn_xml_cdf_city_mayor_expected_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/unisyn_xml_cdf_city_mayor/unisyn_xml_cdf_city_mayor_expected_summary.json b/src/test/resources/network/brightspots/rcv/test_data/unisyn_xml_cdf_city_mayor/unisyn_xml_cdf_city_mayor_expected_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/unisyn_xml_cdf_city_mayor/unisyn_xml_cdf_city_mayor_expected_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/unisyn_xml_cdf_city_mayor/unisyn_xml_cdf_city_mayor_expected_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/unisyn_xml_cdf_city_tax_collector/unisyn_xml_cdf_city_tax_collector_expected_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/unisyn_xml_cdf_city_tax_collector/unisyn_xml_cdf_city_tax_collector_expected_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/unisyn_xml_cdf_city_tax_collector/unisyn_xml_cdf_city_tax_collector_expected_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/unisyn_xml_cdf_city_tax_collector/unisyn_xml_cdf_city_tax_collector_expected_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/unisyn_xml_cdf_city_tax_collector/unisyn_xml_cdf_city_tax_collector_expected_summary.json b/src/test/resources/network/brightspots/rcv/test_data/unisyn_xml_cdf_city_tax_collector/unisyn_xml_cdf_city_tax_collector_expected_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/unisyn_xml_cdf_city_tax_collector/unisyn_xml_cdf_city_tax_collector_expected_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/unisyn_xml_cdf_city_tax_collector/unisyn_xml_cdf_city_tax_collector_expected_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/unisyn_xml_cdf_county_coroner/unisyn_xml_cdf_county_coroner_expected_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/unisyn_xml_cdf_county_coroner/unisyn_xml_cdf_county_coroner_expected_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/unisyn_xml_cdf_county_coroner/unisyn_xml_cdf_county_coroner_expected_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/unisyn_xml_cdf_county_coroner/unisyn_xml_cdf_county_coroner_expected_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/unisyn_xml_cdf_county_coroner/unisyn_xml_cdf_county_coroner_expected_summary.json b/src/test/resources/network/brightspots/rcv/test_data/unisyn_xml_cdf_county_coroner/unisyn_xml_cdf_county_coroner_expected_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/unisyn_xml_cdf_county_coroner/unisyn_xml_cdf_county_coroner_expected_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/unisyn_xml_cdf_county_coroner/unisyn_xml_cdf_county_coroner_expected_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/unisyn_xml_cdf_county_sheriff/unisyn_xml_cdf_county_sheriff_expected_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/unisyn_xml_cdf_county_sheriff/unisyn_xml_cdf_county_sheriff_expected_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/unisyn_xml_cdf_county_sheriff/unisyn_xml_cdf_county_sheriff_expected_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/unisyn_xml_cdf_county_sheriff/unisyn_xml_cdf_county_sheriff_expected_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/unisyn_xml_cdf_county_sheriff/unisyn_xml_cdf_county_sheriff_expected_summary.json b/src/test/resources/network/brightspots/rcv/test_data/unisyn_xml_cdf_county_sheriff/unisyn_xml_cdf_county_sheriff_expected_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/unisyn_xml_cdf_county_sheriff/unisyn_xml_cdf_county_sheriff_expected_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/unisyn_xml_cdf_county_sheriff/unisyn_xml_cdf_county_sheriff_expected_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/uwi_cannot_win_test/uwi_cannot_win_test_expected_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/uwi_cannot_win_test/uwi_cannot_win_test_expected_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/uwi_cannot_win_test/uwi_cannot_win_test_expected_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/uwi_cannot_win_test/uwi_cannot_win_test_expected_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/uwi_cannot_win_test/uwi_cannot_win_test_expected_summary.json b/src/test/resources/network/brightspots/rcv/test_data/uwi_cannot_win_test/uwi_cannot_win_test_expected_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/uwi_cannot_win_test/uwi_cannot_win_test_expected_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/uwi_cannot_win_test/uwi_cannot_win_test_expected_detailed_report.json From b9dacb66bd856254392e5e09b7d6e602ad6cffff Mon Sep 17 00:00:00 2001 From: Armin Samii Date: Sat, 19 Oct 2024 15:50:52 -0400 Subject: [PATCH 03/17] rename ResultFile to ResultTypeAndSlice, and CVR_CDF to CDF_CVR --- .../brightspots/rcv/ResultsWriter.java | 76 ++++++++++--------- .../brightspots/rcv/TabulatorTests.java | 28 +++---- 2 files changed, 55 insertions(+), 49 deletions(-) diff --git a/src/main/java/network/brightspots/rcv/ResultsWriter.java b/src/main/java/network/brightspots/rcv/ResultsWriter.java index f00b2668f..088bdc5f1 100644 --- a/src/main/java/network/brightspots/rcv/ResultsWriter.java +++ b/src/main/java/network/brightspots/rcv/ResultsWriter.java @@ -93,7 +93,7 @@ public enum ResultType { SUMMARY_CSV("summary_report", "csv"), DETAILED_CSV("detailed_report", "csv"), DETAILED_JSON("detailed_report", "json"), - CDF("cvr_cdf", "json"), + CDF_CVR("cdf_cvr", "json"), RCTAB_CVR("rctab_cvr", "csv"); private final String basename; @@ -113,7 +113,7 @@ public String getExtension() { } } - public static class ResultFile { + public static class ResultTypeAndSlice { // Since sanitizing Slice IDs can cause filename collisions, ensure each non-sanitized // Slice ID is given a unique sanitized name. private static final Dictionary sliceIdToUniqueSanitizedId = new Hashtable<>(); @@ -125,14 +125,14 @@ public static class ResultFile { private final TabulateBySlice slice; private final String sliceId; - ResultFile(ResultType resultType) { + ResultTypeAndSlice(ResultType resultType) { this.resultType = resultType; this.isSlice = false; slice = null; sliceId = null; } - ResultFile(ResultType resultType, TabulateBySlice slice, String sliceId) { + ResultTypeAndSlice(ResultType resultType, TabulateBySlice slice, String sliceId) { this.resultType = resultType; this.isSlice = true; this.slice = slice; @@ -336,20 +336,22 @@ void generateBySliceSummaryFiles( String sliceId = entry.getKey(); RoundTallies roundTallies = entry.getValue(); TallyTransfers tallyTransfers = tallyTransfersBySlice.get(slice, sliceId); - ResultFile resultFileCsv = new ResultFile(ResultType.DETAILED_CSV, slice, sliceId); - ResultFile resultFileJson = new ResultFile(ResultType.DETAILED_JSON, slice, sliceId); - generateSummaryCsv(roundTallies, candidateOrder, resultFileCsv); - generateSummaryJson(roundTallies, tallyTransfers, resultFileJson); + ResultTypeAndSlice resultTypeAndSliceCsv = + new ResultTypeAndSlice(ResultType.DETAILED_CSV, slice, sliceId); + ResultTypeAndSlice resultTypeAndSliceJson = + new ResultTypeAndSlice(ResultType.DETAILED_JSON, slice, sliceId); + generateSummaryCsv(roundTallies, candidateOrder, resultTypeAndSliceCsv); + generateSummaryJson(roundTallies, tallyTransfers, resultTypeAndSliceJson); } } } - private AuditableFile createAuditableFile(ResultFile resultFile) { + private AuditableFile createAuditableFile(ResultTypeAndSlice resultTypeAndSlice) { Integer sequentialId = null; if (config.isMultiSeatSequentialWinnerTakesAllEnabled()) { sequentialId = config.getSequentialWinners().size() + 1; } - return new AuditableFile(resultFile.getPath( + return new AuditableFile(resultTypeAndSlice.getPath( config.getOutputDirectory(), timestampString, sequentialId)); } @@ -363,11 +365,11 @@ private AuditableFile createAuditableFile(ResultFile resultFile) { private void generateSummaryCsv( RoundTallies roundTallies, List candidateOrder, - ResultFile resultFile) throws IOException { - if (resultFile.resultType != ResultType.SUMMARY_CSV - && resultFile.resultType != ResultType.DETAILED_CSV) { + ResultTypeAndSlice resultTypeAndSlice) throws IOException { + if (resultTypeAndSlice.resultType != ResultType.SUMMARY_CSV + && resultTypeAndSlice.resultType != ResultType.DETAILED_CSV) { throw new IllegalArgumentException("ResultFile provided non-CSV type " - + resultFile.resultType); + + resultTypeAndSlice.resultType); } // Check that all candidates are included in the candidate order Set expectedCandidates = roundTallies.get(1).getCandidates(); @@ -379,7 +381,7 @@ private void generateSummaryCsv( + "\nProvided: " + providedCandidates); } - AuditableFile csvFile = createAuditableFile(resultFile); + AuditableFile csvFile = createAuditableFile(resultTypeAndSlice); Logger.info("Generating summary spreadsheet: %s...", csvFile.getAbsolutePath()); CSVPrinter csvPrinter; @@ -394,7 +396,8 @@ private void generateSummaryCsv( } BigDecimal winningThreshold = roundTallies.get(numRounds).getWinningThreshold(); - addContestInformationRows(csvPrinter, winningThreshold, resultFile.slice, resultFile.sliceId); + addContestInformationRows(csvPrinter, winningThreshold, + resultTypeAndSlice.slice, resultTypeAndSlice.sliceId); addContestSummaryRows(csvPrinter, roundTallies.get(1)); csvPrinter.print("Rounds"); for (int round = 1; round <= numRounds; round++) { @@ -404,10 +407,10 @@ private void generateSummaryCsv( } csvPrinter.println(); - csvPrinter.print(resultFile.isSlice ? "Eliminated*" : "Eliminated"); + csvPrinter.print(resultTypeAndSlice.isSlice ? "Eliminated*" : "Eliminated"); printActionSummary(csvPrinter, roundToEliminatedCandidates); - csvPrinter.print(resultFile.isSlice ? "Elected*" : "Elected"); + csvPrinter.print(resultTypeAndSlice.isSlice ? "Elected*" : "Elected"); printActionSummary(csvPrinter, roundToWinningCandidates); // For each candidate: for each round: output total votes @@ -463,7 +466,7 @@ private void generateSummaryCsv( } csvPrinter.println(); - if (!resultFile.isSlice) { + if (!resultTypeAndSlice.isSlice) { csvPrinter.print("Current Round Threshold"); for (int round = 1; round <= numRounds; round++) { csvPrinter.print(roundTallies.get(round).getWinningThreshold()); @@ -473,7 +476,7 @@ private void generateSummaryCsv( csvPrinter.println(); } - if (resultFile.resultType == ResultType.DETAILED_CSV) { + if (resultTypeAndSlice.resultType == ResultType.DETAILED_CSV) { for (StatusForRound status : STATUSES_TO_PRINT) { csvPrinter.print(status.getTitleCaseKey()); @@ -525,7 +528,7 @@ private void generateSummaryCsv( // whether the value in the final round is positive. // Note that this concept only makes sense when we're reporting the overall tabulation, so we // omit it when generating results at the individual by-slice level. - if (!resultFile.isSlice && roundToResidualSurplus.get(numRounds).signum() == 1) { + if (!resultTypeAndSlice.isSlice && roundToResidualSurplus.get(numRounds).signum() == 1) { csvPrinter.print("Residual surplus"); for (int round = 1; round <= numRounds; round++) { csvPrinter.print(roundToResidualSurplus.get(round)); @@ -552,11 +555,11 @@ private void generateSummaryCsv( csvPrinter.println(); } - if (resultFile.isSlice) { + if (resultTypeAndSlice.isSlice) { csvPrinter.println(); csvPrinter.print(String.format("*Elect/Eliminate decisions are from the full contest. " + "All other results on this report are at the %s level.", - resultFile.slice.toLowerString())); + resultTypeAndSlice.slice.toLowerString())); csvPrinter.println(); } @@ -565,7 +568,7 @@ private void generateSummaryCsv( csvPrinter.close(); csvFile.finalizeAndHash(); } catch (IOException exception) { - Logger.severe("Error saving file: %s\n%s", resultFile.resultType, exception); + Logger.severe("Error saving file: %s\n%s", resultTypeAndSlice.resultType, exception); throw exception; } Logger.info("Summary spreadsheet generated successfully."); @@ -656,9 +659,12 @@ void generateOverallSummaryFiles( RoundTallies roundTallies, TallyTransfers tallyTransfers, List candidateOrder) throws IOException { - generateSummaryCsv(roundTallies, candidateOrder, new ResultFile(ResultType.SUMMARY_CSV)); - generateSummaryCsv(roundTallies, candidateOrder, new ResultFile(ResultType.DETAILED_CSV)); - generateSummaryJson(roundTallies, tallyTransfers, new ResultFile(ResultType.DETAILED_JSON)); + generateSummaryCsv(roundTallies, candidateOrder, + new ResultTypeAndSlice(ResultType.SUMMARY_CSV)); + generateSummaryCsv(roundTallies, candidateOrder, + new ResultTypeAndSlice(ResultType.DETAILED_CSV)); + generateSummaryJson(roundTallies, tallyTransfers, + new ResultTypeAndSlice(ResultType.DETAILED_JSON)); } // Write CastVoteRecords for the specified contest to the provided folder, @@ -675,8 +681,8 @@ String writeRcTabCvrCsv( // Put the input filename in the output filename in case contestId isn't unique -- // knowing that it's possible that if both the filename AND the contestId isn't unique, // this will fail. - ResultFile resultFile = new ResultFile(ResultType.RCTAB_CVR); - AuditableFile auditableFile = createAuditableFile(resultFile); + ResultTypeAndSlice resultTypeAndSlice = new ResultTypeAndSlice(ResultType.RCTAB_CVR); + AuditableFile auditableFile = createAuditableFile(resultTypeAndSlice); try { Logger.info("Writing cast vote records in generic format to file: %s...", auditableFile.getAbsolutePath()); @@ -795,8 +801,8 @@ void generateCdfJson(List castVoteRecords) // generate GpUnitIds for precincts "geopolitical units" (can be a precinct or jurisdiction) gpUnitIds = generateGpUnitIds(); - ResultFile resultFile = new ResultFile(ResultType.CDF); - AuditableFile auditableFile = createAuditableFile(resultFile); + ResultTypeAndSlice resultTypeAndSlice = new ResultTypeAndSlice(ResultType.CDF_CVR); + AuditableFile auditableFile = createAuditableFile(resultTypeAndSlice); Logger.info("Generating cast vote record CDF JSON file: %s...", auditableFile.getAbsolutePath()); @@ -1032,9 +1038,9 @@ private Map generateCdfMapForElection() { private void generateSummaryJson( RoundTallies roundTallies, TallyTransfers tallyTransfers, - ResultFile resultFile) + ResultTypeAndSlice resultTypeAndSlice) throws IOException { - AuditableFile jsonFile = createAuditableFile(resultFile); + AuditableFile jsonFile = createAuditableFile(resultTypeAndSlice); Logger.info("Generating summary JSON file: %s...", jsonFile.getAbsolutePath()); // config will contain contest configuration info @@ -1044,8 +1050,8 @@ private void generateSummaryJson( configData.put("jurisdiction", config.getContestJurisdiction()); configData.put("office", config.getContestOffice()); configData.put("date", config.getContestDate()); - if (resultFile.isSlice) { - configData.put(resultFile.slice.toLowerString(), resultFile.sliceId); + if (resultTypeAndSlice.isSlice) { + configData.put(resultTypeAndSlice.slice.toLowerString(), resultTypeAndSlice.sliceId); } BigDecimal numNoRankings = diff --git a/src/test/java/network/brightspots/rcv/TabulatorTests.java b/src/test/java/network/brightspots/rcv/TabulatorTests.java index 3e19030a0..3d2c72883 100644 --- a/src/test/java/network/brightspots/rcv/TabulatorTests.java +++ b/src/test/java/network/brightspots/rcv/TabulatorTests.java @@ -39,7 +39,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import network.brightspots.rcv.ResultsWriter.ResultFile; +import network.brightspots.rcv.ResultsWriter.ResultTypeAndSlice; import network.brightspots.rcv.ResultsWriter.ResultType; import network.brightspots.rcv.Tabulator.TabulationAbortedException; import org.junit.jupiter.api.BeforeAll; @@ -241,12 +241,12 @@ private static void runTabulationTest(String stem, String expectedException, int numSlicedFilesChecked = 0; for (ContestConfig.TabulateBySlice slice : config.enabledSlices()) { for (String sliceName : session.loadSliceNamesFromCvrs(slice, config)) { - ResultFile resultFileJson = new ResultFile(ResultType.DETAILED_JSON, slice, sliceName); - ResultFile resultFileCsv = new ResultFile(ResultType.DETAILED_CSV, slice, sliceName); - if (compareFiles(config, stem, resultFileJson, timestampString, null, true)) { + ResultsWriter.ResultTypeAndSlice resultTypeAndSliceJson = new ResultTypeAndSlice(ResultType.DETAILED_JSON, slice, sliceName); + ResultsWriter.ResultTypeAndSlice resultTypeAndSliceCsv = new ResultsWriter.ResultTypeAndSlice(ResultType.DETAILED_CSV, slice, sliceName); + if (compareFiles(config, stem, resultTypeAndSliceJson, timestampString, null, true)) { numSlicedFilesChecked++; } - if (compareFiles(config, stem, resultFileCsv, timestampString, null, true)) { + if (compareFiles(config, stem, resultTypeAndSliceCsv, timestampString, null, true)) { numSlicedFilesChecked++; } } @@ -265,7 +265,7 @@ private static void runConvertToCdfTest(String stem) { String timestampString = session.getTimestampString(); ContestConfig config = ContestConfig.loadContestConfig(configPath); - compareFiles(config, stem, ResultType.CDF, timestampString, null, false); + compareFiles(config, stem, ResultType.CDF_CVR, timestampString, null, false); cleanOutputFolder(session); } @@ -333,7 +333,7 @@ private static void compareFiles( compareFiles(config, stem, ResultType.DETAILED_CSV, timestampString, sequentialId, false); compareExtendedSummaryToSummary(config, timestampString, sequentialId); if (config.isGenerateCdfJsonEnabled()) { - compareFiles(config, stem, ResultType.CDF, timestampString, sequentialId, false); + compareFiles(config, stem, ResultType.CDF_CVR, timestampString, sequentialId, false); } } @@ -347,11 +347,11 @@ private static boolean compareFiles( String timestampString, Integer sequentialId, boolean onlyCheckIfExpectedFileExists) { - ResultFile actualResultFile = new ResultFile(resultType); + ResultsWriter.ResultTypeAndSlice actualResultTypeAndSlice = new ResultTypeAndSlice(resultType); return compareFiles( config, stem, - actualResultFile, + actualResultTypeAndSlice, timestampString, sequentialId, onlyCheckIfExpectedFileExists); @@ -364,13 +364,13 @@ private static boolean compareFiles( private static boolean compareFiles( ContestConfig config, String stem, - ResultFile actualResultFile, + ResultsWriter.ResultTypeAndSlice actualResultTypeAndSlice, String timestampString, Integer sequentialId, boolean onlyCheckIfExpectedFileExists) { - String actualOutputPath = actualResultFile.getPath( + String actualOutputPath = actualResultTypeAndSlice.getPath( config.getOutputDirectory(), timestampString, sequentialId).toAbsolutePath().toString(); - String expectedPath = actualResultFile.getPath(getTestDirectory(stem).toString(), + String expectedPath = actualResultTypeAndSlice.getPath(getTestDirectory(stem).toString(), stem, "expected", sequentialId).toString(); Logger.info("Comparing files:\nGenerated: %s\nReference: %s", actualOutputPath, expectedPath); @@ -395,9 +395,9 @@ private static boolean compareFiles( private static void compareExtendedSummaryToSummary( ContestConfig config, String timestampString, Integer sequentialId) { String dir = config.getOutputDirectory(); - String summaryPath = new ResultFile(ResultType.SUMMARY_CSV).getPath( + String summaryPath = new ResultTypeAndSlice(ResultType.SUMMARY_CSV).getPath( dir, timestampString, sequentialId).toAbsolutePath().toString(); - String detailedPath = new ResultFile(ResultType.DETAILED_CSV).getPath( + String detailedPath = new ResultsWriter.ResultTypeAndSlice(ResultType.DETAILED_CSV).getPath( dir, timestampString, sequentialId).toAbsolutePath().toString(); try (BufferedReader brSummary = new BufferedReader(new FileReader(summaryPath, UTF_8)); From 43dae825bec154c7e5d292ebe3f7c618ace85506 Mon Sep 17 00:00:00 2001 From: Armin Samii Date: Sat, 19 Oct 2024 15:55:04 -0400 Subject: [PATCH 04/17] address additional PR comments --- src/main/java/network/brightspots/rcv/ResultsWriter.java | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/main/java/network/brightspots/rcv/ResultsWriter.java b/src/main/java/network/brightspots/rcv/ResultsWriter.java index 088bdc5f1..51197b9ac 100644 --- a/src/main/java/network/brightspots/rcv/ResultsWriter.java +++ b/src/main/java/network/brightspots/rcv/ResultsWriter.java @@ -358,10 +358,7 @@ private AuditableFile createAuditableFile(ResultTypeAndSlice resultTypeAndSlice) // create a summary spreadsheet .csv file // param: roundTallies is the round-by-count count of votes per candidate // param: candidateOrder is to allow a consistent ordering of candidates, including across slices - // param: slice indicates which type of slice we're reporting results for (null means all) - // param: sliceId indicates the specific slice ID we're reporting results for (null means all) - // param: outputPath is the path to the output file, minus its extension - // param: extended include additional details in the output file? + // param: resultTypeAndSlice must only have type DETAILED_CSV or SUMMARY_CSV private void generateSummaryCsv( RoundTallies roundTallies, List candidateOrder, @@ -568,7 +565,7 @@ private void generateSummaryCsv( csvPrinter.close(); csvFile.finalizeAndHash(); } catch (IOException exception) { - Logger.severe("Error saving file: %s\n%s", resultTypeAndSlice.resultType, exception); + Logger.severe("Error saving file: %s\n%s", csvFile.getAbsolutePath(), exception); throw exception; } Logger.info("Summary spreadsheet generated successfully."); From 47bcf7ee83420581a291d7b907ffb7529dfd794a Mon Sep 17 00:00:00 2001 From: Armin Samii Date: Sat, 19 Oct 2024 15:57:15 -0400 Subject: [PATCH 05/17] rename files: CVR_CDF to CDF_CVR --- ...pected_cvr_cdf.json => aliases_cdf_json_expected_cdf_cvr.json} | 0 ..._expected_cvr_cdf.json => batch_example_expected_cdf_cvr.json} | 0 ...ed_cvr_cdf.json => conversions_from_cdf_expected_cdf_cvr.json} | 0 ...r_cdf.json => conversions_from_dominion_expected_cdf_cvr.json} | 0 ...ed_cvr_cdf.json => conversions_from_ess_expected_cdf_cvr.json} | 0 ...pected_cvr_cdf.json => precinct_example_expected_cdf_cvr.json} | 0 ...json => test_set_0_skipped_first_choice_expected_cdf_cvr.json} | 0 ....json => test_set_1_exhaust_at_overvote_expected_cdf_cvr.json} | 0 ...son => test_set_2_overvote_skip_to_next_expected_cdf_cvr.json} | 0 ...on => test_set_3_skipped_choice_exhaust_expected_cdf_cvr.json} | 0 ....json => test_set_4_skipped_choice_next_expected_cdf_cvr.json} | 0 ...> test_set_5_two_skipped_choice_exhaust_expected_cdf_cvr.json} | 0 ...df.json => test_set_6_duplicate_exhaust_expected_cdf_cvr.json} | 0 ...on => test_set_7_duplicate_skip_to_next_expected_cdf_cvr.json} | 0 ...ed_cvr_cdf.json => test_set_8_multi_cdf_expected_cdf_cvr.json} | 0 ...t_set_multi_winner_fractional_threshold_expected_cdf_cvr.json} | 0 ...> test_set_multi_winner_whole_threshold_expected_cdf_cvr.json} | 0 17 files changed, 0 insertions(+), 0 deletions(-) rename src/test/resources/network/brightspots/rcv/test_data/aliases_cdf_json/{aliases_cdf_json_expected_cvr_cdf.json => aliases_cdf_json_expected_cdf_cvr.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/batch_example/{batch_example_expected_cvr_cdf.json => batch_example_expected_cdf_cvr.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/conversions_from_cdf/{conversions_from_cdf_expected_cvr_cdf.json => conversions_from_cdf_expected_cdf_cvr.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/conversions_from_dominion/{conversions_from_dominion_expected_cvr_cdf.json => conversions_from_dominion_expected_cdf_cvr.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/conversions_from_ess/{conversions_from_ess_expected_cvr_cdf.json => conversions_from_ess_expected_cdf_cvr.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/precinct_example/{precinct_example_expected_cvr_cdf.json => precinct_example_expected_cdf_cvr.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/test_set_0_skipped_first_choice/{test_set_0_skipped_first_choice_expected_cvr_cdf.json => test_set_0_skipped_first_choice_expected_cdf_cvr.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/test_set_1_exhaust_at_overvote/{test_set_1_exhaust_at_overvote_expected_cvr_cdf.json => test_set_1_exhaust_at_overvote_expected_cdf_cvr.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/test_set_2_overvote_skip_to_next/{test_set_2_overvote_skip_to_next_expected_cvr_cdf.json => test_set_2_overvote_skip_to_next_expected_cdf_cvr.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/test_set_3_skipped_choice_exhaust/{test_set_3_skipped_choice_exhaust_expected_cvr_cdf.json => test_set_3_skipped_choice_exhaust_expected_cdf_cvr.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/test_set_4_skipped_choice_next/{test_set_4_skipped_choice_next_expected_cvr_cdf.json => test_set_4_skipped_choice_next_expected_cdf_cvr.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/test_set_5_two_skipped_choice_exhaust/{test_set_5_two_skipped_choice_exhaust_expected_cvr_cdf.json => test_set_5_two_skipped_choice_exhaust_expected_cdf_cvr.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/test_set_6_duplicate_exhaust/{test_set_6_duplicate_exhaust_expected_cvr_cdf.json => test_set_6_duplicate_exhaust_expected_cdf_cvr.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/test_set_7_duplicate_skip_to_next/{test_set_7_duplicate_skip_to_next_expected_cvr_cdf.json => test_set_7_duplicate_skip_to_next_expected_cdf_cvr.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/test_set_8_multi_cdf/{test_set_8_multi_cdf_expected_cvr_cdf.json => test_set_8_multi_cdf_expected_cdf_cvr.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/test_set_multi_winner_fractional_threshold/{test_set_multi_winner_fractional_threshold_expected_cvr_cdf.json => test_set_multi_winner_fractional_threshold_expected_cdf_cvr.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/test_set_multi_winner_whole_threshold/{test_set_multi_winner_whole_threshold_expected_cvr_cdf.json => test_set_multi_winner_whole_threshold_expected_cdf_cvr.json} (100%) diff --git a/src/test/resources/network/brightspots/rcv/test_data/aliases_cdf_json/aliases_cdf_json_expected_cvr_cdf.json b/src/test/resources/network/brightspots/rcv/test_data/aliases_cdf_json/aliases_cdf_json_expected_cdf_cvr.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/aliases_cdf_json/aliases_cdf_json_expected_cvr_cdf.json rename to src/test/resources/network/brightspots/rcv/test_data/aliases_cdf_json/aliases_cdf_json_expected_cdf_cvr.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/batch_example/batch_example_expected_cvr_cdf.json b/src/test/resources/network/brightspots/rcv/test_data/batch_example/batch_example_expected_cdf_cvr.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/batch_example/batch_example_expected_cvr_cdf.json rename to src/test/resources/network/brightspots/rcv/test_data/batch_example/batch_example_expected_cdf_cvr.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/conversions_from_cdf/conversions_from_cdf_expected_cvr_cdf.json b/src/test/resources/network/brightspots/rcv/test_data/conversions_from_cdf/conversions_from_cdf_expected_cdf_cvr.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/conversions_from_cdf/conversions_from_cdf_expected_cvr_cdf.json rename to src/test/resources/network/brightspots/rcv/test_data/conversions_from_cdf/conversions_from_cdf_expected_cdf_cvr.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/conversions_from_dominion/conversions_from_dominion_expected_cvr_cdf.json b/src/test/resources/network/brightspots/rcv/test_data/conversions_from_dominion/conversions_from_dominion_expected_cdf_cvr.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/conversions_from_dominion/conversions_from_dominion_expected_cvr_cdf.json rename to src/test/resources/network/brightspots/rcv/test_data/conversions_from_dominion/conversions_from_dominion_expected_cdf_cvr.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/conversions_from_ess/conversions_from_ess_expected_cvr_cdf.json b/src/test/resources/network/brightspots/rcv/test_data/conversions_from_ess/conversions_from_ess_expected_cdf_cvr.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/conversions_from_ess/conversions_from_ess_expected_cvr_cdf.json rename to src/test/resources/network/brightspots/rcv/test_data/conversions_from_ess/conversions_from_ess_expected_cdf_cvr.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/precinct_example/precinct_example_expected_cvr_cdf.json b/src/test/resources/network/brightspots/rcv/test_data/precinct_example/precinct_example_expected_cdf_cvr.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/precinct_example/precinct_example_expected_cvr_cdf.json rename to src/test/resources/network/brightspots/rcv/test_data/precinct_example/precinct_example_expected_cdf_cvr.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/test_set_0_skipped_first_choice/test_set_0_skipped_first_choice_expected_cvr_cdf.json b/src/test/resources/network/brightspots/rcv/test_data/test_set_0_skipped_first_choice/test_set_0_skipped_first_choice_expected_cdf_cvr.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/test_set_0_skipped_first_choice/test_set_0_skipped_first_choice_expected_cvr_cdf.json rename to src/test/resources/network/brightspots/rcv/test_data/test_set_0_skipped_first_choice/test_set_0_skipped_first_choice_expected_cdf_cvr.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/test_set_1_exhaust_at_overvote/test_set_1_exhaust_at_overvote_expected_cvr_cdf.json b/src/test/resources/network/brightspots/rcv/test_data/test_set_1_exhaust_at_overvote/test_set_1_exhaust_at_overvote_expected_cdf_cvr.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/test_set_1_exhaust_at_overvote/test_set_1_exhaust_at_overvote_expected_cvr_cdf.json rename to src/test/resources/network/brightspots/rcv/test_data/test_set_1_exhaust_at_overvote/test_set_1_exhaust_at_overvote_expected_cdf_cvr.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/test_set_2_overvote_skip_to_next/test_set_2_overvote_skip_to_next_expected_cvr_cdf.json b/src/test/resources/network/brightspots/rcv/test_data/test_set_2_overvote_skip_to_next/test_set_2_overvote_skip_to_next_expected_cdf_cvr.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/test_set_2_overvote_skip_to_next/test_set_2_overvote_skip_to_next_expected_cvr_cdf.json rename to src/test/resources/network/brightspots/rcv/test_data/test_set_2_overvote_skip_to_next/test_set_2_overvote_skip_to_next_expected_cdf_cvr.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/test_set_3_skipped_choice_exhaust/test_set_3_skipped_choice_exhaust_expected_cvr_cdf.json b/src/test/resources/network/brightspots/rcv/test_data/test_set_3_skipped_choice_exhaust/test_set_3_skipped_choice_exhaust_expected_cdf_cvr.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/test_set_3_skipped_choice_exhaust/test_set_3_skipped_choice_exhaust_expected_cvr_cdf.json rename to src/test/resources/network/brightspots/rcv/test_data/test_set_3_skipped_choice_exhaust/test_set_3_skipped_choice_exhaust_expected_cdf_cvr.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/test_set_4_skipped_choice_next/test_set_4_skipped_choice_next_expected_cvr_cdf.json b/src/test/resources/network/brightspots/rcv/test_data/test_set_4_skipped_choice_next/test_set_4_skipped_choice_next_expected_cdf_cvr.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/test_set_4_skipped_choice_next/test_set_4_skipped_choice_next_expected_cvr_cdf.json rename to src/test/resources/network/brightspots/rcv/test_data/test_set_4_skipped_choice_next/test_set_4_skipped_choice_next_expected_cdf_cvr.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/test_set_5_two_skipped_choice_exhaust/test_set_5_two_skipped_choice_exhaust_expected_cvr_cdf.json b/src/test/resources/network/brightspots/rcv/test_data/test_set_5_two_skipped_choice_exhaust/test_set_5_two_skipped_choice_exhaust_expected_cdf_cvr.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/test_set_5_two_skipped_choice_exhaust/test_set_5_two_skipped_choice_exhaust_expected_cvr_cdf.json rename to src/test/resources/network/brightspots/rcv/test_data/test_set_5_two_skipped_choice_exhaust/test_set_5_two_skipped_choice_exhaust_expected_cdf_cvr.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/test_set_6_duplicate_exhaust/test_set_6_duplicate_exhaust_expected_cvr_cdf.json b/src/test/resources/network/brightspots/rcv/test_data/test_set_6_duplicate_exhaust/test_set_6_duplicate_exhaust_expected_cdf_cvr.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/test_set_6_duplicate_exhaust/test_set_6_duplicate_exhaust_expected_cvr_cdf.json rename to src/test/resources/network/brightspots/rcv/test_data/test_set_6_duplicate_exhaust/test_set_6_duplicate_exhaust_expected_cdf_cvr.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/test_set_7_duplicate_skip_to_next/test_set_7_duplicate_skip_to_next_expected_cvr_cdf.json b/src/test/resources/network/brightspots/rcv/test_data/test_set_7_duplicate_skip_to_next/test_set_7_duplicate_skip_to_next_expected_cdf_cvr.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/test_set_7_duplicate_skip_to_next/test_set_7_duplicate_skip_to_next_expected_cvr_cdf.json rename to src/test/resources/network/brightspots/rcv/test_data/test_set_7_duplicate_skip_to_next/test_set_7_duplicate_skip_to_next_expected_cdf_cvr.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/test_set_8_multi_cdf/test_set_8_multi_cdf_expected_cvr_cdf.json b/src/test/resources/network/brightspots/rcv/test_data/test_set_8_multi_cdf/test_set_8_multi_cdf_expected_cdf_cvr.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/test_set_8_multi_cdf/test_set_8_multi_cdf_expected_cvr_cdf.json rename to src/test/resources/network/brightspots/rcv/test_data/test_set_8_multi_cdf/test_set_8_multi_cdf_expected_cdf_cvr.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/test_set_multi_winner_fractional_threshold/test_set_multi_winner_fractional_threshold_expected_cvr_cdf.json b/src/test/resources/network/brightspots/rcv/test_data/test_set_multi_winner_fractional_threshold/test_set_multi_winner_fractional_threshold_expected_cdf_cvr.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/test_set_multi_winner_fractional_threshold/test_set_multi_winner_fractional_threshold_expected_cvr_cdf.json rename to src/test/resources/network/brightspots/rcv/test_data/test_set_multi_winner_fractional_threshold/test_set_multi_winner_fractional_threshold_expected_cdf_cvr.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/test_set_multi_winner_whole_threshold/test_set_multi_winner_whole_threshold_expected_cvr_cdf.json b/src/test/resources/network/brightspots/rcv/test_data/test_set_multi_winner_whole_threshold/test_set_multi_winner_whole_threshold_expected_cdf_cvr.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/test_set_multi_winner_whole_threshold/test_set_multi_winner_whole_threshold_expected_cvr_cdf.json rename to src/test/resources/network/brightspots/rcv/test_data/test_set_multi_winner_whole_threshold/test_set_multi_winner_whole_threshold_expected_cdf_cvr.json From b7f6708ed4ed7770442cceb9e904660b64fafe11 Mon Sep 17 00:00:00 2001 From: yezr <8996546+yezr@users.noreply.github.com> Date: Mon, 21 Oct 2024 14:32:47 -0400 Subject: [PATCH 06/17] refator to make explicit the difference between a results file (what we previously referred to as the summary files) and an output file (the results files plus rctab_cvr and cdf_cvr) --- .../rcv/GuiTabulateController.java | 2 +- .../{ResultsWriter.java => OutputWriter.java} | 120 +++++++++--------- .../brightspots/rcv/StreamingCvrReader.java | 2 +- .../network/brightspots/rcv/Tabulator.java | 10 +- .../brightspots/rcv/TabulatorSession.java | 22 ++-- .../brightspots/rcv/TabulatorTests.java | 36 +++--- 6 files changed, 97 insertions(+), 95 deletions(-) rename src/main/java/network/brightspots/rcv/{ResultsWriter.java => OutputWriter.java} (92%) diff --git a/src/main/java/network/brightspots/rcv/GuiTabulateController.java b/src/main/java/network/brightspots/rcv/GuiTabulateController.java index 4ca57cda4..c382070ac 100644 --- a/src/main/java/network/brightspots/rcv/GuiTabulateController.java +++ b/src/main/java/network/brightspots/rcv/GuiTabulateController.java @@ -233,7 +233,7 @@ private void watchParseCvrServiceProgress(Service service) { // and calculate the width of the filename column perSourceCvrCountTable.getItems().clear(); int maxFilenameLength = 0; - for (ResultsWriter.CvrSourceData sourceData : data.getCvrSourcesData()) { + for (OutputWriter.CvrSourceData sourceData : data.getCvrSourcesData()) { String countString = String.format("%,d", sourceData.getNumCvrs()); String fileString = new File(sourceData.source.getFilePath()).getName(); perSourceCvrCountTable.getItems().add(new Pair<>(fileString, countString)); diff --git a/src/main/java/network/brightspots/rcv/ResultsWriter.java b/src/main/java/network/brightspots/rcv/OutputWriter.java similarity index 92% rename from src/main/java/network/brightspots/rcv/ResultsWriter.java rename to src/main/java/network/brightspots/rcv/OutputWriter.java index 51197b9ac..2f9b218c5 100644 --- a/src/main/java/network/brightspots/rcv/ResultsWriter.java +++ b/src/main/java/network/brightspots/rcv/OutputWriter.java @@ -57,7 +57,7 @@ import org.apache.commons.csv.CSVFormat; import org.apache.commons.csv.CSVPrinter; -class ResultsWriter { +class OutputWriter { private static final String CDF_CONTEST_ID = "contest-001"; private static final String CDF_ELECTION_ID = "election-001"; private static final String CDF_GPU_ID = "gpu-election"; @@ -89,7 +89,7 @@ class ResultsWriter { StatusForRound.EXHAUSTED_CHOICE, StatusForRound.INVALIDATED_BY_REPEATED_RANKING); - public enum ResultType { + public enum OutputType { SUMMARY_CSV("summary_report", "csv"), DETAILED_CSV("detailed_report", "csv"), DETAILED_JSON("detailed_report", "json"), @@ -99,7 +99,7 @@ public enum ResultType { private final String basename; private final String extension; - ResultType(String basename, String extension) { + OutputType(String basename, String extension) { this.basename = basename; this.extension = extension; } @@ -113,27 +113,29 @@ public String getExtension() { } } - public static class ResultTypeAndSlice { + // Core traits of any output file + // Includes helpers for the work we need to do with the Identifiers to write the actual files themselves + public static class OutputFileIdentifiers { // Since sanitizing Slice IDs can cause filename collisions, ensure each non-sanitized // Slice ID is given a unique sanitized name. private static final Dictionary sliceIdToUniqueSanitizedId = new Hashtable<>(); // This is a set of the values in sanitizerCollisionResolution to ensure there are no collisions // in the resulting sanitized names. private static final HashSet uniqueSanitizedIds = new HashSet<>(); - private final ResultType resultType; + private final OutputType outputType; private final boolean isSlice; private final TabulateBySlice slice; private final String sliceId; - ResultTypeAndSlice(ResultType resultType) { - this.resultType = resultType; + OutputFileIdentifiers(OutputType outputType) { + this.outputType = outputType; this.isSlice = false; slice = null; sliceId = null; } - ResultTypeAndSlice(ResultType resultType, TabulateBySlice slice, String sliceId) { - this.resultType = resultType; + OutputFileIdentifiers(OutputType outputType, TabulateBySlice slice, String sliceId) { + this.outputType = outputType; this.isSlice = true; this.slice = slice; this.sliceId = sliceId; @@ -161,10 +163,10 @@ public Path getPath(String directory, String prefix, String modifier, Integer se parts.add(sanitizeSliceWithoutCollisions(sliceId)); parts.add(slice.toLowerString()); } - parts.add(resultType.getBasename()); + parts.add(outputType.getBasename()); String filenameWithoutExt = String.join("_", parts); - return Path.of(directory, "%s.%s".formatted(filenameWithoutExt, resultType.getExtension())); + return Path.of(directory, "%s.%s".formatted(filenameWithoutExt, outputType.getExtension())); } private String sanitizeSliceWithoutCollisions(String sliceId) { @@ -276,22 +278,22 @@ private static List>> getCandidatesWithRanksList return sortedCandidatesWithRanks; } - ResultsWriter setRoundToResidualSurplus(Map roundToResidualSurplus) { + OutputWriter setRoundToResidualSurplus(Map roundToResidualSurplus) { this.roundToResidualSurplus = roundToResidualSurplus; return this; } - ResultsWriter setNumRounds(int numRounds) { + OutputWriter setNumRounds(int numRounds) { this.numRounds = numRounds; return this; } - ResultsWriter setSliceIds(SliceIdSet sliceIds) { + OutputWriter setSliceIds(SliceIdSet sliceIds) { this.sliceIds = sliceIds; return this; } - ResultsWriter setCandidatesToRoundEliminated(Map candidatesToRoundEliminated) { + OutputWriter setCandidatesToRoundEliminated(Map candidatesToRoundEliminated) { // roundToEliminatedCandidates is the inverse of candidatesToRoundEliminated map, // so we can look up who got eliminated for each round roundToEliminatedCandidates = new HashMap<>(); @@ -302,7 +304,7 @@ ResultsWriter setCandidatesToRoundEliminated(Map candidatesToRo return this; } - ResultsWriter setWinnerToRound(Map winnerToRound) { + OutputWriter setWinnerToRound(Map winnerToRound) { // very similar to the logic in setCandidatesToRoundEliminated above roundToWinningCandidates = new HashMap<>(); for (var entry : winnerToRound.entrySet()) { @@ -312,21 +314,21 @@ ResultsWriter setWinnerToRound(Map winnerToRound) { return this; } - ResultsWriter setContestConfig(ContestConfig config) { + OutputWriter setContestConfig(ContestConfig config) { this.config = config; return this; } - ResultsWriter setTimestampString(String timestampString) { + OutputWriter setTimestampString(String timestampString) { this.timestampString = timestampString; return this; } - // creates summary files for the votes split by a TabulateBySlice + // creates results files for the votes split by a TabulateBySlice // param: roundTalliesBySlice is map from a slice type to the round-by-round vote tallies // param: tallyTransfersBySlice is a map from a slice type to tally transfers for that slice // param: candidateOrder is to allow a consistent ordering of candidates, including across slices - void generateBySliceSummaryFiles( + void generateBySliceResultsFiles( Tabulator.BreakdownBySlice roundTalliesBySlice, Tabulator.BreakdownBySlice tallyTransfersBySlice, List candidateOrder) @@ -336,37 +338,37 @@ void generateBySliceSummaryFiles( String sliceId = entry.getKey(); RoundTallies roundTallies = entry.getValue(); TallyTransfers tallyTransfers = tallyTransfersBySlice.get(slice, sliceId); - ResultTypeAndSlice resultTypeAndSliceCsv = - new ResultTypeAndSlice(ResultType.DETAILED_CSV, slice, sliceId); - ResultTypeAndSlice resultTypeAndSliceJson = - new ResultTypeAndSlice(ResultType.DETAILED_JSON, slice, sliceId); - generateSummaryCsv(roundTallies, candidateOrder, resultTypeAndSliceCsv); - generateSummaryJson(roundTallies, tallyTransfers, resultTypeAndSliceJson); + OutputFileIdentifiers outputFileIdentifiersCsv = + new OutputFileIdentifiers(OutputType.DETAILED_CSV, slice, sliceId); + OutputFileIdentifiers outputFileIdentifiersJson = + new OutputFileIdentifiers(OutputType.DETAILED_JSON, slice, sliceId); + generateResultsCsv(roundTallies, candidateOrder, outputFileIdentifiersCsv); + generateResultsJson(roundTallies, tallyTransfers, outputFileIdentifiersJson); } } } - private AuditableFile createAuditableFile(ResultTypeAndSlice resultTypeAndSlice) { + private AuditableFile createAuditableFile(OutputFileIdentifiers outputFileIdentifiers) { Integer sequentialId = null; if (config.isMultiSeatSequentialWinnerTakesAllEnabled()) { sequentialId = config.getSequentialWinners().size() + 1; } - return new AuditableFile(resultTypeAndSlice.getPath( + return new AuditableFile(outputFileIdentifiers.getPath( config.getOutputDirectory(), timestampString, sequentialId)); } - // create a summary spreadsheet .csv file + // create a results .csv file // param: roundTallies is the round-by-count count of votes per candidate // param: candidateOrder is to allow a consistent ordering of candidates, including across slices // param: resultTypeAndSlice must only have type DETAILED_CSV or SUMMARY_CSV - private void generateSummaryCsv( + private void generateResultsCsv( RoundTallies roundTallies, List candidateOrder, - ResultTypeAndSlice resultTypeAndSlice) throws IOException { - if (resultTypeAndSlice.resultType != ResultType.SUMMARY_CSV - && resultTypeAndSlice.resultType != ResultType.DETAILED_CSV) { + OutputFileIdentifiers outputFileIdentifiers) throws IOException { + if (outputFileIdentifiers.outputType != OutputType.SUMMARY_CSV + && outputFileIdentifiers.outputType != OutputType.DETAILED_CSV) { throw new IllegalArgumentException("ResultFile provided non-CSV type " - + resultTypeAndSlice.resultType); + + outputFileIdentifiers.outputType); } // Check that all candidates are included in the candidate order Set expectedCandidates = roundTallies.get(1).getCandidates(); @@ -378,7 +380,7 @@ private void generateSummaryCsv( + "\nProvided: " + providedCandidates); } - AuditableFile csvFile = createAuditableFile(resultTypeAndSlice); + AuditableFile csvFile = createAuditableFile(outputFileIdentifiers); Logger.info("Generating summary spreadsheet: %s...", csvFile.getAbsolutePath()); CSVPrinter csvPrinter; @@ -394,7 +396,7 @@ private void generateSummaryCsv( BigDecimal winningThreshold = roundTallies.get(numRounds).getWinningThreshold(); addContestInformationRows(csvPrinter, winningThreshold, - resultTypeAndSlice.slice, resultTypeAndSlice.sliceId); + outputFileIdentifiers.slice, outputFileIdentifiers.sliceId); addContestSummaryRows(csvPrinter, roundTallies.get(1)); csvPrinter.print("Rounds"); for (int round = 1; round <= numRounds; round++) { @@ -404,10 +406,10 @@ private void generateSummaryCsv( } csvPrinter.println(); - csvPrinter.print(resultTypeAndSlice.isSlice ? "Eliminated*" : "Eliminated"); + csvPrinter.print(outputFileIdentifiers.isSlice ? "Eliminated*" : "Eliminated"); printActionSummary(csvPrinter, roundToEliminatedCandidates); - csvPrinter.print(resultTypeAndSlice.isSlice ? "Elected*" : "Elected"); + csvPrinter.print(outputFileIdentifiers.isSlice ? "Elected*" : "Elected"); printActionSummary(csvPrinter, roundToWinningCandidates); // For each candidate: for each round: output total votes @@ -463,7 +465,7 @@ private void generateSummaryCsv( } csvPrinter.println(); - if (!resultTypeAndSlice.isSlice) { + if (!outputFileIdentifiers.isSlice) { csvPrinter.print("Current Round Threshold"); for (int round = 1; round <= numRounds; round++) { csvPrinter.print(roundTallies.get(round).getWinningThreshold()); @@ -473,7 +475,7 @@ private void generateSummaryCsv( csvPrinter.println(); } - if (resultTypeAndSlice.resultType == ResultType.DETAILED_CSV) { + if (outputFileIdentifiers.outputType == OutputType.DETAILED_CSV) { for (StatusForRound status : STATUSES_TO_PRINT) { csvPrinter.print(status.getTitleCaseKey()); @@ -525,7 +527,7 @@ private void generateSummaryCsv( // whether the value in the final round is positive. // Note that this concept only makes sense when we're reporting the overall tabulation, so we // omit it when generating results at the individual by-slice level. - if (!resultTypeAndSlice.isSlice && roundToResidualSurplus.get(numRounds).signum() == 1) { + if (!outputFileIdentifiers.isSlice && roundToResidualSurplus.get(numRounds).signum() == 1) { csvPrinter.print("Residual surplus"); for (int round = 1; round <= numRounds; round++) { csvPrinter.print(roundToResidualSurplus.get(round)); @@ -552,11 +554,11 @@ private void generateSummaryCsv( csvPrinter.println(); } - if (resultTypeAndSlice.isSlice) { + if (outputFileIdentifiers.isSlice) { csvPrinter.println(); csvPrinter.print(String.format("*Elect/Eliminate decisions are from the full contest. " + "All other results on this report are at the %s level.", - resultTypeAndSlice.slice.toLowerString())); + outputFileIdentifiers.slice.toLowerString())); csvPrinter.println(); } @@ -652,16 +654,16 @@ private void addContestInformationRows(CSVPrinter csvPrinter, } // creates a summary spreadsheet and JSON for the full contest (as opposed to a specific slice) - void generateOverallSummaryFiles( + void generateContestResultFiles( RoundTallies roundTallies, TallyTransfers tallyTransfers, List candidateOrder) throws IOException { - generateSummaryCsv(roundTallies, candidateOrder, - new ResultTypeAndSlice(ResultType.SUMMARY_CSV)); - generateSummaryCsv(roundTallies, candidateOrder, - new ResultTypeAndSlice(ResultType.DETAILED_CSV)); - generateSummaryJson(roundTallies, tallyTransfers, - new ResultTypeAndSlice(ResultType.DETAILED_JSON)); + generateResultsCsv(roundTallies, candidateOrder, + new OutputFileIdentifiers(OutputType.SUMMARY_CSV)); + generateResultsCsv(roundTallies, candidateOrder, + new OutputFileIdentifiers(OutputType.DETAILED_CSV)); + generateResultsJson(roundTallies, tallyTransfers, + new OutputFileIdentifiers(OutputType.DETAILED_JSON)); } // Write CastVoteRecords for the specified contest to the provided folder, @@ -678,8 +680,8 @@ String writeRcTabCvrCsv( // Put the input filename in the output filename in case contestId isn't unique -- // knowing that it's possible that if both the filename AND the contestId isn't unique, // this will fail. - ResultTypeAndSlice resultTypeAndSlice = new ResultTypeAndSlice(ResultType.RCTAB_CVR); - AuditableFile auditableFile = createAuditableFile(resultTypeAndSlice); + OutputFileIdentifiers outputFileIdentifiers = new OutputFileIdentifiers(OutputType.RCTAB_CVR); + AuditableFile auditableFile = createAuditableFile(outputFileIdentifiers); try { Logger.info("Writing cast vote records in generic format to file: %s...", auditableFile.getAbsolutePath()); @@ -798,8 +800,8 @@ void generateCdfJson(List castVoteRecords) // generate GpUnitIds for precincts "geopolitical units" (can be a precinct or jurisdiction) gpUnitIds = generateGpUnitIds(); - ResultTypeAndSlice resultTypeAndSlice = new ResultTypeAndSlice(ResultType.CDF_CVR); - AuditableFile auditableFile = createAuditableFile(resultTypeAndSlice); + OutputFileIdentifiers outputFileIdentifiers = new OutputFileIdentifiers(OutputType.CDF_CVR); + AuditableFile auditableFile = createAuditableFile(outputFileIdentifiers); Logger.info("Generating cast vote record CDF JSON file: %s...", auditableFile.getAbsolutePath()); @@ -1032,12 +1034,12 @@ private Map generateCdfMapForElection() { } // create summary json data for use with external visualizer software, unit tests and other tools - private void generateSummaryJson( + private void generateResultsJson( RoundTallies roundTallies, TallyTransfers tallyTransfers, - ResultTypeAndSlice resultTypeAndSlice) + OutputFileIdentifiers outputFileIdentifiers) throws IOException { - AuditableFile jsonFile = createAuditableFile(resultTypeAndSlice); + AuditableFile jsonFile = createAuditableFile(outputFileIdentifiers); Logger.info("Generating summary JSON file: %s...", jsonFile.getAbsolutePath()); // config will contain contest configuration info @@ -1047,8 +1049,8 @@ private void generateSummaryJson( configData.put("jurisdiction", config.getContestJurisdiction()); configData.put("office", config.getContestOffice()); configData.put("date", config.getContestDate()); - if (resultTypeAndSlice.isSlice) { - configData.put(resultTypeAndSlice.slice.toLowerString(), resultTypeAndSlice.sliceId); + if (outputFileIdentifiers.isSlice) { + configData.put(outputFileIdentifiers.slice.toLowerString(), outputFileIdentifiers.sliceId); } BigDecimal numNoRankings = diff --git a/src/main/java/network/brightspots/rcv/StreamingCvrReader.java b/src/main/java/network/brightspots/rcv/StreamingCvrReader.java index 2e6443f5b..8bf1ffa89 100644 --- a/src/main/java/network/brightspots/rcv/StreamingCvrReader.java +++ b/src/main/java/network/brightspots/rcv/StreamingCvrReader.java @@ -181,7 +181,7 @@ private void endCvr() { handleEmptyCells(config.getMaxRankingsAllowedWhenNotSetToMaximum() + 1); } String computedCastVoteRecordId = - String.format("%s-%d", ResultsWriter.sanitizeStringForOutput(excelFileName), cvrIndex); + String.format("%s-%d", OutputWriter.sanitizeStringForOutput(excelFileName), cvrIndex); // add precinct ID if needed if (precinctColumnIndex != null) { diff --git a/src/main/java/network/brightspots/rcv/Tabulator.java b/src/main/java/network/brightspots/rcv/Tabulator.java index 0f44f5834..1f16c76b3 100644 --- a/src/main/java/network/brightspots/rcv/Tabulator.java +++ b/src/main/java/network/brightspots/rcv/Tabulator.java @@ -40,7 +40,7 @@ import javafx.util.Pair; import network.brightspots.rcv.CastVoteRecord.VoteOutcomeType; import network.brightspots.rcv.ContestConfig.TabulateBySlice; -import network.brightspots.rcv.ResultsWriter.RoundSnapshotDataMissingException; +import network.brightspots.rcv.OutputWriter.RoundSnapshotDataMissingException; final class Tabulator { @@ -794,8 +794,8 @@ private List doRegularElimination( // to generate the results spreadsheets // param: timestamp string to use when creating output filenames void generateSummaryFiles(String timestamp) throws IOException { - ResultsWriter writer = - new ResultsWriter() + OutputWriter writer = + new OutputWriter() .setNumRounds(currentRound) .setCandidatesToRoundEliminated(candidateToRoundEliminated) .setWinnerToRound(winnerToRound) @@ -805,8 +805,8 @@ void generateSummaryFiles(String timestamp) throws IOException { .setRoundToResidualSurplus(roundToResidualSurplus); List candidateOrder = roundTallies.get(1).getSortedCandidatesByTally(); - writer.generateOverallSummaryFiles(roundTallies, tallyTransfers, candidateOrder); - writer.generateBySliceSummaryFiles(roundTalliesBySlices, tallyTransfersBySlice, candidateOrder); + writer.generateContestResultFiles(roundTallies, tallyTransfers, candidateOrder); + writer.generateBySliceResultsFiles(roundTalliesBySlices, tallyTransfersBySlice, candidateOrder); if (config.isGenerateCdfJsonEnabled()) { try { diff --git a/src/main/java/network/brightspots/rcv/TabulatorSession.java b/src/main/java/network/brightspots/rcv/TabulatorSession.java index 037c4efd4..86bd362ff 100644 --- a/src/main/java/network/brightspots/rcv/TabulatorSession.java +++ b/src/main/java/network/brightspots/rcv/TabulatorSession.java @@ -38,7 +38,7 @@ import network.brightspots.rcv.ContestConfig.Provider; import network.brightspots.rcv.ContestConfig.UnrecognizedProviderException; import network.brightspots.rcv.FileUtils.UnableToCreateDirectoryException; -import network.brightspots.rcv.ResultsWriter.RoundSnapshotDataMissingException; +import network.brightspots.rcv.OutputWriter.RoundSnapshotDataMissingException; import network.brightspots.rcv.Tabulator.TabulationAbortedException; @SuppressWarnings("RedundantSuppression") @@ -115,8 +115,8 @@ boolean convertToCdf(BiConsumer progressUpdate) { } else { Tabulator.SliceIdSet sliceIds = new Tabulator(castVoteRecords.getCvrs(), config).getEnabledSliceIds(); - ResultsWriter writer = - new ResultsWriter() + OutputWriter writer = + new OutputWriter() .setNumRounds(0) .setSliceIds(sliceIds) .setContestConfig(config) @@ -338,7 +338,7 @@ private LoadedCvrData parseCastVoteRecords( boolean encounteredSourceProblem = false; // Per-source data for writing generic CSV - List cvrSourceData = new ArrayList<>(); + List cvrSourceData = new ArrayList<>(); // At each iteration of the following loop, we add records from another source file. for (int sourceIndex = 0; sourceIndex < config.rawConfig.cvrFileSources.size(); ++sourceIndex) { @@ -353,7 +353,7 @@ private LoadedCvrData parseCastVoteRecords( // Update the per-source data for the results writer cvrSourceData.add( - new ResultsWriter.CvrSourceData( + new OutputWriter.CvrSourceData( source, reader, sourceIndex, startIndex, castVoteRecords.size() - 1)); // Check for unrecognized candidates @@ -416,8 +416,8 @@ private LoadedCvrData parseCastVoteRecords( // Output the RCTab-CSV CVR if (shouldOutputRcTabCvr) { try { - ResultsWriter writer = - new ResultsWriter().setContestConfig(config).setTimestampString(timestampString); + OutputWriter writer = + new OutputWriter().setContestConfig(config).setTimestampString(timestampString); this.rctabCvrFilePath = writer.writeRcTabCvrCsv( castVoteRecords, @@ -461,11 +461,11 @@ public static class LoadedCvrData { private List cvrs; private final int numCvrs; - private final List cvrSourcesData; + private final List cvrSourcesData; private boolean isDiscarded; private final boolean doesMatchAllMetadata; - LoadedCvrData(List cvrs, List cvrSourcesData) { + LoadedCvrData(List cvrs, List cvrSourcesData) { this.cvrs = cvrs; this.successfullyReadAll = cvrs != null; this.numCvrs = cvrs != null ? cvrs.size() : 0; @@ -504,7 +504,7 @@ public int numCvrs() { return numCvrs; } - List getCvrSourcesData() { + List getCvrSourcesData() { return cvrSourcesData; } @@ -522,7 +522,7 @@ List getCvrs() { public void printSummary() { Logger.info("Cast Vote Record summary:"); - for (ResultsWriter.CvrSourceData sourceData : cvrSourcesData) { + for (OutputWriter.CvrSourceData sourceData : cvrSourcesData) { Logger.info("Source %d: %s", sourceData.sourceIndex + 1, sourceData.source.getFilePath()); Logger.info(" uses provider: %s", sourceData.source.getProvider()); Logger.info(" read %d cast vote records", sourceData.getNumCvrs()); diff --git a/src/test/java/network/brightspots/rcv/TabulatorTests.java b/src/test/java/network/brightspots/rcv/TabulatorTests.java index 3d2c72883..9dff21b5c 100644 --- a/src/test/java/network/brightspots/rcv/TabulatorTests.java +++ b/src/test/java/network/brightspots/rcv/TabulatorTests.java @@ -39,8 +39,8 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import network.brightspots.rcv.ResultsWriter.ResultTypeAndSlice; -import network.brightspots.rcv.ResultsWriter.ResultType; +import network.brightspots.rcv.OutputWriter.OutputFileIdentifiers; +import network.brightspots.rcv.OutputWriter.OutputType; import network.brightspots.rcv.Tabulator.TabulationAbortedException; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.DisplayName; @@ -241,12 +241,12 @@ private static void runTabulationTest(String stem, String expectedException, int numSlicedFilesChecked = 0; for (ContestConfig.TabulateBySlice slice : config.enabledSlices()) { for (String sliceName : session.loadSliceNamesFromCvrs(slice, config)) { - ResultsWriter.ResultTypeAndSlice resultTypeAndSliceJson = new ResultTypeAndSlice(ResultType.DETAILED_JSON, slice, sliceName); - ResultsWriter.ResultTypeAndSlice resultTypeAndSliceCsv = new ResultsWriter.ResultTypeAndSlice(ResultType.DETAILED_CSV, slice, sliceName); - if (compareFiles(config, stem, resultTypeAndSliceJson, timestampString, null, true)) { + OutputFileIdentifiers outputFileIdentifiersJson = new OutputFileIdentifiers(OutputType.DETAILED_JSON, slice, sliceName); + OutputFileIdentifiers outputFileIdentifiersCsv = new OutputFileIdentifiers(OutputType.DETAILED_CSV, slice, sliceName); + if (compareFiles(config, stem, outputFileIdentifiersJson, timestampString, null, true)) { numSlicedFilesChecked++; } - if (compareFiles(config, stem, resultTypeAndSliceCsv, timestampString, null, true)) { + if (compareFiles(config, stem, outputFileIdentifiersCsv, timestampString, null, true)) { numSlicedFilesChecked++; } } @@ -265,7 +265,7 @@ private static void runConvertToCdfTest(String stem) { String timestampString = session.getTimestampString(); ContestConfig config = ContestConfig.loadContestConfig(configPath); - compareFiles(config, stem, ResultType.CDF_CVR, timestampString, null, false); + compareFiles(config, stem, OutputType.CDF_CVR, timestampString, null, false); cleanOutputFolder(session); } @@ -329,11 +329,11 @@ private static void cleanOutputFolder(TabulatorSession session) { private static void compareFiles( ContestConfig config, String stem, String timestampString, Integer sequentialId) { - compareFiles(config, stem, ResultType.DETAILED_JSON, timestampString, sequentialId, false); - compareFiles(config, stem, ResultType.DETAILED_CSV, timestampString, sequentialId, false); + compareFiles(config, stem, OutputType.DETAILED_JSON, timestampString, sequentialId, false); + compareFiles(config, stem, OutputType.DETAILED_CSV, timestampString, sequentialId, false); compareExtendedSummaryToSummary(config, timestampString, sequentialId); if (config.isGenerateCdfJsonEnabled()) { - compareFiles(config, stem, ResultType.CDF_CVR, timestampString, sequentialId, false); + compareFiles(config, stem, OutputType.CDF_CVR, timestampString, sequentialId, false); } } @@ -343,15 +343,15 @@ private static void compareFiles( private static boolean compareFiles( ContestConfig config, String stem, - ResultType resultType, + OutputType outputType, String timestampString, Integer sequentialId, boolean onlyCheckIfExpectedFileExists) { - ResultsWriter.ResultTypeAndSlice actualResultTypeAndSlice = new ResultTypeAndSlice(resultType); + OutputFileIdentifiers actualOutputFileIdentifiers = new OutputFileIdentifiers(outputType); return compareFiles( config, stem, - actualResultTypeAndSlice, + actualOutputFileIdentifiers, timestampString, sequentialId, onlyCheckIfExpectedFileExists); @@ -364,13 +364,13 @@ private static boolean compareFiles( private static boolean compareFiles( ContestConfig config, String stem, - ResultsWriter.ResultTypeAndSlice actualResultTypeAndSlice, + OutputFileIdentifiers actualOutputFileIdentifiers, String timestampString, Integer sequentialId, boolean onlyCheckIfExpectedFileExists) { - String actualOutputPath = actualResultTypeAndSlice.getPath( + String actualOutputPath = actualOutputFileIdentifiers.getPath( config.getOutputDirectory(), timestampString, sequentialId).toAbsolutePath().toString(); - String expectedPath = actualResultTypeAndSlice.getPath(getTestDirectory(stem).toString(), + String expectedPath = actualOutputFileIdentifiers.getPath(getTestDirectory(stem).toString(), stem, "expected", sequentialId).toString(); Logger.info("Comparing files:\nGenerated: %s\nReference: %s", actualOutputPath, expectedPath); @@ -395,9 +395,9 @@ private static boolean compareFiles( private static void compareExtendedSummaryToSummary( ContestConfig config, String timestampString, Integer sequentialId) { String dir = config.getOutputDirectory(); - String summaryPath = new ResultTypeAndSlice(ResultType.SUMMARY_CSV).getPath( + String summaryPath = new OutputFileIdentifiers(OutputType.SUMMARY_CSV).getPath( dir, timestampString, sequentialId).toAbsolutePath().toString(); - String detailedPath = new ResultsWriter.ResultTypeAndSlice(ResultType.DETAILED_CSV).getPath( + String detailedPath = new OutputFileIdentifiers(OutputType.DETAILED_CSV).getPath( dir, timestampString, sequentialId).toAbsolutePath().toString(); try (BufferedReader brSummary = new BufferedReader(new FileReader(summaryPath, UTF_8)); From 36ee3549d4c0ba962a5beadbae51f0b5f2a4c9b7 Mon Sep 17 00:00:00 2001 From: yezr <8996546+yezr@users.noreply.github.com> Date: Thu, 24 Oct 2024 14:44:37 -0400 Subject: [PATCH 07/17] fix comment --- src/main/java/network/brightspots/rcv/OutputWriter.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/network/brightspots/rcv/OutputWriter.java b/src/main/java/network/brightspots/rcv/OutputWriter.java index 2f9b218c5..59a913fd5 100644 --- a/src/main/java/network/brightspots/rcv/OutputWriter.java +++ b/src/main/java/network/brightspots/rcv/OutputWriter.java @@ -360,7 +360,7 @@ private AuditableFile createAuditableFile(OutputFileIdentifiers outputFileIdenti // create a results .csv file // param: roundTallies is the round-by-count count of votes per candidate // param: candidateOrder is to allow a consistent ordering of candidates, including across slices - // param: resultTypeAndSlice must only have type DETAILED_CSV or SUMMARY_CSV + // param: outputFileIdentifiers must only have type DETAILED_CSV or SUMMARY_CSV private void generateResultsCsv( RoundTallies roundTallies, List candidateOrder, From 5780b409b7313a56dc57c5631ec6a44fdd55c100 Mon Sep 17 00:00:00 2001 From: Armin Samii Date: Tue, 8 Oct 2024 18:33:41 -0400 Subject: [PATCH 08/17] refactor how filenames are chosen --- .../brightspots/rcv/AuditableFile.java | 5 + .../brightspots/rcv/ResultsWriter.java | 272 ++++++++++-------- .../brightspots/rcv/TabulatorTests.java | 101 ++++--- 3 files changed, 220 insertions(+), 158 deletions(-) diff --git a/src/main/java/network/brightspots/rcv/AuditableFile.java b/src/main/java/network/brightspots/rcv/AuditableFile.java index 1a56d1cc0..3464f3431 100644 --- a/src/main/java/network/brightspots/rcv/AuditableFile.java +++ b/src/main/java/network/brightspots/rcv/AuditableFile.java @@ -19,12 +19,17 @@ import java.io.File; import java.io.IOException; import java.nio.file.Files; +import java.nio.file.Path; final class AuditableFile extends File { public AuditableFile(String pathname) { super(pathname); } + public AuditableFile(Path pathname) { + super(pathname.toAbsolutePath().toString()); + } + public void finalizeAndHash() { String hash = Utils.bytesToHex(FileUtils.getHashBytes(this, "SHA-512")); diff --git a/src/main/java/network/brightspots/rcv/ResultsWriter.java b/src/main/java/network/brightspots/rcv/ResultsWriter.java index f138184a6..dfcabc37f 100644 --- a/src/main/java/network/brightspots/rcv/ResultsWriter.java +++ b/src/main/java/network/brightspots/rcv/ResultsWriter.java @@ -34,13 +34,15 @@ import java.math.BigDecimal; import java.math.MathContext; import java.nio.file.Files; -import java.nio.file.Paths; +import java.nio.file.Path; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Collections; import java.util.Date; +import java.util.Dictionary; import java.util.HashMap; import java.util.HashSet; +import java.util.Hashtable; import java.util.LinkedList; import java.util.List; import java.util.Map; @@ -87,33 +89,116 @@ class ResultsWriter { StatusForRound.EXHAUSTED_CHOICE, StatusForRound.INVALIDATED_BY_REPEATED_RANKING); + public enum ResultType { + SUMMARY_REPORT("summary"/*"summary_report"*/, "csv"), + DETAILED_REPORT("extended_summary"/*"detailed_report"*/, "csv"), + JSON("summary", "json"), + CDF("cvr_cdf", "json"), + RCTAB_CVR("rctab_cvr", "csv"); - // visible for testing - @SuppressWarnings("WeakerAccess") - static String sequentialSuffixForOutputPath(String sequentialTabulationId) { - return sequentialTabulationId != null ? "_" + sequentialTabulationId : ""; + private final String basename; + private final String extension; + + ResultType(String basename, String extension) { + this.basename = basename; + this.extension = extension; + } + + public String getBasename() { + return basename; + } + + public String getExtension() { + return extension; + } } - // visible for testing - @SuppressWarnings("WeakerAccess") - static String getOutputFilePath( - String outputDirectory, - String outputType, - String timestampString, - String sequentialTabulationId) { - outputType = sanitizeStringForOutput(outputType); - String fileName = - String.format( - "%s_%s%s", - timestampString, outputType, sequentialSuffixForOutputPath(sequentialTabulationId)); - return Paths.get(outputDirectory, fileName).toAbsolutePath().toString(); + public static class ResultFile { + // Since sanitizing Slice IDs can cause filename collisions, ensure each non-sanitized + // Slice ID is given a unique sanitized name. + private static final Dictionary sliceIdToUniqueSanitizedId = new Hashtable<>(); + // This is a set of the values in sanitizerCollisionResolution to ensure there are no collisions + // in the resulting sanitized names. + private static final HashSet uniqueSanitizedIds = new HashSet<>(); + private final ResultType resultType; + private final boolean isSlice; + private final TabulateBySlice slice; + private final String sliceId; + + ResultFile(ResultType resultType) { + this.resultType = resultType; + this.isSlice = false; + slice = null; + sliceId = null; + } + + ResultFile(ResultType resultType, TabulateBySlice slice, String sliceId) { + this.resultType = resultType; + this.isSlice = true; + this.slice = slice; + this.sliceId = sliceId; + } + + // getPath helper without the modifier argument + public Path getPath(String directory, String prefix, Integer sequentialId) { + return getPath(directory, prefix, null, sequentialId); + } + + // The filename is an underscore-separated string containing all components needed + // to create a unique output file. The modifier is likely only used in tests, where + // it is set to "expected" to distinguish expected output files from actual output files. + public Path getPath(String directory, String prefix, String modifier, Integer sequentialId) { + List parts = new ArrayList<>(); + parts.add(prefix); + if (sequentialId != null) { + parts.add(sequentialId.toString()); + } + if (modifier != null) { + parts.add(modifier); + } + if (isSlice) { + assert slice != null; + parts.add(sanitizeSliceWithoutCollisions(sliceId)); + parts.add(slice.toLowerString()); + } + parts.add(resultType.getBasename()); + + String filenameWithoutExt = String.join("_", parts); + return Path.of(directory, "%s.%s".formatted(filenameWithoutExt, resultType.getExtension())); + } + + private String sanitizeSliceWithoutCollisions(String sliceId) { + String previousSanitizedSliceId = sliceIdToUniqueSanitizedId.get(sliceId); + String sanitizedSliceId; + + if (previousSanitizedSliceId != null) { + sanitizedSliceId = previousSanitizedSliceId; + } else { + sanitizedSliceId = sanitizeStringForOutput(sliceId); + + // In most cases, sanitizedSliceId will be unique and we can use it as-is. + // Here, we handle the case where it is not unique. + int increment = 1; + while (uniqueSanitizedIds.contains(sanitizedSliceId)) { + sanitizedSliceId = String.format("%s_%d", sanitizeStringForOutput(sliceId), increment); + increment++; + } + + uniqueSanitizedIds.add(sanitizedSliceId); + sliceIdToUniqueSanitizedId.put(sliceId, sanitizedSliceId); + } + + return sanitizedSliceId; + } + } static String sanitizeStringForOutput(String s) { return s == null ? "" : s.replaceAll("[^a-zA-Z0-9_\\-.]", "_"); } - private static void generateJsonFile(String path, Map json) throws IOException { + private static void generateJsonFile(AuditableFile outFile, Map json) + throws IOException { ObjectMapper mapper = new ObjectMapper(); // for improved legibility we sort alphabetically on keys mapper.configure(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS, true); @@ -121,7 +206,6 @@ private static void generateJsonFile(String path, Map json) thro module.addSerializer(BigDecimal.class, new ToStringSerializer()); mapper.registerModule(module); ObjectWriter jsonWriter = mapper.writer(new DefaultPrettyPrinter()); - AuditableFile outFile = new AuditableFile(path); try { jsonWriter.writeValue(outFile, json); @@ -129,7 +213,7 @@ private static void generateJsonFile(String path, Map json) thro } catch (IOException exception) { Logger.severe( "Error writing to JSON file: %s\n%s\nCheck the file path and permissions!", - path, exception); + outFile.getAbsolutePath(), exception); throw exception; } Logger.info("JSON file generated successfully."); @@ -192,32 +276,6 @@ private static List>> getCandidatesWithRanksList return sortedCandidatesWithRanks; } - // return a unique, valid string for this slice's output spreadsheet filename - private static String getFileStringForSlice( - ContestConfig.TabulateBySlice slice, String sliceId, Set filenames) { - String sanitized = "%s_%s".formatted(sanitizeStringForOutput(sliceId), slice.toLowerString()); - String filename = sanitized; - // appendNumber is used to find a unique filename (in practice this really shouldn't be - // necessary because different slice IDs shouldn't have the same sanitized name, but we're - // doing it here to be safe) - int appendNumber = 2; - while (filenames.contains(filename)) { - filename = sanitized + "_" + appendNumber++; - } - filenames.add(filename); - return filename; - } - - private String getOutputFilePathFromInstance(String outputType) { - String tabulationSequenceId = null; - if (config.isMultiSeatSequentialWinnerTakesAllEnabled()) { - int sequence = config.getSequentialWinners().size() + 1; - tabulationSequenceId = Integer.toString(sequence); - } - return getOutputFilePath( - config.getOutputDirectory(), outputType, timestampString, tabulationSequenceId); - } - ResultsWriter setRoundToResidualSurplus(Map roundToResidualSurplus) { this.roundToResidualSurplus = roundToResidualSurplus; return this; @@ -274,38 +332,25 @@ void generateBySliceSummaryFiles( List candidateOrder) throws IOException { for (ContestConfig.TabulateBySlice slice : config.enabledSlices()) { - Set filenames = new HashSet<>(); for (var entry : roundTalliesBySlice.get(slice).entrySet()) { String sliceId = entry.getKey(); RoundTallies roundTallies = entry.getValue(); TallyTransfers tallyTransfers = tallyTransfersBySlice.get(slice, sliceId); - String sliceFileString = getFileStringForSlice(slice, sliceId, filenames); - String outputPathCsv = getOutputFilePathFromInstance( - String.format("%s_extended_summary", sliceFileString)); - String outputPathJson = getOutputFilePathFromInstance( - String.format("%s_summary", sliceFileString)); - generateSummaryExtendedCsv(roundTallies, candidateOrder, slice, sliceId, outputPathCsv); - generateSummaryJson(roundTallies, tallyTransfers, slice, sliceId, outputPathJson); + ResultFile resultFileCsv = new ResultFile(ResultType.DETAILED_REPORT, slice, sliceId); + ResultFile resultFileJson = new ResultFile(ResultType.JSON, slice, sliceId); + generateSummaryCsv(roundTallies, candidateOrder, resultFileCsv); + generateSummaryJson(roundTallies, tallyTransfers, resultFileJson); } } } - private void generateSummaryExtendedCsv( - RoundTallies roundTallies, - List candidateOrder, - TabulateBySlice slice, - String sliceId, - String outputPath) throws IOException { - generateSummaryCsvHelper(roundTallies, candidateOrder, slice, sliceId, outputPath, true); - } - - private void generateSummaryCsv( - RoundTallies roundTallies, - List candidateOrder, - TabulateBySlice slice, - String sliceId, - String outputPath) throws IOException { - generateSummaryCsvHelper(roundTallies, candidateOrder, slice, sliceId, outputPath, false); + private AuditableFile createAuditableFile(ResultFile resultFile) { + Integer sequentialId = null; + if (config.isMultiSeatSequentialWinnerTakesAllEnabled()) { + sequentialId = config.getSequentialWinners().size() + 1; + } + return new AuditableFile(resultFile.getPath( + config.getOutputDirectory(), timestampString, sequentialId)); } // create a summary spreadsheet .csv file @@ -315,13 +360,15 @@ private void generateSummaryCsv( // param: sliceId indicates the specific slice ID we're reporting results for (null means all) // param: outputPath is the path to the output file, minus its extension // param: extended include additional details in the output file? - private void generateSummaryCsvHelper( + private void generateSummaryCsv( RoundTallies roundTallies, List candidateOrder, - TabulateBySlice slice, - String sliceId, - String outputPath, - boolean extended) throws IOException { + ResultFile resultFile) throws IOException { + if (resultFile.resultType != ResultType.SUMMARY_REPORT + && resultFile.resultType != ResultType.DETAILED_REPORT) { + throw new IllegalArgumentException("ResultFile provided non-CSV type " + + resultFile.resultType); + } // Check that all candidates are included in the candidate order Set expectedCandidates = roundTallies.get(1).getCandidates(); Set providedCandidates = new HashSet<>(candidateOrder); @@ -332,7 +379,7 @@ private void generateSummaryCsvHelper( + "\nProvided: " + providedCandidates); } - AuditableFile csvFile = new AuditableFile(outputPath + ".csv"); + AuditableFile csvFile = createAuditableFile(resultFile); Logger.info("Generating summary spreadsheet: %s...", csvFile.getAbsolutePath()); CSVPrinter csvPrinter; @@ -347,7 +394,7 @@ private void generateSummaryCsvHelper( } BigDecimal winningThreshold = roundTallies.get(numRounds).getWinningThreshold(); - addContestInformationRows(csvPrinter, winningThreshold, slice, sliceId); + addContestInformationRows(csvPrinter, winningThreshold, resultFile.slice, resultFile.sliceId); addContestSummaryRows(csvPrinter, roundTallies.get(1)); csvPrinter.print("Rounds"); for (int round = 1; round <= numRounds; round++) { @@ -357,11 +404,10 @@ private void generateSummaryCsvHelper( } csvPrinter.println(); - final boolean isSlice = !isNullOrBlank(sliceId); - csvPrinter.print(isSlice ? "Eliminated*" : "Eliminated"); + csvPrinter.print(resultFile.isSlice ? "Eliminated*" : "Eliminated"); printActionSummary(csvPrinter, roundToEliminatedCandidates); - csvPrinter.print(isSlice ? "Elected*" : "Elected"); + csvPrinter.print(resultFile.isSlice ? "Elected*" : "Elected"); printActionSummary(csvPrinter, roundToWinningCandidates); // For each candidate: for each round: output total votes @@ -417,7 +463,7 @@ private void generateSummaryCsvHelper( } csvPrinter.println(); - if (!isSlice) { + if (!resultFile.isSlice) { csvPrinter.print("Current Round Threshold"); for (int round = 1; round <= numRounds; round++) { csvPrinter.print(roundTallies.get(round).getWinningThreshold()); @@ -427,7 +473,7 @@ private void generateSummaryCsvHelper( csvPrinter.println(); } - if (extended) { + if (resultFile.resultType == ResultType.DETAILED_REPORT) { for (StatusForRound status : STATUSES_TO_PRINT) { csvPrinter.print(status.getTitleCaseKey()); @@ -479,7 +525,7 @@ private void generateSummaryCsvHelper( // whether the value in the final round is positive. // Note that this concept only makes sense when we're reporting the overall tabulation, so we // omit it when generating results at the individual by-slice level. - if (!isSlice && roundToResidualSurplus.get(numRounds).signum() == 1) { + if (!resultFile.isSlice && roundToResidualSurplus.get(numRounds).signum() == 1) { csvPrinter.print("Residual surplus"); for (int round = 1; round <= numRounds; round++) { csvPrinter.print(roundToResidualSurplus.get(round)); @@ -506,10 +552,11 @@ private void generateSummaryCsvHelper( csvPrinter.println(); } - if (isSlice) { + if (resultFile.isSlice) { csvPrinter.println(); csvPrinter.print(String.format("*Elect/Eliminate decisions are from the full contest. " - + "All other results on this report are at the %s level.", slice.toLowerString())); + + "All other results on this report are at the %s level.", + resultFile.slice.toLowerString())); csvPrinter.println(); } @@ -518,7 +565,7 @@ private void generateSummaryCsvHelper( csvPrinter.close(); csvFile.finalizeAndHash(); } catch (IOException exception) { - Logger.severe("Error saving file: %s\n%s", outputPath, exception); + Logger.severe("Error saving file: %s\n%s", resultFile.resultType, exception); throw exception; } Logger.info("Summary spreadsheet generated successfully."); @@ -609,11 +656,9 @@ void generateOverallSummaryFiles( RoundTallies roundTallies, TallyTransfers tallyTransfers, List candidateOrder) throws IOException { - String outputPathSummary = getOutputFilePathFromInstance("summary"); - String outputPathExtended = getOutputFilePathFromInstance("extended_summary"); - generateSummaryExtendedCsv(roundTallies, candidateOrder, null, null, outputPathExtended); - generateSummaryCsv(roundTallies, candidateOrder, null, null, outputPathSummary); - generateSummaryJson(roundTallies, tallyTransfers, null, null, outputPathSummary); + generateSummaryCsv(roundTallies, candidateOrder, new ResultFile(ResultType.SUMMARY_REPORT)); + generateSummaryCsv(roundTallies, candidateOrder, new ResultFile(ResultType.DETAILED_REPORT)); + generateSummaryJson(roundTallies, tallyTransfers, new ResultFile(ResultType.JSON)); } // Write CastVoteRecords for the specified contest to the provided folder, @@ -630,18 +675,13 @@ String writeRcTabCvrCsv( // Put the input filename in the output filename in case contestId isn't unique -- // knowing that it's possible that if both the filename AND the contestId isn't unique, // this will fail. - AuditableFile outputFile = new AuditableFile( - getOutputFilePath( - csvOutputFolder, - "rctab_cvr", - timestampString, - null) - + ".csv"); + ResultFile resultFile = new ResultFile(ResultType.RCTAB_CVR); + AuditableFile auditableFile = createAuditableFile(resultFile); try { Logger.info("Writing cast vote records in generic format to file: %s...", - outputFile.getAbsolutePath()); + auditableFile.getAbsolutePath()); CSVPrinter csvPrinter; - BufferedWriter writer = Files.newBufferedWriter(outputFile.toPath()); + BufferedWriter writer = Files.newBufferedWriter(auditableFile.toPath()); CSVFormat format = CSVFormat.DEFAULT.builder().setNullString("").build(); csvPrinter = new CSVPrinter(writer, format); // print header: @@ -701,14 +741,14 @@ String writeRcTabCvrCsv( // finalize the file csvPrinter.flush(); csvPrinter.close(); - fileWritten = outputFile.getAbsolutePath(); - Logger.info("Successfully wrote: %s", outputFile.getAbsolutePath()); + fileWritten = auditableFile.getAbsolutePath(); + Logger.info("Successfully wrote: %s", auditableFile.getAbsolutePath()); - outputFile.finalizeAndHash(); + auditableFile.finalizeAndHash(); } catch (IOException exception) { Logger.severe( "Error writing cast vote records in generic format to output path: %s\n%s", - outputFile.getAbsolutePath(), exception); + auditableFile.getAbsolutePath(), exception); throw exception; } return fileWritten; @@ -755,8 +795,10 @@ void generateCdfJson(List castVoteRecords) // generate GpUnitIds for precincts "geopolitical units" (can be a precinct or jurisdiction) gpUnitIds = generateGpUnitIds(); - String outputPath = getOutputFilePathFromInstance("cvr_cdf") + ".json"; - Logger.info("Generating cast vote record CDF JSON file: %s...", outputPath); + ResultFile resultFile = new ResultFile(ResultType.CDF); + AuditableFile auditableFile = createAuditableFile(resultFile); + Logger.info("Generating cast vote record CDF JSON file: %s...", + auditableFile.getAbsolutePath()); HashMap outputJson = new HashMap<>(); outputJson.put("CVR", generateCdfMapForCvrs(castVoteRecords)); @@ -777,7 +819,7 @@ void generateCdfJson(List castVoteRecords) outputJson.put("Version", "1.0.0"); outputJson.put("@type", "CVR.CastVoteRecordReport"); - generateJsonFile(outputPath, outputJson); + generateJsonFile(auditableFile, outputJson); } // build map from precinctId => GpUnitId, as lookups are done by precinctId during cvr creation @@ -990,12 +1032,10 @@ private Map generateCdfMapForElection() { private void generateSummaryJson( RoundTallies roundTallies, TallyTransfers tallyTransfers, - TabulateBySlice slice, - String sliceId, - String outputPath) + ResultFile resultFile) throws IOException { - String jsonPath = outputPath + ".json"; - Logger.info("Generating summary JSON file: %s...", jsonPath); + AuditableFile jsonFile = createAuditableFile(resultFile); + Logger.info("Generating summary JSON file: %s...", jsonFile.getAbsolutePath()); // config will contain contest configuration info HashMap configData = new HashMap<>(); @@ -1004,8 +1044,8 @@ private void generateSummaryJson( configData.put("jurisdiction", config.getContestJurisdiction()); configData.put("office", config.getContestOffice()); configData.put("date", config.getContestDate()); - if (!isNullOrBlank(sliceId)) { - configData.put(slice.toLowerString(), sliceId); + if (resultFile.isSlice) { + configData.put(resultFile.slice.toLowerString(), resultFile.sliceId); } BigDecimal numNoRankings = @@ -1045,7 +1085,7 @@ private void generateSummaryJson( outputJson.put("config", configData); outputJson.put("results", results); - generateJsonFile(jsonPath, outputJson); + generateJsonFile(jsonFile, outputJson); } private Map updateCandidateNamesInTally(RoundTally roundSummary) { diff --git a/src/test/java/network/brightspots/rcv/TabulatorTests.java b/src/test/java/network/brightspots/rcv/TabulatorTests.java index d732d4f6a..8141f9406 100644 --- a/src/test/java/network/brightspots/rcv/TabulatorTests.java +++ b/src/test/java/network/brightspots/rcv/TabulatorTests.java @@ -34,10 +34,13 @@ import java.io.FileReader; import java.io.IOException; import java.nio.file.Files; +import java.nio.file.Path; import java.nio.file.Paths; import java.util.HashMap; import java.util.List; import java.util.Map; +import network.brightspots.rcv.ResultsWriter.ResultFile; +import network.brightspots.rcv.ResultsWriter.ResultType; import network.brightspots.rcv.Tabulator.TabulationAbortedException; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.DisplayName; @@ -187,11 +190,16 @@ private static boolean fileCompareLineByLine(String path1, String path2) { return result; } + // given stem and suffix returns path to file in test asset folder + private static Path getTestDirectory(String stem) { + return Paths.get(System.getProperty("user.dir"), TEST_ASSET_FOLDER, stem); + } + // given stem and suffix returns path to file in test asset folder private static String getTestFilePath(String stem, String suffix) { - return Paths.get(System.getProperty("user.dir"), TEST_ASSET_FOLDER, stem, stem + suffix) - .toAbsolutePath() - .toString(); + Path directory = getTestDirectory(stem); + String filename = stem + suffix; + return Paths.get(directory.toString(), filename).toAbsolutePath().toString(); } private static void runTabulationTest(String testStem) { @@ -224,7 +232,7 @@ private static void runTabulationTest(String stem, String expectedException, if (config.isMultiSeatSequentialWinnerTakesAllEnabled()) { for (int i = 1; i <= config.getNumberOfWinners(); i++) { - compareFiles(config, stem, timestampString, Integer.toString(i)); + compareFiles(config, stem, timestampString, i); } } else { compareFiles(config, stem, timestampString, null); @@ -233,14 +241,12 @@ private static void runTabulationTest(String stem, String expectedException, int numSlicedFilesChecked = 0; for (ContestConfig.TabulateBySlice slice : config.enabledSlices()) { for (String sliceName : session.loadSliceNamesFromCvrs(slice, config)) { - String outputTypeJson = ResultsWriter.sanitizeStringForOutput( - String.format("%s_%s_summary", sliceName, slice.toLowerString())); - String outputTypeCsv = ResultsWriter.sanitizeStringForOutput( - String.format("%s_%s_extended_summary", sliceName, slice.toLowerString())); - if (compareFiles(config, stem, outputTypeJson, ".json", timestampString, null, true)) { + ResultFile resultFileJson = new ResultFile(ResultType.JSON, slice, sliceName); + ResultFile resultFileCsv = new ResultFile(ResultType.DETAILED_REPORT, slice, sliceName); + if (compareFiles(config, stem, resultFileJson, timestampString, null, true)) { numSlicedFilesChecked++; } - if (compareFiles(config, stem, outputTypeCsv, ".csv", timestampString, null, true)) { + if (compareFiles(config, stem, resultFileCsv, timestampString, null, true)) { numSlicedFilesChecked++; } } @@ -259,7 +265,7 @@ private static void runConvertToCdfTest(String stem) { String timestampString = session.getTimestampString(); ContestConfig config = ContestConfig.loadContestConfig(configPath); - compareFiles(config, stem, "cvr_cdf", ".json", timestampString, null, false); + compareFiles(config, stem, ResultType.CDF, timestampString, null, false); cleanOutputFolder(session); } @@ -322,15 +328,35 @@ private static void cleanOutputFolder(TabulatorSession session) { } private static void compareFiles( - ContestConfig config, String stem, String timestampString, String sequentialId) { - compareFiles(config, stem, "summary", ".json", timestampString, sequentialId, false); - compareFiles(config, stem, "extended_summary", ".csv", timestampString, sequentialId, false); + ContestConfig config, String stem, String timestampString, Integer sequentialId) { + compareFiles(config, stem, ResultType.JSON, timestampString, sequentialId, false); + compareFiles(config, stem, ResultType.DETAILED_REPORT, timestampString, sequentialId, false); compareExtendedSummaryToSummary(config, timestampString, sequentialId); if (config.isGenerateCdfJsonEnabled()) { - compareFiles(config, stem, "cvr_cdf", ".json", timestampString, sequentialId, false); + compareFiles(config, stem, ResultType.CDF, timestampString, sequentialId, false); } } + /** + * Helper comparison for non-slice files. + */ + private static boolean compareFiles( + ContestConfig config, + String stem, + ResultType resultType, + String timestampString, + Integer sequentialId, + boolean onlyCheckIfExpectedFileExists) { + ResultFile actualResultFile = new ResultFile(resultType); + return compareFiles( + config, + stem, + actualResultFile, + timestampString, + sequentialId, + onlyCheckIfExpectedFileExists); + } + /** * Returns whether the files were compared at all. * If they were compared and not equal, the test will fail. @@ -338,22 +364,14 @@ private static void compareFiles( private static boolean compareFiles( ContestConfig config, String stem, - String outputType, - String extension, + ResultFile actualResultFile, String timestampString, - String sequentialId, + Integer sequentialId, boolean onlyCheckIfExpectedFileExists) { - String actualOutputPath = - ResultsWriter.getOutputFilePath( - config.getOutputDirectory(), outputType, timestampString, sequentialId) - + extension; - String expectedPath = - getTestFilePath( - stem, - ResultsWriter.sequentialSuffixForOutputPath(sequentialId) - + "_expected_" - + outputType - + extension); + String actualOutputPath = actualResultFile.getPath( + config.getOutputDirectory(), timestampString, sequentialId).toAbsolutePath().toString(); + String expectedPath = actualResultFile.getPath(getTestDirectory(stem).toString(), + stem, "expected", sequentialId).toString(); Logger.info("Comparing files:\nGenerated: %s\nReference: %s", actualOutputPath, expectedPath); boolean didCompare = true; @@ -375,20 +393,19 @@ private static boolean compareFiles( * extended file except for the inactive ballot breakdown. */ private static void compareExtendedSummaryToSummary( - ContestConfig config, String timestampString, String sequentialId) { - String summaryPath = ResultsWriter.getOutputFilePath( - config.getOutputDirectory(), "summary", timestampString, sequentialId) - + ".csv"; - String extendedPath = ResultsWriter.getOutputFilePath( - config.getOutputDirectory(), "extended_summary", timestampString, sequentialId) - + ".csv"; + ContestConfig config, String timestampString, Integer sequentialId) { + String dir = config.getOutputDirectory(); + String summaryPath = new ResultFile(ResultType.SUMMARY_REPORT).getPath( + dir, timestampString, sequentialId).toAbsolutePath().toString(); + String detailedPath = new ResultFile(ResultType.DETAILED_REPORT).getPath( + dir, timestampString, sequentialId).toAbsolutePath().toString(); try (BufferedReader brSummary = new BufferedReader(new FileReader(summaryPath, UTF_8)); - BufferedReader brExtended = new BufferedReader(new FileReader(extendedPath, UTF_8))) { + BufferedReader brDetailed = new BufferedReader(new FileReader(detailedPath, UTF_8))) { while (true) { - String lineExtended = brExtended.readLine(); + String lineDetailed = brDetailed.readLine(); // If the extended file has reached its end, then the non-extended file must have too - if (lineExtended == null) { + if (lineDetailed == null) { assertNull(brSummary.readLine(), "Extended file is missing a line"); return; } @@ -396,7 +413,7 @@ private static void compareExtendedSummaryToSummary( // If the extended file should be excluded, continue without moving the file pointer // in the non-extended file. For now, there's only one type of row excluded, and they // happen to all start with "Inactive Ballots by" - if (lineExtended.startsWith("Inactive Ballots by")) { + if (lineDetailed.startsWith("Inactive Ballots by")) { continue; } @@ -404,9 +421,9 @@ private static void compareExtendedSummaryToSummary( // in both files. String lineSummary = brSummary.readLine(); assertNotNull(lineSummary, "Summary file is missing a line"); - if (!lineSummary.equals(lineExtended)) { + if (!lineSummary.equals(lineDetailed)) { fail("Line differes in extended vs non-extended CSV: \n%s\n%s".formatted( - lineSummary, lineExtended)); + lineSummary, lineDetailed)); } } } catch (FileNotFoundException exception) { From 4b9363dc95c03fa82d1c9cec75c4e0d798d09d40 Mon Sep 17 00:00:00 2001 From: Armin Samii Date: Tue, 8 Oct 2024 19:01:21 -0400 Subject: [PATCH 09/17] move files to new recommended name --- .../brightspots/rcv/ResultsWriter.java | 22 +++++++++---------- .../brightspots/rcv/TabulatorTests.java | 12 +++++----- ...IS_W-13_P-09_precinct_detailed_report.csv} | 0 ...S_W-13_P-09_precinct_detailed_report.json} | 0 ...LIS_W-1_P-01_precinct_detailed_report.csv} | 0 ...IS_W-1_P-01_precinct_detailed_report.json} | 0 ...apolis_mayor_expected_detailed_report.csv} | 0 ...polis_mayor_expected_detailed_report.json} | 0 ..._mayor_scale_expected_detailed_report.csv} | 0 ...mayor_scale_expected_detailed_report.json} | 0 ...eapolis_park_expected_detailed_report.csv} | 0 ...apolis_park_expected_detailed_report.json} | 0 ...k_bottoms_up_expected_detailed_report.csv} | 0 ..._bottoms_up_expected_detailed_report.json} | 0 ...is_park_hare_expected_detailed_report.csv} | 0 ...s_park_hare_expected_detailed_report.json} | 0 ...sequential_1_expected_detailed_report.csv} | 0 ...equential_1_expected_detailed_report.json} | 0 ...sequential_2_expected_detailed_report.csv} | 0 ...equential_2_expected_detailed_report.json} | 0 ...sequential_3_expected_detailed_report.csv} | 0 ...equential_3_expected_detailed_report.json} | 0 ...rtland_mayor_expected_detailed_report.csv} | 0 ...tland_mayor_expected_detailed_report.json} | 0 ..._mayor_codes_expected_detailed_report.csv} | 0 ...mayor_codes_expected_detailed_report.json} | 0 ...IS_W-13_P-13_precinct_detailed_report.csv} | 0 ...S_W-13_P-13_precinct_detailed_report.json} | 0 ...LIS_W-1_P-01_precinct_detailed_report.csv} | 0 ...IS_W-1_P-01_precinct_detailed_report.json} | 0 ...apolis_mayor_expected_detailed_report.csv} | 0 ...polis_mayor_expected_detailed_report.json} | 0 ...rnor_primary_expected_detailed_report.csv} | 0 ...nor_primary_expected_detailed_report.json} | 0 ...ses_cdf_json_expected_detailed_report.csv} | 0 ...es_cdf_json_expected_detailed_report.json} | 0 ...ses_ess_xlsx_expected_detailed_report.csv} | 0 ...es_ess_xlsx_expected_detailed_report.json} | 0 ...APOLIS_W-1_P-02_batch_detailed_report.csv} | 0 ...POLIS_W-1_P-04_batch_detailed_report.json} | 0 ...atch_example_expected_detailed_report.csv} | 0 ...tch_example_expected_detailed_report.json} | 0 ...nsas_primary_expected_detailed_report.csv} | 0 ...sas_primary_expected_detailed_report.json} | 0 ...inline_comma_expected_detailed_report.csv} | 0 ...nline_comma_expected_detailed_report.json} | 0 ...ulation_test_expected_detailed_report.csv} | 0 ...lation_test_expected_detailed_report.json} | 0 ...ination_test_expected_detailed_report.csv} | 0 ...nation_test_expected_detailed_report.json} | 0 ..._header_test_expected_detailed_report.csv} | 0 ...header_test_expected_detailed_report.json} | 0 ...inion_alaska_expected_detailed_report.csv} | 0 ...nion_alaska_expected_detailed_report.json} | 0 ...inion_kansas_expected_detailed_report.csv} | 0 ...nion_kansas_expected_detailed_report.json} | 0 ...n_multi_file_expected_detailed_report.csv} | 0 ..._multi_file_expected_detailed_report.json} | 0 ...recinct_data_expected_detailed_report.csv} | 0 ...ecinct_data_expected_detailed_report.json} | 0 ...nion_wyoming_expected_detailed_report.csv} | 0 ...ion_wyoming_expected_detailed_report.json} | 0 ...plicate_test_expected_detailed_report.csv} | 0 ...licate_test_expected_detailed_report.json} | 0 ...xcluded_test_expected_detailed_report.csv} | 0 ...cluded_test_expected_detailed_report.json} | 0 ...e_continuing_expected_detailed_report.csv} | 0 ..._continuing_expected_detailed_report.json} | 0 ...reshold_test_expected_detailed_report.csv} | 0 ...eshold_test_expected_detailed_report.json} | 0 ...breaker_test_expected_detailed_report.csv} | 0 ...reaker_test_expected_detailed_report.json} | 0 ...ric_csv_test_expected_detailed_report.csv} | 0 ...ic_csv_test_expected_detailed_report.json} | 0 ...school_board_expected_detailed_report.csv} | 0 ...chool_board_expected_detailed_report.json} | 0 ...nty_officers_expected_detailed_report.csv} | 0 ...ty_officers_expected_detailed_report.json} | 0 ...reshold_test_expected_detailed_report.csv} | 0 ...eshold_test_expected_detailed_report.json} | 0 ...at_threshold_expected_detailed_report.csv} | 0 ...t_threshold_expected_detailed_report.json} | 0 ...expected_pc1_precinct_detailed_report.csv} | 0 ...expected_pc2_precinct_detailed_report.csv} | 0 ...xpected_pc2_precinct_detailed_report.json} | 0 ...IS_W-13_P-13_precinct_detailed_report.csv} | 0 ...S_W-13_P-13_precinct_detailed_report.json} | 0 ...inct_example_expected_detailed_report.csv} | 0 ...nct_example_expected_detailed_report.json} | 0 ..._precinct_id_precinct_detailed_report.csv} | 0 ...precinct_id_precinct_detailed_report.json} | 0 ...n_candidates_expected_detailed_report.csv} | 0 ..._candidates_expected_detailed_report.json} | 0 ...th_threshold_expected_detailed_report.csv} | 0 ...h_threshold_expected_detailed_report.json} | 0 ...eat_uwi_test_expected_detailed_report.csv} | 0 ...at_uwi_test_expected_detailed_report.json} | 0 ...st_xml_cdf_2_expected_detailed_report.csv} | 0 ...t_xml_cdf_2_expected_detailed_report.json} | 0 ...LIS_W-1_P-02_precinct_detailed_report.csv} | 0 ...IS_W-1_P-02_precinct_detailed_report.json} | 0 ...inct_example_expected_detailed_report.csv} | 0 ...nct_example_expected_detailed_report.json} | 0 ...with_batch_1_expected_detailed_report.csv} | 0 ...ith_batch_1_expected_detailed_report.json} | 0 ...with_batch_2_expected_detailed_report.csv} | 0 ...ith_batch_2_expected_detailed_report.json} | 0 ...with_batch_3_expected_detailed_report.csv} | 0 ...ith_batch_3_expected_detailed_report.json} | 0 ..._until_two_1_expected_detailed_report.csv} | 0 ...until_two_1_expected_detailed_report.json} | 0 ..._until_two_2_expected_detailed_report.csv} | 0 ...until_two_2_expected_detailed_report.json} | 0 ..._until_two_3_expected_detailed_report.csv} | 0 ...until_two_3_expected_detailed_report.json} | 0 ...to_next_test_expected_detailed_report.csv} | 0 ...o_next_test_expected_detailed_report.json} | 0 ...n_early_test_expected_detailed_report.csv} | 0 ..._early_test_expected_detailed_report.json} | 0 ...first_choice_expected_detailed_report.csv} | 0 ...irst_choice_expected_detailed_report.json} | 0 ..._at_overvote_expected_detailed_report.csv} | 0 ...at_overvote_expected_detailed_report.json} | 0 ...skip_to_next_expected_detailed_report.csv} | 0 ...kip_to_next_expected_detailed_report.json} | 0 ...oice_exhaust_expected_detailed_report.csv} | 0 ...ice_exhaust_expected_detailed_report.json} | 0 ..._choice_next_expected_detailed_report.csv} | 0 ...choice_next_expected_detailed_report.json} | 0 ...oice_exhaust_expected_detailed_report.csv} | 0 ...ice_exhaust_expected_detailed_report.json} | 0 ...cate_exhaust_expected_detailed_report.csv} | 0 ...ate_exhaust_expected_detailed_report.json} | 0 ...skip_to_next_expected_detailed_report.csv} | 0 ...kip_to_next_expected_detailed_report.json} | 0 ..._8_multi_cdf_expected_detailed_report.csv} | 0 ...8_multi_cdf_expected_detailed_report.json} | 0 ...er_per_round_expected_detailed_report.csv} | 0 ...r_per_round_expected_detailed_report.json} | 0 ...al_threshold_expected_detailed_report.csv} | 0 ...l_threshold_expected_detailed_report.json} | 0 ...le_threshold_expected_detailed_report.csv} | 0 ...e_threshold_expected_detailed_report.json} | 0 ...te_delimiter_expected_detailed_report.csv} | 0 ...e_delimiter_expected_detailed_report.json} | 0 ...red_write_in_expected_detailed_report.csv} | 0 ...ed_write_in_expected_detailed_report.json} | 0 ...utation_test_expected_detailed_report.csv} | 0 ...tation_test_expected_detailed_report.json} | 0 ..._random_test_expected_detailed_report.csv} | 0 ...random_test_expected_detailed_report.json} | 0 ...ak_seed_test_expected_detailed_report.csv} | 0 ...k_seed_test_expected_detailed_report.json} | 0 ..._config_test_expected_detailed_report.csv} | 0 ...config_test_expected_detailed_report.json} | 0 ...ef_of_police_expected_detailed_report.csv} | 0 ...f_of_police_expected_detailed_report.json} | 0 ...city_coroner_expected_detailed_report.csv} | 0 ...ity_coroner_expected_detailed_report.json} | 0 ...uncil_member_expected_detailed_report.csv} | 0 ...ncil_member_expected_detailed_report.json} | 0 ...f_city_mayor_expected_detailed_report.csv} | 0 ..._city_mayor_expected_detailed_report.json} | 0 ...ax_collector_expected_detailed_report.csv} | 0 ...x_collector_expected_detailed_report.json} | 0 ...unty_coroner_expected_detailed_report.csv} | 0 ...nty_coroner_expected_detailed_report.json} | 0 ...unty_sheriff_expected_detailed_report.csv} | 0 ...nty_sheriff_expected_detailed_report.json} | 0 ...not_win_test_expected_detailed_report.csv} | 0 ...ot_win_test_expected_detailed_report.json} | 0 171 files changed, 17 insertions(+), 17 deletions(-) rename src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_mayor/{2013_minneapolis_mayor_expected_MINNEAPOLIS_W-13_P-09_precinct_extended_summary.csv => 2013_minneapolis_mayor_expected_MINNEAPOLIS_W-13_P-09_precinct_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_mayor/{2013_minneapolis_mayor_expected_MINNEAPOLIS_W-13_P-09_precinct_summary.json => 2013_minneapolis_mayor_expected_MINNEAPOLIS_W-13_P-09_precinct_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_mayor/{2013_minneapolis_mayor_expected_MINNEAPOLIS_W-1_P-01_precinct_extended_summary.csv => 2013_minneapolis_mayor_expected_MINNEAPOLIS_W-1_P-01_precinct_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_mayor/{2013_minneapolis_mayor_expected_MINNEAPOLIS_W-1_P-01_precinct_summary.json => 2013_minneapolis_mayor_expected_MINNEAPOLIS_W-1_P-01_precinct_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_mayor/{2013_minneapolis_mayor_expected_extended_summary.csv => 2013_minneapolis_mayor_expected_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_mayor/{2013_minneapolis_mayor_expected_summary.json => 2013_minneapolis_mayor_expected_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_mayor_scale/{2013_minneapolis_mayor_scale_expected_extended_summary.csv => 2013_minneapolis_mayor_scale_expected_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_mayor_scale/{2013_minneapolis_mayor_scale_expected_summary.json => 2013_minneapolis_mayor_scale_expected_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_park/{2013_minneapolis_park_expected_extended_summary.csv => 2013_minneapolis_park_expected_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_park/{2013_minneapolis_park_expected_summary.json => 2013_minneapolis_park_expected_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_park_bottoms_up/{2013_minneapolis_park_bottoms_up_expected_extended_summary.csv => 2013_minneapolis_park_bottoms_up_expected_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_park_bottoms_up/{2013_minneapolis_park_bottoms_up_expected_summary.json => 2013_minneapolis_park_bottoms_up_expected_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_park_hare/{2013_minneapolis_park_hare_expected_extended_summary.csv => 2013_minneapolis_park_hare_expected_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_park_hare/{2013_minneapolis_park_hare_expected_summary.json => 2013_minneapolis_park_hare_expected_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_park_sequential/{2013_minneapolis_park_sequential_1_expected_extended_summary.csv => 2013_minneapolis_park_sequential_1_expected_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_park_sequential/{2013_minneapolis_park_sequential_1_expected_summary.json => 2013_minneapolis_park_sequential_1_expected_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_park_sequential/{2013_minneapolis_park_sequential_2_expected_extended_summary.csv => 2013_minneapolis_park_sequential_2_expected_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_park_sequential/{2013_minneapolis_park_sequential_2_expected_summary.json => 2013_minneapolis_park_sequential_2_expected_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_park_sequential/{2013_minneapolis_park_sequential_3_expected_extended_summary.csv => 2013_minneapolis_park_sequential_3_expected_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_park_sequential/{2013_minneapolis_park_sequential_3_expected_summary.json => 2013_minneapolis_park_sequential_3_expected_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/2015_portland_mayor/{2015_portland_mayor_expected_extended_summary.csv => 2015_portland_mayor_expected_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/2015_portland_mayor/{2015_portland_mayor_expected_summary.json => 2015_portland_mayor_expected_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/2015_portland_mayor_codes/{2015_portland_mayor_codes_expected_extended_summary.csv => 2015_portland_mayor_codes_expected_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/2015_portland_mayor_codes/{2015_portland_mayor_codes_expected_summary.json => 2015_portland_mayor_codes_expected_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/2017_minneapolis_mayor/{2017_minneapolis_mayor_expected_MINNEAPOLIS_W-13_P-13_precinct_extended_summary.csv => 2017_minneapolis_mayor_expected_MINNEAPOLIS_W-13_P-13_precinct_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/2017_minneapolis_mayor/{2017_minneapolis_mayor_expected_MINNEAPOLIS_W-13_P-13_precinct_summary.json => 2017_minneapolis_mayor_expected_MINNEAPOLIS_W-13_P-13_precinct_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/2017_minneapolis_mayor/{2017_minneapolis_mayor_expected_MINNEAPOLIS_W-1_P-01_precinct_extended_summary.csv => 2017_minneapolis_mayor_expected_MINNEAPOLIS_W-1_P-01_precinct_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/2017_minneapolis_mayor/{2017_minneapolis_mayor_expected_MINNEAPOLIS_W-1_P-01_precinct_summary.json => 2017_minneapolis_mayor_expected_MINNEAPOLIS_W-1_P-01_precinct_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/2017_minneapolis_mayor/{2017_minneapolis_mayor_expected_extended_summary.csv => 2017_minneapolis_mayor_expected_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/2017_minneapolis_mayor/{2017_minneapolis_mayor_expected_summary.json => 2017_minneapolis_mayor_expected_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/2018_maine_governor_primary/{2018_maine_governor_primary_expected_extended_summary.csv => 2018_maine_governor_primary_expected_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/2018_maine_governor_primary/{2018_maine_governor_primary_expected_summary.json => 2018_maine_governor_primary_expected_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/aliases_cdf_json/{aliases_cdf_json_expected_extended_summary.csv => aliases_cdf_json_expected_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/aliases_cdf_json/{aliases_cdf_json_expected_summary.json => aliases_cdf_json_expected_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/aliases_ess_xlsx/{aliases_ess_xlsx_expected_extended_summary.csv => aliases_ess_xlsx_expected_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/aliases_ess_xlsx/{aliases_ess_xlsx_expected_summary.json => aliases_ess_xlsx_expected_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/batch_example/{batch_example_expected_MINNEAPOLIS_W-1_P-02_batch_extended_summary.csv => batch_example_expected_MINNEAPOLIS_W-1_P-02_batch_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/batch_example/{batch_example_expected_MINNEAPOLIS_W-1_P-04_batch_summary.json => batch_example_expected_MINNEAPOLIS_W-1_P-04_batch_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/batch_example/{batch_example_expected_extended_summary.csv => batch_example_expected_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/batch_example/{batch_example_expected_summary.json => batch_example_expected_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/clear_ballot_kansas_primary/{clear_ballot_kansas_primary_expected_extended_summary.csv => clear_ballot_kansas_primary_expected_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/clear_ballot_kansas_primary/{clear_ballot_kansas_primary_expected_summary.json => clear_ballot_kansas_primary_expected_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/clear_ballot_with_inline_comma/{clear_ballot_with_inline_comma_expected_extended_summary.csv => clear_ballot_with_inline_comma_expected_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/clear_ballot_with_inline_comma/{clear_ballot_with_inline_comma_expected_summary.json => clear_ballot_with_inline_comma_expected_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/continue_tabulation_test/{continue_tabulation_test_expected_extended_summary.csv => continue_tabulation_test_expected_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/continue_tabulation_test/{continue_tabulation_test_expected_summary.json => continue_tabulation_test_expected_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/continue_until_two_with_batch_elimination_test/{continue_until_two_with_batch_elimination_test_expected_extended_summary.csv => continue_until_two_with_batch_elimination_test_expected_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/continue_until_two_with_batch_elimination_test/{continue_until_two_with_batch_elimination_test_expected_summary.json => continue_until_two_with_batch_elimination_test_expected_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/csv_missing_header_test/{csv_missing_header_test_expected_extended_summary.csv => csv_missing_header_test_expected_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/csv_missing_header_test/{csv_missing_header_test_expected_summary.json => csv_missing_header_test_expected_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/dominion_alaska/{dominion_alaska_expected_extended_summary.csv => dominion_alaska_expected_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/dominion_alaska/{dominion_alaska_expected_summary.json => dominion_alaska_expected_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/dominion_kansas/{dominion_kansas_expected_extended_summary.csv => dominion_kansas_expected_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/dominion_kansas/{dominion_kansas_expected_summary.json => dominion_kansas_expected_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/dominion_multi_file/{dominion_multi_file_expected_extended_summary.csv => dominion_multi_file_expected_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/dominion_multi_file/{dominion_multi_file_expected_summary.json => dominion_multi_file_expected_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/dominion_no_precinct_data/{dominion_no_precinct_data_expected_extended_summary.csv => dominion_no_precinct_data_expected_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/dominion_no_precinct_data/{dominion_no_precinct_data_expected_summary.json => dominion_no_precinct_data_expected_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/dominion_wyoming/{dominion_wyoming_expected_extended_summary.csv => dominion_wyoming_expected_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/dominion_wyoming/{dominion_wyoming_expected_summary.json => dominion_wyoming_expected_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/duplicate_test/{duplicate_test_expected_extended_summary.csv => duplicate_test_expected_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/duplicate_test/{duplicate_test_expected_summary.json => duplicate_test_expected_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/excluded_test/{excluded_test_expected_extended_summary.csv => excluded_test_expected_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/excluded_test/{excluded_test_expected_summary.json => excluded_test_expected_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/exhaust_if_multiple_continuing/{exhaust_if_multiple_continuing_expected_extended_summary.csv => exhaust_if_multiple_continuing_expected_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/exhaust_if_multiple_continuing/{exhaust_if_multiple_continuing_expected_summary.json => exhaust_if_multiple_continuing_expected_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/first_round_determines_threshold_test/{first_round_determines_threshold_test_expected_extended_summary.csv => first_round_determines_threshold_test_expected_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/first_round_determines_threshold_test/{first_round_determines_threshold_test_expected_summary.json => first_round_determines_threshold_test_expected_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/first_round_determines_threshold_tiebreaker_test/{first_round_determines_threshold_tiebreaker_test_expected_extended_summary.csv => first_round_determines_threshold_tiebreaker_test_expected_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/first_round_determines_threshold_tiebreaker_test/{first_round_determines_threshold_tiebreaker_test_expected_summary.json => first_round_determines_threshold_tiebreaker_test_expected_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/generic_csv_test/{generic_csv_test_expected_extended_summary.csv => generic_csv_test_expected_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/generic_csv_test/{generic_csv_test_expected_summary.json => generic_csv_test_expected_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/hart_cedar_park_school_board/{hart_cedar_park_school_board_expected_extended_summary.csv => hart_cedar_park_school_board_expected_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/hart_cedar_park_school_board/{hart_cedar_park_school_board_expected_summary.json => hart_cedar_park_school_board_expected_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/hart_travis_county_officers/{hart_travis_county_officers_expected_extended_summary.csv => hart_travis_county_officers_expected_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/hart_travis_county_officers/{hart_travis_county_officers_expected_summary.json => hart_travis_county_officers_expected_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/minimum_threshold_test/{minimum_threshold_test_expected_extended_summary.csv => minimum_threshold_test_expected_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/minimum_threshold_test/{minimum_threshold_test_expected_summary.json => minimum_threshold_test_expected_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/minneapolis_multi_seat_threshold/{minneapolis_multi_seat_threshold_expected_extended_summary.csv => minneapolis_multi_seat_threshold_expected_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/minneapolis_multi_seat_threshold/{minneapolis_multi_seat_threshold_expected_summary.json => minneapolis_multi_seat_threshold_expected_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/minneapolis_multi_seat_threshold/{minneapolis_multi_seat_threshold_expected_pc1_precinct_extended_summary.csv => minneapolis_multi_seat_threshold_expected_pc1_precinct_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/minneapolis_multi_seat_threshold/{minneapolis_multi_seat_threshold_expected_pc2_precinct_extended_summary.csv => minneapolis_multi_seat_threshold_expected_pc2_precinct_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/minneapolis_multi_seat_threshold/{minneapolis_multi_seat_threshold_expected_pc2_precinct_summary.json => minneapolis_multi_seat_threshold_expected_pc2_precinct_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/missing_precinct_example/{missing_precinct_example_expected_MINNEAPOLIS_W-13_P-13_precinct_extended_summary.csv => missing_precinct_example_expected_MINNEAPOLIS_W-13_P-13_precinct_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/missing_precinct_example/{missing_precinct_example_expected_MINNEAPOLIS_W-13_P-13_precinct_summary.json => missing_precinct_example_expected_MINNEAPOLIS_W-13_P-13_precinct_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/missing_precinct_example/{missing_precinct_example_expected_extended_summary.csv => missing_precinct_example_expected_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/missing_precinct_example/{missing_precinct_example_expected_summary.json => missing_precinct_example_expected_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/missing_precinct_example/{missing_precinct_example_expected_missing_precinct_id_precinct_extended_summary.csv => missing_precinct_example_expected_missing_precinct_id_precinct_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/missing_precinct_example/{missing_precinct_example_expected_missing_precinct_id_precinct_summary.json => missing_precinct_example_expected_missing_precinct_id_precinct_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/more_winners_than_candidates/{more_winners_than_candidates_expected_extended_summary.csv => more_winners_than_candidates_expected_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/more_winners_than_candidates/{more_winners_than_candidates_expected_summary.json => more_winners_than_candidates_expected_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/multi_seat_bottoms_up_with_threshold/{multi_seat_bottoms_up_with_threshold_expected_extended_summary.csv => multi_seat_bottoms_up_with_threshold_expected_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/multi_seat_bottoms_up_with_threshold/{multi_seat_bottoms_up_with_threshold_expected_summary.json => multi_seat_bottoms_up_with_threshold_expected_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/multi_seat_uwi_test/{multi_seat_uwi_test_expected_extended_summary.csv => multi_seat_uwi_test_expected_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/multi_seat_uwi_test/{multi_seat_uwi_test_expected_summary.json => multi_seat_uwi_test_expected_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/nist_xml_cdf_2/{nist_xml_cdf_2_expected_extended_summary.csv => nist_xml_cdf_2_expected_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/nist_xml_cdf_2/{nist_xml_cdf_2_expected_summary.json => nist_xml_cdf_2_expected_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/precinct_example/{precinct_example_expected_MINNEAPOLIS_W-1_P-02_precinct_extended_summary.csv => precinct_example_expected_MINNEAPOLIS_W-1_P-02_precinct_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/precinct_example/{precinct_example_expected_MINNEAPOLIS_W-1_P-02_precinct_summary.json => precinct_example_expected_MINNEAPOLIS_W-1_P-02_precinct_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/precinct_example/{precinct_example_expected_extended_summary.csv => precinct_example_expected_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/precinct_example/{precinct_example_expected_summary.json => precinct_example_expected_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/sequential_with_batch/{sequential_with_batch_1_expected_extended_summary.csv => sequential_with_batch_1_expected_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/sequential_with_batch/{sequential_with_batch_1_expected_summary.json => sequential_with_batch_1_expected_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/sequential_with_batch/{sequential_with_batch_2_expected_extended_summary.csv => sequential_with_batch_2_expected_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/sequential_with_batch/{sequential_with_batch_2_expected_summary.json => sequential_with_batch_2_expected_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/sequential_with_batch/{sequential_with_batch_3_expected_extended_summary.csv => sequential_with_batch_3_expected_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/sequential_with_batch/{sequential_with_batch_3_expected_summary.json => sequential_with_batch_3_expected_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/sequential_with_continue_until_two/{sequential_with_continue_until_two_1_expected_extended_summary.csv => sequential_with_continue_until_two_1_expected_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/sequential_with_continue_until_two/{sequential_with_continue_until_two_1_expected_summary.json => sequential_with_continue_until_two_1_expected_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/sequential_with_continue_until_two/{sequential_with_continue_until_two_2_expected_extended_summary.csv => sequential_with_continue_until_two_2_expected_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/sequential_with_continue_until_two/{sequential_with_continue_until_two_2_expected_summary.json => sequential_with_continue_until_two_2_expected_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/sequential_with_continue_until_two/{sequential_with_continue_until_two_3_expected_extended_summary.csv => sequential_with_continue_until_two_3_expected_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/sequential_with_continue_until_two/{sequential_with_continue_until_two_3_expected_summary.json => sequential_with_continue_until_two_3_expected_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/skip_to_next_test/{skip_to_next_test_expected_extended_summary.csv => skip_to_next_test_expected_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/skip_to_next_test/{skip_to_next_test_expected_summary.json => skip_to_next_test_expected_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/stop_tabulation_early_test/{stop_tabulation_early_test_expected_extended_summary.csv => stop_tabulation_early_test_expected_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/stop_tabulation_early_test/{stop_tabulation_early_test_expected_summary.json => stop_tabulation_early_test_expected_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/test_set_0_skipped_first_choice/{test_set_0_skipped_first_choice_expected_extended_summary.csv => test_set_0_skipped_first_choice_expected_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/test_set_0_skipped_first_choice/{test_set_0_skipped_first_choice_expected_summary.json => test_set_0_skipped_first_choice_expected_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/test_set_1_exhaust_at_overvote/{test_set_1_exhaust_at_overvote_expected_extended_summary.csv => test_set_1_exhaust_at_overvote_expected_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/test_set_1_exhaust_at_overvote/{test_set_1_exhaust_at_overvote_expected_summary.json => test_set_1_exhaust_at_overvote_expected_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/test_set_2_overvote_skip_to_next/{test_set_2_overvote_skip_to_next_expected_extended_summary.csv => test_set_2_overvote_skip_to_next_expected_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/test_set_2_overvote_skip_to_next/{test_set_2_overvote_skip_to_next_expected_summary.json => test_set_2_overvote_skip_to_next_expected_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/test_set_3_skipped_choice_exhaust/{test_set_3_skipped_choice_exhaust_expected_extended_summary.csv => test_set_3_skipped_choice_exhaust_expected_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/test_set_3_skipped_choice_exhaust/{test_set_3_skipped_choice_exhaust_expected_summary.json => test_set_3_skipped_choice_exhaust_expected_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/test_set_4_skipped_choice_next/{test_set_4_skipped_choice_next_expected_extended_summary.csv => test_set_4_skipped_choice_next_expected_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/test_set_4_skipped_choice_next/{test_set_4_skipped_choice_next_expected_summary.json => test_set_4_skipped_choice_next_expected_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/test_set_5_two_skipped_choice_exhaust/{test_set_5_two_skipped_choice_exhaust_expected_extended_summary.csv => test_set_5_two_skipped_choice_exhaust_expected_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/test_set_5_two_skipped_choice_exhaust/{test_set_5_two_skipped_choice_exhaust_expected_summary.json => test_set_5_two_skipped_choice_exhaust_expected_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/test_set_6_duplicate_exhaust/{test_set_6_duplicate_exhaust_expected_extended_summary.csv => test_set_6_duplicate_exhaust_expected_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/test_set_6_duplicate_exhaust/{test_set_6_duplicate_exhaust_expected_summary.json => test_set_6_duplicate_exhaust_expected_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/test_set_7_duplicate_skip_to_next/{test_set_7_duplicate_skip_to_next_expected_extended_summary.csv => test_set_7_duplicate_skip_to_next_expected_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/test_set_7_duplicate_skip_to_next/{test_set_7_duplicate_skip_to_next_expected_summary.json => test_set_7_duplicate_skip_to_next_expected_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/test_set_8_multi_cdf/{test_set_8_multi_cdf_expected_extended_summary.csv => test_set_8_multi_cdf_expected_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/test_set_8_multi_cdf/{test_set_8_multi_cdf_expected_summary.json => test_set_8_multi_cdf_expected_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/test_set_allow_only_one_winner_per_round/{test_set_allow_only_one_winner_per_round_expected_extended_summary.csv => test_set_allow_only_one_winner_per_round_expected_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/test_set_allow_only_one_winner_per_round/{test_set_allow_only_one_winner_per_round_expected_summary.json => test_set_allow_only_one_winner_per_round_expected_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/test_set_multi_winner_fractional_threshold/{test_set_multi_winner_fractional_threshold_expected_extended_summary.csv => test_set_multi_winner_fractional_threshold_expected_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/test_set_multi_winner_fractional_threshold/{test_set_multi_winner_fractional_threshold_expected_summary.json => test_set_multi_winner_fractional_threshold_expected_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/test_set_multi_winner_whole_threshold/{test_set_multi_winner_whole_threshold_expected_extended_summary.csv => test_set_multi_winner_whole_threshold_expected_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/test_set_multi_winner_whole_threshold/{test_set_multi_winner_whole_threshold_expected_summary.json => test_set_multi_winner_whole_threshold_expected_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/test_set_overvote_delimiter/{test_set_overvote_delimiter_expected_extended_summary.csv => test_set_overvote_delimiter_expected_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/test_set_overvote_delimiter/{test_set_overvote_delimiter_expected_summary.json => test_set_overvote_delimiter_expected_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/test_set_treat_blank_as_undeclared_write_in/{test_set_treat_blank_as_undeclared_write_in_expected_extended_summary.csv => test_set_treat_blank_as_undeclared_write_in_expected_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/test_set_treat_blank_as_undeclared_write_in/{test_set_treat_blank_as_undeclared_write_in_expected_summary.json => test_set_treat_blank_as_undeclared_write_in_expected_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/tiebreak_generate_permutation_test/{tiebreak_generate_permutation_test_expected_extended_summary.csv => tiebreak_generate_permutation_test_expected_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/tiebreak_generate_permutation_test/{tiebreak_generate_permutation_test_expected_summary.json => tiebreak_generate_permutation_test_expected_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/tiebreak_previous_round_counts_then_random_test/{tiebreak_previous_round_counts_then_random_test_expected_extended_summary.csv => tiebreak_previous_round_counts_then_random_test_expected_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/tiebreak_previous_round_counts_then_random_test/{tiebreak_previous_round_counts_then_random_test_expected_summary.json => tiebreak_previous_round_counts_then_random_test_expected_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/tiebreak_seed_test/{tiebreak_seed_test_expected_extended_summary.csv => tiebreak_seed_test_expected_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/tiebreak_seed_test/{tiebreak_seed_test_expected_summary.json => tiebreak_seed_test_expected_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/tiebreak_use_permutation_in_config_test/{tiebreak_use_permutation_in_config_test_expected_extended_summary.csv => tiebreak_use_permutation_in_config_test_expected_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/tiebreak_use_permutation_in_config_test/{tiebreak_use_permutation_in_config_test_expected_summary.json => tiebreak_use_permutation_in_config_test_expected_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/unisyn_xml_cdf_city_chief_of_police/{unisyn_xml_cdf_city_chief_of_police_expected_extended_summary.csv => unisyn_xml_cdf_city_chief_of_police_expected_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/unisyn_xml_cdf_city_chief_of_police/{unisyn_xml_cdf_city_chief_of_police_expected_summary.json => unisyn_xml_cdf_city_chief_of_police_expected_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/unisyn_xml_cdf_city_coroner/{unisyn_xml_cdf_city_coroner_expected_extended_summary.csv => unisyn_xml_cdf_city_coroner_expected_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/unisyn_xml_cdf_city_coroner/{unisyn_xml_cdf_city_coroner_expected_summary.json => unisyn_xml_cdf_city_coroner_expected_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/unisyn_xml_cdf_city_council_member/{unisyn_xml_cdf_city_council_member_expected_extended_summary.csv => unisyn_xml_cdf_city_council_member_expected_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/unisyn_xml_cdf_city_council_member/{unisyn_xml_cdf_city_council_member_expected_summary.json => unisyn_xml_cdf_city_council_member_expected_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/unisyn_xml_cdf_city_mayor/{unisyn_xml_cdf_city_mayor_expected_extended_summary.csv => unisyn_xml_cdf_city_mayor_expected_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/unisyn_xml_cdf_city_mayor/{unisyn_xml_cdf_city_mayor_expected_summary.json => unisyn_xml_cdf_city_mayor_expected_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/unisyn_xml_cdf_city_tax_collector/{unisyn_xml_cdf_city_tax_collector_expected_extended_summary.csv => unisyn_xml_cdf_city_tax_collector_expected_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/unisyn_xml_cdf_city_tax_collector/{unisyn_xml_cdf_city_tax_collector_expected_summary.json => unisyn_xml_cdf_city_tax_collector_expected_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/unisyn_xml_cdf_county_coroner/{unisyn_xml_cdf_county_coroner_expected_extended_summary.csv => unisyn_xml_cdf_county_coroner_expected_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/unisyn_xml_cdf_county_coroner/{unisyn_xml_cdf_county_coroner_expected_summary.json => unisyn_xml_cdf_county_coroner_expected_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/unisyn_xml_cdf_county_sheriff/{unisyn_xml_cdf_county_sheriff_expected_extended_summary.csv => unisyn_xml_cdf_county_sheriff_expected_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/unisyn_xml_cdf_county_sheriff/{unisyn_xml_cdf_county_sheriff_expected_summary.json => unisyn_xml_cdf_county_sheriff_expected_detailed_report.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/uwi_cannot_win_test/{uwi_cannot_win_test_expected_extended_summary.csv => uwi_cannot_win_test_expected_detailed_report.csv} (100%) rename src/test/resources/network/brightspots/rcv/test_data/uwi_cannot_win_test/{uwi_cannot_win_test_expected_summary.json => uwi_cannot_win_test_expected_detailed_report.json} (100%) diff --git a/src/main/java/network/brightspots/rcv/ResultsWriter.java b/src/main/java/network/brightspots/rcv/ResultsWriter.java index dfcabc37f..f00b2668f 100644 --- a/src/main/java/network/brightspots/rcv/ResultsWriter.java +++ b/src/main/java/network/brightspots/rcv/ResultsWriter.java @@ -90,9 +90,9 @@ class ResultsWriter { StatusForRound.INVALIDATED_BY_REPEATED_RANKING); public enum ResultType { - SUMMARY_REPORT("summary"/*"summary_report"*/, "csv"), - DETAILED_REPORT("extended_summary"/*"detailed_report"*/, "csv"), - JSON("summary", "json"), + SUMMARY_CSV("summary_report", "csv"), + DETAILED_CSV("detailed_report", "csv"), + DETAILED_JSON("detailed_report", "json"), CDF("cvr_cdf", "json"), RCTAB_CVR("rctab_cvr", "csv"); @@ -336,8 +336,8 @@ void generateBySliceSummaryFiles( String sliceId = entry.getKey(); RoundTallies roundTallies = entry.getValue(); TallyTransfers tallyTransfers = tallyTransfersBySlice.get(slice, sliceId); - ResultFile resultFileCsv = new ResultFile(ResultType.DETAILED_REPORT, slice, sliceId); - ResultFile resultFileJson = new ResultFile(ResultType.JSON, slice, sliceId); + ResultFile resultFileCsv = new ResultFile(ResultType.DETAILED_CSV, slice, sliceId); + ResultFile resultFileJson = new ResultFile(ResultType.DETAILED_JSON, slice, sliceId); generateSummaryCsv(roundTallies, candidateOrder, resultFileCsv); generateSummaryJson(roundTallies, tallyTransfers, resultFileJson); } @@ -364,8 +364,8 @@ private void generateSummaryCsv( RoundTallies roundTallies, List candidateOrder, ResultFile resultFile) throws IOException { - if (resultFile.resultType != ResultType.SUMMARY_REPORT - && resultFile.resultType != ResultType.DETAILED_REPORT) { + if (resultFile.resultType != ResultType.SUMMARY_CSV + && resultFile.resultType != ResultType.DETAILED_CSV) { throw new IllegalArgumentException("ResultFile provided non-CSV type " + resultFile.resultType); } @@ -473,7 +473,7 @@ private void generateSummaryCsv( csvPrinter.println(); } - if (resultFile.resultType == ResultType.DETAILED_REPORT) { + if (resultFile.resultType == ResultType.DETAILED_CSV) { for (StatusForRound status : STATUSES_TO_PRINT) { csvPrinter.print(status.getTitleCaseKey()); @@ -656,9 +656,9 @@ void generateOverallSummaryFiles( RoundTallies roundTallies, TallyTransfers tallyTransfers, List candidateOrder) throws IOException { - generateSummaryCsv(roundTallies, candidateOrder, new ResultFile(ResultType.SUMMARY_REPORT)); - generateSummaryCsv(roundTallies, candidateOrder, new ResultFile(ResultType.DETAILED_REPORT)); - generateSummaryJson(roundTallies, tallyTransfers, new ResultFile(ResultType.JSON)); + generateSummaryCsv(roundTallies, candidateOrder, new ResultFile(ResultType.SUMMARY_CSV)); + generateSummaryCsv(roundTallies, candidateOrder, new ResultFile(ResultType.DETAILED_CSV)); + generateSummaryJson(roundTallies, tallyTransfers, new ResultFile(ResultType.DETAILED_JSON)); } // Write CastVoteRecords for the specified contest to the provided folder, diff --git a/src/test/java/network/brightspots/rcv/TabulatorTests.java b/src/test/java/network/brightspots/rcv/TabulatorTests.java index 8141f9406..3e19030a0 100644 --- a/src/test/java/network/brightspots/rcv/TabulatorTests.java +++ b/src/test/java/network/brightspots/rcv/TabulatorTests.java @@ -241,8 +241,8 @@ private static void runTabulationTest(String stem, String expectedException, int numSlicedFilesChecked = 0; for (ContestConfig.TabulateBySlice slice : config.enabledSlices()) { for (String sliceName : session.loadSliceNamesFromCvrs(slice, config)) { - ResultFile resultFileJson = new ResultFile(ResultType.JSON, slice, sliceName); - ResultFile resultFileCsv = new ResultFile(ResultType.DETAILED_REPORT, slice, sliceName); + ResultFile resultFileJson = new ResultFile(ResultType.DETAILED_JSON, slice, sliceName); + ResultFile resultFileCsv = new ResultFile(ResultType.DETAILED_CSV, slice, sliceName); if (compareFiles(config, stem, resultFileJson, timestampString, null, true)) { numSlicedFilesChecked++; } @@ -329,8 +329,8 @@ private static void cleanOutputFolder(TabulatorSession session) { private static void compareFiles( ContestConfig config, String stem, String timestampString, Integer sequentialId) { - compareFiles(config, stem, ResultType.JSON, timestampString, sequentialId, false); - compareFiles(config, stem, ResultType.DETAILED_REPORT, timestampString, sequentialId, false); + compareFiles(config, stem, ResultType.DETAILED_JSON, timestampString, sequentialId, false); + compareFiles(config, stem, ResultType.DETAILED_CSV, timestampString, sequentialId, false); compareExtendedSummaryToSummary(config, timestampString, sequentialId); if (config.isGenerateCdfJsonEnabled()) { compareFiles(config, stem, ResultType.CDF, timestampString, sequentialId, false); @@ -395,9 +395,9 @@ private static boolean compareFiles( private static void compareExtendedSummaryToSummary( ContestConfig config, String timestampString, Integer sequentialId) { String dir = config.getOutputDirectory(); - String summaryPath = new ResultFile(ResultType.SUMMARY_REPORT).getPath( + String summaryPath = new ResultFile(ResultType.SUMMARY_CSV).getPath( dir, timestampString, sequentialId).toAbsolutePath().toString(); - String detailedPath = new ResultFile(ResultType.DETAILED_REPORT).getPath( + String detailedPath = new ResultFile(ResultType.DETAILED_CSV).getPath( dir, timestampString, sequentialId).toAbsolutePath().toString(); try (BufferedReader brSummary = new BufferedReader(new FileReader(summaryPath, UTF_8)); diff --git a/src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_mayor/2013_minneapolis_mayor_expected_MINNEAPOLIS_W-13_P-09_precinct_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_mayor/2013_minneapolis_mayor_expected_MINNEAPOLIS_W-13_P-09_precinct_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_mayor/2013_minneapolis_mayor_expected_MINNEAPOLIS_W-13_P-09_precinct_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_mayor/2013_minneapolis_mayor_expected_MINNEAPOLIS_W-13_P-09_precinct_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_mayor/2013_minneapolis_mayor_expected_MINNEAPOLIS_W-13_P-09_precinct_summary.json b/src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_mayor/2013_minneapolis_mayor_expected_MINNEAPOLIS_W-13_P-09_precinct_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_mayor/2013_minneapolis_mayor_expected_MINNEAPOLIS_W-13_P-09_precinct_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_mayor/2013_minneapolis_mayor_expected_MINNEAPOLIS_W-13_P-09_precinct_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_mayor/2013_minneapolis_mayor_expected_MINNEAPOLIS_W-1_P-01_precinct_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_mayor/2013_minneapolis_mayor_expected_MINNEAPOLIS_W-1_P-01_precinct_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_mayor/2013_minneapolis_mayor_expected_MINNEAPOLIS_W-1_P-01_precinct_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_mayor/2013_minneapolis_mayor_expected_MINNEAPOLIS_W-1_P-01_precinct_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_mayor/2013_minneapolis_mayor_expected_MINNEAPOLIS_W-1_P-01_precinct_summary.json b/src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_mayor/2013_minneapolis_mayor_expected_MINNEAPOLIS_W-1_P-01_precinct_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_mayor/2013_minneapolis_mayor_expected_MINNEAPOLIS_W-1_P-01_precinct_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_mayor/2013_minneapolis_mayor_expected_MINNEAPOLIS_W-1_P-01_precinct_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_mayor/2013_minneapolis_mayor_expected_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_mayor/2013_minneapolis_mayor_expected_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_mayor/2013_minneapolis_mayor_expected_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_mayor/2013_minneapolis_mayor_expected_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_mayor/2013_minneapolis_mayor_expected_summary.json b/src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_mayor/2013_minneapolis_mayor_expected_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_mayor/2013_minneapolis_mayor_expected_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_mayor/2013_minneapolis_mayor_expected_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_mayor_scale/2013_minneapolis_mayor_scale_expected_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_mayor_scale/2013_minneapolis_mayor_scale_expected_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_mayor_scale/2013_minneapolis_mayor_scale_expected_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_mayor_scale/2013_minneapolis_mayor_scale_expected_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_mayor_scale/2013_minneapolis_mayor_scale_expected_summary.json b/src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_mayor_scale/2013_minneapolis_mayor_scale_expected_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_mayor_scale/2013_minneapolis_mayor_scale_expected_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_mayor_scale/2013_minneapolis_mayor_scale_expected_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_park/2013_minneapolis_park_expected_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_park/2013_minneapolis_park_expected_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_park/2013_minneapolis_park_expected_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_park/2013_minneapolis_park_expected_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_park/2013_minneapolis_park_expected_summary.json b/src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_park/2013_minneapolis_park_expected_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_park/2013_minneapolis_park_expected_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_park/2013_minneapolis_park_expected_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_park_bottoms_up/2013_minneapolis_park_bottoms_up_expected_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_park_bottoms_up/2013_minneapolis_park_bottoms_up_expected_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_park_bottoms_up/2013_minneapolis_park_bottoms_up_expected_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_park_bottoms_up/2013_minneapolis_park_bottoms_up_expected_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_park_bottoms_up/2013_minneapolis_park_bottoms_up_expected_summary.json b/src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_park_bottoms_up/2013_minneapolis_park_bottoms_up_expected_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_park_bottoms_up/2013_minneapolis_park_bottoms_up_expected_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_park_bottoms_up/2013_minneapolis_park_bottoms_up_expected_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_park_hare/2013_minneapolis_park_hare_expected_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_park_hare/2013_minneapolis_park_hare_expected_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_park_hare/2013_minneapolis_park_hare_expected_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_park_hare/2013_minneapolis_park_hare_expected_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_park_hare/2013_minneapolis_park_hare_expected_summary.json b/src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_park_hare/2013_minneapolis_park_hare_expected_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_park_hare/2013_minneapolis_park_hare_expected_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_park_hare/2013_minneapolis_park_hare_expected_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_park_sequential/2013_minneapolis_park_sequential_1_expected_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_park_sequential/2013_minneapolis_park_sequential_1_expected_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_park_sequential/2013_minneapolis_park_sequential_1_expected_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_park_sequential/2013_minneapolis_park_sequential_1_expected_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_park_sequential/2013_minneapolis_park_sequential_1_expected_summary.json b/src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_park_sequential/2013_minneapolis_park_sequential_1_expected_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_park_sequential/2013_minneapolis_park_sequential_1_expected_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_park_sequential/2013_minneapolis_park_sequential_1_expected_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_park_sequential/2013_minneapolis_park_sequential_2_expected_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_park_sequential/2013_minneapolis_park_sequential_2_expected_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_park_sequential/2013_minneapolis_park_sequential_2_expected_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_park_sequential/2013_minneapolis_park_sequential_2_expected_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_park_sequential/2013_minneapolis_park_sequential_2_expected_summary.json b/src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_park_sequential/2013_minneapolis_park_sequential_2_expected_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_park_sequential/2013_minneapolis_park_sequential_2_expected_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_park_sequential/2013_minneapolis_park_sequential_2_expected_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_park_sequential/2013_minneapolis_park_sequential_3_expected_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_park_sequential/2013_minneapolis_park_sequential_3_expected_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_park_sequential/2013_minneapolis_park_sequential_3_expected_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_park_sequential/2013_minneapolis_park_sequential_3_expected_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_park_sequential/2013_minneapolis_park_sequential_3_expected_summary.json b/src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_park_sequential/2013_minneapolis_park_sequential_3_expected_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_park_sequential/2013_minneapolis_park_sequential_3_expected_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/2013_minneapolis_park_sequential/2013_minneapolis_park_sequential_3_expected_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/2015_portland_mayor/2015_portland_mayor_expected_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/2015_portland_mayor/2015_portland_mayor_expected_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/2015_portland_mayor/2015_portland_mayor_expected_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/2015_portland_mayor/2015_portland_mayor_expected_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/2015_portland_mayor/2015_portland_mayor_expected_summary.json b/src/test/resources/network/brightspots/rcv/test_data/2015_portland_mayor/2015_portland_mayor_expected_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/2015_portland_mayor/2015_portland_mayor_expected_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/2015_portland_mayor/2015_portland_mayor_expected_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/2015_portland_mayor_codes/2015_portland_mayor_codes_expected_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/2015_portland_mayor_codes/2015_portland_mayor_codes_expected_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/2015_portland_mayor_codes/2015_portland_mayor_codes_expected_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/2015_portland_mayor_codes/2015_portland_mayor_codes_expected_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/2015_portland_mayor_codes/2015_portland_mayor_codes_expected_summary.json b/src/test/resources/network/brightspots/rcv/test_data/2015_portland_mayor_codes/2015_portland_mayor_codes_expected_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/2015_portland_mayor_codes/2015_portland_mayor_codes_expected_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/2015_portland_mayor_codes/2015_portland_mayor_codes_expected_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/2017_minneapolis_mayor/2017_minneapolis_mayor_expected_MINNEAPOLIS_W-13_P-13_precinct_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/2017_minneapolis_mayor/2017_minneapolis_mayor_expected_MINNEAPOLIS_W-13_P-13_precinct_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/2017_minneapolis_mayor/2017_minneapolis_mayor_expected_MINNEAPOLIS_W-13_P-13_precinct_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/2017_minneapolis_mayor/2017_minneapolis_mayor_expected_MINNEAPOLIS_W-13_P-13_precinct_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/2017_minneapolis_mayor/2017_minneapolis_mayor_expected_MINNEAPOLIS_W-13_P-13_precinct_summary.json b/src/test/resources/network/brightspots/rcv/test_data/2017_minneapolis_mayor/2017_minneapolis_mayor_expected_MINNEAPOLIS_W-13_P-13_precinct_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/2017_minneapolis_mayor/2017_minneapolis_mayor_expected_MINNEAPOLIS_W-13_P-13_precinct_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/2017_minneapolis_mayor/2017_minneapolis_mayor_expected_MINNEAPOLIS_W-13_P-13_precinct_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/2017_minneapolis_mayor/2017_minneapolis_mayor_expected_MINNEAPOLIS_W-1_P-01_precinct_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/2017_minneapolis_mayor/2017_minneapolis_mayor_expected_MINNEAPOLIS_W-1_P-01_precinct_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/2017_minneapolis_mayor/2017_minneapolis_mayor_expected_MINNEAPOLIS_W-1_P-01_precinct_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/2017_minneapolis_mayor/2017_minneapolis_mayor_expected_MINNEAPOLIS_W-1_P-01_precinct_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/2017_minneapolis_mayor/2017_minneapolis_mayor_expected_MINNEAPOLIS_W-1_P-01_precinct_summary.json b/src/test/resources/network/brightspots/rcv/test_data/2017_minneapolis_mayor/2017_minneapolis_mayor_expected_MINNEAPOLIS_W-1_P-01_precinct_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/2017_minneapolis_mayor/2017_minneapolis_mayor_expected_MINNEAPOLIS_W-1_P-01_precinct_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/2017_minneapolis_mayor/2017_minneapolis_mayor_expected_MINNEAPOLIS_W-1_P-01_precinct_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/2017_minneapolis_mayor/2017_minneapolis_mayor_expected_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/2017_minneapolis_mayor/2017_minneapolis_mayor_expected_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/2017_minneapolis_mayor/2017_minneapolis_mayor_expected_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/2017_minneapolis_mayor/2017_minneapolis_mayor_expected_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/2017_minneapolis_mayor/2017_minneapolis_mayor_expected_summary.json b/src/test/resources/network/brightspots/rcv/test_data/2017_minneapolis_mayor/2017_minneapolis_mayor_expected_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/2017_minneapolis_mayor/2017_minneapolis_mayor_expected_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/2017_minneapolis_mayor/2017_minneapolis_mayor_expected_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/2018_maine_governor_primary/2018_maine_governor_primary_expected_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/2018_maine_governor_primary/2018_maine_governor_primary_expected_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/2018_maine_governor_primary/2018_maine_governor_primary_expected_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/2018_maine_governor_primary/2018_maine_governor_primary_expected_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/2018_maine_governor_primary/2018_maine_governor_primary_expected_summary.json b/src/test/resources/network/brightspots/rcv/test_data/2018_maine_governor_primary/2018_maine_governor_primary_expected_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/2018_maine_governor_primary/2018_maine_governor_primary_expected_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/2018_maine_governor_primary/2018_maine_governor_primary_expected_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/aliases_cdf_json/aliases_cdf_json_expected_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/aliases_cdf_json/aliases_cdf_json_expected_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/aliases_cdf_json/aliases_cdf_json_expected_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/aliases_cdf_json/aliases_cdf_json_expected_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/aliases_cdf_json/aliases_cdf_json_expected_summary.json b/src/test/resources/network/brightspots/rcv/test_data/aliases_cdf_json/aliases_cdf_json_expected_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/aliases_cdf_json/aliases_cdf_json_expected_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/aliases_cdf_json/aliases_cdf_json_expected_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/aliases_ess_xlsx/aliases_ess_xlsx_expected_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/aliases_ess_xlsx/aliases_ess_xlsx_expected_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/aliases_ess_xlsx/aliases_ess_xlsx_expected_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/aliases_ess_xlsx/aliases_ess_xlsx_expected_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/aliases_ess_xlsx/aliases_ess_xlsx_expected_summary.json b/src/test/resources/network/brightspots/rcv/test_data/aliases_ess_xlsx/aliases_ess_xlsx_expected_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/aliases_ess_xlsx/aliases_ess_xlsx_expected_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/aliases_ess_xlsx/aliases_ess_xlsx_expected_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/batch_example/batch_example_expected_MINNEAPOLIS_W-1_P-02_batch_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/batch_example/batch_example_expected_MINNEAPOLIS_W-1_P-02_batch_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/batch_example/batch_example_expected_MINNEAPOLIS_W-1_P-02_batch_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/batch_example/batch_example_expected_MINNEAPOLIS_W-1_P-02_batch_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/batch_example/batch_example_expected_MINNEAPOLIS_W-1_P-04_batch_summary.json b/src/test/resources/network/brightspots/rcv/test_data/batch_example/batch_example_expected_MINNEAPOLIS_W-1_P-04_batch_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/batch_example/batch_example_expected_MINNEAPOLIS_W-1_P-04_batch_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/batch_example/batch_example_expected_MINNEAPOLIS_W-1_P-04_batch_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/batch_example/batch_example_expected_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/batch_example/batch_example_expected_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/batch_example/batch_example_expected_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/batch_example/batch_example_expected_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/batch_example/batch_example_expected_summary.json b/src/test/resources/network/brightspots/rcv/test_data/batch_example/batch_example_expected_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/batch_example/batch_example_expected_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/batch_example/batch_example_expected_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/clear_ballot_kansas_primary/clear_ballot_kansas_primary_expected_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/clear_ballot_kansas_primary/clear_ballot_kansas_primary_expected_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/clear_ballot_kansas_primary/clear_ballot_kansas_primary_expected_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/clear_ballot_kansas_primary/clear_ballot_kansas_primary_expected_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/clear_ballot_kansas_primary/clear_ballot_kansas_primary_expected_summary.json b/src/test/resources/network/brightspots/rcv/test_data/clear_ballot_kansas_primary/clear_ballot_kansas_primary_expected_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/clear_ballot_kansas_primary/clear_ballot_kansas_primary_expected_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/clear_ballot_kansas_primary/clear_ballot_kansas_primary_expected_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/clear_ballot_with_inline_comma/clear_ballot_with_inline_comma_expected_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/clear_ballot_with_inline_comma/clear_ballot_with_inline_comma_expected_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/clear_ballot_with_inline_comma/clear_ballot_with_inline_comma_expected_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/clear_ballot_with_inline_comma/clear_ballot_with_inline_comma_expected_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/clear_ballot_with_inline_comma/clear_ballot_with_inline_comma_expected_summary.json b/src/test/resources/network/brightspots/rcv/test_data/clear_ballot_with_inline_comma/clear_ballot_with_inline_comma_expected_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/clear_ballot_with_inline_comma/clear_ballot_with_inline_comma_expected_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/clear_ballot_with_inline_comma/clear_ballot_with_inline_comma_expected_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/continue_tabulation_test/continue_tabulation_test_expected_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/continue_tabulation_test/continue_tabulation_test_expected_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/continue_tabulation_test/continue_tabulation_test_expected_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/continue_tabulation_test/continue_tabulation_test_expected_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/continue_tabulation_test/continue_tabulation_test_expected_summary.json b/src/test/resources/network/brightspots/rcv/test_data/continue_tabulation_test/continue_tabulation_test_expected_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/continue_tabulation_test/continue_tabulation_test_expected_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/continue_tabulation_test/continue_tabulation_test_expected_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/continue_until_two_with_batch_elimination_test/continue_until_two_with_batch_elimination_test_expected_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/continue_until_two_with_batch_elimination_test/continue_until_two_with_batch_elimination_test_expected_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/continue_until_two_with_batch_elimination_test/continue_until_two_with_batch_elimination_test_expected_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/continue_until_two_with_batch_elimination_test/continue_until_two_with_batch_elimination_test_expected_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/continue_until_two_with_batch_elimination_test/continue_until_two_with_batch_elimination_test_expected_summary.json b/src/test/resources/network/brightspots/rcv/test_data/continue_until_two_with_batch_elimination_test/continue_until_two_with_batch_elimination_test_expected_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/continue_until_two_with_batch_elimination_test/continue_until_two_with_batch_elimination_test_expected_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/continue_until_two_with_batch_elimination_test/continue_until_two_with_batch_elimination_test_expected_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/csv_missing_header_test/csv_missing_header_test_expected_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/csv_missing_header_test/csv_missing_header_test_expected_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/csv_missing_header_test/csv_missing_header_test_expected_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/csv_missing_header_test/csv_missing_header_test_expected_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/csv_missing_header_test/csv_missing_header_test_expected_summary.json b/src/test/resources/network/brightspots/rcv/test_data/csv_missing_header_test/csv_missing_header_test_expected_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/csv_missing_header_test/csv_missing_header_test_expected_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/csv_missing_header_test/csv_missing_header_test_expected_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/dominion_alaska/dominion_alaska_expected_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/dominion_alaska/dominion_alaska_expected_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/dominion_alaska/dominion_alaska_expected_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/dominion_alaska/dominion_alaska_expected_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/dominion_alaska/dominion_alaska_expected_summary.json b/src/test/resources/network/brightspots/rcv/test_data/dominion_alaska/dominion_alaska_expected_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/dominion_alaska/dominion_alaska_expected_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/dominion_alaska/dominion_alaska_expected_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/dominion_kansas/dominion_kansas_expected_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/dominion_kansas/dominion_kansas_expected_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/dominion_kansas/dominion_kansas_expected_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/dominion_kansas/dominion_kansas_expected_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/dominion_kansas/dominion_kansas_expected_summary.json b/src/test/resources/network/brightspots/rcv/test_data/dominion_kansas/dominion_kansas_expected_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/dominion_kansas/dominion_kansas_expected_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/dominion_kansas/dominion_kansas_expected_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/dominion_multi_file/dominion_multi_file_expected_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/dominion_multi_file/dominion_multi_file_expected_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/dominion_multi_file/dominion_multi_file_expected_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/dominion_multi_file/dominion_multi_file_expected_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/dominion_multi_file/dominion_multi_file_expected_summary.json b/src/test/resources/network/brightspots/rcv/test_data/dominion_multi_file/dominion_multi_file_expected_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/dominion_multi_file/dominion_multi_file_expected_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/dominion_multi_file/dominion_multi_file_expected_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/dominion_no_precinct_data/dominion_no_precinct_data_expected_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/dominion_no_precinct_data/dominion_no_precinct_data_expected_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/dominion_no_precinct_data/dominion_no_precinct_data_expected_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/dominion_no_precinct_data/dominion_no_precinct_data_expected_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/dominion_no_precinct_data/dominion_no_precinct_data_expected_summary.json b/src/test/resources/network/brightspots/rcv/test_data/dominion_no_precinct_data/dominion_no_precinct_data_expected_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/dominion_no_precinct_data/dominion_no_precinct_data_expected_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/dominion_no_precinct_data/dominion_no_precinct_data_expected_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/dominion_wyoming/dominion_wyoming_expected_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/dominion_wyoming/dominion_wyoming_expected_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/dominion_wyoming/dominion_wyoming_expected_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/dominion_wyoming/dominion_wyoming_expected_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/dominion_wyoming/dominion_wyoming_expected_summary.json b/src/test/resources/network/brightspots/rcv/test_data/dominion_wyoming/dominion_wyoming_expected_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/dominion_wyoming/dominion_wyoming_expected_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/dominion_wyoming/dominion_wyoming_expected_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/duplicate_test/duplicate_test_expected_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/duplicate_test/duplicate_test_expected_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/duplicate_test/duplicate_test_expected_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/duplicate_test/duplicate_test_expected_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/duplicate_test/duplicate_test_expected_summary.json b/src/test/resources/network/brightspots/rcv/test_data/duplicate_test/duplicate_test_expected_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/duplicate_test/duplicate_test_expected_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/duplicate_test/duplicate_test_expected_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/excluded_test/excluded_test_expected_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/excluded_test/excluded_test_expected_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/excluded_test/excluded_test_expected_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/excluded_test/excluded_test_expected_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/excluded_test/excluded_test_expected_summary.json b/src/test/resources/network/brightspots/rcv/test_data/excluded_test/excluded_test_expected_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/excluded_test/excluded_test_expected_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/excluded_test/excluded_test_expected_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/exhaust_if_multiple_continuing/exhaust_if_multiple_continuing_expected_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/exhaust_if_multiple_continuing/exhaust_if_multiple_continuing_expected_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/exhaust_if_multiple_continuing/exhaust_if_multiple_continuing_expected_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/exhaust_if_multiple_continuing/exhaust_if_multiple_continuing_expected_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/exhaust_if_multiple_continuing/exhaust_if_multiple_continuing_expected_summary.json b/src/test/resources/network/brightspots/rcv/test_data/exhaust_if_multiple_continuing/exhaust_if_multiple_continuing_expected_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/exhaust_if_multiple_continuing/exhaust_if_multiple_continuing_expected_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/exhaust_if_multiple_continuing/exhaust_if_multiple_continuing_expected_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/first_round_determines_threshold_test/first_round_determines_threshold_test_expected_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/first_round_determines_threshold_test/first_round_determines_threshold_test_expected_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/first_round_determines_threshold_test/first_round_determines_threshold_test_expected_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/first_round_determines_threshold_test/first_round_determines_threshold_test_expected_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/first_round_determines_threshold_test/first_round_determines_threshold_test_expected_summary.json b/src/test/resources/network/brightspots/rcv/test_data/first_round_determines_threshold_test/first_round_determines_threshold_test_expected_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/first_round_determines_threshold_test/first_round_determines_threshold_test_expected_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/first_round_determines_threshold_test/first_round_determines_threshold_test_expected_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/first_round_determines_threshold_tiebreaker_test/first_round_determines_threshold_tiebreaker_test_expected_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/first_round_determines_threshold_tiebreaker_test/first_round_determines_threshold_tiebreaker_test_expected_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/first_round_determines_threshold_tiebreaker_test/first_round_determines_threshold_tiebreaker_test_expected_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/first_round_determines_threshold_tiebreaker_test/first_round_determines_threshold_tiebreaker_test_expected_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/first_round_determines_threshold_tiebreaker_test/first_round_determines_threshold_tiebreaker_test_expected_summary.json b/src/test/resources/network/brightspots/rcv/test_data/first_round_determines_threshold_tiebreaker_test/first_round_determines_threshold_tiebreaker_test_expected_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/first_round_determines_threshold_tiebreaker_test/first_round_determines_threshold_tiebreaker_test_expected_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/first_round_determines_threshold_tiebreaker_test/first_round_determines_threshold_tiebreaker_test_expected_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/generic_csv_test/generic_csv_test_expected_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/generic_csv_test/generic_csv_test_expected_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/generic_csv_test/generic_csv_test_expected_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/generic_csv_test/generic_csv_test_expected_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/generic_csv_test/generic_csv_test_expected_summary.json b/src/test/resources/network/brightspots/rcv/test_data/generic_csv_test/generic_csv_test_expected_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/generic_csv_test/generic_csv_test_expected_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/generic_csv_test/generic_csv_test_expected_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/hart_cedar_park_school_board/hart_cedar_park_school_board_expected_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/hart_cedar_park_school_board/hart_cedar_park_school_board_expected_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/hart_cedar_park_school_board/hart_cedar_park_school_board_expected_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/hart_cedar_park_school_board/hart_cedar_park_school_board_expected_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/hart_cedar_park_school_board/hart_cedar_park_school_board_expected_summary.json b/src/test/resources/network/brightspots/rcv/test_data/hart_cedar_park_school_board/hart_cedar_park_school_board_expected_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/hart_cedar_park_school_board/hart_cedar_park_school_board_expected_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/hart_cedar_park_school_board/hart_cedar_park_school_board_expected_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/hart_travis_county_officers/hart_travis_county_officers_expected_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/hart_travis_county_officers/hart_travis_county_officers_expected_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/hart_travis_county_officers/hart_travis_county_officers_expected_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/hart_travis_county_officers/hart_travis_county_officers_expected_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/hart_travis_county_officers/hart_travis_county_officers_expected_summary.json b/src/test/resources/network/brightspots/rcv/test_data/hart_travis_county_officers/hart_travis_county_officers_expected_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/hart_travis_county_officers/hart_travis_county_officers_expected_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/hart_travis_county_officers/hart_travis_county_officers_expected_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/minimum_threshold_test/minimum_threshold_test_expected_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/minimum_threshold_test/minimum_threshold_test_expected_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/minimum_threshold_test/minimum_threshold_test_expected_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/minimum_threshold_test/minimum_threshold_test_expected_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/minimum_threshold_test/minimum_threshold_test_expected_summary.json b/src/test/resources/network/brightspots/rcv/test_data/minimum_threshold_test/minimum_threshold_test_expected_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/minimum_threshold_test/minimum_threshold_test_expected_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/minimum_threshold_test/minimum_threshold_test_expected_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/minneapolis_multi_seat_threshold/minneapolis_multi_seat_threshold_expected_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/minneapolis_multi_seat_threshold/minneapolis_multi_seat_threshold_expected_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/minneapolis_multi_seat_threshold/minneapolis_multi_seat_threshold_expected_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/minneapolis_multi_seat_threshold/minneapolis_multi_seat_threshold_expected_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/minneapolis_multi_seat_threshold/minneapolis_multi_seat_threshold_expected_summary.json b/src/test/resources/network/brightspots/rcv/test_data/minneapolis_multi_seat_threshold/minneapolis_multi_seat_threshold_expected_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/minneapolis_multi_seat_threshold/minneapolis_multi_seat_threshold_expected_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/minneapolis_multi_seat_threshold/minneapolis_multi_seat_threshold_expected_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/minneapolis_multi_seat_threshold/minneapolis_multi_seat_threshold_expected_pc1_precinct_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/minneapolis_multi_seat_threshold/minneapolis_multi_seat_threshold_expected_pc1_precinct_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/minneapolis_multi_seat_threshold/minneapolis_multi_seat_threshold_expected_pc1_precinct_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/minneapolis_multi_seat_threshold/minneapolis_multi_seat_threshold_expected_pc1_precinct_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/minneapolis_multi_seat_threshold/minneapolis_multi_seat_threshold_expected_pc2_precinct_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/minneapolis_multi_seat_threshold/minneapolis_multi_seat_threshold_expected_pc2_precinct_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/minneapolis_multi_seat_threshold/minneapolis_multi_seat_threshold_expected_pc2_precinct_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/minneapolis_multi_seat_threshold/minneapolis_multi_seat_threshold_expected_pc2_precinct_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/minneapolis_multi_seat_threshold/minneapolis_multi_seat_threshold_expected_pc2_precinct_summary.json b/src/test/resources/network/brightspots/rcv/test_data/minneapolis_multi_seat_threshold/minneapolis_multi_seat_threshold_expected_pc2_precinct_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/minneapolis_multi_seat_threshold/minneapolis_multi_seat_threshold_expected_pc2_precinct_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/minneapolis_multi_seat_threshold/minneapolis_multi_seat_threshold_expected_pc2_precinct_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/missing_precinct_example/missing_precinct_example_expected_MINNEAPOLIS_W-13_P-13_precinct_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/missing_precinct_example/missing_precinct_example_expected_MINNEAPOLIS_W-13_P-13_precinct_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/missing_precinct_example/missing_precinct_example_expected_MINNEAPOLIS_W-13_P-13_precinct_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/missing_precinct_example/missing_precinct_example_expected_MINNEAPOLIS_W-13_P-13_precinct_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/missing_precinct_example/missing_precinct_example_expected_MINNEAPOLIS_W-13_P-13_precinct_summary.json b/src/test/resources/network/brightspots/rcv/test_data/missing_precinct_example/missing_precinct_example_expected_MINNEAPOLIS_W-13_P-13_precinct_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/missing_precinct_example/missing_precinct_example_expected_MINNEAPOLIS_W-13_P-13_precinct_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/missing_precinct_example/missing_precinct_example_expected_MINNEAPOLIS_W-13_P-13_precinct_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/missing_precinct_example/missing_precinct_example_expected_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/missing_precinct_example/missing_precinct_example_expected_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/missing_precinct_example/missing_precinct_example_expected_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/missing_precinct_example/missing_precinct_example_expected_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/missing_precinct_example/missing_precinct_example_expected_summary.json b/src/test/resources/network/brightspots/rcv/test_data/missing_precinct_example/missing_precinct_example_expected_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/missing_precinct_example/missing_precinct_example_expected_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/missing_precinct_example/missing_precinct_example_expected_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/missing_precinct_example/missing_precinct_example_expected_missing_precinct_id_precinct_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/missing_precinct_example/missing_precinct_example_expected_missing_precinct_id_precinct_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/missing_precinct_example/missing_precinct_example_expected_missing_precinct_id_precinct_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/missing_precinct_example/missing_precinct_example_expected_missing_precinct_id_precinct_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/missing_precinct_example/missing_precinct_example_expected_missing_precinct_id_precinct_summary.json b/src/test/resources/network/brightspots/rcv/test_data/missing_precinct_example/missing_precinct_example_expected_missing_precinct_id_precinct_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/missing_precinct_example/missing_precinct_example_expected_missing_precinct_id_precinct_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/missing_precinct_example/missing_precinct_example_expected_missing_precinct_id_precinct_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/more_winners_than_candidates/more_winners_than_candidates_expected_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/more_winners_than_candidates/more_winners_than_candidates_expected_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/more_winners_than_candidates/more_winners_than_candidates_expected_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/more_winners_than_candidates/more_winners_than_candidates_expected_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/more_winners_than_candidates/more_winners_than_candidates_expected_summary.json b/src/test/resources/network/brightspots/rcv/test_data/more_winners_than_candidates/more_winners_than_candidates_expected_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/more_winners_than_candidates/more_winners_than_candidates_expected_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/more_winners_than_candidates/more_winners_than_candidates_expected_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/multi_seat_bottoms_up_with_threshold/multi_seat_bottoms_up_with_threshold_expected_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/multi_seat_bottoms_up_with_threshold/multi_seat_bottoms_up_with_threshold_expected_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/multi_seat_bottoms_up_with_threshold/multi_seat_bottoms_up_with_threshold_expected_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/multi_seat_bottoms_up_with_threshold/multi_seat_bottoms_up_with_threshold_expected_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/multi_seat_bottoms_up_with_threshold/multi_seat_bottoms_up_with_threshold_expected_summary.json b/src/test/resources/network/brightspots/rcv/test_data/multi_seat_bottoms_up_with_threshold/multi_seat_bottoms_up_with_threshold_expected_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/multi_seat_bottoms_up_with_threshold/multi_seat_bottoms_up_with_threshold_expected_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/multi_seat_bottoms_up_with_threshold/multi_seat_bottoms_up_with_threshold_expected_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/multi_seat_uwi_test/multi_seat_uwi_test_expected_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/multi_seat_uwi_test/multi_seat_uwi_test_expected_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/multi_seat_uwi_test/multi_seat_uwi_test_expected_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/multi_seat_uwi_test/multi_seat_uwi_test_expected_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/multi_seat_uwi_test/multi_seat_uwi_test_expected_summary.json b/src/test/resources/network/brightspots/rcv/test_data/multi_seat_uwi_test/multi_seat_uwi_test_expected_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/multi_seat_uwi_test/multi_seat_uwi_test_expected_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/multi_seat_uwi_test/multi_seat_uwi_test_expected_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/nist_xml_cdf_2/nist_xml_cdf_2_expected_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/nist_xml_cdf_2/nist_xml_cdf_2_expected_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/nist_xml_cdf_2/nist_xml_cdf_2_expected_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/nist_xml_cdf_2/nist_xml_cdf_2_expected_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/nist_xml_cdf_2/nist_xml_cdf_2_expected_summary.json b/src/test/resources/network/brightspots/rcv/test_data/nist_xml_cdf_2/nist_xml_cdf_2_expected_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/nist_xml_cdf_2/nist_xml_cdf_2_expected_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/nist_xml_cdf_2/nist_xml_cdf_2_expected_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/precinct_example/precinct_example_expected_MINNEAPOLIS_W-1_P-02_precinct_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/precinct_example/precinct_example_expected_MINNEAPOLIS_W-1_P-02_precinct_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/precinct_example/precinct_example_expected_MINNEAPOLIS_W-1_P-02_precinct_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/precinct_example/precinct_example_expected_MINNEAPOLIS_W-1_P-02_precinct_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/precinct_example/precinct_example_expected_MINNEAPOLIS_W-1_P-02_precinct_summary.json b/src/test/resources/network/brightspots/rcv/test_data/precinct_example/precinct_example_expected_MINNEAPOLIS_W-1_P-02_precinct_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/precinct_example/precinct_example_expected_MINNEAPOLIS_W-1_P-02_precinct_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/precinct_example/precinct_example_expected_MINNEAPOLIS_W-1_P-02_precinct_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/precinct_example/precinct_example_expected_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/precinct_example/precinct_example_expected_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/precinct_example/precinct_example_expected_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/precinct_example/precinct_example_expected_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/precinct_example/precinct_example_expected_summary.json b/src/test/resources/network/brightspots/rcv/test_data/precinct_example/precinct_example_expected_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/precinct_example/precinct_example_expected_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/precinct_example/precinct_example_expected_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/sequential_with_batch/sequential_with_batch_1_expected_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/sequential_with_batch/sequential_with_batch_1_expected_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/sequential_with_batch/sequential_with_batch_1_expected_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/sequential_with_batch/sequential_with_batch_1_expected_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/sequential_with_batch/sequential_with_batch_1_expected_summary.json b/src/test/resources/network/brightspots/rcv/test_data/sequential_with_batch/sequential_with_batch_1_expected_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/sequential_with_batch/sequential_with_batch_1_expected_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/sequential_with_batch/sequential_with_batch_1_expected_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/sequential_with_batch/sequential_with_batch_2_expected_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/sequential_with_batch/sequential_with_batch_2_expected_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/sequential_with_batch/sequential_with_batch_2_expected_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/sequential_with_batch/sequential_with_batch_2_expected_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/sequential_with_batch/sequential_with_batch_2_expected_summary.json b/src/test/resources/network/brightspots/rcv/test_data/sequential_with_batch/sequential_with_batch_2_expected_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/sequential_with_batch/sequential_with_batch_2_expected_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/sequential_with_batch/sequential_with_batch_2_expected_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/sequential_with_batch/sequential_with_batch_3_expected_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/sequential_with_batch/sequential_with_batch_3_expected_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/sequential_with_batch/sequential_with_batch_3_expected_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/sequential_with_batch/sequential_with_batch_3_expected_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/sequential_with_batch/sequential_with_batch_3_expected_summary.json b/src/test/resources/network/brightspots/rcv/test_data/sequential_with_batch/sequential_with_batch_3_expected_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/sequential_with_batch/sequential_with_batch_3_expected_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/sequential_with_batch/sequential_with_batch_3_expected_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/sequential_with_continue_until_two/sequential_with_continue_until_two_1_expected_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/sequential_with_continue_until_two/sequential_with_continue_until_two_1_expected_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/sequential_with_continue_until_two/sequential_with_continue_until_two_1_expected_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/sequential_with_continue_until_two/sequential_with_continue_until_two_1_expected_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/sequential_with_continue_until_two/sequential_with_continue_until_two_1_expected_summary.json b/src/test/resources/network/brightspots/rcv/test_data/sequential_with_continue_until_two/sequential_with_continue_until_two_1_expected_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/sequential_with_continue_until_two/sequential_with_continue_until_two_1_expected_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/sequential_with_continue_until_two/sequential_with_continue_until_two_1_expected_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/sequential_with_continue_until_two/sequential_with_continue_until_two_2_expected_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/sequential_with_continue_until_two/sequential_with_continue_until_two_2_expected_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/sequential_with_continue_until_two/sequential_with_continue_until_two_2_expected_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/sequential_with_continue_until_two/sequential_with_continue_until_two_2_expected_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/sequential_with_continue_until_two/sequential_with_continue_until_two_2_expected_summary.json b/src/test/resources/network/brightspots/rcv/test_data/sequential_with_continue_until_two/sequential_with_continue_until_two_2_expected_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/sequential_with_continue_until_two/sequential_with_continue_until_two_2_expected_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/sequential_with_continue_until_two/sequential_with_continue_until_two_2_expected_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/sequential_with_continue_until_two/sequential_with_continue_until_two_3_expected_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/sequential_with_continue_until_two/sequential_with_continue_until_two_3_expected_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/sequential_with_continue_until_two/sequential_with_continue_until_two_3_expected_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/sequential_with_continue_until_two/sequential_with_continue_until_two_3_expected_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/sequential_with_continue_until_two/sequential_with_continue_until_two_3_expected_summary.json b/src/test/resources/network/brightspots/rcv/test_data/sequential_with_continue_until_two/sequential_with_continue_until_two_3_expected_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/sequential_with_continue_until_two/sequential_with_continue_until_two_3_expected_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/sequential_with_continue_until_two/sequential_with_continue_until_two_3_expected_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/skip_to_next_test/skip_to_next_test_expected_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/skip_to_next_test/skip_to_next_test_expected_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/skip_to_next_test/skip_to_next_test_expected_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/skip_to_next_test/skip_to_next_test_expected_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/skip_to_next_test/skip_to_next_test_expected_summary.json b/src/test/resources/network/brightspots/rcv/test_data/skip_to_next_test/skip_to_next_test_expected_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/skip_to_next_test/skip_to_next_test_expected_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/skip_to_next_test/skip_to_next_test_expected_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/stop_tabulation_early_test/stop_tabulation_early_test_expected_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/stop_tabulation_early_test/stop_tabulation_early_test_expected_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/stop_tabulation_early_test/stop_tabulation_early_test_expected_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/stop_tabulation_early_test/stop_tabulation_early_test_expected_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/stop_tabulation_early_test/stop_tabulation_early_test_expected_summary.json b/src/test/resources/network/brightspots/rcv/test_data/stop_tabulation_early_test/stop_tabulation_early_test_expected_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/stop_tabulation_early_test/stop_tabulation_early_test_expected_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/stop_tabulation_early_test/stop_tabulation_early_test_expected_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/test_set_0_skipped_first_choice/test_set_0_skipped_first_choice_expected_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/test_set_0_skipped_first_choice/test_set_0_skipped_first_choice_expected_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/test_set_0_skipped_first_choice/test_set_0_skipped_first_choice_expected_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/test_set_0_skipped_first_choice/test_set_0_skipped_first_choice_expected_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/test_set_0_skipped_first_choice/test_set_0_skipped_first_choice_expected_summary.json b/src/test/resources/network/brightspots/rcv/test_data/test_set_0_skipped_first_choice/test_set_0_skipped_first_choice_expected_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/test_set_0_skipped_first_choice/test_set_0_skipped_first_choice_expected_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/test_set_0_skipped_first_choice/test_set_0_skipped_first_choice_expected_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/test_set_1_exhaust_at_overvote/test_set_1_exhaust_at_overvote_expected_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/test_set_1_exhaust_at_overvote/test_set_1_exhaust_at_overvote_expected_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/test_set_1_exhaust_at_overvote/test_set_1_exhaust_at_overvote_expected_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/test_set_1_exhaust_at_overvote/test_set_1_exhaust_at_overvote_expected_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/test_set_1_exhaust_at_overvote/test_set_1_exhaust_at_overvote_expected_summary.json b/src/test/resources/network/brightspots/rcv/test_data/test_set_1_exhaust_at_overvote/test_set_1_exhaust_at_overvote_expected_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/test_set_1_exhaust_at_overvote/test_set_1_exhaust_at_overvote_expected_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/test_set_1_exhaust_at_overvote/test_set_1_exhaust_at_overvote_expected_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/test_set_2_overvote_skip_to_next/test_set_2_overvote_skip_to_next_expected_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/test_set_2_overvote_skip_to_next/test_set_2_overvote_skip_to_next_expected_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/test_set_2_overvote_skip_to_next/test_set_2_overvote_skip_to_next_expected_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/test_set_2_overvote_skip_to_next/test_set_2_overvote_skip_to_next_expected_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/test_set_2_overvote_skip_to_next/test_set_2_overvote_skip_to_next_expected_summary.json b/src/test/resources/network/brightspots/rcv/test_data/test_set_2_overvote_skip_to_next/test_set_2_overvote_skip_to_next_expected_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/test_set_2_overvote_skip_to_next/test_set_2_overvote_skip_to_next_expected_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/test_set_2_overvote_skip_to_next/test_set_2_overvote_skip_to_next_expected_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/test_set_3_skipped_choice_exhaust/test_set_3_skipped_choice_exhaust_expected_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/test_set_3_skipped_choice_exhaust/test_set_3_skipped_choice_exhaust_expected_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/test_set_3_skipped_choice_exhaust/test_set_3_skipped_choice_exhaust_expected_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/test_set_3_skipped_choice_exhaust/test_set_3_skipped_choice_exhaust_expected_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/test_set_3_skipped_choice_exhaust/test_set_3_skipped_choice_exhaust_expected_summary.json b/src/test/resources/network/brightspots/rcv/test_data/test_set_3_skipped_choice_exhaust/test_set_3_skipped_choice_exhaust_expected_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/test_set_3_skipped_choice_exhaust/test_set_3_skipped_choice_exhaust_expected_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/test_set_3_skipped_choice_exhaust/test_set_3_skipped_choice_exhaust_expected_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/test_set_4_skipped_choice_next/test_set_4_skipped_choice_next_expected_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/test_set_4_skipped_choice_next/test_set_4_skipped_choice_next_expected_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/test_set_4_skipped_choice_next/test_set_4_skipped_choice_next_expected_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/test_set_4_skipped_choice_next/test_set_4_skipped_choice_next_expected_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/test_set_4_skipped_choice_next/test_set_4_skipped_choice_next_expected_summary.json b/src/test/resources/network/brightspots/rcv/test_data/test_set_4_skipped_choice_next/test_set_4_skipped_choice_next_expected_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/test_set_4_skipped_choice_next/test_set_4_skipped_choice_next_expected_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/test_set_4_skipped_choice_next/test_set_4_skipped_choice_next_expected_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/test_set_5_two_skipped_choice_exhaust/test_set_5_two_skipped_choice_exhaust_expected_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/test_set_5_two_skipped_choice_exhaust/test_set_5_two_skipped_choice_exhaust_expected_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/test_set_5_two_skipped_choice_exhaust/test_set_5_two_skipped_choice_exhaust_expected_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/test_set_5_two_skipped_choice_exhaust/test_set_5_two_skipped_choice_exhaust_expected_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/test_set_5_two_skipped_choice_exhaust/test_set_5_two_skipped_choice_exhaust_expected_summary.json b/src/test/resources/network/brightspots/rcv/test_data/test_set_5_two_skipped_choice_exhaust/test_set_5_two_skipped_choice_exhaust_expected_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/test_set_5_two_skipped_choice_exhaust/test_set_5_two_skipped_choice_exhaust_expected_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/test_set_5_two_skipped_choice_exhaust/test_set_5_two_skipped_choice_exhaust_expected_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/test_set_6_duplicate_exhaust/test_set_6_duplicate_exhaust_expected_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/test_set_6_duplicate_exhaust/test_set_6_duplicate_exhaust_expected_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/test_set_6_duplicate_exhaust/test_set_6_duplicate_exhaust_expected_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/test_set_6_duplicate_exhaust/test_set_6_duplicate_exhaust_expected_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/test_set_6_duplicate_exhaust/test_set_6_duplicate_exhaust_expected_summary.json b/src/test/resources/network/brightspots/rcv/test_data/test_set_6_duplicate_exhaust/test_set_6_duplicate_exhaust_expected_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/test_set_6_duplicate_exhaust/test_set_6_duplicate_exhaust_expected_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/test_set_6_duplicate_exhaust/test_set_6_duplicate_exhaust_expected_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/test_set_7_duplicate_skip_to_next/test_set_7_duplicate_skip_to_next_expected_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/test_set_7_duplicate_skip_to_next/test_set_7_duplicate_skip_to_next_expected_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/test_set_7_duplicate_skip_to_next/test_set_7_duplicate_skip_to_next_expected_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/test_set_7_duplicate_skip_to_next/test_set_7_duplicate_skip_to_next_expected_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/test_set_7_duplicate_skip_to_next/test_set_7_duplicate_skip_to_next_expected_summary.json b/src/test/resources/network/brightspots/rcv/test_data/test_set_7_duplicate_skip_to_next/test_set_7_duplicate_skip_to_next_expected_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/test_set_7_duplicate_skip_to_next/test_set_7_duplicate_skip_to_next_expected_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/test_set_7_duplicate_skip_to_next/test_set_7_duplicate_skip_to_next_expected_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/test_set_8_multi_cdf/test_set_8_multi_cdf_expected_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/test_set_8_multi_cdf/test_set_8_multi_cdf_expected_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/test_set_8_multi_cdf/test_set_8_multi_cdf_expected_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/test_set_8_multi_cdf/test_set_8_multi_cdf_expected_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/test_set_8_multi_cdf/test_set_8_multi_cdf_expected_summary.json b/src/test/resources/network/brightspots/rcv/test_data/test_set_8_multi_cdf/test_set_8_multi_cdf_expected_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/test_set_8_multi_cdf/test_set_8_multi_cdf_expected_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/test_set_8_multi_cdf/test_set_8_multi_cdf_expected_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/test_set_allow_only_one_winner_per_round/test_set_allow_only_one_winner_per_round_expected_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/test_set_allow_only_one_winner_per_round/test_set_allow_only_one_winner_per_round_expected_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/test_set_allow_only_one_winner_per_round/test_set_allow_only_one_winner_per_round_expected_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/test_set_allow_only_one_winner_per_round/test_set_allow_only_one_winner_per_round_expected_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/test_set_allow_only_one_winner_per_round/test_set_allow_only_one_winner_per_round_expected_summary.json b/src/test/resources/network/brightspots/rcv/test_data/test_set_allow_only_one_winner_per_round/test_set_allow_only_one_winner_per_round_expected_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/test_set_allow_only_one_winner_per_round/test_set_allow_only_one_winner_per_round_expected_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/test_set_allow_only_one_winner_per_round/test_set_allow_only_one_winner_per_round_expected_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/test_set_multi_winner_fractional_threshold/test_set_multi_winner_fractional_threshold_expected_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/test_set_multi_winner_fractional_threshold/test_set_multi_winner_fractional_threshold_expected_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/test_set_multi_winner_fractional_threshold/test_set_multi_winner_fractional_threshold_expected_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/test_set_multi_winner_fractional_threshold/test_set_multi_winner_fractional_threshold_expected_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/test_set_multi_winner_fractional_threshold/test_set_multi_winner_fractional_threshold_expected_summary.json b/src/test/resources/network/brightspots/rcv/test_data/test_set_multi_winner_fractional_threshold/test_set_multi_winner_fractional_threshold_expected_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/test_set_multi_winner_fractional_threshold/test_set_multi_winner_fractional_threshold_expected_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/test_set_multi_winner_fractional_threshold/test_set_multi_winner_fractional_threshold_expected_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/test_set_multi_winner_whole_threshold/test_set_multi_winner_whole_threshold_expected_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/test_set_multi_winner_whole_threshold/test_set_multi_winner_whole_threshold_expected_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/test_set_multi_winner_whole_threshold/test_set_multi_winner_whole_threshold_expected_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/test_set_multi_winner_whole_threshold/test_set_multi_winner_whole_threshold_expected_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/test_set_multi_winner_whole_threshold/test_set_multi_winner_whole_threshold_expected_summary.json b/src/test/resources/network/brightspots/rcv/test_data/test_set_multi_winner_whole_threshold/test_set_multi_winner_whole_threshold_expected_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/test_set_multi_winner_whole_threshold/test_set_multi_winner_whole_threshold_expected_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/test_set_multi_winner_whole_threshold/test_set_multi_winner_whole_threshold_expected_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/test_set_overvote_delimiter/test_set_overvote_delimiter_expected_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/test_set_overvote_delimiter/test_set_overvote_delimiter_expected_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/test_set_overvote_delimiter/test_set_overvote_delimiter_expected_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/test_set_overvote_delimiter/test_set_overvote_delimiter_expected_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/test_set_overvote_delimiter/test_set_overvote_delimiter_expected_summary.json b/src/test/resources/network/brightspots/rcv/test_data/test_set_overvote_delimiter/test_set_overvote_delimiter_expected_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/test_set_overvote_delimiter/test_set_overvote_delimiter_expected_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/test_set_overvote_delimiter/test_set_overvote_delimiter_expected_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/test_set_treat_blank_as_undeclared_write_in/test_set_treat_blank_as_undeclared_write_in_expected_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/test_set_treat_blank_as_undeclared_write_in/test_set_treat_blank_as_undeclared_write_in_expected_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/test_set_treat_blank_as_undeclared_write_in/test_set_treat_blank_as_undeclared_write_in_expected_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/test_set_treat_blank_as_undeclared_write_in/test_set_treat_blank_as_undeclared_write_in_expected_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/test_set_treat_blank_as_undeclared_write_in/test_set_treat_blank_as_undeclared_write_in_expected_summary.json b/src/test/resources/network/brightspots/rcv/test_data/test_set_treat_blank_as_undeclared_write_in/test_set_treat_blank_as_undeclared_write_in_expected_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/test_set_treat_blank_as_undeclared_write_in/test_set_treat_blank_as_undeclared_write_in_expected_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/test_set_treat_blank_as_undeclared_write_in/test_set_treat_blank_as_undeclared_write_in_expected_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/tiebreak_generate_permutation_test/tiebreak_generate_permutation_test_expected_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/tiebreak_generate_permutation_test/tiebreak_generate_permutation_test_expected_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/tiebreak_generate_permutation_test/tiebreak_generate_permutation_test_expected_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/tiebreak_generate_permutation_test/tiebreak_generate_permutation_test_expected_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/tiebreak_generate_permutation_test/tiebreak_generate_permutation_test_expected_summary.json b/src/test/resources/network/brightspots/rcv/test_data/tiebreak_generate_permutation_test/tiebreak_generate_permutation_test_expected_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/tiebreak_generate_permutation_test/tiebreak_generate_permutation_test_expected_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/tiebreak_generate_permutation_test/tiebreak_generate_permutation_test_expected_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/tiebreak_previous_round_counts_then_random_test/tiebreak_previous_round_counts_then_random_test_expected_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/tiebreak_previous_round_counts_then_random_test/tiebreak_previous_round_counts_then_random_test_expected_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/tiebreak_previous_round_counts_then_random_test/tiebreak_previous_round_counts_then_random_test_expected_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/tiebreak_previous_round_counts_then_random_test/tiebreak_previous_round_counts_then_random_test_expected_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/tiebreak_previous_round_counts_then_random_test/tiebreak_previous_round_counts_then_random_test_expected_summary.json b/src/test/resources/network/brightspots/rcv/test_data/tiebreak_previous_round_counts_then_random_test/tiebreak_previous_round_counts_then_random_test_expected_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/tiebreak_previous_round_counts_then_random_test/tiebreak_previous_round_counts_then_random_test_expected_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/tiebreak_previous_round_counts_then_random_test/tiebreak_previous_round_counts_then_random_test_expected_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/tiebreak_seed_test/tiebreak_seed_test_expected_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/tiebreak_seed_test/tiebreak_seed_test_expected_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/tiebreak_seed_test/tiebreak_seed_test_expected_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/tiebreak_seed_test/tiebreak_seed_test_expected_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/tiebreak_seed_test/tiebreak_seed_test_expected_summary.json b/src/test/resources/network/brightspots/rcv/test_data/tiebreak_seed_test/tiebreak_seed_test_expected_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/tiebreak_seed_test/tiebreak_seed_test_expected_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/tiebreak_seed_test/tiebreak_seed_test_expected_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/tiebreak_use_permutation_in_config_test/tiebreak_use_permutation_in_config_test_expected_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/tiebreak_use_permutation_in_config_test/tiebreak_use_permutation_in_config_test_expected_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/tiebreak_use_permutation_in_config_test/tiebreak_use_permutation_in_config_test_expected_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/tiebreak_use_permutation_in_config_test/tiebreak_use_permutation_in_config_test_expected_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/tiebreak_use_permutation_in_config_test/tiebreak_use_permutation_in_config_test_expected_summary.json b/src/test/resources/network/brightspots/rcv/test_data/tiebreak_use_permutation_in_config_test/tiebreak_use_permutation_in_config_test_expected_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/tiebreak_use_permutation_in_config_test/tiebreak_use_permutation_in_config_test_expected_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/tiebreak_use_permutation_in_config_test/tiebreak_use_permutation_in_config_test_expected_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/unisyn_xml_cdf_city_chief_of_police/unisyn_xml_cdf_city_chief_of_police_expected_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/unisyn_xml_cdf_city_chief_of_police/unisyn_xml_cdf_city_chief_of_police_expected_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/unisyn_xml_cdf_city_chief_of_police/unisyn_xml_cdf_city_chief_of_police_expected_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/unisyn_xml_cdf_city_chief_of_police/unisyn_xml_cdf_city_chief_of_police_expected_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/unisyn_xml_cdf_city_chief_of_police/unisyn_xml_cdf_city_chief_of_police_expected_summary.json b/src/test/resources/network/brightspots/rcv/test_data/unisyn_xml_cdf_city_chief_of_police/unisyn_xml_cdf_city_chief_of_police_expected_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/unisyn_xml_cdf_city_chief_of_police/unisyn_xml_cdf_city_chief_of_police_expected_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/unisyn_xml_cdf_city_chief_of_police/unisyn_xml_cdf_city_chief_of_police_expected_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/unisyn_xml_cdf_city_coroner/unisyn_xml_cdf_city_coroner_expected_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/unisyn_xml_cdf_city_coroner/unisyn_xml_cdf_city_coroner_expected_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/unisyn_xml_cdf_city_coroner/unisyn_xml_cdf_city_coroner_expected_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/unisyn_xml_cdf_city_coroner/unisyn_xml_cdf_city_coroner_expected_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/unisyn_xml_cdf_city_coroner/unisyn_xml_cdf_city_coroner_expected_summary.json b/src/test/resources/network/brightspots/rcv/test_data/unisyn_xml_cdf_city_coroner/unisyn_xml_cdf_city_coroner_expected_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/unisyn_xml_cdf_city_coroner/unisyn_xml_cdf_city_coroner_expected_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/unisyn_xml_cdf_city_coroner/unisyn_xml_cdf_city_coroner_expected_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/unisyn_xml_cdf_city_council_member/unisyn_xml_cdf_city_council_member_expected_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/unisyn_xml_cdf_city_council_member/unisyn_xml_cdf_city_council_member_expected_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/unisyn_xml_cdf_city_council_member/unisyn_xml_cdf_city_council_member_expected_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/unisyn_xml_cdf_city_council_member/unisyn_xml_cdf_city_council_member_expected_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/unisyn_xml_cdf_city_council_member/unisyn_xml_cdf_city_council_member_expected_summary.json b/src/test/resources/network/brightspots/rcv/test_data/unisyn_xml_cdf_city_council_member/unisyn_xml_cdf_city_council_member_expected_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/unisyn_xml_cdf_city_council_member/unisyn_xml_cdf_city_council_member_expected_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/unisyn_xml_cdf_city_council_member/unisyn_xml_cdf_city_council_member_expected_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/unisyn_xml_cdf_city_mayor/unisyn_xml_cdf_city_mayor_expected_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/unisyn_xml_cdf_city_mayor/unisyn_xml_cdf_city_mayor_expected_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/unisyn_xml_cdf_city_mayor/unisyn_xml_cdf_city_mayor_expected_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/unisyn_xml_cdf_city_mayor/unisyn_xml_cdf_city_mayor_expected_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/unisyn_xml_cdf_city_mayor/unisyn_xml_cdf_city_mayor_expected_summary.json b/src/test/resources/network/brightspots/rcv/test_data/unisyn_xml_cdf_city_mayor/unisyn_xml_cdf_city_mayor_expected_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/unisyn_xml_cdf_city_mayor/unisyn_xml_cdf_city_mayor_expected_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/unisyn_xml_cdf_city_mayor/unisyn_xml_cdf_city_mayor_expected_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/unisyn_xml_cdf_city_tax_collector/unisyn_xml_cdf_city_tax_collector_expected_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/unisyn_xml_cdf_city_tax_collector/unisyn_xml_cdf_city_tax_collector_expected_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/unisyn_xml_cdf_city_tax_collector/unisyn_xml_cdf_city_tax_collector_expected_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/unisyn_xml_cdf_city_tax_collector/unisyn_xml_cdf_city_tax_collector_expected_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/unisyn_xml_cdf_city_tax_collector/unisyn_xml_cdf_city_tax_collector_expected_summary.json b/src/test/resources/network/brightspots/rcv/test_data/unisyn_xml_cdf_city_tax_collector/unisyn_xml_cdf_city_tax_collector_expected_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/unisyn_xml_cdf_city_tax_collector/unisyn_xml_cdf_city_tax_collector_expected_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/unisyn_xml_cdf_city_tax_collector/unisyn_xml_cdf_city_tax_collector_expected_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/unisyn_xml_cdf_county_coroner/unisyn_xml_cdf_county_coroner_expected_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/unisyn_xml_cdf_county_coroner/unisyn_xml_cdf_county_coroner_expected_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/unisyn_xml_cdf_county_coroner/unisyn_xml_cdf_county_coroner_expected_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/unisyn_xml_cdf_county_coroner/unisyn_xml_cdf_county_coroner_expected_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/unisyn_xml_cdf_county_coroner/unisyn_xml_cdf_county_coroner_expected_summary.json b/src/test/resources/network/brightspots/rcv/test_data/unisyn_xml_cdf_county_coroner/unisyn_xml_cdf_county_coroner_expected_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/unisyn_xml_cdf_county_coroner/unisyn_xml_cdf_county_coroner_expected_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/unisyn_xml_cdf_county_coroner/unisyn_xml_cdf_county_coroner_expected_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/unisyn_xml_cdf_county_sheriff/unisyn_xml_cdf_county_sheriff_expected_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/unisyn_xml_cdf_county_sheriff/unisyn_xml_cdf_county_sheriff_expected_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/unisyn_xml_cdf_county_sheriff/unisyn_xml_cdf_county_sheriff_expected_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/unisyn_xml_cdf_county_sheriff/unisyn_xml_cdf_county_sheriff_expected_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/unisyn_xml_cdf_county_sheriff/unisyn_xml_cdf_county_sheriff_expected_summary.json b/src/test/resources/network/brightspots/rcv/test_data/unisyn_xml_cdf_county_sheriff/unisyn_xml_cdf_county_sheriff_expected_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/unisyn_xml_cdf_county_sheriff/unisyn_xml_cdf_county_sheriff_expected_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/unisyn_xml_cdf_county_sheriff/unisyn_xml_cdf_county_sheriff_expected_detailed_report.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/uwi_cannot_win_test/uwi_cannot_win_test_expected_extended_summary.csv b/src/test/resources/network/brightspots/rcv/test_data/uwi_cannot_win_test/uwi_cannot_win_test_expected_detailed_report.csv similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/uwi_cannot_win_test/uwi_cannot_win_test_expected_extended_summary.csv rename to src/test/resources/network/brightspots/rcv/test_data/uwi_cannot_win_test/uwi_cannot_win_test_expected_detailed_report.csv diff --git a/src/test/resources/network/brightspots/rcv/test_data/uwi_cannot_win_test/uwi_cannot_win_test_expected_summary.json b/src/test/resources/network/brightspots/rcv/test_data/uwi_cannot_win_test/uwi_cannot_win_test_expected_detailed_report.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/uwi_cannot_win_test/uwi_cannot_win_test_expected_summary.json rename to src/test/resources/network/brightspots/rcv/test_data/uwi_cannot_win_test/uwi_cannot_win_test_expected_detailed_report.json From d75970894e98ba757264e7fba373c2f2afda4a62 Mon Sep 17 00:00:00 2001 From: Armin Samii Date: Sat, 19 Oct 2024 15:50:52 -0400 Subject: [PATCH 10/17] rename ResultFile to ResultTypeAndSlice, and CVR_CDF to CDF_CVR --- .../brightspots/rcv/ResultsWriter.java | 76 ++++++++++--------- .../brightspots/rcv/TabulatorTests.java | 28 +++---- 2 files changed, 55 insertions(+), 49 deletions(-) diff --git a/src/main/java/network/brightspots/rcv/ResultsWriter.java b/src/main/java/network/brightspots/rcv/ResultsWriter.java index f00b2668f..088bdc5f1 100644 --- a/src/main/java/network/brightspots/rcv/ResultsWriter.java +++ b/src/main/java/network/brightspots/rcv/ResultsWriter.java @@ -93,7 +93,7 @@ public enum ResultType { SUMMARY_CSV("summary_report", "csv"), DETAILED_CSV("detailed_report", "csv"), DETAILED_JSON("detailed_report", "json"), - CDF("cvr_cdf", "json"), + CDF_CVR("cdf_cvr", "json"), RCTAB_CVR("rctab_cvr", "csv"); private final String basename; @@ -113,7 +113,7 @@ public String getExtension() { } } - public static class ResultFile { + public static class ResultTypeAndSlice { // Since sanitizing Slice IDs can cause filename collisions, ensure each non-sanitized // Slice ID is given a unique sanitized name. private static final Dictionary sliceIdToUniqueSanitizedId = new Hashtable<>(); @@ -125,14 +125,14 @@ public static class ResultFile { private final TabulateBySlice slice; private final String sliceId; - ResultFile(ResultType resultType) { + ResultTypeAndSlice(ResultType resultType) { this.resultType = resultType; this.isSlice = false; slice = null; sliceId = null; } - ResultFile(ResultType resultType, TabulateBySlice slice, String sliceId) { + ResultTypeAndSlice(ResultType resultType, TabulateBySlice slice, String sliceId) { this.resultType = resultType; this.isSlice = true; this.slice = slice; @@ -336,20 +336,22 @@ void generateBySliceSummaryFiles( String sliceId = entry.getKey(); RoundTallies roundTallies = entry.getValue(); TallyTransfers tallyTransfers = tallyTransfersBySlice.get(slice, sliceId); - ResultFile resultFileCsv = new ResultFile(ResultType.DETAILED_CSV, slice, sliceId); - ResultFile resultFileJson = new ResultFile(ResultType.DETAILED_JSON, slice, sliceId); - generateSummaryCsv(roundTallies, candidateOrder, resultFileCsv); - generateSummaryJson(roundTallies, tallyTransfers, resultFileJson); + ResultTypeAndSlice resultTypeAndSliceCsv = + new ResultTypeAndSlice(ResultType.DETAILED_CSV, slice, sliceId); + ResultTypeAndSlice resultTypeAndSliceJson = + new ResultTypeAndSlice(ResultType.DETAILED_JSON, slice, sliceId); + generateSummaryCsv(roundTallies, candidateOrder, resultTypeAndSliceCsv); + generateSummaryJson(roundTallies, tallyTransfers, resultTypeAndSliceJson); } } } - private AuditableFile createAuditableFile(ResultFile resultFile) { + private AuditableFile createAuditableFile(ResultTypeAndSlice resultTypeAndSlice) { Integer sequentialId = null; if (config.isMultiSeatSequentialWinnerTakesAllEnabled()) { sequentialId = config.getSequentialWinners().size() + 1; } - return new AuditableFile(resultFile.getPath( + return new AuditableFile(resultTypeAndSlice.getPath( config.getOutputDirectory(), timestampString, sequentialId)); } @@ -363,11 +365,11 @@ private AuditableFile createAuditableFile(ResultFile resultFile) { private void generateSummaryCsv( RoundTallies roundTallies, List candidateOrder, - ResultFile resultFile) throws IOException { - if (resultFile.resultType != ResultType.SUMMARY_CSV - && resultFile.resultType != ResultType.DETAILED_CSV) { + ResultTypeAndSlice resultTypeAndSlice) throws IOException { + if (resultTypeAndSlice.resultType != ResultType.SUMMARY_CSV + && resultTypeAndSlice.resultType != ResultType.DETAILED_CSV) { throw new IllegalArgumentException("ResultFile provided non-CSV type " - + resultFile.resultType); + + resultTypeAndSlice.resultType); } // Check that all candidates are included in the candidate order Set expectedCandidates = roundTallies.get(1).getCandidates(); @@ -379,7 +381,7 @@ private void generateSummaryCsv( + "\nProvided: " + providedCandidates); } - AuditableFile csvFile = createAuditableFile(resultFile); + AuditableFile csvFile = createAuditableFile(resultTypeAndSlice); Logger.info("Generating summary spreadsheet: %s...", csvFile.getAbsolutePath()); CSVPrinter csvPrinter; @@ -394,7 +396,8 @@ private void generateSummaryCsv( } BigDecimal winningThreshold = roundTallies.get(numRounds).getWinningThreshold(); - addContestInformationRows(csvPrinter, winningThreshold, resultFile.slice, resultFile.sliceId); + addContestInformationRows(csvPrinter, winningThreshold, + resultTypeAndSlice.slice, resultTypeAndSlice.sliceId); addContestSummaryRows(csvPrinter, roundTallies.get(1)); csvPrinter.print("Rounds"); for (int round = 1; round <= numRounds; round++) { @@ -404,10 +407,10 @@ private void generateSummaryCsv( } csvPrinter.println(); - csvPrinter.print(resultFile.isSlice ? "Eliminated*" : "Eliminated"); + csvPrinter.print(resultTypeAndSlice.isSlice ? "Eliminated*" : "Eliminated"); printActionSummary(csvPrinter, roundToEliminatedCandidates); - csvPrinter.print(resultFile.isSlice ? "Elected*" : "Elected"); + csvPrinter.print(resultTypeAndSlice.isSlice ? "Elected*" : "Elected"); printActionSummary(csvPrinter, roundToWinningCandidates); // For each candidate: for each round: output total votes @@ -463,7 +466,7 @@ private void generateSummaryCsv( } csvPrinter.println(); - if (!resultFile.isSlice) { + if (!resultTypeAndSlice.isSlice) { csvPrinter.print("Current Round Threshold"); for (int round = 1; round <= numRounds; round++) { csvPrinter.print(roundTallies.get(round).getWinningThreshold()); @@ -473,7 +476,7 @@ private void generateSummaryCsv( csvPrinter.println(); } - if (resultFile.resultType == ResultType.DETAILED_CSV) { + if (resultTypeAndSlice.resultType == ResultType.DETAILED_CSV) { for (StatusForRound status : STATUSES_TO_PRINT) { csvPrinter.print(status.getTitleCaseKey()); @@ -525,7 +528,7 @@ private void generateSummaryCsv( // whether the value in the final round is positive. // Note that this concept only makes sense when we're reporting the overall tabulation, so we // omit it when generating results at the individual by-slice level. - if (!resultFile.isSlice && roundToResidualSurplus.get(numRounds).signum() == 1) { + if (!resultTypeAndSlice.isSlice && roundToResidualSurplus.get(numRounds).signum() == 1) { csvPrinter.print("Residual surplus"); for (int round = 1; round <= numRounds; round++) { csvPrinter.print(roundToResidualSurplus.get(round)); @@ -552,11 +555,11 @@ private void generateSummaryCsv( csvPrinter.println(); } - if (resultFile.isSlice) { + if (resultTypeAndSlice.isSlice) { csvPrinter.println(); csvPrinter.print(String.format("*Elect/Eliminate decisions are from the full contest. " + "All other results on this report are at the %s level.", - resultFile.slice.toLowerString())); + resultTypeAndSlice.slice.toLowerString())); csvPrinter.println(); } @@ -565,7 +568,7 @@ private void generateSummaryCsv( csvPrinter.close(); csvFile.finalizeAndHash(); } catch (IOException exception) { - Logger.severe("Error saving file: %s\n%s", resultFile.resultType, exception); + Logger.severe("Error saving file: %s\n%s", resultTypeAndSlice.resultType, exception); throw exception; } Logger.info("Summary spreadsheet generated successfully."); @@ -656,9 +659,12 @@ void generateOverallSummaryFiles( RoundTallies roundTallies, TallyTransfers tallyTransfers, List candidateOrder) throws IOException { - generateSummaryCsv(roundTallies, candidateOrder, new ResultFile(ResultType.SUMMARY_CSV)); - generateSummaryCsv(roundTallies, candidateOrder, new ResultFile(ResultType.DETAILED_CSV)); - generateSummaryJson(roundTallies, tallyTransfers, new ResultFile(ResultType.DETAILED_JSON)); + generateSummaryCsv(roundTallies, candidateOrder, + new ResultTypeAndSlice(ResultType.SUMMARY_CSV)); + generateSummaryCsv(roundTallies, candidateOrder, + new ResultTypeAndSlice(ResultType.DETAILED_CSV)); + generateSummaryJson(roundTallies, tallyTransfers, + new ResultTypeAndSlice(ResultType.DETAILED_JSON)); } // Write CastVoteRecords for the specified contest to the provided folder, @@ -675,8 +681,8 @@ String writeRcTabCvrCsv( // Put the input filename in the output filename in case contestId isn't unique -- // knowing that it's possible that if both the filename AND the contestId isn't unique, // this will fail. - ResultFile resultFile = new ResultFile(ResultType.RCTAB_CVR); - AuditableFile auditableFile = createAuditableFile(resultFile); + ResultTypeAndSlice resultTypeAndSlice = new ResultTypeAndSlice(ResultType.RCTAB_CVR); + AuditableFile auditableFile = createAuditableFile(resultTypeAndSlice); try { Logger.info("Writing cast vote records in generic format to file: %s...", auditableFile.getAbsolutePath()); @@ -795,8 +801,8 @@ void generateCdfJson(List castVoteRecords) // generate GpUnitIds for precincts "geopolitical units" (can be a precinct or jurisdiction) gpUnitIds = generateGpUnitIds(); - ResultFile resultFile = new ResultFile(ResultType.CDF); - AuditableFile auditableFile = createAuditableFile(resultFile); + ResultTypeAndSlice resultTypeAndSlice = new ResultTypeAndSlice(ResultType.CDF_CVR); + AuditableFile auditableFile = createAuditableFile(resultTypeAndSlice); Logger.info("Generating cast vote record CDF JSON file: %s...", auditableFile.getAbsolutePath()); @@ -1032,9 +1038,9 @@ private Map generateCdfMapForElection() { private void generateSummaryJson( RoundTallies roundTallies, TallyTransfers tallyTransfers, - ResultFile resultFile) + ResultTypeAndSlice resultTypeAndSlice) throws IOException { - AuditableFile jsonFile = createAuditableFile(resultFile); + AuditableFile jsonFile = createAuditableFile(resultTypeAndSlice); Logger.info("Generating summary JSON file: %s...", jsonFile.getAbsolutePath()); // config will contain contest configuration info @@ -1044,8 +1050,8 @@ private void generateSummaryJson( configData.put("jurisdiction", config.getContestJurisdiction()); configData.put("office", config.getContestOffice()); configData.put("date", config.getContestDate()); - if (resultFile.isSlice) { - configData.put(resultFile.slice.toLowerString(), resultFile.sliceId); + if (resultTypeAndSlice.isSlice) { + configData.put(resultTypeAndSlice.slice.toLowerString(), resultTypeAndSlice.sliceId); } BigDecimal numNoRankings = diff --git a/src/test/java/network/brightspots/rcv/TabulatorTests.java b/src/test/java/network/brightspots/rcv/TabulatorTests.java index 3e19030a0..3d2c72883 100644 --- a/src/test/java/network/brightspots/rcv/TabulatorTests.java +++ b/src/test/java/network/brightspots/rcv/TabulatorTests.java @@ -39,7 +39,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import network.brightspots.rcv.ResultsWriter.ResultFile; +import network.brightspots.rcv.ResultsWriter.ResultTypeAndSlice; import network.brightspots.rcv.ResultsWriter.ResultType; import network.brightspots.rcv.Tabulator.TabulationAbortedException; import org.junit.jupiter.api.BeforeAll; @@ -241,12 +241,12 @@ private static void runTabulationTest(String stem, String expectedException, int numSlicedFilesChecked = 0; for (ContestConfig.TabulateBySlice slice : config.enabledSlices()) { for (String sliceName : session.loadSliceNamesFromCvrs(slice, config)) { - ResultFile resultFileJson = new ResultFile(ResultType.DETAILED_JSON, slice, sliceName); - ResultFile resultFileCsv = new ResultFile(ResultType.DETAILED_CSV, slice, sliceName); - if (compareFiles(config, stem, resultFileJson, timestampString, null, true)) { + ResultsWriter.ResultTypeAndSlice resultTypeAndSliceJson = new ResultTypeAndSlice(ResultType.DETAILED_JSON, slice, sliceName); + ResultsWriter.ResultTypeAndSlice resultTypeAndSliceCsv = new ResultsWriter.ResultTypeAndSlice(ResultType.DETAILED_CSV, slice, sliceName); + if (compareFiles(config, stem, resultTypeAndSliceJson, timestampString, null, true)) { numSlicedFilesChecked++; } - if (compareFiles(config, stem, resultFileCsv, timestampString, null, true)) { + if (compareFiles(config, stem, resultTypeAndSliceCsv, timestampString, null, true)) { numSlicedFilesChecked++; } } @@ -265,7 +265,7 @@ private static void runConvertToCdfTest(String stem) { String timestampString = session.getTimestampString(); ContestConfig config = ContestConfig.loadContestConfig(configPath); - compareFiles(config, stem, ResultType.CDF, timestampString, null, false); + compareFiles(config, stem, ResultType.CDF_CVR, timestampString, null, false); cleanOutputFolder(session); } @@ -333,7 +333,7 @@ private static void compareFiles( compareFiles(config, stem, ResultType.DETAILED_CSV, timestampString, sequentialId, false); compareExtendedSummaryToSummary(config, timestampString, sequentialId); if (config.isGenerateCdfJsonEnabled()) { - compareFiles(config, stem, ResultType.CDF, timestampString, sequentialId, false); + compareFiles(config, stem, ResultType.CDF_CVR, timestampString, sequentialId, false); } } @@ -347,11 +347,11 @@ private static boolean compareFiles( String timestampString, Integer sequentialId, boolean onlyCheckIfExpectedFileExists) { - ResultFile actualResultFile = new ResultFile(resultType); + ResultsWriter.ResultTypeAndSlice actualResultTypeAndSlice = new ResultTypeAndSlice(resultType); return compareFiles( config, stem, - actualResultFile, + actualResultTypeAndSlice, timestampString, sequentialId, onlyCheckIfExpectedFileExists); @@ -364,13 +364,13 @@ private static boolean compareFiles( private static boolean compareFiles( ContestConfig config, String stem, - ResultFile actualResultFile, + ResultsWriter.ResultTypeAndSlice actualResultTypeAndSlice, String timestampString, Integer sequentialId, boolean onlyCheckIfExpectedFileExists) { - String actualOutputPath = actualResultFile.getPath( + String actualOutputPath = actualResultTypeAndSlice.getPath( config.getOutputDirectory(), timestampString, sequentialId).toAbsolutePath().toString(); - String expectedPath = actualResultFile.getPath(getTestDirectory(stem).toString(), + String expectedPath = actualResultTypeAndSlice.getPath(getTestDirectory(stem).toString(), stem, "expected", sequentialId).toString(); Logger.info("Comparing files:\nGenerated: %s\nReference: %s", actualOutputPath, expectedPath); @@ -395,9 +395,9 @@ private static boolean compareFiles( private static void compareExtendedSummaryToSummary( ContestConfig config, String timestampString, Integer sequentialId) { String dir = config.getOutputDirectory(); - String summaryPath = new ResultFile(ResultType.SUMMARY_CSV).getPath( + String summaryPath = new ResultTypeAndSlice(ResultType.SUMMARY_CSV).getPath( dir, timestampString, sequentialId).toAbsolutePath().toString(); - String detailedPath = new ResultFile(ResultType.DETAILED_CSV).getPath( + String detailedPath = new ResultsWriter.ResultTypeAndSlice(ResultType.DETAILED_CSV).getPath( dir, timestampString, sequentialId).toAbsolutePath().toString(); try (BufferedReader brSummary = new BufferedReader(new FileReader(summaryPath, UTF_8)); From 2b0549b1bb181fb12a5e303700021c77c95e1c31 Mon Sep 17 00:00:00 2001 From: Armin Samii Date: Sat, 19 Oct 2024 15:55:04 -0400 Subject: [PATCH 11/17] address additional PR comments --- src/main/java/network/brightspots/rcv/ResultsWriter.java | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/main/java/network/brightspots/rcv/ResultsWriter.java b/src/main/java/network/brightspots/rcv/ResultsWriter.java index 088bdc5f1..51197b9ac 100644 --- a/src/main/java/network/brightspots/rcv/ResultsWriter.java +++ b/src/main/java/network/brightspots/rcv/ResultsWriter.java @@ -358,10 +358,7 @@ private AuditableFile createAuditableFile(ResultTypeAndSlice resultTypeAndSlice) // create a summary spreadsheet .csv file // param: roundTallies is the round-by-count count of votes per candidate // param: candidateOrder is to allow a consistent ordering of candidates, including across slices - // param: slice indicates which type of slice we're reporting results for (null means all) - // param: sliceId indicates the specific slice ID we're reporting results for (null means all) - // param: outputPath is the path to the output file, minus its extension - // param: extended include additional details in the output file? + // param: resultTypeAndSlice must only have type DETAILED_CSV or SUMMARY_CSV private void generateSummaryCsv( RoundTallies roundTallies, List candidateOrder, @@ -568,7 +565,7 @@ private void generateSummaryCsv( csvPrinter.close(); csvFile.finalizeAndHash(); } catch (IOException exception) { - Logger.severe("Error saving file: %s\n%s", resultTypeAndSlice.resultType, exception); + Logger.severe("Error saving file: %s\n%s", csvFile.getAbsolutePath(), exception); throw exception; } Logger.info("Summary spreadsheet generated successfully."); From 430fc249d81f17ddf1dea87bcca585bcdd98c47b Mon Sep 17 00:00:00 2001 From: Armin Samii Date: Sat, 19 Oct 2024 15:57:15 -0400 Subject: [PATCH 12/17] rename files: CVR_CDF to CDF_CVR --- ...pected_cvr_cdf.json => aliases_cdf_json_expected_cdf_cvr.json} | 0 ..._expected_cvr_cdf.json => batch_example_expected_cdf_cvr.json} | 0 ...ed_cvr_cdf.json => conversions_from_cdf_expected_cdf_cvr.json} | 0 ...r_cdf.json => conversions_from_dominion_expected_cdf_cvr.json} | 0 ...ed_cvr_cdf.json => conversions_from_ess_expected_cdf_cvr.json} | 0 ...pected_cvr_cdf.json => precinct_example_expected_cdf_cvr.json} | 0 ...json => test_set_0_skipped_first_choice_expected_cdf_cvr.json} | 0 ....json => test_set_1_exhaust_at_overvote_expected_cdf_cvr.json} | 0 ...son => test_set_2_overvote_skip_to_next_expected_cdf_cvr.json} | 0 ...on => test_set_3_skipped_choice_exhaust_expected_cdf_cvr.json} | 0 ....json => test_set_4_skipped_choice_next_expected_cdf_cvr.json} | 0 ...> test_set_5_two_skipped_choice_exhaust_expected_cdf_cvr.json} | 0 ...df.json => test_set_6_duplicate_exhaust_expected_cdf_cvr.json} | 0 ...on => test_set_7_duplicate_skip_to_next_expected_cdf_cvr.json} | 0 ...ed_cvr_cdf.json => test_set_8_multi_cdf_expected_cdf_cvr.json} | 0 ...t_set_multi_winner_fractional_threshold_expected_cdf_cvr.json} | 0 ...> test_set_multi_winner_whole_threshold_expected_cdf_cvr.json} | 0 17 files changed, 0 insertions(+), 0 deletions(-) rename src/test/resources/network/brightspots/rcv/test_data/aliases_cdf_json/{aliases_cdf_json_expected_cvr_cdf.json => aliases_cdf_json_expected_cdf_cvr.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/batch_example/{batch_example_expected_cvr_cdf.json => batch_example_expected_cdf_cvr.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/conversions_from_cdf/{conversions_from_cdf_expected_cvr_cdf.json => conversions_from_cdf_expected_cdf_cvr.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/conversions_from_dominion/{conversions_from_dominion_expected_cvr_cdf.json => conversions_from_dominion_expected_cdf_cvr.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/conversions_from_ess/{conversions_from_ess_expected_cvr_cdf.json => conversions_from_ess_expected_cdf_cvr.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/precinct_example/{precinct_example_expected_cvr_cdf.json => precinct_example_expected_cdf_cvr.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/test_set_0_skipped_first_choice/{test_set_0_skipped_first_choice_expected_cvr_cdf.json => test_set_0_skipped_first_choice_expected_cdf_cvr.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/test_set_1_exhaust_at_overvote/{test_set_1_exhaust_at_overvote_expected_cvr_cdf.json => test_set_1_exhaust_at_overvote_expected_cdf_cvr.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/test_set_2_overvote_skip_to_next/{test_set_2_overvote_skip_to_next_expected_cvr_cdf.json => test_set_2_overvote_skip_to_next_expected_cdf_cvr.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/test_set_3_skipped_choice_exhaust/{test_set_3_skipped_choice_exhaust_expected_cvr_cdf.json => test_set_3_skipped_choice_exhaust_expected_cdf_cvr.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/test_set_4_skipped_choice_next/{test_set_4_skipped_choice_next_expected_cvr_cdf.json => test_set_4_skipped_choice_next_expected_cdf_cvr.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/test_set_5_two_skipped_choice_exhaust/{test_set_5_two_skipped_choice_exhaust_expected_cvr_cdf.json => test_set_5_two_skipped_choice_exhaust_expected_cdf_cvr.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/test_set_6_duplicate_exhaust/{test_set_6_duplicate_exhaust_expected_cvr_cdf.json => test_set_6_duplicate_exhaust_expected_cdf_cvr.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/test_set_7_duplicate_skip_to_next/{test_set_7_duplicate_skip_to_next_expected_cvr_cdf.json => test_set_7_duplicate_skip_to_next_expected_cdf_cvr.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/test_set_8_multi_cdf/{test_set_8_multi_cdf_expected_cvr_cdf.json => test_set_8_multi_cdf_expected_cdf_cvr.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/test_set_multi_winner_fractional_threshold/{test_set_multi_winner_fractional_threshold_expected_cvr_cdf.json => test_set_multi_winner_fractional_threshold_expected_cdf_cvr.json} (100%) rename src/test/resources/network/brightspots/rcv/test_data/test_set_multi_winner_whole_threshold/{test_set_multi_winner_whole_threshold_expected_cvr_cdf.json => test_set_multi_winner_whole_threshold_expected_cdf_cvr.json} (100%) diff --git a/src/test/resources/network/brightspots/rcv/test_data/aliases_cdf_json/aliases_cdf_json_expected_cvr_cdf.json b/src/test/resources/network/brightspots/rcv/test_data/aliases_cdf_json/aliases_cdf_json_expected_cdf_cvr.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/aliases_cdf_json/aliases_cdf_json_expected_cvr_cdf.json rename to src/test/resources/network/brightspots/rcv/test_data/aliases_cdf_json/aliases_cdf_json_expected_cdf_cvr.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/batch_example/batch_example_expected_cvr_cdf.json b/src/test/resources/network/brightspots/rcv/test_data/batch_example/batch_example_expected_cdf_cvr.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/batch_example/batch_example_expected_cvr_cdf.json rename to src/test/resources/network/brightspots/rcv/test_data/batch_example/batch_example_expected_cdf_cvr.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/conversions_from_cdf/conversions_from_cdf_expected_cvr_cdf.json b/src/test/resources/network/brightspots/rcv/test_data/conversions_from_cdf/conversions_from_cdf_expected_cdf_cvr.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/conversions_from_cdf/conversions_from_cdf_expected_cvr_cdf.json rename to src/test/resources/network/brightspots/rcv/test_data/conversions_from_cdf/conversions_from_cdf_expected_cdf_cvr.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/conversions_from_dominion/conversions_from_dominion_expected_cvr_cdf.json b/src/test/resources/network/brightspots/rcv/test_data/conversions_from_dominion/conversions_from_dominion_expected_cdf_cvr.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/conversions_from_dominion/conversions_from_dominion_expected_cvr_cdf.json rename to src/test/resources/network/brightspots/rcv/test_data/conversions_from_dominion/conversions_from_dominion_expected_cdf_cvr.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/conversions_from_ess/conversions_from_ess_expected_cvr_cdf.json b/src/test/resources/network/brightspots/rcv/test_data/conversions_from_ess/conversions_from_ess_expected_cdf_cvr.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/conversions_from_ess/conversions_from_ess_expected_cvr_cdf.json rename to src/test/resources/network/brightspots/rcv/test_data/conversions_from_ess/conversions_from_ess_expected_cdf_cvr.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/precinct_example/precinct_example_expected_cvr_cdf.json b/src/test/resources/network/brightspots/rcv/test_data/precinct_example/precinct_example_expected_cdf_cvr.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/precinct_example/precinct_example_expected_cvr_cdf.json rename to src/test/resources/network/brightspots/rcv/test_data/precinct_example/precinct_example_expected_cdf_cvr.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/test_set_0_skipped_first_choice/test_set_0_skipped_first_choice_expected_cvr_cdf.json b/src/test/resources/network/brightspots/rcv/test_data/test_set_0_skipped_first_choice/test_set_0_skipped_first_choice_expected_cdf_cvr.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/test_set_0_skipped_first_choice/test_set_0_skipped_first_choice_expected_cvr_cdf.json rename to src/test/resources/network/brightspots/rcv/test_data/test_set_0_skipped_first_choice/test_set_0_skipped_first_choice_expected_cdf_cvr.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/test_set_1_exhaust_at_overvote/test_set_1_exhaust_at_overvote_expected_cvr_cdf.json b/src/test/resources/network/brightspots/rcv/test_data/test_set_1_exhaust_at_overvote/test_set_1_exhaust_at_overvote_expected_cdf_cvr.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/test_set_1_exhaust_at_overvote/test_set_1_exhaust_at_overvote_expected_cvr_cdf.json rename to src/test/resources/network/brightspots/rcv/test_data/test_set_1_exhaust_at_overvote/test_set_1_exhaust_at_overvote_expected_cdf_cvr.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/test_set_2_overvote_skip_to_next/test_set_2_overvote_skip_to_next_expected_cvr_cdf.json b/src/test/resources/network/brightspots/rcv/test_data/test_set_2_overvote_skip_to_next/test_set_2_overvote_skip_to_next_expected_cdf_cvr.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/test_set_2_overvote_skip_to_next/test_set_2_overvote_skip_to_next_expected_cvr_cdf.json rename to src/test/resources/network/brightspots/rcv/test_data/test_set_2_overvote_skip_to_next/test_set_2_overvote_skip_to_next_expected_cdf_cvr.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/test_set_3_skipped_choice_exhaust/test_set_3_skipped_choice_exhaust_expected_cvr_cdf.json b/src/test/resources/network/brightspots/rcv/test_data/test_set_3_skipped_choice_exhaust/test_set_3_skipped_choice_exhaust_expected_cdf_cvr.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/test_set_3_skipped_choice_exhaust/test_set_3_skipped_choice_exhaust_expected_cvr_cdf.json rename to src/test/resources/network/brightspots/rcv/test_data/test_set_3_skipped_choice_exhaust/test_set_3_skipped_choice_exhaust_expected_cdf_cvr.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/test_set_4_skipped_choice_next/test_set_4_skipped_choice_next_expected_cvr_cdf.json b/src/test/resources/network/brightspots/rcv/test_data/test_set_4_skipped_choice_next/test_set_4_skipped_choice_next_expected_cdf_cvr.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/test_set_4_skipped_choice_next/test_set_4_skipped_choice_next_expected_cvr_cdf.json rename to src/test/resources/network/brightspots/rcv/test_data/test_set_4_skipped_choice_next/test_set_4_skipped_choice_next_expected_cdf_cvr.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/test_set_5_two_skipped_choice_exhaust/test_set_5_two_skipped_choice_exhaust_expected_cvr_cdf.json b/src/test/resources/network/brightspots/rcv/test_data/test_set_5_two_skipped_choice_exhaust/test_set_5_two_skipped_choice_exhaust_expected_cdf_cvr.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/test_set_5_two_skipped_choice_exhaust/test_set_5_two_skipped_choice_exhaust_expected_cvr_cdf.json rename to src/test/resources/network/brightspots/rcv/test_data/test_set_5_two_skipped_choice_exhaust/test_set_5_two_skipped_choice_exhaust_expected_cdf_cvr.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/test_set_6_duplicate_exhaust/test_set_6_duplicate_exhaust_expected_cvr_cdf.json b/src/test/resources/network/brightspots/rcv/test_data/test_set_6_duplicate_exhaust/test_set_6_duplicate_exhaust_expected_cdf_cvr.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/test_set_6_duplicate_exhaust/test_set_6_duplicate_exhaust_expected_cvr_cdf.json rename to src/test/resources/network/brightspots/rcv/test_data/test_set_6_duplicate_exhaust/test_set_6_duplicate_exhaust_expected_cdf_cvr.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/test_set_7_duplicate_skip_to_next/test_set_7_duplicate_skip_to_next_expected_cvr_cdf.json b/src/test/resources/network/brightspots/rcv/test_data/test_set_7_duplicate_skip_to_next/test_set_7_duplicate_skip_to_next_expected_cdf_cvr.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/test_set_7_duplicate_skip_to_next/test_set_7_duplicate_skip_to_next_expected_cvr_cdf.json rename to src/test/resources/network/brightspots/rcv/test_data/test_set_7_duplicate_skip_to_next/test_set_7_duplicate_skip_to_next_expected_cdf_cvr.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/test_set_8_multi_cdf/test_set_8_multi_cdf_expected_cvr_cdf.json b/src/test/resources/network/brightspots/rcv/test_data/test_set_8_multi_cdf/test_set_8_multi_cdf_expected_cdf_cvr.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/test_set_8_multi_cdf/test_set_8_multi_cdf_expected_cvr_cdf.json rename to src/test/resources/network/brightspots/rcv/test_data/test_set_8_multi_cdf/test_set_8_multi_cdf_expected_cdf_cvr.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/test_set_multi_winner_fractional_threshold/test_set_multi_winner_fractional_threshold_expected_cvr_cdf.json b/src/test/resources/network/brightspots/rcv/test_data/test_set_multi_winner_fractional_threshold/test_set_multi_winner_fractional_threshold_expected_cdf_cvr.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/test_set_multi_winner_fractional_threshold/test_set_multi_winner_fractional_threshold_expected_cvr_cdf.json rename to src/test/resources/network/brightspots/rcv/test_data/test_set_multi_winner_fractional_threshold/test_set_multi_winner_fractional_threshold_expected_cdf_cvr.json diff --git a/src/test/resources/network/brightspots/rcv/test_data/test_set_multi_winner_whole_threshold/test_set_multi_winner_whole_threshold_expected_cvr_cdf.json b/src/test/resources/network/brightspots/rcv/test_data/test_set_multi_winner_whole_threshold/test_set_multi_winner_whole_threshold_expected_cdf_cvr.json similarity index 100% rename from src/test/resources/network/brightspots/rcv/test_data/test_set_multi_winner_whole_threshold/test_set_multi_winner_whole_threshold_expected_cvr_cdf.json rename to src/test/resources/network/brightspots/rcv/test_data/test_set_multi_winner_whole_threshold/test_set_multi_winner_whole_threshold_expected_cdf_cvr.json From e3090be7d2a225e3ff8b1aa3c1dacfe1d314994c Mon Sep 17 00:00:00 2001 From: yezr <8996546+yezr@users.noreply.github.com> Date: Mon, 21 Oct 2024 14:32:47 -0400 Subject: [PATCH 13/17] refator to make explicit the difference between a results file (what we previously referred to as the summary files) and an output file (the results files plus rctab_cvr and cdf_cvr) --- .../rcv/GuiTabulateController.java | 2 +- .../{ResultsWriter.java => OutputWriter.java} | 120 +++++++++--------- .../brightspots/rcv/StreamingCvrReader.java | 2 +- .../network/brightspots/rcv/Tabulator.java | 10 +- .../brightspots/rcv/TabulatorSession.java | 22 ++-- .../brightspots/rcv/TabulatorTests.java | 36 +++--- 6 files changed, 97 insertions(+), 95 deletions(-) rename src/main/java/network/brightspots/rcv/{ResultsWriter.java => OutputWriter.java} (92%) diff --git a/src/main/java/network/brightspots/rcv/GuiTabulateController.java b/src/main/java/network/brightspots/rcv/GuiTabulateController.java index 4ca57cda4..c382070ac 100644 --- a/src/main/java/network/brightspots/rcv/GuiTabulateController.java +++ b/src/main/java/network/brightspots/rcv/GuiTabulateController.java @@ -233,7 +233,7 @@ private void watchParseCvrServiceProgress(Service service) { // and calculate the width of the filename column perSourceCvrCountTable.getItems().clear(); int maxFilenameLength = 0; - for (ResultsWriter.CvrSourceData sourceData : data.getCvrSourcesData()) { + for (OutputWriter.CvrSourceData sourceData : data.getCvrSourcesData()) { String countString = String.format("%,d", sourceData.getNumCvrs()); String fileString = new File(sourceData.source.getFilePath()).getName(); perSourceCvrCountTable.getItems().add(new Pair<>(fileString, countString)); diff --git a/src/main/java/network/brightspots/rcv/ResultsWriter.java b/src/main/java/network/brightspots/rcv/OutputWriter.java similarity index 92% rename from src/main/java/network/brightspots/rcv/ResultsWriter.java rename to src/main/java/network/brightspots/rcv/OutputWriter.java index 51197b9ac..2f9b218c5 100644 --- a/src/main/java/network/brightspots/rcv/ResultsWriter.java +++ b/src/main/java/network/brightspots/rcv/OutputWriter.java @@ -57,7 +57,7 @@ import org.apache.commons.csv.CSVFormat; import org.apache.commons.csv.CSVPrinter; -class ResultsWriter { +class OutputWriter { private static final String CDF_CONTEST_ID = "contest-001"; private static final String CDF_ELECTION_ID = "election-001"; private static final String CDF_GPU_ID = "gpu-election"; @@ -89,7 +89,7 @@ class ResultsWriter { StatusForRound.EXHAUSTED_CHOICE, StatusForRound.INVALIDATED_BY_REPEATED_RANKING); - public enum ResultType { + public enum OutputType { SUMMARY_CSV("summary_report", "csv"), DETAILED_CSV("detailed_report", "csv"), DETAILED_JSON("detailed_report", "json"), @@ -99,7 +99,7 @@ public enum ResultType { private final String basename; private final String extension; - ResultType(String basename, String extension) { + OutputType(String basename, String extension) { this.basename = basename; this.extension = extension; } @@ -113,27 +113,29 @@ public String getExtension() { } } - public static class ResultTypeAndSlice { + // Core traits of any output file + // Includes helpers for the work we need to do with the Identifiers to write the actual files themselves + public static class OutputFileIdentifiers { // Since sanitizing Slice IDs can cause filename collisions, ensure each non-sanitized // Slice ID is given a unique sanitized name. private static final Dictionary sliceIdToUniqueSanitizedId = new Hashtable<>(); // This is a set of the values in sanitizerCollisionResolution to ensure there are no collisions // in the resulting sanitized names. private static final HashSet uniqueSanitizedIds = new HashSet<>(); - private final ResultType resultType; + private final OutputType outputType; private final boolean isSlice; private final TabulateBySlice slice; private final String sliceId; - ResultTypeAndSlice(ResultType resultType) { - this.resultType = resultType; + OutputFileIdentifiers(OutputType outputType) { + this.outputType = outputType; this.isSlice = false; slice = null; sliceId = null; } - ResultTypeAndSlice(ResultType resultType, TabulateBySlice slice, String sliceId) { - this.resultType = resultType; + OutputFileIdentifiers(OutputType outputType, TabulateBySlice slice, String sliceId) { + this.outputType = outputType; this.isSlice = true; this.slice = slice; this.sliceId = sliceId; @@ -161,10 +163,10 @@ public Path getPath(String directory, String prefix, String modifier, Integer se parts.add(sanitizeSliceWithoutCollisions(sliceId)); parts.add(slice.toLowerString()); } - parts.add(resultType.getBasename()); + parts.add(outputType.getBasename()); String filenameWithoutExt = String.join("_", parts); - return Path.of(directory, "%s.%s".formatted(filenameWithoutExt, resultType.getExtension())); + return Path.of(directory, "%s.%s".formatted(filenameWithoutExt, outputType.getExtension())); } private String sanitizeSliceWithoutCollisions(String sliceId) { @@ -276,22 +278,22 @@ private static List>> getCandidatesWithRanksList return sortedCandidatesWithRanks; } - ResultsWriter setRoundToResidualSurplus(Map roundToResidualSurplus) { + OutputWriter setRoundToResidualSurplus(Map roundToResidualSurplus) { this.roundToResidualSurplus = roundToResidualSurplus; return this; } - ResultsWriter setNumRounds(int numRounds) { + OutputWriter setNumRounds(int numRounds) { this.numRounds = numRounds; return this; } - ResultsWriter setSliceIds(SliceIdSet sliceIds) { + OutputWriter setSliceIds(SliceIdSet sliceIds) { this.sliceIds = sliceIds; return this; } - ResultsWriter setCandidatesToRoundEliminated(Map candidatesToRoundEliminated) { + OutputWriter setCandidatesToRoundEliminated(Map candidatesToRoundEliminated) { // roundToEliminatedCandidates is the inverse of candidatesToRoundEliminated map, // so we can look up who got eliminated for each round roundToEliminatedCandidates = new HashMap<>(); @@ -302,7 +304,7 @@ ResultsWriter setCandidatesToRoundEliminated(Map candidatesToRo return this; } - ResultsWriter setWinnerToRound(Map winnerToRound) { + OutputWriter setWinnerToRound(Map winnerToRound) { // very similar to the logic in setCandidatesToRoundEliminated above roundToWinningCandidates = new HashMap<>(); for (var entry : winnerToRound.entrySet()) { @@ -312,21 +314,21 @@ ResultsWriter setWinnerToRound(Map winnerToRound) { return this; } - ResultsWriter setContestConfig(ContestConfig config) { + OutputWriter setContestConfig(ContestConfig config) { this.config = config; return this; } - ResultsWriter setTimestampString(String timestampString) { + OutputWriter setTimestampString(String timestampString) { this.timestampString = timestampString; return this; } - // creates summary files for the votes split by a TabulateBySlice + // creates results files for the votes split by a TabulateBySlice // param: roundTalliesBySlice is map from a slice type to the round-by-round vote tallies // param: tallyTransfersBySlice is a map from a slice type to tally transfers for that slice // param: candidateOrder is to allow a consistent ordering of candidates, including across slices - void generateBySliceSummaryFiles( + void generateBySliceResultsFiles( Tabulator.BreakdownBySlice roundTalliesBySlice, Tabulator.BreakdownBySlice tallyTransfersBySlice, List candidateOrder) @@ -336,37 +338,37 @@ void generateBySliceSummaryFiles( String sliceId = entry.getKey(); RoundTallies roundTallies = entry.getValue(); TallyTransfers tallyTransfers = tallyTransfersBySlice.get(slice, sliceId); - ResultTypeAndSlice resultTypeAndSliceCsv = - new ResultTypeAndSlice(ResultType.DETAILED_CSV, slice, sliceId); - ResultTypeAndSlice resultTypeAndSliceJson = - new ResultTypeAndSlice(ResultType.DETAILED_JSON, slice, sliceId); - generateSummaryCsv(roundTallies, candidateOrder, resultTypeAndSliceCsv); - generateSummaryJson(roundTallies, tallyTransfers, resultTypeAndSliceJson); + OutputFileIdentifiers outputFileIdentifiersCsv = + new OutputFileIdentifiers(OutputType.DETAILED_CSV, slice, sliceId); + OutputFileIdentifiers outputFileIdentifiersJson = + new OutputFileIdentifiers(OutputType.DETAILED_JSON, slice, sliceId); + generateResultsCsv(roundTallies, candidateOrder, outputFileIdentifiersCsv); + generateResultsJson(roundTallies, tallyTransfers, outputFileIdentifiersJson); } } } - private AuditableFile createAuditableFile(ResultTypeAndSlice resultTypeAndSlice) { + private AuditableFile createAuditableFile(OutputFileIdentifiers outputFileIdentifiers) { Integer sequentialId = null; if (config.isMultiSeatSequentialWinnerTakesAllEnabled()) { sequentialId = config.getSequentialWinners().size() + 1; } - return new AuditableFile(resultTypeAndSlice.getPath( + return new AuditableFile(outputFileIdentifiers.getPath( config.getOutputDirectory(), timestampString, sequentialId)); } - // create a summary spreadsheet .csv file + // create a results .csv file // param: roundTallies is the round-by-count count of votes per candidate // param: candidateOrder is to allow a consistent ordering of candidates, including across slices // param: resultTypeAndSlice must only have type DETAILED_CSV or SUMMARY_CSV - private void generateSummaryCsv( + private void generateResultsCsv( RoundTallies roundTallies, List candidateOrder, - ResultTypeAndSlice resultTypeAndSlice) throws IOException { - if (resultTypeAndSlice.resultType != ResultType.SUMMARY_CSV - && resultTypeAndSlice.resultType != ResultType.DETAILED_CSV) { + OutputFileIdentifiers outputFileIdentifiers) throws IOException { + if (outputFileIdentifiers.outputType != OutputType.SUMMARY_CSV + && outputFileIdentifiers.outputType != OutputType.DETAILED_CSV) { throw new IllegalArgumentException("ResultFile provided non-CSV type " - + resultTypeAndSlice.resultType); + + outputFileIdentifiers.outputType); } // Check that all candidates are included in the candidate order Set expectedCandidates = roundTallies.get(1).getCandidates(); @@ -378,7 +380,7 @@ private void generateSummaryCsv( + "\nProvided: " + providedCandidates); } - AuditableFile csvFile = createAuditableFile(resultTypeAndSlice); + AuditableFile csvFile = createAuditableFile(outputFileIdentifiers); Logger.info("Generating summary spreadsheet: %s...", csvFile.getAbsolutePath()); CSVPrinter csvPrinter; @@ -394,7 +396,7 @@ private void generateSummaryCsv( BigDecimal winningThreshold = roundTallies.get(numRounds).getWinningThreshold(); addContestInformationRows(csvPrinter, winningThreshold, - resultTypeAndSlice.slice, resultTypeAndSlice.sliceId); + outputFileIdentifiers.slice, outputFileIdentifiers.sliceId); addContestSummaryRows(csvPrinter, roundTallies.get(1)); csvPrinter.print("Rounds"); for (int round = 1; round <= numRounds; round++) { @@ -404,10 +406,10 @@ private void generateSummaryCsv( } csvPrinter.println(); - csvPrinter.print(resultTypeAndSlice.isSlice ? "Eliminated*" : "Eliminated"); + csvPrinter.print(outputFileIdentifiers.isSlice ? "Eliminated*" : "Eliminated"); printActionSummary(csvPrinter, roundToEliminatedCandidates); - csvPrinter.print(resultTypeAndSlice.isSlice ? "Elected*" : "Elected"); + csvPrinter.print(outputFileIdentifiers.isSlice ? "Elected*" : "Elected"); printActionSummary(csvPrinter, roundToWinningCandidates); // For each candidate: for each round: output total votes @@ -463,7 +465,7 @@ private void generateSummaryCsv( } csvPrinter.println(); - if (!resultTypeAndSlice.isSlice) { + if (!outputFileIdentifiers.isSlice) { csvPrinter.print("Current Round Threshold"); for (int round = 1; round <= numRounds; round++) { csvPrinter.print(roundTallies.get(round).getWinningThreshold()); @@ -473,7 +475,7 @@ private void generateSummaryCsv( csvPrinter.println(); } - if (resultTypeAndSlice.resultType == ResultType.DETAILED_CSV) { + if (outputFileIdentifiers.outputType == OutputType.DETAILED_CSV) { for (StatusForRound status : STATUSES_TO_PRINT) { csvPrinter.print(status.getTitleCaseKey()); @@ -525,7 +527,7 @@ private void generateSummaryCsv( // whether the value in the final round is positive. // Note that this concept only makes sense when we're reporting the overall tabulation, so we // omit it when generating results at the individual by-slice level. - if (!resultTypeAndSlice.isSlice && roundToResidualSurplus.get(numRounds).signum() == 1) { + if (!outputFileIdentifiers.isSlice && roundToResidualSurplus.get(numRounds).signum() == 1) { csvPrinter.print("Residual surplus"); for (int round = 1; round <= numRounds; round++) { csvPrinter.print(roundToResidualSurplus.get(round)); @@ -552,11 +554,11 @@ private void generateSummaryCsv( csvPrinter.println(); } - if (resultTypeAndSlice.isSlice) { + if (outputFileIdentifiers.isSlice) { csvPrinter.println(); csvPrinter.print(String.format("*Elect/Eliminate decisions are from the full contest. " + "All other results on this report are at the %s level.", - resultTypeAndSlice.slice.toLowerString())); + outputFileIdentifiers.slice.toLowerString())); csvPrinter.println(); } @@ -652,16 +654,16 @@ private void addContestInformationRows(CSVPrinter csvPrinter, } // creates a summary spreadsheet and JSON for the full contest (as opposed to a specific slice) - void generateOverallSummaryFiles( + void generateContestResultFiles( RoundTallies roundTallies, TallyTransfers tallyTransfers, List candidateOrder) throws IOException { - generateSummaryCsv(roundTallies, candidateOrder, - new ResultTypeAndSlice(ResultType.SUMMARY_CSV)); - generateSummaryCsv(roundTallies, candidateOrder, - new ResultTypeAndSlice(ResultType.DETAILED_CSV)); - generateSummaryJson(roundTallies, tallyTransfers, - new ResultTypeAndSlice(ResultType.DETAILED_JSON)); + generateResultsCsv(roundTallies, candidateOrder, + new OutputFileIdentifiers(OutputType.SUMMARY_CSV)); + generateResultsCsv(roundTallies, candidateOrder, + new OutputFileIdentifiers(OutputType.DETAILED_CSV)); + generateResultsJson(roundTallies, tallyTransfers, + new OutputFileIdentifiers(OutputType.DETAILED_JSON)); } // Write CastVoteRecords for the specified contest to the provided folder, @@ -678,8 +680,8 @@ String writeRcTabCvrCsv( // Put the input filename in the output filename in case contestId isn't unique -- // knowing that it's possible that if both the filename AND the contestId isn't unique, // this will fail. - ResultTypeAndSlice resultTypeAndSlice = new ResultTypeAndSlice(ResultType.RCTAB_CVR); - AuditableFile auditableFile = createAuditableFile(resultTypeAndSlice); + OutputFileIdentifiers outputFileIdentifiers = new OutputFileIdentifiers(OutputType.RCTAB_CVR); + AuditableFile auditableFile = createAuditableFile(outputFileIdentifiers); try { Logger.info("Writing cast vote records in generic format to file: %s...", auditableFile.getAbsolutePath()); @@ -798,8 +800,8 @@ void generateCdfJson(List castVoteRecords) // generate GpUnitIds for precincts "geopolitical units" (can be a precinct or jurisdiction) gpUnitIds = generateGpUnitIds(); - ResultTypeAndSlice resultTypeAndSlice = new ResultTypeAndSlice(ResultType.CDF_CVR); - AuditableFile auditableFile = createAuditableFile(resultTypeAndSlice); + OutputFileIdentifiers outputFileIdentifiers = new OutputFileIdentifiers(OutputType.CDF_CVR); + AuditableFile auditableFile = createAuditableFile(outputFileIdentifiers); Logger.info("Generating cast vote record CDF JSON file: %s...", auditableFile.getAbsolutePath()); @@ -1032,12 +1034,12 @@ private Map generateCdfMapForElection() { } // create summary json data for use with external visualizer software, unit tests and other tools - private void generateSummaryJson( + private void generateResultsJson( RoundTallies roundTallies, TallyTransfers tallyTransfers, - ResultTypeAndSlice resultTypeAndSlice) + OutputFileIdentifiers outputFileIdentifiers) throws IOException { - AuditableFile jsonFile = createAuditableFile(resultTypeAndSlice); + AuditableFile jsonFile = createAuditableFile(outputFileIdentifiers); Logger.info("Generating summary JSON file: %s...", jsonFile.getAbsolutePath()); // config will contain contest configuration info @@ -1047,8 +1049,8 @@ private void generateSummaryJson( configData.put("jurisdiction", config.getContestJurisdiction()); configData.put("office", config.getContestOffice()); configData.put("date", config.getContestDate()); - if (resultTypeAndSlice.isSlice) { - configData.put(resultTypeAndSlice.slice.toLowerString(), resultTypeAndSlice.sliceId); + if (outputFileIdentifiers.isSlice) { + configData.put(outputFileIdentifiers.slice.toLowerString(), outputFileIdentifiers.sliceId); } BigDecimal numNoRankings = diff --git a/src/main/java/network/brightspots/rcv/StreamingCvrReader.java b/src/main/java/network/brightspots/rcv/StreamingCvrReader.java index 2e6443f5b..8bf1ffa89 100644 --- a/src/main/java/network/brightspots/rcv/StreamingCvrReader.java +++ b/src/main/java/network/brightspots/rcv/StreamingCvrReader.java @@ -181,7 +181,7 @@ private void endCvr() { handleEmptyCells(config.getMaxRankingsAllowedWhenNotSetToMaximum() + 1); } String computedCastVoteRecordId = - String.format("%s-%d", ResultsWriter.sanitizeStringForOutput(excelFileName), cvrIndex); + String.format("%s-%d", OutputWriter.sanitizeStringForOutput(excelFileName), cvrIndex); // add precinct ID if needed if (precinctColumnIndex != null) { diff --git a/src/main/java/network/brightspots/rcv/Tabulator.java b/src/main/java/network/brightspots/rcv/Tabulator.java index 0f44f5834..1f16c76b3 100644 --- a/src/main/java/network/brightspots/rcv/Tabulator.java +++ b/src/main/java/network/brightspots/rcv/Tabulator.java @@ -40,7 +40,7 @@ import javafx.util.Pair; import network.brightspots.rcv.CastVoteRecord.VoteOutcomeType; import network.brightspots.rcv.ContestConfig.TabulateBySlice; -import network.brightspots.rcv.ResultsWriter.RoundSnapshotDataMissingException; +import network.brightspots.rcv.OutputWriter.RoundSnapshotDataMissingException; final class Tabulator { @@ -794,8 +794,8 @@ private List doRegularElimination( // to generate the results spreadsheets // param: timestamp string to use when creating output filenames void generateSummaryFiles(String timestamp) throws IOException { - ResultsWriter writer = - new ResultsWriter() + OutputWriter writer = + new OutputWriter() .setNumRounds(currentRound) .setCandidatesToRoundEliminated(candidateToRoundEliminated) .setWinnerToRound(winnerToRound) @@ -805,8 +805,8 @@ void generateSummaryFiles(String timestamp) throws IOException { .setRoundToResidualSurplus(roundToResidualSurplus); List candidateOrder = roundTallies.get(1).getSortedCandidatesByTally(); - writer.generateOverallSummaryFiles(roundTallies, tallyTransfers, candidateOrder); - writer.generateBySliceSummaryFiles(roundTalliesBySlices, tallyTransfersBySlice, candidateOrder); + writer.generateContestResultFiles(roundTallies, tallyTransfers, candidateOrder); + writer.generateBySliceResultsFiles(roundTalliesBySlices, tallyTransfersBySlice, candidateOrder); if (config.isGenerateCdfJsonEnabled()) { try { diff --git a/src/main/java/network/brightspots/rcv/TabulatorSession.java b/src/main/java/network/brightspots/rcv/TabulatorSession.java index 037c4efd4..86bd362ff 100644 --- a/src/main/java/network/brightspots/rcv/TabulatorSession.java +++ b/src/main/java/network/brightspots/rcv/TabulatorSession.java @@ -38,7 +38,7 @@ import network.brightspots.rcv.ContestConfig.Provider; import network.brightspots.rcv.ContestConfig.UnrecognizedProviderException; import network.brightspots.rcv.FileUtils.UnableToCreateDirectoryException; -import network.brightspots.rcv.ResultsWriter.RoundSnapshotDataMissingException; +import network.brightspots.rcv.OutputWriter.RoundSnapshotDataMissingException; import network.brightspots.rcv.Tabulator.TabulationAbortedException; @SuppressWarnings("RedundantSuppression") @@ -115,8 +115,8 @@ boolean convertToCdf(BiConsumer progressUpdate) { } else { Tabulator.SliceIdSet sliceIds = new Tabulator(castVoteRecords.getCvrs(), config).getEnabledSliceIds(); - ResultsWriter writer = - new ResultsWriter() + OutputWriter writer = + new OutputWriter() .setNumRounds(0) .setSliceIds(sliceIds) .setContestConfig(config) @@ -338,7 +338,7 @@ private LoadedCvrData parseCastVoteRecords( boolean encounteredSourceProblem = false; // Per-source data for writing generic CSV - List cvrSourceData = new ArrayList<>(); + List cvrSourceData = new ArrayList<>(); // At each iteration of the following loop, we add records from another source file. for (int sourceIndex = 0; sourceIndex < config.rawConfig.cvrFileSources.size(); ++sourceIndex) { @@ -353,7 +353,7 @@ private LoadedCvrData parseCastVoteRecords( // Update the per-source data for the results writer cvrSourceData.add( - new ResultsWriter.CvrSourceData( + new OutputWriter.CvrSourceData( source, reader, sourceIndex, startIndex, castVoteRecords.size() - 1)); // Check for unrecognized candidates @@ -416,8 +416,8 @@ private LoadedCvrData parseCastVoteRecords( // Output the RCTab-CSV CVR if (shouldOutputRcTabCvr) { try { - ResultsWriter writer = - new ResultsWriter().setContestConfig(config).setTimestampString(timestampString); + OutputWriter writer = + new OutputWriter().setContestConfig(config).setTimestampString(timestampString); this.rctabCvrFilePath = writer.writeRcTabCvrCsv( castVoteRecords, @@ -461,11 +461,11 @@ public static class LoadedCvrData { private List cvrs; private final int numCvrs; - private final List cvrSourcesData; + private final List cvrSourcesData; private boolean isDiscarded; private final boolean doesMatchAllMetadata; - LoadedCvrData(List cvrs, List cvrSourcesData) { + LoadedCvrData(List cvrs, List cvrSourcesData) { this.cvrs = cvrs; this.successfullyReadAll = cvrs != null; this.numCvrs = cvrs != null ? cvrs.size() : 0; @@ -504,7 +504,7 @@ public int numCvrs() { return numCvrs; } - List getCvrSourcesData() { + List getCvrSourcesData() { return cvrSourcesData; } @@ -522,7 +522,7 @@ List getCvrs() { public void printSummary() { Logger.info("Cast Vote Record summary:"); - for (ResultsWriter.CvrSourceData sourceData : cvrSourcesData) { + for (OutputWriter.CvrSourceData sourceData : cvrSourcesData) { Logger.info("Source %d: %s", sourceData.sourceIndex + 1, sourceData.source.getFilePath()); Logger.info(" uses provider: %s", sourceData.source.getProvider()); Logger.info(" read %d cast vote records", sourceData.getNumCvrs()); diff --git a/src/test/java/network/brightspots/rcv/TabulatorTests.java b/src/test/java/network/brightspots/rcv/TabulatorTests.java index 3d2c72883..9dff21b5c 100644 --- a/src/test/java/network/brightspots/rcv/TabulatorTests.java +++ b/src/test/java/network/brightspots/rcv/TabulatorTests.java @@ -39,8 +39,8 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import network.brightspots.rcv.ResultsWriter.ResultTypeAndSlice; -import network.brightspots.rcv.ResultsWriter.ResultType; +import network.brightspots.rcv.OutputWriter.OutputFileIdentifiers; +import network.brightspots.rcv.OutputWriter.OutputType; import network.brightspots.rcv.Tabulator.TabulationAbortedException; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.DisplayName; @@ -241,12 +241,12 @@ private static void runTabulationTest(String stem, String expectedException, int numSlicedFilesChecked = 0; for (ContestConfig.TabulateBySlice slice : config.enabledSlices()) { for (String sliceName : session.loadSliceNamesFromCvrs(slice, config)) { - ResultsWriter.ResultTypeAndSlice resultTypeAndSliceJson = new ResultTypeAndSlice(ResultType.DETAILED_JSON, slice, sliceName); - ResultsWriter.ResultTypeAndSlice resultTypeAndSliceCsv = new ResultsWriter.ResultTypeAndSlice(ResultType.DETAILED_CSV, slice, sliceName); - if (compareFiles(config, stem, resultTypeAndSliceJson, timestampString, null, true)) { + OutputFileIdentifiers outputFileIdentifiersJson = new OutputFileIdentifiers(OutputType.DETAILED_JSON, slice, sliceName); + OutputFileIdentifiers outputFileIdentifiersCsv = new OutputFileIdentifiers(OutputType.DETAILED_CSV, slice, sliceName); + if (compareFiles(config, stem, outputFileIdentifiersJson, timestampString, null, true)) { numSlicedFilesChecked++; } - if (compareFiles(config, stem, resultTypeAndSliceCsv, timestampString, null, true)) { + if (compareFiles(config, stem, outputFileIdentifiersCsv, timestampString, null, true)) { numSlicedFilesChecked++; } } @@ -265,7 +265,7 @@ private static void runConvertToCdfTest(String stem) { String timestampString = session.getTimestampString(); ContestConfig config = ContestConfig.loadContestConfig(configPath); - compareFiles(config, stem, ResultType.CDF_CVR, timestampString, null, false); + compareFiles(config, stem, OutputType.CDF_CVR, timestampString, null, false); cleanOutputFolder(session); } @@ -329,11 +329,11 @@ private static void cleanOutputFolder(TabulatorSession session) { private static void compareFiles( ContestConfig config, String stem, String timestampString, Integer sequentialId) { - compareFiles(config, stem, ResultType.DETAILED_JSON, timestampString, sequentialId, false); - compareFiles(config, stem, ResultType.DETAILED_CSV, timestampString, sequentialId, false); + compareFiles(config, stem, OutputType.DETAILED_JSON, timestampString, sequentialId, false); + compareFiles(config, stem, OutputType.DETAILED_CSV, timestampString, sequentialId, false); compareExtendedSummaryToSummary(config, timestampString, sequentialId); if (config.isGenerateCdfJsonEnabled()) { - compareFiles(config, stem, ResultType.CDF_CVR, timestampString, sequentialId, false); + compareFiles(config, stem, OutputType.CDF_CVR, timestampString, sequentialId, false); } } @@ -343,15 +343,15 @@ private static void compareFiles( private static boolean compareFiles( ContestConfig config, String stem, - ResultType resultType, + OutputType outputType, String timestampString, Integer sequentialId, boolean onlyCheckIfExpectedFileExists) { - ResultsWriter.ResultTypeAndSlice actualResultTypeAndSlice = new ResultTypeAndSlice(resultType); + OutputFileIdentifiers actualOutputFileIdentifiers = new OutputFileIdentifiers(outputType); return compareFiles( config, stem, - actualResultTypeAndSlice, + actualOutputFileIdentifiers, timestampString, sequentialId, onlyCheckIfExpectedFileExists); @@ -364,13 +364,13 @@ private static boolean compareFiles( private static boolean compareFiles( ContestConfig config, String stem, - ResultsWriter.ResultTypeAndSlice actualResultTypeAndSlice, + OutputFileIdentifiers actualOutputFileIdentifiers, String timestampString, Integer sequentialId, boolean onlyCheckIfExpectedFileExists) { - String actualOutputPath = actualResultTypeAndSlice.getPath( + String actualOutputPath = actualOutputFileIdentifiers.getPath( config.getOutputDirectory(), timestampString, sequentialId).toAbsolutePath().toString(); - String expectedPath = actualResultTypeAndSlice.getPath(getTestDirectory(stem).toString(), + String expectedPath = actualOutputFileIdentifiers.getPath(getTestDirectory(stem).toString(), stem, "expected", sequentialId).toString(); Logger.info("Comparing files:\nGenerated: %s\nReference: %s", actualOutputPath, expectedPath); @@ -395,9 +395,9 @@ private static boolean compareFiles( private static void compareExtendedSummaryToSummary( ContestConfig config, String timestampString, Integer sequentialId) { String dir = config.getOutputDirectory(); - String summaryPath = new ResultTypeAndSlice(ResultType.SUMMARY_CSV).getPath( + String summaryPath = new OutputFileIdentifiers(OutputType.SUMMARY_CSV).getPath( dir, timestampString, sequentialId).toAbsolutePath().toString(); - String detailedPath = new ResultsWriter.ResultTypeAndSlice(ResultType.DETAILED_CSV).getPath( + String detailedPath = new OutputFileIdentifiers(OutputType.DETAILED_CSV).getPath( dir, timestampString, sequentialId).toAbsolutePath().toString(); try (BufferedReader brSummary = new BufferedReader(new FileReader(summaryPath, UTF_8)); From 26db4231ff1b00a5595a95bb5d650f26054a2f59 Mon Sep 17 00:00:00 2001 From: yezr <8996546+yezr@users.noreply.github.com> Date: Thu, 24 Oct 2024 14:44:37 -0400 Subject: [PATCH 14/17] fix comment --- src/main/java/network/brightspots/rcv/OutputWriter.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/network/brightspots/rcv/OutputWriter.java b/src/main/java/network/brightspots/rcv/OutputWriter.java index 2f9b218c5..59a913fd5 100644 --- a/src/main/java/network/brightspots/rcv/OutputWriter.java +++ b/src/main/java/network/brightspots/rcv/OutputWriter.java @@ -360,7 +360,7 @@ private AuditableFile createAuditableFile(OutputFileIdentifiers outputFileIdenti // create a results .csv file // param: roundTallies is the round-by-count count of votes per candidate // param: candidateOrder is to allow a consistent ordering of candidates, including across slices - // param: resultTypeAndSlice must only have type DETAILED_CSV or SUMMARY_CSV + // param: outputFileIdentifiers must only have type DETAILED_CSV or SUMMARY_CSV private void generateResultsCsv( RoundTallies roundTallies, List candidateOrder, From 33bd30946f101c1894f903b3feb20efc463fa5ca Mon Sep 17 00:00:00 2001 From: Armin Samii Date: Tue, 29 Oct 2024 11:54:57 -0400 Subject: [PATCH 15/17] PR comments addressed and tests fixed --- .../network/brightspots/rcv/OutputWriter.java | 57 ++++++++++--------- .../brightspots/rcv/TabulatorTests.java | 6 +- 2 files changed, 33 insertions(+), 30 deletions(-) diff --git a/src/main/java/network/brightspots/rcv/OutputWriter.java b/src/main/java/network/brightspots/rcv/OutputWriter.java index 59a913fd5..b9168661f 100644 --- a/src/main/java/network/brightspots/rcv/OutputWriter.java +++ b/src/main/java/network/brightspots/rcv/OutputWriter.java @@ -114,7 +114,7 @@ public String getExtension() { } // Core traits of any output file - // Includes helpers for the work we need to do with the Identifiers to write the actual files themselves + // Includes helpers for the work we need to do with the Identifiers to write the actual files public static class OutputFileIdentifiers { // Since sanitizing Slice IDs can cause filename collisions, ensure each non-sanitized // Slice ID is given a unique sanitized name. @@ -123,32 +123,33 @@ public static class OutputFileIdentifiers { // in the resulting sanitized names. private static final HashSet uniqueSanitizedIds = new HashSet<>(); private final OutputType outputType; - private final boolean isSlice; private final TabulateBySlice slice; private final String sliceId; OutputFileIdentifiers(OutputType outputType) { this.outputType = outputType; - this.isSlice = false; slice = null; sliceId = null; } OutputFileIdentifiers(OutputType outputType, TabulateBySlice slice, String sliceId) { this.outputType = outputType; - this.isSlice = true; this.slice = slice; this.sliceId = sliceId; } + public boolean isSlice() { + return slice != null; + } + // getPath helper without the modifier argument public Path getPath(String directory, String prefix, Integer sequentialId) { return getPath(directory, prefix, null, sequentialId); } - // The filename is an underscore-separated string containing all components needed - // to create a unique output file. The modifier is likely only used in tests, where - // it is set to "expected" to distinguish expected output files from actual output files. + // The filename is an underscore-separated string containing all components needed to create a + // unique output file. At the time of writing this comment, the modifier is only used in tests, + // where it is set to "expected" to distinguish expected output files from actual output files. public Path getPath(String directory, String prefix, String modifier, Integer sequentialId) { List parts = new ArrayList<>(); parts.add(prefix); @@ -158,8 +159,7 @@ public Path getPath(String directory, String prefix, String modifier, Integer se if (modifier != null) { parts.add(modifier); } - if (isSlice) { - assert slice != null; + if (isSlice()) { parts.add(sanitizeSliceWithoutCollisions(sliceId)); parts.add(slice.toLowerString()); } @@ -337,13 +337,14 @@ void generateBySliceResultsFiles( for (var entry : roundTalliesBySlice.get(slice).entrySet()) { String sliceId = entry.getKey(); RoundTallies roundTallies = entry.getValue(); - TallyTransfers tallyTransfers = tallyTransfersBySlice.get(slice, sliceId); - OutputFileIdentifiers outputFileIdentifiersCsv = - new OutputFileIdentifiers(OutputType.DETAILED_CSV, slice, sliceId); - OutputFileIdentifiers outputFileIdentifiersJson = - new OutputFileIdentifiers(OutputType.DETAILED_JSON, slice, sliceId); - generateResultsCsv(roundTallies, candidateOrder, outputFileIdentifiersCsv); - generateResultsJson(roundTallies, tallyTransfers, outputFileIdentifiersJson); + generateCsvReport( + roundTallies, + candidateOrder, + new OutputFileIdentifiers(OutputType.DETAILED_CSV, slice, sliceId)); + generateJsonReport( + roundTallies, + tallyTransfersBySlice.get(slice, sliceId), + new OutputFileIdentifiers(OutputType.DETAILED_JSON, slice, sliceId)); } } } @@ -361,13 +362,13 @@ private AuditableFile createAuditableFile(OutputFileIdentifiers outputFileIdenti // param: roundTallies is the round-by-count count of votes per candidate // param: candidateOrder is to allow a consistent ordering of candidates, including across slices // param: outputFileIdentifiers must only have type DETAILED_CSV or SUMMARY_CSV - private void generateResultsCsv( + private void generateCsvReport( RoundTallies roundTallies, List candidateOrder, OutputFileIdentifiers outputFileIdentifiers) throws IOException { if (outputFileIdentifiers.outputType != OutputType.SUMMARY_CSV && outputFileIdentifiers.outputType != OutputType.DETAILED_CSV) { - throw new IllegalArgumentException("ResultFile provided non-CSV type " + throw new IllegalArgumentException("ResultFile provided non-CSV Report Type " + outputFileIdentifiers.outputType); } // Check that all candidates are included in the candidate order @@ -406,10 +407,10 @@ private void generateResultsCsv( } csvPrinter.println(); - csvPrinter.print(outputFileIdentifiers.isSlice ? "Eliminated*" : "Eliminated"); + csvPrinter.print(outputFileIdentifiers.isSlice() ? "Eliminated*" : "Eliminated"); printActionSummary(csvPrinter, roundToEliminatedCandidates); - csvPrinter.print(outputFileIdentifiers.isSlice ? "Elected*" : "Elected"); + csvPrinter.print(outputFileIdentifiers.isSlice() ? "Elected*" : "Elected"); printActionSummary(csvPrinter, roundToWinningCandidates); // For each candidate: for each round: output total votes @@ -465,7 +466,7 @@ private void generateResultsCsv( } csvPrinter.println(); - if (!outputFileIdentifiers.isSlice) { + if (!outputFileIdentifiers.isSlice()) { csvPrinter.print("Current Round Threshold"); for (int round = 1; round <= numRounds; round++) { csvPrinter.print(roundTallies.get(round).getWinningThreshold()); @@ -527,7 +528,7 @@ private void generateResultsCsv( // whether the value in the final round is positive. // Note that this concept only makes sense when we're reporting the overall tabulation, so we // omit it when generating results at the individual by-slice level. - if (!outputFileIdentifiers.isSlice && roundToResidualSurplus.get(numRounds).signum() == 1) { + if (!outputFileIdentifiers.isSlice() && roundToResidualSurplus.get(numRounds).signum() == 1) { csvPrinter.print("Residual surplus"); for (int round = 1; round <= numRounds; round++) { csvPrinter.print(roundToResidualSurplus.get(round)); @@ -554,7 +555,7 @@ private void generateResultsCsv( csvPrinter.println(); } - if (outputFileIdentifiers.isSlice) { + if (outputFileIdentifiers.isSlice()) { csvPrinter.println(); csvPrinter.print(String.format("*Elect/Eliminate decisions are from the full contest. " + "All other results on this report are at the %s level.", @@ -658,11 +659,11 @@ void generateContestResultFiles( RoundTallies roundTallies, TallyTransfers tallyTransfers, List candidateOrder) throws IOException { - generateResultsCsv(roundTallies, candidateOrder, + generateCsvReport(roundTallies, candidateOrder, new OutputFileIdentifiers(OutputType.SUMMARY_CSV)); - generateResultsCsv(roundTallies, candidateOrder, + generateCsvReport(roundTallies, candidateOrder, new OutputFileIdentifiers(OutputType.DETAILED_CSV)); - generateResultsJson(roundTallies, tallyTransfers, + generateJsonReport(roundTallies, tallyTransfers, new OutputFileIdentifiers(OutputType.DETAILED_JSON)); } @@ -1034,7 +1035,7 @@ private Map generateCdfMapForElection() { } // create summary json data for use with external visualizer software, unit tests and other tools - private void generateResultsJson( + private void generateJsonReport( RoundTallies roundTallies, TallyTransfers tallyTransfers, OutputFileIdentifiers outputFileIdentifiers) @@ -1049,7 +1050,7 @@ private void generateResultsJson( configData.put("jurisdiction", config.getContestJurisdiction()); configData.put("office", config.getContestOffice()); configData.put("date", config.getContestDate()); - if (outputFileIdentifiers.isSlice) { + if (outputFileIdentifiers.isSlice()) { configData.put(outputFileIdentifiers.slice.toLowerString(), outputFileIdentifiers.sliceId); } diff --git a/src/test/java/network/brightspots/rcv/TabulatorTests.java b/src/test/java/network/brightspots/rcv/TabulatorTests.java index 9dff21b5c..f00a02568 100644 --- a/src/test/java/network/brightspots/rcv/TabulatorTests.java +++ b/src/test/java/network/brightspots/rcv/TabulatorTests.java @@ -241,8 +241,10 @@ private static void runTabulationTest(String stem, String expectedException, int numSlicedFilesChecked = 0; for (ContestConfig.TabulateBySlice slice : config.enabledSlices()) { for (String sliceName : session.loadSliceNamesFromCvrs(slice, config)) { - OutputFileIdentifiers outputFileIdentifiersJson = new OutputFileIdentifiers(OutputType.DETAILED_JSON, slice, sliceName); - OutputFileIdentifiers outputFileIdentifiersCsv = new OutputFileIdentifiers(OutputType.DETAILED_CSV, slice, sliceName); + OutputFileIdentifiers outputFileIdentifiersJson = new OutputFileIdentifiers( + OutputType.DETAILED_JSON, slice, sliceName); + OutputFileIdentifiers outputFileIdentifiersCsv = new OutputFileIdentifiers( + OutputType.DETAILED_CSV, slice, sliceName); if (compareFiles(config, stem, outputFileIdentifiersJson, timestampString, null, true)) { numSlicedFilesChecked++; } From 634b58574735e8aa158d2b485d89580cb035e1d4 Mon Sep 17 00:00:00 2001 From: yezr <8996546+yezr@users.noreply.github.com> Date: Wed, 30 Oct 2024 18:00:29 -0400 Subject: [PATCH 16/17] add warning message for sanitized slice filename collision --- src/main/java/network/brightspots/rcv/OutputWriter.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/java/network/brightspots/rcv/OutputWriter.java b/src/main/java/network/brightspots/rcv/OutputWriter.java index b9168661f..dcf4840fc 100644 --- a/src/main/java/network/brightspots/rcv/OutputWriter.java +++ b/src/main/java/network/brightspots/rcv/OutputWriter.java @@ -178,12 +178,14 @@ private String sanitizeSliceWithoutCollisions(String sliceId) { } else { sanitizedSliceId = sanitizeStringForOutput(sliceId); - // In most cases, sanitizedSliceId will be unique and we can use it as-is. + // In most cases, sanitizedSliceId will be unique, and we can use it as-is. // Here, we handle the case where it is not unique. int increment = 1; while (uniqueSanitizedIds.contains(sanitizedSliceId)) { sanitizedSliceId = String.format("%s_%d", sanitizeStringForOutput(sliceId), increment); increment++; + Logger.warning("The sanitized filename for Precinct %s results is not unique" + + " and has been renamed to %s", sliceId, sanitizedSliceId); } uniqueSanitizedIds.add(sanitizedSliceId); From 24ff1f63e8d3dd98e6dae34fc4833e310eb87cb0 Mon Sep 17 00:00:00 2001 From: Armin Samii Date: Mon, 4 Nov 2024 11:13:23 -0500 Subject: [PATCH 17/17] fix logging message location --- src/main/java/network/brightspots/rcv/OutputWriter.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/main/java/network/brightspots/rcv/OutputWriter.java b/src/main/java/network/brightspots/rcv/OutputWriter.java index dcf4840fc..46676f16f 100644 --- a/src/main/java/network/brightspots/rcv/OutputWriter.java +++ b/src/main/java/network/brightspots/rcv/OutputWriter.java @@ -184,6 +184,9 @@ private String sanitizeSliceWithoutCollisions(String sliceId) { while (uniqueSanitizedIds.contains(sanitizedSliceId)) { sanitizedSliceId = String.format("%s_%d", sanitizeStringForOutput(sliceId), increment); increment++; + } + + if (increment > 1) { Logger.warning("The sanitized filename for Precinct %s results is not unique" + " and has been renamed to %s", sliceId, sanitizedSliceId); }