1 package cz.cuni.amis.pogamut.ut2004.tournament.capturetheflag;
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.state.level0.IAgentState;
18 import cz.cuni.amis.pogamut.base.agent.state.level1.IAgentStateDown;
19 import cz.cuni.amis.pogamut.base.agent.state.level1.IAgentStateUp;
20 import cz.cuni.amis.pogamut.base.communication.worldview.event.IWorldEventListener;
21 import cz.cuni.amis.pogamut.base.communication.worldview.object.IWorldObjectEvent;
22 import cz.cuni.amis.pogamut.base.communication.worldview.object.IWorldObjectEventListener;
23 import cz.cuni.amis.pogamut.base.communication.worldview.object.IWorldObjectListener;
24 import cz.cuni.amis.pogamut.base.communication.worldview.object.event.WorldObjectUpdatedEvent;
25 import cz.cuni.amis.pogamut.base.utils.guice.AdaptableProvider;
26 import cz.cuni.amis.pogamut.base.utils.logging.LogCategory;
27 import cz.cuni.amis.pogamut.unreal.communication.messages.UnrealId;
28 import cz.cuni.amis.pogamut.ut2004.agent.module.sensor.AgentStats;
29 import cz.cuni.amis.pogamut.ut2004.analyzer.IUT2004AnalyzerObserver;
30 import cz.cuni.amis.pogamut.ut2004.analyzer.UT2004Analyzer;
31 import cz.cuni.amis.pogamut.ut2004.analyzer.stats.UT2004AnalyzerObsStats;
32 import cz.cuni.amis.pogamut.ut2004.communication.messages.gbcommands.StartPlayers;
33 import cz.cuni.amis.pogamut.ut2004.communication.messages.gbinfomessages.MapFinished;
34 import cz.cuni.amis.pogamut.ut2004.communication.messages.gbinfomessages.PlayerScore;
35 import cz.cuni.amis.pogamut.ut2004.communication.messages.gbinfomessages.TeamScore;
36 import cz.cuni.amis.pogamut.ut2004.communication.messages.gbinfomessages.TeamScoreMessage;
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.exception.PogamutException;
46 import cz.cuni.amis.utils.exception.PogamutIOException;
47 import cz.cuni.amis.utils.exception.PogamutInterruptedException;
48 import cz.cuni.amis.utils.flag.FlagListener;
49 import cz.cuni.amis.utils.token.IToken;
50
51 public class UT2004CaptureTheFlag extends UT2004Match<UT2004CaptureTheFlagConfig, UT2004CaptureTheFlagResult> {
52
53 protected int targetScoreLimit = 0;
54
55 public UT2004CaptureTheFlag(UT2004CaptureTheFlagConfig config, LogCategory log) {
56 super(true, config, log);
57 }
58
59 @Override
60 protected UT2004MatchResult waitMatchFinish(UCCWrapper ucc, UT2004Server server, UT2004Analyzer analyzer, Bots bots, long timeoutInMillis) {
61
62
63 if (log != null && log.isLoggable(Level.WARNING)) {
64 log.warning(config.getMatchId().getToken() + ": Waiting for the match to finish...");
65 }
66
67 if (config.getTimeLimit() * 60 * 1000 + 5 * 60 * 1000 > timeoutInMillis) {
68 timeoutInMillis = config.getTimeLimit() * 60 * 1000 + 5 * 60 * 1000;
69 }
70
71 Map<IToken, FlagListener<Boolean>> customBotObservers = new HashMap<IToken, FlagListener<Boolean>>(config.getBots().size());
72 FlagListener<IAgentState> serverObs = null;
73 FlagListener<Boolean> uccObs = null;
74 IWorldEventListener<PlayerScore> scoresListener = null;
75 IWorldObjectListener<TeamScore> teamScoresListener = null;
76 IWorldEventListener<MapFinished> mapFinishedListener = null;
77
78 final CountDownLatch waitLatch = new CountDownLatch(1);
79 final AdaptableProvider<Boolean> oneOfBotsDiedOut = new AdaptableProvider<Boolean>(false);
80 final AdaptableProvider<Boolean> serverDiedOut = new AdaptableProvider<Boolean>(false);
81 final Map<UnrealId, PlayerScore> scores = new HashMap<UnrealId, PlayerScore>();
82 final Map<Integer, TeamScore> teamScores = new HashMap<Integer, TeamScore>();
83
84 boolean exception = false;
85
86 try {
87 teamScores.put(0, new TeamScoreMessage(UnrealId.get("TEAM0"), 0, 0));
88 teamScores.put(1, new TeamScoreMessage(UnrealId.get("TEAM1"), 1, 0));
89 serverDiedOut.set(false);
90
91 scoresListener = new IWorldEventListener<PlayerScore>() {
92
93 @Override
94 public void notify(PlayerScore event) {
95 scores.put(event.getId(), event);
96 }
97
98 };
99 server.getWorldView().addEventListener(PlayerScore.class, scoresListener);
100
101 teamScoresListener = new IWorldObjectListener<TeamScore>() {
102
103 @Override
104 public void notify(IWorldObjectEvent<TeamScore> event) {
105 if (event.getObject() == null) return;
106 int team = event.getObject().getTeam();
107 teamScores.put(team, event.getObject());
108
109 if (event.getObject().getScore() >= targetScoreLimit) {
110
111 waitLatch.countDown();
112 }
113 }
114
115 };
116 server.getWorldView().addObjectListener(TeamScore.class, teamScoresListener);
117
118
119 for (UT2004BotConfig botConfig : config.getBots().values()) {
120 FlagListener<Boolean> obs = new FlagListener<Boolean>() {
121 @Override
122 public void flagChanged(Boolean changedValue) {
123 if (!changedValue) {
124
125 oneOfBotsDiedOut.set(true);
126 waitLatch.countDown();
127 }
128 }
129 };
130
131 bots.bots.get(botConfig.getBotId()).getRunning().addListener(obs);
132 customBotObservers.put(botConfig.getBotId(), obs);
133 if (!bots.bots.get(botConfig.getBotId()).getRunning().getFlag()) {
134
135 oneOfBotsDiedOut.set(true);
136 waitLatch.countDown();
137 throw new PogamutException("One of custom bots died out from the start, failure!", log, this);
138 }
139 }
140
141 serverObs = new FlagListener<IAgentState>() {
142
143 @Override
144 public void flagChanged(IAgentState changedValue) {
145 if (changedValue instanceof IAgentStateDown) {
146
147 serverDiedOut.set(true);
148 waitLatch.countDown();
149 }
150 }
151
152 };
153
154 server.getState().addListener(serverObs);
155
156 mapFinishedListener = new IWorldEventListener<MapFinished>() {
157 @Override
158 public void notify(MapFinished event) {
159 log.info("MapFinished event received.");
160 waitLatch.countDown();
161 }
162 };
163
164 server.getWorldView().addEventListener(MapFinished.class, mapFinishedListener);
165
166 if (server.notInState(IAgentStateUp.class)) {
167
168 serverDiedOut.set(true);
169 waitLatch.countDown();
170 throw new PogamutException("Server is dead from the start, failure!", log, this);
171 }
172
173 uccObs = new FlagListener<Boolean>() {
174
175 @Override
176 public void flagChanged(Boolean changedValue) {
177 if (changedValue) {
178
179
180 serverDiedOut.set(true);
181 waitLatch.countDown();
182 }
183 }
184
185 };
186
187 ucc.getGameEnding().addListener(uccObs);
188
189 waitLatch.await(timeoutInMillis, TimeUnit.MILLISECONDS);
190 if (waitLatch.getCount() > 0) {
191
192 throw new PogamutException("TIMEOUT! The match did not end in " + (timeoutInMillis / 1000) + " secs.", log, this);
193 }
194
195 bots.matchEnd = System.currentTimeMillis();
196
197
198 getConfig().setScoreLimit(targetScoreLimit);
199
200
201 if (oneOfBotsDiedOut.get()) {
202
203 try {
204 Thread.sleep(5000);
205 } catch (InterruptedException e) {
206 throw new PogamutInterruptedException("Interrupted while giving GB2004 time to tear down its connection.", log, this);
207 }
208 try {
209 server.getAct().act(new StartPlayers());
210 } catch (Exception e) {
211
212 serverDiedOut.set(true);
213 }
214 if (!serverDiedOut.get()) {
215
216 log.warning("ONE OF BOTS HAS DIED OUT, BUT SERVER IS STILL RUNNING ... POSSIBLE MATCH FAILURE!");
217 }
218 }
219 if (!serverDiedOut.get() && server.inState(IAgentStateUp.class)) {
220
221 server.kill();
222 }
223
224
225
226 if (ucc != null) {
227 try {
228 if (log != null && log.isLoggable(Level.INFO)) {
229 log.info(config.getMatchId().getToken() + ": Killing UCC...");
230 }
231 } catch (Exception e) {
232 }
233 try {
234 ucc.stop();
235 } catch (Exception e) {
236 }
237 }
238
239 List<Integer> winners = new ArrayList<Integer>(1);
240 int maxScore = 0;
241
242
243 for (Entry<Integer, TeamScore> entry : teamScores.entrySet()) {
244 if (entry.getValue() == null || entry.getValue().getScore() == null) {
245 throw new PogamutException("There is a team '" + entry.getKey() + "' that has NULL score!", this);
246 }
247 if (entry.getValue().getScore() == maxScore) {
248 winners.add(entry.getValue().getTeam());
249 } else
250 if (entry.getValue().getScore() > maxScore) {
251 winners.clear();
252 winners.add(entry.getValue().getTeam());
253 maxScore = entry.getValue().getScore();
254 }
255 }
256
257 if (winners.size() == 0) {
258
259 throw new PogamutException("There is no winner, impossible! **puzzled**", log, this);
260 }
261 if (winners.size() > 1) {
262 StringBuffer sb = new StringBuffer();
263 sb.append("There is more than one team with highest score == " + maxScore + ": ");
264 boolean first = true;
265 for (Integer id : winners) {
266 if (first) first = false;
267 else sb.append(", ");
268 sb.append("Team[" + id + "]");
269 }
270 sb.append(".");
271 if (log != null && log.isLoggable(Level.WARNING)) {
272 log.warning(sb.toString());
273 }
274 }
275
276 if (log != null && log.isLoggable(Level.WARNING)) {
277 log.warning(config.getMatchId().getToken() + ": MATCH FINISHED!");
278 }
279
280 return processResults(ucc, server, analyzer, bots, winners, scores, teamScores);
281
282 } catch (Exception e) {
283 exception = true;
284 throw new PogamutException("Failed to perform the match!", e, log, this);
285 } finally {
286 for (Entry<IToken, FlagListener<Boolean>> entry : customBotObservers.entrySet()) {
287 bots.bots.get(entry.getKey()).getRunning().removeListener(entry.getValue());
288 }
289 server.getState().removeListener(serverObs);
290 server.getWorldView().removeEventListener(PlayerScore.class, scoresListener);
291 }
292
293 }
294
295 protected UT2004CaptureTheFlagResult processResults(UCCWrapper ucc, UT2004Server server, UT2004Analyzer analyzer, Bots bots, List<Integer> winners, Map<UnrealId, PlayerScore> finalScores, Map<Integer, TeamScore> teamScores) {
296
297 if (log != null && log.isLoggable(Level.FINE)) {
298 log.fine(config.getMatchId().getToken() + ": Processing results...");
299 }
300
301 UT2004CaptureTheFlagResult result = new UT2004CaptureTheFlagResult();
302
303 result.setMatchTimeEnd(((double)bots.matchEnd - (double)bots.matchStart) / (1000));
304
305 for (Entry<Integer, TeamScore> entry : teamScores.entrySet()) {
306 result.getTeamScores().put(entry.getKey(), entry.getValue());
307 }
308
309 for (Entry<UnrealId, PlayerScore> entry : finalScores.entrySet()) {
310 result.getFinalScores().put(bots.getBotId(entry.getKey()), entry.getValue());
311 }
312
313 for (Entry<IToken, IUT2004AnalyzerObserver> entry : bots.botObservers.entrySet()) {
314 if (!(entry.getValue() instanceof UT2004AnalyzerObsStats)) {
315 throw new PogamutException("There is an observer of wrong class, expecting UT2004AnalyzerObsStats, got " + entry.getValue().getClass().getSimpleName() + "!", log, this);
316 }
317 result.getBotObservers().put(entry.getKey(), (UT2004AnalyzerObsStats)entry.getValue());
318 }
319
320 List<IToken> botIds = config.getAllBotIds();
321 for (IToken botId1 : botIds) {
322 result.getNames().put(botId1, bots.names.get(bots.getUnrealId(botId1)));
323 result.getTotalKills().put(botId1, 0);
324 result.getWasKilled().put(botId1, 0);
325 result.getSuicides().put(botId1, 0);
326 for (IToken botId2 : botIds) {
327 result.getKillCounts().put(botId1, botId2, 0);
328 }
329 }
330
331 for (Entry<IToken, UT2004AnalyzerObsStats> entry : result.getBotObservers().entrySet()) {
332 IToken botId = entry.getKey();
333 UT2004AnalyzerObsStats obs = entry.getValue();
334 AgentStats stats = obs.getStats();
335 for (Entry<UnrealId, Integer> killed : stats.getKilled().entrySet()) {
336 result.getKillCounts().get(botId).put(bots.getBotId(killed.getKey()), killed.getValue());
337 }
338 for (Entry<UnrealId, Integer> killedBy : stats.getKilledBy().entrySet()) {
339 if (bots.isNativeBot(killedBy.getKey())) {
340 result.getKillCounts().get(bots.getBotId(killedBy.getKey())).put(botId, killedBy.getValue());
341 }
342 }
343 result.getSuicides().put(botId, stats.getSuicides());
344 result.getKillCounts().put(botId, botId, stats.getSuicides());
345 }
346
347 for (IToken nativeBotId1 : config.getNativeBots().keySet()) {
348 for (IToken nativeBotId2 : config.getNativeBots().keySet()) {
349 if (nativeBotId1 == nativeBotId2) continue;
350 result.getKillCounts().get(nativeBotId1).put(nativeBotId2, 0);
351 }
352 result.getSuicides().put(nativeBotId1, 0);
353 }
354
355 for (IToken botId : botIds) {
356 int totalKills = 0;
357 int totalKilled = 0;
358 for (IToken other : botIds) {
359 if (botId == other) continue;
360 totalKills += result.getKillCounts().get(botId, other);
361 totalKilled += result.getKillCounts().get(other, botId);
362 }
363 result.getTotalKills().put(botId, totalKills);
364 result.getWasKilled().put(botId, totalKilled);
365 if (config.isNativeBot(botId) || config.isHuman(botId)) {
366 result.getSuicides().put(botId, result.getFinalScores().get(botId).getDeaths() - totalKilled);
367 }
368 }
369
370 if (winners.size() <= 0) {
371 throw new PogamutException("There is no winner, impossible! **puzzled**", log, this);
372 } else
373 if (winners.size() == 1) {
374 result.setWinnerTeam(winners.get(0));
375 } else {
376 result.setDraw(true);
377 }
378
379 if (log != null && log.isLoggable(Level.WARNING)) {
380 log.warning(config.getMatchId().getToken() + ": Results processed, " + (result.isDraw() ? "DRAW!" : "winner is Team[" + winners.get(0) + "]."));
381 }
382
383 return result;
384 }
385
386 protected void outputResults_step1(UT2004CaptureTheFlagResult result, File outputDirectory) {
387 if (log != null && log.isLoggable(Level.FINE)) {
388 log.fine(config.getMatchId().getToken() + ": Outputting match result into CSV file...");
389 }
390
391 File file = new File(outputDirectory.getAbsolutePath() + File.separator + "match-" + config.getMatchId().getToken() + "-result.csv");
392 FilePath.makeDirsToFile(file);
393 try {
394 Formatter writer = new Formatter(file);
395 writer.format("MatchId;ScoreLimit;TimeLimit;TimeEnd;Winner\n");
396 writer.format
397 (
398 "%s;%d;%d;%.3f;%s",
399 config.getMatchId().getToken(),
400 config.getScoreLimit(),
401 config.getTimeLimit(),
402 result.getMatchTimeEnd(),
403 result.isDraw() ? "DRAW" : "TEAM" + String.valueOf(result.getWinnerTeam())
404 );
405 try {
406 writer.close();
407 } catch (Exception e) {
408 }
409 } catch (IOException e) {
410 throw new PogamutIOException("Failed to write results!", e, log, this);
411 }
412
413 if (log != null && log.isLoggable(Level.INFO)) {
414 log.info(config.getMatchId().getToken() + ": Match result output into " + file.getAbsolutePath() + ".");
415 }
416
417 }
418
419 protected void outputResults_step2(UT2004CaptureTheFlagResult result, File outputDirectory) {
420 if (log != null && log.isLoggable(Level.FINE)) {
421 log.fine(config.getMatchId().getToken() + ": Outputting match scores into CSV file...");
422 }
423
424 File file = new File(outputDirectory.getAbsolutePath() + File.separator + "match-" + config.getMatchId().getToken() + "-team-scores.csv");
425 FilePath.makeDirsToFile(file);
426 try {
427 Formatter writer = new Formatter(file);
428
429 List<TeamScore> teams = new ArrayList<TeamScore>();
430 for (TeamScore score : result.getTeamScores().values()) {
431 teams.add(score);
432 }
433
434 Collections.sort(teams, new Comparator<TeamScore>() {
435 @Override
436 public int compare(TeamScore o1, TeamScore o2) {
437 return o1.getTeam().compareTo(o2.getTeam());
438 }
439 });
440
441 writer.format("teamId");
442 writer.format(";score");
443
444 for (TeamScore score : teams) {
445 writer.format("\n");
446 writer.format("%s", "TEAM" + score.getTeam());
447 writer.format(";%d", score.getScore());
448 }
449
450 try {
451 writer.close();
452 } catch (Exception e) {
453 }
454 } catch (IOException e) {
455 throw new PogamutIOException("Failed to write results!", e, log, this);
456 }
457
458 file = new File(outputDirectory.getAbsolutePath() + File.separator + "match-" + config.getMatchId().getToken() + "-bot-scores.csv");
459 FilePath.makeDirsToFile(file);
460 try {
461 Formatter writer = new Formatter(file);
462
463 List<IToken> bots = new ArrayList<IToken>(config.getBots().keySet());
464 List<IToken> nativeBots = new ArrayList<IToken>(config.getNativeBots().keySet());
465 List<IToken> humans = new ArrayList<IToken>(config.getHumans().keySet());
466
467 Collections.sort(bots, new Comparator<IToken>() {
468 @Override
469 public int compare(IToken o1, IToken o2) {
470 return o1.getToken().compareTo(o2.getToken());
471 }
472 });
473 Collections.sort(nativeBots, new Comparator<IToken>() {
474 @Override
475 public int compare(IToken o1, IToken o2) {
476 return o1.getToken().compareTo(o2.getToken());
477 }
478 });
479 Collections.sort(humans, new Comparator<IToken>() {
480 @Override
481 public int compare(IToken o1, IToken o2) {
482 return o1.getToken().compareTo(o2.getToken());
483 }
484 });
485 result.setBots(bots);
486 result.setNativeBots(nativeBots);
487 result.setHumans(humans);
488
489 writer.format("botId");
490 writer.format(";name;score;kills;killedByOthers;deaths;suicides");
491 for (IToken token : config.getAllBotIds()) {
492 writer.format(";");
493 writer.format(token.getToken());
494 }
495
496 for (IToken token : config.getAllBotIds()) {
497 writer.format("\n");
498 writer.format(token.getToken());
499 writer.format(";%s", result.getNames().get(token));
500 writer.format(";%d", result.getFinalScores().get(token).getScore());
501 writer.format(";%d", result.getTotalKills().get(token));
502 writer.format(";%d", result.getWasKilled().get(token));
503 writer.format(";%d", result.getFinalScores().get(token).getDeaths());
504 writer.format(";%d", result.getSuicides().get(token));
505 for (IToken token2 : config.getAllBotIds()) {
506 writer.format(";%d", result.getKillCounts().get(token).get(token2));
507 }
508 }
509
510 try {
511 writer.close();
512 } catch (Exception e) {
513 }
514 } catch (IOException e) {
515 throw new PogamutIOException("Failed to write results!", e, log, this);
516 }
517
518 if (log != null && log.isLoggable(Level.INFO)) {
519 log.info(config.getMatchId().getToken() + ": Match scores output into " + file.getAbsolutePath() + ".");
520 }
521
522 }
523
524 @Override
525 protected void outputResults(UCCWrapper ucc, UT2004Server server, UT2004Analyzer analyzer, Bots bots, UT2004MatchResult result, File outputDirectory) {
526 if (!(result instanceof UT2004CaptureTheFlagResult)) {
527 throw new PogamutException("Can't out results! Expected results of class UT2004CaptureTheFlagResult and got " + result.getClass().getSimpleName() + "!", log, this);
528 }
529 outputResults_step1((UT2004CaptureTheFlagResult) result, outputDirectory);
530 outputResults_step2((UT2004CaptureTheFlagResult) result, outputDirectory);
531 }
532
533 @Override
534 public UT2004CaptureTheFlagResult execute() {
535 try {
536 if (log != null && log.isLoggable(Level.WARNING)) {
537 log.warning(config.getMatchId().getToken() + ": Executing!");
538 }
539 } catch (Exception e) {
540 }
541
542 UCCWrapper ucc = null;
543 UT2004Server server = null;
544 Bots bots = null;
545 UT2004Analyzer analyzer = null;
546 String recordFileName = config.getMatchId().getToken() + "-replay-" + UT2004Match.getCurrentDate();
547 boolean exception = false;
548
549
550
551
552 targetScoreLimit = getConfig().getScoreLimit();
553 getConfig().setScoreLimit(targetScoreLimit + 10);
554
555
556 try {
557
558 setupLogger();
559
560
561 validate();
562
563
564 createUT2004Ini();
565
566
567 createGB2004Ini();
568
569
570 ucc = startUCC();
571
572
573 server = startControlServer(ucc);
574
575
576 bots = startBots(ucc, server);
577
578
579 waitHumanPlayers(server, bots);
580
581
582 analyzer = startAnalyzer(ucc, bots, getOutputPath("bots"), false);
583
584
585 matchIsAboutToBegin(ucc, server, analyzer, bots);
586
587
588 restartMatch(server, bots);
589
590
591 recordReplay(server, recordFileName);
592
593
594 UT2004CaptureTheFlagResult result = (UT2004CaptureTheFlagResult) waitMatchFinish(ucc, server, analyzer, bots, config.getTimeLimit() * 1000 + 60 * 1000);
595
596
597 copyReplay(ucc, recordFileName, getOutputPath());
598
599
600 outputResults(ucc, server, analyzer, bots, result, getOutputPath());
601
602
603 shutdownAll(ucc, server, analyzer, bots);
604
605 ucc = null;
606 server = null;
607 analyzer = null;
608 bots = null;
609
610
611 return result;
612
613 } catch (Exception e) {
614 if (log != null && log.isLoggable(Level.SEVERE)) {
615 log.severe(ExceptionToString.process(config.getMatchId().getToken() + ": EXCEPTION!", e));
616 }
617 exception = true;
618 if (e instanceof PogamutException) throw (PogamutException)e;
619 throw new PogamutException(e, log, this);
620 } finally {
621 try {
622 if (log != null && log.isLoggable(Level.INFO)) {
623 log.info(config.getMatchId().getToken() + ": Cleaning up...");
624 }
625 } catch (Exception e) {
626 }
627
628 if (ucc != null) {
629 try {
630 if (log != null && log.isLoggable(Level.INFO)) {
631 log.info(config.getMatchId().getToken() + ": Killing UCC...");
632 }
633 } catch (Exception e) {
634 }
635 try {
636 ucc.stop();
637 } catch (Exception e) {
638 }
639 }
640 if (server != null) {
641 try {
642 if (log != null && log.isLoggable(Level.INFO)) {
643 log.info(config.getMatchId().getToken() + ": Killing UT2004Server...");
644 }
645 } catch (Exception e) {
646 }
647 try {
648 server.kill();
649 } catch (Exception e) {
650 }
651 }
652 if (bots != null) {
653 try {
654 if (log != null && log.isLoggable(Level.INFO)) {
655 log.info(config.getMatchId().getToken() + ": Killing Custom bots...");
656 }
657 } catch (Exception e) {
658 }
659 for (UT2004BotExecution exec : bots.bots.values()) {
660 try {
661 exec.stop();
662 } catch (Exception e) {
663 }
664 }
665 try {
666 if (log != null && log.isLoggable(Level.INFO)) {
667 log.info(config.getMatchId().getToken() + ": Killing Custom bot observers...");
668 }
669 } catch (Exception e) {
670 }
671 for (IUT2004AnalyzerObserver obs : bots.botObservers.values()) {
672 try {
673 obs.kill();
674 } catch (Exception e) {
675 }
676 }
677 }
678 if (analyzer != null) {
679 try {
680 if (log != null && log.isLoggable(Level.INFO)) {
681 log.info(config.getMatchId().getToken() + ": Killing UT2004Analyzer...");
682 }
683 } catch (Exception e) {
684 }
685 try {
686 analyzer.kill();
687 } catch (Exception e) {
688 }
689 }
690
691 try {
692
693 restoreUT2004IniBackup();
694 } catch (Exception e) {
695 }
696
697 try {
698
699 restoreGB2004IniBackup();
700 } catch (Exception e) {
701 }
702
703 try {
704 if (log != null && log.isLoggable(Level.WARNING)) {
705 if (exception) {
706 log.warning(config.getMatchId().getToken() + ": Cleaned up, MATCH FAILED!");
707 } else {
708 log.warning(config.getMatchId().getToken() + ": Cleaned up, match finished successfully.");
709 }
710 }
711 } catch (Exception e) {
712 }
713 try {
714 closeLogger();
715 } catch (Exception e) {
716
717 }
718 }
719
720 }
721
722 }