Skip to content

Commit 6b37ee1

Browse files
committed
Reduce amount of info needed by MatchResult construction.
Also: - Various minor API changes - Additional testing - Bug fixes for multi-stage tournaments - Update version number
1 parent 4e8ee50 commit 6b37ee1

17 files changed

+334
-77
lines changed

publish.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ apply plugin: 'signing'
55
// Derived from instructions on the Central Repository site:
66
// http://central.sonatype.org/pages/gradle.html
77
group = "net.alloyggp"
8-
version = "0.0.4"
8+
version = "0.0.5"
99
task javadocJar(type: Jar) {
1010
classifier = 'javadoc'
1111
from javadoc

src/main/java/net/alloyggp/tournament/api/MatchResult.java

Lines changed: 38 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -10,35 +10,41 @@
1010

1111
@Immutable
1212
public class MatchResult {
13-
private final MatchSetup setup;
13+
private final String matchId;
14+
//TODO: Eliminate this. This may require significant refactoring of the
15+
//SingleEliminationFormatRunner.
16+
private final ImmutableList<Player> players;
1417
private final Outcome outcome;
1518
private final Optional<ImmutableList<Integer>> goals;
1619

17-
private MatchResult(MatchSetup setup, Outcome outcome, Optional<ImmutableList<Integer>> goals) {
20+
private MatchResult(String matchId, ImmutableList<Player> players,
21+
Outcome outcome, Optional<ImmutableList<Integer>> goals) {
1822
if (outcome == Outcome.COMPLETED) {
1923
Preconditions.checkArgument(goals.isPresent());
2024
}
2125
if (goals.isPresent()) {
22-
Preconditions.checkArgument(goals.get().size() == setup.getPlayers().size());
2326
for (int goal : goals.get()) {
2427
Preconditions.checkArgument(goal >= 0 && goal <= 100);
2528
}
2629
}
27-
this.setup = setup;
30+
this.matchId = matchId;
31+
this.players = players;
2832
this.outcome = outcome;
2933
this.goals = goals;
3034
}
3135

32-
public static MatchResult getAbortedMatchResult(MatchSetup setup) {
33-
return new MatchResult(setup, Outcome.ABORTED, Optional.absent());
36+
public static MatchResult getAbortedMatchResult(String matchId, List<Player> players) {
37+
return new MatchResult(matchId, ImmutableList.copyOf(players),
38+
Outcome.ABORTED, Optional.absent());
3439
}
3540

36-
public static MatchResult getSuccessfulMatchResult(MatchSetup setup, List<Integer> goals) {
37-
return new MatchResult(setup, Outcome.COMPLETED, Optional.of(ImmutableList.copyOf(goals)));
41+
public static MatchResult getSuccessfulMatchResult(String matchId, List<Player> players, List<Integer> goals) {
42+
return new MatchResult(matchId, ImmutableList.copyOf(players),
43+
Outcome.COMPLETED, Optional.of(ImmutableList.copyOf(goals)));
3844
}
3945

40-
public MatchSetup getSetup() {
41-
return setup;
46+
public String getMatchId() {
47+
return matchId;
4248
}
4349

4450
public Outcome getOutcome() {
@@ -49,13 +55,22 @@ public List<Integer> getGoals() {
4955
return goals.get();
5056
}
5157

58+
public ImmutableList<Player> getPlayers() {
59+
return players;
60+
}
61+
62+
public boolean wasAborted() {
63+
return outcome == Outcome.ABORTED;
64+
}
65+
5266
@Override
5367
public int hashCode() {
5468
final int prime = 31;
5569
int result = 1;
5670
result = prime * result + ((goals == null) ? 0 : goals.hashCode());
71+
result = prime * result + ((matchId == null) ? 0 : matchId.hashCode());
5772
result = prime * result + ((outcome == null) ? 0 : outcome.hashCode());
58-
result = prime * result + ((setup == null) ? 0 : setup.hashCode());
73+
result = prime * result + ((players == null) ? 0 : players.hashCode());
5974
return result;
6075
}
6176

@@ -78,22 +93,30 @@ public boolean equals(Object obj) {
7893
} else if (!goals.equals(other.goals)) {
7994
return false;
8095
}
96+
if (matchId == null) {
97+
if (other.matchId != null) {
98+
return false;
99+
}
100+
} else if (!matchId.equals(other.matchId)) {
101+
return false;
102+
}
81103
if (outcome != other.outcome) {
82104
return false;
83105
}
84-
if (setup == null) {
85-
if (other.setup != null) {
106+
if (players == null) {
107+
if (other.players != null) {
86108
return false;
87109
}
88-
} else if (!setup.equals(other.setup)) {
110+
} else if (!players.equals(other.players)) {
89111
return false;
90112
}
91113
return true;
92114
}
93115

94116
@Override
95117
public String toString() {
96-
return "MatchResult [setup=" + setup + ", outcome=" + outcome + ", goals=" + goals + "]";
118+
return "MatchResult [matchId=" + matchId + ", players=" + players + ", outcome=" + outcome + ", goals=" + goals
119+
+ "]";
97120
}
98121

99122
public static enum Outcome {

src/main/java/net/alloyggp/tournament/api/Seeding.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package net.alloyggp.tournament.api;
22

3+
import java.util.Collection;
34
import java.util.Collections;
45
import java.util.List;
56
import java.util.Random;
@@ -9,6 +10,7 @@
910

1011
import com.google.common.base.Splitter;
1112
import com.google.common.collect.ImmutableList;
13+
import com.google.common.collect.ImmutableSet;
1214
import com.google.common.collect.Lists;
1315

1416
@Immutable
@@ -25,8 +27,9 @@ private Seeding(ImmutableList<Player> playersBestFirst) {
2527
* <p>To support fuzz testing (and paranoid clients who want to use
2628
* secure RNGs), the source of randomness is explicitly provided.
2729
*/
28-
public static Seeding createRandomSeeding(Random random, List<Player> players) {
29-
List<Player> playersList = Lists.newArrayList(players);
30+
public static Seeding createRandomSeeding(Random random, Collection<Player> players) {
31+
//Uniquify the players, then put in a mutable list
32+
List<Player> playersList = Lists.newArrayList(ImmutableSet.copyOf(players));
3033
Collections.shuffle(playersList, random);
3134
return create(playersList);
3235
}

src/main/java/net/alloyggp/tournament/api/Tournament.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,12 @@ public interface Tournament {
1919
* This name is specified by the tournament designer, so it may be necessary
2020
* to screen out duplicate names.
2121
*/
22-
String getTournamentInternalName();
22+
String getInternalName();
2323

2424
/**
2525
* Returns a tournament name that is suitable for human-readable displays.
2626
*/
27-
String getTournamentDisplayName();
27+
String getDisplayName();
2828

2929
/**
3030
* Returns the set of matches that should be run in the given tournament state.

src/main/java/net/alloyggp/tournament/impl/MatchResults.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ private MatchResults() {
2323
public static Set<MatchResult> filterByStage(Collection<MatchResult> inputs, int stageNum) {
2424
return inputs.stream()
2525
.filter(result -> {
26-
String matchId = result.getSetup().getMatchId();
26+
String matchId = result.getMatchId();
2727
int matchStage = MatchIds.parseStageNumber(matchId);
2828
return matchStage == stageNum;
2929
})
@@ -37,7 +37,7 @@ public static Set<MatchResult> filterByStage(Collection<MatchResult> inputs, int
3737
public static Set<MatchResult> getResultsPriorToStage(Collection<MatchResult> inputs, int stageNum) {
3838
return inputs.stream()
3939
.filter(result -> {
40-
String matchId = result.getSetup().getMatchId();
40+
String matchId = result.getMatchId();
4141
int matchStage = MatchIds.parseStageNumber(matchId);
4242
return matchStage < stageNum;
4343
})
@@ -52,7 +52,7 @@ public static SetMultimap<Integer, MatchResult> mapByRound(Collection<MatchResul
5252
int stageNum) {
5353
SetMultimap<Integer, MatchResult> mapped = HashMultimap.create();
5454
for (MatchResult result : filterByStage(resultsSoFar, stageNum)) {
55-
String matchId = result.getSetup().getMatchId();
55+
String matchId = result.getMatchId();
5656
int matchRound = MatchIds.parseRoundNumber(matchId);
5757
mapped.put(matchRound, result);
5858
}

src/main/java/net/alloyggp/tournament/impl/SingleEliminationFormatRunner.java

Lines changed: 15 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -162,17 +162,18 @@ public void runNormalRound(List<Player> playersByPosition, int numRoundsLeft) {
162162

163163
public void runMatchesForPositions(List<Player> playersByPosition, int numRoundsLeft,
164164
RoundSpec round, int pairingNum, int position1, int position2) {
165+
Preconditions.checkArgument(position1 < position2);
165166
Player player1 = playersByPosition.get(position1);
166167
Player player2 = playersByPosition.get(position2);
167-
if (wonInRound(player1, numRoundsLeft, round)) {
168+
//TODO: Do we want to define roles according to seeding rather than bracket position?
169+
//If so, pass in seeding here
170+
if (wonInRound(player1, pairingNum, numRoundsLeft, round)) {
168171
playerEliminationRounds.put(player2, numRoundsLeft);
169-
} else if (wonInRound(player2, numRoundsLeft, round)) {
172+
} else if (wonInRound(player2, pairingNum, numRoundsLeft, round)) {
170173
playersByPosition.set(position1, player2);
171174
playersByPosition.set(position2, player1);
172175
playerEliminationRounds.put(player1, numRoundsLeft);
173176
} else {
174-
//TODO: Do we want to define roles according to seeding rather than bracket position?
175-
//If so, pass in seeding here
176177
matchesToReturn.add(getNextMatchForPairing(player1, player2, pairingNum, numRoundsLeft, round));
177178
}
178179
}
@@ -234,13 +235,11 @@ private MatchSetup getNextMatchForPairing(Player player1, Player player2,
234235
List<MatchResult> abortedSoFar = Lists.newArrayList();
235236
//First, gather all the non-abandoned results so far
236237
for (MatchResult result : resultsSoFarInStage) {
237-
//TODO: Replace with MatchIds logic?
238-
String matchId = result.getSetup().getMatchId();
239-
int roundNumber = MatchIds.parseRoundNumber(matchId);
240-
if (roundNumber != numRoundsLeft) {
238+
String matchId = result.getMatchId();
239+
if (numRoundsLeft != MatchIds.parseRoundNumber(matchId)) {
241240
continue;
242241
}
243-
if (!result.getSetup().getPlayers().contains(player1)) {
242+
if (pairingNum != MatchIds.parsePlayerMatchingNumber(matchId)) {
244243
continue;
245244
}
246245
if (result.getOutcome() == Outcome.ABORTED) {
@@ -266,7 +265,7 @@ private MatchSetup getNextMatchForPairing(Player player1, Player player2,
266265
}
267266
int priorMatchAttempts = 0;
268267
for (MatchResult result : abortedSoFar) {
269-
if (MatchIds.parseMatchNumber(result.getSetup().getMatchId()) == matchNum) {
268+
if (MatchIds.parseMatchNumber(result.getMatchId()) == matchNum) {
270269
priorMatchAttempts++;
271270
}
272271
}
@@ -283,7 +282,7 @@ private MatchSetup getNextMatchForPairing(Player player1, Player player2,
283282
private boolean haveCompleted(int matchNumber, List<MatchResult> completedSoFar) {
284283
for (MatchResult result : completedSoFar) {
285284
Preconditions.checkArgument(result.getOutcome() == Outcome.COMPLETED);
286-
String matchId = result.getSetup().getMatchId();
285+
String matchId = result.getMatchId();
287286
int resultMatchNumber = MatchIds.parseMatchNumber(matchId);
288287
if (matchNumber == resultMatchNumber) {
289288
return true;
@@ -292,24 +291,22 @@ private boolean haveCompleted(int matchNumber, List<MatchResult> completedSoFar)
292291
return false;
293292
}
294293

295-
private boolean wonInRound(Player player, int numRoundsLeft, RoundSpec round) {
294+
private boolean wonInRound(Player player, int pairingNumber, int numRoundsLeft, RoundSpec round) {
296295
int gamesPlayed = 0;
297296
int pointsAboveOpponent = 0;
298297
for (MatchResult result : resultsSoFarInStage) {
299-
//TODO: Replace with MatchIds logic?
300-
String matchId = result.getSetup().getMatchId();
301-
int roundNumber = MatchIds.parseRoundNumber(matchId);
302-
if (roundNumber != numRoundsLeft) {
298+
String matchId = result.getMatchId();
299+
if (numRoundsLeft != MatchIds.parseRoundNumber(matchId)) {
303300
continue;
304301
}
305-
if (!result.getSetup().getPlayers().contains(player)) {
302+
if (pairingNumber != MatchIds.parsePlayerMatchingNumber(matchId)) {
306303
continue;
307304
}
308305
if (result.getOutcome() == Outcome.ABORTED) {
309306
continue;
310307
}
311308
gamesPlayed++;
312-
int playerIndex = result.getSetup().getPlayers().indexOf(player);
309+
int playerIndex = result.getPlayers().indexOf(player);
313310
int playerPoints = result.getGoals().get(playerIndex);
314311
Preconditions.checkState(playerIndex == 0 || playerIndex == 1);
315312
int oppIndex = 1 - playerIndex;

src/main/java/net/alloyggp/tournament/impl/SwissFormat1Runner.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -451,7 +451,7 @@ private Optional<Integer> getAttemptNumberIfUnfinished(int groupNum, int matchNu
451451
Set<MatchResult> roundResults) {
452452
int attemptsSoFar = 0;
453453
for (MatchResult result : roundResults) {
454-
String matchId = result.getSetup().getMatchId();
454+
String matchId = result.getMatchId();
455455
if (groupNum == MatchIds.parsePlayerMatchingNumber(matchId)
456456
&& matchNum == MatchIds.parseMatchNumber(matchId)) {
457457
if (result.getOutcome() == Outcome.ABORTED) {
@@ -467,7 +467,7 @@ private Optional<Integer> getAttemptNumberIfUnfinished(int groupNum, int matchNu
467467
private MatchResult getSuccessfulAttempt(int groupNum, int matchNum, Set<MatchResult> roundResults) {
468468
for (MatchResult result : roundResults) {
469469
if (result.getOutcome() == Outcome.COMPLETED) {
470-
String matchId = result.getSetup().getMatchId();
470+
String matchId = result.getMatchId();
471471
if (groupNum == MatchIds.parsePlayerMatchingNumber(matchId)
472472
&& matchNum == MatchIds.parseMatchNumber(matchId)) {
473473
return result;

src/main/java/net/alloyggp/tournament/spec/StageFormat.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
import net.alloyggp.tournament.impl.SwissFormat1Runner;
1313

1414
public enum StageFormat {
15-
SINGLE_ELIMINATION("singleElimination",
15+
SINGLE_ELIMINATION("singleElimination1",
1616
() -> SingleEliminationFormatRunner.create()),
1717
SWISS1("swiss1",
1818
() -> SwissFormat1Runner.create()),

src/main/java/net/alloyggp/tournament/spec/StageSpec.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@
1212
import com.google.common.collect.Lists;
1313

1414
import net.alloyggp.tournament.api.Game;
15-
import net.alloyggp.tournament.api.NextMatchesResult;
1615
import net.alloyggp.tournament.api.MatchResult;
16+
import net.alloyggp.tournament.api.NextMatchesResult;
1717
import net.alloyggp.tournament.api.Ranking;
1818
import net.alloyggp.tournament.api.Seeding;
1919
import net.alloyggp.tournament.impl.FormatRunner;
@@ -96,6 +96,10 @@ public ImmutableList<RoundSpec> getRounds() {
9696
return rounds;
9797
}
9898

99+
public int getPlayerCutoff() {
100+
return playerCutoff;
101+
}
102+
99103
public List<Ranking> getStandingsHistory(String tournamentInternalName,
100104
Seeding initialSeeding, Set<MatchResult> resultsSoFar) {
101105
return format.getRunner().getStandingsHistory(tournamentInternalName, initialSeeding,

0 commit comments

Comments
 (0)