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.Map;
9 import java.util.logging.Level;
10
11 import com.google.inject.Inject;
12
13 import cz.cuni.amis.pogamut.base.agent.state.level1.IAgentStateUp;
14 import cz.cuni.amis.pogamut.base.agent.state.level2.IAgentStateRunning;
15 import cz.cuni.amis.pogamut.base.communication.command.IAct;
16 import cz.cuni.amis.pogamut.base.communication.connection.impl.socket.SocketConnection;
17 import cz.cuni.amis.pogamut.base.communication.worldview.event.IWorldEventListener;
18 import cz.cuni.amis.pogamut.base.communication.worldview.object.IWorldObjectEvent;
19 import cz.cuni.amis.pogamut.base.communication.worldview.object.IWorldObjectListener;
20 import cz.cuni.amis.pogamut.base.communication.worldview.object.event.WorldObjectDestroyedEvent;
21 import cz.cuni.amis.pogamut.base.component.bus.IComponentBus;
22 import cz.cuni.amis.pogamut.base.utils.logging.IAgentLogger;
23 import cz.cuni.amis.pogamut.unreal.communication.messages.UnrealId;
24 import cz.cuni.amis.pogamut.ut2004.communication.messages.gbcommands.Configuration;
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) + ".csv" : null;
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 }
77 }
78
79 private void removeObserver(UnrealId botId) {
80 synchronized(observers) {
81 IUT2004AnalyzerObserver observer = observers.get(botId);
82 if (log.isLoggable(Level.INFO)) log.info("Bot '" + botId.getStringId() + "' has left the game");
83 if (observer != null) {
84 if (log.isLoggable(Level.INFO)) log.info("Stopping observer for the bot.");
85 try {
86 Thread.sleep(50);
87 } catch (InterruptedException e) {
88 throw new PogamutInterruptedException(e, this);
89 }
90 if (observer.getState().getFlag() instanceof IAgentStateUp) {
91 try {
92 observer.stop();
93 } catch (Exception e) {
94 log.warning("Observer for the bot '" + observer.getObservedBotId().getStringId() + "' could not be stopped, killing...");
95 try {
96 observer.kill();
97 } catch (Exception e2) {
98 log.warning("Observer for the bot '" + observer.getObservedBotId().getStringId() + "' could not be killed: " + e2.getMessage());
99 }
100 }
101 }
102 observers.remove(botId);
103 observerRemovedNotifier.setBotId(botId);
104 observerRemovedNotifier.setObserver(observer);
105 observerListeners.notify(observerRemovedNotifier);
106 } else {
107 if (log.isLoggable(Level.WARNING)) log.warning("The bot '" + botId.getStringId() + "' has no observer attached, was not observer, probably because the analyzer has been started after the bot itself.");
108 }
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 (event instanceof WorldObjectDestroyedEvent) {
117 removeObserver(plr.getId());
118 } else {
119 addObserver(plr.getId(), plr.getName(), false);
120 }
121 }
122 };
123
124 private IWorldEventListener<PlayerJoinsGame> playerJoinsGameListener = new IWorldEventListener<PlayerJoinsGame>() {
125 @Override
126 public void notify(PlayerJoinsGame event) {
127 addObserver(event.getId(), event.getName(), false);
128 }
129 };
130
131 private IWorldEventListener<PlayerLeft> playerLeftListener = new IWorldEventListener<PlayerLeft>() {
132
133 @Override
134 public void notify(PlayerLeft event) {
135 removeObserver(event.getId());
136 }
137
138 };
139
140
141
142
143 private Map<UnrealId, IUT2004AnalyzerObserver> observers = new HashMap<UnrealId, IUT2004AnalyzerObserver>();
144
145
146
147
148 private UT2004ObserverRunner<IUT2004AnalyzerObserver, UT2004AnalyzerFullObserverParameters> observerRunner;
149
150 private File humanLike_outputFile = null;
151
152 private PrintWriter humanLike_writer = null;
153
154 @Inject
155 public UT2004Analyzer(UT2004AnalyzerParameters params,
156 IAgentLogger agentLogger, IComponentBus bus,
157 SocketConnection connection, UT2004WorldView worldView, IAct act) {
158 super(params, agentLogger, bus, connection, worldView, act);
159
160 observerListeners.setLog(log, "ObserverListeners");
161
162
163
164 getWorldView().addEventListener(PlayerJoinsGame.class, playerJoinsGameListener);
165 getWorldView().addEventListener(PlayerLeft.class, playerLeftListener);
166
167
168
169
170 }
171
172 private UT2004ObserverRunner<IUT2004AnalyzerObserver, UT2004AnalyzerFullObserverParameters> getObserverRunner() {
173 if (observerRunner == null) {
174 synchronized(mutex) {
175 if (observerRunner == null) {
176 observerRunner =
177 new UT2004ObserverRunner(
178 new UT2004ObserverFactory<IUT2004Observer, UT2004AnalyzerFullObserverParameters>(
179 getParams().getObserverModule())
180 );
181 }
182 }
183 }
184 return observerRunner;
185 }
186
187 @Override
188 public UT2004AnalyzerParameters getParams() {
189 return (UT2004AnalyzerParameters) super.getParams();
190 }
191
192 @Override
193 public Map<UnrealId, IUT2004AnalyzerObserver> getObservers() {
194 synchronized(observers) {
195 return new HashMap<UnrealId, IUT2004AnalyzerObserver>(observers);
196 }
197 }
198
199 @Override
200 protected void startAgent() {
201 super.startAgent();
202 if (getParams().getHumanLikeObserving() != null && getParams().getHumanLikeObserving()) {
203 File humanLike_outputFileDir = new File(getParams().getOutputPath());
204 humanLike_outputFileDir.mkdirs();
205 humanLike_outputFile = new File(getParams().getOutputPath() + System.getProperty("file.separator") + "humanLikeData.log");
206 try {
207 humanLike_writer = new PrintWriter(new FileOutputStream(humanLike_outputFile));
208 } catch (FileNotFoundException e) {
209 throw new RuntimeException("Could not create writer for human-like log at: " + humanLike_outputFile.getAbsolutePath());
210 }
211 }
212 }
213
214 @Override
215 protected void startPausedAgent() {
216 super.startPausedAgent();
217 if (getParams().getHumanLikeObserving() != null && getParams().getHumanLikeObserving()) {
218 File humanLike_outputFileDir = new File(getParams().getOutputPath());
219 humanLike_outputFileDir.mkdirs();
220 humanLike_outputFile = new File(getParams().getOutputPath() + System.getProperty("file.separator") + "humanLikeData.log");
221 try {
222 humanLike_writer = new PrintWriter(new FileOutputStream(humanLike_outputFile));
223 } catch (FileNotFoundException e) {
224 throw new RuntimeException("Could not create writer for human-like log at: " + humanLike_outputFile.getAbsolutePath());
225 }
226 }
227 }
228
229 @Override
230 protected void stopAgent() {
231 super.stopAgent();
232 cleanUp();
233 }
234
235 @Override
236 protected void killAgent() {
237 super.killAgent();
238 cleanUp();
239 }
240
241 protected void init() {
242 super.init();
243 synchronized(mutex) {
244 getAct().act(new StartPlayers(true, true, true));
245 for (Player player : getWorldView().getAll(Player.class).values()) {
246 addObserver(player.getId(), player.getName(), true);
247 }
248 }
249 }
250
251
252
253
254 protected void cleanUp() {
255 synchronized(observers) {
256 for (IUT2004AnalyzerObserver observer : observers.values()) {
257 if (observer.getState().getFlag() instanceof IAgentStateUp) {
258 try {
259 observer.stop();
260 } catch (Exception e) {
261 if (log.isLoggable(Level.WARNING)) log.warning("Observer for the bot '" + observer.getObservedBotId().getStringId() + "' could not be stopped, killing...");
262 try {
263 observer.kill();
264 } catch (Exception e2) {
265 if (log.isLoggable(Level.WARNING)) log.warning("Observer for the bot '" + observer.getObservedBotId().getStringId() + "' could not be killed: " + e2.getMessage());
266 }
267 }
268 }
269 }
270 if (humanLike_writer != null) {
271 try {
272 humanLike_writer.close();
273 } catch (Exception e) {
274 if (humanLike_outputFile != null) {
275 log.warning("Failed to close human-like log file at: " + humanLike_outputFile.getAbsolutePath());
276 } else {
277 log.warning("Failed to close human-like log file (unknown location, weird as well...)!");
278 }
279 }
280 humanLike_outputFile = null;
281 humanLike_writer = null;
282 }
283 }
284 }
285
286 @Override
287 public void addListener(IAnalyzerObserverListener listener) {
288 observerListeners.addWeakListener(listener);
289 }
290
291 @Override
292 public boolean isListening(IAnalyzerObserverListener listener) {
293 return observerListeners.isListening(listener);
294 }
295
296 @Override
297 public void removeListener(IAnalyzerObserverListener listener) {
298 observerListeners.removeListener(listener);
299 }
300
301 public static void main(String[] args) {
302 UT2004AnalyzerRunner<IUT2004Analyzer, UT2004AnalyzerParameters> analyzerRunner = new UT2004AnalyzerRunner<IUT2004Analyzer, UT2004AnalyzerParameters>(
303 new UT2004AnalyzerFactory(
304 new UT2004AnalyzerModule()
305 )
306 );
307 analyzerRunner.setLogLevel(Level.INFO);
308 analyzerRunner.setMain(true).startAgent();
309 }
310
311
312 }