1. /**
  2.  * Captures the idea of the ballot paper completed by one voter.
  3.  */
  4. public class BallotPaper {
  5.  
  6. /**
  7.   * Holds the preferences of this voter.
  8.   */
  9. private Map<Integer, Candidate> preferences;
  10.  
  11. /**
  12.   * Keeps track of the highest preference
  13.   */
  14. private int highestPreference;
  15.  
  16. /**
  17.   * The default constructor, initialises the ballot paper.
  18.   */
  19. public BallotPaper() {
  20. preferences = new ArrayBasedMap<Integer, Candidate>();
  21. highestPreference = 0;
  22. }
  23.  
  24. /**
  25.   * Set the {@code preference}-th preference for candidate
  26.   * {@code candidate}.
  27.   */
  28. public void setPreference( int preference, Candidate candidate ) {
  29. if ( preference > 0 ) {
  30. highestPreference =
  31. Math.max( preference, highestPreference );
  32. preferences.put( preference, candidate );
  33. } else {
  34. System.out.println( "Illegal preference: You must give a"
  35. + " preference of at least 1." );
  36. }
  37. }
  38.  
  39. /**
  40.   * Gets the candidate corresponding to a particular voter's
  41.   * preference.
  42.   */
  43. public Candidate getPreference( int preference ) {
  44. return preferences.get( preference );
  45. }
  46.  
  47. /**
  48.   * Determines whether this ballot paper is valid.
  49.   *
  50.   * <p>A {@code BallotPaper} is valid if the highest preference is
  51.   * equal to the number of candidates that have been voted for, and
  52.   * the number of candidates that have been voted for are equal to
  53.   * the number of candidates that are running.</p>
  54.   */
  55. public boolean isValidBallot( int numCandidates ) {
  56. return (preferences.size() - 1) == highestPreference
  57. && (preferences.size() - 1) == numCandidates;
  58. }
  59. }
  60.  
  61. /**
  62.  * Records the details of an individual candidate (name and party).
  63.  */
  64. public class Candidate {
  65.  
  66. /**
  67.   * The candidate's name.
  68.   */
  69. private String name;
  70.  
  71. /**
  72.   * The candidate's party.
  73.   */
  74. private String party;
  75.  
  76. /**
  77.   * The default constructor.
  78.   */
  79. public Candidate() {
  80. name = "";
  81. party = "";
  82. }
  83.  
  84. /**
  85.   * Sets the value of {@code name}.
  86.   *
  87.   * @param name the new value of {@code name}.
  88.   */
  89. public void setName( String name ) {
  90. this.name = name;
  91. }
  92.  
  93. /**
  94.   * Returns the value of {@code name}.
  95.   *
  96.   * @return the value of {@code name}.
  97.   */
  98. public String getName() {
  99. return name;
  100. }
  101.  
  102. /**
  103.   * Sets the value of {@code party}.
  104.   *
  105.   * @param party the new value of {@code party}.
  106.   */
  107. public void setParty( String party ) {
  108. this.party = party;
  109. }
  110.  
  111. /**
  112.   * Returns the value of {@code party}.
  113.   *
  114.   * @return the value of {@code party}.
  115.   */
  116. public String getParty() {
  117. return party;
  118. }
  119. }
  120.  
  121. public class VoteCounter {
  122.  
  123. private Map<Candidate, List<BallotPaper>> votes;
  124.  
  125. private final int numCandidates;
  126.  
  127. public VoteCounter( List<Candidate> candidates ) {
  128. votes = ArrayBasedMap<Candidate, List<BallotPaper>>();
  129.  
  130. // Associate a list of ballot papers with each candidate
  131. for ( Candidate candidate : candidates ) {
  132. votes.put( candidate, new ArrayBasedList<BallotPaper>() );
  133. }
  134.  
  135. numCandidates = votes.size();
  136. }
  137.  
  138. /**
  139.   * Determine the outcome of the election based on the votes in
  140.   * {@code votesCast}.
  141.   *
  142.   * <p>Return the winning candidate.</p>
  143.   *
  144.   * @param votesCast the completed ballot papers.
  145.   * @return the winning candidate.
  146.   */
  147. public Candidate determineResult( List<BallotPaper> votesCast ) {
  148. int candidatesLeft = numCandidates;
  149. int lowestVotes;
  150. Candidate lowestScorer;
  151.  
  152. while ( candidatesLeft > 1 ) {
  153. for ( BallotPaper vote : votesCast ) {
  154. // Return candidate with currently highest preference
  155. final Candidate c = vote.get( candidatesLeft - 1 );
  156. final List<BallotPaper> vs = votes.get( c );
  157. vs.add( vote );
  158. }
  159. }
  160. }
  161. }
  162.  
  163. /**
  164.  * A unit testing suite for the {@code VoteCounter} class.
  165.  */
  166. public class VoteCounterTest {
  167.  
  168. public static void main( String[] args ) {
  169. List<Candidate> candidates = new ArrayBasedList<Candidate>();
  170.  
  171. candidates.add( new Candidate() );
  172. candidates.get( 0 ).setName( "John" );
  173. candidates.get( 0 ).setParty( "FF" );
  174.  
  175.  
  176.  
  177. List<BallotPaper> votes = new ArrayBasedList<BallotPaper>();
  178.  
  179. votes.add( new BallotPaper() );
  180. votes.get( 0 ).setPreference( 1, candidates.get( 0 ) );
  181.  
  182. votes.add( new BallotPaper() );
  183. votes.get( 1 ).setPreference( 1, candidates.get( 0 ) );
  184.  
  185.  
  186.  
  187. VoteCounter counter = new VoteCounter( candidates );
  188. Candidate winner = counter.determineResult( votes );
  189. System.out.println( winner.getName() );
  190. }
  191. }