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

init

parent 54f6cedf
package clear;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import rescuecore2.log.Logger;
import rescuecore2.messages.Command;
import rescuecore2.messages.control.KSCommands;
import rescuecore2.misc.geometry.GeometryTools2D;
import rescuecore2.misc.geometry.Line2D;
import rescuecore2.misc.geometry.Point2D;
import rescuecore2.standard.components.StandardSimulator;
import rescuecore2.standard.entities.Area;
import rescuecore2.standard.entities.Blockade;
import rescuecore2.standard.entities.PoliceForce;
import rescuecore2.standard.entities.Road;
import rescuecore2.standard.entities.StandardEntity;
import rescuecore2.standard.messages.AKClear;
import rescuecore2.standard.messages.AKClearArea;
import rescuecore2.worldmodel.ChangeSet;
import rescuecore2.worldmodel.EntityID;
/**
* The area model clear simulator. This simulator processes AKClear messages.
*/
public class ClearSimulator extends StandardSimulator {
private static final String SIMULATOR_NAME = "Area Model Clear Simulator";
private static final String REPAIR_RATE_KEY = "clear.repair.rate";
private static final String REPAIR_RAD_KEY = "clear.repair.rad";
private static final String REPAIR_DISTANCE_KEY = "clear.repair.distance";
// Converts square mm to square m.
private static final double REPAIR_COST_FACTOR = 0.000001;
private int repairRate;
private int repairRadius;
private int repairDistance;
@Override
public String getName() {
return SIMULATOR_NAME;
}
@Override
protected void postConnect() {
this.repairRate = config.getIntValue(REPAIR_RATE_KEY);
this.repairRadius = config.getIntValue(REPAIR_RAD_KEY);
this.repairDistance = config.getIntValue(REPAIR_DISTANCE_KEY);
}
@Override
protected void processCommands(KSCommands c, ChangeSet changes) {
long start = System.currentTimeMillis();
int time = c.getTime();
Logger.info("Timestep " + time);
Map<Blockade, Integer> partiallyCleared = new HashMap<>();
Set<EntityID> cleared = new HashSet<>();
for (Command command : c.getCommands()) {
if ((command instanceof AKClear clear) && isValid(clear, cleared)) {
Logger.debug("Processing " + clear);
EntityID blockadeID = clear.getTarget();
Blockade blockade = (Blockade) model.getEntity(blockadeID);
Area area = (Area) model.getEntity(blockade.getPosition());
int cost = blockade.getRepairCost();
Logger.debug("Blockade repair cost: " + cost);
Logger.debug("Blockade repair rate: " + this.repairRate);
if (this.repairRate >= cost) {
// Remove the blockade entirely
List<EntityID> ids = new ArrayList<>(area.getBlockades());
ids.remove(blockadeID);
area.setBlockades(ids);
model.removeEntity(blockadeID);
changes.addChange(area, area.getBlockadesProperty());
changes.entityDeleted(blockadeID);
partiallyCleared.remove(blockade);
cleared.add(blockadeID);
Logger.debug("Cleared " + blockade);
} else {
// Update the repair cost
if (!partiallyCleared.containsKey(blockade)) {
partiallyCleared.put(blockade, cost);
}
cost -= this.repairRate;
blockade.setRepairCost(cost);
changes.addChange(blockade, blockade.getRepairCostProperty());
}
} else if ((command instanceof AKClearArea clearArea)
&& (isValid(clearArea))) {
processClearArea(clearArea, changes);
Logger.debug("Processing " + clearArea);
}
}
// Shrink partially cleared blockades
for (Map.Entry<Blockade, Integer> next : partiallyCleared.entrySet()) {
Blockade b = next.getKey();
double original = next.getValue();
double current = b.getRepairCost();
// d is the new size relative to the old size
double d = current / original;
Logger.debug("Partially cleared " + b);
Logger.debug("Original repair cost: " + original);
Logger.debug("New repair cost: " + current);
Logger.debug("Proportion left: " + d);
int[] apexes = b.getApexes();
double cx = b.getX();
double cy = b.getY();
// Move each apex towards the centre
for (int i = 0; i < apexes.length; i += 2) {
double x = apexes[i];
double y = apexes[i + 1];
double dx = x - cx;
double dy = y - cy;
// Shift both x and y so they are now d * dx from the centre
double newX = cx + (dx * d);
double newY = cy + (dy * d);
apexes[i] = (int) newX;
apexes[i + 1] = (int) newY;
}
b.setApexes(apexes);
changes.addChange(b, b.getApexesProperty());
}
long end = System.currentTimeMillis();
Logger.info("Timestep " + time + " took " + (end - start) + " ms");
}
private void processClearArea(AKClearArea clear, ChangeSet changes) {
PoliceForce agent = (PoliceForce) model.getEntity(clear.getAgentID());
int targetX = clear.getDestinationX();
int targetY = clear.getDestinationY();
int length = this.repairDistance;
Map<Blockade, java.awt.geom.Area> blockades = new HashMap<>();
for (StandardEntity entity : model.getObjectsInRange(agent.getX(),
agent.getY(), length)) {
if ((entity instanceof Area area) && (area.isBlockadesDefined())) {
for (EntityID blockadeID : area.getBlockades()) {
Blockade blockade = (Blockade) model.getEntity(blockadeID);
if (blockade != null) {
if (blockade.getShape() == null) {
Logger.debug("Blockade Shape is null");
}
blockades.put(blockade,
new java.awt.geom.Area(blockade.getShape()));
}
}
}
}
int counter = 0;
int min = 0;
int max = 2 * length;
while (true) {
counter++;
length = (min + max) / 2;
java.awt.geom.Area area = Geometry.getClearArea(agent, targetX, targetY,
length, this.repairRadius);
double firstSurface = Geometry.surface(area);
for (java.awt.geom.Area blockade : blockades.values())
area.subtract(blockade);
double surface = Geometry.surface(area);
double clearedSurface = firstSurface - surface;
if ((clearedSurface * REPAIR_COST_FACTOR) > this.repairRate) {
max = length;
} else if ((counter != 1) && (counter < 15) && ((max - min) > 5)) {
min = length;
} else {
break;
}
}
java.awt.geom.Area area = Geometry.getClearArea(agent, targetX, targetY,
length, this.repairRadius);
for (Map.Entry<Blockade, java.awt.geom.Area> entry : blockades.entrySet()) {
Blockade blockade = entry.getKey();
java.awt.geom.Area blockadeArea = entry.getValue();
Road road = (Road) model.getEntity(blockade.getPosition());
double firstSurface = Geometry.surface(blockadeArea);
blockadeArea.subtract(area);
double surface = Geometry.surface(blockadeArea);
if (surface < firstSurface) {
changes.addChange(blockade, blockade.getApexesProperty());
List<int[]> areas = Geometry.getAreas(blockadeArea);
if (areas.size() == 1) {
Blockade backupBlockade = blockade;
blockade = updateBlockadeApexes(blockade, areas.get(0));
if (blockade == null) {
blockade = backupBlockade;
areas.clear();
} else {
changes.addChange(blockade, blockade.getApexesProperty());
changes.addChange(blockade, blockade.getXProperty());
changes.addChange(blockade, blockade.getYProperty());
changes.addChange(blockade, blockade.getRepairCostProperty());
}
}
if (areas.size() != 1) {
try {
List<EntityID> newIDs = requestNewEntityIDs(areas.size());
Iterator<EntityID> it = newIDs.iterator();
List<Blockade> newBlockades = new ArrayList<>();
if (!areas.isEmpty())
Logger.debug("Creating new blockade objects for "
+ blockade.getID().getValue() + " " + areas.size());
for (int[] apexes : areas) {
EntityID id = it.next();
Blockade b = makeBlockade(id, apexes, road.getID());
if (b != null)
newBlockades.add(b);
}
List<EntityID> existing = road.getBlockades();
List<EntityID> ids = new ArrayList<>();
if (existing != null)
ids.addAll(existing);
for (Blockade b : newBlockades) {
ids.add(b.getID());
}
ids.remove(blockade.getID());
road.setBlockades(ids);
changes.addAll(newBlockades);
model.removeEntity(blockade.getID());
changes.addChange(road, road.getBlockadesProperty());
changes.entityDeleted(blockade.getID());
} catch (InterruptedException e) {
Logger.error("Interrupted while requesting IDs");
}
}
}
}
}
private Blockade updateBlockadeApexes(Blockade blockade, int[] apexes) {
List<Point2D> points = GeometryTools2D.vertexArrayToPoints(apexes);
if (points.size() >= 2) {
Point2D centroid = GeometryTools2D.computeCentroid(points);
blockade.setApexes(apexes);
blockade.setX((int) centroid.getX());
blockade.setY((int) centroid.getY());
int cost = (int) (GeometryTools2D.computeArea(points)
* REPAIR_COST_FACTOR);
if (cost != 0) {
blockade.setRepairCost(cost);
return blockade;
}
}
return null;
}
private Blockade makeBlockade(EntityID id, int[] apexes, EntityID roadID) {
Blockade blockade = new Blockade(id);
blockade.setPosition(roadID);
return updateBlockadeApexes(blockade, apexes);
}
private boolean isValid(AKClear clear, Set<EntityID> cleared) {
// Check Target
StandardEntity target = model.getEntity(clear.getTarget());
if (target == null) {
Logger
.info("Rejecting clear command " + clear + ": target does not exist");
return false;
} else if (cleared.contains(clear.getTarget())) {
Logger.info("Ignoring clear command " + clear
+ ": target already cleared in this timestep");
return false;
} else if (!(target instanceof Blockade)) {
Logger.info(
"Rejecting clear command " + clear + ": target is not a blockade");
return false;
}
// Check Agent
StandardEntity agent = model.getEntity(clear.getAgentID());
if (agent == null) {
Logger
.info("Rejecting clear command " + clear + ": agent does not exist");
return false;
} else if (!(agent instanceof PoliceForce)) {
Logger.info(
"Rejecting clear command " + clear + ": agent is not a PoliceForce");
return false;
}
// Check PoliceForce
PoliceForce police = (PoliceForce) agent;
StandardEntity agentPosition = police.getPosition(model);
if (agentPosition == null) {
Logger.info(
"Rejecting clear command " + clear + ": could not locate the agent");
return false;
} else if (!police.isHPDefined() || police.getHP() <= 0) {
Logger.info("Rejecting clear command " + clear + ": agent is dead");
return false;
} else if (police.isBuriednessDefined() && police.getBuriedness() > 0) {
Logger.info("Rejecting clear command " + clear + ": agent is buried");
return false;
}
// Check Blockade
Blockade targetBlockade = (Blockade) target;
if (!targetBlockade.isPositionDefined()) {
Logger.info(
"Rejecting clear command " + clear + ": blockade position undefined");
return false;
} else if (!targetBlockade.isRepairCostDefined()) {
Logger.info(
"Rejecting clear command " + clear + ": blockade has no repair cost");
return false;
}
// Check Any Blockade to Clear
Point2D agentLocation = new Point2D(police.getX(), police.getY());
double bestDistance = Double.MAX_VALUE;
for (Line2D line : GeometryTools2D.pointsToLines(
GeometryTools2D.vertexArrayToPoints(targetBlockade.getApexes()),
true)) {
Point2D closest = GeometryTools2D.getClosestPointOnSegment(line,
agentLocation);
double distance = GeometryTools2D.getDistance(agentLocation, closest);
if (distance < this.repairDistance) {
return true;
} else if (bestDistance > distance) {
bestDistance = distance;
}
}
Logger.info("Rejecting clear command " + clear
+ ": agent is not adjacent to a target: closest blockade is "
+ bestDistance);
return false;
}
private boolean isValid(AKClearArea clear) {
StandardEntity agent = model.getEntity(clear.getAgentID());
if (agent == null) {
Logger
.info("Rejecting clear command " + clear + ": agent does not exist");
return false;
} else if (!(agent instanceof PoliceForce)) {
Logger.info("Rejecting clear command " + clear
+ ": agent is not a police officer");
return false;
}
// Check PoliceForce
PoliceForce police = (PoliceForce) agent;
StandardEntity agentPosition = police.getPosition(model);
if (!(agentPosition instanceof Area)) {
Logger.info(
"Rejecting clear command " + clear + " : could not locate agent");
return false;
} else if (!police.isHPDefined() || police.getHP() <= 0) {
Logger.info("Rejecting clear command " + clear + " : agent is dead");
return false;
} else if (police.isBuriednessDefined() && police.getBuriedness() > 0) {
Logger.info("Rejecting clear command " + clear + " : agent is buried");
return false;
}
return true;
}
}
\ No newline at end of file
package clear;
import java.awt.Polygon;
import java.awt.geom.Area;
import java.awt.geom.PathIterator;
import java.util.ArrayList;
import java.util.List;
import rescuecore2.misc.geometry.Line2D;
import rescuecore2.misc.geometry.Vector2D;
import rescuecore2.standard.entities.Human;
public class Geometry {
public static Area getClearArea(Human agent, int targetX, int targetY,
int clearLength, int clearRad) {
Vector2D agentToTarget = new Vector2D(targetX - agent.getX(),
targetY - agent.getY());
if (agentToTarget.getLength() > clearLength)
agentToTarget = agentToTarget.normalised().scale(clearLength);
agentToTarget = agentToTarget.normalised()
.scale(agentToTarget.getLength() + 510);
Vector2D backAgent = (new Vector2D(agent.getX(), agent.getY()))
.add(agentToTarget.normalised().scale(-510));
Line2D line = new Line2D(backAgent.getX(), backAgent.getY(),
agentToTarget.getX(), agentToTarget.getY());
Vector2D dir = agentToTarget.normalised().scale(clearRad);
Vector2D perpend1 = new Vector2D(-dir.getY(), dir.getX());
Vector2D perpend2 = new Vector2D(dir.getY(), -dir.getX());
rescuecore2.misc.geometry.Point2D points[] = new rescuecore2.misc.geometry.Point2D[] {
line.getOrigin().plus(perpend1), line.getEndPoint().plus(perpend1),
line.getEndPoint().plus(perpend2), line.getOrigin().plus(perpend2)};
int[] xPoints = new int[points.length];
int[] yPoints = new int[points.length];
for (int i = 0; i < points.length; i++) {
xPoints[i] = (int) points[i].getX();
yPoints[i] = (int) points[i].getY();
}
return new Area(new Polygon(xPoints, yPoints, points.length));
}
public static double surface(Area area) {
PathIterator iter = area.getPathIterator(null);
double sum_all = 0;
while (!iter.isDone()) {
List<double[]> points = new ArrayList<double[]>();
while (!iter.isDone()) {
double point[] = new double[2];
int type = iter.currentSegment(point);
iter.next();
if (type == PathIterator.SEG_CLOSE) {
if (points.size() > 0)
points.add(points.get(0));
break;
}
points.add(point);
}
double sum = 0;
for (int i = 0; i < points.size() - 1; i++)
sum += points.get(i)[0] * points.get(i + 1)[1]
- points.get(i)[1] * points.get(i + 1)[0];
sum_all += Math.abs(sum) / 2;
}
return sum_all;
}
public static List<int[]> getAreas(Area area) {
PathIterator iter = area.getPathIterator(null);
List<int[]> areas = new ArrayList<int[]>();
ArrayList<Integer> list = new ArrayList<Integer>();
while (!iter.isDone()) {
double point[] = new double[2]; // x, y
int type = iter.currentSegment(point);
if (type == PathIterator.SEG_CLOSE) {
if (list.size() > 0) {
int[] newArea = new int[list.size()];
for (int i = 0; i < list.size(); i++)
newArea[i] = list.get(i);
areas.add(newArea);
list = new ArrayList<Integer>();
}
} else {
list.add((int) point[0]);
list.add((int) point[1]);
}
iter.next();
}
return areas;
}
}
\ No newline at end of file
package collapse;
import rescuecore2.standard.entities.Building;
/**
* Collapse Simulator Building (CSBuilding) is a wrapper for the Standard
* Building class that contains extra variables created, updated and used by the
* Collapse Simulator only. This class is created in order to prevented
* unnecessary changes to the Standard Building class.
*
* @author Salim
*
*/
public class CSBuilding {
/**
* The reference to the real building class
*/
private final Building real;
/**
* Collapse Ratio shows the percent that the building has been collapsed so
* far.
*/
private float collapsedRatio = 0;
/**
* This shows whether the building has fire damage in the last cycle or not
*/
private boolean hasFireDamage = false;
public CSBuilding(Building building) {
real = building;
}
/**
* Returns the building's collapse ratio
*
* @return
*/
public float getCollapsedRatio() {
return collapsedRatio;
}
/**
* Changes the collapse ratio of the building to the input ratio
*
* @param collapsedRatio
* is a float
*/
public void setCollapsedRatio(float collapsedRatio) {
this.collapsedRatio = collapsedRatio;
}
/**
* Adds the input ratio to the building's collapse ratio
*
* @param ratio
* is a float that represents the increased value of the collapse
* ratio
*/
public void increaseCollapseRatio(float ratio) {
setCollapsedRatio(getCollapsedRatio() + ratio);
}
public Building getReal() {
return real;
}
/**
* Returns the extent that is still possible to collapse.
*
* @return a float representing the extent
*/
public double getRemainingToCollapse(double floorHeight) {
return floorHeight * real.getFloors() * (1 - getCollapsedRatio());
}
public boolean hasFireDamage() {
return false;
}
public void setHasFireDamage(boolean hasFireDamage) {
this.hasFireDamage = hasFireDamage;
}
public double getTotalCollapse(double floorHeight){
return floorHeight*real.getFloors();
}
}
package collapse;
import rescuecore2.config.Config;
import rescuecore2.messages.Message;
import rescuecore2.messages.control.KSAfterShocksInfo;
import rescuecore2.messages.control.KSCommands;
import rescuecore2.worldmodel.ChangeSet;
import rescuecore2.worldmodel.EntityID;
import rescuecore2.worldmodel.WorldModelListener;
import rescuecore2.worldmodel.WorldModel;
import rescuecore2.misc.geometry.Point2D;
import rescuecore2.misc.geometry.Line2D;
import rescuecore2.misc.geometry.Vector2D;
import rescuecore2.misc.geometry.GeometryTools2D;
import rescuecore2.misc.collections.LazyMap;
import rescuecore2.log.Logger;
import rescuecore2.GUIComponent;
import rescuecore2.standard.components.StandardSimulator;
import rescuecore2.standard.entities.StandardEntity;
import rescuecore2.standard.entities.StandardEntityURN;
import rescuecore2.standard.entities.StandardEntityConstants;
import rescuecore2.standard.entities.Building;
import rescuecore2.standard.entities.Road;
import rescuecore2.standard.entities.Edge;
import rescuecore2.standard.entities.Blockade;
import rescuecore2.standard.entities.StandardWorldModel;
import org.uncommons.maths.random.GaussianGenerator;
import org.uncommons.maths.random.ContinuousUniformGenerator;
import org.uncommons.maths.number.NumberGenerator;
import org.uncommons.maths.Maths;
import java.util.Map;
import java.util.HashMap;
import java.util.HashSet;
import java.util.EnumMap;
import java.util.Iterator;
import java.util.List;
import java.util.ArrayList;
import java.util.Collection;
import java.awt.geom.Path2D;
import java.awt.geom.Ellipse2D;
import java.awt.geom.PathIterator;
import javax.swing.JComponent;
/**
* A simple collapse simulator.
*/
public class CollapseSimulator extends StandardSimulator implements
GUIComponent {
private static final String CONFIG_PREFIX = "collapse.";
private static final String DESTROYED_SUFFIX = ".p-destroyed";
private static final String SEVERE_SUFFIX = ".p-severe";
private static final String MODERATE_SUFFIX = ".p-moderate";
private static final String SLIGHT_SUFFIX = ".p-slight";
private static final String NONE_SUFFIX = ".p-none";
private static final String DESTROYED_MEAN_SUFFIX = "destroyed.mean";
private static final String DESTROYED_SD_SUFFIX = "destroyed.sd";
private static final String SEVERE_MEAN_SUFFIX = "severe.mean";
private static final String SEVERE_SD_SUFFIX = "severe.sd";
private static final String MODERATE_MEAN_SUFFIX = "moderate.mean";
private static final String MODERATE_SD_SUFFIX = "moderate.sd";
private static final String SLIGHT_MEAN_SUFFIX = "slight.mean";
private static final String SLIGHT_SD_SUFFIX = "slight.sd";
private static final String BLOCK_KEY = "collapse.create-road-blockages";
private static final String FLOOR_HEIGHT_KEY = "collapse.floor-height";
private static final String WALL_COLLAPSE_EXTENT_MIN_KEY = "collapse.wall-extent.min";
private static final String WALL_COLLAPSE_EXTENT_MAX_KEY = "collapse.wall-extent.max";
/* Aftershock Requirment 2013 */
private static final String RANDOM_AFTERSHOCK = "collapse.aftershock.random";
/* Aftershock Requirment 2013 */
// enum IntensityType {
// ON_DAMAGE, ON_DISTANCE;
// public String toString() {
// if (this.equals(ON_DAMAGE))
// return "damage";
// else
// return "distance";
// };
//
// }
enum CollapsePolicy {
MERGE_BLOCKADES, DONT_MERGE_BLOCKADES;
public String toString() {
if (this.equals(MERGE_BLOCKADES))
return "merge";
else
return "dont_merge";
};
}
CollapsePolicy policy = CollapsePolicy.DONT_MERGE_BLOCKADES;
private static final int MAX_COLLAPSE = 100;
private static final double REPAIR_COST_FACTOR = 0.000001; // Converts
// square mm to
// square m.
public static final String NAME = "Collapse Simulator v1.1";
private static final List<EntityID> EMPTY_ID_LIST = new ArrayList<EntityID>(
0);
private NumberGenerator<Double> destroyed;
private NumberGenerator<Double> severe;
private NumberGenerator<Double> moderate;
private NumberGenerator<Double> slight;
private boolean block;
private double floorHeight;
private NumberGenerator<Double> extent;
private Map<StandardEntityConstants.BuildingCode, CollapseStats> stats;
private CollapseSimulatorGUI gui;
private Collection<Building> buildingCache;
private Collection<Road> roadCache;
public CollapseSimulator() {
}
/**
* This method instantiate a CollapseWorldModel instance.
*/
@Override
protected StandardWorldModel createWorldModel() {
return new CollapseWorldModel();/* Aftershocks Requirement:2013 */
}
@Override
public JComponent getGUIComponent() {
if (gui == null) {
gui = new CollapseSimulatorGUI();
}
return gui;
}
@Override
public String getGUIComponentName() {
return "Collapse simulator";
}
@Override
public String getName() {
return NAME;
}
@Override
protected void postConnect() {
super.postConnect();
stats = new EnumMap<StandardEntityConstants.BuildingCode, CollapseStats>(
StandardEntityConstants.BuildingCode.class);
for (StandardEntityConstants.BuildingCode code : StandardEntityConstants.BuildingCode
.values()) {
stats.put(code, new CollapseStats(code, config));
}
slight = new GaussianGenerator(config.getFloatValue(CONFIG_PREFIX
+ SLIGHT_MEAN_SUFFIX), config.getFloatValue(CONFIG_PREFIX
+ SLIGHT_SD_SUFFIX), config.getRandom());
moderate = new GaussianGenerator(config.getFloatValue(CONFIG_PREFIX
+ MODERATE_MEAN_SUFFIX), config.getFloatValue(CONFIG_PREFIX
+ MODERATE_SD_SUFFIX), config.getRandom());
severe = new GaussianGenerator(config.getFloatValue(CONFIG_PREFIX
+ SEVERE_MEAN_SUFFIX), config.getFloatValue(CONFIG_PREFIX
+ SEVERE_SD_SUFFIX), config.getRandom());
destroyed = new GaussianGenerator(config.getFloatValue(CONFIG_PREFIX
+ DESTROYED_MEAN_SUFFIX), config.getFloatValue(CONFIG_PREFIX
+ DESTROYED_SD_SUFFIX), config.getRandom());
block = config.getBooleanValue(BLOCK_KEY);
floorHeight = config.getFloatValue(FLOOR_HEIGHT_KEY) * 1000;
extent = new ContinuousUniformGenerator(
config.getFloatValue(WALL_COLLAPSE_EXTENT_MIN_KEY),
config.getFloatValue(WALL_COLLAPSE_EXTENT_MAX_KEY),
config.getRandom());
buildingCache = new HashSet<Building>();
roadCache = new HashSet<Road>();
for (StandardEntity next : model) {
if (next instanceof Building) {
buildingCache.add((Building) next);
}
if (next instanceof Road) {
roadCache.add((Road) next);
}
}
model.addWorldModelListener(new WorldModelListener<StandardEntity>() {
@Override
public void entityAdded(WorldModel<? extends StandardEntity> model,
StandardEntity e) {
if (e instanceof Building) {
buildingCache.add((Building) e);
}
if (e instanceof Road) {
roadCache.add((Road) e);
}
}
@Override
public void entityRemoved(
WorldModel<? extends StandardEntity> model, StandardEntity e) {
if (e instanceof Building) {
buildingCache.remove((Building) e);
}
if (e instanceof Road) {
roadCache.remove((Road) e);
}
}
});
}
@Override
protected void processCommands(KSCommands c, ChangeSet changes) {
long start = System.currentTimeMillis();
int time = c.getTime();
Logger.info("Timestep " + time);
if (gui != null) {
gui.timestep(time);
}
Collection<Building> collapsed = doCollapse(changes, time);
Map<Road, Collection<java.awt.geom.Area>> newBlock = doBlock(collapsed,
time);
// Create blockade objects
Map<Road, Collection<Blockade>> blockades = createBlockadeObjects(newBlock);
for (Map.Entry<Road, Collection<Blockade>> entry : blockades.entrySet()) {
Road r = entry.getKey();
List<EntityID> existing = r.getBlockades();
List<EntityID> ids = new ArrayList<EntityID>();
if (existing != null) {
ids.addAll(existing);
}
for (Blockade b : entry.getValue()) {
ids.add(b.getID());
}
r.setBlockades(ids);
changes.addAll(entry.getValue());
changes.addChange(r, r.getBlockadesProperty());
}
// If any roads have undefined blockades then set the blockades property
// to the empty list
for (Road next : roadCache) {
if (!next.isBlockadesDefined()) {
next.setBlockades(EMPTY_ID_LIST);
changes.addChange(next, next.getBlockadesProperty());
}
}
long end = System.currentTimeMillis();
Logger.info("Timestep " + time + " took " + (end - start) + " ms");
}
private Collection<Building> doCollapse(ChangeSet changes, int time) {
Collection<Building> result = new HashSet<Building>();
if (gui != null) {
gui.startCollapse(buildingCache.size());
}
if (time == 1) {
result.addAll(doEarthquakeCollapse(changes));
}
/* Aftershocks Requirement:2013 */
if (time != 1 && model().aftershockHappens(time)) {
result.addAll(doEarthquakeCollapse(changes));
}
if (gui != null) {
gui.endCollapse();
}
if (gui != null) {
gui.startFire(buildingCache.size());
}
// result.addAll(doFireCollapse(changes));
if (gui != null) {
gui.endFire();
}
return result;
}
static long t1;
static long t2;
static long t3;
private Map<Road, Collection<java.awt.geom.Area>> doBlock(
Collection<Building> collapsed, int time) {
Map<Road, Collection<java.awt.geom.Area>> result = new LazyMap<Road, Collection<java.awt.geom.Area>>() {
@Override
public Collection<java.awt.geom.Area> createValue() {
return new ArrayList<java.awt.geom.Area>();
}
};
if (!block) {
return result;
}
if (gui != null) {
gui.startBlock(collapsed.size());
}
for (Building b : collapsed) {
createBlockages(b, result, time);
if (gui != null) {
gui.bumpBlock();
}
}
if (gui != null) {
gui.endBlock();
}
return result;
}
private Collection<Building> doEarthquakeCollapse(ChangeSet changes) {
Map<StandardEntityConstants.BuildingCode, Map<CollapseDegree, Integer>> count = new EnumMap<StandardEntityConstants.BuildingCode, Map<CollapseDegree, Integer>>(
StandardEntityConstants.BuildingCode.class);
Map<StandardEntityConstants.BuildingCode, Integer> total = new EnumMap<StandardEntityConstants.BuildingCode, Integer>(
StandardEntityConstants.BuildingCode.class);
for (StandardEntityConstants.BuildingCode code : StandardEntityConstants.BuildingCode
.values()) {
Map<CollapseDegree, Integer> next = new EnumMap<CollapseDegree, Integer>(
CollapseDegree.class);
for (CollapseDegree cd : CollapseDegree.values()) {
next.put(cd, 0);
}
count.put(code, next);
total.put(code, 0);
}
Logger.debug("Collapsing buildings");
Collection<Building> result = new HashSet<Building>();
for (Building b : buildingCache) {
StandardEntityConstants.BuildingCode code = b.getBuildingCodeEnum();
int damage = code == null ? 0 : stats.get(code).damage();
damage = Maths.restrictRange(damage, 0, MAX_COLLAPSE);
int lastDamage = b.getBrokenness();
/*
* Aftershock Requirement 2013: this ignores the new damage of it is
* less than the previous
*/
if (damage < lastDamage) {
damage = lastDamage;
}
/* Aftershock Requirement 2013 */
b.setBrokenness(damage);
changes.addChange(b, b.getBrokennessProperty());
CollapseDegree degree = CollapseDegree.get(damage);
count.get(code).put(degree, count.get(code).get(degree) + 1);
total.put(code, total.get(code) + 1);
if (damage > 0) {
result.add(b);
}
if (gui != null) {
gui.bumpCollapse();
}
}
Logger.info("Finished collapsing buildings: ");
for (StandardEntityConstants.BuildingCode code : StandardEntityConstants.BuildingCode
.values()) {
Logger.info("Building code " + code + ": " + total.get(code)
+ " buildings");
Map<CollapseDegree, Integer> data = count.get(code);
for (Map.Entry<CollapseDegree, Integer> entry : data.entrySet()) {
Logger.info(" " + entry.getValue() + " "
+ entry.getKey().toString().toLowerCase());
}
}
return result;
}
private Collection<Building> doFireCollapse(ChangeSet changes) {
Logger.debug("Checking fire damage");
Collection<Building> result = new HashSet<Building>();
for (Building b : buildingCache) {
/*
* Aftershock Requirement @ 2103: it is used in doBlock to check
* whether apply the aftershock intensity or not
*/
model().getCSBuiding(b).setHasFireDamage(false);
if (!b.isFierynessDefined()) {
if (gui != null) {
gui.bumpFire();
}
continue;
}
int minDamage = 0;
switch (b.getFierynessEnum()) {
case HEATING:
minDamage = slight.nextValue().intValue();
break;
case BURNING:
minDamage = moderate.nextValue().intValue();
break;
case INFERNO:
minDamage = severe.nextValue().intValue();
break;
case BURNT_OUT:
minDamage = destroyed.nextValue().intValue();
break;
default:
break;
}
/* Aftershock Requirement @ 2103 */
if (minDamage != 0) {
// indicates that the building has fire damage
model().getCSBuiding(b).setHasFireDamage(true);
}
minDamage = Maths.restrictRange(minDamage, 0, MAX_COLLAPSE);
int damage = b.isBrokennessDefined() ? b.getBrokenness() : 0;
if (damage < minDamage) {
Logger.info(b + " damaged by fire. New brokenness: "
+ minDamage);
b.setBrokenness(minDamage);
changes.addChange(b, b.getBrokennessProperty());
result.add(b);
}
if (gui != null) {
gui.bumpFire();
}
}
Logger.debug("Finished checking fire damage");
return result;
}
private Map<Road, Collection<Blockade>> createBlockadeObjects(
Map<Road, Collection<java.awt.geom.Area>> blocks) {
Map<Road, Collection<Blockade>> result = new LazyMap<Road, Collection<Blockade>>() {
@Override
public Collection<Blockade> createValue() {
return new ArrayList<Blockade>();
}
};
int count = 0;
for (Collection<java.awt.geom.Area> c : blocks.values()) {
count += c.size();
}
try {
if (count != 0) {
List<EntityID> newIDs = requestNewEntityIDs(count);
Iterator<EntityID> it = newIDs.iterator();
Logger.debug("Creating new blockade objects");
for (Map.Entry<Road, Collection<java.awt.geom.Area>> entry : blocks
.entrySet()) {
Road r = entry.getKey();
for (java.awt.geom.Area area : entry.getValue()) {
EntityID id = it.next();
Blockade blockade = makeBlockade(id, area, r.getID());
if (blockade != null) {
result.get(r).add(blockade);
}
}
}
}
} catch (InterruptedException e) {
Logger.error("Interrupted while requesting IDs");
}
return result;
}
private void createBlockages(Building b,
Map<Road, Collection<java.awt.geom.Area>> roadBlockages, int time) {
long t = System.currentTimeMillis();
Logger.debug("Creating blockages for " + b);
/*
* Aftershock's Requirement@2103: this checks the ratio of the
* building's floors that is possible to collapsed
*/
double remainingfloors = model().getCSBuiding(b)
.getRemainingToCollapse(floorHeight);
double currentExtent = extent.nextValue();
double damage = b.getBrokenness();
/*
* Aftershock Requirement 2013: applies the intensity of the aftershock.
* This only applies if there is an aftershock and time is >1 and the
* building doesn't have any fire damage. In case of any fire damage the
* building creates the max possible collapse.
*/
if (time != 1 && model().aftershockHappens(time)
&& !model().getCSBuiding(b).hasFireDamage()) {
float intensity = model().aftershockIntensity(time);
damage = (int) ((float) damage * Math.min(1, intensity));
}
/* Aftershock's Requirement: 2013 */
double d = remainingfloors * (damage / (double) MAX_COLLAPSE)
* currentExtent;
t1 += System.currentTimeMillis() - t;
t = System.currentTimeMillis();
/* Aftershock's Requirement: 2013 */
model().getCSBuiding(b).increaseCollapseRatio(
(float) (d / model().getCSBuiding(b).getTotalCollapse(
floorHeight)));
// Place some blockages on surrounding roads
List<java.awt.geom.Area> wallAreas = new ArrayList<java.awt.geom.Area>();
// Project each wall out and build a list of wall areas
for (Edge edge : b.getEdges()) {
projectWall(edge, wallAreas, d);
}
java.awt.geom.Area fullArea = new java.awt.geom.Area();
for (java.awt.geom.Area wallArea : wallAreas) {
fullArea.add(wallArea);
}
/*
* new ShapeDebugFrame().show("Collapsed building", new
* ShapeDebugFrame.AWTShapeInfo(b.getShape(), "Original building area",
* Color.RED, true), new ShapeDebugFrame.AWTShapeInfo(fullArea,
* "Expanded building area (d = " + d + ")", Color.BLACK, false) );
*/
// Find existing blockade areas
java.awt.geom.Area existing = new java.awt.geom.Area();
if (policy.equals(CollapsePolicy.MERGE_BLOCKADES)) {
for (StandardEntity e : model
.getEntitiesOfType(StandardEntityURN.BLOCKADE)) {
Blockade blockade = (Blockade) e;
existing.add(blockadeToArea(blockade));
}
}
t2 += System.currentTimeMillis() - t;
// Intersect wall areas with roads
t = System.currentTimeMillis();
Map<Road, Collection<java.awt.geom.Area>> blockadesForRoads = createRoadBlockades(
fullArea, existing);
t3 += System.currentTimeMillis() - t;
// Add to roadBlockages
for (Map.Entry<Road, Collection<java.awt.geom.Area>> entry : blockadesForRoads
.entrySet()) {
Road r = entry.getKey();
Collection<java.awt.geom.Area> c = entry.getValue();
roadBlockages.get(r).addAll(c);
}
}
private void projectWall(Edge edge,
Collection<java.awt.geom.Area> areaList, double d) {
Line2D wallLine = new Line2D(edge.getStartX(), edge.getStartY(),
edge.getEndX() - edge.getStartX(), edge.getEndY()
- edge.getStartY());
Vector2D wallDirection = wallLine.getDirection();
Vector2D offset = wallDirection.getNormal().normalised().scale(-d);
Path2D path = new Path2D.Double();
Point2D right = wallLine.getOrigin();
Point2D left = wallLine.getEndPoint();
Point2D first = left.plus(offset.scale(-1));
Point2D second = right.plus(offset.scale(-1));
Point2D third = right.plus(offset);
Point2D fourth = left.plus(offset);
path.moveTo(first.getX(), first.getY());
path.lineTo(second.getX(), second.getY());
path.lineTo(third.getX(), third.getY());
path.lineTo(fourth.getX(), fourth.getY());
path.closePath();
java.awt.geom.Area wallArea = new java.awt.geom.Area(path);
areaList.add(wallArea);
// Also add circles at each corner
double radius = offset.getLength();
Ellipse2D ellipse1 = new Ellipse2D.Double(right.getX() - radius,
right.getY() - radius, radius * 2, radius * 2);
Ellipse2D ellipse2 = new Ellipse2D.Double(left.getX() - radius,
left.getY() - radius, radius * 2, radius * 2);
areaList.add(new java.awt.geom.Area(ellipse1));
areaList.add(new java.awt.geom.Area(ellipse2));
// Logger.info("Edge from " + wallLine + " expanded to " + first + ", "
// + second + ", " + third + ", " + fourth);
// debug.show("Collapsed building",
// new ShapeDebugFrame.AWTShapeInfo(buildingArea,
// "Original building area", Color.RED, true),
// new ShapeDebugFrame.Line2DShapeInfo(wallLine, "Wall edge",
// Color.WHITE, true, true),
// new ShapeDebugFrame.AWTShapeInfo(wallArea, "Wall area (d = " + d +
// ")", Color.GREEN, false),
// new ShapeDebugFrame.AWTShapeInfo(ellipse1, "Ellipse 1", Color.BLUE,
// false),
// new ShapeDebugFrame.AWTShapeInfo(ellipse2, "Ellipse 2", Color.ORANGE,
// false)
// );
}
private Map<Road, Collection<java.awt.geom.Area>> createRoadBlockades(
java.awt.geom.Area buildingArea, java.awt.geom.Area existing) {
Map<Road, Collection<java.awt.geom.Area>> result = new HashMap<Road, Collection<java.awt.geom.Area>>();
java.awt.Rectangle rectangle = buildingArea.getBounds();
Collection<StandardEntity> roads = model.getObjectsInRectangle(
(int) rectangle.getMinX(), (int) rectangle.getMinY(),
(int) rectangle.getMaxX(), (int) rectangle.getMaxY());
for (StandardEntity e : roads) {
if (!(e instanceof Road)) {
continue;
}
Road r = (Road) e;
java.awt.geom.Area roadArea = areaToGeomArea(r);
java.awt.geom.Area intersection = new java.awt.geom.Area(roadArea);
intersection.intersect(buildingArea);
intersection.subtract(existing);
if (intersection.isEmpty()) {
continue;
}
existing.add(intersection);
List<java.awt.geom.Area> blockadeAreas = fix(intersection);
result.put(r, blockadeAreas);
// debug.show("Road blockage",
// new ShapeDebugFrame.AWTShapeInfo(buildingArea, "Building area",
// Color.BLACK, false),
// new ShapeDebugFrame.AWTShapeInfo(roadArea, "Road area",
// Color.BLUE, false),
// new ShapeDebugFrame.AWTShapeInfo(intersection, "Intersection",
// Color.GREEN, true)
// );
}
return result;
}
private java.awt.geom.Area areaToGeomArea(
rescuecore2.standard.entities.Area area) {
Path2D result = new Path2D.Double();
Iterator<Edge> it = area.getEdges().iterator();
Edge e = it.next();
result.moveTo(e.getStartX(), e.getStartY());
result.lineTo(e.getEndX(), e.getEndY());
while (it.hasNext()) {
e = it.next();
result.lineTo(e.getEndX(), e.getEndY());
}
return new java.awt.geom.Area(result);
}
private List<java.awt.geom.Area> fix(java.awt.geom.Area area) {
List<java.awt.geom.Area> result = new ArrayList<java.awt.geom.Area>();
if (area.isSingular()) {
result.add(area);
return result;
}
PathIterator it = area.getPathIterator(null);
Path2D current = null;
// CHECKSTYLE:OFF:MagicNumber
double[] d = new double[6];
while (!it.isDone()) {
switch (it.currentSegment(d)) {
case PathIterator.SEG_MOVETO:
if (current != null) {
result.add(new java.awt.geom.Area(current));
}
current = new Path2D.Double();
current.moveTo(d[0], d[1]);
break;
case PathIterator.SEG_LINETO:
current.lineTo(d[0], d[1]);
break;
case PathIterator.SEG_QUADTO:
current.quadTo(d[0], d[1], d[2], d[3]);
break;
case PathIterator.SEG_CUBICTO:
current.curveTo(d[0], d[1], d[2], d[3], d[4], d[5]);
break;
case PathIterator.SEG_CLOSE:
current.closePath();
break;
default:
throw new RuntimeException(
"Unexpected result from PathIterator.currentSegment: "
+ it.currentSegment(d));
}
it.next();
}
// CHECKSTYLE:ON:MagicNumber
if (current != null) {
result.add(new java.awt.geom.Area(current));
}
return result;
}
private Blockade makeBlockade(EntityID id, java.awt.geom.Area area,
EntityID roadID) {
if (area.isEmpty()) {
return null;
}
Blockade result = new Blockade(id);
int[] apexes = getApexes(area);
List<Point2D> points = GeometryTools2D.vertexArrayToPoints(apexes);
if (points.size() < 2) {
return null;
}
int cost = (int) (GeometryTools2D.computeArea(points) * REPAIR_COST_FACTOR);
if (cost == 0) {
return null;
}
Point2D centroid = GeometryTools2D.computeCentroid(points);
result.setApexes(apexes);
result.setPosition(roadID);
result.setX((int) centroid.getX());
result.setY((int) centroid.getY());
result.setRepairCost((int) cost);
return result;
}
private int[] getApexes(java.awt.geom.Area area) {
// Logger.debug("getApexes");
List<Integer> apexes = new ArrayList<Integer>();
// CHECKSTYLE:OFF:MagicNumber
PathIterator it = area.getPathIterator(null, 100);
double[] d = new double[6];
int moveX = 0;
int moveY = 0;
int lastX = 0;
int lastY = 0;
boolean finished = false;
while (!finished && !it.isDone()) {
int x = 0;
int y = 0;
switch (it.currentSegment(d)) {
case PathIterator.SEG_MOVETO:
x = (int) d[0];
y = (int) d[1];
moveX = x;
moveY = y;
// Logger.debug("Move to " + x + ", " + y);
break;
case PathIterator.SEG_LINETO:
x = (int) d[0];
y = (int) d[1];
// Logger.debug("Line to " + x + ", " + y);
if (x == moveX && y == moveY) {
finished = true;
}
break;
case PathIterator.SEG_QUADTO:
x = (int) d[2];
y = (int) d[3];
// Logger.debug("Quad to " + x + ", " + y);
if (x == moveX && y == moveY) {
finished = true;
}
break;
case PathIterator.SEG_CUBICTO:
x = (int) d[4];
y = (int) d[5];
// Logger.debug("Cubic to " + x + ", " + y);
if (x == moveX && y == moveY) {
finished = true;
}
break;
case PathIterator.SEG_CLOSE:
// Logger.debug("Close");
finished = true;
break;
default:
throw new RuntimeException(
"Unexpected result from PathIterator.currentSegment: "
+ it.currentSegment(d));
}
// Logger.debug(x + ", " + y);
if (!finished && (x != lastX || y != lastY)) {
apexes.add(x);
apexes.add(y);
}
lastX = x;
lastY = y;
it.next();
}
// CHECKSTYLE:ON:MagicNumber
int[] result = new int[apexes.size()];
int i = 0;
for (Integer next : apexes) {
result[i++] = next;
}
return result;
}
private java.awt.geom.Area blockadeToArea(Blockade b) {
Path2D result = new Path2D.Double();
int[] apexes = b.getApexes();
result.moveTo(apexes[0], apexes[1]);
for (int i = 2; i < apexes.length; i += 2) {
result.lineTo(apexes[i], apexes[i + 1]);
}
result.closePath();
return new java.awt.geom.Area(result);
}
private class CollapseStats {
private double pDestroyed;
private double pSevere;
private double pModerate;
private double pSlight;
CollapseStats(StandardEntityConstants.BuildingCode code, Config config) {
String s = CONFIG_PREFIX + code.toString().toLowerCase();
pDestroyed = config.getFloatValue(s + DESTROYED_SUFFIX);
pSevere = pDestroyed + config.getFloatValue(s + SEVERE_SUFFIX);
pModerate = pSevere + config.getFloatValue(s + MODERATE_SUFFIX);
pSlight = pModerate + config.getFloatValue(s + SLIGHT_SUFFIX);
}
int damage() {
double d = random.nextDouble();
if (d < pDestroyed) {
return destroyed.nextValue().intValue();
}
if (d < pSevere) {
return severe.nextValue().intValue();
}
if (d < pModerate) {
return moderate.nextValue().intValue();
}
if (d < pSlight) {
return slight.nextValue().intValue();
}
return 0;
}
}
private enum CollapseDegree {
NONE(0), SLIGHT(25), MODERATE(50), SEVERE(75), DESTROYED(100);
private int max;
private CollapseDegree(int max) {
this.max = max;
}
public static CollapseDegree get(int d) {
for (CollapseDegree next : values()) {
if (d <= next.max) {
return next;
}
}
throw new IllegalArgumentException(
"Don't know what to do with a damage value of " + d);
}
}
// /* Aftershocks Requirement:2013 */
// /**
// * Handles KAAftershocksInfo and calls the parent processMessage.
// */
// @Override
// protected void processMessage(Message msg) {
//
// }
/* Aftershocks Requirement:2013 */
public CollapseWorldModel model() {
return (CollapseWorldModel) model;
}
@Override
protected void processMessage(Message msg) {
if (msg instanceof KSAfterShocksInfo) {
model().updateAftershocks((KSAfterShocksInfo) msg);
} else {
super.processMessage(msg);
}
}
public static void main(String[] args) {
}
}
package collapse;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.JLabel;
import javax.swing.SwingUtilities;
import java.awt.GridLayout;
/**
GUI for the collapse simulator.
*/
public class CollapseSimulatorGUI extends JPanel {
private JLabel timeLabel;
private JLabel statusLabel;
private JProgressBar collapseProgress;
private JProgressBar fireProgress;
private JProgressBar blockadeProgress;
private int collapse;
private int fire;
private int block;
/**
Construct a collapse simulator GUI.
*/
public CollapseSimulatorGUI() {
super(new GridLayout(0, 2));
timeLabel = new JLabel("Not started");
statusLabel = new JLabel("Not started");
collapseProgress = new JProgressBar(0, 1);
fireProgress = new JProgressBar(0, 1);
blockadeProgress = new JProgressBar(0, 1);
collapseProgress.setStringPainted(true);
fireProgress.setStringPainted(true);
blockadeProgress.setStringPainted(true);
add(new JLabel("Timestep"));
add(timeLabel);
add(new JLabel("Status"));
add(statusLabel);
add(new JLabel("Collapsing buildings"));
add(collapseProgress);
add(new JLabel("Fire damage"));
add(fireProgress);
add(new JLabel("Creating blockades"));
add(blockadeProgress);
}
/**
Notify the gui that a new timestep has started.
@param time The timestep.
*/
void timestep(final int time) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
timeLabel.setText(String.valueOf(time));
collapseProgress.setValue(0);
fireProgress.setValue(0);
blockadeProgress.setValue(0);
collapse = 0;
fire = 0;
block = 0;
}
});
}
/**
Notify the gui that collapse computation has begun.
@param buildingCount The number of buildings to process.
*/
void startCollapse(final int buildingCount) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
statusLabel.setText("Collapsing buildings");
collapseProgress.setMaximum(buildingCount);
collapseProgress.setValue(0);
collapse = 0;
}
});
}
/**
Notify the gui that a building collapse has been processed.
*/
void bumpCollapse() {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
collapseProgress.setValue(++collapse);
}
});
}
/**
Notify the gui that building collapse computation is complete.
*/
void endCollapse() {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
collapseProgress.setValue(collapseProgress.getMaximum());
}
});
}
/**
Notify the gui that fire collapse computation has begun.
@param buildingCount The number of buildings to process.
*/
void startFire(final int buildingCount) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
statusLabel.setText("Fire damage");
fireProgress.setMaximum(buildingCount);
fireProgress.setValue(0);
fire = 0;
}
});
}
/**
Notify the gui that a fire collapse has been processed.
*/
void bumpFire() {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
fireProgress.setValue(++fire);
}
});
}
/**
Notify the gui that fire collapse computation is complete.
*/
void endFire() {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
fireProgress.setValue(fireProgress.getMaximum());
}
});
}
/**
Notify the gui that blockade generation has begun.
@param buildingCount The number of buildings to process.
*/
void startBlock(final int buildingCount) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
statusLabel.setText("Computing blockades");
if (buildingCount == 0) {
blockadeProgress.setMaximum(1);
blockadeProgress.setValue(1);
}
else {
blockadeProgress.setMaximum(buildingCount);
blockadeProgress.setValue(0);
block = 0;
}
}
});
}
/**
Notify the gui that blockade generation for a building has been processed.
*/
void bumpBlock() {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
blockadeProgress.setValue(++block);
}
});
}
/**
Notify the gui that blockade generation is complete.
*/
void endBlock() {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
blockadeProgress.setValue(blockadeProgress.getMaximum());
statusLabel.setText("Done");
}
});
}
}
\ No newline at end of file
package collapse;
import java.util.HashMap;
import rescuecore2.messages.control.KSAfterShocksInfo;
import rescuecore2.standard.entities.Building;
import rescuecore2.standard.entities.StandardEntity;
import rescuecore2.standard.entities.StandardEntityURN;
import rescuecore2.standard.entities.StandardWorldModel;
import rescuecore2.worldmodel.ChangeSet;
import rescuecore2.worldmodel.EntityID;
/**
*
* Collapse simulator's world model contains aftershocks' information that other
* simulators don't need.
*
* @author Salim
*
*/
public class CollapseWorldModel extends StandardWorldModel {
private HashMap<Integer, Float> aftershocks;
private HashMap<Building, CSBuilding> collapseBuildings;
public CollapseWorldModel() {
this.aftershocks = new HashMap<Integer, Float>();
collapseBuildings = new HashMap<Building, CSBuilding>();
}
@Override
public void merge(ChangeSet changes) {
super.merge(changes);
}
/**
* Changes the list in the world model with the new input aftershock list
*
* @param msg
* instance of KSAfterShocksInfo
*/
public void updateAftershocks(KSAfterShocksInfo msg) {
aftershocks = msg.getAftershocks();
}
public boolean aftershockHappens(int time) {
return aftershocks.get(time) != null;
}
public float aftershockIntensity(int time) {
return aftershocks.get(time);
}
public HashMap<Building, CSBuilding> getCollapseBuildings() {
if (collapseBuildings.size() == 0)
createCollapseBuildings();
return collapseBuildings;
}
/**
* Creates Collapse Simulator Buildings using the Standard Buildings
*/
private void createCollapseBuildings() {
for (StandardEntity entity : this) {
if(entity instanceof Building)
collapseBuildings.put((Building) entity, new CSBuilding((Building) entity));
}
}
/**
* Returns a specific CSBuilding by its EntityID
*
* @param id
* is an EntityID
* @return the corresponding CSBuilding to id
*/
public CSBuilding getCSBuiding(EntityID id) {
return getCollapseBuildings().get((Building) getEntity(id));
}
/**
* Returns a specific CSBuilding by its Building
*
* @param building
* is an Building
* @return the corresponding CSBuilding to building
*/
public CSBuilding getCSBuiding(Building building) {
return getCollapseBuildings().get(building);
}
}
package gis2;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import org.apache.log4j.Logger;
import rescuecore2.Constants;
import rescuecore2.config.Config;
import rescuecore2.connection.Connection;
import rescuecore2.connection.ConnectionException;
import rescuecore2.connection.ConnectionListener;
import rescuecore2.connection.TCPConnection;
import rescuecore2.messages.Message;
import rescuecore2.messages.control.GKConnectOK;
import rescuecore2.messages.control.KGConnect;
import rescuecore2.messages.control.Shutdown;
import rescuecore2.misc.CommandLineOptions;
import rescuecore2.misc.java.LoadableTypeProcessor;
import rescuecore2.registry.Registry;
import rescuecore2.worldmodel.Entity;
import rescuecore2.worldmodel.WorldModel;
/**
* This class is used for starting a remote GIS server.
*/
public final class GISServer {
private static final long WAIT_TIME = 1000;
private ServerSocket server;
private WorldModel<? extends Entity> world;
private volatile boolean running;
private static final Logger LOG = Logger.getLogger(GISServer.class);
private GISServer(int port, WorldModel<? extends Entity> world) throws IOException {
server = new ServerSocket(port);
this.world = world;
running = true;
}
/**
* Start the GIS server.
*
* @param args Command line arguments: <-c config file>
*/
public static void main(String[] args) {
Config config = new Config();
try {
CommandLineOptions.processArgs(args, config);
int port = config.getIntValue(Constants.GIS_PORT_NUMBER_KEY, Constants.DEFAULT_GIS_PORT_NUMBER);
processJarFiles(config);
GMLWorldModelCreator creator = new GMLWorldModelCreator();
new GISServer(port, creator.buildWorldModel(config)).run();
LOG.info("GIS server listening on port " + port);
} catch (Exception e) {
LOG.fatal("Error starting GIS server", e);
}
}
private static void processJarFiles(Config config) throws IOException {
LoadableTypeProcessor processor = new LoadableTypeProcessor(config);
processor.addFactoryRegisterCallbacks(Registry.SYSTEM_REGISTRY);
processor.process();
}
/**
* Run the GIS server.
*/
public void run() {
while (running) {
try {
Socket socket = server.accept();
new ServerThread(socket).start();
} catch (IOException e) {
LOG.error("Error accepting connection", e);
running = false;
}
}
}
private class ServerThread extends Thread implements ConnectionListener {
private Socket socket;
private boolean dead;
public ServerThread(Socket socket) {
this.socket = socket;
dead = false;
}
@Override
public void run() {
TCPConnection c = null;
try {
c = new TCPConnection(socket);
} catch (IOException e) {
LOG.error("Error starting TCPConnection", e);
return;
}
c.startup();
c.addConnectionListener(this);
synchronized (this) {
while (!dead) {
try {
this.wait(WAIT_TIME);
} catch (InterruptedException e) {
dead = true;
}
}
}
c.shutdown();
}
@Override
public void messageReceived(Connection c, Message msg) {
if (msg instanceof KGConnect) {
// Send a GKConnectOK
try {
c.sendMessage(new GKConnectOK(world.getAllEntities()));
} catch (ConnectionException e) {
LOG.fatal("Error sending message", e);
die();
}
}
if (msg instanceof Shutdown) {
die();
}
}
private void die() {
synchronized (this) {
dead = true;
notifyAll();
}
running = false;
}
}
}
\ No newline at end of file
package gis2;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import kernel.KernelException;
import kernel.WorldModelCreator;
import maps.CoordinateConversion;
import maps.MapException;
import maps.MapReader;
import maps.ScaleConversion;
import maps.gml.GMLBuilding;
import maps.gml.GMLCoordinates;
import maps.gml.GMLDirectedEdge;
import maps.gml.GMLMap;
import maps.gml.GMLRoad;
import maps.gml.GMLShape;
import org.apache.log4j.Logger;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.io.SAXReader;
import rescuecore2.config.Config;
import rescuecore2.misc.geometry.GeometryTools2D;
import rescuecore2.misc.geometry.Point2D;
import rescuecore2.scenario.exceptions.ScenarioException;
import rescuecore2.standard.entities.Building;
import rescuecore2.standard.entities.Edge;
import rescuecore2.standard.entities.Road;
import rescuecore2.standard.entities.StandardWorldModel;
import rescuecore2.worldmodel.Entity;
import rescuecore2.worldmodel.EntityID;
import rescuecore2.worldmodel.WorldModel;
/**
* A WorldModelCreator that reads a GML file and scenario descriptor.
*/
public class GMLWorldModelCreator implements WorldModelCreator {
private static final String MAP_DIRECTORY_KEY = "gis.map.dir";
private static final String MAP_FILE_KEY = "gis.map.file";
private static final String DEFAULT_MAP_FILE = "map.gml";
private static final String SCENARIO_FILE_KEY = "gis.map.scenario";
private static final String DEFAULT_SCENARIO_FILE = "scenario.xml";
private static final String MAX_FLOOR = "gis.map.max-floor";
private static final String FLOOR_PLACEMENT_TYPE = "gis.map.floor-placement.random";
private static final String RANDOM_FLOOR_RATE = "gis.map.floor-placement.random.floor-rate.";
private static final String BUILDING_CODE_PLACEMENT_TYPE = "gis.map.building-code-placement.random";
private static final String RANDOM_BUILDING_CODE_RATE = "gis.map.building-code-placement.random.code-rate.";
private static final String MAX_BUILDING_CODE = "gis.map.max-building-code";
private static final double SQ_MM_TO_SQ_M = 0.000001;
private GisScenario scenario;
private static final Logger LOG = Logger
.getLogger(GMLWorldModelCreator.class);
// private ShapeDebugFrame debug;
private int nextID;
@Override
public String toString() {
return "GML world model creator";
}
@Override
public WorldModel<? extends Entity> buildWorldModel(Config config)
throws KernelException {
try {
StandardWorldModel result = new StandardWorldModel();
File dir = new File(config.getValue(MAP_DIRECTORY_KEY));
File mapFile = new File(dir,
config.getValue(MAP_FILE_KEY, DEFAULT_MAP_FILE));
File scenarioFile = new File(dir,
config.getValue(SCENARIO_FILE_KEY, DEFAULT_SCENARIO_FILE));
readMapData(mapFile, result, config);
readScenarioAndApply(scenarioFile, result, config);
for (Entity e : result) {
nextID = Math.max(nextID, e.getID().getValue());
}
++nextID;
result.index();
return result;
} catch (MapException e) {
throw new KernelException("Couldn't read GML file", e);
} catch (DocumentException e) {
throw new KernelException("Couldn't read scenario file", e);
} catch (ScenarioException e) {
throw new KernelException("Invalid scenario file", e);
}
}
@Override
public EntityID generateID() {
return new EntityID(nextID++);
}
private void readMapData(File mapFile, StandardWorldModel result,
Config config) throws MapException {
int maxFloor = config.getIntValue(MAX_FLOOR, 3);
boolean randomfloorPlacement = config.getBooleanValue(FLOOR_PLACEMENT_TYPE,
false);
int[] floorRates = null;
int[] floorRatesCumulative = null;
if (randomfloorPlacement) {
floorRates = new int[maxFloor + 1];
floorRatesCumulative = new int[maxFloor + 1];
for (int i = 1; i <= maxFloor; i++) {
floorRates[i] = config.getIntValue(RANDOM_FLOOR_RATE + i);
floorRatesCumulative[i] = floorRatesCumulative[i - 1] + floorRates[i];
}
}
int maxBuildingCode = config.getIntValue(MAX_BUILDING_CODE, 2);
boolean randomBuildingCodePlacement = config
.getBooleanValue(BUILDING_CODE_PLACEMENT_TYPE, false);
int[] buildingCodeRates = null;
int[] buildingCodesCumulative = null;
if (randomBuildingCodePlacement) {
buildingCodeRates = new int[maxBuildingCode + 1];
buildingCodesCumulative = new int[maxBuildingCode + 1];
for (int i = 0; i <= maxBuildingCode; i++) {
buildingCodeRates[i] = config
.getIntValue(RANDOM_BUILDING_CODE_RATE + i);
buildingCodesCumulative[i] = (i > 0 ? buildingCodesCumulative[i - 1]
: 0) + buildingCodeRates[i];
}
}
GMLMap map = (GMLMap) MapReader.readMap(mapFile);
CoordinateConversion conversion = getCoordinateConversion(map);
LOG.debug("Creating entities");
LOG.debug(map.getBuildings().size() + " buildings");
LOG.debug(map.getRoads().size() + " roads");
for (GMLBuilding next : map.getBuildings()) {
// Create a new Building entity
EntityID id = new EntityID(next.getID());
Building b = new Building(id);
List<Point2D> vertices = convertShapeToPoints(next, conversion);
double area = GeometryTools2D.computeArea(vertices) * SQ_MM_TO_SQ_M;
Point2D centroid = GeometryTools2D.computeCentroid(vertices);
// Building properties
int floors = Math.min(maxFloor, next.getFloors());
if (randomfloorPlacement) {
int rnd = config.getRandom().nextInt(floorRatesCumulative[maxFloor])
+ 1;
for (int i = 1; i <= maxFloor; i++) {
if (rnd <= floorRatesCumulative[i]) {
floors = i;
break;
}
}
}
int code = Math.min(maxBuildingCode, next.getCode());
if (randomBuildingCodePlacement) {
int rnd = config.getRandom()
.nextInt(buildingCodesCumulative[maxBuildingCode]) + 1;
for (int i = 0; i <= maxBuildingCode; i++) {
if (rnd <= buildingCodesCumulative[i]) {
code = i;
break;
}
}
}
b.setFloors(floors);
b.setFieryness(0);
b.setBrokenness(0);
b.setBuildingCode(code);
b.setBuildingAttributes(0);
b.setGroundArea((int) Math.abs(area));
b.setTotalArea(((int) Math.abs(area)) * b.getFloors());
b.setImportance(next.getImportance());
b.setCapacity(0);
// Area properties
b.setEdges(createEdges(next, conversion));
b.setX((int) centroid.getX());
b.setY((int) centroid.getY());
result.addEntity(b);
}
for (GMLRoad next : map.getRoads()) {
// Create a new Road entity
EntityID id = new EntityID(next.getID());
Road r = new Road(id);
List<Point2D> vertices = convertShapeToPoints(next, conversion);
Point2D centroid = GeometryTools2D.computeCentroid(vertices);
// Road properties: None
// Area properties
r.setX((int) centroid.getX());
r.setY((int) centroid.getY());
r.setEdges(createEdges(next, conversion));
result.addEntity(r);
}
}
private void readScenarioAndApply(File scenarioFile,
StandardWorldModel result, Config config)
throws DocumentException, ScenarioException {
if (scenarioFile.exists()) {
readScenario(scenarioFile, config);
LOG.debug("Applying scenario");
scenario.apply(result, config);
}
}
private void readScenario(File scenarioFile, Config config)
throws DocumentException, ScenarioException {
if (scenarioFile.exists()) {
SAXReader reader = new SAXReader();
LOG.debug("Reading scenario");
Document doc = reader.read(scenarioFile);
scenario = new GisScenario(doc, config);
}
}
private List<Edge> createEdges(GMLShape s, CoordinateConversion conversion) {
List<Edge> result = new ArrayList<Edge>();
for (GMLDirectedEdge edge : s.getEdges()) {
GMLCoordinates start = edge.getStartCoordinates();
GMLCoordinates end = edge.getEndCoordinates();
Integer neighbourID = s.getNeighbour(edge);
EntityID id = neighbourID == null ? null : new EntityID(neighbourID);
double sx = conversion.convertX(start.getX());
double sy = conversion.convertY(start.getY());
double ex = conversion.convertX(end.getX());
double ey = conversion.convertY(end.getY());
result.add(new Edge((int) sx, (int) sy, (int) ex, (int) ey, id));
}
return result;
}
private List<Point2D> convertShapeToPoints(GMLShape shape,
CoordinateConversion conversion) {
List<Point2D> points = new ArrayList<Point2D>();
for (GMLCoordinates next : shape.getCoordinates()) {
points.add(new Point2D(conversion.convertX(next.getX()),
conversion.convertY(next.getY())));
}
return points;
}
private CoordinateConversion getCoordinateConversion(GMLMap map) {
return new ScaleConversion(map.getMinX(), map.getMinY(), 1000, 1000);
}
public GisScenario getScenario(Config config) throws DocumentException {
if (scenario == null) {
File dir = new File(config.getValue(MAP_DIRECTORY_KEY));
File scenarioFile = new File(dir,
config.getValue(SCENARIO_FILE_KEY, DEFAULT_SCENARIO_FILE));
try {
readScenario(scenarioFile, config);
} catch (ScenarioException e) {
e.printStackTrace();
}
}
return scenario;
}
}
\ No newline at end of file
package gis2;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import maps.gml.GMLRefuge;
import org.apache.log4j.Logger;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.Namespace;
import org.dom4j.QName;
import rescuecore2.config.Config;
import rescuecore2.scenario.compatibilities.CollapseSimCompatibaleScenarioV1_1;
import rescuecore2.scenario.exceptions.ScenarioException;
import rescuecore2.standard.entities.AmbulanceCentre;
import rescuecore2.standard.entities.AmbulanceTeam;
import rescuecore2.standard.entities.Area;
import rescuecore2.standard.entities.Building;
import rescuecore2.standard.entities.Civilian;
import rescuecore2.standard.entities.FireBrigade;
import rescuecore2.standard.entities.FireStation;
import rescuecore2.standard.entities.GasStation;
import rescuecore2.standard.entities.Human;
import rescuecore2.standard.entities.Hydrant;
import rescuecore2.standard.entities.PoliceForce;
import rescuecore2.standard.entities.PoliceOffice;
import rescuecore2.standard.entities.Refuge;
import rescuecore2.standard.entities.Road;
import rescuecore2.standard.entities.StandardEntity;
import rescuecore2.standard.entities.StandardWorldModel;
import rescuecore2.worldmodel.Entity;
import rescuecore2.worldmodel.EntityID;
/**
* This class knows how to read scenario files and apply them to
* StandardWorldModels.
*/
public class GisScenario implements rescuecore2.scenario.Scenario, CollapseSimCompatibaleScenarioV1_1 {
private static final String SCENARIO_NAMESPACE_URI = "urn:roborescue:map:scenario";
private static final Namespace SCENARIO_NAMESPACE = DocumentHelper.createNamespace("scenario",
SCENARIO_NAMESPACE_URI);
private static final int DEFAULT_HP = 10000;
private static final int DEFAULT_STAMINA = 10000;
private static final String WATER_QUANTITY_KEY = "fire.tank.maximum";
private static final QName LOCATION_QNAME = DocumentHelper.createQName("location", SCENARIO_NAMESPACE);
private static final QName TIME_QNAME = DocumentHelper.createQName("time", SCENARIO_NAMESPACE);
private static final QName INTENSITY_QNAME = DocumentHelper.createQName("intensity", SCENARIO_NAMESPACE);
private static final QName SCENARIO_QNAME = DocumentHelper.createQName("scenario", SCENARIO_NAMESPACE);
private static final QName REFUGE_QNAME = DocumentHelper.createQName("refuge", SCENARIO_NAMESPACE);
private static final QName GAS_STATION_QNAME = DocumentHelper.createQName("gasstation", SCENARIO_NAMESPACE);
private static final QName HYDRANT_QNAME = DocumentHelper.createQName("hydrant", SCENARIO_NAMESPACE);
private static final QName CIV_QNAME = DocumentHelper.createQName("civilian", SCENARIO_NAMESPACE);
private static final QName FB_QNAME = DocumentHelper.createQName("firebrigade", SCENARIO_NAMESPACE);
private static final QName AT_QNAME = DocumentHelper.createQName("ambulanceteam", SCENARIO_NAMESPACE);
private static final QName PF_QNAME = DocumentHelper.createQName("policeforce", SCENARIO_NAMESPACE);
private static final QName FS_QNAME = DocumentHelper.createQName("firestation", SCENARIO_NAMESPACE);
private static final QName AC_QNAME = DocumentHelper.createQName("ambulancecentre", SCENARIO_NAMESPACE);
private static final QName PO_QNAME = DocumentHelper.createQName("policeoffice", SCENARIO_NAMESPACE);
private static final QName FIRE_QNAME = DocumentHelper.createQName("fire", SCENARIO_NAMESPACE);
/* Aftershock requirement:2013 */
private static final QName AFTERSHOCK_QNAME = DocumentHelper.createQName("aftershock", SCENARIO_NAMESPACE);
/* Refuge bed capacity:2020 */
private static final QName BEDCAPACITY_QNAME = DocumentHelper.createQName("bedCapacity", SCENARIO_NAMESPACE);
/* Refuge refill capacity:2020 */
private static final QName REFILLCAPACITY_QNAME = DocumentHelper.createQName("refillCapacity", SCENARIO_NAMESPACE);
private Set<Integer> refuges;
private Set<Integer> hydrants;
private Set<Integer> gasStations;
private Set<Integer> fires;
/* Aftershock requirement:2013 */
private HashMap<Integer, Float> aftershocks;
private Collection<Integer> civLocations;
private Collection<Integer> fbLocations;
private Collection<Integer> atLocations;
private Collection<Integer> pfLocations;
private Collection<Integer> fsLocations;
private Collection<Integer> acLocations;
private Collection<Integer> poLocations;
/* Refuge Capacity requirements: 2020 */
private HashMap<Integer, Integer> refugeBedCapacity;
private HashMap<Integer, Integer> refugeRefillCapacity;
private Map<Integer, GMLRefuge> gmlRefuges;
private static final Logger LOG = Logger.getLogger(GisScenario.class);
/**
* Create an empty scenario.
*/
public GisScenario() {
refuges = new HashSet<Integer>();
hydrants = new HashSet<Integer>();
gasStations = new HashSet<Integer>();
fires = new HashSet<Integer>();
civLocations = new ArrayList<Integer>();
fbLocations = new ArrayList<Integer>();
pfLocations = new ArrayList<Integer>();
atLocations = new ArrayList<Integer>();
fsLocations = new ArrayList<Integer>();
poLocations = new ArrayList<Integer>();
acLocations = new ArrayList<Integer>();
/* Aftershock requirement:2013 */
aftershocks = new HashMap<Integer, Float>();
/* Refuge Capacity requirements: 2020 */
refugeBedCapacity = new HashMap<Integer, Integer>();
refugeRefillCapacity = new HashMap<Integer, Integer>();
gmlRefuges = new HashMap<Integer, GMLRefuge>();
}
/**
* Create a scenario from an XML document.
*
* @param doc The document to read.
* @throws ScenarioException If the scenario is invalid.
*/
public GisScenario(Document doc, Config config) throws ScenarioException {
this();
read(doc, config);
}
/**
* Read scenario data from an XML document.
*
* @param doc The document to read.
* @throws ScenarioException If the scenario is invalid.
*/
public void read(Document doc, Config config) throws ScenarioException {
hydrants.clear();
gasStations.clear();
refuges.clear();
fires.clear();
civLocations.clear();
fbLocations.clear();
pfLocations.clear();
atLocations.clear();
fsLocations.clear();
poLocations.clear();
acLocations.clear();
refugeBedCapacity.clear();
refugeRefillCapacity.clear();
Element root = doc.getRootElement();
if (!root.getQName().equals(SCENARIO_QNAME)) {
throw new ScenarioException(
"Scenario document has wrong root element: expecting " + SCENARIO_QNAME + "; not " + root.getQName());
}
for (Object next : root.elements(REFUGE_QNAME)) {
Element e = (Element) next;
refuges.add(Integer.parseInt(e.attributeValue(LOCATION_QNAME)));
/* capacity requirements:2020 */
int default_bedCapacity = config.getIntValue("gis.map.refuge.default-bedCapacity", 1000);
int default_refillCapacity = config.getIntValue("gis.map.refuge.default-refillCapacity", 1000);
int bedCapacity = e.attributeValue(BEDCAPACITY_QNAME) != null
? Integer.parseInt(e.attributeValue(BEDCAPACITY_QNAME))
: default_bedCapacity;
int refillCapacity = e.attributeValue(REFILLCAPACITY_QNAME) != null
? Integer.parseInt(e.attributeValue(REFILLCAPACITY_QNAME))
: default_refillCapacity;
refugeBedCapacity.put(Integer.parseInt(e.attributeValue(LOCATION_QNAME)), bedCapacity);
refugeRefillCapacity.put(Integer.parseInt(e.attributeValue(LOCATION_QNAME)), refillCapacity);
}
for (Object next : root.elements(HYDRANT_QNAME)) {
Element e = (Element) next;
hydrants.add(Integer.parseInt(e.attributeValue(LOCATION_QNAME)));
}
for (Object next : root.elements(GAS_STATION_QNAME)) {
Element e = (Element) next;
gasStations.add(Integer.parseInt(e.attributeValue(LOCATION_QNAME)));
}
for (Object next : root.elements(CIV_QNAME)) {
Element e = (Element) next;
civLocations.add(Integer.parseInt(e.attributeValue(LOCATION_QNAME)));
}
for (Object next : root.elements(FB_QNAME)) {
Element e = (Element) next;
fbLocations.add(Integer.parseInt(e.attributeValue(LOCATION_QNAME)));
}
for (Object next : root.elements(PF_QNAME)) {
Element e = (Element) next;
pfLocations.add(Integer.parseInt(e.attributeValue(LOCATION_QNAME)));
}
for (Object next : root.elements(AT_QNAME)) {
Element e = (Element) next;
atLocations.add(Integer.parseInt(e.attributeValue(LOCATION_QNAME)));
}
for (Object next : root.elements(FS_QNAME)) {
Element e = (Element) next;
fsLocations.add(Integer.parseInt(e.attributeValue(LOCATION_QNAME)));
}
for (Object next : root.elements(PO_QNAME)) {
Element e = (Element) next;
poLocations.add(Integer.parseInt(e.attributeValue(LOCATION_QNAME)));
}
for (Object next : root.elements(AC_QNAME)) {
Element e = (Element) next;
acLocations.add(Integer.parseInt(e.attributeValue(LOCATION_QNAME)));
}
for (Object next : root.elements(FIRE_QNAME)) {
Element e = (Element) next;
fires.add(Integer.parseInt(e.attributeValue(LOCATION_QNAME)));
}
/*
* Aftershock requirement:2013
*/
for (Object next : root.elements(AFTERSHOCK_QNAME)) {
Element e = (Element) next;
aftershocks.put(Integer.parseInt(e.attributeValue(TIME_QNAME)),
Float.parseFloat(e.attributeValue(INTENSITY_QNAME)));
}
}
/**
* Write scenario data to an XML document.
*
* @param doc The document to write to.
*/
public void write(Document doc) {
Element root = DocumentHelper.createElement(SCENARIO_QNAME);
doc.setRootElement(root);
for (int next : refuges) {
Element el = root.addElement(REFUGE_QNAME);
el.addAttribute(LOCATION_QNAME, String.valueOf(next));
el.addAttribute(BEDCAPACITY_QNAME, String.valueOf(refugeBedCapacity.get(next)));
// el.addAttribute(REFILLCAPACITY_QNAME,
// String.valueOf(refugeRefillCapacity.get(next)));
}
for (int next : fires) {
root.addElement(FIRE_QNAME).addAttribute(LOCATION_QNAME, String.valueOf(next));
}
for (int next : hydrants) {
root.addElement(HYDRANT_QNAME).addAttribute(LOCATION_QNAME, String.valueOf(next));
}
for (int next : gasStations) {
root.addElement(GAS_STATION_QNAME).addAttribute(LOCATION_QNAME, String.valueOf(next));
}
for (int next : civLocations) {
root.addElement(CIV_QNAME).addAttribute(LOCATION_QNAME, String.valueOf(next));
}
for (int next : fbLocations) {
root.addElement(FB_QNAME).addAttribute(LOCATION_QNAME, String.valueOf(next));
}
for (int next : fsLocations) {
root.addElement(FS_QNAME).addAttribute(LOCATION_QNAME, String.valueOf(next));
}
for (int next : pfLocations) {
root.addElement(PF_QNAME).addAttribute(LOCATION_QNAME, String.valueOf(next));
}
for (int next : poLocations) {
root.addElement(PO_QNAME).addAttribute(LOCATION_QNAME, String.valueOf(next));
}
for (int next : atLocations) {
root.addElement(AT_QNAME).addAttribute(LOCATION_QNAME, String.valueOf(next));
}
for (int next : acLocations) {
root.addElement(AC_QNAME).addAttribute(LOCATION_QNAME, String.valueOf(next));
}
root.addNamespace("scenario", SCENARIO_NAMESPACE_URI);
}
/**
* Apply this scenario to a world model.
*
* @param model The world model to alter.
* @param config The configuration.
* @throws ScenarioException if this scenario is invalid.
*/
public void apply(StandardWorldModel model, Config config) throws ScenarioException {
LOG.debug("Creating " + refuges.size() + " refuges");
for (int next : refuges) {
LOG.debug("Converting building " + next + " to a refuge");
Building b = (Building) model.getEntity(new EntityID(next));
if (b == null) {
throw new ScenarioException("Building " + next + " does not exist");
}
Refuge r = new Refuge(b);
if (refugeBedCapacity.containsKey(next))
r.setBedCapacity(refugeBedCapacity.get(next));
else
throw new ScenarioException("RefugeBedCapacity dose not contains " + next);
if (refugeRefillCapacity.containsKey(next))
r.setRefillCapacity(refugeRefillCapacity.get(next));
else
throw new ScenarioException("refugeRefillCapacity dose not contain " + next);
r.setOccupiedBeds(0);
r.setCapacity(0);// todo
r.setWaitingListSize(0);
model.removeEntity(b);
model.addEntity(r);
LOG.debug("Converted " + b + " into " + r);
}
for (int next : gasStations) {
LOG.debug("Converting building " + next + " to a gas station");
Building b = (Building) model.getEntity(new EntityID(next));
if (b == null) {
throw new ScenarioException("Building " + next + " does not exist");
}
GasStation r = new GasStation(b);
r.setImportance(5);
model.removeEntity(b);
model.addEntity(r);
LOG.debug("Converted " + b + " into " + r);
}
for (int next : hydrants) {
LOG.debug("Converting Road " + next + " to a hydrant");
Area area = (Area) model.getEntity(new EntityID(next));
if (area == null || !(area instanceof Road)) {
throw new ScenarioException("Road " + next + " does not exist");
}
Hydrant h = new Hydrant((Road) area);
model.removeEntity(area);
model.addEntity(h);
LOG.debug("Converted " + area + " into " + h);
}
LOG.debug("Igniting " + fires.size() + " fires");
for (int next : fires) {
LOG.debug("Igniting " + next);
Building b = (Building) model.getEntity(new EntityID(next));
if (b == null) {
throw new ScenarioException("Building " + next + " does not exist");
}
b.setIgnition(true);
}
int lastID = 0;
for (StandardEntity next : model) {
lastID = Math.max(lastID, next.getID().getValue());
}
LOG.debug("Creating " + fbLocations.size() + " fire brigades");
for (int next : fbLocations) {
EntityID id = new EntityID(next);
lastID = getNextId(model, config, lastID);
FireBrigade f = new FireBrigade(new EntityID(lastID));
setupAgent(f, id, model, config);
}
LOG.debug("Creating " + pfLocations.size() + " police forces");
for (int next : pfLocations) {
EntityID id = new EntityID(next);
lastID = getNextId(model, config, lastID);
PoliceForce p = new PoliceForce(new EntityID(lastID));
setupAgent(p, id, model, config);
}
LOG.debug("Creating " + atLocations.size() + " ambulance teams");
for (int next : atLocations) {
EntityID id = new EntityID(next);
lastID = getNextId(model, config, lastID);
AmbulanceTeam a = new AmbulanceTeam(new EntityID(lastID));
setupAgent(a, id, model, config);
}
LOG.debug("Creating " + fsLocations.size() + " fire stations");
for (int next : fsLocations) {
EntityID id = new EntityID(next);
LOG.debug("Coverting building " + next + " to a fire station");
Building b = (Building) model.getEntity(id);
if (b == null) {
throw new ScenarioException("Building " + next + " does not exist");
}
FireStation f = new FireStation(b);
model.removeEntity(b);
model.addEntity(f);
LOG.debug("Converted " + b + " into " + f);
}
LOG.debug("Creating " + poLocations.size() + " police offices");
for (int next : poLocations) {
EntityID id = new EntityID(next);
LOG.debug("Coverting building " + next + " to a police office");
Building b = (Building) model.getEntity(id);
if (b == null) {
throw new ScenarioException("Building " + next + " does not exist");
}
PoliceOffice p = new PoliceOffice(b);
model.removeEntity(b);
model.addEntity(p);
LOG.debug("Converted " + b + " into " + p);
}
LOG.debug("Creating " + acLocations.size() + " ambulance centres");
for (int next : acLocations) {
EntityID id = new EntityID(next);
LOG.debug("Coverting building " + next + " to an ambulance centre");
Building b = (Building) model.getEntity(id);
if (b == null) {
throw new ScenarioException("Building " + next + " does not exist");
}
AmbulanceCentre a = new AmbulanceCentre(b);
model.removeEntity(b);
model.addEntity(a);
LOG.debug("Converted " + b + " into " + a);
}
LOG.debug("Creating " + civLocations.size() + " civilians");
for (int next : civLocations) {
EntityID id = new EntityID(next);
lastID = getNextId(model, config, lastID);
Civilian c = new Civilian(new EntityID(lastID));
setupAgent(c, id, model, config);
}
}
private int getNextId(StandardWorldModel model, Config config, int lastId) {
boolean humanRandomId = config.getBooleanValue("senario.human.random-id", true);
if (humanRandomId) {
int newId;
do {
newId = config.getRandom().nextInt(Integer.MAX_VALUE);
} while (model.getEntity(new EntityID(newId)) != null);
return newId;
} else {
return lastId + 1;
}
}
/**
* Get the set of fire locations.
*
* @return The set of fire locations.
*/
public Set<Integer> getFires() {
return Collections.unmodifiableSet(fires);
}
/**
* Get the set of refuge locations.
*
* @return The set of refuge locations.
*/
public Set<Integer> getRefuges() {
return Collections.unmodifiableSet(refuges);
}
/**
* Get a refuge by ID.
*
* @param id The ID to look up.
* @return The refuge with that ID or null if the ID is not found.
*/
public GMLRefuge getRefuge(int id) {
return gmlRefuges.get(id);
}
/**
* Get the set of GMLRefuges.
*
* @return The set of GMLRefuges.
*/
public Map<Integer, GMLRefuge> getGMLRefuges() {
return gmlRefuges;
}
/**
* Get the HashMap of refuge bed capacity.
*
* @return The HashMap of refuge bed capacity.
*/
public HashMap<Integer, Integer> getRefugeBedCapacity() {
return refugeBedCapacity;
}
/**
* Get the HashMap of refuge refill capacity.
*
* @return The HashMap of refuge refill capacity.
*/
public HashMap<Integer, Integer> getRefugeRefillCapacity() {
return refugeRefillCapacity;
}
/**
* Get the set of GasStations locations.
*
* @return The set of GasStations locations.
*/
public Set<Integer> getGasStations() {
return Collections.unmodifiableSet(gasStations);
}
/**
* Get the set of hydrant locations.
*
* @return The set of hydrant locations.
*/
public Set<Integer> getHydrants() {
return Collections.unmodifiableSet(hydrants);
}
/**
* Get the list of civilian locations.
*
* @return The list of civilian locations.
*/
public Collection<Integer> getCivilians() {
return Collections.unmodifiableCollection(civLocations);
}
/**
* Get the list of fire brigade locations.
*
* @return The list of fire brigade locations.
*/
public Collection<Integer> getFireBrigades() {
return Collections.unmodifiableCollection(fbLocations);
}
/**
* Get the list of fire station locations.
*
* @return The list of fire station locations.
*/
public Collection<Integer> getFireStations() {
return Collections.unmodifiableCollection(fsLocations);
}
/**
* Get the list of police force locations.
*
* @return The list of police force locations.
*/
public Collection<Integer> getPoliceForces() {
return Collections.unmodifiableCollection(pfLocations);
}
/**
* Get the list of police office locations.
*
* @return The list of police office locations.
*/
public Collection<Integer> getPoliceOffices() {
return Collections.unmodifiableCollection(poLocations);
}
/**
* Get the list of ambulance team locations.
*
* @return The list of ambulance team locations.
*/
public Collection<Integer> getAmbulanceTeams() {
return Collections.unmodifiableCollection(atLocations);
}
/**
* Get the list of ambulance centre locations.
*
* @return The list of ambulance centre locations.
*/
public Collection<Integer> getAmbulanceCentres() {
return Collections.unmodifiableCollection(acLocations);
}
/**
* Set the set of fire locations.
*
* @param newLocations The new set of locations.
*/
public void setFires(Set<Integer> newLocations) {
fires.clear();
fires.addAll(newLocations);
}
/**
* Set the set of refuge locations.
*
* @param newLocations The new set of locations.
*/
public void setRefuges(Set<Integer> newLocations) {
refuges.clear();
refuges.addAll(newLocations);
}
/**
* Set the set of gas station locations.
*
* @param newLocations The new set of locations.
*/
public void setGasStations(Set<Integer> newLocations) {
gasStations.clear();
gasStations.addAll(newLocations);
}
/**
* Set the set of hydrant locations.
*
* @param newLocations The new set of locations.
*/
public void setHydrants(Set<Integer> newLocations) {
hydrants.clear();
hydrants.addAll(newLocations);
}
/**
* Set the list of civilian locations.
*
* @param newLocations The new list of locations.
*/
public void setCivilians(Collection<Integer> newLocations) {
civLocations.clear();
civLocations.addAll(newLocations);
}
/**
* Set the list of fire brigade locations.
*
* @param newLocations The new list of locations.
*/
public void setFireBrigades(Collection<Integer> newLocations) {
fbLocations.clear();
fbLocations.addAll(newLocations);
}
/**
* Set the list of fire station locations.
*
* @param newLocations The new list of locations.
*/
public void setFireStations(Collection<Integer> newLocations) {
fsLocations.clear();
fsLocations.addAll(newLocations);
}
/**
* Set the list of police force locations.
*
* @param newLocations The new list of locations.
*/
public void setPoliceForces(Collection<Integer> newLocations) {
pfLocations.clear();
pfLocations.addAll(newLocations);
}
/**
* Set the list of police office locations.
*
* @param newLocations The new list of locations.
*/
public void setPoliceOffices(Collection<Integer> newLocations) {
poLocations.clear();
poLocations.addAll(newLocations);
}
/**
* Set the list of ambulance team locations.
*
* @param newLocations The new list of locations.
*/
public void setAmbulanceTeams(Collection<Integer> newLocations) {
atLocations.clear();
atLocations.addAll(newLocations);
}
/**
* Set the list of ambulance centre locations.
*
* @param newLocations The new list of locations.
*/
public void setAmbulanceCentres(Collection<Integer> newLocations) {
acLocations.clear();
acLocations.addAll(newLocations);
}
/**
* Add a fire.
*
* @param location The new fire location.
*/
public void addFire(int location) {
fires.add(location);
}
/**
* Remove a fire.
*
* @param location The fire location to remove.
*/
public void removeFire(int location) {
fires.remove(location);
}
/**
* Add a refuge.
*
* @param location The new refuge location.
*/
public void addRefuge(int location) {
refuges.add(location);
}
public void addRefuge(int location, int bedCapacity, int refillCapacity) {
refuges.add(location);
refugeBedCapacity.put(location, bedCapacity);
refugeRefillCapacity.put(location, refillCapacity);
}
public void addRefuge(int location, int bedCapacity) {
refuges.add(location);
refugeBedCapacity.put(location, bedCapacity);
}
public void addGMLRefuge(GMLRefuge r) {
gmlRefuges.put(r.getID(), r);
}
/**
* Remove a refuge.
*
* @param location The refuge location to remove.
*/
public void removeRefuge(int location) {
refuges.remove(location);
if (refugeRefillCapacity.containsKey(location)) {
refugeRefillCapacity.remove(location);
}
if (refugeBedCapacity.containsKey(location)) {
refugeBedCapacity.remove(location);
}
gmlRefuges.remove(location);
}
/**
* Add a hydrant.
*
* @param location The new hydrant location.
*/
public void addHydrant(int location) {
hydrants.add(location);
}
/**
* Remove a hydrant.
*
* @param location The hydrant location to remove.
*/
public void removeHydrant(int location) {
hydrants.remove(location);
}
/**
* Remove a GasStation.
*
* @param location The GasStation location to remove.
*/
public void removeGasStation(int location) {
gasStations.remove(location);
}
/**
* Add a GasStation.
*
* @param location The new GasStation location.
*/
public void addGasStation(int location) {
gasStations.add(location);
}
/**
* Add a civilian.
*
* @param location The new civilian location.
*/
public void addCivilian(int location) {
civLocations.add(location);
}
/**
* Remove a civilian.
*
* @param location The civilian location to remove.
*/
public void removeCivilian(int location) {
civLocations.remove(location);
}
/**
* Add a fire brigade.
*
* @param location The new fire brigade location.
*/
public void addFireBrigade(int location) {
fbLocations.add(location);
}
/**
* Remove a fire brigade.
*
* @param location The fire brigade location to remove.
*/
public void removeFireBrigade(int location) {
fbLocations.remove(location);
}
/**
* Add a fire station.
*
* @param location The new fire station location.
*/
public void addFireStation(int location) {
fsLocations.add(location);
}
/**
* Remove a fire station.
*
* @param location The fire station location to remove.
*/
public void removeFireStation(int location) {
fsLocations.remove(location);
}
/**
* Add a police force.
*
* @param location The new police force location.
*/
public void addPoliceForce(int location) {
pfLocations.add(location);
}
/**
* Remove a police force.
*
* @param location The police force location to remove.
*/
public void removePoliceForce(int location) {
pfLocations.remove(location);
}
/**
* Add a police office.
*
* @param location The new police office location.
*/
public void addPoliceOffice(int location) {
poLocations.add(location);
}
/**
* Remove a police office.
*
* @param location The police office location to remove.
*/
public void removePoliceOffice(int location) {
poLocations.remove(location);
}
/**
* Add an ambulance team.
*
* @param location The new ambulance team location.
*/
public void addAmbulanceTeam(int location) {
atLocations.add(location);
}
/**
* Remove an ambulance team.
*
* @param location The ambulance team location to remove.
*/
public void removeAmbulanceTeam(int location) {
atLocations.remove(location);
}
/**
* Add an ambulance centre.
*
* @param location The new ambulance centre location.
*/
public void addAmbulanceCentre(int location) {
acLocations.add(location);
}
/**
* Remove an ambulance centre.
*
* @param location The ambulance centre location to remove.
*/
public void removeAmbulanceCentre(int location) {
acLocations.remove(location);
}
private void setupAgent(Human h, EntityID position, StandardWorldModel model, Config config)
throws ScenarioException {
Entity areaEntity = model.getEntity(position);
if (areaEntity == null) {
throw new ScenarioException("Area " + position + " does not exist");
}
if (!(areaEntity instanceof Area)) {
throw new ScenarioException("Entity " + position + " is not an area: " + areaEntity);
}
Area area = (Area) areaEntity;
h.setX(area.getX());
h.setY(area.getY());
h.setPosition(position);
h.setStamina(DEFAULT_STAMINA);
h.setHP(DEFAULT_HP);
h.setDamage(0);
h.setBuriedness(0);
h.setDirection(0);
h.setTravelDistance(0);
h.setPositionHistory(new int[0]);
if (h instanceof FireBrigade) {
((FireBrigade) h).setWater(config.getIntValue(WATER_QUANTITY_KEY));
}
model.addEntity(h);
LOG.debug("Created " + h);
}
@Override
public HashMap<Integer, Float> getAftershocks() {
return aftershocks;
}
}
package gis2;
/**
* Exception class for problems with scenarios.
*/
public class ScenarioException extends Exception {
/**
* Construct a scenario exception with no information.
*/
public ScenarioException() {
super();
}
/**
* Construct a scenario exception with an error message.
*
* @param msg The error message.
*/
public ScenarioException(String msg) {
super(msg);
}
/**
* Construct a scenario exception that was caused by another exception.
*
* @param cause The cause of this exception.
*/
public ScenarioException(Throwable cause) {
super(cause);
}
/**
* Construct a scenario exception with an error message and an underlying cause.
*
* @param msg The error message.
* @param cause The cause of this exception.
*/
public ScenarioException(String msg, Throwable cause) {
super(msg, cause);
}
}
\ No newline at end of file
package gis2.scenario;
/**
* Abstract base class for scenario editing functions.
*/
public abstract class AbstractFunction implements Function {
/** The editor instance. */
protected ScenarioEditor editor;
/**
* Construct an AbstractFunction.
*
* @param editor The editor instance.
*/
protected AbstractFunction(ScenarioEditor editor) {
this.editor = editor;
}
}
\ No newline at end of file
package gis2.scenario;
/**
* Abstract base class for scenario editing tools.
*/
public abstract class AbstractTool implements Tool {
/** The scenario editor instance. */
protected ScenarioEditor editor;
/**
* Construct an AbstractTool.
*
* @param editor The scenario editor instance.
*/
protected AbstractTool(ScenarioEditor editor) {
this.editor = editor;
}
}
\ No newline at end of file
package gis2.scenario;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.Shape;
import java.awt.geom.Ellipse2D;
import java.util.Map;
import maps.gml.GMLShape;
import maps.gml.view.Overlay;
import rescuecore2.misc.collections.LazyMap;
import rescuecore2.misc.gui.ScreenTransform;
/**
* Overlay for viewing agents in a scenario.
*/
public class AgentOverlay implements Overlay {
private static final int SIZE = 11;
private static final Color CIVILIAN_COLOUR = Color.GREEN;
private static final Color FIRE_BRIGADE_COLOUR = Color.RED;
private static final Color POLICE_FORCE_COLOUR = Color.BLUE;
private static final Color AMBULANCE_TEAM_COLOUR = Color.WHITE;
private static final int OFFSET = 7;
private ScenarioEditor editor;
/**
* Construct an AgentOverlay.
*
* @param editor The scenario editor.
*/
public AgentOverlay(ScenarioEditor editor) {
this.editor = editor;
}
@Override
public void render(Graphics2D g, ScreenTransform transform) {
// Count agents in each location
g.setFont(new Font(g.getFont().getName(), Font.BOLD, g.getFont().getSize()));
Map<Integer, Integer> civs = new LazyMap<Integer, Integer>() {
@Override
public Integer createValue() {
return 0;
}
};
Map<Integer, Integer> fbs = new LazyMap<Integer, Integer>() {
@Override
public Integer createValue() {
return 0;
}
};
Map<Integer, Integer> pfs = new LazyMap<Integer, Integer>() {
@Override
public Integer createValue() {
return 0;
}
};
Map<Integer, Integer> ats = new LazyMap<Integer, Integer>() {
@Override
public Integer createValue() {
return 0;
}
};
for (int next : editor.getScenario().getCivilians()) {
civs.put(next, civs.get(next) + 1);
}
for (int next : editor.getScenario().getFireBrigades()) {
fbs.put(next, fbs.get(next) + 1);
}
for (int next : editor.getScenario().getPoliceForces()) {
pfs.put(next, pfs.get(next) + 1);
}
for (int next : editor.getScenario().getAmbulanceTeams()) {
ats.put(next, ats.get(next) + 1);
}
// Now draw them
for (Map.Entry<Integer, Integer> next : civs.entrySet()) {
GMLShape shape = editor.getMap().getShape(next.getKey());
int count = next.getValue();
// int x = transform.xToScreen(shape.getCentreX());
// int y = transform.yToScreen(shape.getCentreY()) + CIV_OFFSET;
int x = transform.xToScreen(shape.getCentreX()) + OFFSET;
int y = transform.yToScreen(shape.getCentreY());
// g.drawString(count + " civs", x, y);
paint(g, x, y, CIVILIAN_COLOUR);
g.drawString(count + "", x, y);
}
for (Map.Entry<Integer, Integer> next : fbs.entrySet()) {
GMLShape shape = editor.getMap().getShape(next.getKey());
int count = next.getValue();
// int x = transform.xToScreen(shape.getCentreX());
// int y = transform.yToScreen(shape.getCentreY()) + FB_OFFSET;
int x = transform.xToScreen(shape.getCentreX());
int y = transform.yToScreen(shape.getCentreY()) - OFFSET;
// g.drawString(count + " fbs", x, y);
paint(g, x, y, FIRE_BRIGADE_COLOUR);
g.drawString(count + "", x, y);
}
for (Map.Entry<Integer, Integer> next : pfs.entrySet()) {
GMLShape shape = editor.getMap().getShape(next.getKey());
int count = next.getValue();
// int x = transform.xToScreen(shape.getCentreX());
// int y = transform.yToScreen(shape.getCentreY()) + PF_OFFSET;
int x = transform.xToScreen(shape.getCentreX());
int y = transform.yToScreen(shape.getCentreY()) + OFFSET;
// g.drawString(count + " pfs", x, y);
paint(g, x, y, POLICE_FORCE_COLOUR);
g.drawString(count + "", x, y);
}
for (Map.Entry<Integer, Integer> next : ats.entrySet()) {
GMLShape shape = editor.getMap().getShape(next.getKey());
int count = next.getValue();
// int x = transform.xToScreen(shape.getCentreX());
// int y = transform.yToScreen(shape.getCentreY()) + AT_OFFSET;
int x = transform.xToScreen(shape.getCentreX()) - OFFSET;
int y = transform.yToScreen(shape.getCentreY());
// g.drawString(count + " ats", x, y);
paint(g, x, y, AMBULANCE_TEAM_COLOUR);
g.drawString(count + "", x, y);
}
}
public void paint(Graphics2D g, int x, int y, Color color) {
Shape shape = new Ellipse2D.Double(x - SIZE / 4, y - SIZE, SIZE, SIZE);
g.setColor(color);
g.fill(shape);
g.draw(shape);
g.setColor(Color.black);
}
}
\ No newline at end of file
package gis2.scenario;
/**
* Exception for indicating the the user has cancelled an operation.
*/
public class CancelledByUserException extends Exception {
/**
* Constructor.
*/
public CancelledByUserException() {
}
}
\ No newline at end of file
package gis2.scenario;
import gis2.GisScenario;
import java.util.HashSet;
/**
* Function for removing all agents.
*/
public class ClearAgentsFunction extends AbstractFunction {
/**
* Construct a clear agents function.
*
* @param editor The editor instance.
*/
public ClearAgentsFunction(ScenarioEditor editor) {
super(editor);
}
@Override
public String getName() {
return "Remove agents";
}
@Override
public void execute() {
GisScenario s = editor.getScenario();
s.setFireBrigades(new HashSet<Integer>());
s.setFireStations(new HashSet<Integer>());
s.setPoliceForces(new HashSet<Integer>());
s.setPoliceOffices(new HashSet<Integer>());
s.setAmbulanceTeams(new HashSet<Integer>());
s.setAmbulanceCentres(new HashSet<Integer>());
editor.setChanged();
editor.updateOverlays();
}
}
\ No newline at end of file
package gis2.scenario;
import gis2.GisScenario;
import java.util.HashSet;
/**
* Function for removing all agents, fires, civilians and refuges.
*/
public class ClearAllFunction extends AbstractFunction {
/**
* Construct a clear all function.
*
* @param editor The editor instance.
*/
public ClearAllFunction(ScenarioEditor editor) {
super(editor);
}
@Override
public String getName() {
return "Remove all";
}
@Override
public void execute() {
GisScenario s = editor.getScenario();
s.setFireBrigades(new HashSet<Integer>());
s.setFireStations(new HashSet<Integer>());
s.setPoliceForces(new HashSet<Integer>());
s.setPoliceOffices(new HashSet<Integer>());
s.setAmbulanceTeams(new HashSet<Integer>());
s.setAmbulanceCentres(new HashSet<Integer>());
s.setCivilians(new HashSet<Integer>());
s.setFires(new HashSet<Integer>());
s.setRefuges(new HashSet<Integer>());
s.setGasStations(new HashSet<Integer>());
s.setHydrants(new HashSet<Integer>());
editor.setChanged();
editor.updateOverlays();
}
}
\ No newline at end of file
package gis2.scenario;
import gis2.GisScenario;
import java.util.HashSet;
/**
* Function for removing all fires.
*/
public class ClearFiresFunction extends AbstractFunction {
/**
* Construct a clear fires function.
*
* @param editor The editor instance.
*/
public ClearFiresFunction(ScenarioEditor editor) {
super(editor);
}
@Override
public String getName() {
return "Remove fires";
}
@Override
public void execute() {
GisScenario s = editor.getScenario();
s.setFires(new HashSet<Integer>());
editor.setChanged();
editor.updateOverlays();
}
}
\ No newline at end of file
package gis2.scenario;
/**
* Interface for a scenario editing function.
*/
public interface Function {
/**
* Get the name of this function.
*
* @return The name of the function.
*/
String getName();
/**
* Execute this function.
*/
void execute();
}
\ No newline at end of file
package gis2.scenario;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Insets;
/**
* A modified version of FlowLayout that allows containers using this Layout to
* behave in a reasonable manner when placed inside a JScrollPane
*
* @author Babu Kalakrishnan Modifications by greearb and jzd
*/
public class ModifiedFlowLayout extends FlowLayout {
public ModifiedFlowLayout() {
super(FlowLayout.LEFT);
}
public ModifiedFlowLayout(int align) {
super(align);
}
public ModifiedFlowLayout(int align, int hgap, int vgap) {
super(align, hgap, vgap);
}
public Dimension minimumLayoutSize(Container target) {
// Size of largest component, so we can resize it in
// either direction with something like a split-pane.
return computeMinSize(target);
}
public Dimension preferredLayoutSize(Container target) {
return computeSize(target);
}
private Dimension computeSize(Container target) {
synchronized (target.getTreeLock()) {
int hgap = getHgap();
int vgap = getVgap();
int w = target.getWidth();
// Let this behave like a regular FlowLayout (single row)
// if the container hasn't been assigned any size yet
if (w == 0) {
w = Integer.MAX_VALUE;
}
Insets insets = target.getInsets();
if (insets == null) {
insets = new Insets(0, 0, 0, 0);
}
int reqdWidth = 0;
int maxwidth = w - (insets.left + insets.right + hgap * 2);
int n = target.getComponentCount();
int x = 0;
int y = insets.top + vgap; // FlowLayout starts by adding vgap, so
// do that here too.
int rowHeight = 0;
for (int i = 0; i < n; i++) {
Component c = target.getComponent(i);
if (c.isVisible()) {
Dimension d = c.getPreferredSize();
if ((x == 0) || ((x + d.width) <= maxwidth)) {
// fits in current row.
if (x > 0) {
x += hgap;
}
x += d.width;
rowHeight = Math.max(rowHeight, d.height);
} else {
// Start of new row
x = d.width;
y += vgap + rowHeight;
rowHeight = d.height;
}
reqdWidth = Math.max(reqdWidth, x);
}
}
y += rowHeight;
y += insets.bottom;
return new Dimension(reqdWidth + insets.left + insets.right, y);
}
}
private Dimension computeMinSize(Container target) {
synchronized (target.getTreeLock()) {
int minx = Integer.MAX_VALUE;
int miny = Integer.MIN_VALUE;
boolean found_one = false;
int n = target.getComponentCount();
for (int i = 0; i < n; i++) {
Component c = target.getComponent(i);
if (c.isVisible()) {
found_one = true;
Dimension d = c.getPreferredSize();
minx = Math.min(minx, d.width);
miny = Math.min(miny, d.height);
}
}
if (found_one) {
return new Dimension(minx, miny);
}
return new Dimension(0, 0);
}
}
}
\ No newline at end of file
package gis2.scenario;
import gis2.GisScenario;
import java.awt.GridLayout;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextField;
import maps.gml.GMLShape;
/**
* Function for placing agents.
*/
public class PlaceAgentsFunction extends AbstractFunction {
private static final int TYPE_FIRE = 0;
private static final int TYPE_POLICE = 1;
private static final int TYPE_AMBULANCE = 2;
private static final int TYPE_CIVILIAN = 3;
private Random random;
/**
* Construct a place agents function.
*
* @param editor The editor instance.
*/
public PlaceAgentsFunction(ScenarioEditor editor) {
super(editor);
random = new Random();
}
@Override
public String getName() {
return "Place agents";
}
@Override
public void execute() {
JPanel panel = new JPanel(new GridLayout(3, 2));
JTextField numberField = new JTextField("1");
JComboBox<String> typeCombo = new JComboBox<String>(new String[] { "Fire", "Police", "Ambulance", "Civilian" });
JCheckBox buildingBox = new JCheckBox("In buildings?", false);
JCheckBox roadBox = new JCheckBox("In Roads?", true);
JPanel jp = new JPanel();
jp.add(buildingBox);
jp.add(roadBox);
panel.add(new JLabel("Type"));
panel.add(typeCombo);
panel.add(new JLabel("Number"));
panel.add(numberField);
panel.add(jp);
List<Integer> ids = new ArrayList<Integer>();
int type = -1;
List<GMLShape> all = new ArrayList<GMLShape>();
if (JOptionPane.showConfirmDialog(null, panel, "Add agents",
JOptionPane.OK_CANCEL_OPTION) == JOptionPane.OK_OPTION) {
try {
int number = Integer.parseInt(numberField.getText());
type = typeCombo.getSelectedIndex();
if (roadBox.isSelected())
all.addAll(editor.getMap().getRoads());
if (buildingBox.isSelected())
all.addAll(editor.getMap().getBuildings());
if (all.size() == 0) {
JOptionPane.showMessageDialog(null, "No Area to Place... Please choose In Road or Building...", "Error",
JOptionPane.ERROR_MESSAGE);
return;
}
for (int i = 0; i < number; ++i) {
ids.add(all.get(random.nextInt(all.size())).getID());
}
} catch (NumberFormatException e) {
e.printStackTrace();
}
}
GisScenario s = editor.getScenario();
switch (type) {
case TYPE_FIRE:
for (int id : ids) {
s.addFireBrigade(id);
}
break;
case TYPE_POLICE:
for (int id : ids) {
s.addPoliceForce(id);
}
break;
case TYPE_AMBULANCE:
for (int id : ids) {
s.addAmbulanceTeam(id);
}
break;
case TYPE_CIVILIAN:
for (int id : ids) {
s.addCivilian(id);
}
break;
default:
throw new IllegalArgumentException("Unexpected type: " + type);
}
editor.setChanged();
editor.updateOverlays();
}
}
\ No newline at end of file
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