Skip to content

Commit c898564

Browse files
authored
Merge pull request #1 from nypi/file_logs
File logs
2 parents c564969 + 00ddace commit c898564

File tree

10 files changed

+186
-9
lines changed

10 files changed

+186
-9
lines changed

README.md

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -257,22 +257,28 @@ TODO
257257

258258
```
259259
match
260+
num_bots {NUM_BOTS}
261+
##MatchConfig
260262
mode {MATCH_MODE}
261263
num_rounds {NUM_ROUNDS}
262-
num_bots {NUM_BOTS}
264+
random_seed {RANDOM_SEED}
265+
move_time_limit {MOVE_TIME_LIMIT}
266+
coin_spawn_period {COIN_SPAWN_PERIOD}
267+
coin_spawn_volume {COIN_SPAWN_VOLUME}
268+
##MapConfig
263269
map_size {MAP_WIDTH} {MAP_HEIGHT}
264270
view_radius {VIEW_RADIUS}
265271
mining_radius {MINING_RADIUS}
266272
attack_radius {ATTACK_RADIUS}
267-
move_time_limit {MOVE_TIME_LIMIT}
273+
block {X} {Y}
274+
##BotsAndCoinsInfo
268275
bot_name {BOT_ID} {BOT_NAME}
269276
bot {BOT_ID} {X} {Y}
270277
bot_coins {BOT_ID} {NUM_COINS}
271-
block {X} {Y}
272278
coin {X} {Y}
273279
round {ROUND}
274280
bot {BOT_ID} {X} {Y}
275-
bot_coins {BOT_ID} {X} {Y}
281+
bot_coins {BOT_ID} {NUM_COINS}
276282
attack {BOT_1_ID} {BOT_2_ID}
277283
coin_collected {X} {Y} {BOT_ID}
278284
coin {X} {Y}

common/src/main/java/ru/croccode/hypernull/geometry/Point.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,4 +113,8 @@ public int hashCode() {
113113
public String toString() {
114114
return "(" + x + ", " + y + ")";
115115
}
116+
117+
public String toLog() {
118+
return x + " " + y;
119+
}
116120
}

server/hypernull.properties

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
server.port=2021
2+
match.log.folder=./matchlogs/

server/src/main/java/ru/croccode/hypernull/match/Match.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -365,4 +365,23 @@ private void collectCoins() {
365365
}
366366
}
367367
}
368+
369+
public void finished() {
370+
//TODO Надо ли оповещать через MatchListener, что матч совсем всё?
371+
for (MatchListener<K> listener : listeners) {
372+
try {
373+
listener.close();
374+
} catch (Exception e) {
375+
throw new RuntimeException(
376+
String.format(
377+
"Ошибка при закрытии слушателя %s матча %s: %s",
378+
listener.getClass().getSimpleName(),
379+
this,//TODO id?
380+
e.getMessage()
381+
),
382+
e
383+
);
384+
}
385+
}
386+
}
368387
}

server/src/main/java/ru/croccode/hypernull/match/MatchConfig.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,11 @@
55

66
public class MatchConfig {
77

8-
private final long randomSeed;
8+
private final MatchMode mode;
99

1010
private final int numRounds;
1111

12-
private final MatchMode mode;
12+
private final long randomSeed;
1313

1414
private final long moveTimeLimit;
1515

server/src/main/java/ru/croccode/hypernull/match/MatchListener.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
import ru.croccode.hypernull.domain.MatchMap;
66
import ru.croccode.hypernull.geometry.Point;
77

8-
public interface MatchListener<K> {
8+
public interface MatchListener<K> extends AutoCloseable{
99

1010
void matchStarted(MatchMap map, MatchConfig config, Map<K, String> botNames);
1111

server/src/main/java/ru/croccode/hypernull/server/AsciiMatchPrinter.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,11 @@ public class AsciiMatchPrinter implements MatchListener<Integer> {
3333

3434
private int round;
3535

36+
@Override
37+
public void close() {
38+
//nothing
39+
}
40+
3641
static class BotState {
3742

3843
String name = Strings.empty();

server/src/main/java/ru/croccode/hypernull/server/HyperNull.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,13 +34,16 @@ public class HyperNull implements Runnable, Closeable {
3434
private final MapRegistry mapRegistry;
3535

3636
private final Server server;
37+
private final String matchLogsFolder;
3738

3839
public HyperNull(Properties properties) throws IOException {
3940
Check.notNull(properties);
4041
mapRegistry = new RandomMapRegistry(); // TODO implement MapRegistry
4142
// start server
4243
int serverPort = Integer.parseInt(
4344
properties.getProperty("server.port", "2021"));
45+
46+
matchLogsFolder = properties.getProperty("match.log.folder","./matchlogs/");
4447
this.server = new Server(serverPort);
4548
}
4649

@@ -87,7 +90,8 @@ private void runMatch(MatchMode mode, List<MatchRequest> matchRequests) {
8790
MatchMap map = mapRegistry.randomMap(numBots);
8891
MatchConfig config = buildMatchConfig(mode, map);
8992
List<MatchListener<Integer>> listeners = Arrays.asList(
90-
new AsciiMatchPrinter()
93+
new AsciiMatchPrinter(),
94+
new MatchFileLogger<>(this.matchLogsFolder)
9195
);
9296
Match<Integer> match = new Match<>(map, config, botNames, listeners);
9397
new MatchRunner(match, botSessions).run();
@@ -109,6 +113,7 @@ public void close() throws IOException {
109113
}
110114

111115
public static void main(String[] args) throws IOException {
116+
System.out.println("Запуск сервера...");
112117
String configPath = args.length > 0
113118
? args[0]
114119
: "hypernull.properties";
Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
package ru.croccode.hypernull.server;
2+
3+
import ru.croccode.hypernull.domain.MatchMap;
4+
import ru.croccode.hypernull.geometry.Point;
5+
import ru.croccode.hypernull.geometry.Size;
6+
import ru.croccode.hypernull.match.MatchConfig;
7+
import ru.croccode.hypernull.match.MatchListener;
8+
9+
import java.io.IOException;
10+
import java.io.PrintWriter;
11+
import java.lang.reflect.Field;
12+
import java.nio.file.Files;
13+
import java.nio.file.Path;
14+
import java.nio.file.Paths;
15+
import java.util.Map;
16+
import java.util.UUID;
17+
18+
public class MatchFileLogger<K> implements MatchListener<K> {
19+
20+
private final static String LOG_FILE_TEMPLATE = "%s/Match_log_%s.txt";
21+
22+
private final UUID matchId;
23+
private final PrintWriter logWriter;
24+
25+
public MatchFileLogger(String logsFolder) {
26+
this.matchId = UUID.randomUUID();
27+
Path path = Paths.get(logsFolder);
28+
try {
29+
Files.createDirectories(path);
30+
final String logFileName = String.format(LOG_FILE_TEMPLATE, logsFolder, matchId);
31+
this.logWriter = new PrintWriter(logFileName);
32+
} catch (IOException ex) {
33+
throw new RuntimeException(
34+
"Ошибка инициализации логера в файл: " + ex.getMessage(),
35+
ex
36+
);
37+
}
38+
}
39+
40+
@Override
41+
public void matchStarted(MatchMap map, MatchConfig config, Map<K, String> botNames) {
42+
write("match");
43+
write("num_bots " + botNames.size());
44+
write("##MatchConfig");
45+
printAllFields(config);
46+
write("##MapConfig");
47+
final Size mapSize = map.getSize();
48+
write("map_size " + mapSize.width() + " " + mapSize.height());
49+
write("view_radius " + map.getViewRadius());
50+
write("mining_radius " + map.getMiningRadius());
51+
write("attack_radius " + map.getAttackRadius());
52+
printAllBlocks(map);
53+
write("##BotsAndCoinsInfo");
54+
for (Map.Entry<K, String> botEntry : botNames.entrySet()) {
55+
write("bot_name " + botEntry.getKey() + " " + botEntry.getValue());
56+
}
57+
}
58+
59+
private void printAllBlocks(MatchMap map) {
60+
for (int row = 0; row < map.getHeight(); row++) {
61+
for (int column = 0; column < map.getWidth(); column++) {
62+
Point somePoint = new Point(column, row);
63+
if (map.isBlocked(somePoint)) {
64+
write("block " + somePoint.toLog());
65+
}
66+
}
67+
}
68+
}
69+
70+
@Override
71+
public void matchRound(int round) {
72+
write("round " + round);
73+
}
74+
75+
@Override
76+
public void coinSpawned(Point position) {
77+
write("coin " + position.toLog());
78+
}
79+
80+
@Override
81+
public void coinCollected(Point position, K botKey) {
82+
write("coin_collected " + position.toLog() + " " + botKey);
83+
}
84+
85+
@Override
86+
public void botSpawned(K botKey, Point position) {
87+
botMoved(botKey, position);
88+
}
89+
90+
@Override
91+
public void botMoved(K botKey, Point position) {
92+
write("bot " + botKey + " " + position.toLog());
93+
}
94+
95+
@Override
96+
public void attack(K attackingKey, K defendingKey) {
97+
write("attack " + attackingKey + " " + defendingKey);
98+
}
99+
100+
@Override
101+
public void botCoinsChanged(K botKey, int numCoins) {
102+
write("bot_coins " + botKey + " " + numCoins); //TODO надо ли выводить предыдущее кол-во монет?
103+
}
104+
105+
@Override
106+
public void matchOver(K botKey) {
107+
write("match_over " + botKey);
108+
}
109+
110+
private void write(String msg) {
111+
logWriter.println(msg);
112+
logWriter.flush();
113+
}
114+
@Override
115+
public void close() {
116+
logWriter.close();
117+
}
118+
119+
private void printAllFields(Object someObj) {
120+
final Class<?> objClass = someObj.getClass();
121+
for (Field declaredField : objClass.getDeclaredFields()) {
122+
try {
123+
declaredField.setAccessible(true);
124+
final String filedName = declaredField.getName()
125+
.replaceAll("([A-Z][a-z])", "_$1")
126+
.toLowerCase();
127+
write(filedName + " " + declaredField.get(someObj));
128+
} catch (IllegalAccessException e) {
129+
throw new RuntimeException(
130+
"Ошибка получения значения поля для класса " + objClass.getSimpleName()
131+
+ " через рефлексию: " + e.getMessage(),
132+
e
133+
);
134+
}
135+
}
136+
}
137+
}

server/src/main/java/ru/croccode/hypernull/server/MatchRunner.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ public void run() {
9393
}
9494
match.completeRound(botMoves);
9595
}
96-
96+
match.finished();
9797
new ArrayList<>(botSessions.keySet()).forEach(this::closeSession);
9898
}
9999

0 commit comments

Comments
 (0)