package nl.tudelft.bw4t.server.environment; import java.io.File; import org.apache.log4j.Logger; import eis.eis2java.environment.AbstractEnvironment; import eis.iilang.EnvironmentState; import repast.simphony.scenario.ScenarioLoadException; /** * Stepper is the thread that schedules the bot stepping according to the * environment run mode and the loopDelay setting. */ public class Stepper implements Runnable { /** * The log4j logger, logs to the console. */ public static final int MIN_DELAY = 10; public static final int MAX_DELAY = 200; private static final Logger LOGGER = Logger.getLogger(Stepper.class); /** * HACK should be private. */ BW4TRunner runner; private final String scenarioLocation; private final AbstractEnvironment environment; /** * default 10ms between steps */ private long loopDelay = 20; private boolean running = true; public Stepper(String scenario, AbstractEnvironment envi) throws ScenarioLoadException { scenarioLocation = scenario; environment = envi; runner = new BW4TRunner(); runner.load(new File(scenarioLocation)); runner.runInitialize(); } @Override public void run() { try { while (running) { while (runner.getActionCount() > 0 && running) { /* * note: busy-wait since we have to be prepared to be killed * also if env is in pause mode. The sleep avoid sucking * CPU. */ if (environment.getState() == EnvironmentState.RUNNING) { if (runner.getModelActionCount() == 0) { runner.setFinishing(true); } runner.step(); } try { Thread.sleep(loopDelay); } catch (InterruptedException e) { LOGGER.warn("The main loop was interrupted.", e); } } runner.stop(); runner.cleanUpRun(); } } catch (Exception e) { LOGGER.error("An internal error occurred while running the stepper: ", e); } running = false; runner = null; } public long getDelay() { return loopDelay; } /** * set new delay value. Lower is faster animation speed. * * @param value * the value for the delay. Should be at least {@link #MIN_DELAY} * . */ public void setDelay(int value) { if (value < MIN_DELAY || value > MAX_DELAY) { throw new IllegalArgumentException( "speed should be >=" + MIN_DELAY + " and <= " + MAX_DELAY + " but got " + value); } loopDelay = value; } /** * Call this only after EnvironmentState=KILLED. This function returns only * after the stepper thread stopped. */ public void terminate() { running = false; while (runner != null) { LOGGER.info("Stepper is running... waiting for requests."); try { Thread.sleep(1000); } catch (InterruptedException e) { LOGGER.warn("Ignoring interrupt from wait.", e); } } } }