CPD Results

The following document contains the results of PMD's CPD 4.2.5.

Duplications

FileLine
cz/cuni/amis/pogamut/ut2004/tournament/capturetheflag/UT2004CaptureTheFlag.java55
cz/cuni/amis/pogamut/ut2004/tournament/teamdeathmatch/UT2004TeamDeathMatch.java53
	public UT2004TeamDeathMatch(UT2004TeamDeathMatchConfig config, LogCategory log) {
		super(true, config, log);		
	}

	@Override
	protected UT2004MatchResult waitMatchFinish(UCCWrapper ucc, UT2004Server server, UT2004Analyzer analyzer, Bots bots, long timeoutInMillis) {
		// usually the GB2004 dies out whenever match ends -> just wait till server does not fail + timeout + observe bots
		
		if (log != null && log.isLoggable(Level.WARNING)) {
			log.warning(config.getMatchId().getToken() + ": Waiting for the match to finish...");
		}
		
		if (config.getTimeLimit() * 60 * 1000 + 5 * 60 * 1000 > timeoutInMillis) {
			timeoutInMillis = config.getTimeLimit() * 60 * 1000 + 5 * 60 * 1000; // give additional 5 minutes to UT2004 to restart GB2004
		}
		
		Map<IToken, FlagListener<Boolean>> customBotObservers = new HashMap<IToken, FlagListener<Boolean>>(config.getBots().size());
		FlagListener<IAgentState> serverObs = null;
		FlagListener<Boolean> uccObs = null;
		IWorldEventListener<PlayerScore> scoresListener = null;
		IWorldObjectListener<TeamScore> teamScoresListener = null;
		IWorldEventListener<MapFinished> mapFinishedListener = null;
		
		final CountDownLatch waitLatch = new CountDownLatch(1);
		final AdaptableProvider<Boolean> oneOfBotsDiedOut = new AdaptableProvider<Boolean>(false);
		final AdaptableProvider<Boolean> serverDiedOut    = new AdaptableProvider<Boolean>(false);
		final Map<UnrealId, PlayerScore> scores           = new HashMap<UnrealId, PlayerScore>();
		final Map<Integer, TeamScore>    teamScores       = new HashMap<Integer, TeamScore>();
		
		boolean exception = false;
		
		try {
			teamScores.put(0, new TeamScoreMessage(UnrealId.get("TEAM0"), 0, 0));
			teamScores.put(1, new TeamScoreMessage(UnrealId.get("TEAM1"), 1, 0));
			serverDiedOut.set(false);
			
			scoresListener = new IWorldEventListener<PlayerScore>() {

				@Override
				public void notify(PlayerScore event) {
					scores.put(event.getId(), event);
				}
				
			};
			server.getWorldView().addEventListener(PlayerScore.class, scoresListener);
			
			teamScoresListener = new IWorldObjectListener<TeamScore>() {

				@Override
				public void notify(IWorldObjectEvent<TeamScore> event) {
					if (event.getObject() == null) return;
					int team = event.getObject().getTeam();
					teamScores.put(team, event.getObject());
					
					if (event.getObject().getScore() >= targetScoreLimit) {
						// TARGET SCORE REACHED BY ONE OF THE TEAMS!
						waitLatch.countDown();
					}
				}
				
			};
			server.getWorldView().addObjectListener(TeamScore.class, teamScoresListener);

			
			for (UT2004BotConfig botConfig : config.getBots().values()) {
				FlagListener<Boolean> obs = new FlagListener<Boolean>() {
					@Override
					public void flagChanged(Boolean changedValue) {
						if (!changedValue) {
							// bot has died out
							oneOfBotsDiedOut.set(true);
							waitLatch.countDown();
						}
					}
				};
				
				bots.bots.get(botConfig.getBotId()).getRunning().addListener(obs);
				customBotObservers.put(botConfig.getBotId(), obs);
				if (!bots.bots.get(botConfig.getBotId()).getRunning().getFlag()) {
					// bot has died out
					oneOfBotsDiedOut.set(true);
					waitLatch.countDown();
					throw new PogamutException("One of custom bots died out from the start, failure!", log, this);
				}			
			}
			
			serverObs = new FlagListener<IAgentState>() {
	
				@Override
				public void flagChanged(IAgentState changedValue) {
					if (changedValue instanceof IAgentStateDown) {
						// server has died out ... consider match to be over...
						serverDiedOut.set(true);
						waitLatch.countDown();
					}
				}
				
			};
			
			server.getState().addListener(serverObs);
			
			mapFinishedListener = new IWorldEventListener<MapFinished>() {
				@Override
				public void notify(MapFinished event) {
					log.info("MapFinished event received.");
					waitLatch.countDown();
				}
			};
			
			server.getWorldView().addEventListener(MapFinished.class, mapFinishedListener);
			
			if (server.notInState(IAgentStateUp.class)) {
				// server has died out ... consider match to be over...
				serverDiedOut.set(true);
				waitLatch.countDown();
				throw new PogamutException("Server is dead from the start, failure!", log, this);
			}
			
			uccObs = new FlagListener<Boolean>() {

				@Override
				public void flagChanged(Boolean changedValue) {
					if (changedValue) {
						// GAME IS ENDING!
						// Consider match to be over...
						serverDiedOut.set(true);
						waitLatch.countDown();
					}
				}
				
			};
			
			ucc.getGameEnding().addListener(uccObs);
			
			waitLatch.await(timeoutInMillis, TimeUnit.MILLISECONDS);
			if (waitLatch.getCount() > 0) {
				// TIMEOUT!
				throw new PogamutException("TIMEOUT! The match did not end in " + (timeoutInMillis / 1000) + " secs.", log, this);
			}
			
			bots.matchEnd = System.currentTimeMillis();
			
			// RESTORE THE CONFIG...
			getConfig().setScoreLimit(targetScoreLimit); 
			
			// WHAT HAS HAPPENED?
			if (oneOfBotsDiedOut.get()) {
				// check whether the server is down as well... but let GB2004 to process it
				try {
					Thread.sleep(5000);
				} catch (InterruptedException e) {
					throw new PogamutInterruptedException("Interrupted while giving GB2004 time to tear down its connection.", log, this);
				}
				try {
					server.getAct().act(new StartPlayers());
				} catch (Exception e) {
					// YEP, server is down
					serverDiedOut.set(true);
				}
				if (!serverDiedOut.get()) {
					// NO SERVER IS STILL RUNNING
					log.warning("ONE OF BOTS HAS DIED OUT, BUT SERVER IS STILL RUNNING ... POSSIBLE MATCH FAILURE!");
				}
			}
			if (!serverDiedOut.get() && server.inState(IAgentStateUp.class)) {
				// server is still running? Kill it...
				server.kill();
			}
			// server is DEAD -> assume that the match has ended
			
			// KILL UCC TO ENSURE NOTHING WILL CHANGE AFTER THAT
			if (ucc != null) {
				try {
					if (log != null && log.isLoggable(Level.INFO)) {
						log.info(config.getMatchId().getToken() + ": Killing UCC...");
					} 
				} catch (Exception e) {				
				}
				try {
					ucc.stop();
				} catch (Exception e) {					
				}
			}
			
			List<Integer> winners = new ArrayList<Integer>(1);
			int maxScore = 0;
			
			// PROCESS THE RESULT
			for (Entry<Integer, TeamScore> entry : teamScores.entrySet()) {
				if (entry.getValue() == null || entry.getValue().getScore() == null) {
					throw new PogamutException("There is a team '" + entry.getKey() + "' that has NULL score!", this);
				}
				if (entry.getValue().getScore() == maxScore) {
					winners.add(entry.getValue().getTeam());
				} else
				if (entry.getValue().getScore() > maxScore) {
					winners.clear();
					winners.add(entry.getValue().getTeam());
					maxScore = entry.getValue().getScore();
				}
			}
			
			if (winners.size() == 0) {
				// no one has reached FragLimit
				throw new PogamutException("There is no winner, impossible! **puzzled**", log, this);
			}
			if (winners.size() > 1) {
				StringBuffer sb = new StringBuffer();
				sb.append("There is more than one team with highest score == " + maxScore + ": ");
				boolean first = true;
				for (Integer id : winners) {
					if (first) first = false;
					else sb.append(", ");
					sb.append("Team[" + id + "]");
				}
				sb.append(".");
				if (log != null && log.isLoggable(Level.WARNING)) {
					log.warning(sb.toString());
				}
			}
			
			if (log != null && log.isLoggable(Level.WARNING)) {
				log.warning(config.getMatchId().getToken() + ": MATCH FINISHED!");
			}
			
			return processResults(ucc, server, analyzer, bots, winners, scores, teamScores);
			
		} catch (Exception e) {
			exception = true;
			throw new PogamutException("Failed to perform the match!", e, log, this);
		} finally {
			for (Entry<IToken, FlagListener<Boolean>> entry : customBotObservers.entrySet()) {
				bots.bots.get(entry.getKey()).getRunning().removeListener(entry.getValue());
			}
			server.getState().removeListener(serverObs);
			server.getWorldView().removeEventListener(PlayerScore.class, scoresListener);
		}		

	}
	
	protected UT2004TeamDeathMatchResult processResults(UCCWrapper ucc, UT2004Server server, UT2004Analyzer analyzer, Bots bots, List<Integer> winners, Map<UnrealId, PlayerScore> finalScores, Map<Integer, TeamScore> teamScores) {
FileLine
cz/cuni/amis/pogamut/ut2004/tournament/capturetheflag/UT2004CaptureTheFlag.java419
cz/cuni/amis/pogamut/ut2004/tournament/teamdeathmatch/UT2004TeamDeathMatch.java417
	protected void outputResults_step2(UT2004TeamDeathMatchResult result, File outputDirectory) {
		if (log != null && log.isLoggable(Level.FINE)) {
			log.fine(config.getMatchId().getToken() + ": Outputting match scores into CSV file...");
		}
		
		File file = new File(outputDirectory.getAbsolutePath() + File.separator + "match-" + config.getMatchId().getToken() + "-team-scores.csv");
		FilePath.makeDirsToFile(file);
		try {
			Formatter writer = new Formatter(file);
			
			List<TeamScore> teams = new ArrayList<TeamScore>();
			for (TeamScore score : result.getTeamScores().values()) {
				teams.add(score);
			}
			
			Collections.sort(teams, new Comparator<TeamScore>() {
				@Override
				public int compare(TeamScore o1, TeamScore o2) {
					return o1.getTeam().compareTo(o2.getTeam());
				}				
			});
			
			writer.format("teamId");
			writer.format(";score");
			
			for (TeamScore score : teams) {
				writer.format("\n");
				writer.format("%s", "TEAM" + score.getTeam());
				writer.format(";%d", score.getScore());								
			}
			
			try {
				writer.close();
			} catch (Exception e) {			
			}
		} catch (IOException e) {
			throw new PogamutIOException("Failed to write results!", e, log, this);
		}
		
		file = new File(outputDirectory.getAbsolutePath() + File.separator + "match-" + config.getMatchId().getToken() + "-bot-scores.csv");
		FilePath.makeDirsToFile(file);
		try {
			Formatter writer = new Formatter(file);
			
			List<IToken> bots = new ArrayList<IToken>(config.getBots().keySet());
			List<IToken> nativeBots = new ArrayList<IToken>(config.getNativeBots().keySet());
			List<IToken> humans = new ArrayList<IToken>(config.getHumans().keySet());
			
			Collections.sort(bots, new Comparator<IToken>() {
				@Override
				public int compare(IToken o1, IToken o2) {
					return o1.getToken().compareTo(o2.getToken());
				}				
			});
			Collections.sort(nativeBots, new Comparator<IToken>() {
				@Override
				public int compare(IToken o1, IToken o2) {
					return o1.getToken().compareTo(o2.getToken());
				}				
			});
			Collections.sort(humans, new Comparator<IToken>() {
				@Override
				public int compare(IToken o1, IToken o2) {
					return o1.getToken().compareTo(o2.getToken());
				}				
			});
			result.setBots(bots);
			result.setNativeBots(nativeBots);
			result.setHumans(humans);
			
			writer.format("botId");
			writer.format(";name;score;kills;killedByOthers;deaths;suicides");
			for (IToken token : config.getAllBotIds()) {
				writer.format(";");
				writer.format(token.getToken());
			}
			
			for (IToken token : config.getAllBotIds()) {
				writer.format("\n");
				writer.format(token.getToken());
				writer.format(";%s", result.getNames().get(token));
				writer.format(";%d", result.getFinalScores().get(token).getScore());
				writer.format(";%d", result.getTotalKills().get(token));
				writer.format(";%d", result.getWasKilled().get(token));
				writer.format(";%d", result.getFinalScores().get(token).getDeaths());
				writer.format(";%d", result.getSuicides().get(token));				
				for (IToken token2 : config.getAllBotIds()) {
					writer.format(";%d", result.getKillCounts().get(token).get(token2));
				}				
			}
			
			try {
				writer.close();
			} catch (Exception e) {			
			}
		} catch (IOException e) {
			throw new PogamutIOException("Failed to write results!", e, log, this);
		}
		
		if (log != null && log.isLoggable(Level.INFO)) {
			log.info(config.getMatchId().getToken() + ": Match scores output into " + file.getAbsolutePath() + ".");
		}
		
	}
	
	@Override
	protected void outputResults(UCCWrapper ucc, UT2004Server server, UT2004Analyzer analyzer, Bots bots, UT2004MatchResult result,	File outputDirectory) {
		if (!(result instanceof UT2004TeamDeathMatchResult)) {
FileLine
cz/cuni/amis/pogamut/ut2004/tournament/capturetheflag/UT2004CaptureTheFlag.java301
cz/cuni/amis/pogamut/ut2004/tournament/teamdeathmatch/UT2004TeamDeathMatch.java299
		UT2004TeamDeathMatchResult result = new UT2004TeamDeathMatchResult();
		
		result.setMatchTimeEnd(((double)bots.matchEnd - (double)bots.matchStart) / (1000));
		
		for (Entry<Integer, TeamScore> entry : teamScores.entrySet()) {
			result.getTeamScores().put(entry.getKey(), entry.getValue());
		}
		
		for (Entry<UnrealId, PlayerScore> entry : finalScores.entrySet()) {
			result.getFinalScores().put(bots.getBotId(entry.getKey()), entry.getValue());
		}
		
		for (Entry<IToken, IUT2004AnalyzerObserver> entry : bots.botObservers.entrySet()) {
			if (!(entry.getValue() instanceof UT2004AnalyzerObsStats)) {
				throw new PogamutException("There is an observer of wrong class, expecting UT2004AnalyzerObsStats, got " + entry.getValue().getClass().getSimpleName() + "!", log, this);
			}
			result.getBotObservers().put(entry.getKey(), (UT2004AnalyzerObsStats)entry.getValue());
		}
		
		List<IToken> botIds = config.getAllBotIds();
		for (IToken botId1 : botIds) {
			result.getNames().put(botId1, bots.names.get(bots.getUnrealId(botId1)));
			result.getTotalKills().put(botId1, 0);
			result.getWasKilled().put(botId1, 0);
			result.getSuicides().put(botId1, 0);
			for (IToken botId2 : botIds) {
				result.getKillCounts().put(botId1, botId2, 0);
			}
		}
		
		for (Entry<IToken, UT2004AnalyzerObsStats> entry : result.getBotObservers().entrySet()) {
			IToken botId = entry.getKey();
			UT2004AnalyzerObsStats obs = entry.getValue();
			AgentStats stats = obs.getStats();
			for (Entry<UnrealId, Integer> killed : stats.getKilled().entrySet()) {
				result.getKillCounts().get(botId).put(bots.getBotId(killed.getKey()), killed.getValue());				
			}
			for (Entry<UnrealId, Integer> killedBy : stats.getKilledBy().entrySet()) {
				if (bots.isNativeBot(killedBy.getKey())) {
					result.getKillCounts().get(bots.getBotId(killedBy.getKey())).put(botId, killedBy.getValue());
				}
			}
			result.getSuicides().put(botId, stats.getSuicides());
			result.getKillCounts().put(botId, botId, stats.getSuicides());
		}
		
		for (IToken nativeBotId1 : config.getNativeBots().keySet()) {
			for (IToken nativeBotId2 : config.getNativeBots().keySet()) {
				if (nativeBotId1 == nativeBotId2) continue;
				result.getKillCounts().get(nativeBotId1).put(nativeBotId2, 0);
			}
			result.getSuicides().put(nativeBotId1, 0);
		}
		
		for (IToken botId : botIds) {
			int totalKills = 0;
			int totalKilled = 0;
			for (IToken other : botIds) {
				if (botId == other) continue;
				totalKills += result.getKillCounts().get(botId, other);
				totalKilled += result.getKillCounts().get(other, botId);
			}
			result.getTotalKills().put(botId, totalKills);
			result.getWasKilled().put(botId, totalKilled);
			if (config.isNativeBot(botId) || config.isHuman(botId)) {
				result.getSuicides().put(botId, result.getFinalScores().get(botId).getDeaths() - totalKilled);
			}
		}
		
		if (winners.size() <= 0) {
			throw new PogamutException("There is no winner, impossible! **puzzled**", log, this);
		} else 
		if (winners.size() == 1) {
			result.setWinnerTeam(winners.get(0));
		} else {
			result.setDraw(true);
		}
		
		if (log != null && log.isLoggable(Level.WARNING)) {
			log.warning(config.getMatchId().getToken() + ": Results processed, " + (result.isDraw() ? "DRAW!" : "winner is Team[" + winners.get(0) + "]."));
		}
		
		return result;
	}
	
	protected void outputResults_step1(UT2004TeamDeathMatchResult result, File outputDirectory) {
FileLine
cz/cuni/amis/pogamut/ut2004/tournament/capturetheflag/UT2004CaptureTheFlag.java309
cz/cuni/amis/pogamut/ut2004/tournament/deathmatch/UT2004DeathMatch.java280
		for (Entry<UnrealId, PlayerScore> entry : finalScores.entrySet()) {
			result.getFinalScores().put(bots.getBotId(entry.getKey()), entry.getValue());
		}
		
		for (Entry<IToken, IUT2004AnalyzerObserver> entry : bots.botObservers.entrySet()) {
			if (!(entry.getValue() instanceof UT2004AnalyzerObsStats)) {
				throw new PogamutException("There is an observer of wrong class, expecting UT2004AnalyzerObsStats, got " + entry.getValue().getClass().getSimpleName() + "!", log, this);
			}
			result.getBotObservers().put(entry.getKey(), (UT2004AnalyzerObsStats)entry.getValue());
		}
		
		List<IToken> botIds = config.getAllBotIds();
		for (IToken botId1 : botIds) {
			result.getNames().put(botId1, bots.names.get(bots.getUnrealId(botId1)));
			result.getTotalKills().put(botId1, 0);
			result.getWasKilled().put(botId1, 0);
			result.getSuicides().put(botId1, 0);
			for (IToken botId2 : botIds) {
				result.getKillCounts().put(botId1, botId2, 0);
			}
		}
		
		for (Entry<IToken, UT2004AnalyzerObsStats> entry : result.getBotObservers().entrySet()) {
			IToken botId = entry.getKey();
			UT2004AnalyzerObsStats obs = entry.getValue();
			AgentStats stats = obs.getStats();
			for (Entry<UnrealId, Integer> killed : stats.getKilled().entrySet()) {
				result.getKillCounts().get(botId).put(bots.getBotId(killed.getKey()), killed.getValue());				
			}
			for (Entry<UnrealId, Integer> killedBy : stats.getKilledBy().entrySet()) {
				if (bots.isNativeBot(killedBy.getKey())) {
					result.getKillCounts().get(bots.getBotId(killedBy.getKey())).put(botId, killedBy.getValue());
				}
			}
			result.getSuicides().put(botId, stats.getSuicides());
			result.getKillCounts().put(botId, botId, stats.getSuicides());
		}
		
		for (IToken nativeBotId1 : config.getNativeBots().keySet()) {
			for (IToken nativeBotId2 : config.getNativeBots().keySet()) {
				if (nativeBotId1 == nativeBotId2) continue;
				result.getKillCounts().get(nativeBotId1).put(nativeBotId2, 0);
			}
			result.getSuicides().put(nativeBotId1, 0);
		}
		
		for (IToken botId : botIds) {
			int totalKills = 0;
			int totalKilled = 0;
			for (IToken other : botIds) {
				if (botId == other) continue;
				totalKills += result.getKillCounts().get(botId, other);
				totalKilled += result.getKillCounts().get(other, botId);
			}
			result.getTotalKills().put(botId, totalKills);
			result.getWasKilled().put(botId, totalKilled);
			if (config.isNativeBot(botId) || config.isHuman(botId)) {
				result.getSuicides().put(botId, result.getFinalScores().get(botId).getDeaths() - totalKilled);
			}
		}
		
		if (winners.size() <= 0) {
			throw new PogamutException("There is no winner, impossible! **puzzled**", log, this);
		} else 
		if (winners.size() == 1) {
			result.setWinnerBot(bots.getBotId(winners.get(0)));
FileLine
cz/cuni/amis/pogamut/ut2004/tournament/capturetheflag/UT2004CaptureTheFlag.java594
cz/cuni/amis/pogamut/ut2004/tournament/teamdeathmatch/UT2004TeamDeathMatch.java592
			UT2004TeamDeathMatchResult result = (UT2004TeamDeathMatchResult) waitMatchFinish(ucc, server, analyzer, bots, config.getTimeLimit() * 1000 + 60 * 1000);
			
			// STEP 11
			copyReplay(ucc, recordFileName, getOutputPath());

			// STEP 12
			outputResults(ucc, server, analyzer, bots, result, getOutputPath());
			
			// STEP 13
			shutdownAll(ucc, server, analyzer, bots);
			
			ucc = null;
			server = null;
			analyzer = null;
			bots = null;
			
			// WE'RE DONE! ... all that is left is a possible cleanup...
			return result;
			
		} catch (Exception e) {
			if (log != null && log.isLoggable(Level.SEVERE)) {
				log.severe(ExceptionToString.process(config.getMatchId().getToken() + ": EXCEPTION!", e));
			}
			exception = true;
			if (e instanceof PogamutException) throw (PogamutException)e;
			throw new PogamutException(e, log, this);
		} finally {		
			try {
				if (log != null && log.isLoggable(Level.INFO)) {
					log.info(config.getMatchId().getToken() + ": Cleaning up...");
				} 
			} catch (Exception e) {				
			}
			
			if (ucc != null) {
				try {
					if (log != null && log.isLoggable(Level.INFO)) {
						log.info(config.getMatchId().getToken() + ": Killing UCC...");
					} 
				} catch (Exception e) {				
				}
				try {
					ucc.stop();
				} catch (Exception e) {					
				}
			}
			if (server != null) {
				try {
					if (log != null && log.isLoggable(Level.INFO)) {
						log.info(config.getMatchId().getToken() + ": Killing UT2004Server...");
					} 
				} catch (Exception e) {				
				}
				try {
					server.kill();
				} catch (Exception e) {					
				}
			}
			if (bots != null) {
				try {
					if (log != null && log.isLoggable(Level.INFO)) {
						log.info(config.getMatchId().getToken() + ": Killing Custom bots...");
					} 
				} catch (Exception e) {				
				}
				for (UT2004BotExecution exec : bots.bots.values()) {
					try {
						exec.stop();					
					} catch (Exception e) {					
					}
				}
				try {
					if (log != null && log.isLoggable(Level.INFO)) {
						log.info(config.getMatchId().getToken() + ": Killing Custom bot observers...");
					} 
				} catch (Exception e) {				
				}
				for (IUT2004AnalyzerObserver obs : bots.botObservers.values()) {
					try {
						obs.kill();
					} catch (Exception e) {						
					}
				}
			}
			if (analyzer != null) {
				try {
					if (log != null && log.isLoggable(Level.INFO)) {
						log.info(config.getMatchId().getToken() + ": Killing UT2004Analyzer...");
					} 
				} catch (Exception e) {				
				}
				try {
					analyzer.kill();
				} catch (Exception e) {					
				}
			}	
			
			try {
				// STEP 10.1
				restoreUT2004IniBackup();
			} catch (Exception e) {				
			}
			
			try {
				// STEP 10.2
				restoreGB2004IniBackup();
			} catch (Exception e) {				
			}
			
			try {
				if (log != null && log.isLoggable(Level.WARNING)) {
					if (exception) {
						log.warning(config.getMatchId().getToken() + ": Cleaned up, MATCH FAILED!");
					} else { 
						log.warning(config.getMatchId().getToken() + ": Cleaned up, match finished successfully.");
					}
				} 
			} catch (Exception e) {				
			}
			try {
				closeLogger();
			} catch (Exception e) {
				
			}
		}
		
	}

}
FileLine
cz/cuni/amis/pogamut/ut2004/tournament/capturetheflag/UT2004CaptureTheFlag.java458
cz/cuni/amis/pogamut/ut2004/tournament/deathmatch/UT2004DeathMatch.java405
		File file = new File(outputDirectory.getAbsolutePath() + File.separator + "match-" + config.getMatchId().getToken() + "-bot-scores.csv");
		FilePath.makeDirsToFile(file);
		try {
			Formatter writer = new Formatter(file);
			
			List<IToken> bots = new ArrayList<IToken>(config.getBots().keySet());
			List<IToken> nativeBots = new ArrayList<IToken>(config.getNativeBots().keySet());
			List<IToken> humans = new ArrayList<IToken>(config.getHumans().keySet());
			
			Collections.sort(bots, new Comparator<IToken>() {
				@Override
				public int compare(IToken o1, IToken o2) {
					return o1.getToken().compareTo(o2.getToken());
				}				
			});
			Collections.sort(nativeBots, new Comparator<IToken>() {
				@Override
				public int compare(IToken o1, IToken o2) {
					return o1.getToken().compareTo(o2.getToken());
				}				
			});
			Collections.sort(humans, new Comparator<IToken>() {
				@Override
				public int compare(IToken o1, IToken o2) {
					return o1.getToken().compareTo(o2.getToken());
				}				
			});
			result.setBots(bots);
			result.setNativeBots(nativeBots);
			result.setHumans(humans);
			
			writer.format("botId");
			writer.format(";name;score;kills;killedByOthers;deaths;suicides");
			for (IToken token : config.getAllBotIds()) {
				writer.format(";");
				writer.format(token.getToken());
			}
			
			for (IToken token : config.getAllBotIds()) {
				writer.format("\n");
				writer.format(token.getToken());
				writer.format(";%s", result.getNames().get(token));
				writer.format(";%d", result.getFinalScores().get(token).getScore());
				writer.format(";%d", result.getTotalKills().get(token));
				writer.format(";%d", result.getWasKilled().get(token));
				writer.format(";%d", result.getFinalScores().get(token).getDeaths());
				writer.format(";%d", result.getSuicides().get(token));				
				for (IToken token2 : config.getAllBotIds()) {
					writer.format(";%d", result.getKillCounts().get(token).get(token2));
				}				
			}
			
			try {
				writer.close();
			} catch (Exception e) {			
			}
		} catch (IOException e) {
			throw new PogamutIOException("Failed to write results!", e, log, this);
		}
		
		if (log != null && log.isLoggable(Level.INFO)) {
			log.info(config.getMatchId().getToken() + ": Match scores output into " + file.getAbsolutePath() + ".");
		}
		
	}
	
	@Override
	protected void outputResults(UCCWrapper ucc, UT2004Server server, UT2004Analyzer analyzer, Bots bots, UT2004MatchResult result,	File outputDirectory) {
		if (!(result instanceof UT2004DeathMatchResult)) {
FileLine
cz/cuni/amis/pogamut/ut2004/tournament/capturetheflag/UT2004CaptureTheFlag.java621
cz/cuni/amis/pogamut/ut2004/tournament/deathmatch/UT2004DeathMatch.java569
			try {
				if (log != null && log.isLoggable(Level.INFO)) {
					log.info(config.getMatchId().getToken() + ": Cleaning up...");
				} 
			} catch (Exception e) {				
			}
			
			if (ucc != null) {
				try {
					if (log != null && log.isLoggable(Level.INFO)) {
						log.info(config.getMatchId().getToken() + ": Killing UCC...");
					} 
				} catch (Exception e) {				
				}
				try {
					ucc.stop();
				} catch (Exception e) {					
				}
			}
			if (server != null) {
				try {
					if (log != null && log.isLoggable(Level.INFO)) {
						log.info(config.getMatchId().getToken() + ": Killing UT2004Server...");
					} 
				} catch (Exception e) {				
				}
				try {
					server.kill();
				} catch (Exception e) {					
				}
			}
			if (bots != null) {
				try {
					if (log != null && log.isLoggable(Level.INFO)) {
						log.info(config.getMatchId().getToken() + ": Killing Custom bots...");
					} 
				} catch (Exception e) {				
				}
				for (UT2004BotExecution exec : bots.bots.values()) {
					try {
						exec.stop();					
					} catch (Exception e) {					
					}
				}
				try {
					if (log != null && log.isLoggable(Level.INFO)) {
						log.info(config.getMatchId().getToken() + ": Killing Custom bot observers...");
					} 
				} catch (Exception e) {				
				}
				for (IUT2004AnalyzerObserver obs : bots.botObservers.values()) {
					try {
						obs.kill();
					} catch (Exception e) {						
					}
				}
			}
			if (analyzer != null) {
				try {
					if (log != null && log.isLoggable(Level.INFO)) {
						log.info(config.getMatchId().getToken() + ": Killing UT2004Analyzer...");
					} 
				} catch (Exception e) {				
				}
				try {
					analyzer.kill();
				} catch (Exception e) {					
				}
			}	
			
			try {
				// STEP 10.1
				restoreUT2004IniBackup();
			} catch (Exception e) {				
			}
			
			try {
				// STEP 10.2
				restoreGB2004IniBackup();
			} catch (Exception e) {				
			}
			
			try {
				if (log != null && log.isLoggable(Level.WARNING)) {
					if (exception) {
						log.warning(config.getMatchId().getToken() + ": Cleaned up, MATCH FAILED!");
					} else { 
						log.warning(config.getMatchId().getToken() + ": Cleaned up, match finished successfully.");
					}
				} 
			} catch (Exception e) {				
			}
			try {
				closeLogger();
			} catch (Exception e) {
				
			}
		}
		
	}

}
FileLine
cz/cuni/amis/pogamut/ut2004/tournament/capturetheflag/UT2004CaptureTheFlagResult.java53
cz/cuni/amis/pogamut/ut2004/tournament/teamdeathmatch/UT2004TeamDeathMatchResult.java53
	public UT2004TeamDeathMatchResult(int winnerTeam) {
		super(winnerTeam);
	}

	/**
	 * Returns list with custom bots (run by Pogamut platform).
	 * @return
	 */
	public List<IToken> getBots() {
		return bots;
	}

	/**
	 * List with custom bots (run by Pogamut platform).
	 * @param bots
	 */
	public void setBots(List<IToken> bots) {
		this.bots = bots;
	}

	/**
	 * Returns list with native bots (bots from UT2004 itself).
	 * @return
	 */
	public List<IToken> getNativeBots() {
		return nativeBots;
	}

	/**
	 * List with native bots (bots from UT2004 itself).
	 * @param nativeBots
	 */
	public void setNativeBots(List<IToken> nativeBots) {
		this.nativeBots = nativeBots;
	}
	
	/**
	 * Returns list with humans.
	 * @return
	 */
	public List<IToken> getHumans() {
		return humans;
	}

	/**
	 * List with humans.
	 * @param HumanBots
	 */
	public void setHumans(List<IToken> humans) {
		this.humans = humans;
	}
	
	/**
	 * Returns mapping ID to Name the bot/human had in the game.
	 * @return
	 */
	public Map<IToken, String> getNames() {
		return names;
	}

	/**
	 * Sets mapping ID to Name the bot/human had in the game.
	 * @param names
	 */
	public void setNames(Map<IToken, String> names) {
		this.names = names;
	}

	/**
	 * Returns list of all bot (custom + native) ids.
	 * @return
	 */
	public List<IToken> getAllBots() {
		List<IToken> all = new ArrayList<IToken>(this.bots);
		all.addAll(this.nativeBots);
		all.addAll(this.humans);
		return all;
	}

	/**
	 * When the match has ended (in seconds). I.e., how long was the match.
	 */
	public double getMatchTimeEnd() {
		return matchTimeEnd;
	}

	/**
	 * When the match has ended (in seconds). I.e., how long was the match.
	 */
	public void setMatchTimeEnd(double matchTimeEnd) {
		this.matchTimeEnd = matchTimeEnd;
	}

	/**
	 * Final scores of bots.
	 * @return
	 */
	public Map<IToken, PlayerScore> getFinalScores() {
		return finalScores;
	}

	/**
	 * Final scores of bots.
	 * @return
	 */
	public void setFinalScores(Map<IToken, PlayerScore> finalScores) {
		this.finalScores = finalScores;
	}

	/**
	 * Who -&gt; killed Whom -&gt; How many times, i.e., map.get(killerId).get(victimId) == how many time killer killed the victim.
	 * @return
	 */
	public HashMapMap<IToken, IToken, Integer> getKillCounts() {
		return killCounts;
	}

	/**
	 * Who -&gt; killed Whom -&gt; How many times, i.e., map.get(killerId).get(victimId) == how many time killer killed the victim.
	 * @return
	 */
	public void setKillCounts(HashMapMap<IToken, IToken, Integer> killCounts) {
		this.killCounts = killCounts;
	}
	
	
	/**
	 * How many times one bot killed another bot.
	 * @return
	 */
	public Map<IToken, Integer> getTotalKills() {
		return totalKills;
	}

	/**
	 * How many times one bot killed another bot.
	 * @return
	 */
	public void setTotalKills(Map<IToken, Integer> totalKills) {
		this.totalKills = totalKills;
	}
	
	/**
	 * How many times some bot was killed by ANOTHER bot (== without suicides).
	 * @return
	 */
	public Map<IToken, Integer> getWasKilled() {
		return wasKilled;
	}

	/**
	 * How many times some bot was killed by ANOTHER bot (== without suicides).
	 * @return
	 */
	public void setWasKilled(Map<IToken, Integer> wasKilled) {
		this.wasKilled = wasKilled;
	}

	/**
	 * How many times the bot (key == botId) has commit suicide.
	 * @return
	 */
	public Map<IToken, Integer> getSuicides() {
		return suicides;
	}

	/**
	 * How many times the bot (key == botId) has commit suicide.
	 * @param suicides
	 */
	public void setSuicides(Map<IToken, Integer> suicides) {
		this.suicides = suicides;
	}

	/**
	 * Map with observers (custom bots only!) containing detailed statistics about respective bots.
	 * @return
	 */
	public Map<IToken, UT2004AnalyzerObsStats> getBotObservers() {
		return botObservers;
	}

	/**
	 * Map with observers (custom bots only!) containing detailed statistics about respective bots.
	 * @param botObservers
	 */
	public void setBotObservers(Map<IToken, UT2004AnalyzerObsStats> botObservers) {
		this.botObservers = botObservers;
	}

	/**
	 * Returns scores of respective teams that were in the game.
	 * @return
	 */
	public Map<Integer, TeamScore> getTeamScores() {
		return teamScores;
	}

	/**
	 * Sets team scores.
	 * @param teamScores
	 */
	public void setTeamScores(Map<Integer, TeamScore> teamScores) {
		this.teamScores = teamScores;
	}

}
FileLine
cz/cuni/amis/pogamut/ut2004/tournament/capturetheflag/UT2004CaptureTheFlagResult.java54
cz/cuni/amis/pogamut/ut2004/tournament/deathmatch/UT2004DeathMatchResult.java52
		super(winnerBot);
	}

	/**
	 * Returns list with custom bots (run by Pogamut platform).
	 * @return
	 */
	public List<IToken> getBots() {
		return bots;
	}

	/**
	 * List with custom bots (run by Pogamut platform).
	 * @param bots
	 */
	public void setBots(List<IToken> bots) {
		this.bots = bots;
	}

	/**
	 * Returns list with native bots (bots from UT2004 itself).
	 * @return
	 */
	public List<IToken> getNativeBots() {
		return nativeBots;
	}

	/**
	 * List with native bots (bots from UT2004 itself).
	 * @param nativeBots
	 */
	public void setNativeBots(List<IToken> nativeBots) {
		this.nativeBots = nativeBots;
	}
	
	/**
	 * Returns list with humans.
	 * @return
	 */
	public List<IToken> getHumans() {
		return humans;
	}

	/**
	 * List with humans.
	 * @param humans
	 */
	public void setHumans(List<IToken> humans) {
		this.humans = humans;
	}
	
	/**
	 * Returns mapping ID to Name the bot/human had in the game.
	 * @return
	 */
	public Map<IToken, String> getNames() {
		return names;
	}

	/**
	 * Sets mapping ID to Name the bot/human had in the game.
	 * @param names
	 */
	public void setNames(Map<IToken, String> names) {
		this.names = names;
	}
	
	/**
	 * Returns list of all bot (custom + native) ids.
	 * @return
	 */
	public List<IToken> getAllBots() {
		List<IToken> all = new ArrayList<IToken>(this.bots);
		all.addAll(this.nativeBots);
		all.addAll(this.humans);
		return all;
	}

	/**
	 * When the match has ended (in seconds). I.e., how long was the match.
	 */
	public double getMatchTimeEnd() {
		return matchTimeEnd;
	}

	/**
	 * When the match has ended (in seconds). I.e., how long was the match.
	 */
	public void setMatchTimeEnd(double matchTimeEnd) {
		this.matchTimeEnd = matchTimeEnd;
	}

	/**
	 * Final scores of bots.
	 * @return
	 */
	public Map<IToken, PlayerScore> getFinalScores() {
		return finalScores;
	}

	/**
	 * Final scores of bots.
	 * @return
	 */
	public void setFinalScores(Map<IToken, PlayerScore> finalScores) {
		this.finalScores = finalScores;
	}

	/**
	 * Who -&gt; killed Whom -&gt; How many times, i.e., map.get(killerId).get(victimId) == how many time killer killed the victim.
	 * @return
	 */
	public HashMapMap<IToken, IToken, Integer> getKillCounts() {
		return killCounts;
	}

	/**
	 * Who -&gt; killed Whom -&gt; How many times, i.e., map.get(killerId).get(victimId) == how many time killer killed the victim.
	 * @return
	 */
	public void setKillCounts(HashMapMap<IToken, IToken, Integer> killCounts) {
		this.killCounts = killCounts;
	}
	
	
	/**
	 * How many times one bot killed another bot.
	 * @return
	 */
	public Map<IToken, Integer> getTotalKills() {
		return totalKills;
	}

	/**
	 * How many times one bot killed another bot.
	 * @return
	 */
	public void setTotalKills(Map<IToken, Integer> totalKills) {
		this.totalKills = totalKills;
	}
	
	/**
	 * How many times some bot was killed by ANOTHER bot (== without suicides).
	 * @return
	 */
	public Map<IToken, Integer> getWasKilled() {
		return wasKilled;
	}

	/**
	 * How many times some bot was killed by ANOTHER bot (== without suicides).
	 * @return
	 */
	public void setWasKilled(Map<IToken, Integer> wasKilled) {
		this.wasKilled = wasKilled;
	}

	/**
	 * How many times the bot (key == botId) has commit suicide.
	 * @return
	 */
	public Map<IToken, Integer> getSuicides() {
		return suicides;
	}

	/**
	 * How many times the bot (key == botId) has commit suicide.
	 * @param suicides
	 */
	public void setSuicides(Map<IToken, Integer> suicides) {
		this.suicides = suicides;
	}

	/**
	 * Map with observers (custom bots only!) containing detailed statistics about respective bots.
	 * @return
	 */
	public Map<IToken, UT2004AnalyzerObsStats> getBotObservers() {
		return botObservers;
	}

	/**
	 * Map with observers (custom bots only!) containing detailed statistics about respective bots.
	 * @param botObservers
	 */
	public void setBotObservers(Map<IToken, UT2004AnalyzerObsStats> botObservers) {
		this.botObservers = botObservers;
	}
FileLine
cz/cuni/amis/pogamut/ut2004/tournament/capturetheflag/UT2004CaptureTheFlag.java386
cz/cuni/amis/pogamut/ut2004/tournament/teamdeathmatch/UT2004TeamDeathMatch.java384
	protected void outputResults_step1(UT2004TeamDeathMatchResult result, File outputDirectory) {
		if (log != null && log.isLoggable(Level.FINE)) {
			log.fine(config.getMatchId().getToken() + ": Outputting match result into CSV file...");
		}
		
		File file = new File(outputDirectory.getAbsolutePath() + File.separator + "match-" + config.getMatchId().getToken() + "-result.csv");
		FilePath.makeDirsToFile(file);
		try {
			Formatter writer = new Formatter(file);
			writer.format("MatchId;ScoreLimit;TimeLimit;TimeEnd;Winner\n");
			writer.format
					(
						"%s;%d;%d;%.3f;%s",
						config.getMatchId().getToken(),
						config.getScoreLimit(),
						config.getTimeLimit(),
						result.getMatchTimeEnd(),
						result.isDraw() ? "DRAW" : "TEAM" + String.valueOf(result.getWinnerTeam())
					);
			try {
				writer.close();
			} catch (Exception e) {			
			}
		} catch (IOException e) {
			throw new PogamutIOException("Failed to write results!", e, log, this);
		}
		
		if (log != null && log.isLoggable(Level.INFO)) {
			log.info(config.getMatchId().getToken() + ": Match result output into " + file.getAbsolutePath() + ".");
		}
		
	}
	
	protected void outputResults_step2(UT2004TeamDeathMatchResult result, File outputDirectory) {
FileLine
cz/cuni/amis/pogamut/ut2004/tournament/match/UT2004Match.java717
cz/cuni/amis/pogamut/ut2004/tournament/match/UT2004Match.java891
						bots.nativeUnrealId2BotId.put(player.getId(), connecting.get());
						bots.names.put(player.getId(), player.getName());
						
						latch.get().countDown();
					}
				}
				@Override
				public void preRemoveEvent(Collection<Player> toBeRemoved, Collection<Player> whereToRemove) {
					if (toBeRemoved.size() == 0) return;
					boolean bot = false;
					for (Player player : toBeRemoved) {
						if (isHumanPlayer(player)) continue;
						if (player.isSpectator()) continue;
						bot = true;
					}
					if (!bot) return;
					if (log != null && log.isLoggable(Level.WARNING)) {
						StringBuffer sb = new StringBuffer();
						sb.append(config.getMatchId().getToken() + ": Bot(s) removed from GB2004!!!");
						boolean first = true;
						for (Player plr : toBeRemoved) {
							if (first) first = false;
							else sb.append(", ");
							sb.append("Bot[unrealId=" + plr.getId().getStringId() + ", name=" + plr.getName() + "]");
						}
						log.warning(sb.toString());
					}
					throw new PogamutException("(NativeBot connecting) There can't be any 'removes' at this stage.", log, this);
FileLine
cz/cuni/amis/pogamut/ut2004/tournament/match/UT2004Match.java687
cz/cuni/amis/pogamut/ut2004/tournament/match/UT2004Match.java859
				server.getPlayers().removeCollectionListener(playerListener);
			}
			// SUCCESS ALL CUSTOM BOTS ARE RUNNING AS THEY SHOULD
		}
		
		//
		// CONNECT ALL NATIVE BOTS
		//
		{
			final AdaptableProvider<IToken> connecting = new AdaptableProvider<IToken>(null);
			final AdaptableProvider<CountDownLatch> latch = new AdaptableProvider<CountDownLatch>(null);
			
			CollectionEventListener<Player> playerListener = new CollectionEventListener<Player>() {
				@Override
				public void postAddEvent(Collection<Player> alreadyAdded,Collection<Player> whereWereAdded) {				
				}
				@Override
				public void postRemoveEvent(Collection<Player> alreadyAdded,Collection<Player> whereWereRemoved) {
					if (alreadyAdded.size() == 0) return;
				}
				@Override
				public void preAddEvent(Collection<Player> toBeAdded, Collection<Player> whereToAdd) {
					if (toBeAdded.size() == 0) return;
					for (Player player : toBeAdded) {					
						if (isHumanPlayer(player)) continue;
						if (player.isSpectator()) continue;
						
						if (log != null && log.isLoggable(Level.FINE)) {
							log.fine(config.getMatchId().getToken() + ": New bot connected to GB2004. Bot[unrealId=" + player.getId().getStringId() + ", name=" + player.getName() + "], binding its unrealId to botId " + connecting.get().getToken() + "...");
FileLine
cz/cuni/amis/pogamut/ut2004/tournament/capturetheflag/UT2004CaptureTheFlagResult.java15
cz/cuni/amis/pogamut/ut2004/tournament/teamdeathmatch/UT2004TeamDeathMatchResult.java15
public class UT2004TeamDeathMatchResult extends UT2004TeamMatchResult {
	
	private List<IToken> bots = new ArrayList<IToken>();
	
	private List<IToken> nativeBots = new ArrayList<IToken>();
	
	private List<IToken> humans = new ArrayList<IToken>();
	
	private Map<IToken, String> names = new HashMap<IToken, String>();
	
	private Map<IToken, PlayerScore> finalScores = new HashMap<IToken, PlayerScore>();
	
	private Map<IToken, Integer> totalKills = new HashMap<IToken, Integer>();
	
	private Map<IToken, Integer> wasKilled = new HashMap<IToken, Integer>();
	
	private HashMapMap<IToken, IToken, Integer> killCounts = new HashMapMap<IToken, IToken, Integer>(); 
	
	private Map<IToken, Integer> suicides = new HashMap<IToken, Integer>();
	
	private Map<IToken, UT2004AnalyzerObsStats> botObservers = new HashMap<IToken, UT2004AnalyzerObsStats>();

	private Map<Integer, TeamScore> teamScores = new HashMap<Integer, TeamScore>();
	
	/**
	 * When the match has ended (in seconds);
	 */
	public double matchTimeEnd;

	@Override
	public String toString() {
		return "UT2004TeamDeathMatchResult[" + (isDraw() ? "DRAW" : ("winnerTeam=" + getWinnerTeam()) ) + "]";
FileLine
cz/cuni/amis/pogamut/ut2004/tournament/capturetheflag/UT2004CaptureTheFlag.java116
cz/cuni/amis/pogamut/ut2004/tournament/deathmatch/UT2004DeathMatch.java99
			server.getWorldView().addEventListener(PlayerScore.class, scoresListener);
			
			for (UT2004BotConfig botConfig : config.getBots().values()) {
				FlagListener<Boolean> obs = new FlagListener<Boolean>() {
					@Override
					public void flagChanged(Boolean changedValue) {
						if (!changedValue) {
							// bot has died out
							oneOfBotsDiedOut.set(true);
							waitLatch.countDown();
						}
					}
				};
				
				bots.bots.get(botConfig.getBotId()).getRunning().addListener(obs);
				customBotObservers.put(botConfig.getBotId(), obs);
				if (!bots.bots.get(botConfig.getBotId()).getRunning().getFlag()) {
					// bot has died out
					oneOfBotsDiedOut.set(true);
					waitLatch.countDown();
					throw new PogamutException("One of custom bots died out from the start, failure!", log, this);
				}			
			}
			
			serverObs = new FlagListener<IAgentState>() {
	
				@Override
				public void flagChanged(IAgentState changedValue) {					
					if (changedValue instanceof IAgentStateDown) {
						// server has died out ... consider match to be over...
						serverDiedOut.set(true);
						waitLatch.countDown();
					}
				}
				
			};
			
			server.getState().addListener(serverObs);
FileLine
cz/cuni/amis/pogamut/ut2004/tournament/capturetheflag/UT2004CaptureTheFlagConfig.java146
cz/cuni/amis/pogamut/ut2004/tournament/teamdeathmatch/UT2004TeamDeathMatchConfig.java146
	public UT2004TeamDeathMatchConfig addNativeBot(UT2004NativeBotConfig... bots) {
		super.addNativeBot(bots);
		return this;
	}
	
	public UT2004MatchConfig setNativeBot(UT2004NativeBotConfig... bots) {
		super.setNativeBot(bots);
		return this;
	}
	
	@Override
	protected void validateInner() {
		super.validateInner();
		if (scoreLimit <= 0) {
			validationError = true;
			validationBuffer.append(Const.NEW_LINE);
			validationBuffer.append("ScoreLimit = " + scoreLimit + " <= 0");
		}
		if (timeLimitInMin < 1) {
			validationError = true;
			validationBuffer.append(Const.NEW_LINE);
			validationBuffer.append("TimeLimit = " + timeLimitInMin + " < 1 min.");
		}
		if (getGb2004Ini().getCTFScoreLimit() <= 0) {
			validationError = true;
			validationBuffer.append(Const.NEW_LINE);
			validationBuffer.append("GameBots2004.ini ScoreLimit = " + getGb2004Ini().getCTFScoreLimit() + " <= 0.");
		}
		if (getGb2004Ini().getCTFTimeLimit() < 1) {
			validationError = true;
			validationBuffer.append(Const.NEW_LINE);
			validationBuffer.append("GameBots2004.ini TimeLimit = " + getGb2004Ini().getCTFTimeLimit() + " < 1 min.");
		}
	}

}
FileLine
cz/cuni/amis/pogamut/ut2004/tournament/capturetheflag/UT2004CaptureTheFlag.java626
cz/cuni/amis/pogamut/ut2004/tournament/match/UT2004Match.java1473
		}
		
		if (ucc != null) {
			try {
				if (log != null && log.isLoggable(Level.INFO)) {
					log.info(config.getMatchId().getToken() + ": Killing UCC...");
				} 
			} catch (Exception e) {				
			}
			try {
				ucc.stop();
			} catch (Exception e) {					
			}
		}
		if (server != null) {
			try {
				if (log != null && log.isLoggable(Level.INFO)) {
					log.info(config.getMatchId().getToken() + ": Killing UT2004Server...");
				} 
			} catch (Exception e) {				
			}
			try {
				server.kill();
			} catch (Exception e) {					
			}
		}
		if (bots != null) {
			try {
				if (log != null && log.isLoggable(Level.INFO)) {
					log.info(config.getMatchId().getToken() + ": Killing Custom bots...");
				} 
			} catch (Exception e) {				
			}
FileLine
cz/cuni/amis/pogamut/ut2004/tournament/capturetheflag/UT2004CaptureTheFlag.java534
cz/cuni/amis/pogamut/ut2004/tournament/teamdeathmatch/UT2004TeamDeathMatch.java532
	public UT2004TeamDeathMatchResult execute() {
		try {
			if (log != null && log.isLoggable(Level.WARNING)) {
				log.warning(config.getMatchId().getToken() + ": Executing!");
			} 
		} catch (Exception e) {				
		}
		
		UCCWrapper ucc = null;
		UT2004Server server = null;
		Bots bots = null;
		UT2004Analyzer analyzer = null;
		String recordFileName = config.getMatchId().getToken() + "-replay-" + UT2004Match.getCurrentDate();
		boolean exception = false;
		
		// HACK!!!
		// We must set frag limit to actually BIGGER NUMBER because otherwise GB2004 would drop the connection sooner before telling us that some bot
		// has achieved required score :-/
		targetScoreLimit = getConfig().getScoreLimit();
		getConfig().setScoreLimit(targetScoreLimit + 10); 

		
		try {
			// STEP 0
			setupLogger();
			
			// STEP 1
			validate();

			// STEP 2.1
			createUT2004Ini();
			
			// STEP 2.2
			createGB2004Ini();
			
			// STEP 3
			ucc = startUCC();
			
			// STEP 4
			server = startControlServer(ucc);
			
			// STEP 5.1
			bots = startBots(ucc, server);
			
			// STEP 5.2
			waitHumanPlayers(server, bots);
			
			// STEP 6
			analyzer = startAnalyzer(ucc, bots, getOutputPath("bots"), false);
			
			// STEP 7
			matchIsAboutToBegin(ucc, server, analyzer, bots);
			
			// STEP 8
			restartMatch(server, bots);
			
			// STEP 9			
			recordReplay(server, recordFileName);
FileLine
cz/cuni/amis/pogamut/ut2004/tournament/capturetheflag/UT2004CaptureTheFlag.java198
cz/cuni/amis/pogamut/ut2004/tournament/deathmatch/UT2004DeathMatch.java170
			getConfig().setFragLimit(targetFragCount); 
			
			// WHAT HAS HAPPENED?
			if (oneOfBotsDiedOut.get()) {
				// check whether the server is down as well... but let GB2004 to process it
				try {
					Thread.sleep(5000);
				} catch (InterruptedException e) {
					throw new PogamutInterruptedException("Interrupted while giving GB2004 time to tear down its connection.", log, this);
				}
				try {
					server.getAct().act(new StartPlayers());
				} catch (Exception e) {
					// YEP, server is down
					serverDiedOut.set(true);
				}
				if (!serverDiedOut.get()) {
					// NO SERVER IS STILL RUNNING
					log.warning("ONE OF BOTS HAS DIED OUT, BUT SERVER IS STILL RUNNING ... POSSIBLE MATCH FAILURE!");
				}
			}
			if (!serverDiedOut.get() && server.inState(IAgentStateUp.class)) {
				// Server is still running? ... This will likely to always happen as frag limit is targetFragCount+10 !!! 
				// Kill it...
				server.kill();
			}
			// server is DEAD -> assume that the match has ended
			
			// KILL UCC TO ENSURE NOTHING WILL CHANGE AFTER THAT
			if (ucc != null) {
				try {
					if (log != null && log.isLoggable(Level.INFO)) {
						log.info(config.getMatchId().getToken() + ": Killing UCC...");
					} 
				} catch (Exception e) {				
				}
				try {
					ucc.stop();
				} catch (Exception e) {					
				}
			}
			
			List<UnrealId> winners = new ArrayList<UnrealId>(1);
FileLine
cz/cuni/amis/pogamut/ut2004/tournament/capturetheflag/UT2004CaptureTheFlagResult.java15
cz/cuni/amis/pogamut/ut2004/tournament/deathmatch/UT2004DeathMatchResult.java15
public class UT2004DeathMatchResult extends UT2004IndividualMatchResult {
	
	private List<IToken> bots = new ArrayList<IToken>();
	
	private List<IToken> nativeBots = new ArrayList<IToken>();
	
	private List<IToken> humans = new ArrayList<IToken>();
	
	private Map<IToken, String> names = new HashMap<IToken, String>();
	
	private Map<IToken, PlayerScore> finalScores = new HashMap<IToken, PlayerScore>();
	
	private Map<IToken, Integer> totalKills = new HashMap<IToken, Integer>();
	
	private Map<IToken, Integer> wasKilled = new HashMap<IToken, Integer>();
	
	private HashMapMap<IToken, IToken, Integer> killCounts = new HashMapMap<IToken, IToken, Integer>(); 
	
	private Map<IToken, Integer> suicides = new HashMap<IToken, Integer>();
	
	private Map<IToken, UT2004AnalyzerObsStats> botObservers = new HashMap<IToken, UT2004AnalyzerObsStats>();
FileLine
cz/cuni/amis/pogamut/ut2004/tournament/capturetheflag/UT2004CaptureTheFlag.java57
cz/cuni/amis/pogamut/ut2004/tournament/deathmatch/UT2004DeathMatch.java56
	}

	@Override
	protected UT2004MatchResult waitMatchFinish(UCCWrapper ucc, UT2004Server server, UT2004Analyzer analyzer, Bots bots, long timeoutInMillis) {
		// usually the GB2004 dies out whenever match ends -> just wait till server does not fail + timeout + observe bots
		
		if (log != null && log.isLoggable(Level.WARNING)) {
			log.warning(config.getMatchId().getToken() + ": Waiting for the match to finish...");
		}
		
		if (config.getTimeLimit() * 60 * 1000 + 5 * 60 * 1000 > timeoutInMillis) {
			timeoutInMillis = config.getTimeLimit() * 60 * 1000 + 5 * 60 * 1000; // give additional 5 minutes to UT2004 to restart GB2004
		}
		
		Map<IToken, FlagListener<Boolean>> customBotObservers = new HashMap<IToken, FlagListener<Boolean>>(config.getBots().size());
		FlagListener<IAgentState> serverObs = null;
		FlagListener<Boolean> uccObs = null;
		IWorldEventListener<PlayerScore> scoresListener = null;
FileLine
cz/cuni/amis/pogamut/ut2004/tournament/capturetheflag/UT2004CaptureTheFlag.java594
cz/cuni/amis/pogamut/ut2004/tournament/deathmatch/UT2004DeathMatch.java540
			UT2004DeathMatchResult result = (UT2004DeathMatchResult) waitMatchFinish(ucc, server, analyzer, bots, config.getTimeLimit() * 1000 + 60 * 1000);
			
			// STEP 11
			copyReplay(ucc, recordFileName, getOutputPath());

			// STEP 12
			outputResults(ucc, server, analyzer, bots, result, getOutputPath());
			
			// STEP 13
			shutdownAll(ucc, server, analyzer, bots);
			
			ucc = null;
			server = null;
			analyzer = null;
			bots = null;
			
			// WE'RE DONE! ... all that is left is a possible cleanup...
			return result;
			
		} catch (Exception e) {
			if (log != null && log.isLoggable(Level.SEVERE)) {
				log.severe(ExceptionToString.process(config.getMatchId().getToken() + ": EXCEPTION!", e));
			}
			exception = true;
			if (e instanceof PogamutException) throw (PogamutException)e;
			throw new PogamutException(e, log, this);
		} finally {	
FileLine
cz/cuni/amis/pogamut/ut2004/tournament/capturetheflag/UT2004CaptureTheFlag.java465
cz/cuni/amis/pogamut/ut2004/tournament/match/UT2004MatchConfig.java170
		List<IToken> humans = new ArrayList<IToken>(getHumans().keySet());
		Collections.sort(bots, new Comparator<IToken>() {
			@Override
			public int compare(IToken o1, IToken o2) {
				return o1.getToken().compareTo(o2.getToken());
			}				
		});
		Collections.sort(nativeBots, new Comparator<IToken>() {
			@Override
			public int compare(IToken o1, IToken o2) {
				return o1.getToken().compareTo(o2.getToken());
			}				
		});	
		Collections.sort(humans, new Comparator<IToken>() {
			@Override
			public int compare(IToken o1, IToken o2) {
				return o1.getToken().compareTo(o2.getToken());
			}				
		});
FileLine
cz/cuni/amis/pogamut/ut2004/tournament/capturetheflag/UT2004CaptureTheFlag.java164
cz/cuni/amis/pogamut/ut2004/tournament/deathmatch/UT2004DeathMatch.java136
			server.getState().addListener(serverObs);
			
			if (server.notInState(IAgentStateUp.class)) {
				// server has died out ... consider match to be over...
				serverDiedOut.set(true);
				waitLatch.countDown();
				throw new PogamutException("Server is dead from the start, failure!", log, this);
			}
			
			uccObs = new FlagListener<Boolean>() {

				@Override
				public void flagChanged(Boolean changedValue) {
					if (changedValue) {
						// GAME IS ENDING!
						// Consider match to be over...
						serverDiedOut.set(true);
						waitLatch.countDown();
					}
				}
				
			};
			
			ucc.getGameEnding().addListener(uccObs);
			
			waitLatch.await(timeoutInMillis, TimeUnit.MILLISECONDS);
			if (waitLatch.getCount() > 0) {
				// TIMEOUT!
				throw new PogamutException("TIMEOUT! The match did not end in " + (timeoutInMillis / 1000) + " secs.", log, this);
			}
			
			bots.matchEnd = System.currentTimeMillis();
			
			// RESTORE THE CONFIG...
			getConfig().setFragLimit(targetFragCount); 
FileLine
cz/cuni/amis/pogamut/ut2004/tournament/deathmatch/UT2004DeathMatchTournamentConfig.java219
cz/cuni/amis/pogamut/ut2004/tournament/match/UT2004MatchConfig.java244
	public UT2004MatchConfig addBot(UT2004BotConfig... bots) {
		if (bots == null) return this;
		for (UT2004BotConfig bot : bots) {
			NullCheck.check(bot.getBotId(), "bot.getBotId()");
			if (this.bots.containsKey(bot.getBotId())) {
				throw new PogamutException("Can't add another bot under the id " + bot.getBotId().getToken() + ", there is already an existing custom bot configuration under this ID. If you need to override it, use setBot().", this);
			}
			if (this.nativeBots.containsKey(bot.getBotId())) {
				throw new PogamutException("Can't add another bot under the id " + bot.getBotId().getToken() + ", there is already an existing native bot configuration under this ID. If you need to override it, use setBot().", this);
			}