CSCI 1103 Project 5: Election!
- Due: 11:59pm Wed 12/13/2017
- Approximately 5.0% of total grade
- Submit to Canvas
- Projects are individual work: no collaboration with other students is allowed. Seek help from course staff if you get stuck for too long.
0.0.1 CODE DISTRIBUTION:
- Project files: p5-code.zip
- Testing files: p5-tests.zip
0.0.2 CHANGELOG:
- Wed Dec 6 23:34:21 CST 2017
- Tests for the project are now available linked from the top of
the spec and directly here: p5-tests.zip. Download the
testing zip, unzip it, and copy all files into the p5-code
project directory. Some of the
vote-XXX.txt
files may be duplicates but use the new versions in case there have been minor changes over the initial release. - Mon Dec 4 10:43:49 CST 2017
- Exception messages for
Tally eliminate()
have been added to the documentation. They should have the following form:'Freddie' not in Tally{Francis:0, Claire:0, Heather:0, Viktor:0}
Tally countAll()
has been clarified. If anyVote
returnsnull
for its best vote, any action may be taken such as raising exceptions or ignoring the vote. This condition will not be tested.The convention of passing a command line argument to the
main()
method ofElection
has been clarified. If no file is named, print a usage message like:usage: java Election <votes.txt>
1 Introduction
Instant Runoff Voting (IRV) or Ranked Choice Voting (RCV) is a system in which each voter selects ranks candidates for a position according to preference rather than selecting only their first choice. This is the source of the "ranked choice" name. Election results are calculated in rounds in which the candidate with the lowest vote count is dropped. If a voter's first-choice is dropped, their vote moves to their next choice. This is the source of the "instant runoff" name: a runoff election is when low-vote candidates are eliminated and voters choices are restricted. With IRV/RCV run-offs can be done "instantly" based on the rankings of voters.
IRV is generally considered advantageous over other schemes and have started to see use in some local elections including those in local Minnesota elections. It means that voters are free to cast votes for unpopular candidates who strongly align with their views knowing that if their favorite is eliminated, their vote will not be lost but transfer to their next best choice.
A couple videos explaining Ranked Choice Voting:
- City of Minneapolis description if Ranked Choice Voting (Youtube, 2:00min)
- MPR Overview of Instant Runoff Voting (Youtube, 1:10min)
This project will center on calculating the results of elections which use IRV. It will employ all of the skill that we have studied in Java so far including some new ones.
- The IRV algorithm is iterative in nature with several termination criteria so looping and conditionals will be essential.
- Objects and classes will be used to divide up responsibilities such
as
Vote
andTally
along with associated functionality in methods such ascountVote()
. - Voting information will be stored in files which must be read to create the necessary internal data.
1.1 Simplified Rules for Ranked Choice Voting
- Winners: At any point, if any candidate has more than 50% of the total votes, that candidate is the winner and the results are complete.
- Ties: At any point, if all remaining candidates have an equal number of votes there is an all-way tie and the results are complete.
- Drop Lowest: If there is not a winner or tie, the candidate(s) with the lowest number of votes are dropped from the election. There may be multiple such candidates. Another round of tallying is done in which votes are recalculated based on the new, smaller pool of candidates.
- All Votes Complete: It is assumed that each vote has a complete
ordering of the candidates from
1
toN
. Additional rules would need to be introduced to deal with partial or improper rankings.
1.2 An Example Election
Four candidates are running for office: Francis, Claire, Heather, and Viktor. There are 12 voters which rank the candidates each as either 1st, 2nd, or 3rd choice according to the rules of IRV.
1.2.1 Round 1 of Tabulating
RANKS | ||||
---|---|---|---|---|
Voter | Francis | Claire | Heather | Viktor |
A | 1 | 4 | 3 | 2 |
B | 2 | 1 | 3 | 4 |
C | 3 | 2 | 1 | 4 |
D | 3 | 2 | 1 | 4 |
E | 2 | 1 | 3 | 4 |
F | 1 | 3 | 2 | 4 |
G | 1 | 2 | 3 | 4 |
H | 3 | 2 | 1 | 4 |
I | 2 | 3 | 1 | 4 |
J | 2 | 4 | 3 | 1 |
K | 1 | 2 | 3 | 4 |
L | 2 | 3 | 1 | 4 |
total | 4 | 2 | 5 | 1 |
While Heather has the most 1st place votes, she does not have a majority so does not yet win the election. Viktor is the candidate with the fewest 1st place votes so is eliminated. Votes are recounted with any voter who chose Viktor as their 1st place (Voter J) selecting their next choice.
1.2.2 Round 2 Tabulating
RANKS | ||||
---|---|---|---|---|
XXX | ||||
Voter | Francis | Claire | Heather | Viktor |
A | 1 | 4 | 3 | 2 |
B | 2 | 1 | 3 | 4 |
C | 3 | 2 | 1 | 4 |
D | 3 | 2 | 1 | 4 |
E | 2 | 1 | 3 | 4 |
F | 1 | 3 | 2 | 4 |
G | 1 | 2 | 3 | 4 |
H | 3 | 2 | 1 | 4 |
I | 2 | 3 | 1 | 4 |
J | 2 | 4 | 3 | 1 |
K | 1 | 2 | 3 | 4 |
L | 2 | 3 | 1 | 4 |
total | 5 | 2 | 5 | XXX |
Note that Voter J's vote goes to Francis now as he was 2nd choice after Viktor. Francis and Heather both have 5 votes but this is not a majority. Claire is eliminated with votes to her going to other candidates.
1.2.3 Round 3 Tabulating
RANKS | ||||
---|---|---|---|---|
WINNER | XXX | XXX | ||
Voter | Francis | Claire | Heather | Viktor |
A | 1 | 4 | 3 | 2 |
B | 2 | 1 | 3 | 4 |
C | 3 | 2 | 1 | 4 |
D | 3 | 2 | 1 | 4 |
E | 2 | 1 | 3 | 4 |
F | 1 | 3 | 2 | 4 |
G | 1 | 2 | 3 | 4 |
H | 3 | 2 | 1 | 4 |
I | 2 | 3 | 1 | 4 |
J | 2 | 4 | 3 | 1 |
K | 1 | 2 | 3 | 4 |
L | 2 | 3 | 1 | 4 |
total | 7 | XXX | 5 | XXX |
The voters who picked Claire as their top choice (Voters B and E) both picked Francis as choice 2 so his votes increase. Francis now has a majority and is the winner of the election. This is despite initially having fewer votes than Heather.
2 Download Code and Setup
As in previous projects, download the code pack linked at the top of the page. Unzip this which will create a folder and create your files in that folder.
File | State | Notes |
---|---|---|
Vote.java | Create | Represents a Vote by a Voter |
Tally.java | Create | Represents a Tally of votes, a partial election result |
Util.java | Create | Utility methods to help parse files and split strings |
Election.java | Create | Provides a main() method to read a vote file and calculate election results |
votes-1round.txt | Data | Votes data with an immediate winner |
votes-2waytie.txt | Data | Votes data with a 2-way tie |
votes-3cands.txt | Data | Votes data with 3 candidates |
votes-3waytie.txt | Data | Votes data with a 3-way tie |
votes-5cands.txt | Data | Votes data with 5 candidates |
votes-drop2.txt | Data | Votes data with 2 lowest vote candidates in a round |
votes-many.txt | Data | Votes data with many candidates |
votes-standard.txt | Data | Votes data with the 4-candidate spec election in it |
votes-stress.txt | Data | Votes data with many candidates and votes |
VoteTests.java | Testing | Tests for the Vote class |
TallyTests.java | Testing | Tests for the Tally class |
ElectionTests.java | Testing | Tests for the Election class |
KTests.java | Testing | Test utilities and run all tests on command line |
junit-1103.jar | Testing | JUnit testing library for command line tests |
3 Util Class
Several static text-processing methods are useful elsewhere in the
project but do not fill well into any specific class so are housed in
the Util
class. These are as follows.
3.1 Class Structure of Util
public class Util{ // Contains static methods useful for parsing files. public static int countLines(String filename) throws Exception; // Count the number of lines in the file given. Makes use of a // Scanner to read the file. public static String [] splitIntoStrings(String str); // Create an array of strings filled with each String in str // separated by spaces. Uses a Scanner to parse the String str. // // For example: // // String str = "here are some words"; // String tokens[] = Util.splitIntoStrings(str); // tokens is now the array { here, are, some, words } // 0 1 2 3 public static int [] splitIntoInts(String str); // Create an array of ints filled with each integer in str separated // by spaces. Uses a Scanner to parse the String str. // // String str = "8 6 7 5 30 9"; // int nums[] = Util.splitIntoInts(str); // nums is now the array { 8, 6, 7, 5, 30, 9 } // 0 1 2 3 4 5 }
3.2 Implementation of the Util
3.2.1 Counting File Lines
public class Util{ public static int countLines(String filename) throws Exception; }
Make use of a Scanner
and a loop involving hasNextLine()
and
nextLine()
to count how many lines are in a file.
Note that you should not use a try/catch block in this method which
states in its type signature that it throws Exception
. This is a
bit similar to a lab 12 problem and just means writing less code
Examples:
> Util.countLines("votes-standard.txt") 13 > Util.countLines("votes-2waytie.txt") 7 > Util.countLines("votes-3waytie.txt") 7 > Util.countLines("votes-drop2.txt") 8 > Util.countLines("not-there.txt") java.io.FileNotFoundException: not-there.txt (No such file or directory) at java.io.FileInputStream.open0(Native Method) at java.io.FileInputStream.open(FileInputStream.java:195) at java.io.FileInputStream.<init>(FileInputStream.java:138) at java.util.Scanner.<init>(Scanner.java:611) at Util.countLines(Util.java:10)
3.2.2 Splitting Strings
public class Util{ public static String [] splitIntoStrings(String str); public static int [] splitIntoInts(String str); }
There are a couple occasions in this project in which it will be
necessary to process a line of text read from a file into an array
integers or strings. The two methods splitIntoStrings()
and
splitIntoInts()
do this and return arrays of their respective
types. A Scanner which reads from the parameter strings should be
used for this in two passes
- First read all tokens in the input string to count them
- Then allocate an array of the appropriate size
- Then read back through the tokens in the input string and assign them to elements of the array
The method ARE NOT required to do any error checking (for null strings, for non-numbers, etc.).
Here are examples of the splitting methods from Util
shown in
DrJava's interactions pane.
Welcome to DrJava > String s = "Strings to read"; > String arr[] = Util.splitIntoStrings(s); > arr { Strings, to, read } > String candsStr = "Francis Claire Heather Viktor"; > String cands[] = Util.splitIntoStrings(candsStr); > cands { Francis, Claire, Heather, Viktor } > String rankStr = "4 2 3 1"; > int ranks[] = Util.splitIntoInts(rankStr); > ranks { 4, 2, 3, 1 } > int ranks2[] = Util.splitIntoInts("8 5 4 6 1 2 3 7"); > ranks2 { 8, 5, 4, 6, 1, 2, 3, 7 } > ranks2[3] 6
3.3 Util Class Manual Inspection Criteria grading
The criteria below will be examined by graders to account for part of your grade.
Wgt | Criteria |
---|---|
2% | Good style, indentation, and variable name choices are used. The Camel case naming convention is used. Code is properly indented |
3% | Scanners and their methods are used to read through files, count tokens, and read tokens. |
5% | The split() methods use a clearly documented two-pass strategy of counting, the reading tokens into an array. |
10% | Total weight for these criteria |
4 Vote Class
Any election has votes and to accommodate them, the Vote
class
provides basic facilities to track preferred candidates. In IRV
elections, voters must specify a ranking of candidates, a primary
feature of the class. Also notable is that, to preserve some
semblance of integrity, the Vote
class will be immutable: once
constructed, it does not change and only has accessor methods.
Very few fields are required for Vote
. The instructor implementation
of the project uses only one field to keep the ranked
candidates. Students may use additional fields if it seems relevant
though all fields should be private and documented with their
purpose.
4.1 Class Structure of Vote
All the methods in the outline for Vote
are required. Note that the
private
fields have been omitted in the class description but they
should be added.
public class Vote{ // A class to represent a ranked ordering of candidates. public Vote(String candidates[], int ranks[]); // Create a vote. The candidates given are ranked according to the // ranks[] parameter. For example, the parameters // // candidates = {Francis, Claire, Heather, Viktor}; // ranks = {2, 3, 0, 1 }; // // results in the vote // // Vote{Heather, Viktor, Francis, Claire} // // where the ordering of the candidates is reflected in the idexes // given in ranks[]. // public String toString(); // Produce a string representatin of this Vote which shows the // ranked ordering of the candidates. The format is as follows. // // 0 candidates example: // Vote{} // // 4 candidates example: // Vote{Heather, Viktor, Francis, Claire} // // Uses a loop to incrementally build up the string representation. public static Vote[] readVoteFile(String filename) throws Exception; // Read votes from a file like the following. // // Francis Claire Heather Viktor // 1 4 3 2 // 2 1 3 4 // 3 2 1 4 // // The first line shows the candidates, 4 in this case while each // subsequent line are the ranks of those candidates. Returns an // array of Vote[] objects initialzied from their contents of the // file. Makes use of Scanner and methods of Util the split lines // into arrays of strings and integers. Note that each line is // 1-indexed so should be decremented to form the ranks of the vote. public String getBest(Tally tally); // Retrieve the highest ranked candidate for this Vote which is in // the Tally given. The parameter tally may contain fewer candidates // than were used to create the Vote. If the Vote has no candidate // contained in the given Tally, return null. }
4.2 Implementation of the Vote Class
4.2.1 Constructor, Fields, toString()
public class Vote{ public Vote(String candidates[], int ranks[]); public String toString();
The constructor for Vote
takes an array of candidates and an equal
length array of their ranks. During the constructor, a new array of
Strings
should be allocated for a internal, private field of
Vote
. Candidates are copied into this array in ranked order and
the toString()
method produces a string representation of the vote
with candidates in ranked order. An example:
Welcome to DrJava. > String [] candidates = {"Francis", "Claire", "Heather", "Viktor"}; > int ranks[] = {2, 3, 0, 1 }; > Vote vote = new Vote(candidates, ranks); > vote.toString() Vote{Heather, Viktor, Francis, Claire} > int ranks2[] = {1, 0, 3, 2 }; > Vote vote2 = new Vote(candidates, ranks2); > vote2.toString() Vote{Claire, Francis, Viktor, Heather}
Note that the constructor does no copy the candidates identically but
instead arranges its internal array of ranked candidates according to
the ranking specified in the ranks[]
parameter.
Also note that the ranks are 0-indexed to make creating the internal ranked array of candidates easy.
It is an error to construct a Vote with candidate/rank arrays with
differing lengths. A RuntimeException
should be thrown with an
information error message formatted as follows.
> Vote bad = new Vote(candidates, ranks3); java.lang.RuntimeException: candidates.length 4 != 2 ranks.length at Vote.<init>(Vote.java:25)
It is not specified what should happen if a vote is constructed with bad ranks which are negative, larger than then Lent of candidates, or have repeats in them. In an industrial implementation, checking for these errors and handling them would be important but it is not required here.
4.2.2 Reading Votes from a File
public static Vote[] readVoteFile(String filename) throws Exception
Votes will be stored in text files necessitating that they be read
in. The format of these data files is well represented by the provided
votes-standard.txt
.
Francis Claire Heather Viktor 1 4 3 2 2 1 3 4 3 2 1 4 3 2 1 4 2 1 3 4 1 3 2 4 1 2 3 4 3 2 1 4 2 3 1 4 2 4 3 1 1 2 3 4 2 3 1 4
The first line contains the names of all candidates while remaining
lines contain the ranks of those candidates by each voter. The ranks
in data files are 1-indexed so care will need be taken as the Vote
class constructor required 0-indexed arrays.
The readVoteFile()
method does the following.
- Takes the name of a vote data file as an argument.
- Uses a method of Util to count the lines in the file
- Allocates an array of the correct size to hold all votes in file knowing that the first line does not contain a vote but the candidate list
- Open the file using a Scanner NOT in a try/catch block
- Reads the first line and splits it into an array using methods from Util to get the candidates from the file.
- Proceeds to read each remaining line of the file which is split to
produce ranks of the candidates by a voter and creates a
Vote
object which is put into the array - Closes the file and returns the array of votes
- No exceptions are caught or thrown in the method explicitly;
instead any exceptions that result percolate up as indicated by the
throws Exception
in the type signature of the method.
Example of calling the readVoteFile()
is below.
> Vote [] standard = Vote.readVoteFile("votes-standard.txt"); > standard.length 12 > standard {Vote{Francis, Viktor, Heather, Claire}, Vote{Claire, Francis, Heather, Viktor}, Vote{Heather, Claire, Francis, Viktor}, Vote{Heather, Claire, Francis, Viktor}, Vote{Claire, Francis, Heather, Viktor}, Vote{Francis, Heather, Claire, Viktor}, Vote{Francis, Claire, Heather, Viktor}, Vote{Heather, Claire, Francis, Viktor}, Vote{Heather, Francis, Claire, Viktor}, Vote{Viktor, Francis, Heather, Claire}, Vote{Francis, Claire, Heather, Viktor}, Vote{Heather, Francis, Claire, Viktor} } > Vote [] tie = Vote.readVoteFile("votes-2waytie.txt"); > tie.length 6 > tie {Vote{Viktor, Heather, Claire, Francis}, Vote{Viktor, Heather, Claire, Francis}, Vote{Viktor, Heather, Claire, Francis}, Vote{Claire, Heather, Viktor, Francis}, Vote{Claire, Heather, Viktor, Francis}, Vote{Claire, Heather, Viktor, Francis} }
4.2.3 getBest() Candidate
public String getBest(Tally tally)
IRV elections require that a vote must provide its "best" candidate of
a specified number available. This will be done by an interaction
vbetween the Vote
and Tally
classes. A Tally keeps track of which
candidates remain after some are eliminated and the Vote
will be
required to produces which candidate is considered best in its ranking
among those that remain.
> String [] candidates = {"Francis", "Claire", "Heather", "Viktor"}; > int ranks[] = {2, 3, 0, 1 }; > Vote vote = new Vote(candidates, ranks); > Tally tally1 = new Tally(candidates); > tally1 Tally{Francis:0, Claire:0, Heather:0, Viktor:0} > vote Vote{Heather, Viktor, Francis, Claire} > vote.getBest(tally1) Heather // top candidate available > String [] candidates2 = {"Francis", "Claire", "Viktor"}; > Tally tally2 = new Tally(candidates2); > tally2 Tally{Francis:0, Claire:0, Viktor:0} > vote Vote{Heather, Viktor, Francis, Claire} > vote.getBest(tally2) Viktor // Heather gone, 2nd choice Viktor > String [] candidates3 = {"Francis", "Claire"}; > Tally tally3 = new Tally(candidates3); > tally3 Tally{Francis:0, Claire:0} > vote.getBest(tally3) Francis // top 2 gone, Francis ranked next > Tally tally4 = new Tally(new String[]{"Freddy","Remy"}); > tally4 Tally{Freddy:0, Remy:0} > vote Vote{Heather, Viktor, Francis, Claire} > vote.getBest(tally4) // No candidates preferred available null // return null - something is likely wrong
This method will require some parts of Tally
to be complete it may
be wise to work on that class and then return to Vote
when it is
suitable. In particular, the contains()
method of Tally
is useful
if used in a loop in getBest()
over the candidates in order of rank.
4.3 Vote Class Manual Inspection Criteria grading
The criteria below will be examined by graders to account for part of your grade.
Wgt | Criteria |
---|---|
3% | Good style, indentation, and variable name choices are used. The Camel case naming convention is used. Code is properly indented |
2% | Fields of the class are private and fields/methods are non-static. |
3% | The readVoteFile() is clearly laid out and has comments describing what is happening. |
2% | readVoteFile() makes use of the methods from the Util class to count file lines and split lines. |
10% | Total weight for these criteria |
5 Tally Class Overview
Elections need results to be calculated which is the responsibility of
the Tally
class. It represents a set of candidates and their current
count of votes. Unlike the Vote
class, Tally
is somewhat mutable:
it has methods which alter its internal state such as countVote()
.
It also has a method called eliminate()
used to produce a new tally
with one candidate eliminated. These methods will all see use in
performing election calculations.
5.1 Class Structure of Tally
Below are all of the public methods that should appear in the class. The private fields do not appear but should be added.
public class Tally{ // Represent the candidates in election along with the counts of the // votes for each of them. public Tally(String candidates[]); // Construct a Tally with the given candidates. The constructor // makes a deep copy of the array given so that subsequent changes // to the parameter array do not affect the tally. The initial vot // counts for each candidate are all 0. public String toString(); // Produce a string version of the Tally formatted as follows. // // 0 candidates // Tally{} // // 3 candidates // Tally{Francis:4, Claire:2, Heather:4} // // Builds the string reprsentation up incrementally using a loop. public int size(); // Return the number of candidates in this Tally. public boolean contains(String candidate); // Return true if the specified candidate is present in this Tally // and false otherwise. public void countVote(String candidate); // Increment the vote count of the candidate specified. The the // candidate is not present in this Tally, throw a RuntimeException // with a message formatted like: // // 'Edmond' not in Tally{Francis:0, Claire:0, Heather:1, Viktor:0} public int totalVotes(); // Return the total number of votes which have been counted in this // Tally. public String outputString(); // Produce a nicely formatted table of the Tally. The table includes // vote count, percent, and name for each candidate which appears // // CNT % NAME // 4 33.3 Francis // 2 16.7 Claire // 5 41.7 Heather // 1 8.3 Viktor // // The format string "%3d %5.1f %s\n" is useful where the arguments // are the vote counts, percentage of votes won, and candidate // names. public String getWinner(); // Calculate the percent of the total votes each candidate has // earned. If any candidate has greater than 50% of the votes, // return that candidate as a String. If no candidate has more than // 50% of the vote, return null. public String [] getMinCandidates(); // Return an array of Strings containing all candidate names which // are tied for the minimum number of votes. First searche for the // minimum vote count in the Tally among candidates, the allocates // an array of Strings of that size and fills it with candidates // which have vote counts equal to the minimum. public boolean allWayTie(); // Return true if an all-way tie has occurred and false // otherwise. This happens if all candidates have an equal number of // votes. Note that all-way ties correspond with getMinCanidates() // producing an array with equal length to the size() of the // tally. public Tally eliminate(String candidate); // Create a new Tally with the candidate specified eliminated. This // Tally should have 1 fewer candidates. The vote counts for each // candidate in the resulting ballot shoudl be 0. If the candidate // mentioned is not in the Tally, throw a RuntimeException with the // message: // // 'Freddie' not in Tally{Francis:0, Claire:0, Heather:0, Viktor:0} public static Tally readTallyFromFile(String filename) throws Exception; // Read candidate names from the first line of the given file and // create a Tally from them. The initial vote counts for each of // candidate are 0. Makes use of Scanner and the // Util.splitIntoStrings() method. This method may throw Exceptions // and should not use a try/catch block. public String countAll(Vote votes[]); // Count all of the votes in the given array and add them to the // counts of votes in this tally. Each vote has its best remaining // candidate added to the tally. While tabulating, create a // transcript String of the process which shows what is done for // each vote. This string has the following format // // 0 : Francis Vote{Francis, Viktor, Heather, Claire} Tally{Francis:1, Claire:0, Heather:0} // 1 : Claire Vote{Claire, Francis, Heather, Viktor} Tally{Francis:1, Claire:1, Heather:0} // ... // 9 : Francis Vote{Viktor, Francis, Heather, Claire} Tally{Francis:4, Claire:2, Heather:4} // 10 : Francis Vote{Francis, Claire, Heather, Viktor} Tally{Francis:5, Claire:2, Heather:4} // 11 : Heather Vote{Heather, Francis, Claire, Viktor} Tally{Francis:5, Claire:2, Heather:5} // // for which the following format string is useful: // "%2d : %-10s %s %s\n" // arguments are the vote index, best candidate, vote toString(), and tally toString(). // // If any Vote returns null, the behavior of this method is NOT // DEFINED. Any action may be taken such as printing a warning, // throwing an exception or ignoring the vote. No tests will be run // on this case. }
5.2 Implementation of Tally
5.2.1 Constructor, Fields, size(), toString(), contains()
public class Tally{ public Tally(String candidates[]); public String toString(); public boolean contains(String candidate); }
Tally will need a least a couple fields to track the candidates on the
tally and their respective counts of votes. Students may add
additional fields as the need arises. All fields should be
private. Only the candidates are passed to the constructor while the
vote counts should default to 0 for all candidates. The size()
method returns how many candidates are associated with the tally.
The toString()
method should produce a string that combines the
candidate names and counts in a similar format to Vote.
Finally, Tally provides a way to determine whether a candidate is
present or absent from its roster of candidates via the
contains(cand)
method. True or false is returned based on whether
the named candidate is among those tracked by the tally.
Below are examples of calling the constructor, toString()
, and contains()
.
> String cands[] = { "Francis", "Claire", "Heather", "Viktor" }; > Tally tally1 = new Tally(cands); > tally1.toString() Tally{Francis:0, Claire:0, Heather:0, Viktor:0} > tally1.size() 4 > tally1.contains("Heather") true > tally1.contains("Claire") true > tally1.contains("Freddy") false > tally1.contains("Remy") false > String none[] = {}; > Tally tally0 = new Tally(none); > tally0.toString() Tally{} > tally0.size() 0 > tally0.contains("Viktor") false > tally0.contains("Francis") false > String lots [] = {"A","B","C","D","E","F","G","H"}; > Tally tally3 = new Tally(lots); > tally3.toString() Tally{A:0, B:0, C:0, D:0, E:0, F:0, G:0, H:0} > tally3.size() 8 > tally3.contains("B") true > tally3.contains("G") true > tally3.contains("Z") false > tally3.contains("Francis") false
5.2.2 countVote(), totalVotes(), outputString()
public void countVote(String candidate); public int totalVotes(); public String outputString();
Counting votes is essential to the purpose of Tally and is done via
the countVote(cand)
method. This method increases the named
candidate's vote count by 1 and will be used in conjunction with the
vote.getBest(tally)
method to select a favored candidate to
increase.
The total votes cast for all candidates so far will be needed at
various points which is produced by totalVotes()
. It sums all votes
and returns the total.
Finally, a read out of the current state of the tally in tabular
format is produced by the outputString()
. This method creates
somewhat more verbose output than toString()
which shows candidate
standings. An example table table:
CNT % NAME 4 33.3 Francis 2 16.7 Claire 5 41.7 Heather 1 8.3 Viktor
Demonstrations of the above methods.
> String cands[] = { "Francis", "Claire", "Heather", "Viktor" }; > Tally tally1 = new Tally(cands); > tally1 Tally{Francis:0, Claire:0, Heather:0, Viktor:0} > tally1.countVote("Claire"); > tally1.countVote("Heather"); > tally1.countVote("Heather"); > tally1.countVote("Viktor"); > tally1.countVote("Francis"); > tally1.countVote("Heather"); > tally1.countVote("Francis"); > tally1.totalVotes() 7 > tally1.toString() Tally{Francis:2, Claire:1, Heather:3, Viktor:1} > tally1.outputString() CNT % NAME 2 28.6 Francis 1 14.3 Claire 3 42.9 Heather 1 14.3 Viktor > tally1.countVote("Francis"); > tally1.countVote("Claire"); > tally1.totalVotes() 9 > tally1.outputString() CNT % NAME 3 33.3 Francis 2 22.2 Claire 3 33.3 Heather 1 11.1 Viktor // Throw RuntimeExceptions when a candidate is not present in a call to countVote() > tally1.countVote("Freddie"); java.lang.RuntimeException: 'Freddie' not in Tally{Francis:3, Claire:2, Heather:3, Viktor:1} at Tally.countVote(Tally.java:73)
5.2.3 Winners
public String getWinner();
According to our rules for IRV elections, a winner can be declared if
any candidate has more than 50% of the counted votes. The
getWinner()
method should analyze the internal counts of votes for a
Tally and determine this. Should a candidate have greater than 50% of
the vote, getWinner()
should return the candidate as a string. It
may happen that no candidate has sufficient votes to be the winner in
which case null
is returned. Here are examples.
> tally1.outputString() CNT % NAME 3 33.3 Francis 2 22.2 Claire 3 33.3 Heather 1 11.1 Viktor > tally1.getWinner() null // no one has a majority yet > tally1.countVote("Heather") > tally1.countVote("Heather") > tally1.countVote("Heather") > tally1.outputString() CNT % NAME 3 25.0 Francis 2 16.7 Claire 6 50.0 Heather // Heather is close but no above 50% 1 8.3 Viktor > tally1.getWinner() null // no winner yet > tally1.countVote("Heather") > tally1.outputString() CNT % NAME 3 23.1 Francis 2 15.4 Claire 7 53.8 Heather // above 50% 1 7.7 Viktor > tally1.getWinner() Heather // winner, winner, chicken dinner // stuff the ballot box > for(int i=0; i<10; i++){ tally1.countVote("Francis"); } > tally1.outputString() CNT % NAME 13 56.5 Francis // winners are not permanent... 2 8.7 Claire 7 30.4 Heather 1 4.3 Viktor > tally1.getWinner() Francis // house of cards complete
5.2.4 Losers and Ties
public String [] getMinCandidates(); public boolean allWayTie();
As there are winners, there are also losers in the elections. IRV
elections focuses on dropping candidates with low vote counts. There
may be several such candidates. All of them are reported by the
getMinCandidates()
which returns an array of the candidates who have
the lowest vote counts. Often this will be a single candidate but
there may be more.
> tally.outputString() CNT % NAME 2 13.3 Francis 4 26.7 Claire 4 26.7 Heather 5 33.3 Viktor > String mins[] = tally.getMinCandidates(); > mins { Francis } // single minimum candidate // adjust the votes > for(int i=0; i<6; i++){ tally.countVote("Francis"); } > tally.outputString() CNT % NAME 8 38.1 Francis 4 19.0 Claire // tied for last 4 19.0 Heather // tied for last 5 23.8 Viktor > String mins[] = tally.getMinCandidates(); > mins { Claire, Heather } // two minimum candidates
It is possible that the election may result in an all-way tie. This occurs when the remaining candidates all have the same number of votes. Conveniently, since all candidates are tied, they all have the minimum number of votes so a convenient mechanism to detect all-way ties is to compare the size of the candidates with minimum votes to the size of all the candidates. There are also other ways to determine whether an all-way tie has occurred.
The allWayTie()
method returns true if an tie has occurred and false
otherwise.
> tally.outputString() CNT % NAME 8 38.1 Francis // clear winnner 4 19.0 Claire 4 19.0 Heather 5 23.8 Viktor > tally.allWayTie() // no tie at present false // Adjust vote counts > for(int i=0; i<4; i++){ tally.countVote("Claire"); } > for(int i=0; i<4; i++){ tally.countVote("Heather"); } > for(int i=0; i<3; i++){ tally.countVote("Viktor"); } > tally.outputString() CNT % NAME 8 25.0 Francis // all even now 8 25.0 Claire 8 25.0 Heather 8 25.0 Viktor > tally.allWayTie() // allWayTie() has occurred true
5.2.5 Eliminating Candidates
public Tally eliminate(String candidate);
IRV elections happen in automatic rounds. At the end of each round,
the candidates with minimum votes are dropped. To facilitate this, the
Tally class provides the eliminate(cand)
method. This method takes
the interesting tack of producing a fresh new Tally with the requested
candidate dropped. The new Tally is distinct from the original with a
smaller size and 0 vote counts. The original Tally is disconnected
from it.
To complete this method, create a new String array and copy in all
candidates save for the candidate to eliminate. The call the Tally()
constructor to create a fresh tally with the smaller candidate roster
and return it.
If the candidate requested in the drop is not present, throw a
RuntimeException
with a message formatted as indicated.
> original.toString() Tally{Francis:2, Claire:7, Heather:5, Viktor:3} // 4 candidates originally > Tally dropped1 = original.eliminate("Viktor"); // drop 1 candidate > dropped1.toString() // new Tally has fewer candidates Tally{Francis:0, Claire:0, Heather:0} // and has counts reset to 0 > dropped1.countVote("Claire") > dropped1.toString() Tally{Francis:0, Claire:1, Heather:0} // new Tally is independent from original > original.toString() Tally{Francis:2, Claire:7, Heather:5, Viktor:3} // same vote counts in original > Tally dropped2 = dropped1.eliminate("Francis"); // drop a second candidate, get another Tally > dropped2.toString() Tally{Claire:0, Heather:0} // also has counts reset to 0 > dropped2.contains("Remy") false // when called with a non-existen candidate > dropped2.eliminate("Remy") // eliminate() throws a RuntimeException java.lang.RuntimeException: No candidate 'Remy' in Tally{Claire:0, Heather:0} at Tally.eliminate(Tally.java:181)
5.2.6 Reading a Tally from a File
public static Tally readTallyFromFile(String filename) throws Exception;
It is necessary in the main election algorithm to initialize a Tally
based on the contents of voter files. This should be done by opening
the file and reading the first line of the file which contains the
candidates. This line can be split using methods from the Util
class. The remainder of the file is ignored by this method.
Since it is static, this method has a different calling convention that uses the class name to invoke it.
> Tally tally = Tally.readTallyFromFile("votes-standard.txt") > tally.toString() Tally{Francis:0, Claire:0, Heather:0, Viktor:0} > Tally many = Tally.readTallyFromFile("votes-many.txt"); > many.toString() Tally{A:0, B:0, C:0, D:0, E:0, F:0, G:0, H:0}
5.2.7 Transcripts of Counting all Votes
public String countAll(Vote votes[])
The primary concern of Tally is to count votes which come in
batches. The countAll(votes)
method will loop through the given
array and of votes and count all of them. Importantly, this is where
the vote.getBest(tally)
method should be used so that if the first
choice mentioned in a vote is not present in the given Tally, a lower
ranked choice can be gotten.
Calls to vote.getBest(tally)
require an instance of a Tally to
produce their best candidate. Since countAll()
is a non-static
method, such a reference is available via the this
pointer.
The return value of the transcript should be a String which shows how each vote was counted. The format of each line shown below and is similar to the following.
0 : Francis Vote{Francis, Viktor, Heather, Claire} Tally{Francis:1, Claire:0, Heather:0, Viktor:0} 1 : Claire Vote{Claire, Francis, Heather, Viktor} Tally{Francis:1, Claire:1, Heather:0, Viktor:0} 2 : Heather Vote{Heather, Claire, Francis, Viktor} Tally{Francis:1, Claire:1, Heather:1, Viktor:0} 3 : Heather Vote{Heather, Claire, Francis, Viktor} Tally{Francis:1, Claire:1, Heather:2, Viktor:0} 4 : Claire Vote{Claire, Francis, Heather, Viktor} Tally{Francis:1, Claire:2, Heather:2, Viktor:0} ...
- Vote index in array (indexed from 0)
- Vote toString()
- Tally toString() after dding the best available candidate for the vote.
A good way to build up the string is via String.format()
and string concatenation.
Here are examples of the method.
> Tally tally = Tally.readTallyFromFile("votes-standard.txt") > tally.toString() Tally{Francis:0, Claire:0, Heather:0, Viktor:0} > Vote votes[] = Vote.readVoteFile("votes-standard.txt"); > votes { Vote{Francis, Viktor, Heather, Claire}, Vote{Claire, Francis, Heather, Viktor}, Vote{Heather, Claire, Francis, Viktor}, Vote{Heather, Claire, Francis, Viktor}, Vote{Claire, Francis, Heather, Viktor}, Vote{Francis, Heather, Claire, Viktor}, Vote{Francis, Claire, Heather, Viktor}, Vote{Heather, Claire, Francis, Viktor}, Vote{Heather, Francis, Claire, Viktor}, Vote{Viktor, Francis, Heather, Claire}, Vote{Francis, Claire, Heather, Viktor}, Vote{Heather, Francis, Claire, Viktor} } > String transcript = tally.countAll(votes); > tally.toString() Tally{Francis:4, Claire:2, Heather:5, Viktor:1} > tally.outputString() CNT % NAME 4 33.3 Francis 2 16.7 Claire 5 41.7 Heather 1 8.3 Viktor > transcript 0 : Francis Vote{Francis, Viktor, Heather, Claire} Tally{Francis:1, Claire:0, Heather:0, Viktor:0} 1 : Claire Vote{Claire, Francis, Heather, Viktor} Tally{Francis:1, Claire:1, Heather:0, Viktor:0} 2 : Heather Vote{Heather, Claire, Francis, Viktor} Tally{Francis:1, Claire:1, Heather:1, Viktor:0} 3 : Heather Vote{Heather, Claire, Francis, Viktor} Tally{Francis:1, Claire:1, Heather:2, Viktor:0} 4 : Claire Vote{Claire, Francis, Heather, Viktor} Tally{Francis:1, Claire:2, Heather:2, Viktor:0} 5 : Francis Vote{Francis, Heather, Claire, Viktor} Tally{Francis:2, Claire:2, Heather:2, Viktor:0} 6 : Francis Vote{Francis, Claire, Heather, Viktor} Tally{Francis:3, Claire:2, Heather:2, Viktor:0} 7 : Heather Vote{Heather, Claire, Francis, Viktor} Tally{Francis:3, Claire:2, Heather:3, Viktor:0} 8 : Heather Vote{Heather, Francis, Claire, Viktor} Tally{Francis:3, Claire:2, Heather:4, Viktor:0} 9 : Viktor Vote{Viktor, Francis, Heather, Claire} Tally{Francis:3, Claire:2, Heather:4, Viktor:1} 10 : Francis Vote{Francis, Claire, Heather, Viktor} Tally{Francis:4, Claire:2, Heather:4, Viktor:1} 11 : Heather Vote{Heather, Francis, Claire, Viktor} Tally{Francis:4, Claire:2, Heather:5, Viktor:1}
5.3 Tally Class Manual Inspection Criteria grading
The criteria below will be examined by graders to account for part of your grade.
Wgt | Criteria |
---|---|
2% | Fields of the class are private and each method has the correct static/non-static designator |
3% | Good style, indentation, and variable name choices are used. The Camel case naming convention is used. Code is properly indented |
2% | Brief but sufficient comments are supplied to indicate what is happening. Comments that appear in the specification do not count. |
5% | getMinCandidate() is clearly laid out: determine the minimum count, count candidates with the minimum, add them to an array. |
5% | eliminate() has a clear loop which passes over the candidate which should be eliminated. |
3% | readTallyFromFile() uses Scanner appropriately to parse the first line for the candidates |
20% | Total weight for these criteria |
6 Election Class
The Election
class ties all of the parts together. Its
main()
method reads a file of votes, allocates an initial tally, and
then starts calculating results. Each result is checked for winner or
tie and if neither occurs, minimum candidates are dropped and another
round of voting is performed.
6.1 Class Structure of Election
Below are all of the public methods that should appear in the class. The private fields do not appear but should be added.
public class Election{ // Contains a main method to tabulate the results of an election based // on votes stored in text files. public static void main(String args[]) throws Exception; // Read a vote file named on the command line such as // votes-standard.txt. Creates a Tally and repeatedly eliminate // minimum vote candidates until either a winner is found or an // all-way-tie occurs. Prints the results of each round of vote // calculation. // // The vote file should be specified on the command line in runs like this: // // $> java Election votes-standard.txt // // If no, vote file is specified, main() should print a usage // message message: // // $> java Election // usage: java Election <votes.txt> // // and return immediately. }
6.2 Implementation of Election
6.2.1 main() Method and command line arguments
The main()
method should accept a command line argument which is the
name of a vote file. Several of these are provided as sample
data. This allows one to run the election program on the command line
or in DrJava's interactions pane on different vote results.
> java Election votes-standard.txt ... > java Election votes-2waytie.txt ... > java Election votes-many.txt ...
6.2.2 Algorithm for Running election
The main algorithm for running the entire election shoudl run something like the following.
read TALLY from given file read VOTES[] from the given file report how many votes have been read loop while no winner/tie has been found { print the round number (starting with round 1), remaining candidates, and TALLY count all the votes for TALLY and get its TRANSCRIPT print the TRANSCRIPT check for a winner: print and finish if there is one check for a tie: print and finish if there is one determine the minimum vote candidates and eliminate them to create a new TALLY increase the voting round and repeat }
Study the sample sessions below to determine the approximate format for the output.
6.3 Election Class Manual Instances Criteria grading
Wgt | Criteria |
---|---|
2% | Good style, indentation, and variable name choices are used. The Camel case naming convention is used. Code is properly indented |
3% | Brief but sufficient comments are supplied to indicate what is happening. Comments that appear in the specification do not count. |
5% | The flow of control is clear as to which part of the election is being performed at each step. |
10% | Total weight for these criteria |
6.4 Sample Session
> java Election votes-standard.txt votes-standard.txt : 12 votes read Round 1 : 4 candidates Tally{Francis:0, Claire:0, Heather:0, Viktor:0} Transcript: 0 : Francis Vote{Francis, Viktor, Heather, Claire} Tally{Francis:1, Claire:0, Heather:0, Viktor:0} 1 : Claire Vote{Claire, Francis, Heather, Viktor} Tally{Francis:1, Claire:1, Heather:0, Viktor:0} 2 : Heather Vote{Heather, Claire, Francis, Viktor} Tally{Francis:1, Claire:1, Heather:1, Viktor:0} 3 : Heather Vote{Heather, Claire, Francis, Viktor} Tally{Francis:1, Claire:1, Heather:2, Viktor:0} 4 : Claire Vote{Claire, Francis, Heather, Viktor} Tally{Francis:1, Claire:2, Heather:2, Viktor:0} 5 : Francis Vote{Francis, Heather, Claire, Viktor} Tally{Francis:2, Claire:2, Heather:2, Viktor:0} 6 : Francis Vote{Francis, Claire, Heather, Viktor} Tally{Francis:3, Claire:2, Heather:2, Viktor:0} 7 : Heather Vote{Heather, Claire, Francis, Viktor} Tally{Francis:3, Claire:2, Heather:3, Viktor:0} 8 : Heather Vote{Heather, Francis, Claire, Viktor} Tally{Francis:3, Claire:2, Heather:4, Viktor:0} 9 : Viktor Vote{Viktor, Francis, Heather, Claire} Tally{Francis:3, Claire:2, Heather:4, Viktor:1} 10 : Francis Vote{Francis, Claire, Heather, Viktor} Tally{Francis:4, Claire:2, Heather:4, Viktor:1} 11 : Heather Vote{Heather, Francis, Claire, Viktor} Tally{Francis:4, Claire:2, Heather:5, Viktor:1} CNT % NAME 4 33.3 Francis 2 16.7 Claire 5 41.7 Heather 1 8.3 Viktor 1 minimum vote candidates Eliminating: Viktor Round 2 : 3 candidates Tally{Francis:0, Claire:0, Heather:0} Transcript: 0 : Francis Vote{Francis, Viktor, Heather, Claire} Tally{Francis:1, Claire:0, Heather:0} 1 : Claire Vote{Claire, Francis, Heather, Viktor} Tally{Francis:1, Claire:1, Heather:0} 2 : Heather Vote{Heather, Claire, Francis, Viktor} Tally{Francis:1, Claire:1, Heather:1} 3 : Heather Vote{Heather, Claire, Francis, Viktor} Tally{Francis:1, Claire:1, Heather:2} 4 : Claire Vote{Claire, Francis, Heather, Viktor} Tally{Francis:1, Claire:2, Heather:2} 5 : Francis Vote{Francis, Heather, Claire, Viktor} Tally{Francis:2, Claire:2, Heather:2} 6 : Francis Vote{Francis, Claire, Heather, Viktor} Tally{Francis:3, Claire:2, Heather:2} 7 : Heather Vote{Heather, Claire, Francis, Viktor} Tally{Francis:3, Claire:2, Heather:3} 8 : Heather Vote{Heather, Francis, Claire, Viktor} Tally{Francis:3, Claire:2, Heather:4} 9 : Francis Vote{Viktor, Francis, Heather, Claire} Tally{Francis:4, Claire:2, Heather:4} 10 : Francis Vote{Francis, Claire, Heather, Viktor} Tally{Francis:5, Claire:2, Heather:4} 11 : Heather Vote{Heather, Francis, Claire, Viktor} Tally{Francis:5, Claire:2, Heather:5} CNT % NAME 5 41.7 Francis 2 16.7 Claire 5 41.7 Heather 1 minimum vote candidates Eliminating: Claire Round 3 : 2 candidates Tally{Francis:0, Heather:0} Transcript: 0 : Francis Vote{Francis, Viktor, Heather, Claire} Tally{Francis:1, Heather:0} 1 : Francis Vote{Claire, Francis, Heather, Viktor} Tally{Francis:2, Heather:0} 2 : Heather Vote{Heather, Claire, Francis, Viktor} Tally{Francis:2, Heather:1} 3 : Heather Vote{Heather, Claire, Francis, Viktor} Tally{Francis:2, Heather:2} 4 : Francis Vote{Claire, Francis, Heather, Viktor} Tally{Francis:3, Heather:2} 5 : Francis Vote{Francis, Heather, Claire, Viktor} Tally{Francis:4, Heather:2} 6 : Francis Vote{Francis, Claire, Heather, Viktor} Tally{Francis:5, Heather:2} 7 : Heather Vote{Heather, Claire, Francis, Viktor} Tally{Francis:5, Heather:3} 8 : Heather Vote{Heather, Francis, Claire, Viktor} Tally{Francis:5, Heather:4} 9 : Francis Vote{Viktor, Francis, Heather, Claire} Tally{Francis:6, Heather:4} 10 : Francis Vote{Francis, Claire, Heather, Viktor} Tally{Francis:7, Heather:4} 11 : Heather Vote{Heather, Francis, Claire, Viktor} Tally{Francis:7, Heather:5} CNT % NAME 7 58.3 Francis 5 41.7 Heather WINNER: Francis > java Election votes-1round.txt votes-1round.txt : 7 votes read Round 1 : 4 candidates Tally{Francis:0, Claire:0, Heather:0, Viktor:0} Transcript: 0 : Francis Vote{Francis, Claire, Heather, Viktor} Tally{Francis:1, Claire:0, Heather:0, Viktor:0} 1 : Francis Vote{Francis, Claire, Heather, Viktor} Tally{Francis:2, Claire:0, Heather:0, Viktor:0} 2 : Francis Vote{Francis, Claire, Heather, Viktor} Tally{Francis:3, Claire:0, Heather:0, Viktor:0} 3 : Francis Vote{Francis, Claire, Heather, Viktor} Tally{Francis:4, Claire:0, Heather:0, Viktor:0} 4 : Viktor Vote{Viktor, Heather, Claire, Francis} Tally{Francis:4, Claire:0, Heather:0, Viktor:1} 5 : Viktor Vote{Viktor, Heather, Claire, Francis} Tally{Francis:4, Claire:0, Heather:0, Viktor:2} 6 : Claire Vote{Claire, Heather, Viktor, Francis} Tally{Francis:4, Claire:1, Heather:0, Viktor:2} CNT % NAME 4 57.1 Francis 1 14.3 Claire 0 0.0 Heather 2 28.6 Viktor WINNER: Francis > java Election votes-2waytie.txt votes-2waytie.txt : 6 votes read Round 1 : 4 candidates Tally{Francis:0, Claire:0, Heather:0, Viktor:0} Transcript: 0 : Viktor Vote{Viktor, Heather, Claire, Francis} Tally{Francis:0, Claire:0, Heather:0, Viktor:1} 1 : Viktor Vote{Viktor, Heather, Claire, Francis} Tally{Francis:0, Claire:0, Heather:0, Viktor:2} 2 : Viktor Vote{Viktor, Heather, Claire, Francis} Tally{Francis:0, Claire:0, Heather:0, Viktor:3} 3 : Claire Vote{Claire, Heather, Viktor, Francis} Tally{Francis:0, Claire:1, Heather:0, Viktor:3} 4 : Claire Vote{Claire, Heather, Viktor, Francis} Tally{Francis:0, Claire:2, Heather:0, Viktor:3} 5 : Claire Vote{Claire, Heather, Viktor, Francis} Tally{Francis:0, Claire:3, Heather:0, Viktor:3} CNT % NAME 0 0.0 Francis 3 50.0 Claire 0 0.0 Heather 3 50.0 Viktor 2 minimum vote candidates Eliminating: Francis Eliminating: Heather Round 2 : 2 candidates Tally{Claire:0, Viktor:0} Transcript: 0 : Viktor Vote{Viktor, Heather, Claire, Francis} Tally{Claire:0, Viktor:1} 1 : Viktor Vote{Viktor, Heather, Claire, Francis} Tally{Claire:0, Viktor:2} 2 : Viktor Vote{Viktor, Heather, Claire, Francis} Tally{Claire:0, Viktor:3} 3 : Claire Vote{Claire, Heather, Viktor, Francis} Tally{Claire:1, Viktor:3} 4 : Claire Vote{Claire, Heather, Viktor, Francis} Tally{Claire:2, Viktor:3} 5 : Claire Vote{Claire, Heather, Viktor, Francis} Tally{Claire:3, Viktor:3} CNT % NAME 3 50.0 Claire 3 50.0 Viktor ALL WAY TIE BETWEEN: Claire Viktor > java Election votes-drop2.txt votes-drop2.txt : 7 votes read Round 1 : 4 candidates Tally{Francis:0, Claire:0, Heather:0, Viktor:0} Transcript: 0 : Francis Vote{Francis, Claire, Heather, Viktor} Tally{Francis:1, Claire:0, Heather:0, Viktor:0} 1 : Francis Vote{Francis, Claire, Heather, Viktor} Tally{Francis:2, Claire:0, Heather:0, Viktor:0} 2 : Francis Vote{Francis, Claire, Heather, Viktor} Tally{Francis:3, Claire:0, Heather:0, Viktor:0} 3 : Viktor Vote{Viktor, Heather, Claire, Francis} Tally{Francis:3, Claire:0, Heather:0, Viktor:1} 4 : Viktor Vote{Viktor, Heather, Claire, Francis} Tally{Francis:3, Claire:0, Heather:0, Viktor:2} 5 : Heather Vote{Heather, Viktor, Claire, Francis} Tally{Francis:3, Claire:0, Heather:1, Viktor:2} 6 : Heather Vote{Heather, Viktor, Claire, Francis} Tally{Francis:3, Claire:0, Heather:2, Viktor:2} CNT % NAME 3 42.9 Francis 0 0.0 Claire 2 28.6 Heather 2 28.6 Viktor 1 minimum vote candidates Eliminating: Claire Round 2 : 3 candidates Tally{Francis:0, Heather:0, Viktor:0} Transcript: 0 : Francis Vote{Francis, Claire, Heather, Viktor} Tally{Francis:1, Heather:0, Viktor:0} 1 : Francis Vote{Francis, Claire, Heather, Viktor} Tally{Francis:2, Heather:0, Viktor:0} 2 : Francis Vote{Francis, Claire, Heather, Viktor} Tally{Francis:3, Heather:0, Viktor:0} 3 : Viktor Vote{Viktor, Heather, Claire, Francis} Tally{Francis:3, Heather:0, Viktor:1} 4 : Viktor Vote{Viktor, Heather, Claire, Francis} Tally{Francis:3, Heather:0, Viktor:2} 5 : Heather Vote{Heather, Viktor, Claire, Francis} Tally{Francis:3, Heather:1, Viktor:2} 6 : Heather Vote{Heather, Viktor, Claire, Francis} Tally{Francis:3, Heather:2, Viktor:2} CNT % NAME 3 42.9 Francis 2 28.6 Heather 2 28.6 Viktor 2 minimum vote candidates Eliminating: Heather Eliminating: Viktor Round 3 : 1 candidates Tally{Francis:0} Transcript: 0 : Francis Vote{Francis, Claire, Heather, Viktor} Tally{Francis:1} 1 : Francis Vote{Francis, Claire, Heather, Viktor} Tally{Francis:2} 2 : Francis Vote{Francis, Claire, Heather, Viktor} Tally{Francis:3} 3 : Francis Vote{Viktor, Heather, Claire, Francis} Tally{Francis:4} 4 : Francis Vote{Viktor, Heather, Claire, Francis} Tally{Francis:5} 5 : Francis Vote{Heather, Viktor, Claire, Francis} Tally{Francis:6} 6 : Francis Vote{Heather, Viktor, Claire, Francis} Tally{Francis:7} CNT % NAME 7 100.0 Francis WINNER: Francis > java Election votes-many.txt votes-many.txt : 20 votes read Round 1 : 8 candidates Tally{A:0, B:0, C:0, D:0, E:0, F:0, G:0, H:0} Transcript: 0 : D Vote{D, G, B, A, E, C, F, H} Tally{A:0, B:0, C:0, D:1, E:0, F:0, G:0, H:0} 1 : H Vote{H, D, C, B, A, G, F, E} Tally{A:0, B:0, C:0, D:1, E:0, F:0, G:0, H:1} 2 : A Vote{A, E, G, C, H, B, F, D} Tally{A:1, B:0, C:0, D:1, E:0, F:0, G:0, H:1} 3 : E Vote{E, A, D, G, C, B, H, F} Tally{A:1, B:0, C:0, D:1, E:1, F:0, G:0, H:1} 4 : C Vote{C, F, A, B, E, H, D, G} Tally{A:1, B:0, C:1, D:1, E:1, F:0, G:0, H:1} 5 : H Vote{H, A, G, D, E, F, B, C} Tally{A:1, B:0, C:1, D:1, E:1, F:0, G:0, H:2} 6 : A Vote{A, F, D, E, B, H, C, G} Tally{A:2, B:0, C:1, D:1, E:1, F:0, G:0, H:2} 7 : D Vote{D, E, A, H, G, C, F, B} Tally{A:2, B:0, C:1, D:2, E:1, F:0, G:0, H:2} 8 : H Vote{H, F, C, D, B, A, E, G} Tally{A:2, B:0, C:1, D:2, E:1, F:0, G:0, H:3} 9 : B Vote{B, G, F, C, D, E, H, A} Tally{A:2, B:1, C:1, D:2, E:1, F:0, G:0, H:3} 10 : C Vote{C, A, D, H, B, F, G, E} Tally{A:2, B:1, C:2, D:2, E:1, F:0, G:0, H:3} 11 : C Vote{C, B, E, G, H, A, F, D} Tally{A:2, B:1, C:3, D:2, E:1, F:0, G:0, H:3} 12 : F Vote{F, A, E, D, B, G, C, H} Tally{A:2, B:1, C:3, D:2, E:1, F:1, G:0, H:3} 13 : E Vote{E, B, D, F, C, G, H, A} Tally{A:2, B:1, C:3, D:2, E:2, F:1, G:0, H:3} 14 : A Vote{A, B, D, E, G, F, H, C} Tally{A:3, B:1, C:3, D:2, E:2, F:1, G:0, H:3} 15 : H Vote{H, F, C, B, D, G, E, A} Tally{A:3, B:1, C:3, D:2, E:2, F:1, G:0, H:4} 16 : H Vote{H, F, B, D, C, A, G, E} Tally{A:3, B:1, C:3, D:2, E:2, F:1, G:0, H:5} 17 : D Vote{D, A, C, G, H, E, F, B} Tally{A:3, B:1, C:3, D:3, E:2, F:1, G:0, H:5} 18 : D Vote{D, G, H, E, B, A, C, F} Tally{A:3, B:1, C:3, D:4, E:2, F:1, G:0, H:5} 19 : E Vote{E, C, D, A, G, B, F, H} Tally{A:3, B:1, C:3, D:4, E:3, F:1, G:0, H:5} CNT % NAME 3 15.0 A 1 5.0 B 3 15.0 C 4 20.0 D 3 15.0 E 1 5.0 F 0 0.0 G 5 25.0 H 1 minimum vote candidates Eliminating: G Round 2 : 7 candidates Tally{A:0, B:0, C:0, D:0, E:0, F:0, H:0} Transcript: 0 : D Vote{D, G, B, A, E, C, F, H} Tally{A:0, B:0, C:0, D:1, E:0, F:0, H:0} 1 : H Vote{H, D, C, B, A, G, F, E} Tally{A:0, B:0, C:0, D:1, E:0, F:0, H:1} 2 : A Vote{A, E, G, C, H, B, F, D} Tally{A:1, B:0, C:0, D:1, E:0, F:0, H:1} 3 : E Vote{E, A, D, G, C, B, H, F} Tally{A:1, B:0, C:0, D:1, E:1, F:0, H:1} 4 : C Vote{C, F, A, B, E, H, D, G} Tally{A:1, B:0, C:1, D:1, E:1, F:0, H:1} 5 : H Vote{H, A, G, D, E, F, B, C} Tally{A:1, B:0, C:1, D:1, E:1, F:0, H:2} 6 : A Vote{A, F, D, E, B, H, C, G} Tally{A:2, B:0, C:1, D:1, E:1, F:0, H:2} 7 : D Vote{D, E, A, H, G, C, F, B} Tally{A:2, B:0, C:1, D:2, E:1, F:0, H:2} 8 : H Vote{H, F, C, D, B, A, E, G} Tally{A:2, B:0, C:1, D:2, E:1, F:0, H:3} 9 : B Vote{B, G, F, C, D, E, H, A} Tally{A:2, B:1, C:1, D:2, E:1, F:0, H:3} 10 : C Vote{C, A, D, H, B, F, G, E} Tally{A:2, B:1, C:2, D:2, E:1, F:0, H:3} 11 : C Vote{C, B, E, G, H, A, F, D} Tally{A:2, B:1, C:3, D:2, E:1, F:0, H:3} 12 : F Vote{F, A, E, D, B, G, C, H} Tally{A:2, B:1, C:3, D:2, E:1, F:1, H:3} 13 : E Vote{E, B, D, F, C, G, H, A} Tally{A:2, B:1, C:3, D:2, E:2, F:1, H:3} 14 : A Vote{A, B, D, E, G, F, H, C} Tally{A:3, B:1, C:3, D:2, E:2, F:1, H:3} 15 : H Vote{H, F, C, B, D, G, E, A} Tally{A:3, B:1, C:3, D:2, E:2, F:1, H:4} 16 : H Vote{H, F, B, D, C, A, G, E} Tally{A:3, B:1, C:3, D:2, E:2, F:1, H:5} 17 : D Vote{D, A, C, G, H, E, F, B} Tally{A:3, B:1, C:3, D:3, E:2, F:1, H:5} 18 : D Vote{D, G, H, E, B, A, C, F} Tally{A:3, B:1, C:3, D:4, E:2, F:1, H:5} 19 : E Vote{E, C, D, A, G, B, F, H} Tally{A:3, B:1, C:3, D:4, E:3, F:1, H:5} CNT % NAME 3 15.0 A 1 5.0 B 3 15.0 C 4 20.0 D 3 15.0 E 1 5.0 F 5 25.0 H 2 minimum vote candidates Eliminating: B Eliminating: F Round 3 : 5 candidates Tally{A:0, C:0, D:0, E:0, H:0} Transcript: 0 : D Vote{D, G, B, A, E, C, F, H} Tally{A:0, C:0, D:1, E:0, H:0} 1 : H Vote{H, D, C, B, A, G, F, E} Tally{A:0, C:0, D:1, E:0, H:1} 2 : A Vote{A, E, G, C, H, B, F, D} Tally{A:1, C:0, D:1, E:0, H:1} 3 : E Vote{E, A, D, G, C, B, H, F} Tally{A:1, C:0, D:1, E:1, H:1} 4 : C Vote{C, F, A, B, E, H, D, G} Tally{A:1, C:1, D:1, E:1, H:1} 5 : H Vote{H, A, G, D, E, F, B, C} Tally{A:1, C:1, D:1, E:1, H:2} 6 : A Vote{A, F, D, E, B, H, C, G} Tally{A:2, C:1, D:1, E:1, H:2} 7 : D Vote{D, E, A, H, G, C, F, B} Tally{A:2, C:1, D:2, E:1, H:2} 8 : H Vote{H, F, C, D, B, A, E, G} Tally{A:2, C:1, D:2, E:1, H:3} 9 : C Vote{B, G, F, C, D, E, H, A} Tally{A:2, C:2, D:2, E:1, H:3} 10 : C Vote{C, A, D, H, B, F, G, E} Tally{A:2, C:3, D:2, E:1, H:3} 11 : C Vote{C, B, E, G, H, A, F, D} Tally{A:2, C:4, D:2, E:1, H:3} 12 : A Vote{F, A, E, D, B, G, C, H} Tally{A:3, C:4, D:2, E:1, H:3} 13 : E Vote{E, B, D, F, C, G, H, A} Tally{A:3, C:4, D:2, E:2, H:3} 14 : A Vote{A, B, D, E, G, F, H, C} Tally{A:4, C:4, D:2, E:2, H:3} 15 : H Vote{H, F, C, B, D, G, E, A} Tally{A:4, C:4, D:2, E:2, H:4} 16 : H Vote{H, F, B, D, C, A, G, E} Tally{A:4, C:4, D:2, E:2, H:5} 17 : D Vote{D, A, C, G, H, E, F, B} Tally{A:4, C:4, D:3, E:2, H:5} 18 : D Vote{D, G, H, E, B, A, C, F} Tally{A:4, C:4, D:4, E:2, H:5} 19 : E Vote{E, C, D, A, G, B, F, H} Tally{A:4, C:4, D:4, E:3, H:5} CNT % NAME 4 20.0 A 4 20.0 C 4 20.0 D 3 15.0 E 5 25.0 H 1 minimum vote candidates Eliminating: E Round 4 : 4 candidates Tally{A:0, C:0, D:0, H:0} Transcript: 0 : D Vote{D, G, B, A, E, C, F, H} Tally{A:0, C:0, D:1, H:0} 1 : H Vote{H, D, C, B, A, G, F, E} Tally{A:0, C:0, D:1, H:1} 2 : A Vote{A, E, G, C, H, B, F, D} Tally{A:1, C:0, D:1, H:1} 3 : A Vote{E, A, D, G, C, B, H, F} Tally{A:2, C:0, D:1, H:1} 4 : C Vote{C, F, A, B, E, H, D, G} Tally{A:2, C:1, D:1, H:1} 5 : H Vote{H, A, G, D, E, F, B, C} Tally{A:2, C:1, D:1, H:2} 6 : A Vote{A, F, D, E, B, H, C, G} Tally{A:3, C:1, D:1, H:2} 7 : D Vote{D, E, A, H, G, C, F, B} Tally{A:3, C:1, D:2, H:2} 8 : H Vote{H, F, C, D, B, A, E, G} Tally{A:3, C:1, D:2, H:3} 9 : C Vote{B, G, F, C, D, E, H, A} Tally{A:3, C:2, D:2, H:3} 10 : C Vote{C, A, D, H, B, F, G, E} Tally{A:3, C:3, D:2, H:3} 11 : C Vote{C, B, E, G, H, A, F, D} Tally{A:3, C:4, D:2, H:3} 12 : A Vote{F, A, E, D, B, G, C, H} Tally{A:4, C:4, D:2, H:3} 13 : D Vote{E, B, D, F, C, G, H, A} Tally{A:4, C:4, D:3, H:3} 14 : A Vote{A, B, D, E, G, F, H, C} Tally{A:5, C:4, D:3, H:3} 15 : H Vote{H, F, C, B, D, G, E, A} Tally{A:5, C:4, D:3, H:4} 16 : H Vote{H, F, B, D, C, A, G, E} Tally{A:5, C:4, D:3, H:5} 17 : D Vote{D, A, C, G, H, E, F, B} Tally{A:5, C:4, D:4, H:5} 18 : D Vote{D, G, H, E, B, A, C, F} Tally{A:5, C:4, D:5, H:5} 19 : C Vote{E, C, D, A, G, B, F, H} Tally{A:5, C:5, D:5, H:5} CNT % NAME 5 25.0 A 5 25.0 C 5 25.0 D 5 25.0 H ALL WAY TIE BETWEEN: A C D H
7 Automatic Testing (50%) grading
7.1 Running Tests
Run the tests associated with the project and ensure all of them
pass. This can be done in DrJava by pressing the Test
button when
test files are open.
On the command line you can run all tests with the following commands.
On Unix/Mac platforms, use a terminal to run the following commands in the folder where your code exists.
> javac -cp .:junit-1103.jar KTests.java #compile > java -cp .:junit-1103.jar KTests #run tests
On windows, use cmd.exe
and change to the correct directory. Run the
commands below where which use a semicolon (;) rather than a colon (:).
> javac -cp .;junit-1103.jar KTests.java #compile > java -cp .;junit-1103.jar KTests #run tests
Correctly passing all tests will yield output similar to the following.
JUnit version 4.12 .......... Time: 0.024 OK (10 tests)
Failing some tests will yield long messages which hint at where there might be a problem. Failures always end with the number of tests passed/failed as in the following.
FAILURES!!! Tests run: 10, Failures: 5
7.2 Test Grading Policies
Some policies to keep in mind with respect to how automatic tests affect grades.
- Credit on this section is proportional to the number of tests passed.
- If there were 30 total tests for the project…
- Passing 30 / 30 tests gets
30 / 30 * 50 = 50.00
- Passing 15 / 30 tests gets
15 / 30 * 50 = 25.00
- Passing 4 / 30 tests gets
4 / 30 * 50 = 6.67
- A 5% penalty may be deducted from this portion if code does not compile initially but a grader is able to quickly fix the problem.
- Passing no tests because code does not compile or does not work properly gets 0 credit.
8 Zip and Submit
8.1 Submit to Canvas
Once your are confident your code is working, you are ready to submit. Ensure your folder has all of the required files. Create a zip archive of your lab folder and submit it to blackboard.
On Canvas:
- Click on the Assignments section
- Click on the appropriate link for this lab
- Scroll down to "Attach a File"
- Click "Browse My Computer"
- Select you Zip file and press OK
8.2 Late Policies
You may wish to review the policy on late project submission which will cost you late tokens to submit late or credit if you run out of tokens. No projects will be accepted more than 48 hours after the deadline.
http://www-users.cs.umn.edu/~kauffman/1103/syllabus.html#late-projects