package srsim.domain;
import java.util.LinkedList;
import java.util.List;
import srsim.simulator.ContextChangedEvent;
import srsim.simulator.ControllerActionEvent;
import srsim.simulator.IContextListener;
import srsim.simulator.IControllerActionListener;
import srsim.simulator.ISimulationListener;
import srsim.simulator.ITimeSource;
import srsim.simulator.SimulationContext;
import srsim.simulator.SimulationContextException;
/**
* The simulation class handles the process of simulation a given room
* configuration.
*
* @author phil
*
*/
public class Simulation implements IContextListener, IControllerActionListener {
private SimulationContext globalContext;
private List<Room> rooms;
private List<ISimulationListener> simulationListeners;
private long resolution;
/**
* Creates a new simulation using the provided timesource for timestamp
* generation
*
* @param timeSource
* ITimesource implementation to be used for timestamping
*/
public Simulation(final ITimeSource timeSource) {
globalContext = new SimulationContext(timeSource);
simulationListeners = new LinkedList<ISimulationListener>();
rooms = new LinkedList<Room>();
resolution = 1000;
}
/**
* Returns true if the simulation is finished
*
* @return
*/
public boolean isFinished() {
return false;
}
/**
* Performs the next simulation step
*
* @throws SimulationContextException
* @throws InterruptedException
*/
public void step() throws SimulationContextException, InterruptedException {
long start = System.currentTimeMillis();
for (Room room : rooms) {
for (ISensor sensor : room.getSensors()) {
sensor.step();
}
for (IController controller : room.getControllers()) {
controller.step();
}
for (IActuator actuator : room.getActuators()) {
actuator.step();
}
}
long duration = resolution - (System.currentTimeMillis() - start);
Thread.sleep(duration > 0L ? duration : 0L);
}
/**
* Returns the global simulation context
*
* @return
*/
public SimulationContext getContext() {
return globalContext;
}
/**
* Returns a list of simulated rooms
*
* @return
*/
public List<Room> getRooms() {
return rooms;
}
/**
* Adds a room to the simulation
*
* @param room
*/
public void addRoom(final Room room) {
try {
room.setContext(globalContext);
room.getLocalContext().addContextListener(this);
for (IController controller : room.getControllers()) {
controller.addControllerActionListener(this);
}
rooms.add(room);
} catch (SimulationContextException e) {
e.printStackTrace();
}
}
/**
* Adds a listener to be notified on simulation changes
*
* @param simulationListener
*/
public void addSimulationListener(
final ISimulationListener simulationListener) {
synchronized (simulationListeners) {
simulationListeners.add(simulationListener);
}
}
@Override
public void handleContextChange(final ContextChangedEvent event)
throws SimulationContextException {
synchronized (simulationListeners) {
for (ISimulationListener listener : simulationListeners) {
listener.handleContextChange(event);
}
}
}
@Override
public void handleControllerAction(final ControllerActionEvent event) {
synchronized (simulationListeners) {
for (ISimulationListener listener : simulationListeners) {
listener.handleControllerAction(event);
}
}
}
public void setResolution(final long resolution) {
this.resolution = resolution;
}
}