Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 38 additions & 8 deletions src/App.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ private App() {
public static String[] sColumnHeadings;
public static PrintWriter sWriter;

public static void main(String[] args) throws IOException {
public static void main(String[] args) throws Exception {
System.out.println("Looking in " + System.getProperty("user.dir") + " for voteTallies.csv");
BufferedReader reader;

Expand All @@ -43,15 +43,15 @@ public static void main(String[] args) throws IOException {
|| heading.contains("Full Name")) {
continue;
}
String position = getElectionNameFromHeading(heading);// remove first/second/third
String election = getElectionNameFromHeading(heading);// remove first/second/third
sWriter.println("Found column " + heading);

if (!sAllVotes.containsKey(position)) {
sAllVotes.put(position, new TreeMap<>());
sWriter.println("Created election " + position);
if (position.contains("Captain")) {
sImportantElections.add(position);
sWriter.println("Important position " + position + " noted");
if (!sAllVotes.containsKey(election)) {
sAllVotes.put(election, new TreeMap<>());
sWriter.println("Created election " + election);
if (election.contains("Captain")) {
sImportantElections.add(election);
sWriter.println("Important election " + election + " noted");
}
}
}
Expand All @@ -70,6 +70,13 @@ public static void main(String[] args) throws IOException {
for (String importantName : sImportantElections) {
runElection(importantName);
System.out.println("Running election " + importantName);
if (sWinners.containsKey(importantName)) { // a winner has been found so they need to be removed from the
// list of eligible candidates
sAllVotes.keySet().forEach((electionName) -> {
deregisterCandidate(electionName, sWinners.get(importantName));
});

}
}

for (Map.Entry<String, TreeMap<String, ArrayList<Ballot>>> elections : sAllVotes.entrySet()) {
Expand Down Expand Up @@ -243,4 +250,27 @@ public static SimpleEntry<String, Integer> getCurrentLoser(String election) {
return new SimpleEntry<>(potentialCurrentLoser, potentialLoserVotes);
}

public static void registerCandidate(String electionName, String candidate) {
TreeMap<String, ArrayList<Ballot>> candidatesForThisElection = sAllVotes.get(electionName);
if (!candidatesForThisElection.containsKey(candidate)) {// candidate not in list for this election
candidatesForThisElection.put(candidate, new ArrayList<>());
}
}

public static void deregisterCandidate(String electionName, String candidate) throws Exception {
TreeMap<String, ArrayList<Ballot>> candidatesVotesForThisElection = sAllVotes.get(electionName);
if (candidatesVotesForThisElection.get(candidate).size() > 0) {
throw new Exception("Trying to deregister candidate " + candidate + " in election " + electionName
+ " but they have votes!");
}
}

public static boolean isCandidateAvailable(String electionName, String candidate) {
if (!App.sAllVotes.get(electionName).containsKey(candidate)) {
return false;
}

return true;
}

}
76 changes: 29 additions & 47 deletions src/Ballot.java
Original file line number Diff line number Diff line change
@@ -1,98 +1,80 @@
import java.io.IOException;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Queue;
import java.util.TreeMap;

public final class Ballot {
private TreeMap<String, ArrayList<String>> mVotes = new TreeMap<>();// ballotData
private TreeMap<String, Queue<String>> mVotes = new TreeMap<>();// ballotData
private int mBallotIndex;
private TreeMap<String, Integer> currentChoiceIdxs = new TreeMap<>();

public Ballot(String ballotLine, int idx) {
mBallotIndex = idx;
String[] voteNames = ballotLine.split(",");// chosenCandidates
if (voteNames.length != App.sColumnHeadings.length) {
String[] ballotEntries = ballotLine.split(",");// chosenCandidates
if (ballotEntries.length != App.sColumnHeadings.length) {
System.err.println("Length of ballot " + ballotLine + " doesn't match number of elections!");
System.exit(-1);
}
for (int columnIdx = 3; columnIdx < voteNames.length; columnIdx++) {// start at 3 to skip timestamp, email, name
for (int columnIdx = 3; columnIdx < ballotEntries.length; columnIdx++) {// start at 3 to skip timestamp, email,
// name
String thisColumnHeading = App.sColumnHeadings[columnIdx];// thisColumnString
String thisElection = App.getElectionNameFromHeading(thisColumnHeading);
String thisVote = voteNames[columnIdx];// chosenCandidate
String thisElectionName = App.getElectionNameFromHeading(thisColumnHeading);
String thisChoice = ballotEntries[columnIdx];// chosenCandidate

if (!mVotes.containsKey(thisElection)) {// no votes yet by this ballot for this election
mVotes.put(thisElection, new ArrayList<>());
if (!mVotes.containsKey(thisElectionName)) {// no votes yet by this ballot for this election
mVotes.put(thisElectionName, new LinkedList<>());
}

if (thisVote.length() > 0) {
TreeMap<String, ArrayList<Ballot>> candidatesForThisElection = App.sAllVotes.get(thisElection);
if (!candidatesForThisElection.containsKey(thisVote)) {// candidate not in list for this election
candidatesForThisElection.put(thisVote, new ArrayList<>());
}
ArrayList<String> thisBallotVotesForThisElection = mVotes.get(thisElection);
thisBallotVotesForThisElection.add(thisVote);// better be in order
if (thisChoice.length() > 0) {
App.registerCandidate(thisElectionName, thisChoice);
mVotes.get(thisElectionName).add(thisChoice);// ballot must have numbered choices in order (choice 1 in
// column D, 2 in E, etc.)
}
}
}

@Override
public String toString() {
StringBuilder rBuilder = new StringBuilder();
for (Map.Entry<String, ArrayList<String>> thisElectionChoices : mVotes.entrySet()) {
for (Map.Entry<String, Queue<String>> thisElectionChoices : mVotes.entrySet()) {
rBuilder.append("Election " + thisElectionChoices.getKey() + ":");
for (int i = 0; i < thisElectionChoices.getValue().size(); i++) {
rBuilder.append(" #" + i + "," + thisElectionChoices.getValue().get(i) + "; ");
List<String> listOfChoices = new ArrayList<>(thisElectionChoices.getValue());
for (int i = 0; i < listOfChoices.size(); i++) {
rBuilder.append(" #" + i + "," + listOfChoices.get(i) + "; ");
}
}
return (rBuilder.toString());
}

public boolean cast(String election) throws IOException {
if (!currentChoiceIdxs.containsKey(election)) {
currentChoiceIdxs.put(election, -1);
}
int choice = currentChoiceIdxs.get(election) + 1;

if (mVotes.get(election).size() <= choice) {
if (mVotes.get(election).size() == 0) {
App.sWriter.println(
"Ballot " + mBallotIndex + " thrown away for election " + election + ". Choice " + (choice + 1)
+ " not available.");
"Ballot " + mBallotIndex + " thrown away for election " + election
+ ". No more choices available.");
return false;
}

String thisBallotsChoice = mVotes.get(election).get(choice);
String thisBallotsChoice = mVotes.get(election).peek();

if (!App.sAllVotes.get(election).containsKey(thisBallotsChoice)) {
mVotes.get(election).remove(choice);
if (!App.isCandidateAvailable(election, thisBallotsChoice)) {
mVotes.get(election).poll(); // like pop
App.sWriter.println(
"Ballot " + mBallotIndex + " choice #" + (choice + 1)
+ " was already eliminated. Moving choices up 1.");
"Ballot " + mBallotIndex + " choice " + thisBallotsChoice
+ " is captain or has already been eliminated. Trying next choice.");
return cast(election); // now the choice should be valid
}

ArrayList<Ballot> thisCandidatesBallotList = App.sAllVotes.get(election).get(thisBallotsChoice);

for (String importantElection : App.sImportantElections) {
if (App.sWinners.containsKey(importantElection)) {
if (App.sWinners.get(importantElection).equals(thisBallotsChoice)) {
// this ballot's choice is for someone who already won captain
mVotes.get(election).remove(choice);
App.sWriter.println(
"Ballot " + mBallotIndex + " choice #" + (choice + 1) + " is captain. Moving choices up 1.");
return cast(election); // now the choice should be valid
}
}
}

if (thisCandidatesBallotList.contains(this)) {
System.err.println(
"Ballot " + mBallotIndex + " already voted for " + thisBallotsChoice + " in election " + election);
System.exit(-2);
}
thisCandidatesBallotList.add(this);
App.sWriter.println("Ballot " + mBallotIndex + " cast for " + thisBallotsChoice + ", choice #" + (choice + 1)
+ " in election " + election);
currentChoiceIdxs.put(election, choice);
App.sWriter.println("Ballot " + mBallotIndex + " cast for " + thisBallotsChoice + " in election " + election);

return true;
}
Expand Down