Headless.java (5658B) download
1package nl.isygameclient;
2
3import com.google.gson.Gson;
4import com.google.gson.reflect.TypeToken;
5import java.io.IOException;
6import java.lang.reflect.Type;
7import java.nio.file.Files;
8import java.nio.file.NoSuchFileException;
9import java.nio.file.Paths;
10import java.util.*;
11import java.util.concurrent.Executors;
12import java.util.concurrent.locks.Lock;
13import java.util.concurrent.locks.ReentrantLock;
14import java.util.stream.Collectors;
15import nl.isygameclient.models.Ai;
16import nl.isygameclient.models.Game;
17import nl.isygameclient.models.Player;
18import nl.isygameclient.models.PlayerManager;
19import nl.isygameclient.models.games.othello.Othello;
20import nl.isygameclient.util.DataSaver;
21import nl.isygameclient.util.Vector2D;
22
23
24public class Headless {
25 private static final String JSON_FILENAME = "heuristics.json";
26 private static final int THREAD_POOL_SIZE = 10;
27 private static final int ROUNDS_PER_GAME = 100;
28
29 private static long calculateAverage(List<Long> values) {
30 long sum = values.stream().mapToLong(Long::longValue).sum();
31 return sum / values.size();
32 }
33
34 private static Map<String, Game> createGames(Map<String, int[][]> heuristics) {
35 Map<String, Game> games = new HashMap<>();
36 for (Map.Entry<String, int[][]> heuristic1 : heuristics.entrySet()) {
37 for (Map.Entry<String, int[][]> heuristic2 : heuristics.entrySet()) {
38
39 ArrayList<Player> players = new ArrayList<>();
40 players.add(new Ai(heuristic1.getKey(), "black", heuristic1.getValue()));
41 players.add(new Ai(heuristic2.getKey(), "white", heuristic2.getValue()));
42
43 var playerManager = new PlayerManager(0, players);
44 Othello othello = new Othello(playerManager);
45 games.put(heuristic1.getKey() + ", " + heuristic2.getKey(), othello);
46 }
47 }
48 return games;
49 }
50
51 private static String buildDataString(
52 String gameName, int gameTurns, boolean isDraw, Player winner, long totalGameTime,
53 Map<Player, ArrayList<Long>> playersTimePerMoves,
54 Map<Player, ArrayList<Vector2D<Integer, Integer>>> playersMovesMade) {
55 StringBuilder builder = new StringBuilder();
56
57 String joined = String.join(",", gameName, String.valueOf(gameTurns), String.valueOf(isDraw),
58 winner.getPlayerName(), winner.getPlayingAs(), String.valueOf(totalGameTime)) +
59 ",";
60 builder.append(joined);
61
62 playersTimePerMoves.forEach((k, v) -> {
63 var average = calculateAverage(v);
64 builder.append(average).append(",");
65 });
66 playersMovesMade.forEach((k, v) -> {
67 String listString = v.stream().map(Object::toString).collect(Collectors.joining("; "));
68 builder.append(listString).append(",");
69 });
70 return builder.toString();
71 }
72
73 private static Map<String, int[][]> loadHeuristics() {
74 try {
75 Type mapType = new TypeToken<Map<String, int[][]>>() {
76 }.getType();
77 String inFile = new String(Files.readAllBytes(Paths.get(JSON_FILENAME)));
78 return new Gson().fromJson(inFile, mapType);
79 } catch (NoSuchFileException e) {
80 System.err.println("NO HEURISTICS JSON HAS BEEN PROVIDED.");
81 e.printStackTrace();
82 } catch (IOException e) {
83 e.printStackTrace();
84 }
85 return null;
86 }
87
88 public static void main(String[] args) {
89 var heuristics = loadHeuristics();
90 if (heuristics == null) {
91 System.err.println("No heuristics in file.");
92 return;
93 }
94
95 var executor = Executors.newFixedThreadPool(THREAD_POOL_SIZE);
96 var games = createGames(heuristics);
97 var dataSaver = new DataSaver();
98 dataSaver.saveData("Name Ai1, Name Ai2, Game Turns, Draw, Winner Name, Winner Playing As, Total Game Time, Average Time Per Move Ai1, Average Time Per Move Ai2, Moves Ai1, Moves Ai2");
99 for (Map.Entry<String, Game> game : games.entrySet()) {
100 Runnable simulation = new Simulation(game.getKey(), game.getValue(), ROUNDS_PER_GAME, new ReentrantLock(), dataSaver);
101 executor.execute(simulation);
102 }
103 executor.shutdown();
104
105 while (!executor.isTerminated()) {
106 }
107
108 System.out.println("All simulations completed successfully.");
109 }
110
111 private record Simulation(String gameName, Game game, int rounds, Lock lock, DataSaver dataSaver) implements Runnable {
112 @Override
113 public void run() {
114 System.out.println("Starting simulation: " + gameName);
115
116 var playerManager = game.getPlayerManager();
117 for (int i = 0; i < rounds; i++) {
118 System.out.println("Start round" + i + " " + gameName);
119
120 Map<Player, ArrayList<Long>> playersTimePerMoves = new HashMap<>();
121 Map<Player, ArrayList<Vector2D<Integer, Integer>>> PlayersMovesMade = new HashMap<>();
122
123 long totalGameTime = 0;
124 int gameTurns = 0;
125 while (!game.isGameOver()) {
126 gameTurns++;
127 var currentPlayer = playerManager.getCurrentPlayer();
128 if (game.getValidMoves(currentPlayer).isEmpty()) {
129 playerManager.nextPlayer();
130 continue;
131 }
132
133 final long startTime = System.currentTimeMillis();
134 var move = currentPlayer.onPlayerTurn();
135 game.move(currentPlayer, move);
136 final long endTime = System.currentTimeMillis();
137 final long deltaTime = endTime - startTime;
138 totalGameTime += deltaTime;
139
140 PlayersMovesMade.computeIfAbsent(currentPlayer, k -> new ArrayList<>()).add(move);
141 playersTimePerMoves.computeIfAbsent(currentPlayer, k -> new ArrayList<>()).add(deltaTime);
142 }
143
144 var winner = game.getWinners().get(0);
145 var data = buildDataString(gameName, gameTurns, game.isDraw(), winner, totalGameTime, playersTimePerMoves, PlayersMovesMade);
146
147 lock.lock();
148 try {
149 dataSaver.saveData(data);
150 } finally {
151 lock.unlock();
152 }
153 game.restart();
154 System.out.println("end round" + i + " " + gameName);
155 }
156 System.out.println(gameName + " has finished");
157 }
158 }
159}