View Javadoc

1   package cz.cuni.amis.pogamut.ut2004.agent.module.logic;
2   
3   import java.util.concurrent.TimeUnit;
4   import java.util.logging.Level;
5   import java.util.logging.Logger;
6   
7   import com.google.inject.Inject;
8   
9   import cz.cuni.amis.pogamut.base.agent.exceptions.AgentException;
10  import cz.cuni.amis.pogamut.base.agent.module.IAgentLogic;
11  import cz.cuni.amis.pogamut.base.agent.module.LogicModule;
12  import cz.cuni.amis.pogamut.base.communication.worldview.object.IWorldObjectEvent;
13  import cz.cuni.amis.pogamut.base.communication.worldview.react.EventReact;
14  import cz.cuni.amis.pogamut.base.communication.worldview.react.EventReactOnce;
15  import cz.cuni.amis.pogamut.base.communication.worldview.react.ObjectEventReactOnce;
16  import cz.cuni.amis.pogamut.base.component.bus.event.BusAwareCountDownLatch;
17  import cz.cuni.amis.pogamut.base.component.controller.ComponentDependencies;
18  import cz.cuni.amis.pogamut.base.component.controller.ComponentDependencyType;
19  import cz.cuni.amis.pogamut.base.component.exception.ComponentCantStartException;
20  import cz.cuni.amis.pogamut.ut2004.bot.impl.UT2004Bot;
21  import cz.cuni.amis.pogamut.ut2004.communication.messages.gbinfomessages.EndMessage;
22  import cz.cuni.amis.pogamut.ut2004.communication.messages.gbinfomessages.GameInfo;
23  import cz.cuni.amis.pogamut.ut2004.communication.messages.gbinfomessages.GamePaused;
24  import cz.cuni.amis.pogamut.ut2004.communication.messages.gbinfomessages.GameResumed;
25  import cz.cuni.amis.pogamut.ut2004.communication.messages.gbinfomessages.Self;
26  import cz.cuni.amis.pogamut.ut2004.communication.messages.gbinfomessages.SelfLocal;
27  import cz.cuni.amis.utils.flag.Flag;
28  
29  public class UT2004BotLogic<BOT extends UT2004Bot> extends LogicModule<BOT> {
30  
31  	private EventReact<GamePaused>            pauseReaction;
32  	private EventReact<GameResumed>           resumeReaction;
33  	private ObjectEventReactOnce<Self, ?>     selfReaction;
34  	private ObjectEventReactOnce<GameInfo, ?> gameInfoReaction;
35  	private EventReact<EndMessage>            endReaction;
36  	private BusAwareCountDownLatch            latch;
37  	
38  	private Flag<Boolean> gameInfoCame = new Flag<Boolean>(false);
39  	private Flag<Boolean> selfCame = new Flag<Boolean>(false);
40  	private Flag<Boolean> endCame = new Flag<Boolean>(false);
41  	
42  	@Inject
43  	public UT2004BotLogic(BOT agent, IAgentLogic logic) {
44  		this(agent, logic, null, new ComponentDependencies(ComponentDependencyType.STARTS_WITH).add(agent.getWorldView()));
45  	}
46  	
47  	public UT2004BotLogic(BOT agent, IAgentLogic logic, Logger log) {
48  		this(agent, logic, log, new ComponentDependencies(ComponentDependencyType.STARTS_WITH).add(agent.getWorldView()));
49  	}
50  	
51  	public UT2004BotLogic(BOT agent, IAgentLogic logic, Logger log, ComponentDependencies dependencies) {
52  		super(agent, logic, log, dependencies);
53  		pauseReaction = new EventReact<GamePaused>(GamePaused.class, agent.getWorldView()) {
54  			@Override
55  			protected void react(GamePaused event) {
56  				controller.manualPause("Game paused.");
57  			}
58  		};
59  		resumeReaction = new EventReact<GameResumed>(GameResumed.class, agent.getWorldView()) {
60  			@Override
61  			protected void react(GameResumed event) {
62  				controller.manualResume("Game resumed.");
63  			}
64  		};
65  		gameInfoReaction = new ObjectEventReactOnce<GameInfo, IWorldObjectEvent<GameInfo>>(GameInfo.class, agent.getWorldView()) {
66  			@Override
67  			protected void react(IWorldObjectEvent<GameInfo> event) {
68  				if (event.getObject().isBotsPaused() || event.getObject().isGamePaused()) {
69  					controller.manualPause("Bot launched into paused game.");
70  				}
71  				gameInfoCame.setFlag(true);
72  			}
73  		};
74  		selfReaction = new ObjectEventReactOnce<Self, IWorldObjectEvent<Self>>(Self.class, agent.getWorldView()) {
75  			@Override
76  			protected void react(IWorldObjectEvent<Self> event) {
77  				selfCame.setFlag(true);
78  			}
79  		};
80  		
81  		endReaction = new EventReactOnce<EndMessage>(EndMessage.class, agent.getWorldView()) {
82  			@Override
83  			protected void react(EndMessage event) {
84  				synchronized(endCame) {
85  					endCame.setFlag(true);
86  					latch.countDown();
87  				}
88  			}
89  		};		
90  		cleanUp();
91  	}
92  
93  	@Override
94  	protected void logicLatch(String threadName) {
95  		super.logicLatch(threadName);
96  		if (log.isLoggable(Level.FINE)) log.fine(threadName + ": Waiting for the first End message.");
97  		if (!latch.await(120, TimeUnit.SECONDS)) {
98  			throw new ComponentCantStartException("End message was not received in 120secs.", this);
99  		}		
100 		if (log.isLoggable(Level.INFO)) log.info(threadName + ": First END message received, starting logic cycles.");
101 		boolean came = selfCame.waitFor(60000, true);
102 		if (!came) {
103 			throw new ComponentCantStartException(threadName + ": SELF message DID NOT COME in 60secs! Even though End message has been received.", this);
104 		}
105 		if (!gameInfoCame.getFlag()) {
106 			if (log.isLoggable(Level.WARNING)) log.warning(threadName + ": GAMEINFO message DID NOT COME! Even though End message has been received. Was it disabled in GameBot2004.ini? Or is it a bug... ?");
107 		}
108 	}
109 	
110 	@Override
111 	protected void start(boolean startPaused) throws AgentException {
112 		super.start(startPaused);
113 		// this is synchronized also in EndMessage listener, we must not allow the situation
114 		// 1. END MESSAGE CAME
115 		// 2. thread1: fires EndMessageListener
116 		// 3. thread2: start() is called
117 		// 4. thread1: calls latch.countDown on old version of the latch
118 		// 5. thread2: latch is initialized
119 		// ... FIRST END MESSAGE IS TOTALLY MISSED, LOGIC WON'T START!
120 		synchronized(endCame) {
121 			latch = new BusAwareCountDownLatch(1, agent.getEventBus(), agent.getWorldView().getComponentId());
122 			if (endCame.getFlag()) {
123 				latch.countDown();
124 			}
125 		}
126 	}
127 	
128 	@Override
129 	protected void cleanUp() throws AgentException {
130 		super.cleanUp();
131 		gameInfoCame.setFlag(false);
132 		selfCame.setFlag(false);
133 		gameInfoReaction.enable();
134 		selfReaction.enable();
135 		endReaction.enable();
136 		endCame.setFlag(false);
137 	}
138 
139 }