package com.plectix.simulator.simulator;
import com.plectix.simulator.controller.SimulatorInputData;
import com.plectix.simulator.controller.SimulatorInterface;
import com.plectix.simulator.controller.SimulatorResultsData;
import com.plectix.simulator.controller.SimulatorStatusInterface;
import com.plectix.simulator.simulator.api.steps.CommandLineDefinedWorkflow;
import com.plectix.simulator.simulator.api.steps.OperationManager;
import com.plectix.simulator.simulator.api.steps.SimulationOperation;
import com.plectix.simulator.simulator.api.steps.SolutionInitializationOperation;
import com.plectix.simulator.simulator.api.steps.StoriesComputationOperation;
import com.plectix.simulator.streaming.LiveData;
import com.plectix.simulator.streaming.LiveDataStreamer;
import com.plectix.simulator.util.io.PlxLogger;
public final class Simulator implements SimulatorInterface {
private static final PlxLogger logger = ThreadLocalData.getLogger(Simulator.class);
private final SimulationData simulationData = new SimulationData();
private final SimulatorStatus simulatorStatus = new SimulatorStatus();
private final SimulatorResultsData simulatorResultsData = new SimulatorResultsData();
private final LiveDataStreamer liveDataStreamer = new LiveDataStreamer();
/**
* Object to lock when we are reading variables to compute the current
* status
*/
private final Object statusLock = new Object();
// TODO maybe we can just leave only SimulatorStatus
private SimulationState state = new SimulationState();
public Simulator() {
super();
simulatorStatus.setStatusMessage(SimulatorMessage.STATUS_IDLE);
}
/**
* We assume that this method is called from a separate thread than the
* simulation thread. We also assume that there can be only one thread
* calling this method at a time.
*
*/
public final SimulatorStatusInterface getStatus() {
synchronized (statusLock) {
// save the current state variables in the status object and use
// them below
simulatorStatus.setCurrentTime(state.getCurrentTime());
simulatorStatus.setCurrentEventNumber(state.getCurrentEventNumber());
simulatorStatus.setCurrentIterationNumber(state.getCurrentIterationNumber());
}
// let's compute our progress:
double progress = simulatorStatus.getProgress();
if (Double.isNaN(progress) || progress < 1.0) {
SimulationArguments simulationArguments = simulationData
.getSimulationArguments();
if (simulationArguments.isTime()) {
progress = simulatorStatus.getCurrentTime()
/ simulationArguments.getTimeLimit();
} else {
progress = simulatorStatus.getCurrentEventNumber() * 1.0
/ simulationArguments.getMaxNumberOfEvents();
}
if (simulationArguments.needToStorify()) {
progress = (progress + simulatorStatus
.getCurrentIterationNumber())
/ simulationArguments.getIterations();
if (progress > 1.0) {
progress = 1.0;
}
}
simulatorStatus.setProgress(progress);
}
return simulatorStatus;
}
@Override
public final void cleanUpAfterException(Exception exception) {
simulatorStatus.setStatusMessage(SimulatorMessage.STATUS_EXCEPTION
+ exception.getClass().getName());
simulatorStatus.setProgress(1.0);
}
public final void run(SimulatorInputData simulatorInputData)
throws Exception {
OperationManager manager = simulationData.getKappaSystem().getOperationManager();
manager.perform(new CommandLineDefinedWorkflow(this, simulatorInputData));
}
public final void runSimulation() throws Exception {
OperationManager manager = simulationData.getKappaSystem().getOperationManager();
manager.perform(new SimulationOperation(this));
}
public final void runStories() throws Exception {
OperationManager manager = simulationData.getKappaSystem().getOperationManager();
manager.perform(new StoriesComputationOperation(this));
}
/**
* This method only reads Kappa File and builds the KappaSystem object We
* should be able to run it independently
* @throws Exception
*/
public final void initializeKappaSystem() throws Exception {
simulatorStatus.setStatusMessage(SimulatorMessage.STATUS_INITIALIZING);
simulationData.getKappaSystem().getOperationManager()
.perform(new SolutionInitializationOperation(simulationData));
}
// ////////////////////////////////////////////////////////////////////////
//
// GETTERS AND SETTERS
//
//
public final LiveData getLiveData() {
return liveDataStreamer.getLiveData();
}
public final String getName() {
return SimulatorMessage.NAME;
}
public final SimulationData getSimulationData() {
return simulationData;
}
public final SimulatorResultsData getSimulatorResultsData() {
return simulatorResultsData;
}
public PlxLogger getLogger() {
return logger;
}
public LiveDataStreamer getLiveDataStreamer() {
return liveDataStreamer;
}
public Object getStatusLock() {
return statusLock;
}
public SimulationState initializeSimulationState() {
state = new SimulationState();
return state;
}
public SimulatorStatus getLatestFreezedStatus() {
return simulatorStatus;
}
public SimulationState getState() {
return state;
}
}