Document LoadData vote loading and migrate monitoring README to Markdown. Record v3 vote-results.json as the tally source of truth, warn on old-school txt/ini, and refuse v2 raw_board_votes.json. Point whatif and the STV tests at the same loaders. Co-authored-by: Grok <grok@x.ai>
diff --git a/README.md b/README.md index d831a35..7acf14a 100644 --- a/README.md +++ b/README.md
@@ -15,6 +15,42 @@ > this version. Read the [Getting Started Guide](v3/docs/quickstart.md) > to set up a development environment for v3. +## STV tally and what-if + +Meek STV lives in [`monitoring/stv_tool.py`](monitoring/stv_tool.py). +v3 tallies (`steve.vtypes.stv`) and the what-if CLI both call that module. + +**Load a vote file** with `LoadData.from_path` (a file, not a directory): + +| Input | Behavior | +|---|---| +| `vote-results.json` (v3 tally JSON) | Source of truth. No warning. | +| `raw_board_votes.txt` (+ sibling `board_nominations.ini`) | Old-school. Warns on stderr. | +| `raw_board_votes.json` (v2 export) | Not a tally format. Warns and exits. | + +``` +python3 monitoring/stv_tool.py path/to/vote-results.json +python3 monitoring/stv_tool.py -s 9 -v path/to/raw_board_votes.txt +``` + +**What-if scenarios** (seats, drop a candidate, runoff-only set) are +[`whatif.py`](whatif.py). The positional argv is fixed for `whatif.rb`: + +``` +python3 whatif.py [-v] VOTES_FILE [seats] [name ...] +python3 whatif.py VOTES_FILE -Lastname +``` + +Names may be first, last, or compacted full name (case-insensitive). +A leading `-` on a name removes that candidate; otherwise only the +named candidates run. Warnings for legacy files go to stderr so they +do not break `whatif.rb` grepping of `elected` lines. + +`whatif.rb` still consumes `raw_board_votes.txt`. Do not point it at +v2 JSON. Prefer `vote-results.json` for new tallies. + +See also [`monitoring/README.md`](monitoring/README.md). + ## Getting Started Getting Started documentation can be found at: http://steve.apache.org/demo.html
diff --git a/monitoring/README.md b/monitoring/README.md new file mode 100644 index 0000000..2dd0497 --- /dev/null +++ b/monitoring/README.md
@@ -0,0 +1,66 @@ +# Vote monitoring tools + +Helpers for processing closed-election tallies. + +When votes are closed, each monitor historically received an email: a +final list of votes with hash ID and timestamp, time-ordered so later +ballots sit at the bottom. + +## STV (`stv_tool.py`) + +Meek STV engine plus `LoadData` (load a **file**, not a directory). +v3 (`steve.vtypes.stv`) and `whatif.py` (repo root) call this module. + +``` +./stv_tool.py vote-results.json +./stv_tool.py -s 9 -v raw_board_votes.txt +``` + +| Input | Behavior | +|---|---| +| `vote-results.json` (v3 tally JSON) | Source of truth. `labelmap` + votestrings for the STV issue. | +| `raw_board_votes.txt` (+ sibling `board_nominations.ini`) | Old-school emailed format. Non-vote lines ignored; later vote per 32-char hash wins. Warns on stderr. | +| `raw_board_votes.json` (v2 export, labels like `AA`/`AB`) | Not a tally format. Warns and exits. Keep for posterity; pass txt or v3 JSON instead. | + +`whatif.py` runs seat / drop / runoff scenarios on the same loaders. +`whatif.rb` still wants txt+ini. + +## Other STV tools + +OpenSTV or the deprecated VoteMain systems. Most modern tools use BLT. + +Feed the STV-tally email and write an output file: + +``` +./nstv-rank.py raw_votes.txt > outputFile +``` + +After installing Voting Systems Toolbox: + +``` +java -cp Vote-0-4.jar VoteMain -system stv-meek -seats 9 outputFile +java -cp Quick_STV_1_2.jar VoteMain -system stv-meek -seats 9 outputFile +``` + +BLT-oriented tools such as OpenSTV: + +``` +./nstv-rank.py -b raw_votes.txt > outputFile.blt +``` + +ASF Meek STV settings: precision 6; threshold Droop | Dynamic | Fractional. + +## YNA + +`yna-summary.pl` tallies Yes / No / Abstain. You can concatenate all +final YNA tallies into one file; it pulls out each issue name and +result, honoring only the most recent vote per voter. + +``` +./yna-summary.pl all30tally.txt +``` + +## Voter checks + +`monitoring-check.pl` checks that incoming votes are from legitimate +voters.
diff --git a/monitoring/README.txt b/monitoring/README.txt deleted file mode 100644 index 74c79e9..0000000 --- a/monitoring/README.txt +++ /dev/null
@@ -1,67 +0,0 @@ -Included are some helpful tools/scripts to make the -vote monitor's job easier. - -When votes are closed, each monitor will get, via EMail, -a final tally (list) of all votes cast, with hash ID and -timestamp. The list is time-ordered as well, so the later- -cast ballots are closer to the bottom of the tally. - -For STV, we use voter/stv_tool.py to process the vote results: - - ./stv_tool.py raw_votes.txt - -where `raw_votes.txt` is the emailed set of votes. For example, -see Meetings/.../raw_board_votes.txt. Lines other than votes -are ignored, and the votes are assumed to be time-ordered to -ensure that only the latest vote by each voter is considered. - -We also support OpenSTV (www.openstv.org) or the deprecated VoteMain -(http://sourceforge.net/projects/votesystem) systems. Most modern -tools use the blt format. - -Simply feed as input the STV-tally email (typically used for the board -elections) and direct the output to 'outputFile' (or whatever -you'd like): - - ./nstv-rank.py raw_votes.txt > outputFile - -After installing Voting Systems Toolbox, you can execute the 'VoteMain' -program as - - java -cp Vote-0-4.jar VoteMain -system stv-meek -seats 9 outputFile - or - java -cp Quick_STV_1_2.jar VoteMain -system stv-meek -seats 9 outputFile - -where outputFile is the output of nstv-rank.py above. - -Using blt-oriented STV tools, such as OpenSTV: - - ./nstv-rank.py -b raw_votes.txt > outputFile.blt - -and load in the blt file to OpenSTV. Please note the ASF uses Meek STV with: - - Precision: 6 - Threshold: Droop | Dynamic | Fractional - ----- - -For simple YNA votes (Yes / No / Abstain), we have - - yna-summary.pl - -which does the checks for you. - -This script is smart enough that you can actually concat -*all* the final vote tallies for yna elections into one big -file, and it will pull out the issue name and the results -for each issue. - - ./yna-summary.pl all30tally.txt - -yna-summary.pl will only honor the most recent vote cast by each voter. - - ----- - -Also see monitoring-check.pl to ensure the incoming votes are from -legitimate voters.
diff --git a/v3/tests/README.md b/v3/tests/README.md index 059af96..51cb6e5 100644 --- a/v3/tests/README.md +++ b/v3/tests/README.md
@@ -27,8 +27,8 @@ ### Prerequisites -- Ensure the `stv_tool` module is available at `../../../monitoring/stv_tool.py` (relative to `v3/steve/vtypes/stv.py`). -- Provide a `Meetings` directory containing subdirectories (e.g., `yyyymmdd`) with the required input files: `raw_board_votes.txt` (raw vote data) and `board_nominations.ini` (label mappings for candidates). +- Ensure the `stv_tool` module is available at `../../../monitoring/stv_tool.py` (relative to `v3/steve/vtypes/stv.py`). Live tallies prefer v3 `vote-results.json` via `LoadData.from_path`. These regression tests still use historical `raw_board_votes.txt` so v3 continues to match pre-v3 Meek results (the loader will warn that txt is old-school). +- Provide a `Meetings` directory containing subdirectories (e.g., `yyyymmdd`) with `raw_board_votes.txt` and `board_nominations.ini`. ### Scripts @@ -43,9 +43,10 @@ ### Dependencies -- `raw_board_votes.txt`: Contains the raw vote data in each meeting subdirectory. -- `board_nominations.ini`: Contains the label mappings for candidates in each meeting subdirectory. +- `raw_board_votes.txt`: Historical raw vote data in each meeting subdirectory (legacy format; `read_votefile` takes only the filename). +- `board_nominations.ini`: Letter-to-name map for those txt files. +- Do not pass v2 `raw_board_votes.json` into `stv_tool`; it is not a tally format. ### Importing stv_tool -The `stv.py` module imports `stv_tool` from `../../../monitoring/stv_tool.py` using dynamic loading to ensure compatibility. +The `stv.py` module imports `stv_tool` from `../../../monitoring/stv_tool.py` using dynamic loading. Tally math is `run_stv`; file loading for new code is `LoadData.from_path`. See also [`monitoring/README.md`](../../monitoring/README.md).