Unverified Commit 342fea6f authored by Juon Kawakami's avatar Juon Kawakami 🥗
Browse files

init

parent 54f6cedf
package misc;
import java.util.Random;
import java.util.Map;
import java.util.EnumMap;
import rescuecore2.config.Config;
import rescuecore2.standard.entities.Building;
import rescuecore2.standard.entities.Human;
import rescuecore2.standard.entities.AmbulanceTeam;
import rescuecore2.standard.entities.FireBrigade;
import rescuecore2.standard.entities.PoliceForce;
import rescuecore2.standard.entities.Refuge;
/**
* Container for all misc simulator parameters.
* @author Maitreyi Nanjanath
* @author Cameron Skinner
*/
public class MiscParameters {
private Config config;
// All building classes indexed by building code and degree of collapse. The BuildingClass class knows about buriedness rates, injury rates etc.
private Map<BuildingCode, Map<BrokennessDegree, BuildingClass>> buildingClasses;
private DamageType collapseDamage;
private DamageType buryDamage;
private DamageType fireDamage;
/**
Create a new MiscParameters object based on a Config.
@param config The Config to read.
*/
public MiscParameters(Config config) {
this.config = config;
initBuildingData();
initInjuryData();
}
/**
Find out if an agent inside a building should be buried due to collapse.
@param b The building to check.
@param hA Human Attribute for calc should bury.
@return True if an agent inside the building should be buried, false otherwise.
*/
public boolean shouldBuryAgent(Building b, HumanAttributes hA) {
if (!b.isBuildingCodeDefined() || !b.isBrokennessDefined() || b.getBrokenness() == 0||b instanceof Refuge) {
return false;
}
BuildingClass clazz = getBuildingClass(b);
return clazz.shouldBury(hA);
}
/**
Get the buriedness of an agent inside a building.
@param b The building to check.
@return The buriedness of an agent inside the building.
*/
public int getBuriedness(Building b) {
if (!b.isBuildingCodeDefined() || !b.isBrokennessDefined() || b.getBrokenness() == 0) {
return 0;
}
BuildingClass clazz = getBuildingClass(b);
return clazz.getAgentBuriedness();
}
/**
Get the amount of damage an agent should take as a result of being in a collapsing building.
@param b The building.
@param hA The HumanAttributes.
@return The amount of damage to add to the agent.
*/
public int getCollapseDamage(Building b, HumanAttributes hA) {
if (!b.isBuildingCodeDefined() || !b.isBrokennessDefined() || b.getBrokenness() == 0) {
return 0;
}
BuildingClass clazz = getBuildingClass(b);
Injury injury = clazz.getCollapseInjury(hA.getRandom());
return collapseDamage.getDamage(injury, hA.getHuman());
}
/**
Get the amount of damage an agent should take as a result of being buried in a collapsed building.
@param b The building.
@param hA The HumanAttributes.
@return The amount of damage to add to the agent.
*/
public int getBuryDamage(Building b, HumanAttributes hA) {
if (!b.isBuildingCodeDefined() || !b.isBrokennessDefined() || b.getBrokenness() == 0) {
return 0;
}
BuildingClass clazz = getBuildingClass(b);
Injury injury = clazz.getBuryInjury(hA.getRandom());
return buryDamage.getDamage(injury, hA.getHuman());
}
/**
Get the amount of damage an agent should take as a result of being in a burning building.
@param b The building.
@param hA The HumanAttributes.
@return The amount of damage to add to the agent.
*/
public int getFireDamage(Building b, HumanAttributes hA) {
if (!b.isBuildingCodeDefined()) {
return 0;
}
BuildingClass clazz = getBuildingClass(b);
Injury injury = clazz.getFireInjury(hA.getRandom());
return fireDamage.getDamage(injury, hA.getHuman());
}
private void initBuildingData() {
buildingClasses = new EnumMap<BuildingCode, Map<BrokennessDegree, BuildingClass>>(BuildingCode.class);
for (BuildingCode code : BuildingCode.values()) {
Map<BrokennessDegree, BuildingClass> codeMap = new EnumMap<BrokennessDegree, BuildingClass>(BrokennessDegree.class);
for (BrokennessDegree degree : BrokennessDegree.values()) {
codeMap.put(degree, new BuildingClass(config, code, degree));
}
buildingClasses.put(code, codeMap);
}
}
private void initInjuryData() {
collapseDamage = new DamageType(config, "collapse");
buryDamage = new DamageType(config, "bury");
fireDamage = new DamageType(config, "fire");
}
private BuildingClass getBuildingClass(Building b) {
BuildingCode code = BuildingCode.values()[b.getBuildingCode()];
BrokennessDegree degree = BrokennessDegree.getBrokennessDegree(b);
return buildingClasses.get(code).get(degree);
}
private class BuildingClass {
private double buriedProbability;
private int initialBuriedness;
private Map<Injury, Double> collapseInjuryProbability;
private Map<Injury, Double> buryInjuryProbability;
private Map<Injury, Double> fireInjuryProbability;
public BuildingClass(Config config, BuildingCode code, BrokennessDegree degree) {
buriedProbability = config.getFloatValue("misc.buriedness." + code + "." + degree + ".rate");
initialBuriedness = config.getIntValue("misc.buriedness." + code + "." + degree + ".value");
collapseInjuryProbability = new EnumMap<Injury, Double>(Injury.class);
buryInjuryProbability = new EnumMap<Injury, Double>(Injury.class);
fireInjuryProbability = new EnumMap<Injury, Double>(Injury.class);
collapseInjuryProbability.put(Injury.SLIGHT, config.getFloatValue("misc.injury.collapse." + code + "." + degree + ".slight"));
collapseInjuryProbability.put(Injury.SERIOUS, config.getFloatValue("misc.injury.collapse." + code + "." + degree + ".serious"));
collapseInjuryProbability.put(Injury.CRITICAL, config.getFloatValue("misc.injury.collapse." + code + "." + degree + ".critical"));
buryInjuryProbability.put(Injury.SLIGHT, config.getFloatValue("misc.injury.bury." + code + "." + degree + ".slight"));
buryInjuryProbability.put(Injury.SERIOUS, config.getFloatValue("misc.injury.bury." + code + "." + degree + ".serious"));
buryInjuryProbability.put(Injury.CRITICAL, config.getFloatValue("misc.injury.bury." + code + "." + degree + ".critical"));
fireInjuryProbability.put(Injury.SLIGHT, config.getFloatValue("misc.injury.fire." + code + "." + degree + ".slight"));
fireInjuryProbability.put(Injury.SERIOUS, config.getFloatValue("misc.injury.fire." + code + "." + degree + ".serious"));
fireInjuryProbability.put(Injury.CRITICAL, config.getFloatValue("misc.injury.fire." + code + "." + degree + ".critical"));
}
public int getAgentBuriedness() {
return initialBuriedness ;//TODO Genrate Random;
}
public boolean shouldBury(HumanAttributes hA) {
return hA.getRandom().nextDouble() < buriedProbability;
}
public Injury getCollapseInjury(Random random) {
return getInjury(collapseInjuryProbability, random);
}
public Injury getBuryInjury(Random random) {
return getInjury(buryInjuryProbability, random);
}
public Injury getFireInjury(Random random) {
return getInjury(fireInjuryProbability, random);
}
private Injury getInjury(Map<Injury, Double> table, Random random) {
double d = random.nextDouble();
double d1 = table.get(Injury.SLIGHT);
double d2 = table.get(Injury.SERIOUS) + d1;
double d3 = table.get(Injury.CRITICAL) + d2;
if (d < d1) {
return Injury.SLIGHT;
}
if (d < d2) {
return Injury.SERIOUS;
}
if (d < d3) {
return Injury.CRITICAL;
}
return Injury.NONE;
}
}
private enum BuildingCode {
WOOD,
STEEL,
CONCRETE;
public String toString() {
return super.toString().toLowerCase();
}
}
private enum BrokennessDegree {
NONE(0, 0),
PARTIAL(1, 25),
HALF(26, 50),
ALL(51, 100);
private int min;
private int max;
private BrokennessDegree(int min, int max) {
this.min = min;
this.max = max;
}
@Override
public String toString() {
return super.toString().toLowerCase();
}
public static BrokennessDegree getBrokennessDegree(Building b) {
int brokenness = b.isBrokennessDefined() ? b.getBrokenness() : 0;
for (BrokennessDegree next : BrokennessDegree.values()) {
if (brokenness >= next.min && brokenness <= next.max) {
return next;
}
}
return BrokennessDegree.NONE;
}
}
private enum Injury {
NONE,
SLIGHT,
SERIOUS,
CRITICAL;
}
private static class DamageType {
private Map<Injury, Integer> damage;
private double ambulanceMultiplier;
private double policeMultiplier;
private double fireMultiplier;
public DamageType(Config config, String type) {
damage = new EnumMap<Injury, Integer>(Injury.class);
damage.put(Injury.NONE, 0);
damage.put(Injury.SLIGHT, config.getIntValue("misc.injury." + type + ".slight"));
damage.put(Injury.SERIOUS, config.getIntValue("misc.injury." + type + ".serious"));
damage.put(Injury.CRITICAL, config.getIntValue("misc.injury." + type + ".critical"));
ambulanceMultiplier = config.getFloatValue("misc.injury." + type + ".multiplier.ambulance");
policeMultiplier = config.getFloatValue("misc.injury." + type + ".multiplier.police");
fireMultiplier = config.getFloatValue("misc.injury." + type + ".multiplier.fire");
}
public int getDamage(Injury injury, Human agent) {
int result = damage.get(injury);
if (agent instanceof AmbulanceTeam) {
return (int)(result * ambulanceMultiplier);
}
if (agent instanceof PoliceForce) {
return (int)(result * policeMultiplier);
}
if (agent instanceof FireBrigade) {
return (int)(result * fireMultiplier);
}
return result;
}
}
}
package misc;
import java.util.ArrayList;
import java.util.Deque;
import java.util.Formatter;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Map;
import java.util.Set;
import javax.swing.JComponent;
import rescuecore2.GUIComponent;
import rescuecore2.log.Logger;
import rescuecore2.messages.Command;
import rescuecore2.messages.control.KSCommands;
import rescuecore2.messages.control.KSUpdate;
import rescuecore2.misc.geometry.GeometryTools2D;
import rescuecore2.misc.geometry.Point2D;
import rescuecore2.standard.components.StandardSimulator;
import rescuecore2.standard.entities.AmbulanceTeam;
import rescuecore2.standard.entities.Building;
import rescuecore2.standard.entities.Civilian;
import rescuecore2.standard.entities.FireBrigade;
import rescuecore2.standard.entities.GasStation;
import rescuecore2.standard.entities.Human;
import rescuecore2.standard.entities.PoliceForce;
import rescuecore2.standard.entities.Refuge;
import rescuecore2.standard.entities.StandardEntity;
import rescuecore2.standard.entities.StandardEntityURN;
import rescuecore2.standard.entities.StandardPropertyURN;
import rescuecore2.standard.messages.AKLoad;
import rescuecore2.standard.messages.AKRescue;
import rescuecore2.standard.messages.AKUnload;
import rescuecore2.worldmodel.ChangeSet;
import rescuecore2.worldmodel.Entity;
import rescuecore2.worldmodel.EntityID;
import rescuecore2.worldmodel.EntityListener;
import rescuecore2.worldmodel.Property;
/**
* Implementation of the legacy misc simulator.
*
* @author Maitreyi Nanjanath
* @author Cameron Skinner
*
* Implementation of Refuge Bed Capacity
* @author Farshid Faraji
*/
public class MiscSimulator extends StandardSimulator implements GUIComponent {
private Map<EntityID, HumanAttributes> humans;
private Set<EntityID> newlyBrokenBuildings;
private Map<EntityID, Integer> oldBrokenBuildingsBuriedness = new HashMap<>();
private MiscParameters parameters;
private MiscSimulatorGUI gui;
private int GAS_STATION_EXPLOSION_RANG;
private int GAS_STATION_Buriedness_Bound;
private int GAS_STATION_Buriedness_MIN;
private int GAS_STATION_Damage_Bound;
private int GAS_STATION_Damage_MIN;
private Set<EntityID> notExplosedGasStations;
private Map<EntityID, Deque<EntityID>> waitingList;
private Map<EntityID, Deque<EntityID>> beds;
@Override
public JComponent getGUIComponent() {
if (gui == null) {
gui = new MiscSimulatorGUI();
}
return gui;
}
@Override
public String getGUIComponentName() {
return "Misc simulator";
}
@Override
protected void postConnect() {
super.postConnect();
notExplosedGasStations = new HashSet<>();
waitingList = new HashMap<EntityID, Deque<EntityID>>();
beds = new HashMap<EntityID, Deque<EntityID>>();
parameters = new MiscParameters(config);
GAS_STATION_EXPLOSION_RANG = config.getIntValue("ignition.gas_station.explosion.range", 0);
GAS_STATION_Buriedness_Bound = config.getIntValue("misc.gas_station.Buriedness.bound", 30);
GAS_STATION_Buriedness_MIN = config.getIntValue("misc.gas_station.Buriedness.min", 0);
GAS_STATION_Damage_Bound = config.getIntValue("misc.gas_station.Damage.bound", 50);
GAS_STATION_Damage_MIN = config.getIntValue("misc.gas_station.Damage.min", 15);
humans = new HashMap<EntityID, HumanAttributes>();
newlyBrokenBuildings = new HashSet<EntityID>();
Logger.info("MiscSimulator connected. World has " + model.getAllEntities().size() + " entities.");
BuildingChangeListener buildingListener = new BuildingChangeListener();
// HumanChangeListener humanListener = new HumanChangeListener();
for (Entity et : model.getAllEntities()) {
if (et instanceof GasStation) {
notExplosedGasStations.add(et.getID());
}
if (et instanceof Refuge) {
Deque<EntityID> wlist = new LinkedList<EntityID>();
waitingList.put(et.getID(), wlist);
Deque<EntityID> blist = new LinkedList<EntityID>();
beds.put(et.getID(), blist);
}
if (et instanceof Building) {
et.addEntityListener(buildingListener);
} else if (et instanceof Human) {
// et.addEntityListener(humanListener);
Human human = (Human) et;
HumanAttributes ha = new HumanAttributes(human, config);
humans.put(ha.getID(), ha);
}
}
}
@Override
protected void processCommands(KSCommands c, ChangeSet changes) {
long start = System.currentTimeMillis();
int time = c.getTime();
Logger.info("Timestep " + time);
for (Command com : c.getCommands()) {
if (checkValidity(com)) {
if (com instanceof AKRescue) {
Human human = (Human) (model.getEntity(((AKRescue) com).getTarget()));
handleRescue(human, changes);
}
/*
* For the implementation of Refuge Bed Capacity
**/
if (com instanceof AKUnload) {
handleUnload(com, changes);
}
if (com instanceof AKLoad) {
handleLoad((AKLoad) com, changes);
}
} else {
Logger.debug("Ignoring " + com);
}
}
updateRefuges();
processBrokenBuildings(changes);
// processBurningBuildings( changes );
// processExplodedGasStations( changes );
updateDamage(changes);
updateChangeSet(changes);
// Clean up
newlyBrokenBuildings.clear();
writeDebugOutput(c.getTime());
if (gui != null) {
gui.refresh(humans.values());
}
long end = System.currentTimeMillis();
Logger.info("Timestep " + time + " took " + (end - start) + " ms");
}
private void processExplodedGasStations(ChangeSet changes) {
Logger.info("processExplodedGasStations for " + notExplosedGasStations);
for (Iterator<EntityID> iterator = notExplosedGasStations.iterator(); iterator.hasNext();) {
GasStation gasStation = (GasStation) model.getEntity(iterator.next());
if (gasStation.isFierynessDefined() && gasStation.getFieryness() == 1) {
for (HumanAttributes hA : humans.values()) {
Human human = hA.getHuman();
if (!human.isXDefined() || !human.isYDefined())
continue;
if (GeometryTools2D.getDistance(new Point2D(human.getX(), human.getY()),
new Point2D(gasStation.getX(), gasStation.getY())) < GAS_STATION_EXPLOSION_RANG) {
Logger.info(human + " getting damage from explosion..." + human);
int oldBuriedness = human.isBuriednessDefined() ? human.getBuriedness() : 0;
human.setBuriedness(
oldBuriedness + hA.getRandom().nextInt(GAS_STATION_Buriedness_Bound) + GAS_STATION_Buriedness_MIN);
changes.addChange(human, human.getBuriednessProperty());
// Check for injury from being exploded
int damage = hA.getRandom().nextInt(GAS_STATION_Damage_Bound) + GAS_STATION_Damage_MIN;
if (damage != 0) {
hA.addCollapseDamage(damage);
}
}
}
iterator.remove();
}
}
}
private void processBrokenBuildings(ChangeSet changes) {
for (HumanAttributes hA : humans.values()) {
Human human = hA.getHuman();
EntityID positionID = human.getPosition();
if (!newlyBrokenBuildings.contains(positionID)) {
continue;
}
// Human is in a newly collapsed building
// Check for buriedness
Logger.trace("Checking if human should be buried in broken building");
Building b = (Building) human.getPosition(model);
if (parameters.shouldBuryAgent(b, hA)) {
int buriedness = parameters.getBuriedness(b) - oldBrokenBuildingsBuriedness.get(b.getID());
if (buriedness != 0) {
int oldBuriedness = human.isBuriednessDefined() ? human.getBuriedness() : 0;
human.setBuriedness(oldBuriedness + buriedness);
changes.addChange(human, human.getBuriednessProperty());
// Check for injury from being buried
int damage = parameters.getBuryDamage(b, hA);
if (damage != 0) {
hA.addBuriednessDamage(damage);
}
}
}
// Now check for injury from the collapse
int damage = parameters.getCollapseDamage(b, hA);
if (damage != 0) {
hA.addCollapseDamage(damage);
}
}
}
private void processBurningBuildings(ChangeSet changes) {
for (HumanAttributes hA : humans.values()) {
Human human = hA.getHuman();
Entity position = human.getPosition(model);
if (position instanceof Building && ((Building) position).isOnFire()) {
// Human is in a burning building
int damage = parameters.getFireDamage((Building) position, hA);
if (damage != 0) {
hA.addFireDamage(damage);
}
}
}
}
private void writeDebugOutput(int time) {
StringBuilder builder = new StringBuilder();
Formatter format = new Formatter(builder);
format.format("Agents damaged or buried at timestep %1d%n", time);
format.format(" ID | HP | Damage | Bury | Collapse | Fire | Buriedness%n");
for (HumanAttributes ha : humans.values()) {
Human h = ha.getHuman();
int hp = h.isHPDefined() ? h.getHP() : 0;
int damage = ha.getTotalDamage();
int buriedness = h.isBuriednessDefined() ? h.getBuriedness() : 0;
boolean isAlive = hp > 0;
boolean hasDamage = damage > 0;
boolean isBuried = buriedness > 0;
if ((hasDamage || isBuried) && isAlive) {
format.format("%1$9d | %2$6d | %3$6d | %4$8.3f | %5$8.3f | %6$8.3f | %7$6d%n", ha.getID().getValue(), hp,
damage, ha.getBuriednessDamage(), ha.getCollapseDamage(), ha.getFireDamage(), buriedness);
}
}
format.close();
Logger.debug(builder.toString());
}
private void updateDamage(ChangeSet changes) {
for (HumanAttributes ha : humans.values()) {
Human h = ha.getHuman();
int oldDamage = ha.getTotalDamage();
if (h.isPositionDefined() && !(h.getPosition(model) instanceof Refuge)) {
updateDamage(ha);
int hp = h.isHPDefined() ? h.getHP() : 0;
int damage = ha.getTotalDamage();
h.setDamage(damage);
changes.addChange(ha.getHuman(), ha.getHuman().getDamageProperty());
// Update HP
boolean isAlive = hp > 0;
boolean hasDamage = damage > 0;
if (isAlive && hasDamage) {
int newHP = Math.max(0, hp - damage);
h.setHP(newHP);
changes.addChange(ha.getHuman(), ha.getHuman().getHPProperty());
}
}
/*
* For the implementation of Refuge Bed Capacity Damage increases and HP
* decreases while victim is in waiting list in Refuge While victim is on the
* bed, Damage is reducing but HP is fix human will not die while on the bed but
* it takes time to get damage to 0
*/
else if (h.isPositionDefined() && (h.getPosition(model) instanceof Refuge) && h.isHPDefined() && h.getHP() > 0) {
if (h instanceof FireBrigade || h instanceof AmbulanceTeam || h instanceof PoliceForce) {
ha.clearDamage();
h.setDamage(0);
changes.addChange(ha.getHuman(), ha.getHuman().getDamageProperty());
continue;
}
if (waitingList.get(h.getPosition()).size() > 0 && waitingList.get(h.getPosition()).contains(h.getID())) {
updateDamage(ha);
int hp = h.isHPDefined() ? h.getHP() : 0;
int damage = ha.getTotalDamage();
h.setDamage(damage);
changes.addChange(ha.getHuman(), ha.getHuman().getDamageProperty());
// Update HP
boolean isAlive = hp > 0;
boolean hasDamage = damage > 0;
if (isAlive && hasDamage) {
int newHP = Math.max(0, hp - damage);
h.setHP(newHP);
changes.addChange(ha.getHuman(), ha.getHuman().getHPProperty());
}
} else if (beds.get(h.getPosition()).size() > 0 && beds.get(h.getPosition()).contains(h.getID())) {
updateDamageInRefuge(ha);
h.setDamage(ha.getTotalDamage());
changes.addChange(ha.getHuman(), ha.getHuman().getDamageProperty());
if (oldDamage > 0 && h.getDamage() <= 0) {
if (beds.get(h.getPosition()).remove(h.getID())) {
((Refuge) h.getPosition(model)).decreaseOccupiedBeds();
}
if (waitingList.get(h.getPosition()).size() > 0) {
beds.get(h.getPosition()).add(waitingList.get(h.getPosition()).remove());
((Refuge) h.getPosition(model)).increaseOccupiedBeds();
}
}
}
}
}
}
private void updateDamage(HumanAttributes ha) {
Human h = ha.getHuman();
if (h.getHP() <= 0) {
return; // Agent is already dead.
}
ha.progressDamage();
}
/*
* For the implementation of Refuge Bed Capacity
**/
private void updateDamageInRefuge(HumanAttributes ha) {
Human h = ha.getHuman();
if (h.getHP() <= 0) {
return; // Agent is already dead.
}
ha.progressDamageInRefuge();
}
private boolean checkValidity(Command command) {
Entity e = model.getEntity(command.getAgentID());
if (e == null) {
Logger.warn("Received a " + command.getURN() + " command from an unknown agent: " + command.getAgentID());
return false;
}
if (command instanceof AKRescue) {
return checkRescue((AKRescue) command, e);
}
if (command instanceof AKUnload)
return checkUnload((AKUnload) command, e);
if (command instanceof AKLoad)
return checkLoad((AKLoad) command, e);
return false;
}
private boolean checkRescue(AKRescue rescue, Entity agent) {
EntityID targetID = rescue.getTarget();
Entity target = model.getEntity(targetID);
// || agent instanceof AmbulanceTeam
if (!(agent instanceof FireBrigade)) {
Logger.warn("Rejecting rescue command from agent " + agent.getID() + " who is of type " + agent.getURN());
return false;
}
if (target == null) {
Logger.warn("Rejecting rescue command from agent " + agent.getID() + " for a non-existent target " + targetID);
return false;
}
if (!(target instanceof Human)) {
Logger.warn("Rejecting rescue command from agent " + agent.getID() + " for a non-human target: " + targetID
+ " is of type " + target.getURN());
return false;
}
Human h = (Human) target;
if (!h.isBuriednessDefined() || h.getBuriedness() == 0) {
Logger.warn("Rejecting rescue command from agent " + agent.getID() + " for a non-buried target " + targetID);
return false;
}
// || agent instanceof AmbulanceTeam
if (agent instanceof FireBrigade) {
Human ag = (Human) agent;
if (ag.isHPDefined() && ag.getHP() <= 0) {
Logger.warn("Rejecting rescue command from agent " + agent.getID() + ": agent is dead");
return false;
}
if (ag.isBuriednessDefined() && ag.getBuriedness() > 0) {
Logger.warn("Rejecting rescue command from agent " + agent.getID() + ": agent is buried");
return false;
}
if (!h.isPositionDefined() || !ag.isPositionDefined() || !h.getPosition().equals(ag.getPosition())) {
Logger.warn("Rejecting rescue command from agent " + agent.getID() + " for a non-adjacent target " + targetID);
return false;
}
if (h.getID().equals(ag.getID())) {
Logger.warn("Rejecting rescue command from agent " + agent.getID() + ": tried to rescue self");
return false;
}
}
return true;
}
private boolean checkUnload(AKUnload unload, Entity agent) {
if (!(agent instanceof AmbulanceTeam)) {
Logger.warn("Rejecting unload command from agent " + agent.getID() + " who is of type " + agent.getURN());
return false;
}
AmbulanceTeam at = (AmbulanceTeam) agent;
if (at.isHPDefined() && at.getHP() <= 0) {
Logger.warn("Rejecting Unload command from agent " + agent.getID() + ": agent is dead");
return false;
}
return true;
}
private boolean checkLoad(AKLoad unload, Entity agent) {
if (!(agent instanceof AmbulanceTeam)) {
Logger.warn("Rejecting load command from agent " + agent.getID() + " who is of type " + agent.getURN());
return false;
}
AmbulanceTeam at = (AmbulanceTeam) agent;
if (at.isHPDefined() && at.getHP() <= 0) {
Logger.warn("Rejecting Unload command from agent " + agent.getID() + ": agent is dead");
return false;
}
return true;
}
private void handleRescue(Human target, ChangeSet changes) {
target.setBuriedness(Math.max(0, target.getBuriedness() - 1));
changes.addChange(target, target.getBuriednessProperty());
}
/*
* For the implementation of Refuge Bed Capacity
**/
private void handleUnload(Command command, ChangeSet changes) {
EntityID agentID = command.getAgentID();
Entity agent = model.getEntity(agentID);
Civilian target = null;
for (Entity e : model.getEntitiesOfType(StandardEntityURN.CIVILIAN)) {
Civilian civ = (Civilian) e;
if (civ.isPositionDefined() && agentID.equals(civ.getPosition())) {
target = civ;
break;
}
}
if (target != null) {
Entity AgentPosition = ((Human) agent).getPosition(model);
if (AgentPosition != null && AgentPosition instanceof Refuge) {
addVictimToWaitingList(AgentPosition, target);
}
}
}
private void handleLoad(AKLoad load, ChangeSet changes) {
EntityID agentID = load.getAgentID();
Entity agent = model.getEntity(agentID);
EntityID targetID = load.getTarget();
Entity target = model.getEntity(targetID);
// ---------------
if (agent == null) {
Logger.warn("Rejecting load command from agent " + agentID + ": agent does not exist");
return;
}
if (!(agent instanceof AmbulanceTeam)) {
Logger.warn("Rejecting load command from agent " + agentID + ": agent type is " + agent.getURN());
return;
}
if (target == null) {
Logger.warn("Rejecting load command from agent " + agentID + ": target does not exist " + targetID);
return;
}
AmbulanceTeam at = (AmbulanceTeam) agent;
Civilian h = (Civilian) target;
if (at.isHPDefined() && at.getHP() <= 0) {
Logger.warn("Rejecting load command from agent " + agentID + ": agent is dead");
return;
}
if (!h.isPositionDefined() || !at.isPositionDefined() || !h.getPosition().equals(at.getPosition())) {
Logger.warn("Rejecting load command from agent " + agentID + ": target is non-adjacent " + targetID);
return;
}
if (h.getID().equals(at.getID())) {
Logger.warn("Rejecting load command from agent " + agentID + ": tried to load self");
return;
}
// Is there something already loaded?
for (Entity e : model.getEntitiesOfType(StandardEntityURN.CIVILIAN)) {
Civilian c = (Civilian) e;
if (c.isPositionDefined() && agentID.equals(c.getPosition())) {
Logger.warn(
"Rejecting load command from agent " + agentID + ": agent already has civilian " + c.getID() + " loaded");
return;
}
}
// --------------------
Entity AgentPosition = ((Human) agent).getPosition(model);
if (AgentPosition != null && AgentPosition instanceof Refuge) {
if (waitingList.get(h.getPosition()).size() > 0 && waitingList.get(h.getPosition()).contains(h.getID())) {
waitingList.get(h.getPosition()).remove(h.getID());
}
if (beds.get(h.getPosition()).size() > 0 && beds.get(h.getPosition()).contains(h.getID())) {
beds.get(h.getPosition()).remove(h.getID());
((Refuge) h.getPosition(model)).decreaseOccupiedBeds();
if (waitingList.get(h.getPosition()).size() > 0) {
beds.get(h.getPosition()).add(waitingList.get(h.getPosition()).remove());
((Refuge) h.getPosition(model)).increaseOccupiedBeds();
}
}
}
}
private class BuildingChangeListener implements EntityListener {
@Override
public void propertyChanged(Entity e, Property p, Object oldValue, Object newValue) {
if (!(e instanceof Building)) {
return; // we want to only look at buildings
}
if (p.getURN() == (StandardPropertyURN.BROKENNESS.getURNId()))
checkBrokenness(e, oldValue, newValue);
}
private void checkBrokenness(Entity e, Object oldValue, Object newValue) {
double old = oldValue == null ? 0 : (Integer) oldValue;
double next = newValue == null ? 0 : (Integer) newValue;
if (next > old) {
newlyBrokenBuildings.add(e.getID());
}
}
}
@Override
protected void handleUpdate(KSUpdate u) {
for (StandardEntity entity : model) {
if (entity instanceof Building) {
oldBrokenBuildingsBuriedness.put(entity.getID(), parameters.getBuriedness((Building) entity));
}
}
super.handleUpdate(u);
}
private void addVictimToWaitingList(Entity refuge, Civilian victim) {
if (victim.getDamage() > 0)
waitingList.get(refuge.getID()).add(victim.getID());
}
/*
* For the implementation of Refuge Bed Capacity
**/
private void updateRefuges() {
for (Map.Entry<EntityID, Deque<EntityID>> e : waitingList.entrySet()) {
ArrayList<EntityID> tempList = new ArrayList<EntityID>();
for (EntityID civ : (Deque<EntityID>) e.getValue()) {
if (model.getEntity(civ) instanceof Human) {
if (((Human) model.getEntity(civ)).getDamage() <= 0) {
tempList.add(civ);
}
if (((Human) model.getEntity(civ)).getHP() <= 0) {
tempList.add(civ);
}
}
}
if (tempList.size() > 0) {
((Deque<EntityID>) e.getValue()).removeAll(tempList);
}
}
for (Map.Entry<EntityID, Deque<EntityID>> e : beds.entrySet()) {
ArrayList<EntityID> tempList = new ArrayList<EntityID>();
for (EntityID civ : (Deque<EntityID>) e.getValue()) {
if (model.getEntity(civ) instanceof Human) {
if (((Human) model.getEntity(civ)).getDamage() <= 0) {
tempList.add(civ);
}
if (((Human) model.getEntity(civ)).getHP() <= 0) {
tempList.add(civ);
}
}
}
if (tempList.size() > 0) {
// ( (Deque<EntityID>) e.getValue() ).removeAll( tempList );
for (EntityID id : tempList) {
if (((Deque<EntityID>) e.getValue()).remove(id)) {
((Refuge) model.getEntity(e.getKey())).decreaseOccupiedBeds();
Logger.warn("decreaseOccupiedBeds in update Refuge");
}
}
}
}
for (StandardEntity e : model.getEntitiesOfType(StandardEntityURN.REFUGE)) {
if (e instanceof Refuge) {
// Logger.warn("Refuge = " + e.getID() + " bed cap = " + ( (Refuge) e
// ).getOccupiedBeds() + " beds size = " + beds.get(e.getID()).size() + " wait
// size = " + waitingList.get(e.getID()).size());
while (((Refuge) e).getOccupiedBeds() < ((Refuge) e).getBedCapacity()) {
if (waitingList.get(e.getID()).size() > 0) {
beds.get(e.getID()).add(waitingList.get(e.getID()).remove());
((Refuge) e).increaseOccupiedBeds();
} else
break;
}
}
}
}
/*
* For the implementation of Refuge Bed Capacity
**/
private void updateChangeSet(ChangeSet changes) {
for (StandardEntity e : model.getEntitiesOfType(StandardEntityURN.REFUGE))
if (e instanceof Refuge) {
int size = waitingList.get(e.getID()).size();
((Refuge) e).setWaitingListSize(size);
changes.addChange((Refuge) e, ((Refuge) e).getOccupiedBedsProperty());
changes.addChange((Refuge) e, ((Refuge) e).getWaitingListSizeProperty());
}
}
}
\ No newline at end of file
package misc;
import javax.swing.JPanel;
import javax.swing.JTable;
import javax.swing.JScrollPane;
import javax.swing.table.AbstractTableModel;
import java.awt.BorderLayout;
import java.util.Collection;
/**
A GUI component for viewing the misc simulator state.
*/
public class MiscSimulatorGUI extends JPanel {
private static final int COLUMN_ID = 0;
private static final int COLUMN_HP = 1;
private static final int COLUMN_DAMAGE = 2;
private static final int COLUMN_BURY = 3;
private static final int COLUMN_COLLAPSE = 4;
private static final int COLUMN_FIRE = 5;
private static final int COLUMN_BURIEDNESS = 6;
private static final int COLUMNS = 7;
private MiscTableModel model;
/**
Create a MiscSimulatorGUI.
*/
public MiscSimulatorGUI() {
super(new BorderLayout());
model = new MiscTableModel();
add(new JScrollPane(new JTable(model)), BorderLayout.CENTER);
}
/**
Refresh the UI.
@param data The set of human data to show.
*/
public void refresh(Collection<HumanAttributes> data) {
model.setData(data.toArray(new HumanAttributes[data.size()]));
}
private static class MiscTableModel extends AbstractTableModel {
private HumanAttributes[] data;
void setData(HumanAttributes[] data) {
this.data = data;
fireTableDataChanged();
}
@Override
public int getRowCount() {
return data == null ? 0 : data.length;
}
@Override
public int getColumnCount() {
return COLUMNS;
}
@Override
public Object getValueAt(int row, int col) {
HumanAttributes att = data[row];
switch (col) {
case COLUMN_ID:
return att.getID();
case COLUMN_HP:
return att.getHuman().isHPDefined() ? String.valueOf(att.getHuman().getHP()) : "undefined";
case COLUMN_DAMAGE:
return att.getHuman().isDamageDefined() ? String.valueOf(att.getHuman().getDamage()) : "undefined";
case COLUMN_BURY:
return att.getBuriednessDamage();
case COLUMN_COLLAPSE:
return att.getCollapseDamage();
case COLUMN_FIRE:
return att.getFireDamage();
case COLUMN_BURIEDNESS:
return att.getHuman().isBuriednessDefined() ? String.valueOf(att.getHuman().getBuriedness()) : "undefined";
default:
throw new IllegalArgumentException("Unrecognised column: " + col);
}
}
@Override
public String getColumnName(int col) {
switch (col) {
case COLUMN_ID:
return "ID";
case COLUMN_HP:
return "HP";
case COLUMN_DAMAGE:
return "Total damage";
case COLUMN_BURY:
return "Buriedness damage";
case COLUMN_COLLAPSE:
return "Collapse damage";
case COLUMN_FIRE:
return "Fire damage";
case COLUMN_BURIEDNESS:
return "Buriedness";
default:
throw new IllegalArgumentException("Unrecognised column: " + col);
}
}
}
}
package firesimulator.kernel;
import firesimulator.simulator.Simulator;
/**
* @author tn
*
*/
public interface Kernel {
public void register(Simulator sim);
public void establishConnection();
public void signalReadyness();
public boolean waitForNextCycle();
public void sendUpdate();
public void receiveUpdate();
}
package firesimulator.simulator;
import java.util.Map;
import java.util.HashMap;
import firesimulator.world.World;
import firesimulator.world.Building;
import org.apache.log4j.Logger;
public class EnergyHistory {
private static final Logger LOG = Logger.getLogger(EnergyHistory.class);
private int time;
private Map<Building, Double> initialEnergy;
private Map<Building, Double> initialTemperature;
private Map<Building, Double> burnEnergy;
private Map<Building, Double> coolEnergy;
private Map<Building, Double> exchangedWithAir;
private Map<Building, Double> lostToRadiation;
private Map<Building, Double> gainedByRadiation;
private Map<Building, Double> finalEnergy;
private Map<Building, Double> finalTemperature;
public EnergyHistory(World world, int time) {
initialEnergy = new HashMap<Building, Double>();
initialTemperature = new HashMap<Building, Double>();
burnEnergy = new HashMap<Building, Double>();
coolEnergy = new HashMap<Building, Double>();
exchangedWithAir = new HashMap<Building, Double>();
lostToRadiation = new HashMap<Building, Double>();
gainedByRadiation = new HashMap<Building, Double>();
finalEnergy = new HashMap<Building, Double>();
finalTemperature = new HashMap<Building, Double>();
this.time = time;
for (Building next : world.getBuildings()) {
initialEnergy.put(next, next.getEnergy());
initialTemperature.put(next, next.getTemperature());
}
}
public void registerBurn(Building b, double energy) {
burnEnergy.put(b, energy);
}
public void registerCool(Building b, double energy) {
coolEnergy.put(b, energy);
}
public void registerAir(Building b, double energy) {
exchangedWithAir.put(b, energy);
}
public void registerRadiationLoss(Building b, double energy) {
lostToRadiation.put(b, energy);
}
public void registerRadiationGain(Building b, double energy) {
double old = gainedByRadiation.containsKey(b) ? gainedByRadiation.get(b) : 0;
gainedByRadiation.put(b, old + energy);
}
public void registerFinalEnergy(World world) {
for (Building next : world.getBuildings()) {
finalEnergy.put(next, next.getEnergy());
finalTemperature.put(next, next.getTemperature());
}
}
public void logSummary() {
LOG.debug("Energy summary at time " + time);
for (Building next : initialEnergy.keySet()) {
boolean changed = burnEnergy.containsKey(next) || coolEnergy.containsKey(next) || exchangedWithAir.containsKey(next) || lostToRadiation.containsKey(next) || gainedByRadiation.containsKey(next);
if (changed && !initialEnergy.get(next).equals(finalEnergy.get(next))) {
LOG.debug("Building " + next.getID());
LOG.debug(" Initial energy / temperature: " + initialEnergy.get(next) + " / " + initialTemperature.get(next));
LOG.debug(" Burn energy : " + burnEnergy.get(next));
LOG.debug(" Cool energy : " + coolEnergy.get(next));
LOG.debug(" Exchanged with air : " + exchangedWithAir.get(next));
LOG.debug(" Lost to radiation : " + lostToRadiation.get(next));
LOG.debug(" Gained by radiation : " + gainedByRadiation.get(next));
LOG.debug(" Final energy / temperature : " + finalEnergy.get(next) + " / " + finalTemperature.get(next));
}
}
}
}
\ No newline at end of file
package firesimulator.simulator;
import firesimulator.util.Configuration;
import firesimulator.world.Building;
import firesimulator.world.FireBrigade;
import org.apache.log4j.Logger;
/**
* @author tn
*
*/
public class ExtinguishRequest {
private static final Logger LOG = Logger.getLogger(ExtinguishRequest.class);
public static final int REASON_OK=1;
public static final int REASON_OK_VIRTUAL=2;
public static final int REASON_FB_WAS_NULL=-1;
public static final int REASON_TO_MUCH_WATER=-2;
public static final int REASON_TANK_EMPTY=-3;
public static final int REASON_OUT_OF_RANGE=-4;
public static final int REASON_NEGATIVE_WATER=-5;//Add by Ali Modaresi To fix using kernel bug
public static final String OK="passed all tests";
public static final String OK_VIRT="is virtual mode";
public static final String ER_FB_NULL="firebrigade is null";
public static final String ER_TO_MUCH="firebrigade is exceeding limt";
public static final String ER_EMPTY="tank is empty";
public static final String ER_RANGE="target is out of range";
public static final String ER_NEGATIVE_WATER="negative water request";//Add by Ali Modaresi To fix using kernel bug
public static final String UNKNOWN="unknown code ";
public static int MAX_WATER_PER_CYCLE;
public static int MAX_DISTANCE;
private FireBrigade source;
private Building target;
private int quantity;
private static boolean DEBUG_VERBOSE=true;
public ExtinguishRequest(FireBrigade source, Building target,int quantity){
this.target=target;
this.source=source;
this.quantity=quantity;
}
public void verbose(String msg){
if(DEBUG_VERBOSE)
LOG.debug(msg);
}
public int validate(){
if(source==null && Configuration.isActive("virtual"))return REASON_OK_VIRTUAL;
if(source==null)return REASON_FB_WAS_NULL;
if(source.getWaterUsed()+quantity>MAX_WATER_PER_CYCLE){
return REASON_TO_MUCH_WATER;
}
if(source.getWaterQuantity()<quantity){
return REASON_TANK_EMPTY;
}
if(distance(source,target)>MAX_DISTANCE)
return REASON_OUT_OF_RANGE;
if(quantity<0){//Added by Ali Modaresi to fix using kernel bug
LOG.warn("Using kernel bug.... Extinguish with negative water");//Added by Ali Modaresi to fix using kernel bug
return REASON_NEGATIVE_WATER;//Added by Ali Modaresi to fix using kernel bug
}
return REASON_OK;
}
public String getReason(int code){
switch (code) {
case REASON_OK:
return OK;
case REASON_OK_VIRTUAL:
return OK_VIRT;
case REASON_FB_WAS_NULL:
return ER_FB_NULL;
case REASON_OUT_OF_RANGE:
return ER_RANGE;
case REASON_TANK_EMPTY:
return ER_EMPTY;
case REASON_TO_MUCH_WATER:
return ER_TO_MUCH;
case REASON_NEGATIVE_WATER://Added by Ali Modaresi to fix using kernel bug
return ER_NEGATIVE_WATER;//Added by Ali Modaresi to fix using kernel bug
default:
return UNKNOWN+code;
}
}
private double distance(FireBrigade source2, Building target2) {
double x=source2.getX()-target2.getX();
double y=source2.getY()-target2.getY();
return Math.sqrt((x*x)+(y*y));
}
public boolean execute(){
verbose(toString());
int result;
if((result=validate())<0){
verbose("ERROR reason = "+getReason(result)+"\n");
return false;
}
if(source!=null){
source.addWaterUsed(quantity);
source.setWaterQuantity(source.getWaterQuantity()-quantity);
}
target.setWaterQuantity(target.getWaterQuantity()+quantity);
verbose("OK reason = "+getReason(result)+"\n");
return true;
}
public FireBrigade getSource() {
return source;
}
public String toString(){
String fb;
try{
fb="fb="+source.getID();
}catch (Exception e) {
fb="fb=null";
}
return "extinguish request; "+fb+", target="+target.getID()+", quantity="+quantity+" -> ";
}
}
package firesimulator.simulator;
import firesimulator.world.World;
public interface Monitor {
public void step(World world);
public void reset(World world);
public void done(World world);
}
package firesimulator.simulator;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import java.util.Map;
import java.util.HashMap;
import firesimulator.util.Configuration;
import firesimulator.util.Rnd;
import firesimulator.world.Building;
import firesimulator.world.FireBrigade;
import firesimulator.world.World;
import org.apache.log4j.Logger;
public class Simulator {
private static final Logger LOG = Logger.getLogger( Simulator.class );
private World world;
private WindShift windShift;
public static float GAMMA = 0.5f;
public static float AIR_TO_AIR_COEFFICIENT = 0.5f;
public static float AIR_TO_BUILDING_COEFFICIENT = 45f;
public static float WATER_COEFFICIENT = 0.5f;
public static float ENERGY_LOSS = 0.9f;
public static float WIND_DIRECTION = 0.9f;
public static float WIND_RANDOM = 0f;
public static int WIND_SPEED = 0;
public static float RADIATION_COEFFICENT = 1.0f;
public static float TIME_STEP_LENGTH = 1f;
public static float WEIGHT_GRID = 0.2f;
public static float AIR_CELL_HEAT_CAPACITY = 1f;
private Set monitors;
private static boolean verbose;
private static Simulator me;
private EnergyHistory energyHistory;
public Simulator( World world ) {
me = this;
monitors = new HashSet();
verbose = true;
this.world = world;
windShift = null;
}
public static Simulator getSimulator() {
return me;
}
public void addMonitor( Monitor monitor ) {
monitors.add( monitor );
}
public void removeMonitor( Monitor monitor ) {
monitors.remove( monitor );
}
private void informStep() {
for ( Iterator i = monitors.iterator(); i.hasNext(); ) {
((Monitor) i.next()).step( world );
}
}
private void informDone() {
for ( Iterator i = monitors.iterator(); i.hasNext(); ) {
((Monitor) i.next()).done( world );
}
}
private void informReset() {
for ( Iterator i = monitors.iterator(); i.hasNext(); ) {
((Monitor) i.next()).reset( world );
}
}
public void step( int timestep ) {
energyHistory = new EnergyHistory( world, timestep );
refill();
executeExtinguishRequests();
burn();
cool();
updateGrid();
exchangeBuilding();
// FIXED
cool();
energyHistory.registerFinalEnergy( world );
energyHistory.logSummary();
}
private void cool() {
for ( Iterator i = world.getBuildings().iterator(); i.hasNext(); ) {
Building b = (Building) i.next();
waterCooling( b );
}
}
private void refill() {
for ( Iterator i = world.getFirebrigades().iterator(); i.hasNext(); ) {
FireBrigade fb = ((FireBrigade) i.next());
if ( fb.refill() ) {
LOG.debug( "refilling fire brigade " + fb.getID() );
}
}
}
private void executeExtinguishRequests() {
for ( Iterator i = world.getExtinguishIterator(); i.hasNext(); ) {
ExtinguishRequest er = (ExtinguishRequest) i.next();
er.execute();
}
world.clearExtinguishRequests();
}
private void burn() {
for ( Building b : world.getBuildings() ) {
if ( b.getTemperature() >= b.getIgnitionPoint() && b.fuel > 0
&& b.isInflameable() ) {
float consumed = b.getConsum();
if ( consumed > b.fuel ) {
consumed = b.fuel;
}
double oldFuel = b.fuel;
double oldEnergy = b.getEnergy();
double oldTemp = b.getTemperature();
b.setEnergy( b.getEnergy() + consumed );
energyHistory.registerBurn( b, consumed );
b.fuel -= consumed;
b.setPrevBurned( consumed );
} else {
b.setPrevBurned( 0f );
}
}
}
private void waterCooling( Building b ) {
double lWATER_COEFFICIENT = (b.getFieryness() > 0 && b.getFieryness() < 4
? WATER_COEFFICIENT
: WATER_COEFFICIENT * GAMMA);
boolean cond = false;
if ( b.getWaterQuantity() > 0 ) {
double oldEnergy = b.getEnergy();
double oldTemp = b.getTemperature();
double oldWater = b.getWaterQuantity();
double dE = b.getTemperature() * b.getCapacity();
if ( dE <= 0 ) {
return;
}
double effect = b.getWaterQuantity() * lWATER_COEFFICIENT;
int consumed = b.getWaterQuantity();
if ( effect > dE ) {
cond = true;
double pc = 1 - ((effect - dE) / effect);
effect *= pc;
consumed *= pc;
}
b.setWaterQuantity( b.getWaterQuantity() - consumed );
b.setEnergy( b.getEnergy() - effect );
energyHistory.registerCool( b, effect );
LOG.debug( "Building " + b.getID() + " water cooling" );
LOG.debug( "Old energy: " + oldEnergy + ", old temperature: " + oldTemp
+ ", old water: " + oldWater );
LOG.debug( "Consumed " + consumed + " water: effect = " + effect );
LOG.debug( "New energy: " + b.getEnergy() + ", new temperature: "
+ b.getTemperature() + ", new water: " + b.getWaterQuantity() );
}
}
private void exchangeBuilding() {
for ( Iterator i = world.getBuildings().iterator(); i.hasNext(); ) {
Building b = (Building) i.next();
exchangeWithAir( b );
}
double sumdt = 0;
Map<Building, Double> radiation = new HashMap<Building, Double>();
for ( Iterator i = world.getBuildings().iterator(); i.hasNext(); ) {
Building b = (Building) i.next();
double radEn = b.getRadiationEnergy();
radiation.put( b, radEn );
}
for ( Iterator i = world.getBuildings().iterator(); i.hasNext(); ) {
Building b = (Building) i.next();
double radEn = radiation.get( b );
Building[] bs = b.connectedBuilding;
float[] vs = b.connectedValues;
for ( int c = 0; c < vs.length; c++ ) {
double oldEnergy = bs[c].getEnergy();
double connectionValue = vs[c];
double a = radEn * connectionValue;
double sum = oldEnergy + a;
bs[c].setEnergy( sum );
energyHistory.registerRadiationGain( bs[c], a );
}
b.setEnergy( b.getEnergy() - radEn );
energyHistory.registerRadiationLoss( b, -radEn );
}
}
private void exchangeWithAir( Building b ) {
// Give/take heat to/from air cells
double oldTemperature = b.getTemperature();
double oldEnergy = b.getEnergy();
double energyDelta = 0;
for ( int[] nextCell : b.cells ) {
int cellX = nextCell[0];
int cellY = nextCell[1];
double cellCover = nextCell[2] / 100.0;
double cellTemp = world.getAirCellTemp( cellX, cellY );
double dT = cellTemp - b.getTemperature();
double energyTransferToBuilding = dT * AIR_TO_BUILDING_COEFFICIENT
* TIME_STEP_LENGTH * cellCover * world.SAMPLE_SIZE;
energyDelta += energyTransferToBuilding;
double newCellTemp = cellTemp - energyTransferToBuilding
/ (AIR_CELL_HEAT_CAPACITY * world.SAMPLE_SIZE);
world.setAirCellTemp( cellX, cellY, newCellTemp );
}
b.setEnergy( oldEnergy + energyDelta );
energyHistory.registerAir( b, energyDelta );
}
private void updateGrid() {
LOG.debug( "Updating air grid" );
double[][] airtemp = world.getAirTemp();
double[][] newairtemp = new double[airtemp.length][airtemp[0].length];
for ( int x = 0; x < airtemp.length; x++ ) {
for ( int y = 0; y < airtemp[0].length; y++ ) {
double dt = (averageTemp( x, y ) - airtemp[x][y]);
double change = (dt * AIR_TO_AIR_COEFFICIENT * TIME_STEP_LENGTH);
newairtemp[x][y] = relTemp( airtemp[x][y] + change );
if ( !(newairtemp[x][y] > -Double.MAX_VALUE
&& newairtemp[x][y] < Double.MAX_VALUE) ) {
LOG.warn( "Value is not sensible: " + newairtemp[x][y] );
newairtemp[x][y] = Double.MAX_VALUE * 0.75;
}
if ( newairtemp[x][y] == Double.NEGATIVE_INFINITY
|| newairtemp[x][y] == Double.POSITIVE_INFINITY ) {
LOG.warn( "aha" );
}
}
}
world.setAirTemp( newairtemp );
// Disable on October 21, 2018 because the wind direction and speed was not
// correctly implemented.
// world.setAirTemp( getWindShift().shift( world.getAirTemp(), this ) );
}
private double relTemp( double deltaT ) {
return Math.max( 0, deltaT * ENERGY_LOSS * TIME_STEP_LENGTH );
}
private double averageTemp( int x, int y ) {
double rv = neighbourCellAverage( x, y ) / weightSummCells( x, y );
return rv;
}
private double neighbourCellAverage( int x, int y ) {
double total = getTempAt( x + 1, y - 1 );
total += getTempAt( x + 1, y );
total += getTempAt( x + 1, y + 1 );
total += getTempAt( x, y - 1 );
total += getTempAt( x, y + 1 );
total += getTempAt( x - 1, y - 1 );
total += getTempAt( x - 1, y );
total += getTempAt( x - 1, y + 1 );
return total * WEIGHT_GRID;
}
private float weightSummCells( int x, int y ) {
return 8 * WEIGHT_GRID;
}
protected double getTempAt( int x, int y ) {
if ( x < 0 || y < 0 || x >= world.getAirTemp().length
|| y >= world.getAirTemp()[0].length )
return 0;
return world.getAirTemp()[x][y];
}
public void setWind( float direction, float speed ) {
windShift = new WindShift( direction, speed, world.SAMPLE_SIZE );
}
public WindShift getWindShift() {
if ( WIND_RANDOM > 0 && windShift != null ) {
float nd = (float) (windShift.direction
+ windShift.direction * WIND_RANDOM * Rnd.get01());
float ns = (float) (windShift.speed
+ windShift.speed * WIND_RANDOM * Rnd.get01());
setWind( nd, ns );
}
if ( windShift == null || windShift.direction != WIND_DIRECTION
|| windShift.speed != WIND_SPEED )
setWind( WIND_DIRECTION, WIND_SPEED );
return windShift;
}
private void loadVars() {
AIR_TO_BUILDING_COEFFICIENT = Float.parseFloat(
Configuration.getValue( "resq-fire.air_to_building_flow" ) );
AIR_TO_AIR_COEFFICIENT = Float
.parseFloat( Configuration.getValue( "resq-fire.air_to_air_flow" ) );
ENERGY_LOSS = Float
.parseFloat( Configuration.getValue( "resq-fire.energy_loss" ) );
WATER_COEFFICIENT = Float.parseFloat(
Configuration.getValue( "resq-fire.water_thermal_capacity" ) );
// Disable on October 21, 2018 because the wind direction and speed was not
// correctly implemented.
// WIND_SPEED = Integer
// .parseInt( Configuration.getValue( "resq-fire.wind_speed" ) );
// WIND_DIRECTION = Float
// .parseFloat( Configuration.getValue( "resq-fire.wind_direction" ) );
// WIND_RANDOM = Float
// .parseFloat( Configuration.getValue( "resq-fire.wind_random" ) );
RADIATION_COEFFICENT = Float.parseFloat(
Configuration.getValue( "resq-fire.radiation_coefficient" ) );
AIR_CELL_HEAT_CAPACITY = Float.parseFloat(
Configuration.getValue( "resq-fire.air_cell_heat_capacity" ) );
ExtinguishRequest.MAX_WATER_PER_CYCLE = Integer.parseInt(
Configuration.getValue( "resq-fire.max_extinguish_power_sum" ) );
ExtinguishRequest.MAX_DISTANCE = Integer
.parseInt( Configuration.getValue( "resq-fire.water_distance" ) );
GAMMA = Float.parseFloat( Configuration.getValue( "resq-fire.gamma" ) );
Rnd.setSeed( Long.parseLong( Configuration.getValue( "random.seed" ) ) );
}
public void initialize() {
try {
loadVars();
} catch ( Exception e ) {
LOG.fatal( "invalid configuration, aborting", e );
System.exit( -1 );
}
world.initialize();
}
public void reset() {
loadVars();
world.reset();
informReset();
}
}
\ No newline at end of file
package firesimulator.simulator;
/**
* @author Timo N�ssle
*
*/
public class WindShift {
float speed;
float direction;
float directionDg;
int[][] grid = new int[4][2];
float[] weights = new float[4];
public WindShift( float direction, float speed, int gridSize ) {
this.speed = speed % gridSize;
directionDg = direction;
direction = direction % 360;
direction = (float) (direction / (360 / (2 * Math.PI)));
this.direction = direction;
float v_y = -((float) Math.cos( direction ) * speed);
float v_x = -((float) Math.sin( direction ) * speed);
float[][] points = new float[4][2];
points[0][0] = v_x;
points[0][1] = v_y;
points[1][0] = v_x + gridSize;
points[1][1] = v_y;
points[2][0] = v_x + gridSize;
points[2][1] = v_y + gridSize;
points[3][0] = v_x;
points[3][1] = v_y + gridSize;
float areaTotal = gridSize * gridSize;
for ( int c = 0; c < 4; c++ ) {
float tx = grid[c][0] * gridSize;
float ty = grid[c][1] * gridSize;
float sx = points[0][0];
float sy = points[0][1];
float dx = gridSize - Math.abs( sx - tx );
float dy = gridSize - Math.abs( sy - ty );
float weight = (dx * dy) / areaTotal;
weights[c] = weight;
}
}
public float getDirection() {
return directionDg;
}
public double[][] shift( double[][] source, Simulator sim ) {
if ( speed == 0 )
return source;
double[][] result = new double[source.length][source[0].length];
for ( int x = 0; x < source.length; x++ )
for ( int y = 0; y < source[0].length; y++ ) {
float temp = 0;
for ( int c = 0; c < 4; c++ ) {
temp += sim.getTempAt( x - grid[c][0], y - grid[c][1] ) * weights[c];
System.out.println( weights[c] );
}
result[x][y] = temp;
}
return result;
}
}
\ No newline at end of file
package firesimulator.util;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.LinkedList;
import java.util.ArrayList;
import java.util.Properties;
import java.util.StringTokenizer;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import firesimulator.world.Wall;
import org.apache.log4j.Logger;
public class Configuration {
private static final Logger LOG = Logger.getLogger(Configuration.class);
private static final String PREFIX = "resq-fire.";
public class Prop{
private String name;
private String command;
private String description;
private String paramName;
private boolean paramReq;
private String value;
boolean active;
public Prop(String name, String command, String description , String paramName, boolean paramReq,String def){
this.name=name;
this.command=command;
this.description=description;
this.paramName=paramName;
this.paramReq=paramReq;
if(def!=null){
value=def;
active=true;
}else{
value=null;
active=false;
}
}
public String getValue(){
return value;
}
public boolean isActive(){
return active;
}
public boolean validate(){
if(paramReq)
if(value==null||value.length()==0)return false;
return true;
}
public String getDescription(){
if(description==null)return "";
return "\n"+name+": "+command+" "+(paramName!=null?(!paramReq?"[":"")+"<"+paramName+">"+(!paramReq?"]":""):"")+"\n"+description+"\n";
}
}
private static LinkedList Props =new LinkedList();
private static final String CONFIG_TXT_PATH=".";
public static String VERSION="06.08.2005";
public void initialize(){
Props.add(new Prop(PREFIX + "store","s","Stores the intial data from the kernel in the given file.","filename",true,null));
Props.add(new Prop(PREFIX + "virtual","v","Use the virtual kernel instead of the rescue kernel.\nRequires a .scn file.","filename",true,null));
Props.add(new Prop(PREFIX + "host","h","The host to connect to. Default host is localhost.","host",true,"localhost"));
Props.add(new Prop(PREFIX + "port","p","The port to connect to. Default port is 6000","port",true,"6000"));
Props.add(new Prop(PREFIX + "setup","stp","Uses the given setup file","filename",true,null));
Props.add(new Prop(PREFIX + "csetup","cstp","Uses the given config.txt file","filename",true,null));
Props.add(new Prop(PREFIX + "ray_rate","ray_rate","Number of emitted rays per mm while sampling. Default rate is "+Wall.RAY_RATE,"rate",true,Wall.RAY_RATE+""));
Props.add(new Prop(PREFIX + "help","help","Prints this text and exits",null,false,null));
//hidden parameters
Props.add(new Prop(PREFIX + "cell_size","cell_size",null,null,true,null));
Props.add(new Prop(PREFIX + "max_ray_distance","max_ray_distance",null,null,true,null));
Props.add(new Prop(PREFIX + "energy_loss","energy_loss",null,null,true,null));
Props.add(new Prop(PREFIX + "air_to_air_flow","air_to_air_flow",null,null,true,null));
Props.add(new Prop(PREFIX + "air_to_building_flow","air_to_building_flow",null,null,true,null));
Props.add(new Prop(PREFIX + "air_cell_heat_capacity","air_cell_heat_capacity",null,null,true,null));
Props.add(new Prop(PREFIX + "wooden_capacity","wooden_capacity",null,null,true,null));
Props.add(new Prop(PREFIX + "wooden_energy","wooden_energy",null,null,true,null));
Props.add(new Prop(PREFIX + "wooden_ignition","wooden_ignition",null,null,true,null));
Props.add(new Prop(PREFIX + "wooden_burning","wooden_burning",null,null,true,null));
Props.add(new Prop(PREFIX + "wooden_speed","wooden_speed",null,null,true,null));
Props.add(new Prop(PREFIX + "steel_capacity","steel_capacity",null,null,true,null));
Props.add(new Prop(PREFIX + "steel_energy","steel_energy",null,null,true,null));
Props.add(new Prop(PREFIX + "steel_ignition","steel_ignition",null,null,true,null));
Props.add(new Prop(PREFIX + "steel_burning","steel_burning",null,null,true,null));
Props.add(new Prop(PREFIX + "steel_speed","steel_speed",null,null,true,null));
Props.add(new Prop(PREFIX + "concrete_capacity","concrete_capacity",null,null,true,null));
Props.add(new Prop(PREFIX + "concrete_energy","concrete_energy",null,null,true,null));
Props.add(new Prop(PREFIX + "concrete_ignition","concrete_ignition",null,null,true,null));
Props.add(new Prop(PREFIX + "concrete_burning","concrete_burning",null,null,true,null));
Props.add(new Prop(PREFIX + "concrete_speed","concrete_speed",null,null,true,null));
Props.add(new Prop(PREFIX + "max_extinguish_power_sum","max_extinguish_power_sum",null,null,true,null));
Props.add(new Prop(PREFIX + "water_refill_rate","water_refill_rate",null,null,true,null));
Props.add(new Prop(PREFIX + "water_hydrant_refill_rate","water_hydrant_refill_rate",null,null,true,null));
Props.add(new Prop(PREFIX + "water_capacity","water_capacity",null,null,true,null));
Props.add(new Prop(PREFIX + "water_thermal_capacity","water_thermal_capacity",null,null,true,null));
Props.add(new Prop(PREFIX + "water_distance","water_distance",null,null,true,null));
Props.add(new Prop(PREFIX + "radiation_coefficient","radiation_coefficient",null,null,true,null));
Props.add(new Prop(PREFIX + "wind_speed","wind_speed",null,null,true,null));
Props.add(new Prop(PREFIX + "wind_direction","wind_direction",null,null,true,null));
Props.add(new Prop(PREFIX + "wind_random","wind_random",null,null,true,null));
Props.add(new Prop(PREFIX + "randomseed","randomseed",null,null,true,null));
Props.add(new Prop("random.seed","random.seed",null,null,true,null));
Props.add(new Prop(PREFIX + "refuge_inflammable","refuge_inflammable",null,null,true,null));
Props.add(new Prop(PREFIX + "fire_station_inflammable","firestation_inflammable",null,null,true,null));
Props.add(new Prop(PREFIX + "police_office_inflammable","policeoffice_inflammable",null,null,true,null));
Props.add(new Prop(PREFIX + "ambulance_center_inflammable","ambulancecenter_inflammable",null,null,true,null));
Props.add(new Prop(PREFIX + "gamma","gamma",null,null,true,null));
Props.add(new Prop(PREFIX + "rays.dir","rays",null,null,true,"rays"));
Props.add(new Prop(PREFIX + "burn-rate-average","burn-rate-average",null,null,true,"0.2"));
Props.add(new Prop(PREFIX + "burn-rate-variance","burn-rate-variance",null,null,true,"0"));
}
public void parse(String cmdLine){
StringTokenizer st=new StringTokenizer(cmdLine,"-");
try{
while(st.hasMoreTokens()){
String tok=st.nextToken();
int index=tok.indexOf(" ");
String cmd;
if(index==-1){
cmd=tok.trim();
if(cmd.length()==0)continue;
Prop p =propForCmd(cmd);
p.active=true;
}else{
cmd=tok.substring(0,index).trim();
if(cmd.length()==0)continue;
Prop p =propForCmd(cmd);
p.active=true;
p.value=tok.substring(index).trim();
}
}
}catch(Exception e){printHelpAndExit();}
if(isActive("help")){
printHelpAndExit();
}
}
private void printHelpAndExit(){
System.out.println("ResQ Firesimulator");
System.out.println(VERSION);
System.out.println("author: Timo N�ssle\nemail: nuessle@informatik.uni-freiburg.de\n");
System.out.println("java Main [-<option> <value>]*");
for(Iterator i=Props.iterator();i.hasNext();)
System.out.print(((Prop)i.next()).getDescription());
System.exit(0);
}
private static Configuration.Prop propForCmd(String cmd){
for(Iterator i=Props.iterator();i.hasNext();){
Prop p=(Prop)i.next();
if(p.command.compareTo(cmd)==0)return p;
}
return null;
}
public static boolean isActive(String name){
for(Iterator i=Props.iterator();i.hasNext();){
Prop p=(Prop)i.next();
if(p.name.compareTo(name)==0) return p.isActive();
}
return false;
}
public static String getValue(String name){
for(Iterator i=Props.iterator();i.hasNext();){
Prop p=(Prop)i.next();
if(p.name.compareTo(name)==0) return p.getValue();
}
return null;
}
public void parse(String[] args) {
if(args.length<1)return;
String s="";
for(int i=0;i<args.length;s+=" "+args[i],i++);
parse(s);
}
public static boolean loadSetup(String fileName) {
try {
FileInputStream fis=new FileInputStream(new File(fileName));
Properties prop=new Properties();
prop.load(fis);
fis.close();
for(Iterator i=Props.iterator();i.hasNext();){
Prop p=(Prop)i.next();
String val=prop.getProperty(p.command);
if(val!=null){
p.value=val;
p.active=true;
}
}
} catch (Exception e) {
return false;
}
return true;
}
public static void loadConfigTXT(String filename) {
String fname=CONFIG_TXT_PATH+File.separator+"config.txt";
if(filename!=null)
fname=filename;
LOG.info("loading values from \""+fname+"\"");
try{
Pattern comment=Pattern.compile("([^#]*)(#(.*))*",Pattern.DOTALL);
Pattern keyValue=Pattern.compile("([^:]*):(.*)",Pattern.DOTALL);
BufferedReader br=new BufferedReader(new FileReader(fname));
Hashtable lines=new Hashtable();
String line;
String key;
String value;
while((line=br.readLine())!=null){
line=line.trim();
Matcher m=comment.matcher(line);
if(m.matches()){
Matcher gm=keyValue.matcher(m.group(1));
if(gm.matches()&&gm.groupCount()==2){
key=gm.group(1).trim();
value=gm.group(2).trim();
lines.put(key,value);
}
}
}
for(Iterator i=Props.iterator();i.hasNext();){
Prop p=(Prop)i.next();
String name=p.name;
value=(String) lines.get(name);
if(value!=null){
p.active=true;
p.value=value;
}
}
}catch (Exception e) {
LOG.error("unable to load \""+fname+"\"", e);
}
}
public static void setProperty(String name, String value, boolean state){
for(Iterator i=Props.iterator();i.hasNext();){
Prop p=(Prop)i.next();
if(p.name.compareTo(name)==0){
p.value=value;
p.active=state;
break;
}
}
}
public static List<String> getPropertyNames() {
List<String> result = new ArrayList<String>();
for(Iterator i = Props.iterator(); i.hasNext();){
Prop next = (Prop)i.next();
result.add(next.name);
}
return result;
}
public static void dump(){
for(Iterator i=Props.iterator();i.hasNext();){
Prop p=(Prop)i.next();
LOG.debug(p.command+"="+p.value+ "["+p.active+"]");
}
}
public static void storeHiddenProps(String fileName) throws IOException {
Properties prop= new Properties();
for(Iterator i=Props.iterator();i.hasNext();){
Prop p=(Prop)i.next();
if(p.description==null){
if(p.value==null) {
LOG.debug(p.command);
}
prop.put(p.command,p.value);
}
}
if(!fileName.endsWith(".stp"))fileName+=".stp";
File f=new File(fileName);
if(f.exists())f.delete();
f.createNewFile();
FileOutputStream fos=new FileOutputStream(f);
prop.store(fos,"fire simulator setup file");
fos.close();
}
}
package firesimulator.util;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.JFrame;
import javax.swing.WindowConstants;
/**
* @author tn
*
*/
public class GeoTest extends JFrame implements MouseListener{
private static final long serialVersionUID = 1L;
float p[];
float[] cross;
int current=0;
Point c;
Point d;
public static void main(String[] args) {
GeoTest gt=new GeoTest();
gt.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
gt.setVisible(true);
}
public GeoTest(){
super("geotest");
p=new float[]{50f,50f,300f,300f,100f,100f,200f,200f};
addMouseListener(this);
setSize(500,500);
cross=null;
}
public void update(Graphics g){
g.setColor(Color.BLACK);
g.fillRect(0,0,getWidth(),getHeight());
g.setColor(Color.RED);
g.drawLine((int)p[0],(int)p[1],(int)p[2],(int)p[3]);
g.setColor(Color.GREEN);
g.drawLine((int)p[4],(int)p[5],(int)p[6],(int)p[7]);
if(d!=null&&c!=null){
g.setColor(Color.YELLOW);
g.drawLine(c.x,c.y,d.x,d.y);
}
if(cross!=null){
g.setColor(Color.CYAN);
g.drawLine((int)cross[0]-10,(int)cross[1]-10,(int)cross[0]+10,(int)cross[1]+10);
g.drawLine((int)cross[0]-10,(int)cross[1]+10,(int)cross[0]+10,(int)cross[1]-10);
}
if(c!=null){
g.setColor(Color.YELLOW);
g.drawOval(c.x-5,c.y-5,10,10);
}
}
public void mouseClicked(MouseEvent e) {
if(e.getButton()==MouseEvent.BUTTON1){
if(current>7)current=0;
p[current]=(float)e.getX();
p[++current]=(float)e.getY();
if(e.isControlDown()) p[current-1]=200f;
if(e.isShiftDown()) p[current-1]=400f;
current++;
}
findPoint();
d=Geometry.getRndPoint(c,100d);
findIntersect();
update(getGraphics());
}
private void findPoint() {
Point a=new Point((int)p[0],(int)p[1]);
Point b=new Point((int)p[2],(int)p[3]);
c=Geometry.getRndPoint(a,b);
}
private void findIntersect() {
cross=Geometry.intersect(p);
}
public void mousePressed(MouseEvent e) {
}
public void mouseReleased(MouseEvent e) {
}
public void mouseEntered(MouseEvent e) {
}
public void mouseExited(MouseEvent e) {
}
}
package firesimulator.util;
import java.awt.Point;
import java.awt.Polygon;
import java.awt.Rectangle;
import java.awt.geom.Point2D;
import firesimulator.world.StationaryObject;
/**
* @author tn
*
*/
public class Geometry {
private static Rectangle rect=new Rectangle(0,0,0,0);
public static int percent(float x1,float y1, float width, float height,Polygon p){
int counter=0;
double dx=width/10;
double dy=height/10;
for(int i=0;i<10;i++)
for(int j=0;j<10;j++){
if(p.contains(dx*i+x1,dy*j+y1))counter++;
}
return counter;
}
public static boolean boundingTest(Polygon p,int x,int y,int w,int h){
rect.setBounds(x,y,w,h);
return p.intersects(rect);
}
public static Point intersect(Point a, Point b, Point c, Point d){
float[] rv=intersect(new float[]{a.x,a.y,b.x,b.y,c.x,c.y,d.x,d.y});
if(rv==null)return null;
return new Point((int)rv[0],(int)rv[1]);
}
public static float[] intersect(float[] points){
float dx1 = points[2] - points[0];
float dy1 = points[3] - points[1];
float dx2 = points[6] - points[4];
float dy2 = points[7] - points[5];
float s = (dx1 * (points[1] - points[5]) - dy1 * (points[0] - points[4])) / (dx1 * dy2 - dx2 * dy1);
float t = (dx2 * (points[1] - points[5]) - dy2 * (points[0] - points[4])) / (dx1 * dy2 - dx2 * dy1);
if (s >= 0 && s <= 1 && t >= 0 && t <= 1) {
return new float[] {points[0] + (t * dx1), points[1] + (t * dy1)};
}
return null;
}
public static float[] getAffineFunction(float x1,float y1,float x2,float y2){
if(x1==x2)return null;
float m=(y1-y2)/(x1-x2);
float b=y1-m*x1;
return new float[]{m,b};
}
public static float getLength(Point2D a, Point2D b){
a.distance(b);
return 0;
}
public static boolean inBounds(float bx1,float by1,float bx2, float by2, float x, float y){
if(bx1<bx2){
if(x<bx1||x>bx2)return false;
}else{
if(x>bx1||x<bx2)return false;
}
if(by1<by2){
if(y<by1||y>by2)return false;
}else{
if(y>by1||y<by2)return false;
}
return true;
}
/**
* Returns a random point on a line
* @param a One point defineing the line
* @param b The other point defineing the line
* @return A point between a and b
*/
public static Point getRndPoint(Point a, Point b){
float[] mb=Geometry.getAffineFunction((float)a.x,(float)a.y,(float)b.x,(float)b.y);
float dx=(Math.max((float)a.x,(float)b.x)-Math.min((float)a.x,(float)b.x));
dx*=Rnd.get01();
dx+=Math.min((float)a.x,(float)b.x);
if(mb==null){
//vertical line
int p = Math.max(a.y,b.y)-Math.min(a.y,b.y);
p = (int) (p*Rnd.get01());
p = p + Math.min(a.y,b.y);
return new Point(a.x,p);
}
float y=mb[0]*dx+mb[1];
Point rtv=new Point((int)dx,(int)y);
if(rtv == null){
System.currentTimeMillis();
}
return rtv;
}
public static Point getRndPoint(Point a, double length){
double angel=Rnd.get01()*2d*Math.PI;
double x=Math.sin(angel)*length;
double y=Math.cos(angel)*length;
return new Point((int)x+a.x,(int)y+a.y);
}
public static int dist(StationaryObject o1, StationaryObject o2){
double x = o1.getX()-o2.getX();
double y = o1.getY()-o2.getY();
return (int )Math.sqrt(Math.pow(x,2)+Math.pow(y,2));
}
}
package firesimulator.util;
import java.util.Random;
/**
* @author tn
*
*/
public class Rnd {
private static Random rnd;
public static void setSeed( long seed ) {
if ( seed <= 0 )
rnd = new Random( System.currentTimeMillis() );
else
rnd = new Random( seed );
}
public static double get01() {
if ( rnd == null ) {
rnd = new Random();
}
return rnd.nextDouble();
}
}
\ No newline at end of file
package firesimulator.util;
import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JFrame;
import javax.swing.WindowConstants;
/**
* @author tn
*
*/
public class TempView extends JFrame{
/**
*
*/
private static final long serialVersionUID = 1L;
static float[][] keyColors={{1000,1,0,0},
{300,1,1,0},
{100,0,1,0},
{50,0,0,1},
{20,0,0,0.8f},
{0,0,0,0}};
public static void main(String[] args) {
TempView gt=new TempView();
gt.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
gt.setVisible(true);
}
public void update(Graphics g){
g.setColor(Color.WHITE);
g.fillRect(0,0,getWidth(),getHeight());
for(int x=0;x<=200;x++){
Color c=interpolator(x*5,keyColors);
g.setColor(c);
g.drawLine(50,250-x,100,250-x);
}
g.setColor(Color.BLACK);
for(int x=0;x<=200;x+=40){
g.drawLine(105,250-x,110,250-x);
g.drawString(""+x*5+"�C",115,255-x);
}
}
private Color interpolator(float temp,float[][]keys){
float[][] keyColors=keys;
int pos=0;
do{
pos++;
}while(keyColors[pos][0]>temp&&pos<keyColors.length);
if(pos>=keyColors.length)
return Color.BLUE;
float pc=(temp-keyColors[pos][0])/(keyColors[pos-1][0]-keyColors[pos][0]);
float red=(keyColors[pos-1][1]-keyColors[pos][1])*pc+keyColors[pos][1];
float green=(keyColors[pos-1][2]-keyColors[pos][2])*pc+keyColors[pos][2];
float blue=(keyColors[pos-1][3]-keyColors[pos][3])*pc+keyColors[pos][3];
return new Color(red,green,blue);
}
}
package firesimulator.world;
/**
* @author tn
*
* To change the template for this generated type comment go to
* Window>Preferences>Java>Code Generation>Code and Comments
*/
public class AmbulanceCenter extends Building {
/**
* @param id
*/
public AmbulanceCenter(int id) {
super(id);
}
public String getType(){
return "AMBULANCE_CENTRE";
}
public boolean isInflameable(){
return Building.AMBULANCE_INFALMEABLE;
}
public int getFieryness(){
if(isInflameable())
return super.getFieryness();
return 0;
}
}
package firesimulator.world;
/**
* @author tn
*
* To change the template for this generated type comment go to
* Window>Preferences>Java>Code Generation>Code and Comments
*/
public class AmbulanceTeam extends MovingObject {
public AmbulanceTeam(int id) {
super(id);
}
public String getType(){
return "AMBULANCE_TEAM";
}
}
package firesimulator.world;
import java.awt.Polygon;
import java.util.Collection;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.LinkedList;
import org.apache.log4j.Logger;
import org.uncommons.maths.number.NumberGenerator;
import org.uncommons.maths.random.GaussianGenerator;
import firesimulator.simulator.Simulator;
import firesimulator.util.Configuration;
import firesimulator.util.Geometry;
/**
* @author tn
*
*/
public class Building extends StationaryObject {
private static final Logger LOG = Logger.getLogger(Building.class);
private static final double STEFAN_BOLTZMANN_CONSTANT = 0.000000056704;
public static int WATER_EXTINGUISH_PARAM;
public static float woodSpeed;
public static float steelSpeed;
public static float concreteSpeed;
public static float WATER_CAPCITY;
public static boolean POLICE_INFALMEABLE = false;
public static boolean AMBULANCE_INFALMEABLE = false;
public static boolean FIRE_INFALMEABLE = false;
public static boolean REFUGE_INFALMEABLE = false;
public NumberGenerator<Double> burnRate;
public boolean fierynessChanged;
private int waterQuantity;
private int floors = 1;
private int attributes = 0;
private int ignition = 0;
protected int fieryness = 0;
private int brokenness = 0;
public int[][] cells;
private int[] entrances;
private int code = 0;
private float buildingAreaGround = 0;
private float buildingAreaTotal = 0;
private int[] apexes;
private Polygon polygon;
public float fuel;
private float initFuel;
private float prevBurned;
public float volume;
public float capacity;
private double energy;
static final int FLOOR_HEIGHT = 3;
public float cooling = 0;
public Collection walls;
public Hashtable connectedBuildings;
public Building[] connectedBuilding;
public float[] connectedValues;
public double totalWallArea;
private int lwater = 0;
private int lwTime = -1;
private boolean wasEverWatered = false;
public boolean inflameable = true;
public static float woodCapacity = 4;
public static float steelCapacity = 4;
public static float concreteCapacity = 4;
public static float woodIgnition = 400;
public static float steelIgnition = 400;
public static float concreteIgnition = 400;
public static float woodEnergie = 1;
public static float steelEnergie = 1;
public static float concreteEnergie = 1;
public static float woodBurning = 800;
public static float steelBurning = 800;
public static float concreteBurning = 800;
public static final int NORMAL = 0;
public static final int HEATING = 1;
public static final int BURNING = 2;
public static final int COOLING_DOWN = 3;
public static final int EXTINGUISHED = 5;
public static final int BURNED_DOWN = 4;
public Building(int id) {
super(id);
polygon = null;
connectedBuildings = new Hashtable(30);
initFuel = -1;
prevBurned = 0;
java.util.Random random = new java.util.Random(Long.valueOf(Configuration.getValue("random.seed")).longValue());
burnRate = new GaussianGenerator(
Double.valueOf(Configuration.getValue("resq-fire.burn-rate-average")).doubleValue(),
Double.valueOf(Configuration.getValue("resq-fire.burn-rate-variance")).doubleValue(), random);
}
public float getBurningTemp() {
switch (code) {
case 0:
return woodBurning;
case 1:
return steelBurning;
default:
return concreteBurning;
}
}
public float getIgnitionPoint() {
switch (code) {
case 0:
return woodIgnition;
case 1:
return steelIgnition;
default:
return concreteIgnition;
}
}
public void ignite() {
energy = getCapacity() * getIgnitionPoint() * 1.5;
}
public float getBuildingAreaGround() {
return buildingAreaGround;
}
public int getFloors() {
return floors;
}
public void initialize(World world) {
initWalls(world);
setFieryness(0);
setWaterQuantity(0);
fierynessChanged = false;
if (polygon == null) {
polygon = new Polygon();
for (int n = 0; n < apexes.length; n++)
polygon.addPoint(apexes[n], apexes[++n]);
}
volume = buildingAreaGround * floors * FLOOR_HEIGHT;
fuel = getInitialFuel();
setCapacity(volume * getThermoCapacity());
energy = 0;
initFuel = -1;
prevBurned = 0;
lwTime = -1;
lwater = 0;
wasEverWatered = false;
LOG.debug("Initialised building " + id + ": ground area = " + buildingAreaGround + ", floors = " + floors
+ ", volume = " + volume + ", initial fuel = " + fuel + ", energy capacity = " + getCapacity());
}
public void reset(World w) {
setFieryness(0);
setWaterQuantity(0);
initialize(w);
}
private void initWalls(World world) {
if (walls != null)
return;
totalWallArea = 0;
walls = new LinkedList();
int fx = apexes[0];
int fy = apexes[1];
int lx = fx;
int ly = fy;
for (int n = 2; n < apexes.length; n++) {
int tx = apexes[n];
int ty = apexes[++n];
Wall w = new Wall(lx, ly, tx, ty, this);
if (w.validate()) {
walls.add(w);
totalWallArea += FLOOR_HEIGHT * 1000 * w.length;
} else
LOG.warn("Ignoring odd wall at building " + getID());
lx = tx;
ly = ty;
}
Wall w = new Wall(lx, ly, fx, fy, this);
walls.add(w);
world.allWalls.addAll(walls);
totalWallArea = totalWallArea / 1000000d;
}
public int hashCode() {
return id;
}
public void initWallValues(World world) {
int totalHits = 0;
int totalRays = 0;
int selfHits = 0;
int strange = 0;
for (Iterator w = walls.iterator(); w.hasNext();) {
Wall wall = (Wall) w.next();
wall.findHits(world);
totalHits += wall.hits;
selfHits += wall.selfHits;
totalRays += wall.rays;
strange = wall.strange;
}
int c = 0;
connectedBuilding = new Building[connectedBuildings.size()];
connectedValues = new float[connectedBuildings.size()];
float base = totalRays;
for (Enumeration e = connectedBuildings.keys(); e.hasMoreElements(); c++) {
Building b = (Building) e.nextElement();
Integer value = (Integer) connectedBuildings.get(b);
connectedBuilding[c] = b;
connectedValues[c] = value.floatValue() / base;
}
LOG.debug("{" + (((float) totalHits) * 100 / ((float) totalRays)) + "," + totalRays + "," + totalHits + ","
+ selfHits + "," + strange + "}");
}
public float getInitialFuel() {
if (initFuel < 0) {
initFuel = (float) (getFuelDensity() * volume);
}
return initFuel;
}
private float getFuelDensity() {
switch (code) {
case 0:
return woodEnergie;
case 1:
return steelEnergie;
default:
return concreteEnergie;
}
}
private float getThermoCapacity() {
switch (code) {
case 0:
return woodCapacity;
case 1:
return steelCapacity;
default:
return concreteCapacity;
}
}
public Polygon getPolygon() {
return polygon;
}
public String getType() {
return "BUILDING";
}
public void setAttributes(int atrb) {
this.attributes = atrb;
}
public int getCode() {
return code;
}
public void setIgnition(int ignition) {
this.ignition = ignition;
}
public int getIgnition() {
return ignition;
}
public void setFieryness(int fieryness) {
this.fieryness = fieryness;
}
public float getFuel() {
return fuel;
}
public int getFieryness() {
if (!isInflameable())
return 0;
if (getTemperature() >= getIgnitionPoint()) {
if (fuel >= getInitialFuel() * 0.66)
return 1; // burning, slightly damaged
if (fuel >= getInitialFuel() * 0.33)
return 2; // burning, more damaged
if (fuel > 0)
return 3; // burning, severly damaged
}
if (fuel == getInitialFuel())
if (wasEverWatered)
return 4; // not burnt, but watered-damaged
else
return 0; // not burnt, no water damage
if (fuel >= getInitialFuel() * 0.66)
return 5; // extinguished, slightly damaged
if (fuel >= getInitialFuel() * 0.33)
return 6; // extinguished, more damaged
if (fuel > 0)
return 7; // extinguished, severely damaged
return 8; // completely burnt down
}
public void setBrokenness(int brk) {
this.brokenness = brk;
}
public void setEntrances(int[] ent) {
this.entrances = ent;
}
public void setCode(int code) {
this.code = code;
}
public void setBuildingAreaGround(float area) {
this.buildingAreaGround = area;
}
public void setBuildingAreaTotal(float area) {
this.buildingAreaTotal = area;
}
public void setApexes(int[] apx) {
this.apexes = apx;
}
public int[] getApexes() {
return apexes;
}
public void setFloors(int floors) {
this.floors = floors;
}
public void findCells(World w) {
LinkedList tmp = new LinkedList();
for (int x = 0; x < w.getAirTemp().length; x++)
for (int y = 0; y < w.getAirTemp()[0].length; y++) {
int xv = x * w.SAMPLE_SIZE + w.getMinX();
int yv = y * w.SAMPLE_SIZE + w.getMinY();
if (Geometry.boundingTest(polygon, xv, yv, w.SAMPLE_SIZE, w.SAMPLE_SIZE)) {
int pc = Geometry.percent((float) xv, (float) yv, (float) w.SAMPLE_SIZE, (float) w.SAMPLE_SIZE, polygon);
if (pc > 0) {
tmp.add(Integer.valueOf(x));
tmp.add(Integer.valueOf(y));
tmp.add(Integer.valueOf(pc));
Object[] o = new Object[] { this, Float.valueOf(pc) };
w.gridToBuilding[x][y].add(o);
}
}
}
if (tmp.size() > 0) {
cells = new int[tmp.size() / 3][3];
Iterator i = tmp.iterator();
for (int c = 0; c < cells.length; c++) {
cells[c][0] = ((Integer) i.next()).intValue();
cells[c][1] = ((Integer) i.next()).intValue();
cells[c][2] = ((Integer) i.next()).intValue();
}
} else {
LOG.warn(getID() + " has no cell");
LOG.warn("Sample size: " + w.SAMPLE_SIZE);
LOG.warn("World min X, Y: " + w.getMinX() + ", " + w.getMinY());
LOG.warn("Air grid size: " + w.getAirTemp().length + " x " + w.getAirTemp()[0].length);
LOG.warn("Building polygon: ");
for (int i = 0; i < apexes.length; i += 2) {
LOG.warn(apexes[i] + ", " + apexes[i + 1]);
}
int expectedCellX = (apexes[0] - w.getMinX()) / w.SAMPLE_SIZE;
int expectedCellY = (apexes[1] - w.getMinY()) / w.SAMPLE_SIZE;
LOG.warn("Building should be in cell " + expectedCellX + ", " + expectedCellY);
for (int x = 0; x < w.getAirTemp().length; x++) {
for (int y = 0; y < w.getAirTemp()[0].length; y++) {
int xv = x * w.SAMPLE_SIZE + w.getMinX();
int yv = y * w.SAMPLE_SIZE + w.getMinY();
if (Geometry.boundingTest(polygon, xv, yv, w.SAMPLE_SIZE, w.SAMPLE_SIZE)) {
LOG.warn("Cell " + x + ", " + y);
LOG.warn("boundingTest(polygon, " + xv + ", " + yv + ", " + w.SAMPLE_SIZE + ", " + w.SAMPLE_SIZE + ") = "
+ Geometry.boundingTest(polygon, xv, yv, w.SAMPLE_SIZE, w.SAMPLE_SIZE));
LOG.warn("pc = "
+ Geometry.percent((float) xv, (float) yv, (float) w.SAMPLE_SIZE, (float) w.SAMPLE_SIZE, polygon));
int counter = 0;
double dx = w.SAMPLE_SIZE / 100;
double dy = w.SAMPLE_SIZE / 100;
for (int i = 0; i < 100; i++) {
for (int j = 0; j < 100; j++) {
double testX = dx * i + xv;
double testY = dy * j + yv;
if (polygon.contains(dx * i + xv, dy * j + yv)) {
counter++;
LOG.warn("Point " + testX + ", " + testY + " is inside");
}
}
}
LOG.warn("Counted " + counter + " interior points");
}
}
}
}
}
public double getTemperature() {
double rv = energy / getCapacity();
if (Double.isNaN(rv)) {
LOG.warn("Building " + id + " getTemperature returned NaN");
new RuntimeException().printStackTrace();
LOG.warn("Energy: " + energy);
LOG.warn("Capacity: " + getCapacity());
LOG.warn("Volume: " + volume);
LOG.warn("Thermal capacity: " + getThermoCapacity());
LOG.warn("Ground area: " + buildingAreaGround);
LOG.warn("Floors: " + floors);
}
if (rv == Double.NaN || rv == Double.POSITIVE_INFINITY || rv == Double.NEGATIVE_INFINITY)
rv = Double.MAX_VALUE * 0.75;
return rv;
}
public String codeToString() {
switch (code) {
case 0:
return "wooden";
case 1:
return "steelframe";
default:
return "concret";
}
}
public int getLastWater() {
return lwater;
}
public boolean getLastWatered() {
return lwTime == World.getWorld().getTime();
}
public boolean wasEverWatered() {
return wasEverWatered;
}
public int getWaterQuantity() {
return waterQuantity;
}
public void setWaterQuantity(int i) {
if (i > waterQuantity) {
lwTime = World.getWorld().getTime();
lwater = i - waterQuantity;
wasEverWatered = true;
}
waterQuantity = i;
}
public float getCapacity() {
return capacity;
}
public void setCapacity(float f) {
capacity = f;
}
public String toString() {
String rv = "building " + getID() + "\n";
for (Iterator i = walls.iterator(); i.hasNext(); rv += i.next() + "\n")
;
return rv;
}
public double getRadiationEnergy() {
double t = getTemperature() + 293; // Assume ambient temperature is 293 Kelvin.
double radEn = (t * t * t * t) * totalWallArea * Simulator.RADIATION_COEFFICENT * STEFAN_BOLTZMANN_CONSTANT;
if (id == 23545) {
LOG.debug("Getting radiation energy for building " + id);
LOG.debug("t = " + t);
LOG.debug("t^4 = " + (t * t * t * t));
LOG.debug("Total wall area: " + totalWallArea);
LOG.debug("Radiation coefficient: " + Simulator.RADIATION_COEFFICENT);
LOG.debug("Stefan-Boltzmann constant: " + STEFAN_BOLTZMANN_CONSTANT);
LOG.debug("Radiation energy: " + radEn);
LOG.debug("Building energy: " + getEnergy());
}
if (radEn == Double.NaN || radEn == Double.POSITIVE_INFINITY || radEn == Double.NEGATIVE_INFINITY)
radEn = Double.MAX_VALUE * 0.75;
if (radEn > getEnergy()) {
radEn = getEnergy();
}
return radEn;
}
public boolean isBuilding(int x, int y) {
return getX() == x && getY() == y;
}
public double getEnergy() {
if (energy == Double.NaN || energy == Double.POSITIVE_INFINITY || energy == Double.NEGATIVE_INFINITY)
energy = Double.MAX_VALUE * 0.75d;
return energy;
}
public void setEnergy(double energy) {
if (energy == Double.NaN || energy == Double.POSITIVE_INFINITY || energy == Double.NEGATIVE_INFINITY) {
energy = Double.MAX_VALUE * 0.75d;
}
this.energy = energy;
}
public float getConsum() {
if (fuel == 0) {
return 0;
}
float tf = (float) (getTemperature() / 1000f);
float lf = getFuel() / getInitialFuel();
float f = (float) (tf * lf * burnRate.nextValue());
if (f < 0.005f)
f = 0.005f;
return getInitialFuel() * f;
}
public float getPrevBurned() {
return prevBurned;
}
public void setPrevBurned(float prevBurned) {
this.prevBurned = prevBurned;
}
public void setInflameable(boolean inflameable) {
this.inflameable = inflameable;
}
public boolean isInflameable() {
return inflameable;
}
}
\ No newline at end of file
package firesimulator.world;
/**
* @author tn
*
* To change the template for this generated type comment go to
* Window>Preferences>Java>Code Generation>Code and Comments
*/
public class Car extends MovingObject {
public Car(int id) {
super(id);
}
public String getType(){
return "CAR";
}
}
package firesimulator.world;
/**
* @author tn
*
* To change the template for this generated type comment go to
* Window>Preferences>Java>Code Generation>Code and Comments
*/
public class Civilian extends MovingObject {
public Civilian(int id) {
super(id);
}
public String getType(){
return "CIVILIAN";
}
}
package firesimulator.world;
/**
* @author tn
*
* To change the template for this generated type comment go to
* Window>Preferences>Java>Code Generation>Code and Comments
*/
public abstract class Edge extends StationaryObject {
int headID;
int tailID;
int Length;
public Edge(int id) {
super(id);
}
public void setHead(int id){
headID=id;
}
public void setTail(int id){
tailID=id;
}
public void setLength(int length){
this.Length=length;
}
protected int getTailID() {
return tailID;
}
protected int getHeadID() {
return headID;
}
protected int length() {
return Length;
}
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment