-
Notifications
You must be signed in to change notification settings - Fork 19
/
config_file_documentation.txt
276 lines (226 loc) · 15.4 KB
/
config_file_documentation.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
This document lists the parameters that can be included in a config file suitable for input tabulation.
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
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 output files
example: "Portland Mayoral Race 2017"
value: text string of length [1..1000]
"outputDirectory" optional
directory for output files
if a relative path is supplied it will be appended to the current working directory
if an absolute path is supplied it will be used as is
example: /Path/To/TabulatorResults
example: output_data/contest1
value: string of length [1..1000]
if not supplied: files will be saved to the current working directory
"contestDate" optional
date of the contest
example: "2015-11-03"
value: text string of length [1..1000]
"contestJurisdiction" optional
text description of the jurisdiction of this contest
example: "Portland, ME"
value: text string of length [1..1000]
"contestOffice" optional
text description of the office being contested
example: "Mayor"
value: text string of length [1..1000]
"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
"cvrFileSources" required
list of input cast vote record (CVR) file paths and their associated parameters
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..1000]
"contestId" required when CVR source files are from a provider other than ES&S; must be blank otherwise
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 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 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 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 provider is ES&S
index of the column (starting from 1) that contains the precinct name for each CVR
example: 2
value: [1..1000]
"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
"overvoteLabel" optional and can be used only if 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 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 (i.e. a candidate who has not notified election officials that they're running for election); note that tabulator always eliminates undeclared write-ins first if present
example: "UWI"
value: string of length [1..1000]
"treatBlankAsUndeclaredWriteIn" optional and can be used only if 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 (including declared write-in candidates) and associated optional fields (note: leave this section 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]
"aliases" optional
aliases which may appear in CVRs in addition to candidate name
example: ["JCD"], or ["Jimmy", "Jim"]
value: list containing string(s) of length [1..1000]
"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 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"
"alwaysSkipToNextRank": when we encounter an overvote, ignore this rank and look at the next rank in the cast vote record
"exhaustImmediately": exhaust a ballot as soon as we encounter an overvote
"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)
"winnerElectionMode" required
whether the program should apply a special process for selecting the winner(s)
value: "singleWinnerMajority" | "multiWinnerAllowOnlyOneWinnerPerRound" | "multiWinnerAllowMultipleWinnersPerRound" | "bottomsUp" | "bottomsUpUsingPercentageThreshold" | "multiPassIrv"
"singleWinnerMajority": no special process (only valid when numberOfWinners = 1)
"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)
"multiWinnerAllowMultipleWinnersPerRound": may elect more than one winner per round when there are multiple candidates exceeding the winning threshold (only valid when numberOfWinners is > 1)
"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)
"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)
"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)
"numberOfWinners" required
the number of seats to be won in this contest
note: we use fractional vote transfer to redistribute votes in multi-seat contests
note: 0 is valid only when winnerElectionMode is set to "bottomsUpUsingPercentageThreshold"
value: [0..number of declared candidates]
"decimalPlacesForVoteArithmetic" required
number of rounding decimal places when computing winning thresholds and fractional vote transfers
note: only matters when winnerElectionMode is "multiWinnerAllowOnlyOneWinnerPerRound" or "multiWinnerAllowMultipleWinnersPerRound"
value: [1..20]
"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)
"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
example: 15
values: [max, 1..1000000]
"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]
"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]
"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 for single-seat or in the first round for multi-seat); S = numberOfWinners; and d = decimalPlacesForVoteArithmetic
(note that S+1 in the formulas above becomes just S if hareQuota is set to true)
note: only valid for multi-seat contests
value: true | false
if not supplied: false
"hareQuota" optional
the winning threshold should be computed using the Hare quota (votes divided by seats) instead of the preferred Droop quota (votes divided by (seats+1))
note: only valid for multi-seat contests
value: true | false
if not supplied: false
"batchElimination" optional
tabulator will use batch elimination
note: 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 when numberOfWinners is 1)
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