1   package cz.cuni.amis.pogamut.udk.observer.impl;
2   
3   import java.util.concurrent.TimeUnit;
4   import java.util.logging.Level;
5   
6   import com.google.inject.Inject;
7   
8   import cz.cuni.amis.pogamut.base.agent.IAgentId;
9   import cz.cuni.amis.pogamut.base.agent.impl.AbstractGhostAgent;
10  import cz.cuni.amis.pogamut.base.agent.state.impl.AgentStateStarting;
11  import cz.cuni.amis.pogamut.base.communication.command.IAct;
12  import cz.cuni.amis.pogamut.base.communication.worldview.event.IWorldEventListener;
13  import cz.cuni.amis.pogamut.base.communication.worldview.object.IWorldObjectEvent;
14  import cz.cuni.amis.pogamut.base.communication.worldview.react.ObjectEventReactOnce;
15  import cz.cuni.amis.pogamut.base.component.bus.IComponentBus;
16  import cz.cuni.amis.pogamut.base.component.bus.event.BusAwareCountDownLatch;
17  import cz.cuni.amis.pogamut.base.component.exception.ComponentCantStartException;
18  import cz.cuni.amis.pogamut.base.utils.guice.AgentScoped;
19  import cz.cuni.amis.pogamut.base.utils.logging.IAgentLogger;
20  import cz.cuni.amis.pogamut.base3d.worldview.IVisionWorldView;
21  import cz.cuni.amis.pogamut.udk.communication.messages.gbcommands.PasswordReply;
22  import cz.cuni.amis.pogamut.udk.communication.messages.gbcommands.Ready;
23  import cz.cuni.amis.pogamut.udk.communication.messages.gbinfomessages.GameInfo;
24  import cz.cuni.amis.pogamut.udk.communication.messages.gbinfomessages.Password;
25  import cz.cuni.amis.pogamut.udk.communication.translator.shared.events.ReadyCommandRequest;
26  import cz.cuni.amis.pogamut.udk.observer.IUDKObserver;
27  
28  
29  
30  
31  
32  
33  
34  
35  
36  
37  
38  
39  
40  
41  
42  
43  
44  
45  
46  @AgentScoped
47  public abstract class AbstractUDKObserver<WORLD_VIEW extends IVisionWorldView, ACT extends IAct> extends AbstractGhostAgent<WORLD_VIEW, ACT> implements IUDKObserver {
48  	
49  	
50  
51  
52  
53  	private String desiredPassword = null;
54  	
55  	private ObjectEventReactOnce<GameInfo, IWorldObjectEvent<GameInfo>> latchRaiseReact;
56  	
57  	private BusAwareCountDownLatch latch;
58  	
59  	@Inject
60  	public AbstractUDKObserver(IAgentId agentId, IComponentBus bus, IAgentLogger agentLogger, WORLD_VIEW worldView, ACT act) {
61  		super(agentId, bus, agentLogger, worldView, act);
62  
63  		getWorldView().addEventListener(ReadyCommandRequest.class, readyCommandRequestListener);
64  		getWorldView().addEventListener(Password.class, passwordRequestedListener);
65  		
66  		latch = new BusAwareCountDownLatch(1, bus, getWorldView());
67  		
68  		latchRaiseReact = new ObjectEventReactOnce<GameInfo, IWorldObjectEvent<GameInfo>>(
69  				GameInfo.class, getWorldView()
70  		) {
71  			@Override
72  			protected void react(IWorldObjectEvent<GameInfo> event) {
73  				latch.countDown();
74  			}
75  		};
76  
77  		
78  	}
79  
80  	
81  
82  
83  
84  
85  	public void setPassword(String password) {
86  		this.desiredPassword = password;
87  	}
88  
89  	
90  	
91  	
92  	
93  	
94  	
95  
96  
97  
98  
99  	protected void readyCommandRequested() {
100 		getAct().act(new Ready());
101 	}
102 
103 	
104 
105 
106 
107 
108 	private IWorldEventListener<ReadyCommandRequest> readyCommandRequestListener = new IWorldEventListener<ReadyCommandRequest>() {
109 
110 		@Override
111 		public void notify(ReadyCommandRequest event) {
112 			setState(new AgentStateStarting("GameBots2004 greeted us, sending READY."));
113 			readyCommandRequested();
114 			setState(new AgentStateStarting("READY sent."));
115 		}
116 	};
117 	
118 	
119 	
120 	
121 	
122 	
123 
124 
125 
126 
127 
128 
129 
130 	private PasswordReply passwordReply = null;
131 
132 	
133 
134 
135 
136 
137 
138 
139 
140 
141 
142 	public PasswordReply getPasswordReply() {
143 		return passwordReply;
144 	}
145 
146 	
147 
148 
149 
150 
151 
152 
153 
154 
155 
156 
157 
158 
159 
160 
161 
162 
163 
164 	protected PasswordReply createPasswordReply() {
165 		return desiredPassword != null ? new PasswordReply(desiredPassword)
166 				: null;
167 	}
168 
169 	
170 
171 
172 
173 	private IWorldEventListener<Password> passwordRequestedListener = new IWorldEventListener<Password>() {
174 
175 		@Override
176 		public void notify(Password event) {
177 			setState(new AgentStateStarting("Password requested by the world."));
178 			passwordReply = createPasswordReply();
179 			if (passwordReply == null) {
180 				passwordReply = new PasswordReply("");
181 			}
182 			if (log.isLoggable(Level.INFO)) log.info("Password required for the world, replying with '"
183 					+ passwordReply.getPassword() + "'.");
184 			getAct().act(passwordReply);
185 		}
186 	};
187 
188 	@Override
189 	public WORLD_VIEW getWorldView() {
190 		return super.getWorldView();
191 	}
192 	
193 	
194 	
195 	
196 	
197 	
198 	
199 	
200 
201 
202 	protected void reset() {
203 		latch.countDown();
204 		latch = new BusAwareCountDownLatch(1, getEventBus(), getWorldView());
205 		latchRaiseReact.enable();
206 	}
207 	
208 	@Override
209 	protected void startAgent() {
210 		super.startAgent();
211 		if (!latch.await(60000, TimeUnit.MILLISECONDS)) {
212 			throw new ComponentCantStartException("GameInfo message was not received in 60 secs.", this);
213 		}
214 	}
215 	
216 	@Override
217 	protected void resetAgent() {
218 		super.resetAgent();
219 		reset();
220 	}
221 	
222 	@Override
223 	protected void stopAgent() {
224 		super.stopAgent();
225 		reset();
226 	}
227 	
228 	@Override
229 	protected void killAgent() {
230 		super.killAgent();
231 		reset();
232 	}
233 }