-
Notifications
You must be signed in to change notification settings - Fork 5
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
EDF to ballot data model extractor #112
Changes from all commits
f38ced9
88aa5bc
41e188c
25ff3cf
584bb41
43eb184
24b921f
9f0ab55
f1fd991
309db0e
f5090b8
55b5b38
a262592
4a27316
15efb15
4355de7
26deeaf
fb03e3f
1547160
78f933a
e658646
d48ddf7
4d1bfb4
8fd9337
6a88c50
929a4be
827b2c9
8d6d431
2bec0c1
05fac8f
67d3933
9921c2d
4e7283f
e099419
5dc5ca8
a112e03
7873833
3621f32
893af78
e03c3bb
a7f19c1
341df82
002e415
b173842
5ace8d6
04e0d3e
5350723
7e2f748
1195709
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
Data to use for BallotLab inputs. The data is extracted from EDF test cases | ||
and constrained to the data model Ballot Lab is using. | ||
|
||
Output file naming format is `{test-case-source}_{ballot-style-id}.json`. | ||
Note the use of `-` to separate words, and `_` to separate the name parts. | ||
|
||
All the current examples are taken from these EDF files: | ||
|
||
- https://github.com/TrustTheVote-Project/NIST-1500-100-103-examples/blob/main/test_cases/june_test_case.json | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Did you also test the September JSON? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, the example I posted above is from the September test case README is out of date. It shouldn't have been in the PR. I forgot to delete it. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No worries, I drafted this comment earlier today and didn't notice that you had specifically mentioned the Sept. JSON in your comments, above. |
||
|
||
To run it: | ||
|
||
- Install the BallotLab fork and change to the 'edf-data-to-ballot' branch. | ||
|
||
git clone https://github.com/ion-oset/BallotLab -b edf-data-to-ballot | ||
|
||
- Install the project dependencies: | ||
|
||
poetry install | ||
|
||
- Run: | ||
|
||
python scripts/ballot-lab-data.py <test-case-file> <index of ballot style> | ||
|
||
e.g. | ||
|
||
python scripts/ballot-lab-data.py june_test_case.json 1 | ||
|
||
Structure of output: | ||
|
||
- Output is a series of contests, grouped by contest type (candidate, ballot | ||
measure) | ||
- Within a contest type order of records is preserved. | ||
- The `VotingVariation` in the EDF is `vote_type` here. It can be filtered. | ||
- `vote_type` of `plurality` is the simplest kind of ballot. | ||
- Ignore `n-of-m` and `ranked-choice` until later. | ||
- Write-ins are integrated into the candidate list. | ||
- The fields were selected to match what is needed for `plurality` candidate | ||
contests and a little extra. | ||
- To add fields or modify them we should modify `extract_{contest type}_contest`. | ||
|
||
Notes: | ||
|
||
- There are no `Header`s or `OrderedHeader`s in `june_test_case.json`. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
import argparse | ||
import json | ||
from dataclasses import asdict | ||
from pathlib import Path | ||
|
||
from electos.ballotmaker.data.extractor import BallotDataExtractor | ||
|
||
|
||
def report(data, **opts): | ||
"""Generate data needed by BallotLab.""" | ||
extractor = BallotDataExtractor() | ||
ballot_data = extractor.extract(data) | ||
ballot_data = [asdict(_) for _ in ballot_data] | ||
print(json.dumps(ballot_data, indent = 4)) | ||
|
||
|
||
def main(): | ||
parser = argparse.ArgumentParser() | ||
parser.add_argument( | ||
"file", type = Path, | ||
help = "Test case data (JSON)" | ||
) | ||
parser.add_argument( | ||
"--debug", action = "store_true", | ||
help = "Enable debugging output and stack traces" | ||
) | ||
opts = parser.parse_args() | ||
file = opts.file | ||
opts = vars(opts) | ||
|
||
try: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This should be a separate file loader function outside of main() so that:
Good enough for now, though! There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sure. But there's not much to it, we can just copy it out. It's not a separate loader because I don't see the script as being used except to test out results. I presume the rest of BallotMaker will be managing files elsewhere and passing them in. You'll note that I'm trying this out now on a branch: modifying There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Cool! Let me know how it works out |
||
with file.open() as input: | ||
text = input.read() | ||
data = json.loads(text) | ||
report(data, **opts) | ||
except Exception as ex: | ||
if opts["debug"]: | ||
raise ex | ||
print("error:", ex) | ||
|
||
|
||
if __name__ == '__main__': | ||
main() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I know this is out of date, so any questions here are really just a matter of curiosity.