diff --git a/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/tournament/DefaultTournament.java b/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/tournament/DefaultTournament.java index dc3c7f531..dc760447a 100644 --- a/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/tournament/DefaultTournament.java +++ b/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/tournament/DefaultTournament.java @@ -308,7 +308,10 @@ public class DefaultTournament implements Tournament { _tournamentService.updateTournamentRound(_tournamentId, _tournamentRound); Map pairingResults = new HashMap(); Set byeResults = new HashSet(); - boolean finished = _pairingMechanism.pairPlayers(_tournamentRound, _players, _droppedPlayers, _playerByes, getCurrentStandings(), pairingResults, byeResults); + + Map> previouslyPaired = getPreviouslyPairedPlayersMap(); + + boolean finished = _pairingMechanism.pairPlayers(_tournamentRound, _players, _droppedPlayers, _playerByes, getCurrentStandings(), previouslyPaired, pairingResults, byeResults); if (finished) { finishTournament(tournamentCallback, collectionsManager); } else { @@ -328,6 +331,18 @@ public class DefaultTournament implements Tournament { } } + private Map> getPreviouslyPairedPlayersMap() { + Map> previouslyPaired = new HashMap>(); + for (String player : _players) + previouslyPaired.put(player, new HashSet()); + + for (TournamentMatch finishedTournamentMatch : _finishedTournamentMatches) { + previouslyPaired.get(finishedTournamentMatch.getWinner()).add(finishedTournamentMatch.getLoser()); + previouslyPaired.get(finishedTournamentMatch.getLoser()).add(finishedTournamentMatch.getWinner()); + } + return previouslyPaired; + } + private void addPlayerBye(String player) { Integer byes = _playerByes.get(player); if (byes == null) diff --git a/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/tournament/PairingMechanism.java b/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/tournament/PairingMechanism.java index 0dd985dee..893f85ec6 100644 --- a/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/tournament/PairingMechanism.java +++ b/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/tournament/PairingMechanism.java @@ -11,7 +11,8 @@ public interface PairingMechanism { public boolean isFinished(int round, Set players, Set droppedPlayers); - public boolean pairPlayers(int round, Set players, Set droppedPlayers, Map playerByes, List currentStandings, Map pairingResults, Set byeResults); + public boolean pairPlayers(int round, Set players, Set droppedPlayers, Map playerByes, + List currentStandings, Map> previouslyPaired, Map pairingResults, Set byeResults); public String getPlayOffSystem(); } diff --git a/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/tournament/SwissPairingMechanism.java b/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/tournament/SwissPairingMechanism.java new file mode 100644 index 000000000..78c500ea8 --- /dev/null +++ b/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/tournament/SwissPairingMechanism.java @@ -0,0 +1,116 @@ +package com.gempukku.lotro.tournament; + +import com.gempukku.lotro.competitive.PlayerStanding; + +import java.util.*; + +public class SwissPairingMechanism implements PairingMechanism { + @Override + public String getPlayOffSystem() { + return "Swiss"; + } + + @Override + public boolean shouldDropLoser() { + return false; + } + + @Override + public boolean isFinished(int round, Set players, Set droppedPlayers) { + return round >= getRoundCountBasedOnNumberOfPlayers(players.size()); + } + + @Override + public boolean pairPlayers(int round, Set players, Set droppedPlayers, Map playerByes, List currentStandings, + Map> previouslyPaired, Map pairingResults, Set byeResults) { + int maxNumberOfPoints = determineMaximumNumberOfPoints(droppedPlayers, currentStandings); + + List> playersGroupedByBracket = groupPlayersByPointBracket(droppedPlayers, currentStandings, maxNumberOfPoints); + + shufflePlayersWithinBrackets(playersGroupedByBracket); + + Set playersWithByes = getPlayersWithByes(playerByes); + + boolean success = tryPairBracketAndFurther(0, new HashSet(), playersGroupedByBracket, playersWithByes, previouslyPaired, pairingResults, byeResults); + // Managed to pair with this carry over count - proceed with the pairings + if (success) + return false; + + // We can't pair, just finish the tournament + return true; + } + + private boolean tryPairBracketAndFurther(int bracketIndex, Set carryOverPlayers, List> playersGroupedByBracket, Set playersWithByes, + Map> previouslyPaired, Map pairingsResult, Set 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; + } + + private boolean tryPairBracketWithCarryOverMax(int bracketIndex, int carryOverMax, List> playersGroupedByPoints, Set playersWithByes, + Map> previouslyPaired, Map pairingsResult, + Map pairingsResult1, Set byes) { + // TODO + return true; + } + + private Set getPlayersWithByes(Map playerByes) { + Set playersWithByes = new HashSet(); + for (Map.Entry playerByeCount : playerByes.entrySet()) { + if (playerByeCount.getValue() != null && playerByeCount.getValue() > 0) + playersWithByes.add(playerByeCount.getKey()); + } + return playersWithByes; + } + + private void shufflePlayersWithinBrackets(List> playersGroupedByPoints) { + for (List playersByPoint : playersGroupedByPoints) + Collections.shuffle(playersByPoint); + } + + private List> groupPlayersByPointBracket(Set droppedPlayers, List currentStandings, int maxNumberOfPoints) { + List[] playersByPoints = new List[maxNumberOfPoints + 1]; + for (PlayerStanding currentStanding : currentStandings) { + String playerName = currentStanding.getPlayerName(); + if (!droppedPlayers.contains(playerName)) { + int points = currentStanding.getPoints(); + List playersByPoint = playersByPoints[maxNumberOfPoints - points]; + if (playersByPoint == null) { + playersByPoint = new ArrayList(); + playersByPoints[maxNumberOfPoints - points] = playersByPoint; + } + playersByPoint.add(playerName); + } + } + + List> result = new ArrayList>(); + for (List playersByPoint : playersByPoints) { + if (playersByPoint != null) + result.add(playersByPoint); + } + + return result; + } + + private int determineMaximumNumberOfPoints(Set droppedPlayers, List currentStandings) { + int maxNumberOfPoints = 0; + for (PlayerStanding currentStanding : currentStandings) { + if (!droppedPlayers.contains(currentStanding.getPlayerName())) + maxNumberOfPoints = Math.max(currentStanding.getPoints(), maxNumberOfPoints); + } + return maxNumberOfPoints; + } + + private static int getRoundCountBasedOnNumberOfPlayers(int numberOfPlayers) { + return (int) (Math.ceil(Math.log(numberOfPlayers) / Math.log(2))) + 1; + } + + public static void main(String[] args) { + for (int i = 1; i <= 128; i++) { + System.out.println("i=" + i + " - " + getRoundCountBasedOnNumberOfPlayers(i)); + } + } +}