1 package cz.cuni.amis.pogamut.ut2004.hideandseek.tournament;
2
3 import java.io.File;
4 import java.io.IOException;
5 import java.util.ArrayList;
6 import java.util.Collections;
7 import java.util.Comparator;
8 import java.util.Formatter;
9 import java.util.HashMap;
10 import java.util.List;
11 import java.util.Map;
12 import java.util.Map.Entry;
13 import java.util.concurrent.CountDownLatch;
14 import java.util.concurrent.TimeUnit;
15 import java.util.logging.Level;
16
17 import cz.cuni.amis.pogamut.base.agent.impl.AgentId;
18 import cz.cuni.amis.pogamut.base.agent.state.level0.IAgentState;
19 import cz.cuni.amis.pogamut.base.agent.state.level1.IAgentStateDown;
20 import cz.cuni.amis.pogamut.base.agent.state.level1.IAgentStateUp;
21 import cz.cuni.amis.pogamut.base.agent.state.level2.IAgentStateRunning;
22 import cz.cuni.amis.pogamut.base.utils.guice.AdaptableProvider;
23 import cz.cuni.amis.pogamut.base.utils.logging.LogCategory;
24 import cz.cuni.amis.pogamut.unreal.communication.messages.UnrealId;
25 import cz.cuni.amis.pogamut.ut2004.agent.params.UT2004AgentParameters;
26 import cz.cuni.amis.pogamut.ut2004.analyzer.IUT2004AnalyzerObserver;
27 import cz.cuni.amis.pogamut.ut2004.analyzer.UT2004Analyzer;
28 import cz.cuni.amis.pogamut.ut2004.analyzer.UT2004AnalyzerFullObserver;
29 import cz.cuni.amis.pogamut.ut2004.analyzer.stats.UT2004AnalyzerObsStats;
30 import cz.cuni.amis.pogamut.ut2004.communication.messages.gbcommands.StartPlayers;
31 import cz.cuni.amis.pogamut.ut2004.communication.messages.gbinfomessages.PlayerMessage;
32 import cz.cuni.amis.pogamut.ut2004.communication.messages.gbinfomessages.Self;
33 import cz.cuni.amis.pogamut.ut2004.factory.guice.remoteagent.UT2004ServerFactory;
34 import cz.cuni.amis.pogamut.ut2004.hideandseek.server.HSBotRecord;
35 import cz.cuni.amis.pogamut.ut2004.hideandseek.server.UT2004HSServer;
36 import cz.cuni.amis.pogamut.ut2004.hideandseek.server.UT2004HSServerModule;
37 import cz.cuni.amis.pogamut.ut2004.server.impl.UT2004Server;
38 import cz.cuni.amis.pogamut.ut2004.tournament.botexecution.UT2004BotExecution;
39 import cz.cuni.amis.pogamut.ut2004.tournament.match.UT2004BotConfig;
40 import cz.cuni.amis.pogamut.ut2004.tournament.match.UT2004Match;
41 import cz.cuni.amis.pogamut.ut2004.tournament.match.result.UT2004MatchResult;
42 import cz.cuni.amis.pogamut.ut2004.utils.UCCWrapper;
43 import cz.cuni.amis.utils.ExceptionToString;
44 import cz.cuni.amis.utils.FilePath;
45 import cz.cuni.amis.utils.NullCheck;
46 import cz.cuni.amis.utils.collections.MyCollections;
47 import cz.cuni.amis.utils.exception.PogamutException;
48 import cz.cuni.amis.utils.exception.PogamutIOException;
49 import cz.cuni.amis.utils.exception.PogamutInterruptedException;
50 import cz.cuni.amis.utils.flag.FlagListener;
51 import cz.cuni.amis.utils.token.IToken;
52 import cz.cuni.amis.utils.token.Tokens;
53
54 public class UT2004HideAndSeek extends UT2004Match<UT2004HideAndSeekConfig, UT2004HideAndSeekResult> {
55
56 private String origFixedSeekerName = null;
57
58 public UT2004HideAndSeek(UT2004HideAndSeekConfig config, LogCategory log) {
59 super(false, config, log);
60 }
61
62 @Override
63 protected void changeBotTeam(UT2004Server server, UnrealId botId, int desiredTeam) {
64
65 }
66
67 @Override
68 protected UT2004MatchResult waitMatchFinish(UCCWrapper ucc, UT2004Server server, UT2004Analyzer analyzer, Bots bots, long timeoutInMillis) {
69
70
71 if (log != null && log.isLoggable(Level.WARNING)) {
72 log.warning(config.getMatchId().getToken() + ": Waiting for the match to finish...");
73 }
74
75
76 long minTimeoutMillis = (long)(Math.round(config.getHsConfig().getRoundCount() * config.getHsConfig().getRoundTimeUT() * 1000 + config.getHsConfig().getRoundCount() * 60 * 1000 + 5 * 60 * 1000));
77
78 if (minTimeoutMillis > timeoutInMillis) {
79 timeoutInMillis = minTimeoutMillis;
80 log.warning(config.getMatchId().getToken() + ": match global timeout set to " + (minTimeoutMillis/1000) + " seconds");
81 }
82
83 Map<IToken, FlagListener<Boolean>> customBotObservers = new HashMap<IToken, FlagListener<Boolean>>(config.getBots().size());
84 FlagListener<IAgentState> serverObs = null;
85 FlagListener<Boolean> uccObs = null;
86 FlagListener<Boolean> hsGameRunning = null;
87
88 final CountDownLatch waitLatch = new CountDownLatch(1);
89 final AdaptableProvider<Boolean> oneOfBotsDiedOut = new AdaptableProvider<Boolean>(false);
90 final AdaptableProvider<Boolean> serverDiedOut = new AdaptableProvider<Boolean>(false);
91
92 boolean exception = false;
93
94 try {
95 for (UT2004BotConfig botConfig : config.getBots().values()) {
96 FlagListener<Boolean> obs = new FlagListener<Boolean>() {
97 @Override
98 public void flagChanged(Boolean changedValue) {
99 if (!changedValue) {
100
101 oneOfBotsDiedOut.set(true);
102 waitLatch.countDown();
103 }
104 }
105 };
106
107 bots.bots.get(botConfig.getBotId()).getRunning().addListener(obs);
108 customBotObservers.put(botConfig.getBotId(), obs);
109 if (!bots.bots.get(botConfig.getBotId()).getRunning().getFlag()) {
110
111 oneOfBotsDiedOut.set(true);
112 waitLatch.countDown();
113 throw new PogamutException("One of custom bots died out from the start, failure!", log, this);
114 }
115 }
116
117 serverObs = new FlagListener<IAgentState>() {
118
119 @Override
120 public void flagChanged(IAgentState changedValue) {
121 if (changedValue instanceof IAgentStateDown) {
122
123 serverDiedOut.set(true);
124 waitLatch.countDown();
125 }
126 }
127
128 };
129
130 server.getState().addListener(serverObs);
131
132 if (server.notInState(IAgentStateUp.class)) {
133
134 serverDiedOut.set(true);
135 waitLatch.countDown();
136 throw new PogamutException("Server is dead from the start, failure!", log, this);
137 }
138
139 if (!((UT2004HSServer)server).isGameRunning().getFlag()) {
140 serverDiedOut.set(true);
141 waitLatch.countDown();
142 throw new PogamutException("Hide&Seek game is not running at the beginning, invalid!", log, this);
143 }
144
145 hsGameRunning = new FlagListener<Boolean>() {
146
147 @Override
148 public void flagChanged(Boolean changedValue) {
149 if (!changedValue) {
150
151 waitLatch.countDown();
152 }
153 }
154
155 };
156
157 ((UT2004HSServer)server).isGameRunning().addListener(hsGameRunning);
158
159 uccObs = new FlagListener<Boolean>() {
160
161 @Override
162 public void flagChanged(Boolean changedValue) {
163 if (changedValue) {
164
165
166 serverDiedOut.set(true);
167 waitLatch.countDown();
168 }
169 }
170
171 };
172
173 ucc.getGameEnding().addListener(uccObs);
174
175 waitLatch.await(timeoutInMillis, TimeUnit.MILLISECONDS);
176 if (waitLatch.getCount() > 0) {
177
178 throw new PogamutException("TIMEOUT! The match did not end in " + (timeoutInMillis / 1000) + " secs.", log, this);
179 }
180
181 bots.matchEnd = System.currentTimeMillis();
182
183
184 if (oneOfBotsDiedOut.get()) {
185
186 try {
187 Thread.sleep(5000);
188 } catch (InterruptedException e) {
189 throw new PogamutInterruptedException("Interrupted while giving GB2004 time to tear down its connection.", log, this);
190 }
191 try {
192 server.getAct().act(new StartPlayers());
193 } catch (Exception e) {
194
195 serverDiedOut.set(true);
196 }
197 if (!serverDiedOut.get()) {
198
199 log.warning("ONE OF BOTS HAS DIED OUT, BUT SERVER IS STILL RUNNING ... POSSIBLE MATCH FAILURE!");
200 }
201 }
202 if (((UT2004HSServer)server).getGameFailed().getFlag()) {
203 throw new PogamutException("UT2004HSServer reported failure!", log, this);
204 }
205 if (!serverDiedOut.get() && server.inState(IAgentStateUp.class)) {
206
207
208 server.kill();
209 }
210
211
212
213 if (ucc != null) {
214 try {
215 if (log != null && log.isLoggable(Level.INFO)) {
216 log.info(config.getMatchId().getToken() + ": Killing UCC...");
217 }
218 } catch (Exception e) {
219 }
220 try {
221 ucc.stop();
222 } catch (Exception e) {
223 }
224 }
225
226
227 UT2004HSServer hsServer = (UT2004HSServer)server;
228 Map<IToken, HSBotRecord<PlayerMessage>> botRecordMap = new HashMap<IToken, HSBotRecord<PlayerMessage>>();
229 List<HSBotRecord<PlayerMessage>> botRecords = new ArrayList<HSBotRecord<PlayerMessage>>();
230 for (Entry<UnrealId, HSBotRecord<PlayerMessage>> entryRecord : hsServer.getBotRecords().entrySet()) {
231 if (entryRecord.getValue().getPlayer() == null || entryRecord.getValue().getPlayer().getJmx() == null) continue;
232 IToken botId = bots.unrealId2BotId.get(entryRecord.getKey());
233 botRecordMap.put(botId, entryRecord.getValue());
234 botRecords.add(entryRecord.getValue());
235 }
236
237 if (botRecords.size() == 0) {
238 throw new PogamutException("There are not bots results, it seems like the match has not been even played ???", log, this);
239 }
240
241
242 Collections.sort(botRecords, new Comparator<HSBotRecord<PlayerMessage>>() {
243 @Override
244 public int compare(HSBotRecord<PlayerMessage> o1, HSBotRecord<PlayerMessage> o2) {
245 return o2.getScore() - o1.getScore();
246 }
247 });
248
249
250 List<IToken> winners = new ArrayList<IToken>(1);
251 int maxScore = botRecords.get(0).getScore();
252 for (HSBotRecord<PlayerMessage> botRecord : botRecords) {
253 if (maxScore == botRecord.getScore()) {
254 IToken botId = bots.unrealId2BotId.get(botRecord.getBotId());
255 winners.add(botId);
256 } else {
257
258
259 break;
260 }
261 }
262
263
264 if (winners.size() == 0) {
265
266 throw new PogamutException("There is no WINNER, impossible! **puzzled**", log, this);
267 }
268 if (winners.size() > 1) {
269 StringBuffer sb = new StringBuffer();
270 sb.append("There is more than one winner with highest score == " + maxScore + ": ");
271 boolean first = true;
272 for (IToken id : winners) {
273 if (first) first = false;
274 else sb.append(", ");
275 sb.append("Bot[botId=" + id + ", unrealId=" + bots.botId2UnrealId.get(id) + ", score=" + botRecordMap.get(id).getScore() + "]");
276 }
277 sb.append(".");
278 if (log != null && log.isLoggable(Level.WARNING)) {
279 log.warning(sb.toString());
280 }
281 }
282
283 if (log != null && log.isLoggable(Level.WARNING)) {
284 log.warning(config.getMatchId().getToken() + ": MATCH FINISHED!");
285 }
286
287 return processResults(ucc, server, analyzer, bots, winners, botRecordMap);
288
289 } catch (Exception e) {
290 exception = true;
291 throw new PogamutException("Failed to perform the match!", e, log, this);
292 } finally {
293 if (hsGameRunning != null) {
294 ((UT2004HSServer)server).isGameRunning().removeListener(hsGameRunning);
295 hsGameRunning = null;
296 }
297 for (Entry<IToken, FlagListener<Boolean>> entry : customBotObservers.entrySet()) {
298 bots.bots.get(entry.getKey()).getRunning().removeListener(entry.getValue());
299 }
300 server.getState().removeListener(serverObs);
301 }
302
303 }
304
305 protected UT2004HideAndSeekResult processResults(UCCWrapper ucc, UT2004Server server, UT2004Analyzer analyzer, Bots bots, List<IToken> winners, Map<IToken, HSBotRecord<PlayerMessage>> botRecords) {
306 if (log != null && log.isLoggable(Level.FINE)) {
307 log.fine(config.getMatchId().getToken() + ": Processing results...");
308 }
309
310 config.getHsConfig().setFixedSeekerName(origFixedSeekerName);
311
312 UT2004HideAndSeekResult result = new UT2004HideAndSeekResult();
313
314
315 result.setBots(MyCollections.asList(bots.botId2UnrealId.keySet()));
316
317
318 result.setBotIds(bots.botId2UnrealId);
319
320
321 for (Entry<IToken, IUT2004AnalyzerObserver> entry : bots.botObservers.entrySet()) {
322 if (!(entry.getValue() instanceof UT2004AnalyzerObsStats)) {
323 throw new PogamutException("There is an observer of wrong class, expecting UT2004AnalyzerObsStats, got " + entry.getValue().getClass().getSimpleName() + "!", log, this);
324 }
325 result.getBotObservers().put(entry.getKey(), (UT2004AnalyzerObsStats)entry.getValue());
326 }
327
328
329 result.setWinners(winners);
330
331
332 result.setMatchTime(((double)bots.matchEnd - (double)bots.matchStart) / (1000));
333
334
335 result.setScoreDetails(botRecords);
336
337 if (log != null && log.isLoggable(Level.WARNING)) {
338 log.warning(config.getMatchId().getToken() + ": Results processed, #Winners = " + result.getWinners().size() + ", Winners score = " + result.getWinnerScore());
339 }
340
341 return result;
342 }
343
344 protected void outputResults_step1(UT2004HideAndSeekResult result, File outputDirectory) {
345 if (log != null && log.isLoggable(Level.FINE)) {
346 log.fine(config.getMatchId().getToken() + ": Outputting match result into CSV file...");
347 }
348
349 File file = new File(outputDirectory.getAbsolutePath() + File.separator + "match-" + config.getMatchId().getToken() + "-result.csv");
350 FilePath.makeDirsToFile(file);
351 try {
352 Formatter writer = new Formatter(file);
353 writer.format("MatchId;WinnerScore;MatchTimeSecs;" + config.getHsConfig().getCSVHeader() + "");
354 for (int i = 0; i < result.getWinners().size(); ++i) {
355 writer.format(";Winner" + (i+1));
356 }
357 writer.format("\n");
358 writer.format
359 (
360 "%s;%d;%.3f;",
361 config.getMatchId().getToken(),
362 result.getWinnerScore(),
363 result.getMatchTime()
364 );
365 config.getHsConfig().formatCSVLine(writer);
366
367 for (IToken winner : result.getWinners()) {
368 writer.format(";%s", winner.getToken());
369 }
370 try {
371 writer.close();
372 } catch (Exception e) {
373 }
374 } catch (IOException e) {
375 throw new PogamutIOException("Failed to write results!", e, log, this);
376 }
377
378 if (log != null && log.isLoggable(Level.INFO)) {
379 log.info(config.getMatchId().getToken() + ": Match result output into " + file.getAbsolutePath() + ".");
380 }
381 }
382
383 protected void outputResults_step2(UT2004HideAndSeekResult result, File outputDirectory) {
384 if (log != null && log.isLoggable(Level.FINE)) {
385 log.fine(config.getMatchId().getToken() + ": Outputting match scores into CSV file...");
386 }
387
388 File file = new File(outputDirectory.getAbsolutePath() + File.separator + "match-" + config.getMatchId().getToken() + "-bot-scores.csv");
389 FilePath.makeDirsToFile(file);
390 try {
391 Formatter writer = new Formatter(file);
392
393 List<IToken> bots = new ArrayList<IToken>(result.getBots());
394
395 Collections.sort(bots, new Comparator<IToken>() {
396 @Override
397 public int compare(IToken o1, IToken o2) {
398 return o1.getToken().compareTo(o2.getToken());
399 }
400 });
401
402 writer.format("BotId;SeekerCount;RunnerCount;Score");
403
404 writer.format(";RunnerCapturedBySeekerScore;RunnerSpottedBySeekerScore;RunnerSafeScore;RunnerSurvivedScore;RunnerFoulScore");
405 writer.format(";SeekerCapturedRunnerScore;SeekerSpottedRunnerScore;SeekerLetRunnerSurviveScore;SeekerLetRunnerEscapeScore");
406
407 for (IToken token : bots) {
408 writer.format(";ThisRunnerCapturedBySeeker_" + token.getToken() + "_Count");
409 writer.format(";ThisRunnerSpottedBySeeker_" + token.getToken() + "_Count");
410 writer.format(";ThisRunnerSafeCountWhileSeeker_" + token.getToken() + "_Count");
411 writer.format(";ThisRunnerSurvivedWhileSeeker_" + token.getToken() + "_Count");
412 writer.format(";ThisRunnerFoulWhileSeeker_" + token.getToken() + "_Count");
413
414 writer.format(";ThisSeekerCapturedRunner_" + token.getToken() + "_Count");
415 writer.format(";ThisSeekerSpottedRunner_" + token.getToken() + "_Count");
416 writer.format(";ThisSeekerLetRunner_" + token.getToken() + "_SurviveCount");
417 writer.format(";ThisSeekerLetRunner_" + token.getToken() + "_EscapeCount");
418
419 }
420
421 for (IToken token1 : bots) {
422 writer.format("\n");
423 writer.format(token1.getToken());
424
425 HSBotRecord<PlayerMessage> record = result.getScoreDetails().get(token1);
426
427 writer.format(";%d", record.getSeekerCount());
428 writer.format(";%d", record.getRunnerCount());
429 writer.format(";%d", record.getScore());
430
431 writer.format(";%d", record.getRunnerCapturedBySeekerScore());
432 writer.format(";%d", record.getRunnerSpottedBySeekerScore());
433 writer.format(";%d", record.getRunnerSafeScore());
434 writer.format(";%d", record.getRunnerSurvivedScore());
435 writer.format(";%d", record.getRunnerFoulScore());
436
437 writer.format(";%d", record.getSeekerCapturedRunnerScore());
438 writer.format(";%d", record.getSeekerSpottedRunnerScore());
439 writer.format(";%d", record.getSeekerLetRunnerSurviveScore());
440 writer.format(";%d", record.getSeekerLetRunnerEscapeScore());
441
442 for (IToken token2 : bots) {
443 UnrealId bot2Id = result.getBotIds().get(token2);
444 writer.format(";%d", record.getRunnerCapturedBySeekerCount().get(bot2Id));
445 writer.format(";%d", record.getRunnerSpottedBySeekerCount().get(bot2Id));
446 writer.format(";%d", record.getRunnerSafeCount().get(bot2Id));
447 writer.format(";%d", record.getRunnerSurvivedCount().get(bot2Id));
448 writer.format(";%d", record.getRunnerFoulCount().get(bot2Id));
449
450 writer.format(";%d", record.getSeekerCapturedRunnerCount().get(bot2Id));
451 writer.format(";%d", record.getSeekerSpottedRunnerCount().get(bot2Id));
452 writer.format(";%d", record.getSeekerLetRunnerSurviveCount().get(bot2Id));
453 writer.format(";%d", record.getSeekerLetRunnerEscapeCount().get(bot2Id));
454 }
455 }
456
457 try {
458 writer.close();
459 } catch (Exception e) {
460 }
461 } catch (IOException e) {
462 throw new PogamutIOException("Failed to write results!", e, log, this);
463 }
464
465 if (log != null && log.isLoggable(Level.INFO)) {
466 log.info(config.getMatchId().getToken() + ": Match scores output into " + file.getAbsolutePath() + ".");
467 }
468 }
469
470 @Override
471 protected void outputResults(UCCWrapper ucc, UT2004Server server, UT2004Analyzer analyzer, Bots bots, UT2004MatchResult result, File outputDirectory) {
472 if (!(result instanceof UT2004HideAndSeekResult)) {
473 throw new PogamutException("Can't out results! Expected results of class UT2004HideAndSeekResult and got " + result.getClass().getSimpleName() + "!", log, this);
474 }
475 outputResults_step1((UT2004HideAndSeekResult) result, outputDirectory);
476 outputResults_step2((UT2004HideAndSeekResult) result, outputDirectory);
477 }
478
479
480
481
482
483
484
485
486
487
488
489
490
491 @SuppressWarnings("rawtypes")
492 @Override
493 protected UT2004Server startControlServer(UCCWrapper ucc) {
494 if (log != null && log.isLoggable(Level.FINE)) {
495 log.fine(config.getMatchId().getToken() + ": Starting UT2004Server...");
496 }
497 NullCheck.check(ucc, "ucc");
498 UT2004HSServerModule module = new UT2004HSServerModule();
499 UT2004ServerFactory factory = new UT2004ServerFactory(module);
500 UT2004Server server = (UT2004Server) factory.newAgent(new UT2004AgentParameters().setAgentId(new AgentId(config.getMatchId().getToken()+"-UT2004Server")).setWorldAddress(ucc.getServerAddress()));
501
502 server.start();
503
504 if (!server.inState(IAgentStateRunning.class)) {
505 throw new PogamutException("Failed to start UT2004HSServer!", log, this);
506 }
507
508 if (log != null && log.isLoggable(Level.INFO)) {
509 log.info(config.getMatchId().getToken() + ": UT2004Server started.");
510 }
511 return server;
512 }
513
514
515
516
517
518
519
520
521
522 protected void matchIsAboutToBegin(UCCWrapper ucc, UT2004Server server, UT2004Analyzer analyzer, Bots bots) {
523 super.matchIsAboutToBegin(ucc, server, analyzer, bots);
524
525
526 try {
527 Thread.sleep(5000);
528 } catch (InterruptedException e) {
529 throw new PogamutInterruptedException(e, this);
530 }
531
532
533 if (config.getHsConfig().isFixedSeeker()) {
534
535
536 String fixedSeekerString = config.getHsConfig().getFixedSeekerName();
537 IToken fixedSeekerToken = Tokens.get(fixedSeekerString);
538 if (!bots.botObservers.containsKey(fixedSeekerToken)) {
539 throw new RuntimeException("Failed to find '" + fixedSeekerString + "' as token " + fixedSeekerToken + " within observer tokens, cannot ensure FIXED SEEKER settings.");
540 }
541 UT2004AnalyzerFullObserver observer = (UT2004AnalyzerFullObserver) bots.botObservers.get(fixedSeekerToken);
542 if (observer == null) {
543 throw new PogamutException("Failed to find '" + fixedSeekerString + "' as token " + fixedSeekerToken + " within observer map, cannot ensure FIXED SEEKER settings.", log, this);
544 }
545 Self fixedSeekerSelf = observer.getBotSelf();
546 if (fixedSeekerSelf == null) {
547 throw new PogamutException("Failed to obtain fixed seeker '" + fixedSeekerString + "' SELF from the observer, cannot ensure FIXED SEEKER settings.", log, this);
548 }
549 String fixedSeekerTrueName = fixedSeekerSelf.getName();
550 if (fixedSeekerTrueName == null) {
551 throw new PogamutException("Failed to obtain true name of the fixed seeker '" + fixedSeekerString + "' SELF.getName() is null, cannot ensure FIXED SEEKER settings.", log, this);
552 }
553 if (fixedSeekerTrueName.contains("[")) {
554 fixedSeekerTrueName = fixedSeekerTrueName.substring(0, fixedSeekerTrueName.indexOf("[")).trim();
555 }
556 if (fixedSeekerTrueName.isEmpty()) {
557 throw new PogamutException("Failed to obtain true name of the fixed seeker '" + fixedSeekerString + "', true name cannot be enclosed by [] brackets!", log, this);
558 }
559 if (log != null && log.isLoggable(Level.WARNING)) {
560 log.warning("Fixed seeker '" + fixedSeekerString + "' true bot name is '" + fixedSeekerTrueName + "', configuring fixed seeker for this name.");
561 }
562 origFixedSeekerName = config.getHsConfig().getFixedSeekerName();
563 config.getHsConfig().setFixedSeekerName(fixedSeekerTrueName);
564
565 int fixedSeekerTrueNameCount = 0;
566 for (UT2004AnalyzerFullObserver obs : ((Map<IToken, UT2004AnalyzerFullObserver>)(Map)bots.botObservers).values()) {
567 Self self = obs.getBotSelf();
568 if (self == null) {
569 throw new PogamutException("One bot observer does not contain SELF, cannot ensure FIXED SEEKER settings.", log, this);
570 }
571 if (self.getName() == null) {
572 throw new PogamutException("One bot observer has SELF.getName() == NULL, cannot ensure FIXED SEEKER settings.", log, this);
573 }
574 if (self.getName().startsWith(fixedSeekerTrueName)) {
575 ++fixedSeekerTrueNameCount;
576 }
577 }
578 if (fixedSeekerTrueNameCount != 1) {
579 throw new PogamutException("There are INVALID number of bots that has name prefixed with seeker name '" + fixedSeekerTrueName + ": " + fixedSeekerTrueNameCount + ". Cannot ensure FIXED SEEKER settings.", log, this);
580 }
581 }
582
583
584 config.getHsConfig().setObserverPort(ucc.getObserverPort());
585
586
587 UT2004HSServer hsServer = (UT2004HSServer) server;
588 hsServer.startGame(config.getHsConfig());
589 }
590
591 @Override
592 public UT2004HideAndSeekResult execute() {
593 try {
594 if (log != null && log.isLoggable(Level.WARNING)) {
595 log.warning(config.getMatchId().getToken() + ": Executing!");
596 }
597 } catch (Exception e) {
598 }
599
600 UCCWrapper ucc = null;
601 UT2004Server server = null;
602 Bots bots = null;
603 UT2004Analyzer analyzer = null;
604 String recordFileName = config.getMatchId().getToken() + "-replay-" + UT2004Match.getCurrentDate();
605 boolean exception = false;
606
607 try {
608
609 setupLogger();
610
611
612 validate();
613
614
615 createGB2004Ini();
616
617
618 ucc = startUCC();
619
620
621 server = startControlServer(ucc);
622
623
624 bots = startBots(ucc, server);
625
626
627 analyzer = startAnalyzer(ucc, bots, getOutputPath("bots"), config.isHumanLikeLogEnabled());
628
629
630 restartMatch(server, bots);
631
632
633 recordReplay(server, recordFileName);
634
635
636 matchIsAboutToBegin(ucc, server, analyzer, bots);
637
638
639
640 UT2004HideAndSeekResult result = (UT2004HideAndSeekResult) waitMatchFinish(ucc, server, analyzer, bots, 0);
641
642
643 copyReplay(ucc, recordFileName, getOutputPath());
644
645
646 outputResults(ucc, server, analyzer, bots, result, getOutputPath());
647
648
649 shutdownAll(ucc, server, analyzer, bots);
650
651 ucc = null;
652 server = null;
653 analyzer = null;
654 bots = null;
655
656
657 return result;
658
659 } catch (Exception e) {
660 if (log != null && log.isLoggable(Level.SEVERE)) {
661 log.severe(ExceptionToString.process(config.getMatchId().getToken() + ": EXCEPTION!", e));
662 }
663 exception = true;
664 if (e instanceof PogamutException) throw (PogamutException)e;
665 throw new PogamutException(e, log, this);
666 } finally {
667 try {
668 if (log != null && log.isLoggable(Level.INFO)) {
669 log.info(config.getMatchId().getToken() + ": Cleaning up...");
670 }
671 } catch (Exception e) {
672 }
673
674 if (ucc != null) {
675 try {
676 if (log != null && log.isLoggable(Level.INFO)) {
677 log.info(config.getMatchId().getToken() + ": Killing UCC...");
678 }
679 } catch (Exception e) {
680 }
681 try {
682 ucc.stop();
683 } catch (Exception e) {
684 }
685 }
686 if (server != null) {
687 try {
688 if (log != null && log.isLoggable(Level.INFO)) {
689 log.info(config.getMatchId().getToken() + ": Killing UT2004Server...");
690 }
691 } catch (Exception e) {
692 }
693 try {
694 server.kill();
695 } catch (Exception e) {
696 }
697 }
698 if (bots != null) {
699 try {
700 if (log != null && log.isLoggable(Level.INFO)) {
701 log.info(config.getMatchId().getToken() + ": Killing Custom bots...");
702 }
703 } catch (Exception e) {
704 }
705 for (UT2004BotExecution exec : bots.bots.values()) {
706 try {
707 exec.stop();
708 } catch (Exception e) {
709 }
710 }
711 try {
712 if (log != null && log.isLoggable(Level.INFO)) {
713 log.info(config.getMatchId().getToken() + ": Killing Custom bot observers...");
714 }
715 } catch (Exception e) {
716 }
717 for (IUT2004AnalyzerObserver obs : bots.botObservers.values()) {
718 try {
719 obs.kill();
720 } catch (Exception e) {
721 }
722 }
723 if (analyzer != null) {
724 }
725 try {
726 if (log != null && log.isLoggable(Level.INFO)) {
727 log.info(config.getMatchId().getToken() + ": Killing UT2004Analyzer...");
728 }
729 } catch (Exception e) {
730 }
731 try {
732 analyzer.kill();
733 } catch (Exception e) {
734 }
735 }
736
737 try {
738
739 restoreGB2004IniBackup();
740 } catch (Exception e) {
741 }
742
743 try {
744 if (log != null && log.isLoggable(Level.WARNING)) {
745 if (exception) {
746 log.warning(config.getMatchId().getToken() + ": Cleaned up, MATCH FAILED!");
747 } else {
748 log.warning(config.getMatchId().getToken() + ": Cleaned up, match finished successfully.");
749 }
750 }
751 } catch (Exception e) {
752 }
753 try {
754 closeLogger();
755 } catch (Exception e) {
756
757 }
758 }
759
760 }
761
762 }