/*
* Datei: AbstractDefaultMaster.java
* Autor(en): Lukas König
* Java-Version: 6.0
* Erstellt: 21.05.2009
*
* (c) This file and the EAS (Easy Agent Simulation) framework containing it
* is protected by Creative Commons by-nc-sa license. Any altered or
* further developed versions of this file have to meet the agreements
* stated by the license conditions.
*
* In a nutshell
* -------------
* You are free:
* - to Share -- to copy, distribute and transmit the work
* - to Remix -- to adapt the work
*
* Under the following conditions:
* - Attribution -- You must attribute the work in the manner specified by the
* author or licensor (but not in any way that suggests that they endorse
* you or your use of the work).
* - Noncommercial -- You may not use this work for commercial purposes.
* - Share Alike -- If you alter, transform, or build upon this work, you may
* distribute the resulting work only under the same or a similar license to
* this one.
*
* + Detailed license conditions (Germany):
* http://creativecommons.org/licenses/by-nc-sa/3.0/de/
* + Detailed license conditions (unported):
* http://creativecommons.org/licenses/by-nc-sa/3.0/deed.en
*
* This header must be placed in the beginning of any version of this file.
*/
package eas.plugins.masterScheduler;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import eas.miscellaneous.StaticMethods;
import eas.plugins.standard.liveInteraction.AllroundLiveParameterSetterPlugin;
import eas.plugins.standard.liveInteraction.AllroundObserverControllerPlugin;
import eas.plugins.standard.visualization.AllroundVideoPlugin;
import eas.simulation.Wink;
import eas.simulation.agent.AbstractAgent;
import eas.simulation.event.EASEvent;
import eas.simulation.standardEnvironments.AbstractEnvironment;
import eas.startSetup.GlobalVariables;
import eas.startSetup.ParCollection;
import eas.startSetup.SingleParameter;
import eas.startSetup.parameterDatatypes.Datatypes;
/**
* Implementation of a default master scheduler that produces a standard
* behavior suitable for most types of schedulers; however, much
* more functionality than this standard implementation can be achieved with
* schedulers. The standard behavior for the methods is (most important is
* runDuringSim):<BR><BR>
* - generateEnvironments ==> None - method is abstract.<BR>
* - id ==> None - method is abstract.<BR>
* - getGenericParams ==> Return the parameters of all the environments and
* agents that are generated by generateEnvironments.
* <BR>
* IMPORTANT NOTE: A common source of errors is not to add an agent type to
* the original environment that is returned by generateEnvironments, but to
* add it at a later time. While this is allowed, it has to be assured that
* the generic parameters of that agent type are extracted manually by the
* method getGenericParams of the scheduler; otherwise the parameters of the
* agent type cannot be instantiated. (Cf. the standard behavior of that
* method described above.)
* - getRequiredPlugins ==> Return null.<BR>
* - runAfterSim: No functionality implemented.<BR>
* - runBeforeSim: No functionality implemented.<BR>
* - runDuringSim: Call the step method of the calling environment and then
* sequentially the step methods of all agents in the
* environment.<BR>
* - handleEvent: Propagate the event to the calling environment and the
* agents in the environment. Note that no events are
* broadcast to the AbstractDefaultMaster in the standard
* implementation; to do so, the requestEvents method of
* the simulation time object has to be invoked.<BR><BR>
* - onSimulationResumed(): notifies the main runnable and prints an info message to std. out.<BR>
* Note that the most general runnable class supported by the standard master
* scheduler is <code>AbstractEnvironment</code>. For more general simulations
* the <code>MasterScheduler</code> interface has to be implemented directly.
* <BR><BR>
* Always implement in [EAS] order:
* "[E]NVIRONMENT -> [A]GENT -> [S]CHEDULER"
*
* @author Lukas König
*/
public abstract class AbstractDefaultMaster<Env extends AbstractEnvironment<?>>
implements MasterScheduler<Env> {
private static final long serialVersionUID = -4880256149915195030L;
private Double timeToTermination = null;
/**
* Abstract method that has to implement a list of environments. This list
* is used to produce threads for each environment to make them run
* simultaneously.
*/
@Override
public abstract Env[] generateRunnables(
final ParCollection params);
/**
* Returns the list of generic parameters consisting of all parameters of
* the generated environments and agents by the method
* generateEnvironments.
*
* Note that agents that are added later to the environment (i.e. are not
* present in the environment given by the scheduler) do not get checked
* for parameters. If parameters of these agents should be added to the
* parameter collection, this has to be done manually.
*/
@Override
public List<SingleParameter> getParameters() {
LinkedList<SingleParameter> list = new LinkedList<SingleParameter>();
// ParCollection paramsZwisch = new ParCollection(new String[] {});
// paramsZwisch.complete();
list.add(new SingleParameter(
"TimeToTermination",
Datatypes.DOUBLE,
100000.0,
"Simulation time till termination (might be ignored if method 'isTerminationRequested' overriden by master scheduler).",
this.id().toUpperCase()));
try {
Env[] environments = this.generateRunnables(GlobalVariables.getPrematureParameters());
if (environments == null) {
return list;
}
LinkedList<SingleParameter> wholeList = new LinkedList<SingleParameter>();
for (Env e : environments) {
wholeList.addAll(e.getParameters());
for (AbstractAgent<?> a : e.getAgents()) {
wholeList.addAll(a.getParameters());
}
}
for (SingleParameter s1 : wholeList) {
boolean contains = false;
for (SingleParameter s2 : list) {
if (s2.getParameterName().equals(s1.getParameterName())) {
contains = true;
break;
}
}
if (!contains) {
list.add(s1);
}
}
} catch (Exception e) {
StaticMethods.logError("AbstractDefaultMaster could not generate parameters list: " + e.toString(), null);
throw new RuntimeException(e);
}
return list;
}
/**
* No other plugins are required.
*/
@Override
public List<String> getRequiredPlugins() {
return null;
}
@Override
public List<String> getSupportedPlugins() {
ArrayList<String> list = new ArrayList<String>(2);
list.add(new AllroundVideoPlugin().id());
list.add(new AllroundObserverControllerPlugin().id());
list.add(new AllroundLiveParameterSetterPlugin().id());
return list;
}
/**
* The id of this plugin. This id has to be unique at a global level.
*/
@Override
public abstract String id();
/**
* No standard functionality implemented.
*/
@Override
public void runAfterSimulation(
final Env umg,
final ParCollection params) {
}
/**
* No standard functionality implemented.
*/
@Override
public void runBeforeSimulation(
final Env umg,
final ParCollection params) {
}
/**
* Propagate time step to environment and all agents contained in it.
*/
@Override
public synchronized void runDuringSimulation(
final Env env,
final Wink currentTime,
final ParCollection params) {
env.step(currentTime);
for (AbstractAgent<?> agent : env.getAgents()) {
agent.step(currentTime);
}
}
/**
* Propagate event to environment and all agents contained in it.
*/
@Override
public void handleEvent(
final EASEvent e,
final Env env,
final Wink lastTick,
final ParCollection params) {
env.handleEvent(e, lastTick);
for (AbstractAgent<?> agent : env.getAgents()) {
agent.handleEvent(e, lastTick);
}
}
@Override
public boolean isTerminationRequested(Env runnable,
Wink currentTime, ParCollection params) {
if (timeToTermination == null) {
this.timeToTermination = params.getParValueDouble("TimeToTermination");
}
return timeToTermination < currentTime.getCurrentTime();
}
@Override
public void onSimulationResumed(Env env, Wink resumeTime,
ParCollection params) {
env.onSimulationResumed();
params.logInfo("'"
+ this.id()
+ "' has been notified that the simulation has been resumed.\n"
+ "I have passed the notification on to the main runnable '"
+ env.getClass().getSimpleName()
+ "' - please override the master scheduler's onSimulationResumed(.) method to implement additional functionality.");
}
@Override
public String pluginDescription() {
return "Default master scheduler implementation (override pluginDescription method to provide a specific description here).";
}
}