package firesimulator;
import rescuecore2.config.NoSuchConfigOptionException;
import rescuecore2.worldmodel.Entity;
import rescuecore2.worldmodel.EntityID;
import rescuecore2.worldmodel.ChangeSet;
import rescuecore2.messages.Command;
import rescuecore2.messages.control.KSUpdate;
import rescuecore2.messages.control.KSCommands;
import rescuecore2.log.Logger;
import rescuecore2.standard.messages.AKExtinguish;
import rescuecore2.standard.components.StandardSimulator;
import rescuecore2.standard.entities.StandardEntity;
import rescuecore2.standard.entities.StandardEntityURN;
import firesimulator.world.World;
import firesimulator.world.WorldInfo;
import firesimulator.world.Refuge;
import firesimulator.world.FireStation;
import firesimulator.world.PoliceOffice;
import firesimulator.world.AmbulanceCenter;
import firesimulator.world.Building;
import firesimulator.world.Civilian;
import firesimulator.world.FireBrigade;
import firesimulator.world.PoliceForce;
import firesimulator.world.AmbulanceTeam;
import firesimulator.world.RescueObject;
import firesimulator.world.MovingObject;
import firesimulator.simulator.Simulator;
import firesimulator.simulator.ExtinguishRequest;
import firesimulator.util.Configuration;
import java.util.Collection;
/**
A rescuecore2 Simulator that wraps the ResQ Freiburg fire simulator.
*/
public class FireSimulatorWrapper extends StandardSimulator {
private static final String MAX_WATER_KEY = "fire.tank.maximum";
private Simulator sim;
private World world;
@Override
protected void postConnect() {
super.postConnect();
Configuration c = new Configuration();
c.initialize();
for (String next : c.getPropertyNames()) {
try {
String value = config.getValue(next);
Configuration.setProperty(next, value, true);
Logger.debug("Setting '" + next + "' to '" + value + "'");
}
catch (NoSuchConfigOptionException e) {
// Ignore
Logger.debug("Ignoring property " + next);
}
}
world = new World();
sim = new Simulator(world);
// Map each entity to a fire simulator object
for (Entity next : model) {
RescueObject r = mapEntity(next);
if (r != null) {
world.putObject(r);
}
}
sim.initialize();
}
@Override
protected void handleUpdate(KSUpdate u) {
super.handleUpdate(u);
// Merge objects
for (EntityID id : u.getChangeSet().getChangedEntities()) {
Entity e = model.getEntity(id);
RescueObject r = world.getObject(id.getValue());
if (r == null) {
r = mapEntity(e);
if (r != null) {
world.putObject(r);
}
}
else {
if (r instanceof Building && e instanceof rescuecore2.standard.entities.Building) {
Building b = (Building)r;
mapBuildingProperties((rescuecore2.standard.entities.Building)e, b);
// Check for new ignitions
if (b.getIgnition() == 1 && b.isInflameable()) {
int fieryness = b.getFieryness();
// CHECKSTYLE:OFF:MagicNumber
if (fieryness == 0 || fieryness == 4) {
// CHECKSTYLE:ON:MagicNumber
Logger.debug("Igniting " + b);
b.ignite();
}
}
}
else if (r instanceof MovingObject && e instanceof rescuecore2.standard.entities.Human) {
mapHumanProperties((rescuecore2.standard.entities.Human)e, (MovingObject)r);
}
else {
Logger.error("Don't know how to map " + r + " from " + e);
}
}
}
}
@Override
protected void processCommands(KSCommands c, ChangeSet changes) {
long start = System.currentTimeMillis();
for (Command next : c.getCommands()) {
if (next instanceof AKExtinguish) {
AKExtinguish ex = (AKExtinguish)next;
EntityID agentID = ex.getAgentID();
EntityID targetID = ex.getTarget();
int water = ex.getWater();
FireBrigade source = (FireBrigade)world.getObject(agentID.getValue());
Building target = (Building)world.getObject(targetID.getValue());
ExtinguishRequest req = new ExtinguishRequest(source, target, water);
world.addExtinguishRequest(req);
}
}
sim.step(c.getTime());
// Get changes
for (Object next : world.getBuildings()) {
Building b = (Building)next;
rescuecore2.standard.entities.Building oldB = (rescuecore2.standard.entities.Building)model.getEntity(new EntityID(b.getID()));
if ((!oldB.isFierynessDefined()) || (oldB.getFieryness() != b.getFieryness())) {
oldB.setFieryness(b.getFieryness());
changes.addChange(oldB, oldB.getFierynessProperty());
}
if ((!oldB.isTemperatureDefined()) || (oldB.getTemperature() != (int)b.getTemperature())) {
oldB.setTemperature((int)b.getTemperature());
changes.addChange(oldB, oldB.getTemperatureProperty());
}
}
for (Object next : world.getFirebrigades()) {
FireBrigade fb = (FireBrigade)next;
// Logger.debug("Updating water for " + fb);
// Logger.debug(fb.hasChanged() ? "Changed" : "Unchanged");
// if (fb.hasChanged()) {
rescuecore2.standard.entities.FireBrigade oldFB = (rescuecore2.standard.entities.FireBrigade)model.getEntity(new EntityID(fb.getID()));
// Logger.debug("Old water: " + oldFB.getWaterProperty());
// Logger.debug("New water: " + fb.getWaterQuantity());
if ((!oldFB.isWaterDefined()) || (oldFB.getWater() != fb.getWaterQuantity())) {
oldFB.setWater(fb.getWaterQuantity());
changes.addChange(oldFB, oldFB.getWaterProperty());
}
// }
}
if (c.getTime() == 1) {
// Set initial water quantity for all fire brigades
for (StandardEntity next : model.getEntitiesOfType(StandardEntityURN.FIRE_BRIGADE)) {
rescuecore2.standard.entities.FireBrigade fb = (rescuecore2.standard.entities.FireBrigade)next;
fb.setWater(config.getIntValue(MAX_WATER_KEY));
changes.addChange(fb, fb.getWaterProperty());
}
}
long end = System.currentTimeMillis();
Logger.info("Time " + c.getTime() + " took " + (end - start) + "ms");
}
private RescueObject mapEntity(Entity e) {
int id = e.getID().getValue();
if (e instanceof rescuecore2.standard.entities.World) {
return new WorldInfo(id);
}
if (e instanceof rescuecore2.standard.entities.Refuge) {
Refuge r = new Refuge(id);
mapBuildingProperties((rescuecore2.standard.entities.Building)e, r);
return r;
}
if (e instanceof rescuecore2.standard.entities.FireStation) {
FireStation fs = new FireStation(id);
mapBuildingProperties((rescuecore2.standard.entities.Building)e, fs);
return fs;
}
if (e instanceof rescuecore2.standard.entities.PoliceOffice) {
PoliceOffice po = new PoliceOffice(id);
mapBuildingProperties((rescuecore2.standard.entities.Building)e, po);
return po;
}
if (e instanceof rescuecore2.standard.entities.AmbulanceCentre) {
AmbulanceCenter ac = new AmbulanceCenter(id);
mapBuildingProperties((rescuecore2.standard.entities.Building)e, ac);
return ac;
}
if (e instanceof rescuecore2.standard.entities.Building) {
Building b = new Building(id);
mapBuildingProperties((rescuecore2.standard.entities.Building)e, b);
return b;
}
if (e instanceof rescuecore2.standard.entities.Civilian) {
Civilian c = new Civilian(id);
mapHumanProperties((rescuecore2.standard.entities.Civilian)e, c);
return c;
}
if (e instanceof rescuecore2.standard.entities.FireBrigade) {
FireBrigade fb = new FireBrigade(id);
mapHumanProperties((rescuecore2.standard.entities.FireBrigade)e, fb);
return fb;
}
if (e instanceof rescuecore2.standard.entities.PoliceForce) {
PoliceForce pf = new PoliceForce(id);
mapHumanProperties((rescuecore2.standard.entities.PoliceForce)e, pf);
return pf;
}
if (e instanceof rescuecore2.standard.entities.AmbulanceTeam) {
AmbulanceTeam at = new AmbulanceTeam(id);
mapHumanProperties((rescuecore2.standard.entities.AmbulanceTeam)e, at);
return at;
}
if (e instanceof rescuecore2.standard.entities.Road) {
return null;
}
if (e instanceof rescuecore2.standard.entities.Blockade) {
return null;
}
Logger.error("Don't know how to map this: " + e);
return null;
}
private void mapBuildingProperties(rescuecore2.standard.entities.Building oldB, Building newB) {
if (oldB.isFloorsDefined()) {
newB.setFloors(oldB.getFloors());
}
if (oldB.isBuildingAttributesDefined()) {
newB.setAttributes(oldB.getBuildingAttributes());
}
if (oldB.isIgnitionDefined()) {
newB.setIgnition(oldB.getIgnition() ? 1 : 0);
}
if (oldB.isFierynessDefined()) {
newB.setFieryness(oldB.getFieryness());
}
if (oldB.isBrokennessDefined()) {
newB.setBrokenness(oldB.getBrokenness());
}
if (oldB.isBuildingCodeDefined()) {
newB.setCode(oldB.getBuildingCode());
}
if (oldB.isGroundAreaDefined()) {
newB.setBuildingAreaGround(oldB.getGroundArea());
}
if (oldB.isTotalAreaDefined()) {
newB.setBuildingAreaTotal(oldB.getTotalArea());
}
if (oldB.isEdgesDefined()) {
newB.setApexes(oldB.getApexList());
}
if (oldB.isXDefined()) {
newB.setX(oldB.getX());
}
if (oldB.isYDefined()) {
newB.setY(oldB.getY());
}
}
private void mapHumanProperties(rescuecore2.standard.entities.Human oldH, MovingObject newH) {
if (oldH.isStaminaDefined()) {
newH.setStamina(oldH.getStamina());
}
if (oldH.isHPDefined()) {
newH.setHp(oldH.getHP());
}
if (oldH.isDamageDefined()) {
newH.setDamage(oldH.getDamage());
}
if (oldH.isBuriednessDefined()) {
newH.setBuriedness(oldH.getBuriedness());
}
if (oldH.isPositionDefined()) {
newH.setPositionId(oldH.getPosition().getValue());
}
if (oldH.isXDefined()) {
newH.setX(oldH.getX());
}
if (oldH.isYDefined()) {
newH.setY(oldH.getY());
}
if (oldH instanceof rescuecore2.standard.entities.FireBrigade && newH instanceof FireBrigade) {
rescuecore2.standard.entities.FireBrigade oldFB = (rescuecore2.standard.entities.FireBrigade)oldH;
FireBrigade newFB = (FireBrigade)newH;
if (oldFB.isWaterDefined()) {
newFB.setInitialWaterQuantity(oldFB.getWater());
}
}
}
private int[] collectionToIDArray(Collection<EntityID> list) {
int[] ids = new int[list.size()];
int i = 0;
for (EntityID next : list) {
ids[i++] = next.getValue();
}
return ids;
}
}