1   package cz.cuni.amis.pogamut.ut2004.tournament.deathmatch;
2   
3   import java.io.File;
4   import java.util.ArrayList;
5   import java.util.Collections;
6   import java.util.Comparator;
7   import java.util.HashMap;
8   import java.util.List;
9   import java.util.Map;
10  
11  import org.apache.commons.io.FileUtils;
12  
13  import cz.cuni.amis.pogamut.ut2004.tournament.match.IUT2004BotConfig;
14  import cz.cuni.amis.pogamut.ut2004.tournament.match.UT2004BotConfig;
15  import cz.cuni.amis.pogamut.ut2004.tournament.match.UT2004NativeBotConfig;
16  import cz.cuni.amis.pogamut.ut2004.utils.UCCWrapperConf;
17  import cz.cuni.amis.utils.NullCheck;
18  import cz.cuni.amis.utils.exception.PogamutException;
19  import cz.cuni.amis.utils.token.IToken;
20  import cz.cuni.amis.utils.token.Tokens;
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
32  
33  
34  public class UT2004DeathMatchTournamentConfig {
35  	
36  	
37  
38  
39  	protected int numBotsInOneMatch = 2;
40  	
41  	
42  
43  
44  	protected IToken tournamentId;
45  	
46  	
47  
48  
49  	protected int fragLimit;
50  	
51  	
52  
53  
54  	protected int timeLimitInMinutes;
55  	
56  	protected UCCWrapperConf uccConf = new UCCWrapperConf();	
57  	
58  	
59  
60  
61  
62  
63  	protected String outputDir;
64  		
65  	
66  
67  
68  	protected Map<IToken, UT2004BotConfig> bots = new HashMap<IToken, UT2004BotConfig>();
69  	
70  	
71  
72  
73  	protected Map<IToken, UT2004NativeBotConfig> nativeBots = new HashMap<IToken, UT2004NativeBotConfig>();
74  
75  	
76  
77  
78  	public UT2004DeathMatchTournamentConfig() {
79  		uccConf.setGameType("BotDeathMatch");
80  		uccConf.setStartOnUnusedPort(true);
81  	}
82  
83  	
84  
85  
86  
87  	public int getNumBotsInOneMatch() {
88  		return numBotsInOneMatch;
89  	}
90  
91  	
92  
93  
94  
95  
96  	public int getFragLimit() {
97  		return fragLimit;
98  	}
99  
100 	
101 
102 
103 
104 
105 	public int getTimeLimitInMinutes() {
106 		return timeLimitInMinutes;
107 	}
108 
109 	
110 
111 
112 
113 
114 	public IToken getTournamentId() {
115 		return tournamentId;
116 	}
117 	
118 	
119 
120 
121 
122 
123 	public String getOutputDir() {
124 		return outputDir;
125 	}
126 	
127 	
128 
129 
130 
131 	public UCCWrapperConf getUccConf() {
132 		return uccConf;
133 	}
134 	
135 	
136 
137 
138 
139 	public Map<IToken, UT2004BotConfig> getBots() {
140 		return bots;
141 	}
142 	
143 	
144 
145 
146 
147 	public Map<IToken, UT2004NativeBotConfig> getNativeBots() {
148 		return nativeBots;
149 	}
150 	
151 	public void setNumBotsInOneMatch(int numBotsInOneMatch) {
152 		this.numBotsInOneMatch = numBotsInOneMatch;
153 	}
154 
155 	public UT2004DeathMatchTournamentConfig setTournamentId(IToken id) {
156 		this.tournamentId = id;
157 		return this;
158 	}
159 	
160 	public UT2004DeathMatchTournamentConfig setTournamentId(String id) {
161 		this.tournamentId = Tokens.get(id);
162 		return this;
163 	}
164 	
165 	public UT2004DeathMatchTournamentConfig setFragLimit(int fragLimit) {
166 		this.fragLimit = fragLimit;
167 		return this;
168 	}
169 
170 	public UT2004DeathMatchTournamentConfig setTimeLimitInMinutes(int timeLimitInMinutes) {
171 		this.timeLimitInMinutes = timeLimitInMinutes;
172 		return this;
173 	}
174 
175 	public UT2004DeathMatchTournamentConfig setUnrealHome(String unrealHome) {
176 		this.uccConf.setUnrealHome(unrealHome);
177 		return this;
178 	}
179 
180 	public UT2004DeathMatchTournamentConfig setMapName(String mapName) {
181 		this.uccConf.setMapName(mapName);
182 		return this;
183 	}
184 
185 	public UT2004DeathMatchTournamentConfig setOutputDir(String outputDir) {
186 		this.outputDir = outputDir;
187 		return this;
188 	}
189 	
190 	public void setUccConf(UCCWrapperConf uccConf) {
191 		this.uccConf = uccConf;
192 	}
193 	
194 	public UT2004DeathMatchTournamentConfig setBots(Map<IToken, UT2004BotConfig> bots) {
195 		this.bots = bots;
196 		return this;
197 	}
198 	
199 	public UT2004DeathMatchTournamentConfig setNativeBots(Map<IToken, UT2004NativeBotConfig> nativeBots) {
200 		this.nativeBots = nativeBots;
201 		return this;
202 	}
203 	
204 	public UT2004DeathMatchTournamentConfig clearBots() {
205 		this.bots.clear();
206 		return this;
207 	}
208 	
209 	public UT2004DeathMatchTournamentConfig clearNativeBots() {
210 		this.nativeBots.clear();
211 		return this;
212 	}
213 	
214 	
215 
216 
217 
218 
219 	public UT2004DeathMatchTournamentConfig addBot(UT2004BotConfig... bots) {
220 		if (bots == null) return this;
221 		for (UT2004BotConfig bot : bots) {
222 			NullCheck.check(bot.getBotId(), "bot.getBotId()");
223 			if (this.bots.containsKey(bot.getBotId())) {
224 				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);
225 			}
226 			if (this.nativeBots.containsKey(bot.getBotId())) {
227 				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);
228 			}
229 			this.bots.put(bot.getBotId(), bot);
230 		}
231 		return this;
232 	}
233 	
234 	
235 
236 
237 
238 
239 
240 	public UT2004DeathMatchTournamentConfig setBot(UT2004BotConfig... bots) {
241 		if (bots == null) return this;
242 		for (UT2004BotConfig bot : bots) {
243 			NullCheck.check(bot.getBotId(), "bot.getBotId()");
244 			if (this.nativeBots.containsKey(bot.getBotId())) {
245 				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);
246 			}
247 			this.bots.put(bot.getBotId(), bot);
248 		}
249 		return this;
250 	}
251 	
252 	
253 
254 
255 
256 
257 	public UT2004DeathMatchTournamentConfig addNativeBot(UT2004NativeBotConfig... bots) {
258 		if (bots == null) return this;
259 		for (UT2004NativeBotConfig bot : bots) {
260 			NullCheck.check(bot.getBotId(), "bot.getBotId()");
261 			if (this.bots.containsKey(bot.getBotId())) {
262 				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);
263 			}
264 			if (this.nativeBots.containsKey(bot.getBotId())) {
265 				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 setNativeBot().", this);
266 			}
267 			this.nativeBots.put(bot.getBotId(), bot);
268 		}
269 		return this;
270 	}
271 	
272 	
273 
274 
275 
276 
277 	public UT2004DeathMatchTournamentConfig setNativeBot(UT2004NativeBotConfig... bots) {
278 		if (bots == null) return this;
279 		for (UT2004NativeBotConfig bot : bots) {
280 			NullCheck.check(bot.getBotId(), "bot.getBotId()");
281 			if (this.bots.containsKey(bot.getBotId())) {
282 				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);
283 			}
284 			this.nativeBots.put(bot.getBotId(), bot);
285 		}
286 		return this;
287 	}
288 	
289 	public boolean isNativeBot(IToken botId) {
290 		return nativeBots.containsKey(botId);
291 	}
292 	
293 	
294 
295 
296 
297 
298 	public IUT2004BotConfig getBotConfig(IToken botId) {
299 		UT2004BotConfig config = bots.get(botId);
300 		if (config != null) return config;
301 		return nativeBots.get(botId);
302 	}
303 
304 	
305 
306 
307 	public void cleanUp() {
308 		try {
309 			FileUtils.deleteQuietly(new File(outputDir));
310 		} catch (Exception e) {			
311 		}		
312 	}	
313 	
314 	
315 
316 
317 
318 
319 
320 
321 
322 	public UT2004DeathMatchConfig createConfiguration(List<IToken> chosenBots) {
323 		UT2004DeathMatchConfig matchConfig = new UT2004DeathMatchConfig();
324 		
325 		StringBuffer matchId = new StringBuffer();
326 		boolean first = true;
327 		for (IToken token : chosenBots) {
328 			if (first) first = false;
329 			else matchId.append("-vs-");
330 			matchId.append(token.getToken());
331 		}
332 		matchConfig.setMatchId(matchId.toString());
333 		matchConfig.setOutputDirectory(new File(outputDir));
334 				
335 		matchConfig.setFragLimit(getFragLimit());
336 		matchConfig.setTimeLimit(getTimeLimitInMinutes()); 
337 		matchConfig.setUccConf(new UCCWrapperConf(uccConf));
338 		
339 		for (IToken botId : chosenBots) {
340 			if (isNativeBot(botId)) {
341 				matchConfig.addNativeBot(new UT2004NativeBotConfig(nativeBots.get(botId)));
342 			} else {
343 				matchConfig.addBot(new UT2004BotConfig(bots.get(botId)));
344 			}
345 		}
346 		
347 		return matchConfig;
348 	}
349 	
350 	protected void generate(List<UT2004DeathMatchConfig> result, int numBots, List<IToken> botIds, int startFrom, List<IToken> chosenBots) {
351 		if (startFrom >= botIds.size()) {
352 			
353 			return;
354 		}
355 		if (chosenBots.size() + (botIds.size() - startFrom) < numBots) {
356 			
357 			return;
358 		}
359 		
360 		chosenBots.add(botIds.get(startFrom));
361 		
362 		if (chosenBots.size() == numBots) {
363 			
364 			result.add(createConfiguration(chosenBots));
365 		} else {
366 			
367 			for (int i = startFrom+1; i < botIds.size(); ++i) {
368 				generate(result, numBots, botIds, i, chosenBots);
369 			}
370 		}
371 		
372 		chosenBots.remove(chosenBots.size()-1);
373 	}
374 	
375 	protected UT2004DeathMatchConfig[] generateMatches(int numBots) {
376 		List<IToken> botIds = new ArrayList<IToken>(bots.size() + nativeBots.size());
377 		botIds.addAll(bots.keySet());
378 		Collections.sort(botIds, new Comparator<IToken>() {
379 			@Override
380 			public int compare(IToken o1, IToken o2) {
381 				if (o1 == null) {
382 					if (o2 == null) return 0;
383 					else return -1;
384 				}
385 				if (o2 == null) return 1;
386 				return o1.getToken().compareTo(o2.getToken());
387 			}
388 		});
389 		
390 		List<IToken> nativeBotIds = new ArrayList<IToken>(nativeBots.keySet());
391 		Collections.sort(nativeBotIds, new Comparator<IToken>() {
392 			@Override
393 			public int compare(IToken o1, IToken o2) {
394 				if (o1 == null) {
395 					if (o2 == null) return 0;
396 					else return -1;
397 				}
398 				if (o2 == null) return 1;
399 				return o1.getToken().compareTo(o2.getToken());
400 			}
401 		});
402 		
403 		botIds.addAll(nativeBotIds);
404 
405 		List<IToken> chosenBots = new ArrayList<IToken>();
406 		
407 		List<UT2004DeathMatchConfig> result = new ArrayList<UT2004DeathMatchConfig>();
408 		for (int i = 0; i < bots.size(); ++i) {
409 			generate(result, numBots, botIds, i, chosenBots);
410 		}
411 		return result.toArray(new UT2004DeathMatchConfig[result.size()]);
412 	}
413 	
414 	
415 
416 
417 
418 
419 
420 
421 
422 
423 
424 
425 	public UT2004DeathMatchConfig[] createMatcheConfigs(int numBotsInOneMatch) {
426 		if (numBotsInOneMatch < 2) throw new IllegalArgumentException("numBotsInOneMatch = " + numBotsInOneMatch + " < 2 !!!");
427 		if (numBotsInOneMatch > bots.size() + nativeBots.size()) throw new IllegalArgumentException("numBotsInOneMatch = " + numBotsInOneMatch + " > " + (bots.size() + nativeBots.size()) + " = number of all (custom+native) enlisted bots");
428 		if (bots.size() == 0) throw new PogamutException("No custom (Pogamut) bots enlisted to the tournament!", this);
429 		return generateMatches(numBotsInOneMatch);
430 	}
431 	
432 	
433 
434 
435 
436 
437 
438 
439 
440 
441 
442 
443 	public UT2004DeathMatchConfig[] createMatcheConfigs() {
444 		return createMatcheConfigs(getNumBotsInOneMatch());
445 	}
446 	
447 }