1 package cz.cuni.amis.pogamut.ut2004.analyzer;
2
3 import java.io.File;
4 import java.io.FileNotFoundException;
5 import java.io.FileOutputStream;
6 import java.io.PrintWriter;
7 import java.util.HashMap;
8 import java.util.HashSet;
9 import java.util.Map;
10 import java.util.Set;
11 import java.util.logging.Level;
12
13 import com.google.inject.Inject;
14
15 import cz.cuni.amis.pogamut.base.agent.state.level1.IAgentStateUp;
16 import cz.cuni.amis.pogamut.base.agent.state.level2.IAgentStateRunning;
17 import cz.cuni.amis.pogamut.base.communication.command.IAct;
18 import cz.cuni.amis.pogamut.base.communication.connection.impl.socket.SocketConnection;
19 import cz.cuni.amis.pogamut.base.communication.worldview.event.IWorldEventListener;
20 import cz.cuni.amis.pogamut.base.communication.worldview.object.IWorldObjectEvent;
21 import cz.cuni.amis.pogamut.base.communication.worldview.object.IWorldObjectListener;
22 import cz.cuni.amis.pogamut.base.component.bus.IComponentBus;
23 import cz.cuni.amis.pogamut.base.utils.logging.IAgentLogger;
24 import cz.cuni.amis.pogamut.unreal.communication.messages.UnrealId;
25 import cz.cuni.amis.pogamut.ut2004.communication.messages.gbcommands.StartPlayers;
26 import cz.cuni.amis.pogamut.ut2004.communication.messages.gbinfomessages.Player;
27 import cz.cuni.amis.pogamut.ut2004.communication.messages.gbinfomessages.PlayerJoinsGame;
28 import cz.cuni.amis.pogamut.ut2004.communication.messages.gbinfomessages.PlayerLeft;
29 import cz.cuni.amis.pogamut.ut2004.communication.worldview.UT2004WorldView;
30 import cz.cuni.amis.pogamut.ut2004.factory.guice.remoteagent.UT2004AnalyzerFactory;
31 import cz.cuni.amis.pogamut.ut2004.factory.guice.remoteagent.UT2004ObserverFactory;
32 import cz.cuni.amis.pogamut.ut2004.observer.IUT2004Observer;
33 import cz.cuni.amis.pogamut.ut2004.server.impl.UT2004Server;
34 import cz.cuni.amis.pogamut.ut2004.utils.UT2004AnalyzerRunner;
35 import cz.cuni.amis.pogamut.ut2004.utils.UT2004ObserverRunner;
36 import cz.cuni.amis.utils.exception.PogamutInterruptedException;
37 import cz.cuni.amis.utils.listener.Listeners;
38
39
40
41
42
43
44
45
46 public class UT2004Analyzer extends UT2004Server implements IUT2004Analyzer {
47
48 private Object mutex = new Object();
49
50 private Listeners<IAnalyzerObserverListener> observerListeners = new Listeners<IAnalyzerObserverListener>();
51 private IAnalyzerObserverListener.ObserverAddedNotifier observerAddedNotifier = new IAnalyzerObserverListener.ObserverAddedNotifier();
52 private IAnalyzerObserverListener.ObserverRemovedNotifier observerRemovedNotifier = new IAnalyzerObserverListener.ObserverRemovedNotifier();
53
54 private void addObserver(UnrealId botId, String botName, boolean forced) {
55 if (!forced && !inState(IAgentStateRunning.class)) {
56 if (log.isLoggable(Level.INFO)) log.info("Not running yet, could not add observer for " + botId + ".");
57 return;
58 }
59 synchronized(observers) {
60 if (observers.containsKey(botId)) return;
61 if (log.isLoggable(Level.INFO)) log.info("New bot has connected to the game, creating new observer for the bot with id '" + botId.getStringId() + "'.");
62 String fileName = getParams().getFileNames() != null && getParams().getFileNames().get(botId) != null ? getParams().getFileNames().get(botId) + ".csv" : botId + ".csv";
63 IUT2004AnalyzerObserver observer = getObserverRunner().startAgents(
64 new UT2004AnalyzerFullObserverParameters()
65 .setObservedAgentId(botId.getStringId())
66 .setOutputPath(getParams().getOutputPath())
67 .setWaitForMatchRestart(getParams().isWaitForMatchRestart())
68 .setFileName(fileName)
69 .setWorldAddress(getParams().getObserverAddress())
70 .setHumanLikeObserving(botName, humanLike_writer)
71 ).get(0);
72 observers.put(botId, observer);
73 observerAddedNotifier.setBotId(botId);
74 observerAddedNotifier.setObserver(observer);
75 observerListeners.notify(observerAddedNotifier);
76 nonObserved.remove(botId);
77 }
78 }
79
80 private void removeObserver(UnrealId botId) {
81 synchronized(observers) {
82 if (log.isLoggable(Level.INFO)) log.info("Bot '" + botId.getStringId() + "' has left the game");
83 IUT2004AnalyzerObserver observer = observers.get(botId);
84 if (observer != null) {
85 if (log.isLoggable(Level.INFO)) log.info("Stopping observer for the bot.");
86 try {
87 Thread.sleep(50);
88 } catch (InterruptedException e) {
89 throw new PogamutInterruptedException(e, this);
90 }
91 if (observer.getState().getFlag() instanceof IAgentStateUp) {
92 try {
93 observer.stop();
94 } catch (Exception e) {
95 log.warning("Observer for the bot '" + observer.getObservedBotId().getStringId() + "' could not be stopped, killing...");
96 try {
97 observer.kill();
98 } catch (Exception e2) {
99 log.warning("Observer for the bot '" + observer.getObservedBotId().getStringId() + "' could not be killed: " + e2.getMessage());
100 }
101 }
102 }
103 observers.remove(botId);
104 observerRemovedNotifier.setBotId(botId);
105 observerRemovedNotifier.setObserver(observer);
106 observerListeners.notify(observerRemovedNotifier);
107 }
108 nonObserved.remove(botId);
109 }
110 }
111
112 private IWorldObjectListener<Player> playerListener = new IWorldObjectListener<Player>() {
113 @Override
114 public void notify(IWorldObjectEvent<Player> event) {
115 Player plr = event.getObject();
116 if (!observers.containsKey(plr.getId())) return;
117 synchronized(observers){
118 if (plr.isSpectator()) {
119
120 removeObserver(plr.getId());
121
122 nonObserved.add(plr.getId());
123 } else {
124 if (!observers.containsKey(plr.getId())) addObserver(plr.getId(), plr.getName(), false);
125 }
126 }
127 }
128 };
129
130 private IWorldEventListener<PlayerJoinsGame> playerJoinsGameListener = new IWorldEventListener<PlayerJoinsGame>() {
131 @Override
132 public void notify(PlayerJoinsGame event) {
133 addObserver(event.getId(), event.getName(), false);
134 }
135 };
136
137 private IWorldEventListener<PlayerLeft> playerLeftListener = new IWorldEventListener<PlayerLeft>() {
138
139 @Override
140 public void notify(PlayerLeft event) {
141 removeObserver(event.getId());
142 }
143
144 };
145
146
147
148
149 private Map<UnrealId, IUT2004AnalyzerObserver> observers = new HashMap<UnrealId, IUT2004AnalyzerObserver>();
150
151
152
153
154
155 private Set<UnrealId> nonObserved = new HashSet<UnrealId>();
156
157
158
159
160 private UT2004ObserverRunner<IUT2004AnalyzerObserver, UT2004AnalyzerFullObserverParameters> observerRunner;
161
162 private File humanLike_outputFile = null;
163
164 private PrintWriter humanLike_writer = null;
165
166 @Inject
167 public UT2004Analyzer(UT2004AnalyzerParameters params,
168 IAgentLogger agentLogger, IComponentBus bus,
169 SocketConnection connection, UT2004WorldView worldView, IAct act) {
170 super(params, agentLogger, bus, connection, worldView, act);
171
172 observerListeners.setLog(log, "ObserverListeners");
173
174
175
176 getWorldView().addEventListener(PlayerJoinsGame.class, playerJoinsGameListener);
177 getWorldView().addEventListener(PlayerLeft.class, playerLeftListener);
178
179
180
181 getWorldView().addObjectListener(Player.class, playerListener);
182 }
183
184 private UT2004ObserverRunner<IUT2004AnalyzerObserver, UT2004AnalyzerFullObserverParameters> getObserverRunner() {
185 if (observerRunner == null) {
186 synchronized(mutex) {
187 if (observerRunner == null) {
188 observerRunner =
189 new UT2004ObserverRunner(
190 new UT2004ObserverFactory<IUT2004Observer, UT2004AnalyzerFullObserverParameters>(
191 getParams().getObserverModule())
192 );
193 }
194 }
195 }
196 return observerRunner;
197 }
198
199 @Override
200 public UT2004AnalyzerParameters getParams() {
201 return (UT2004AnalyzerParameters) super.getParams();
202 }
203
204 @Override
205 public Map<UnrealId, IUT2004AnalyzerObserver> getObservers() {
206 synchronized(observers) {
207 return new HashMap<UnrealId, IUT2004AnalyzerObserver>(observers);
208 }
209 }
210
211 @Override
212 protected void startAgent() {
213 super.startAgent();
214 if (getParams().getHumanLikeObserving() != null && getParams().getHumanLikeObserving()) {
215 File humanLike_outputFileDir = new File(getParams().getOutputPath());
216 humanLike_outputFileDir.mkdirs();
217 humanLike_outputFile = new File(getParams().getOutputPath() + System.getProperty("file.separator") + "humanLikeData.log");
218 try {
219 humanLike_writer = new PrintWriter(new FileOutputStream(humanLike_outputFile));
220 } catch (FileNotFoundException e) {
221 throw new RuntimeException("Could not create writer for human-like log at: " + humanLike_outputFile.getAbsolutePath());
222 }
223 }
224 }
225
226 @Override
227 protected void startPausedAgent() {
228 super.startPausedAgent();
229 if (getParams().getHumanLikeObserving() != null && getParams().getHumanLikeObserving()) {
230 File humanLike_outputFileDir = new File(getParams().getOutputPath());
231 humanLike_outputFileDir.mkdirs();
232 humanLike_outputFile = new File(getParams().getOutputPath() + System.getProperty("file.separator") + "humanLikeData.log");
233 try {
234 humanLike_writer = new PrintWriter(new FileOutputStream(humanLike_outputFile));
235 } catch (FileNotFoundException e) {
236 throw new RuntimeException("Could not create writer for human-like log at: " + humanLike_outputFile.getAbsolutePath());
237 }
238 }
239 }
240
241 @Override
242 protected void stopAgent() {
243 super.stopAgent();
244 cleanUp();
245 }
246
247 @Override
248 protected void killAgent() {
249 super.killAgent();
250 cleanUp();
251 }
252
253 protected void init() {
254 super.init();
255 synchronized(mutex) {
256 getAct().act(new StartPlayers(true, true, true));
257 for (Player player : getWorldView().getAll(Player.class).values()) {
258 addObserver(player.getId(), player.getName(), true);
259 }
260 }
261 }
262
263
264
265
266 protected void cleanUp() {
267 synchronized(observers) {
268 for (IUT2004AnalyzerObserver observer : observers.values()) {
269 if (observer.getState().getFlag() instanceof IAgentStateUp) {
270 try {
271 observer.stop();
272 } catch (Exception e) {
273 if (log.isLoggable(Level.WARNING)) log.warning("Observer for the bot '" + observer.getObservedBotId().getStringId() + "' could not be stopped, killing...");
274 try {
275 observer.kill();
276 } catch (Exception e2) {
277 if (log.isLoggable(Level.WARNING)) log.warning("Observer for the bot '" + observer.getObservedBotId().getStringId() + "' could not be killed: " + e2.getMessage());
278 }
279 }
280 }
281 }
282 if (humanLike_writer != null) {
283 try {
284 humanLike_writer.close();
285 } catch (Exception e) {
286 if (humanLike_outputFile != null) {
287 log.warning("Failed to close human-like log file at: " + humanLike_outputFile.getAbsolutePath());
288 } else {
289 log.warning("Failed to close human-like log file (unknown location, weird as well...)!");
290 }
291 }
292 humanLike_outputFile = null;
293 humanLike_writer = null;
294 }
295 }
296 }
297
298 @Override
299 public void addListener(IAnalyzerObserverListener listener) {
300 observerListeners.addWeakListener(listener);
301 }
302
303 @Override
304 public boolean isListening(IAnalyzerObserverListener listener) {
305 return observerListeners.isListening(listener);
306 }
307
308 @Override
309 public void removeListener(IAnalyzerObserverListener listener) {
310 observerListeners.removeListener(listener);
311 }
312
313 public static void main(String[] args) {
314 UT2004AnalyzerRunner<IUT2004Analyzer, UT2004AnalyzerParameters> analyzerRunner = new UT2004AnalyzerRunner<IUT2004Analyzer, UT2004AnalyzerParameters>(
315 new UT2004AnalyzerFactory(
316 new UT2004AnalyzerModule()
317 )
318 );
319 analyzerRunner.setLogLevel(Level.INFO);
320 analyzerRunner.setMain(true).startAgent();
321 }
322
323
324 }