Replies: 8 comments 34 replies
-
Here's a start to a UML diagram for what this might look like: BallotMaker Class DiagramclassDiagram
ElectionData *-- BallotData
BallotData *-- CandidateContestData
BallotData *-- BallotMeasureData
BallotMeasureData *-- ChoiceData
CandidateContestData *-- CandidateData
class ElectionData {
+String election_name
+String start_date
+String election_type
+get_election_data()
}
class BallotData {
+String id
+String ballot_scope
+List candidate_contests
+List ballot_measures
+get_ballot_data()
+get_candidate_contests()
+get_ballot_measures()
}
class CandidateContestData {
+String id
+String title
+String district
+Int votes_allowed
+List candidates
+get_candidate_contest_data()
}
class CandidateData {
+String id
+String party
+String party_abbr
+Bool is_write_in
+String name
+get_candidate_data()
}
class BallotMeasureData {
+String id
+String title
+String district
+String text
+List choices
+get_ballot_measure_data()
}
class ChoiceData {
+String id
+String choice
+get_choice_data()
}
Notes
|
Beta Was this translation helpful? Give feedback.
-
My opinion is that most of what you are proposing I take for granted as the baseline for designing a library / long-term service like BallotMaker is.
More specific thoughts / questions forthcoming. |
Beta Was this translation helpful? Give feedback.
-
Let me expand on the initial diagram by asking: what properties does BallotMaker need to track for candidate contests and ballot measure contests? Here's what we have in code so far: Both (this is probably
Candidate contests:
Ballot measure contests:
Let's expand on that - what else is needed? |
Beta Was this translation helpful? Give feedback.
-
@stratofax: Per our discussion on the call we're developing the BallotMaker data model incrementally, as we make fixes that have been filed as issues. Here's what I've got so far. The following all seem to have been straightforward, with minor edits:
This one is already done on the data side. If there's more to it I'm missing, please elaborate. This one is a little complex and I'm still figuring out how to shape it. More details in a reply. |
Beta Was this translation helpful? Give feedback.
-
Order of contests & ballot measuresThe order that the candidate contests and ballot measures appear in your JSON output seems to be reversed from what I'd expect. Specifically, local contests and ballot measures are at the top; and national, at the bottom. I didn't know if this was a result of reading BallotStyle.OrderedContent correctly, which means the order of contests is reversed in the EDF file (like it seems to be with BallotStyle.OrderedContent.OrderedContestSelectionIds). Regardless of the reason, I wanted to float the idea of adding an explicit "order" counter for candidates and contests into your output. Right now, the order is implicit in how the data appears in the file. This seems fragile to me. @ion-oset what do you think? |
Beta Was this translation helpful? Give feedback.
-
@ion-oset you've certainly given me a lot to think about, and your thinking on these issues has (as usual) also been quite excellent. As of tomorrow morning, I'm going to be incorporating the data you've already sent me into the ballot layout, so I'm not going to be able to engage with some of these questions related to tickets and ordering until Friday at the earliest. In the meantime, I think you should keep doing what you've been doing, posting questions here and on the respective issues, tagging John and Ciff as needed. You've given me plenty of high-quality data to work with for Friday's ballot update. So, please understand that my lack of response here has nothing to do with a lack of interest, only that I'm going full "code-mode" tomorrow until I can see the new data on the ballot PDF. So, thanks again for your clear and thoughtful work on chasing down these issues with the data. It's essential and I'll be back to help with it in a day or so. |
Beta Was this translation helpful? Give feedback.
-
We should all be keeping a copy of the NIST-1500-100 spec under our pillows at night -- or at least we should be bookmarking https://pages.nist.gov/ElectionResultsReporting/ for easy access. NIST 1500-100 has been pretty well thought-out, so you should assume they've already thought of the problem you're encountering and have addressed it. If they haven't, first ask yourself if you might need to reformulate your problem: only then should you start thinking about work-arounds and extensions. So: look at the definition of BallotStyle. First, note this in the definition:
This is important: it is expected that the application generating the EDF will list the contests in order. That means the ordering of contests in your PDF is out of your hands: you have to use what you're given. It is up to the application that generates the EDF to order the contests the way the user (election official) wants. That principle (you have to use what you're given) holds throughout. Now look at the definition of ContestSelection. A ContestSelection object (or one of its sub-classes, CandidateSelection or BallotMeasureSelection) has an optional SequenceOrder, but you should ignore that: it is to be used only in post-election results display. Instead, the spec says:
So: the designers of NIST-1500-100 expect the order of contests, and of candidates within them, to be defined by the order in the BallotStyle. You have to play 'em as they lie. (It's worth noting that Python lists and tuples are explictly ordered.) |
Beta Was this translation helpful? Give feedback.
-
This should be a GitHub issue.
… On Aug 24, 2022, at 6:28 PM, Neil Johnson ***@***.***> wrote:
@ion-oset <https://github.com/ion-oset> You noticed that Contest.OfficeIds only lists one ID for the presidential race, but should list two, for president and vice president, respectively. I agree!
Also, it seems that BallotStyle.OrderedContent.OrderedContestSelectionIds are listed in reverse order, with the write-in(s) listed at the top. That doesn't seem correct.
What's the best way to put this on the @cwulfman <https://github.com/cwulfman> radar? Slack? A GitHub Issue?
—
Reply to this email directly, view it on GitHub <#81 (reply in thread)>, or unsubscribe <https://github.com/notifications/unsubscribe-auth/AAGZRWMQZVEQJJX4OPSJDOLV22OZPANCNFSM57IZFLNQ>.
You are receiving this because you were mentioned.
|
Beta Was this translation helpful? Give feedback.
-
I'd like to encapsulate the details of data retrieval from the ballot generation code. This way, we can add new data formats and sources (XML, CSV, SQL, API, etc.) without having to rewrite the ballot generator code. This is a classic example of the Open–closed principle.
What's the best way to implement this in BallotMaker?
I'd like to propose some concrete examples. Right now I'm using dictionaries, but I think it would be better to use dataclasses, because dataclasses:
For example:
The CandidateContest dataclass
I'd like to use a factory pattern to make a new CandidateContest dataclass object for each CandidateContest. This class would contain the contest name, and type as properties, and the list of Contest as collection of Candidate and BallotMeasure objects.
Each ballot would therefore be composed of (in part) an ordered set of CandidateContest data classes, which are in turn composed of a collection of Contest objects.
In addition, we could implement a strategy pattern at runtime to decide (in the future) which data retrieval method we want to use, depending on the data source.
This approach could also apply to Ballots themselves.
Beta Was this translation helpful? Give feedback.
All reactions