Swiss pairing mechanism is finished and working brilliantly!

This commit is contained in:
marcins78@gmail.com
2013-01-03 01:34:02 +00:00
parent 2848fccd32
commit 368a60ca45
3 changed files with 205 additions and 17 deletions

View File

@@ -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;
}

View File

@@ -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));
}
}

View File

@@ -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;
}
}