Swiss pairing mechanism is finished and working brilliantly!
This commit is contained in:
@@ -4,6 +4,8 @@ public class PairingMechanismRegistry {
|
||||
public PairingMechanism getPairingMechanism(String pairingType) {
|
||||
if (pairingType.equals("singleElimination"))
|
||||
return new SingleEliminationPairing();
|
||||
if (pairingType.equals("swiss"))
|
||||
return new SwissPairingMechanism();
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ public class SwissPairingMechanism implements PairingMechanism {
|
||||
|
||||
Set<String> playersWithByes = getPlayersWithByes(playerByes);
|
||||
|
||||
boolean success = tryPairBracketAndFurther(0, new HashSet<String>(), playersGroupedByBracket, playersWithByes, previouslyPaired, pairingResults, byeResults);
|
||||
boolean success = tryPairBracketAndFurther(0, new HashSet<String>(), new HashSet<String>(), playersGroupedByBracket, playersWithByes, previouslyPaired, pairingResults, byeResults);
|
||||
// Managed to pair with this carry over count - proceed with the pairings
|
||||
if (success)
|
||||
return false;
|
||||
@@ -40,21 +40,86 @@ public class SwissPairingMechanism implements PairingMechanism {
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean tryPairBracketAndFurther(int bracketIndex, Set<String> carryOverPlayers, List<List<String>> playersGroupedByBracket, Set<String> playersWithByes,
|
||||
private boolean tryPairBracketAndFurther(int bracketIndex, Set<String> carryOverPlayers, Set<String> carryOverFromThisBracket, List<List<String>> playersGroupedByBracket, Set<String> playersWithByes,
|
||||
Map<String, Set<String>> previouslyPaired, Map<String, String> pairingsResult, Set<String> byes) {
|
||||
for (int carryOverMax = 0; carryOverMax < 4; carryOverMax++) {
|
||||
boolean success = tryPairBracketWithCarryOverMax(bracketIndex, carryOverMax, playersGroupedByBracket, playersWithByes, previouslyPaired, pairingsResult, pairingsResult, byes);
|
||||
if (success)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
List<String> playersInBracket = playersGroupedByBracket.get(bracketIndex);
|
||||
|
||||
private boolean tryPairBracketWithCarryOverMax(int bracketIndex, int carryOverMax, List<List<String>> playersGroupedByPoints, Set<String> playersWithByes,
|
||||
Map<String, Set<String>> previouslyPaired, Map<String, String> pairingsResult,
|
||||
Map<String, String> pairingsResult1, Set<String> byes) {
|
||||
// TODO
|
||||
return true;
|
||||
// First try to pair carried over players
|
||||
while (carryOverPlayers.size() > 0) {
|
||||
String firstCarryOver = carryOverPlayers.iterator().next();
|
||||
carryOverPlayers.remove(firstCarryOver);
|
||||
|
||||
for (int index = 0; index < playersInBracket.size(); index++) {
|
||||
String player = playersInBracket.remove(index);
|
||||
if (!previouslyPaired.get(firstCarryOver).contains(player)) {
|
||||
// This might be a good pairing
|
||||
pairingsResult.put(firstCarryOver, player);
|
||||
// Lets give it a try
|
||||
boolean success = tryPairBracketAndFurther(bracketIndex, carryOverPlayers, carryOverFromThisBracket, playersGroupedByBracket, playersWithByes, previouslyPaired, pairingsResult, byes);
|
||||
if (success)
|
||||
return true;
|
||||
// Naah, it didn't work out
|
||||
pairingsResult.remove(firstCarryOver);
|
||||
}
|
||||
playersInBracket.add(index, player);
|
||||
}
|
||||
|
||||
carryOverFromThisBracket.add(firstCarryOver);
|
||||
}
|
||||
|
||||
if (playersInBracket.size() > 1) {
|
||||
// Pair whatever we manage within a bracket
|
||||
for (int index = 0; index < playersInBracket.size() - 1; index++) {
|
||||
String firstPlayer = playersInBracket.remove(index);
|
||||
for (int index2 = index; index2 < playersInBracket.size(); index2++) {
|
||||
String secondPlayer = playersInBracket.remove(index2);
|
||||
if (!previouslyPaired.get(firstPlayer).contains(secondPlayer)) {
|
||||
// This pairing might work
|
||||
pairingsResult.put(firstPlayer, secondPlayer);
|
||||
// Lets give it a try
|
||||
boolean success = tryPairBracketAndFurther(bracketIndex, Collections.<String>emptySet(), carryOverFromThisBracket, playersGroupedByBracket, playersWithByes, previouslyPaired, pairingsResult, byes);
|
||||
if (success)
|
||||
return true;
|
||||
// Naah, it didn't work out
|
||||
pairingsResult.remove(firstPlayer);
|
||||
}
|
||||
playersInBracket.add(index2, secondPlayer);
|
||||
}
|
||||
playersInBracket.add(index, firstPlayer);
|
||||
}
|
||||
}
|
||||
|
||||
// We have to go to next bracket
|
||||
if (bracketIndex+1 < playersGroupedByBracket.size()) {
|
||||
// Remaining players can't be paired within this bracket
|
||||
Set<String> carryOverForNextBracket = new HashSet<String>(carryOverFromThisBracket);
|
||||
carryOverForNextBracket.addAll(playersInBracket);
|
||||
|
||||
return tryPairBracketAndFurther(bracketIndex+1, carryOverForNextBracket, new HashSet<String>(), playersGroupedByBracket, playersWithByes, previouslyPaired, pairingsResult, byes);
|
||||
} else {
|
||||
// There is no more brackets left, whatever is left, has to get a bye
|
||||
Set<String> leftoverPlayers = new HashSet<String>(carryOverFromThisBracket);
|
||||
leftoverPlayers.addAll(playersInBracket);
|
||||
|
||||
// We only accept one bye
|
||||
int playersLeftWithoutPair = leftoverPlayers.size();
|
||||
switch(playersLeftWithoutPair) {
|
||||
case 0:
|
||||
return true;
|
||||
case 1: {
|
||||
String lastPlayer = leftoverPlayers.iterator().next();
|
||||
if (playersWithByes.contains(lastPlayer)) {
|
||||
// The last remaining player already has a bye
|
||||
return false;
|
||||
} else {
|
||||
byes.add(lastPlayer);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Set<String> getPlayersWithByes(Map<String, Integer> playerByes) {
|
||||
@@ -109,8 +174,8 @@ public class SwissPairingMechanism implements PairingMechanism {
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
for (int i = 1; i <= 128; i++) {
|
||||
System.out.println("i=" + i + " - " + getRoundCountBasedOnNumberOfPlayers(i));
|
||||
}
|
||||
System.out.println(getRoundCountBasedOnNumberOfPlayers(11));
|
||||
System.out.println(getRoundCountBasedOnNumberOfPlayers(9));
|
||||
System.out.println(getRoundCountBasedOnNumberOfPlayers(8));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,121 @@
|
||||
package com.gempukku.lotro.tournament;
|
||||
|
||||
import com.gempukku.lotro.competitive.PlayerStanding;
|
||||
import com.gempukku.lotro.competitive.StandingsProducer;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import static org.junit.Assert.*;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public class SwissPairingMechanismTest {
|
||||
@Test
|
||||
public void testPairingLargeTournament() {
|
||||
int repeatCount = 1;
|
||||
int playerCount = 4096;
|
||||
|
||||
for (int repeat = 0; repeat < repeatCount; repeat++) {
|
||||
testSwissPairingForPlayerCount(playerCount);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPairingSmallTournament() {
|
||||
int repeatCount = 10;
|
||||
int playerCount = 12;
|
||||
|
||||
for (int repeat = 0; repeat < repeatCount; repeat++) {
|
||||
testSwissPairingForPlayerCount(playerCount);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPairingVerySmallTournament() {
|
||||
int repeatCount = 10;
|
||||
int playerCount = 8;
|
||||
|
||||
for (int repeat = 0; repeat < repeatCount; repeat++) {
|
||||
testSwissPairingForPlayerCount(playerCount);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPairingSmallTournamentWithOddNumberOfPlayers() {
|
||||
int repeatCount = 10;
|
||||
int playerCount = 9;
|
||||
|
||||
for (int repeat = 0; repeat < repeatCount; repeat++) {
|
||||
testSwissPairingForPlayerCount(playerCount);
|
||||
}
|
||||
}
|
||||
|
||||
private void testSwissPairingForPlayerCount(int playerCount) {
|
||||
Set<String> players = new HashSet<String>();
|
||||
for (int i = 0; i < playerCount; i++)
|
||||
players.add("p" + i);
|
||||
|
||||
Set<String> droppedPlayers = new HashSet<String>();
|
||||
Map<String, Integer> byes = new HashMap<String, Integer>();
|
||||
|
||||
Set<TournamentMatch> matches = new HashSet<TournamentMatch>();
|
||||
Map<String, Set<String>> previouslyPaired = new HashMap<String, Set<String>>();
|
||||
for (String player : players)
|
||||
previouslyPaired.put(player, new HashSet<String>());
|
||||
|
||||
SwissPairingMechanism pairing = new SwissPairingMechanism();
|
||||
for (int i = 1; i < 20; i++) {
|
||||
if (!pairing.isFinished(i - 1, players, droppedPlayers)) {
|
||||
System.out.println("Pairing round " + i);
|
||||
List<PlayerStanding> standings = StandingsProducer.produceStandings(players, matches, 1, 0, byes);
|
||||
for (PlayerStanding standing : standings) {
|
||||
String player = standing.getPlayerName();
|
||||
log(player +" points - "+standing.getPoints() + " played against: "+ StringUtils.join(previouslyPaired.get(player), ","));
|
||||
}
|
||||
|
||||
Map<String, String> newPairings = new LinkedHashMap<String, String>();
|
||||
Set<String> newByes = new HashSet<String>();
|
||||
|
||||
assertFalse("Unable to pair for round " + i, pairing.pairPlayers(i, players, droppedPlayers, byes, standings, previouslyPaired, newPairings, newByes));
|
||||
assertEquals("Invalid number of pairings", playerCount / 2, newPairings.size());
|
||||
if (playerCount % 2 == 0)
|
||||
assertEquals("Invalid number of byes", 0, newByes.size());
|
||||
else {
|
||||
assertEquals("Invalid number of byes", 1, newByes.size());
|
||||
String newBye = newByes.iterator().next();
|
||||
log("Bye - " + newBye);
|
||||
assertNull("Player already received bye", byes.get(newBye));
|
||||
byes.put(newBye, 1);
|
||||
}
|
||||
|
||||
for (Map.Entry<String, String> newPairing : newPairings.entrySet()) {
|
||||
String playerOne = newPairing.getKey();
|
||||
String playerTwo = newPairing.getValue();
|
||||
|
||||
assertFalse(previouslyPaired.get(playerOne).contains(playerTwo));
|
||||
assertFalse(previouslyPaired.get(playerTwo).contains(playerOne));
|
||||
|
||||
System.out.println("Paired " + playerOne + " against " + playerTwo + " points - " + getPlayerPoints(standings, playerOne) + " vs " + getPlayerPoints(standings, playerTwo));
|
||||
String winner = new Random().nextBoolean() ? playerOne : playerTwo;
|
||||
log("Winner - "+winner);
|
||||
|
||||
previouslyPaired.get(playerOne).add(playerTwo);
|
||||
previouslyPaired.get(playerTwo).add(playerOne);
|
||||
|
||||
matches.add(new TournamentMatch(playerOne, playerTwo, winner, i));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void log(String s) {
|
||||
// System.out.println(s);
|
||||
}
|
||||
|
||||
private int getPlayerPoints(List<PlayerStanding> standings, String player) {
|
||||
for (PlayerStanding standing : standings) {
|
||||
if (standing.getPlayerName().equals(player))
|
||||
return standing.getPoints();
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user