/**
* Captures the idea of the ballot paper completed by one voter.
*/
public class BallotPaper {
/**
* Holds the preferences of this voter.
*/
private Map<Integer, Candidate> preferences;
/**
* Keeps track of the highest preference
*/
private int highestPreference;
/**
* The default constructor, initialises the ballot paper.
*/
public BallotPaper() {
preferences = new ArrayBasedMap<Integer, Candidate>();
highestPreference = 0;
}
/**
* Set the {@code preference}-th preference for candidate
* {@code candidate}.
*/
public void setPreference( int preference, Candidate candidate ) {
if ( preference > 0 ) {
highestPreference =
Math.
max( preference, highestPreference
);
preferences.put( preference, candidate );
} else {
System.
out.
println( "Illegal preference: You must give a" + " preference of at least 1." );
}
}
/**
* Gets the candidate corresponding to a particular voter's
* preference.
*/
public Candidate getPreference( int preference ) {
return preferences.get( preference );
}
/**
* Determines whether this ballot paper is valid.
*
* <p>A {@code BallotPaper} is valid if the highest preference is
* equal to the number of candidates that have been voted for, and
* the number of candidates that have been voted for are equal to
* the number of candidates that are running.</p>
*/
public boolean isValidBallot( int numCandidates ) {
return (preferences.size() - 1) == highestPreference
&& (preferences.size() - 1) == numCandidates;
}
}
/**
* Records the details of an individual candidate (name and party).
*/
public class Candidate {
/**
* The candidate's name.
*/
/**
* The candidate's party.
*/
/**
* The default constructor.
*/
public Candidate() {
name = "";
party = "";
}
/**
* Sets the value of {@code name}.
*
* @param name the new value of {@code name}.
*/
public void setName
( String name
) { this.name = name;
}
/**
* Returns the value of {@code name}.
*
* @return the value of {@code name}.
*/
return name;
}
/**
* Sets the value of {@code party}.
*
* @param party the new value of {@code party}.
*/
public void setParty
( String party
) { this.party = party;
}
/**
* Returns the value of {@code party}.
*
* @return the value of {@code party}.
*/
return party;
}
}
public class VoteCounter {
private Map<Candidate, List<BallotPaper>> votes;
private final int numCandidates;
public VoteCounter( List<Candidate> candidates ) {
votes = ArrayBasedMap<Candidate, List<BallotPaper>>();
// Associate a list of ballot papers with each candidate
for ( Candidate candidate : candidates ) {
votes.put( candidate, new ArrayBasedList<BallotPaper>() );
}
numCandidates = votes.size();
}
/**
* Determine the outcome of the election based on the votes in
* {@code votesCast}.
*
* <p>Return the winning candidate.</p>
*
* @param votesCast the completed ballot papers.
* @return the winning candidate.
*/
public Candidate determineResult( List<BallotPaper> votesCast ) {
int candidatesLeft = numCandidates;
int lowestVotes;
Candidate lowestScorer;
while ( candidatesLeft > 1 ) {
for ( BallotPaper vote : votesCast ) {
// Return candidate with currently highest preference
final Candidate c = vote.get( candidatesLeft - 1 );
final List<BallotPaper> vs = votes.get( c );
vs.add( vote );
}
}
}
}
/**
* A unit testing suite for the {@code VoteCounter} class.
*/
public class VoteCounterTest {
public static void main
( String[] args
) { List<Candidate> candidates = new ArrayBasedList<Candidate>();
candidates.add( new Candidate() );
candidates.get( 0 ).setName( "John" );
candidates.get( 0 ).setParty( "FF" );
List<BallotPaper> votes = new ArrayBasedList<BallotPaper>();
votes.add( new BallotPaper() );
votes.get( 0 ).setPreference( 1, candidates.get( 0 ) );
votes.add( new BallotPaper() );
votes.get( 1 ).setPreference( 1, candidates.get( 0 ) );
VoteCounter counter = new VoteCounter( candidates );
Candidate winner = counter.determineResult( votes );
System.
out.
println( winner.
getName() );
}
}