See also: API documentation
BDPA Elections, Inc. applauds the successful rollout of its IRV-CPL election system. User feedback indicates users are satisfied with your app UX and performance data shows response time tail latencies are very low. But your contractor has identified some changes they want to make to the original app specification.
We're looking for feedback! If you have any opinions or ideas, contact us on Slack.
🚧 🚧 To avoid disqualification, please take note of the following:
Expand
-
Any evidence of illegal remote access to AWS WorkSpaces or any other AWS resource will result in immediate disqualification.
-
As with AWS, any evidence of outside assistance (e.g. commits, offline patches, ongoing annex sync, pulls, remotes, reflog chatter, uploads, etc) during this phase of the competition will result in immediate disqualification. Unlike PS1, only the three to five students on your competition team—and no one else—can work on PS2.
-
Your solution’s source code must be located at
%USERPROFILE%\Desktop\source
on your team's AWS WorkSpace. You can also have other files located elsewhere so long as they are reachable (e.g. junctioned/soft-linked) from%USERPROFILE%\Desktop\source
. This is the only location judges are required to access when scoring your source code. -
Judges must not have to type in anything other than
http://127.0.0.1:3000
into the browser to reach your app.
Additionally, observe the following guidelines so your solution doesn't
malfunction in front of everyone after being deployed to
https://XYZ.submissions.hscc.bdpa.org
:
Expand
-
Your solution’s landing page must be available at
http://127.0.0.1:3000
(localhost) on your team's AWS WorkSpace. -
Prefer relative URIs where possible instead of hardcoding your app to use something like
127.0.0.1:3000
. -
Avoid hardcoding the protocol (e.g. use
//localhost:3000/some-file.png
instead ofhttp://localhost:3000/some-file.png
). -
Avoid loading resources in the browser using ports other than 3000 (e.g. running two separate web-visible servers, one on 3000 and one on 80).
-
If using websockets, stick to port 3000 and ensure your web server can handle Upgrade requests for your websocket-specific routes (e.g.
localhost:3000/ws
). -
Consider deploying your solution in production mode instead of development mode, which is slower and results in a degraded UX (e.g. showing errors that would normally be hidden in production, costing you points).
There are ten (10) changes in total. Three (3) ✨changes✨ are worth more points than the others:
There are 10 changes:
In addition to IRV and CPL voting methods from PS1, your app will support the "Score Then Automatic Runoff" (STAR) method.
When an eligible voter votes in a Score Then Automatic Runoff (STAR) election, they do not just cast a single vote. They must rank each option from most favored (five stars) to least favored (zero stars). After the election closes, the system will calculate the winner by the rules of this fairly simple algorithm described here and here.
There is also a YouTube video explaining the Score Then Automatic Runoff method.
When creating an election, administrators can choose to use this algorithm for determining the winner.
In addition to IRV and CPL voting methods from PS1, your app will support the "Plurality" or "First Past The Post" (FPTP) method.
When an eligible voter votes in a Plurality election, also known as First Past The Post (FPTP), the option with the most first-preference votes is the calculated winner. After the election closes, the system will calculate the winner by the rules of this very simple algorithm described here.
This is the election system used in most of the United States of America (except when voting for president, which uses a system that is somehow even more terrible).
There is also a YouTube video explaining the Plurality method.
When creating an election, administrators can choose to use this algorithm for determining the winner.
History view update: users can view what the result of a past election would have been under a different voting method.
With this change, users must be presented with the option to display how the election would have gone using a different voting method. This is an entirely client-side affair in that using this option to see the result under a different voting method must have absolutely no effect on who won the election or any other server-side effects.
Your team will have to determine how to deal with data inconsistencies between the voting methods.
For example, suppose a user viewing an election that used FPTP wanted to see who
would win if the election were using IRV instead. Each ballot of the FPTP
election might only have a single selection since FPTP
is not a preference-based voting method
(i.e. voters
pick their favorite from a list of choices instead of ranking the
choices). So attempting to see who would win a FPTP election if it were actually
an IRV or STAR election might not be possible. This should be indicated in the
UI.
Another example would be trying to show how an IRV election would have gone
under the rules of the STAR method. IRV allows voters
to rank the choices from
1 to N while STAR only allows voters
to rank choices from 1 to 5. Further,
in STAR-based elections, voters
can give multiple options the same ranking
whereas all options must have a unique ranking in IRV. You will have to
determine how to handle this. A suggestion:
normalize
the IRV rankings into STAR rankings, and then run the STAR algorithm.
A third example could be the reverse of the first: seeing who would win if an IRV election were using FPTP instead. IRV-to-FPTP is trivial to implement: it's just counting all the rank-1 choices from the IRV ballots and seeing which one got the highest score.
History and Election view updates: more descriptive results.
Before this change, a user was shown the winner of an election they're viewing (if it's closed) in the History and Election views. The rest of the UI was left up to the developer. Now, when viewing elections, users must be presented with the option to display at least the following information:
- The total number of eligible
voters
who voted in the election versus the total number of eligiblevoters
; an "eligible voter" is avoter
that has been assigned to the election in question - For each option in the election:
- What the option's current IRV/CPL/STAR/FPTP rank/result is
- That is: in which round the option was eliminated for IRV and what the option's total score was for CPL, STAR, and FPTP
- Sorted in descending order of elimination for IRV, or descending order of score for CPL, STAR, and FPTP, where the option that's winning is at the top
- The currently winning option if the election is open, or the winner if the election is closed, will be emphasized in the UI in some way
- The total number of
voters
whose ballots have this option as the highest rank and/or the largest number of votes (for FPTP)
- What the option's current IRV/CPL/STAR/FPTP rank/result is
For example, suppose Election #1
with options ["red", "green", "blue"]
, that
uses the IRV method, has the following ballots:
[
{
"voter_id": "voter1_<timestamp>",
"ranking": { "green": 1, "blue": 2 }
},
{
"voter_id": "voter2_<timestamp>",
"ranking": { "blue": 1 }
},
{
"voter_id": "voter3_<timestamp>",
"ranking": { "blue": 1, "green": 2 }
},
{
"voter_id": "voter4_<timestamp>",
"ranking": { "blue": 1, "green": 2, "red": 3 }
},
{
"voter_id": "voter5_<timestamp>",
"ranking": { "red": 1, "blue": 2, "green": 3 }
},
{
"voter_id": "voter6_<timestamp>",
"ranking": { "red": 1, "green": 2 }
},
{
"voter_id": "voter7_<timestamp>",
"ranking": { "red": 1 }
}
]
If this election were open, the UI would communicate to the user something like the following:
Currently, option
blue
is winning with 4 votes (3voters
chose it as their first choice); optionred
is in second place with 3 votes (3voters
chose it as their first choice); optiongreen
is in third place (eliminated in round one) (1voter
chose it as their first choice)
If this election were closed, the UI would communicate to the user something like the following:
Official results: option
blue
won with 4 votes (3voters
chose it as their first choice); optionred
came in second place with 3 votes (eliminated in the final round) (3voters
chose it as their first choice); optiongreen
came in third place (eliminated in round one) (1voter
chose it as their first choice)
These are just examples. How you decide to communicate this type of information to the user is entirely up to your team. Note also how the shape of the ranking is entirely up to your team, including if all options must be ranked or not. Keep this in mind when considering how best to render elections created and maintained by other teams.
administrators
can make elections public.
Before this change, no part of the system was accessible to clients that had not
yet authenticated. Therefore, each election in the system was considered
private. Now, an administrator
has the choice to make an election public.
A public election is an election whose results can be viewed by anyone
regardless of if they are logged in or not. All other rules governing elections
still apply, i.e.: what information is shown/hidden and from whom, users must
still be authenticated as voters
to vote in elections, etc.
Maintenance mode.
The
super administrator user
can, from their dashboard, toggle the app into and out of a "read-only" mode,
also known as
"maintenance mode",
where no users other than administrators
can make changes to the system. This
means voters
cannot vote in elections, even if they otherwise could, when the
system is in maintenance mode.
The specific implementation of "maintenance mode" that is most optimal for your application is left up to your team's best judgement.
Dashboard view update: expiration warnings.
Elections a voter
is eligible to vote in that they haven't voted in yet that
are closing in an hour or less will be specially marked in the UI somehow. The
goal is to alert voters
that an election they should have voted in is about to
end.
Election view update: election audit log.
Before this change, a user was shown the winner of an election they're viewing (if it's closed) in the Election view. The rest of the UI was left up to the developer. Now, when viewing an individual election, users must be presented with the option to display an "audit log" of the election.
This log will show a list of all the times the election's metadata (title
,
description
, opensAt
, closesAt
, deleted
) was modified by an
administrator. Additionally, anytime a new ballot is cast, or a ballot is
changed or deleted, along with any other such changes must also be included in
the log.
Remember: voters' names must never be shown unless explicitly instructed otherwise in the problem statement.
The audit log can be viewed by any authenticated user. However, it need only be available for elections owned by your team. You do not need to track changes or present an audit log for elections that are not owned by your team.
administrators
can view voters' real names.
Previously, in the History view
and the Election view, the names
of voters
are explicitly not displayed. This allowed us to preserve our
users' privacy.
However, BDPA Elections, Inc. has determined there is a lot of money to be made
selling this personal information to interested third parties. So,
administrators
and only administrators
, upon accessing these views, will now
see the names of voters
associated with their votes in an aesthetically
pleasing manner.
In the case that a voter's real name is not available, such as when displaying elections unowned by your team, showing the voter's ID is sufficient.
Human-friendly timestamps and timezone locale awareness.
When displaying times like "created at" or "last login time" or "closes at" anywhere in the app, instead of showing a timestamp or a full date, show a more "human-friendly" relative time like "9 years ago," "20 minutes ago," "in a day," "tomorrow at 12:20 PM," "thursday at 2:15 PM," or whatever your team believes looks the most human-friendly.
If your solution already does this, good job!