diff --git a/framework/src/main/java/org/toop/framework/networking/server/Server.java b/framework/src/main/java/org/toop/framework/networking/server/Server.java index 291b8a8..795c2d9 100644 --- a/framework/src/main/java/org/toop/framework/networking/server/Server.java +++ b/framework/src/main/java/org/toop/framework/networking/server/Server.java @@ -295,7 +295,7 @@ public class Server implements GameServer { Tournament tournament = new BasicTournament(new TournamentBuilder( this, - new BasicTournamentRunner(), + new AsyncTournamentRunner(), new RoundRobinMatchMaker(tournamentUsers), new BasicScoreSystem(tournamentUsers) )); diff --git a/framework/src/main/java/org/toop/framework/networking/server/tournaments/AsyncTournamentRunner.java b/framework/src/main/java/org/toop/framework/networking/server/tournaments/AsyncTournamentRunner.java new file mode 100644 index 0000000..e2af24a --- /dev/null +++ b/framework/src/main/java/org/toop/framework/networking/server/tournaments/AsyncTournamentRunner.java @@ -0,0 +1,85 @@ +package org.toop.framework.networking.server.tournaments; + +import org.toop.framework.networking.server.Server; +import org.toop.framework.networking.server.client.NettyClient; +import org.toop.framework.networking.server.tournaments.matchmakers.MatchMaker; +import org.toop.framework.networking.server.tournaments.scoresystems.ScoreSystem; + +import java.util.*; +import java.util.concurrent.*; + +public class AsyncTournamentRunner implements TournamentRunner { + + @Override + public void run( + Server server, + MatchMaker matchMaker, + ScoreSystem scoreSystem, + String gameType + ) { + + ExecutorService matchExecutor = + Executors.newFixedThreadPool( + Runtime.getRuntime().availableProcessors() + ); + + Queue pendingMatches = new ConcurrentLinkedQueue<>(); + matchMaker.forEach(pendingMatches::add); + + Set busyPlayers = ConcurrentHashMap.newKeySet(); + List> runningMatches = new CopyOnWriteArrayList<>(); + + try { + while (!pendingMatches.isEmpty() || !runningMatches.isEmpty()) { + + Iterator it = pendingMatches.iterator(); + while (it.hasNext()) { + TournamentMatch match = it.next(); + + NettyClient a = match.getClient0(); + NettyClient b = match.getClient1(); + + // TODO game != null doesn't work here, fix later + if (busyPlayers.contains(a) || busyPlayers.contains(b)) { + continue; + } + + busyPlayers.add(a); + busyPlayers.add(b); + it.remove(); + + CompletableFuture f = + CompletableFuture.runAsync(() -> { + try { + var game = server.startGame(gameType, a, b); + int result = game.result().join(); + + switch (result) { + case 0 -> scoreSystem.addScore(a); + case 1 -> scoreSystem.addScore(b); + } + } finally { + a.clearGame(); + b.clearGame(); + busyPlayers.remove(a); + busyPlayers.remove(b); + } + }, matchExecutor); + + runningMatches.add(f); + + f.whenComplete((_, _) -> runningMatches.remove(f)); + } + + Thread.sleep(10); + } + + server.endTournament(scoreSystem.getScore(), gameType); + + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } finally { + matchExecutor.shutdown(); + } + } +} diff --git a/framework/src/main/java/org/toop/framework/networking/server/tournaments/BasicTournamentRunner.java b/framework/src/main/java/org/toop/framework/networking/server/tournaments/BasicTournamentRunner.java index 1da24ac..3ee631e 100644 --- a/framework/src/main/java/org/toop/framework/networking/server/tournaments/BasicTournamentRunner.java +++ b/framework/src/main/java/org/toop/framework/networking/server/tournaments/BasicTournamentRunner.java @@ -1,7 +1,5 @@ package org.toop.framework.networking.server.tournaments; -import org.toop.framework.gameFramework.model.game.TurnBasedGame; -import org.toop.framework.networking.server.OnlineGame; import org.toop.framework.networking.server.Server; import org.toop.framework.networking.server.tournaments.matchmakers.MatchMaker; import org.toop.framework.networking.server.tournaments.scoresystems.ScoreSystem; diff --git a/framework/src/main/java/org/toop/framework/networking/server/tournaments/matchmakers/MatchMaker.java b/framework/src/main/java/org/toop/framework/networking/server/tournaments/matchmakers/MatchMaker.java index e61d387..1638c73 100644 --- a/framework/src/main/java/org/toop/framework/networking/server/tournaments/matchmakers/MatchMaker.java +++ b/framework/src/main/java/org/toop/framework/networking/server/tournaments/matchmakers/MatchMaker.java @@ -1,5 +1,10 @@ package org.toop.framework.networking.server.tournaments.matchmakers; +import org.toop.framework.networking.server.client.NettyClient; import org.toop.framework.networking.server.tournaments.TournamentMatch; -public interface MatchMaker extends Iterable {} +import java.util.List; + +public interface MatchMaker extends Iterable { + List getPlayers(); +} diff --git a/framework/src/main/java/org/toop/framework/networking/server/tournaments/matchmakers/RoundRobinMatchMaker.java b/framework/src/main/java/org/toop/framework/networking/server/tournaments/matchmakers/RoundRobinMatchMaker.java index be38af7..3fdb593 100644 --- a/framework/src/main/java/org/toop/framework/networking/server/tournaments/matchmakers/RoundRobinMatchMaker.java +++ b/framework/src/main/java/org/toop/framework/networking/server/tournaments/matchmakers/RoundRobinMatchMaker.java @@ -15,6 +15,11 @@ public class RoundRobinMatchMaker implements MatchMaker { this.players = players; } + @Override + public List getPlayers() { + return players; + } + @Override public Iterator iterator() { return new Iterator<>() { diff --git a/framework/src/main/java/org/toop/framework/networking/server/tournaments/scoresystems/BasicScoreSystem.java b/framework/src/main/java/org/toop/framework/networking/server/tournaments/scoresystems/BasicScoreSystem.java index 75625c3..d90867e 100644 --- a/framework/src/main/java/org/toop/framework/networking/server/tournaments/scoresystems/BasicScoreSystem.java +++ b/framework/src/main/java/org/toop/framework/networking/server/tournaments/scoresystems/BasicScoreSystem.java @@ -2,13 +2,13 @@ package org.toop.framework.networking.server.tournaments.scoresystems; import org.toop.framework.networking.server.client.NettyClient; -import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; public class BasicScoreSystem implements ScoreSystem { - private final Map scores = new HashMap<>(); + private final Map scores = new ConcurrentHashMap<>(); public BasicScoreSystem(List store) { for (NettyClient c : store) {