RCTab v1.3.2 Section 25 - Configuration File Parameters v.1.1.1
RCTab v1.3.2 Section 25 - Configuration File Parameters v.1.1.1 document is solely for use in the State of California. This document can be expanded or updated as is necessary or required. Where relevant, this document refers to specific sections and requirements of the California Voting System Standards. Any recommendations listed in this document should not supersede user jurisdiction procedures or other controlling governance entities.
This document lists the parameters the user will configure within RCTab. The output is the JSON file used for tabulation.
The Config file must be a valid JSON format. Example config files can be found under the test folder. The values a user inputs into any of these fields depend upon the relevant laws and regulations in place in their jurisdiction, as well as the voting system vendor used to produce cast-vote records for their elections. Users must understand the requirements of their laws, regulations, and vendor CVR data in order to fill out these fields successfully.
This document lists the parameters that can be included in a config file suitable for input tabulation. Parameters are categorized by required and optional. If a user fails to fill out a required parameter when building a configuration file, RCTab will alert the user to the missing requirement and provide suggested resolution steps.
Config file must be valid JSON format. Examples can be found in the test_data folder.
-
"tabulatorVersion" required
-
version of the application that created this file
-
used for migrating config data between different application versions
-
example: "1.0.1"
-
value: text string of length [1..1000]
-
"outputSettings" required
A list of output settings and their associated parameters
The "outputSettings" section contains the following parameters:
-
"contestName" required
-
The name of the contest
-
Used for naming audit output files
-
Example: "Portland Mayoral Race 2017"
-
Value: text string of length [1..255]
-
-
The "outputDirectory" optional
-
Directory for audit output files (absolute or relative path)
-
Example: /Path/To/TabulatorResults
-
Example: output data/contest1
-
Value: string of length [1..255]
-
If not supplied: files will be saved to the current working directory
-
-
The "contestDate" optional
-
Date of the contest
-
Example: "2015-11-03"
-
Value: text string of length [1..1000]
-
If not supplied: none
-
-
The "contestJurisdiction" optional
-
Text description of the jurisdiction of this contest
-
Example: "Portland, ME"
-
Value: text string of length [1..1000]
-
If not supplied: none
-
-
"contestOffice" optional
-
text description of the office being contested
-
Example: "Mayor"
-
Value: text string of length [1..1000]
-
If not supplied: none
"cvrFileSources" required
List of input CVR file paths and their associated parameters. Multiple CVRs can be input in a single configuration file.
Each "cvrFileSources" list item contains the following parameters:
-
"provider" required
-
text description of the vendor / machine which generated this file
-
value: "cdf" | "clearBallot" | "dominion" | "ess" | "hart"
-
-
"filePath" required
-
location of the CVR file (in the case of CDF, Clear Ballot, and ES&S), or the CVR folder (in the case of Dominion and Hart)
-
example: /Users/test_data/2015-portland-mayor-cvr.xlsx
-
value: string of length [1..255]
-
-
"contestId" required when CVR source files are from a provider other than ES&S must be blank for ES&S
-
the ID of the contest to tabulate, as represented in the CVR file(s)
-
example: "b651b997-417a-46d9-a676-a43d4df94ddc"
-
value: text string of length [1..1000]
-
-
"firstVoteColumnIndex" required and used if and only if the provider is ES&S
-
index of the column (starting from 1) that contains the top-ranked candidate for each CVR
-
example: 3
-
value: [1..1000]
-
-
"firstVoteRowIndex" required and used if and only if the provider is ES&S
-
index of the row (starting from 1) that contains the rankings for the first CVR
-
example: 2
-
value: [1..100000]
-
-
"idColumnIndex" optional and can be used only if the provider is ES&S
-
index of the column (starting from 1) that contains the unique ID for each CVR
-
example: 1
-
value: [1..1000]
-
-
"precinctColumnIndex" required and used if and only if "tabulateByPrecinct" is enabled and the provider is ES&S
-
index of the column (starting from 1) that contains the precinct name for each CVR
-
example: 2
-
value: [1..1000]
-
-
"overvoteLabel" optional and can be used only if the provider is ES&S or CDF
-
label used in the CVR to denote an overvote; if this parameter is present overvoteRule must be either "alwaysSkipToNextRank" or "exhaustImmediately" (because the other option, "exhaustIfMultipleContinuing", relies on knowing which specific candidates were involved in each overvote)
-
example: "OVERVOTE"
-
value: string of length [1..1000]
-
-
"undervoteLabel" optional and can be used only if the provider is ES&S
-
the special label used in the cast vote records to denote an undervote
-
example: "UNDERVOTE"
-
value: string of length [1..1000]
-
-
"undeclaredWriteInLabel" optional
-
the special label used in the cast vote records to denote a vote for an undeclared write-in
-
example: "UWI"
-
value: string of length [1..1000]
-
-
"treatBlankAsUndeclaredWriteIn" optional and can be used only if the provider is ES&S
-
tabulator will interpret a blank cell in a CVR as a vote for an undeclared write-in
-
value: true | false
-
if not supplied: false
-
"candidates" required
List of registered candidate names and associated candidate code (note: leave empty when CVR is in Common Data Format)
Each "candidates" list item has the following parameters:
-
"name" required
-
Full name of the registered candidate
-
Example: "Duson, Jill C."
-
Value: string of length [1..1000]
-
-
"code" optional
-
Candidate code which may appear in CVRs in lieu of full candidate name
-
Example: "JCD"
-
Value: string of length [1..1000]
-
If not supplied: none
-
-
"excluded" optional
-
Candidate should be ignored during tabulation
-
Value: true | false
-
If not supplied: false
-
"rules" required
Set of configuration parameters that specify the tabulation rules
The "rules" section contains the following parameters:
-
"tiebreakMode" required
-
how the program should decide which candidate to eliminate when multiple candidates are tied for last place
-
or which candidate to elect first when:
-
1) electionWinnerMode is set to multiWinnerAllowOnlyOneWinnerPerRound, and
-
2) multiple candidates exceed the winning threshold in the same round, and
-
3) at least two of those candidates are tied for the highest vote total in that round
-
-
value: "random" | "stopCountingAndAsk" | "previousRoundCountsThenRandom" | "previousRoundCountsThenAsk" | "useCandidateOrder" | "generatePermutation"
-
we use java.util.random for randomness in our tiebreak implementations
-
see: https://docs.oracle.com/en/java/javase/12/docs/api/java.base/java/util/Random.html
-
compatible methods exist for other languages, e.g. https://pypi.org/project/java-random/
-
-
on tabulation start a java.util.Random object is created if required using the randomSeed value specified in the input config file:
- Random random = new Random(config.getRandomSeed());
-
-
"Random"
-
during tabulation, in the event of a tie at the end of a round:
-
the list of tied candidates is sorted alphabetically
-
a randomDouble is generated using the random object:
-
double randomDouble = random.nextDouble();
-
the randomDouble is mapped to one of the tied candidates in the list:
-
int randomCandidateIndex = (int) Math.floor(randomDouble * (double) tiedCandidates.size());
-
the selected candidate will be the winner or loser for that round
-
-
-
"stopCountingAndAsk":
-
the user is presented with a list of tied candidates
-
the user will input their selection manually
-
-
"previousRoundCountsThenRandom"
-
the tied candidate with the highest vote total in the previous round is selected
-
if there is a tie for the vote count in the previous round as well, a candidate is selected from the still tying candidates as described under tiebreakMode "Random"
-
-
"previousRoundCountsThenAsk"
-
the tied candidate with the highest vote total in the previous round is selected
-
if there is a tie for the vote count in the previous round as well, a candidate is selected from the still tying candidates as described under tiebreakMode "Stop counting and ask"
-
-
"useCandidateOrder"
-
during tabulation, in the event of a tie at the end of a round the list of candidates from the config file is consulted
-
if selecting a winner the tied candidate in this round who appears earliest is selected as a winner
-
if selecting a loser the tied candidate who appears latest is selected as the loser.
-
-
"generatePermutation"
-
on config load candidate names are sorted alphabetically by candidate code, or if code is not present, candidate name
-
a randomly ordered candidate permutation is created using Collections.shuffle() with the randomSeed specified in the input config file
-
during tabulation, in the event of a tie at the end of a round, this permutation is consulted
-
if selecting a winner: the tied candidate in this round who appears earliest is selected
-
if selecting a loser: the tied candidate who appears latest is selected
-
-
-
"overvoteRule" required
-
how the program should handle an overvote when it encounters one
-
value: "alwaysSkipToNextRank" | "exhaustImmediately" | "exhaustIfMultipleContinuing"
-
“exhaustImmediately”
- "exhaustImmediately": exhaust a ballot as soon as we encounter an overvote
-
-
"winnerElectionMode" required
-
which process the program should apply for selecting the winner(s)
-
value: "singleWinnerMajority" | "multiWinnerAllowOnlyOneWinnerPerRound" | "multiWinnerAllowMultipleWinnersPerRound" | "bottomsUp" | "bottomsUpUsingPercentageThreshold" | "multiPassIrv"
-
If only “singleWinnerMajority” is in use.
-
"singleWinnerMajority": no special process (only valid when numberOfWinners = 1).
-
Election threshold = floor(V/(S+1)) + 1
-
where V = total number of votes (in the current round); and S = numberOfWinners
-
-
-
-
"numberOfWinners" required
-
the number of seats to be won in this contest
-
Uneditable if using “single-winner majority determines winner,” automatically set to 1. Uneditable if using “Bottoms-up using percentage threshold,” automatically set to 0.
-
note: we use fractional vote transfer to redistribute votes in “multiWinnerAllowOnlyOneWinnerPerRound” and “multiWinnerAllowMultipleWinnersPerRound” contests.
-
note: 0 is valid only when winnerElectionMode is set to "bottomsUpUsingPercentageThreshold"
-
value: [0..number of declared candidates]
-
-
"minimumVoteThreshold" optional
-
if a candidate receives fewer than this number of votes in the first round, they are automatically eliminated
-
example: 150
-
value: [0..1000000]
-
if not supplied: no automatic elimination occurs (equivalent to setting it to 0)
-
Note: If no candidate exceeds the minimum vote threshold, tabulation silently fails. If you are using the minimum vote threshold setting and are having issues getting results, check that you have not set the minimum vote threshold too high.
-
-
"maxSkippedRanksAllowed" required
-
maximum number of skipped ranks (undervotes) on a ballot before the ballot should be considered exhausted; if "unlimited" is entered, a ballot will never be considered exhausted due to skipped ranks
-
example: 1
-
value: [unlimited, 0..1000000]
-
-
"maxRankingsAllowed" required
-
maximum number of candidates that a ballot is allowed to rank; if "max" is entered, this will default to the total number of declared candidates as entered on the candidates tab
-
example: 15
-
values: [max, 1..1000000]
-
-
"rulesDescription" optional
-
text description of this rules configuration for organizing your config files -- not used by the tabulator
-
Example "Maine Rules"
-
value: string of length [1..1000]
-
-
"batchElimination" optional
-
Tabulator will use batch elimination (only valid for single-winner contests)
-
Value: true | false
-
If not supplied: false
-
-
"continueUntilTwoCandidatesRemain" optional
-
tabulator will keep tabulating (beyond winning round) until only two candidates remain (only valid for single-winner contests)
-
Value: true | false
-
If not supplied: false
-
-
"overvoteDelimiter" optional and can be used only if provider is ES&S must be blank when overvoteLabel is provided
-
string that will be used to split a cell into multiple candidate strings in the case of an overvote
-
example: //
-
value: any string that contains no backslashes and at least one character that is not a letter, number, hyphen, period, comma, apostrophe, quote, or space
-
-
"tabulateByPrecinct" optional
-
Tabulator will generate a results spreadsheet for each precinct
-
Value: true | false
-
If not supplied: false
-
-
"generateCdfJson" optional
-
Tabulator will generate a JSON of cast vote records in the Common Data Format
-
Value: true | false
-
If not supplied: false
-
"exhaustOnDuplicateCandidate" optional
-
Tabulator will exhaust a ballot when it encounters a duplicate candidate (instead of just skipping the duplicate)
-
Value: true | false
-
If not supplied: false
-
-
-
"nonIntegerWinningThreshold" optional
-
the vote threshold used to determine winners can be a non-integer
-
if true, threshold = V/(S+1) + 10^-d
-
if false, threshold = floor(V/(S+1)) + 1
-
where V = total number of votes (in the current round or in the first round, depending on the winnerElectionMode); S = numberOfWinners; and d = decimalPlacesForVoteArithmetic
-
(note that S+1 in the formulas above becomes just S if hareQuota is set to true.)
-
Only valid for “multiWinnerAllowOnlyOneWinnerPerRound” and “multiWinnerAllowMultipleWinnersPerRound” contests
-
value: true | false
-
if not supplied: false
-
-
"hareQuota*" optional
-
the winning threshold should be computed using the Hare quota* (floor(votes divided by seats)) instead of the preferred Droop quota (votes divided by (seats+1))
-
Only valid for “multiWinnerAllowOnlyOneWinnerPerRound” and “multiWinnerAllowMultipleWinnersPerRound” contests
-
Value: true | false
-
If not supplied: false
-
-
"randomSeed" required if tiebreakMode is "random", "previousRoundCountsThenRandom", or "generatePermutation"
-
the integer seed for the application's pseudorandom number generator
-
value: [-140737488355328..140737488355327]
-
-
"multiSeatBottomsUpPercentageThreshold" required if winnerElectionMode is "bottomsUpUsingPercentageThreshold" and numberOfWinners is 0
-
the percentage threshold used to determine when to stop the tabulation and declare winners
-
note: only valid when winnerElectionMode is "bottomsUpUsingPercentageThreshold" and numberOfWinners is 0
-
value: [1..100]
-
-
"decimalPlacesForVoteArithmetic" required
-
number of rounding decimal places when computing winning thresholds and fractional vote transfers
-
note: only editable when winnerElectionMode is "multiWinnerAllowOnlyOneWinnerPerRound" or "multiWinnerAllowMultipleWinnersPerRound"
-
value: [1..20]
-
-
"winnerElectionMode" required
-
which process the program should apply for selecting the winner(s)
-
value: "singleWinnerMajority" | "multiWinnerAllowOnlyOneWinnerPerRound" | "multiWinnerAllowMultipleWinnersPerRound" | "bottomsUp" | "bottomsUpUsingPercentageThreshold" | "multiPassIrv"
-
"multiWinnerAllowOnlyOneWinnerPerRound": elect no more than one winner per round, even when there are multiple candidates exceeding the winning threshold (only valid when numberOfWinners is > 1)
-
Election threshold = floor(V/(S+1)) + 1
-
where V = total number of votes (in the first round); and S = numberOfWinners
-
-
"multiWinnerAllowMultipleWinnersPerRound": may elect more than one winner per round when there are multiple candidates exceeding the winning threshold (only valid when numberOfWinners is > 1)
-
Election threshold = floor(V/(S+1)) + 1
-
where V = total number of votes (in the first round); and S = numberOfWinners
-
-
"bottomsUp": instead of running a standard multi-seat contest with single transferable votes, just eliminate candidates until there are numberOfWinners remaining (only valid when numberOfWinners is > 1)
-
Election threshold = floor(V/(S+1)) + 1
-
where V = total number of votes (in the first round); and S = numberOfWinners
-
bottomsUp does not rely on election threshold for any vote processing
-
-
"bottomsUpUsingPercentageThreshold": instead of running a standard multi-seat contest with single transferable votes, just eliminate candidates until all remaining candidates have vote shares that meet or exceed multiSeatBottomsUpPercentageThreshold (only valid when numberOfWinners is 0)
-
Election threshold = V•T
-
where V = total number of votes (in the current round); and T = multiSeatBottomsUpPercentageThreshold
-
-
"multiPassIrv": instead of running a true multi-seat contest, run a series of single-seat contests and progressively exclude candidates as they win seats (only valid when numberOfWinners is > 1).
-
Election threshold = floor(V/(2)) + 1
-
where V = total number of votes (in the current round)
-
-
-
“overvoteRule" required
-
how the program should handle an overvote when it encounters one
-
value: "alwaysSkipToNextRank" | "exhaustImmediately" | "exhaustIfMultipleContinuing"
-
"alwaysSkipToNextRank": when we encounter an overvote, ignore this rank and look at the next rank in the cast vote record
-
"exhaustIfMultipleContinuing": if more than one candidate in an overvote are continuing, exhaust the ballot; if only one, assign the vote to them; if none, continue to the next rank (not valid with an ES&S source unless overvoteDelimiter is supplied)
-
| Document Revision History | |||
|---|---|---|---|
| Date | Version | Description | Author |
| 04/28/2023 | 1.1.1 | Updated to reflect v.1.3.1 | Kelly Sechrist |
| 01/19/2022 | 1.1.0 | Revisions for clarity | Ryan Kirby |
| 04/21/2021 | 1.0.0 | Configuration File Parameters | Chris Hughes |