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

init

parent 54f6cedf
package firesimulator.world;
import java.io.DataOutputStream;
import java.io.IOException;
import rescuecore.OutputBuffer;
public class FireBrigade extends MovingObject {
public static int REFILL_QUANTITY;
public static int REFILL_HYDRANT_QUANTITY;
public static int MAX_WATER_QUANTITY;
private int initialWaterQuantity;
private int waterQuantity;
private int waterUsed;
private boolean changed;
public FireBrigade(int id) {
super(id);
initialWaterQuantity = 0;
waterQuantity = 0;
waterUsed = 0;
changed = false;
}
public String getType() {
return "FIRE_BRIGADE";
}
public void setInitialWaterQuantity(int quantity) {
initialWaterQuantity = quantity;
waterQuantity = quantity;
}
public int getWaterQuantity() {
return waterQuantity;
}
public int getWaterUsed() {
return waterUsed;
}
public void setWaterQuantity(int quantity) {
waterQuantity = quantity;
changed = true;
}
public void addWaterUsed(int quantity) {
waterUsed += quantity;
}
public void nextCycle() {
waterUsed = 0;
changed = false;
}
public void reset() {
waterQuantity = initialWaterQuantity;
waterUsed = 0;
changed = false;
}
public boolean hasChanged() {
return changed;
}
public boolean refillInHydrant() {
//System.out.println(getID()+" Location is:"+getLocation()+" "+getLocation().getType());
if(!(getLocation().getType().equals("HYDRANT")))
return false;
for (Object next : world.getFirebrigades()) {
FireBrigade firebrigade = (FireBrigade)next;
if(firebrigade.getLocationID()==this.getLocationID()&&
firebrigade.getID()<this.getID())
return false;
}
if (getWaterQuantity() + REFILL_HYDRANT_QUANTITY> MAX_WATER_QUANTITY)
setWaterQuantity(MAX_WATER_QUANTITY);
else
setWaterQuantity(getWaterQuantity() + REFILL_HYDRANT_QUANTITY);
return true;
}
public boolean refillInRefuge() {
if (!(getLocation().isRefuge()))
return false;
int fr = ((Refuge) getLocation()).getFieryness();
if (fr == 3 || fr == 6 || fr == 7)
return false;
if (getWaterQuantity() + REFILL_QUANTITY > MAX_WATER_QUANTITY) {
setWaterQuantity(MAX_WATER_QUANTITY);
} else {
setWaterQuantity(getWaterQuantity() + REFILL_QUANTITY);
}
return true;
}
public boolean refill() {
// if (!getCurrentAction().equals("AK_REST")){
// return false;
// }unusable because the old simulator don't know the last action
if (getLocation() == null)
return false;
if(refillInHydrant())
return true;
if(refillInRefuge())
return true;
return false;
}
}
package firesimulator.world;
/**
* @author tn
*
* To change the template for this generated type comment go to
* Window>Preferences>Java>Code Generation>Code and Comments
*/
public class FireStation extends Building {
public FireStation(int id) {
super(id);
}
public String getType(){
return "FIRE_STATION";
}
public boolean isInflameable(){
return Building.FIRE_INFALMEABLE;
}
public int getFieryness(){
if(isInflameable())
return super.getFieryness();
return 0;
}
}
package firesimulator.world;
public class Hydrant extends StationaryObject {
public Hydrant(int id) {
super(id);
}
@Override
public String getType() {
return "HYDRANT";
}
}
package firesimulator.world;
/**
* @author tn
*
*/
public abstract class MovingObject extends RealObject {
private int stamina=0;
private int hp=0;
private int damage=0;
private int buriedness=0;
private int positionId=0;
private int positionExtra=0;
private RescueObject position;
protected World world = null;
private String currentAction;
private int currentActionLastChange;
private int x;
private int y;
public MovingObject(int id) {
super(id);
currentAction = "AK_REST";
currentActionLastChange = 0;
}
public void setWorld(World w) {
world = w;
}
public void setPositionId(int id){
positionId=id;
if (world != null) {
position = world.getObject(positionId);
}
}
public int getPositionId(){
return positionId;
}
public void setPositionExtra(int pos){
positionExtra=pos;
}
public int getPositionExtra(){
return positionExtra;
}
public void setPosition(){
}
public StationaryObject getLocation(){
if (position instanceof MovingObject)
return ((MovingObject) position).getLocation();
else if (position instanceof StationaryObject)
return (StationaryObject) position;
else
return null;
}
public int getLocationID(){
if (position instanceof MovingObject)
return ((MovingObject) position).getLocationID();
else if (position instanceof StationaryObject)
return position.id;
else
return -1;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
public void setX(int x) {
this.x = x;
}
public void setY(int y) {
this.y = y;
}
public void setStamina(int stamina){
this.stamina=stamina;
}
public void setHp(int hp){
this.hp=hp;
}
public void setDamage(int damage){
this.damage=damage;
}
public void setBuriedness(int buriedness){
this.buriedness=buriedness;
}
public String getCurrentAction() {
if(world.getTime()>currentActionLastChange)
return "AK_REST";
return currentAction;
}
public void setCurrentAction(String action) {
currentActionLastChange = world.getTime();
currentAction = action;
}
}
package firesimulator.world;
/**
* @author tn
*
* To change the template for this generated type comment go to
* Window>Preferences>Java>Code Generation>Code and Comments
*/
public abstract class Node extends StationaryObject {
int[] edgesID;
public Node(int id) {
super(id);
}
public void setEdges(int[] value){
edgesID=value;
}
}
package firesimulator.world;
/**
* @author tn
*
* To change the template for this generated type comment go to
* Window>Preferences>Java>Code Generation>Code and Comments
*/
public class PoliceForce extends MovingObject {
public PoliceForce(int id) {
super(id);
}
public String getType(){
return "POLICE_FORCE";
}
}
package firesimulator.world;
/**
* @author tn
*
* To change the template for this generated type comment go to
* Window>Preferences>Java>Code Generation>Code and Comments
*/
public class PoliceOffice extends Building {
public PoliceOffice(int id) {
super(id);
}
public String getType(){
return "POLICE_OFFICE";
}
public boolean isInflameable(){
return Building.POLICE_INFALMEABLE;
}
public int getFieryness(){
if(isInflameable())
return super.getFieryness();
return 0;
}
}
package firesimulator.world;
/**
* @author tn
*
* To change the template for this generated type comment go to
* Window>Preferences>Java>Code Generation>Code and Comments
*/
public abstract class RealObject extends RescueObject{
public RealObject(int id) {
super(id);
}
abstract public int getX();
abstract public int getY();
}
package firesimulator.world;
/**
* @author tn
*
* To change the template for this generated type comment go to
* Window>Preferences>Java>Code Generation>Code and Comments
*/
public class Refuge extends Building {
public Refuge(int id) {
super(id);
}
public String getType(){
return "REFUGE";
}
public boolean isRefuge() {
return true;
}
public boolean isInflameable(){
return Building.REFUGE_INFALMEABLE;
}
public int getFieryness(){
if(isInflameable())
return super.getFieryness();
return 0;
}
}
package firesimulator.world;
import org.apache.log4j.Logger;
/**
* @author tn
*
* To change the template for this generated type comment go to
* Window>Preferences>Java>Code Generation>Code and Comments
*/
public abstract class RescueObject implements WorldConstants {
int id;
public RescueObject(int id){
this.id=id;
}
public boolean isStationary(){
return false;
}
public int hashCode(){
return id;
}
public boolean equals( Object o ) {
if (!(o instanceof RescueObject)) {
return false;
}
return this.id == ((RescueObject)o).id;
}
public abstract String getType();
public int getID(){
return id;
}
}
package firesimulator.world;
import org.apache.log4j.Logger;
/**
* @author tn
*
* To change the template for this generated type comment go to
* Window>Preferences>Java>Code Generation>Code and Comments
*/
public class Road extends Edge {
private static final Logger LOG = Logger.getLogger(Road.class);
int width;
int block;
int linesToHead;
int linesToTail;
StreetNode head;
StreetNode tail;
public Road(int id) {
super(id);
head=null;
tail=null;
}
public void initialize(World world){
head=((StreetNode)world.getObject(getHeadID()));
tail=((StreetNode)world.getObject(getTailID()));
if(head==null||tail==null){
LOG.fatal("Error: head or tail of an streetnode did not exist. exiting");
System.exit(1);
}
}
public void setHead(StreetNode node){
head=node;
}
public void setTail(StreetNode node){
tail=node;
}
public StreetNode getHead(){
return head;
}
public StreetNode getTail(){
return tail;
}
public String getType(){
return "ROAD";
}
public void setWidth(int width){
this.width=width;
}
public void setBlock(int block){
this.block=block;
}
public void setLinesToHead(int lines){
linesToHead=lines;
}
public void setLinesToTail(int lines){
linesToTail=lines;
}
}
package firesimulator.world;
public abstract class StationaryObject extends RealObject {
private int x;
private int y;
public StationaryObject(int id) {
super(id);
}
public boolean isStationary(){
return true;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
public void setX(int x){
this.x=x;
}
public void setY(int y){
this.y=y;
}
public boolean isRefuge() {
return false;
}
}
package firesimulator.world;
public class StreetNode extends Node {
public StreetNode(int id) {
super(id);
}
public String getType(){
return "NODE";
}
}
package firesimulator.world;
import java.awt.Point;
import java.util.Iterator;
import org.apache.log4j.Logger;
/**
* @author tn
*
*/
public class Wall {
private static final Logger LOG = Logger.getLogger(Wall.class);
public static int MAX_SAMPLE_DISTANCE = 50000;
public int x1;
public int y1;
public int x2;
public int y2;
public Building owner;
public int rays;
public int hits;
public int selfHits;
public int strange;
public static float RAY_RATE = 0.01f;
public double length;
Point a;
Point b;
public Wall(int x1, int y1, int x2, int y2, Building owner) {
this.x1 = x1;
this.y1 = y1;
this.x2 = x2;
this.y2 = y2;
a = new Point(x1, y1);
b = new Point(x2, y2);
length = a.distance(b);
rays = (int) Math.ceil(length * RAY_RATE);
hits = 0;
this.owner = owner;
}
public boolean validate() {
return !(a.x == b.x && a.y == b.y);
}
public void findHits(World world) {
selfHits = 0;
strange = 0;
for (int emitted = 0; emitted < rays; emitted++) {
// creating ray
Point start = firesimulator.util.Geometry.getRndPoint(a, b);
if (start == null) {
strange++;
LOG.debug("strange -> " + a.x + "," + a.y + "/" + b.x + "," + b.y);
continue;
}
Point end = firesimulator.util.Geometry.getRndPoint(start, MAX_SAMPLE_DISTANCE);
// intersect
Wall closest = null;
double minDist = Double.MAX_VALUE;
for (Iterator it = world.allWalls.iterator(); it.hasNext();) {
Wall other = (Wall) it.next();
if (other == this)
continue;
Point cross = firesimulator.util.Geometry.intersect(start, end, other.a, other.b);
if (cross != null) {
if (cross.distance(start) < minDist) {
minDist = cross.distance(start);
closest = other;
}
}
}
if (closest == null) {
// Nothing was hit
continue;
}
if (closest.owner == this.owner) {
// The source building was hit
selfHits++;
}
if (closest != this && closest != null && closest.owner != owner) {
hits++;
Integer value = (Integer) owner.connectedBuildings.get(closest.owner);
int temp = 0;
if (value != null) {
temp = value.intValue();
}
temp++;
owner.connectedBuildings.put(closest.owner, Integer.valueOf(temp));
}
}
}
public String toString() {
return "wall (" + a.x + "," + a.y + ")-(" + b.x + "," + b.y + "), length=" + length + "mm, rays=" + rays;
}
}
\ No newline at end of file
package firesimulator.world;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.LinkedList;
import org.apache.log4j.Logger;
import firesimulator.util.Configuration;
/**
* @author tn
*
*/
public class World implements WorldConstants {
private static final Logger LOG = Logger.getLogger(World.class);
private Hashtable pool;
private Collection extinguishRequests;
private int time;
private Collection updatelist;
private Collection<Building> buildings;
private Collection firebrigades;
private int maxX;
private int maxY;
private int minX;
private int minY;
private double[][] airTemp;
public ArrayList[][] gridToBuilding;
public int SAMPLE_SIZE = 5000;
public float AIR_CAPACITY = 0.2f;
public float AIR_HEIGHT = 30;
public int CAPACITY;
public float maxDist;
private boolean isInitialized;
public Collection allWalls;
private Long hashValue;
private static World me;
public World() {
me = this;
hashValue = null;
pool = new Hashtable();
allWalls = new LinkedList();
extinguishRequests = new LinkedList();
updatelist = new LinkedList();
firebrigades = new HashSet();
buildings = new HashSet<Building>();
maxX = Integer.MIN_VALUE;
maxY = Integer.MIN_VALUE;
minX = Integer.MAX_VALUE;
minY = Integer.MAX_VALUE;
isInitialized = false;
}
public static World getWorld() {
return me;
}
public int getMaxX() {
return maxX;
}
public Iterator getExtinguishIterator() {
return extinguishRequests.iterator();
}
public void addExtinguishRequest(Object request) {
extinguishRequests.add(request);
}
public void clearExtinguishRequests() {
extinguishRequests.clear();
for (Iterator i = firebrigades.iterator(); i.hasNext();) {
FireBrigade fb = (FireBrigade) i.next();
fb.nextCycle();
}
}
public boolean isIntialized() {
return isInitialized;
}
public int getMaxY() {
return maxY;
}
public int getMinX() {
return minX;
}
public int getMinY() {
return minY;
}
private void loadVars() {
SAMPLE_SIZE = Integer.valueOf(Configuration.getValue("resq-fire.cell_size")).intValue();
Building.concreteBurning = Float.valueOf(Configuration.getValue("resq-fire.concrete_burning")).floatValue();
Building.concreteCapacity = Float.valueOf(Configuration.getValue("resq-fire.concrete_capacity")).floatValue();
Building.concreteEnergie = Float.valueOf(Configuration.getValue("resq-fire.concrete_energy")).floatValue();
Building.concreteIgnition = Float.valueOf(Configuration.getValue("resq-fire.concrete_ignition")).floatValue();
Building.concreteSpeed = Float.valueOf(Configuration.getValue("resq-fire.concrete_speed")).floatValue();
Building.steelBurning = Float.valueOf(Configuration.getValue("resq-fire.steel_burning")).floatValue();
Building.steelCapacity = Float.valueOf(Configuration.getValue("resq-fire.steel_capacity")).floatValue();
Building.steelEnergie = Float.valueOf(Configuration.getValue("resq-fire.steel_energy")).floatValue();
Building.steelIgnition = Float.valueOf(Configuration.getValue("resq-fire.steel_ignition")).floatValue();
Building.steelSpeed = Float.valueOf(Configuration.getValue("resq-fire.steel_speed")).floatValue();
Building.woodBurning = Float.valueOf(Configuration.getValue("resq-fire.wooden_burning")).floatValue();
Building.woodCapacity = Float.valueOf(Configuration.getValue("resq-fire.wooden_capacity")).floatValue();
Building.woodEnergie = Float.valueOf(Configuration.getValue("resq-fire.wooden_energy")).floatValue();
Building.woodIgnition = Float.valueOf(Configuration.getValue("resq-fire.wooden_ignition")).floatValue();
Building.woodSpeed = Float.valueOf(Configuration.getValue("resq-fire.wooden_speed")).floatValue();
Building.FIRE_INFALMEABLE = Boolean.valueOf(Configuration.getValue("resq-fire.fire_station_inflammable"))
.booleanValue();
Building.AMBULANCE_INFALMEABLE = Boolean.valueOf(Configuration.getValue("resq-fire.ambulance_center_inflammable"))
.booleanValue();
Building.POLICE_INFALMEABLE = Boolean.valueOf(Configuration.getValue("resq-fire.police_office_inflammable"))
.booleanValue();
Building.REFUGE_INFALMEABLE = Boolean.valueOf(Configuration.getValue("resq-fire.refuge_inflammable"))
.booleanValue();
Wall.RAY_RATE = Float.valueOf(Configuration.getValue("resq-fire.ray_rate")).floatValue();
Wall.MAX_SAMPLE_DISTANCE = Integer.valueOf(Configuration.getValue("resq-fire.max_ray_distance")).intValue();
FireBrigade.REFILL_QUANTITY = Integer.valueOf(Configuration.getValue("resq-fire.water_refill_rate")).intValue();
FireBrigade.REFILL_HYDRANT_QUANTITY = Integer.valueOf(Configuration.getValue("resq-fire.water_hydrant_refill_rate"))
.intValue();
FireBrigade.MAX_WATER_QUANTITY = Integer.valueOf(Configuration.getValue("resq-fire.water_capacity")).intValue();
}
public void initialize() {
LOG.info("World initialising");
loadVars();
allWalls.clear();
clearExtinguishRequests();
initializeBuildings();
// initializeRoads();
initializeAir();
igniteGISFires();
isInitialized = true;
LOG.info("World initialised");
}
private void initializeBuildings() {
for (Building b : buildings) {
int[] ap = b.getApexes();
for (int n = 0; n < ap.length; n++) {
if (ap[n] > maxX)
maxX = ap[n];
if (ap[n] < minX)
minX = ap[n];
n++;
if (ap[n] > maxY)
maxY = ap[n];
if (ap[n] < minY)
minY = ap[n];
}
b.initialize(this);
}
maxDist = (float) Math.sqrt(((maxX - minX) * (maxX - minX)) + ((maxY - minY) * (maxY - minY)));
initRayValues();
}
private void initRayValues() {
long hash = hash();
boolean loaded = false;
String fname = Configuration.getValue("resq-fire.rays.dir") + "/" + hash + ".rays";
try {
File f = new File(fname);
BufferedReader br = new BufferedReader(new FileReader(f));
float rayDens = Float.parseFloat(br.readLine());
String nl;
while (null != (nl = br.readLine())) {
int x = Integer.parseInt(nl);
int y = Integer.parseInt(br.readLine());
int quantity = Integer.parseInt(br.readLine());
Building[] bl = new Building[quantity];
float[] wght = new float[quantity];
for (int c = 0; c < quantity; c++) {
int ox = Integer.parseInt(br.readLine());
int oy = Integer.parseInt(br.readLine());
bl[c] = (Building) getBuilding(ox, oy);
wght[c] = Float.parseFloat(br.readLine());
}
Building b = getBuilding(x, y);
b.connectedBuilding = bl;
b.connectedValues = wght;
}
loaded = true;
LOG.info("loaded radiation sample file \"" + fname + "\"");
} catch (Exception e) {
LOG.warn("unable to load radiation sample file \"" + fname + "\", sampling:");
int n = 0;
long t1 = System.currentTimeMillis();
for (Building b : buildings) {
LOG.info("building " + b.getID() + " (" + (n++) + " of " + buildings.size() + ") ");
b.initWallValues(this);
long dt = System.currentTimeMillis() - t1;
dt = dt / n;
dt = dt * (buildings.size() - n);
long sec = dt / (1000);
long min = (sec / 60) % 60;
long hour = sec / (60 * 60);
sec = sec % 60;
LOG.info(" time left: ca. " + hour + ":" + min + ":" + sec);
}
}
try {
if (!loaded) {
File f = new File(fname);
f.createNewFile();
BufferedWriter bw = new BufferedWriter(new FileWriter(f));
bw.write(Wall.RAY_RATE + "\n");
for (Building b : buildings) {
bw.write(b.getX() + "\n");
bw.write(b.getY() + "\n");
bw.write(b.connectedBuilding.length + "\n");
for (int c = 0; c < b.connectedBuilding.length; c++) {
bw.write(b.connectedBuilding[c].getX() + "\n");
bw.write(b.connectedBuilding[c].getY() + "\n");
bw.write(b.connectedValues[c] + "\n");
}
}
bw.close();
LOG.info("wrote radiation sample file \"" + fname + "\"");
}
} catch (Exception e) {
LOG.error("error while writting radiation sample file \"" + fname + "\"", e);
}
}
private Building getBuilding(int x, int y) {
for (Building b : buildings) {
if (b.isBuilding(x, y))
return b;
}
LOG.error("parser error");
throw new NullPointerException();
}
public float getMaxDistance() {
return maxDist;
}
private void initializeAir() {
LOG.info("World width: " + (maxX - minX) + "mm");
LOG.info("World height: " + (maxY - minY) + "mm");
int xSamples = 1 + (maxX - minX) / SAMPLE_SIZE;
int ySamples = 1 + (maxY - minY) / SAMPLE_SIZE;
LOG.info("grid cell size=" + SAMPLE_SIZE + "mm, x*y=" + xSamples + "*" + ySamples + " = " + (xSamples * ySamples));
airTemp = new double[xSamples][ySamples];
for (int x = 0; x < airTemp.length; x++)
for (int y = 0; y < airTemp[x].length; y++)
airTemp[x][y] = 0;
CAPACITY = (int) (SAMPLE_SIZE * SAMPLE_SIZE * AIR_HEIGHT * AIR_CAPACITY) / 1000000;
// assign buildings
gridToBuilding = new ArrayList[xSamples][ySamples];
for (int x = 0; x < gridToBuilding.length; x++)
for (int y = 0; y < gridToBuilding[0].length; y++)
gridToBuilding[x][y] = new ArrayList();
for (Building b : buildings) {
b.findCells(this);
}
}
public double[][] getAirTemp() {
return airTemp;
}
public void setAirTemp(double[][] a) {
airTemp = a;
}
public void setAirCellTemp(int x, int y, double temp) {
airTemp[x][y] = temp;
}
public double getAirCellTemp(int x, int y) {
return airTemp[x][y];
}
public Collection<Building> getBuildings() {
return buildings;
}
public void addUpdate(RescueObject obj) {
updatelist.add(obj);
}
public void clearUpdates() {
updatelist.clear();
}
public Collection getUpdates() {
return updatelist;
}
public int countObjects() {
return pool.size();
}
public int getTime() {
return time;
}
public RescueObject getObject(int ID) {
return (RescueObject) pool.get(Integer.valueOf(ID));
}
public void putObject(RescueObject obj) {
pool.put(Integer.valueOf(obj.getID()), obj);
if (obj instanceof FireBrigade) {
firebrigades.add(obj);
}
if (obj instanceof Building) {
buildings.add((Building) obj);
}
// Moving objects need the world to get their position
if (obj instanceof MovingObject) {
((MovingObject) obj).setWorld(this);
}
}
public void setTime(int time) {
this.time = time;
}
public void reset() {
loadVars();
setTime(0);
resetAir();
for (Iterator i = buildings.iterator(); i.hasNext(); ((Building) i.next()).reset(this))
;
for (Iterator i = firebrigades.iterator(); i.hasNext(); ((FireBrigade) i.next()).reset())
;
igniteGISFires();
}
private void resetAir() {
for (int x = 0; x < airTemp.length; x++)
for (int y = 0; y < airTemp[x].length; y++)
airTemp[x][y] = 0;
}
public void igniteGISFires() {
for (Iterator it = getBuildings().iterator(); it.hasNext();) {
Building b = (Building) it.next();
if (b.getIgnition() != 0) {
b.ignite();
addUpdate(b);
}
}
}
public Collection getFirebrigades() {
return firebrigades;
}
public void setFirebrigades(Collection collection) {
firebrigades = collection;
}
public void printSummary() {
LOG.debug("objects total: " + countObjects());
}
public long hash() {
if (hashValue == null) {
long sum = 0;
for (Iterator i = buildings.iterator(); i.hasNext();) {
Building b = (Building) i.next();
int[] ap = b.getApexes();
for (int c = 0; c < ap.length; c++) {
if (Long.MAX_VALUE - sum <= ap[c]) {
sum = 0;
}
sum += ap[c];
}
}
hashValue = Long.valueOf(sum);
}
return hashValue.longValue();
}
}
\ No newline at end of file
package firesimulator.world;
/**
* @author tn
*
*/
public interface WorldConstants {
public final static int TYPE_NULL = 0;
public final static int TYPE_WORLD = 0x01;
public final static int TYPE_ROAD = 0x02;
public final static int TYPE_RIVER = 0x03;
public final static int TYPE_NODE = 0x04;
public final static int TYPE_RIVER_NODE = 0x05;
public final static int TYPE_BUILDING = 0x20;
public final static int TYPE_REFUGE = 0x21;
public final static int TYPE_FIRE_STATION = 0x22;
public final static int TYPE_AMBULANCE_CENTER = 0x23;
public final static int TYPE_POLICE_OFFICE = 0x24;
public final static int TYPE_CIVILIAN = 0x40;
public final static int TYPE_CAR = 0x41;
public final static int TYPE_FIRE_BRIGADE = 0x42;
public final static int TYPE_AMBULANCE_TEAM = 0x43;
public final static int TYPE_POLICE_FORCE = 0x44;
public final static int PROPERTY_NULL = 0;
public final static int PROPERTY_MIN = 1;
public final static int PROPERTY_START_TIME = 1;
public final static int PROPERTY_LONGITUDE = 2;
public final static int PROPERTY_LATITUDE = 3;
public final static int PROPERTY_WIND_FORCE = 4;
public final static int PROPERTY_WIND_DIRECTION = 5;
public final static int PROPERTY_HEAD = 6;
public final static int PROPERTY_TAIL = 7;
public final static int PROPERTY_LENGTH = 8;
public final static int PROPERTY_ROAD_KIND = 9;
public final static int PROPERTY_CARS_PASS_TO_HEAD = 10;
public final static int PROPERTY_CARS_PASS_TO_TAIL = 11;
public final static int PROPERTY_HUMANS_PASS_TO_HEAD = 12;
public final static int PROPERTY_HUMANS_PASS_TO_TAIL = 13;
public final static int PROPERTY_WIDTH = 14;
public final static int PROPERTY_BLOCK = 15;
public final static int PROPERTY_REPAIR_COST = 16;
public final static int PROPERTY_MEDIAN_STRIP = 17;
public final static int PROPERTY_LINES_TO_HEAD = 18;
public final static int PROPERTY_LINES_TO_TAIL = 19;
public final static int PROPERTY_WIDTH_FOR_WALKERS = 20;
public final static int PROPERTY_SIGNAL = 21;
public final static int PROPERTY_SHORTCUT_TO_TURN = 22;
public final static int PROPERTY_POCKET_TO_TURN_ACROSS = 23;
public final static int PROPERTY_SIGNAL_TIMING = 24;
public final static int PROPERTY_X = 25;
public final static int PROPERTY_Y = 26;
public final static int PROPERTY_EDGES = 27;
public final static int PROPERTY_FLOORS = 28;
public final static int PROPERTY_BUILDING_ATTRIBUTES = 29;
public final static int PROPERTY_IGNITION = 30;
public final static int PROPERTY_FIERYNESS = 31;
public final static int PROPERTY_BROKENNESS = 32;
public final static int PROPERTY_ENTRANCES = 33;
public final static int PROPERTY_BUILDING_CODE = 34;
public final static int PROPERTY_BUILDING_AREA_GROUND = 35;
public final static int PROPERTY_BUILDING_AREA_TOTAL = 36;
public final static int PROPERTY_BUILDING_APEXES = 37;
public final static int PROPERTY_POSITION = 38;
public final static int PROPERTY_POSITION_EXTRA = 39;
public final static int PROPERTY_DIRECTION = 40;
public final static int PROPERTY_POSITION_HISTORY = 41;
public final static int PROPERTY_STAMINA = 42;
public final static int PROPERTY_HP = 43;
public final static int PROPERTY_DAMAGE = 44;
public final static int PROPERTY_BURIEDNESS = 45;
public final static int PROPERTY_WATER_QUANTITY = 46;
public final static int PROPERTY_MAX = 46;
static final int AK_EXTINGUISH = 0x86;
static final int AK_REST = 0x80;
static final int AK_MOVE = 0x81;
static final int AK_LOAD = 0x82;
static final int AK_UNLOAD = 0x83;
static final int AK_SAY = 0x84;
static final int AK_TELL = 0x85;
// static final int AK_STRETCH = 0x87;
static final int AK_RESCUE = 0x88;
static final int AK_CLEAR = 0x89;
}
package firesimulator.world;
/**
* @author tn
*
* To change the template for this generated type comment go to
* Window>Preferences>Java>Code Generation>Code and Comments
*/
public class WorldInfo extends RescueObject {
public WorldInfo(int id) {
super(id);
}
public String getType(){
return "WORLD";
}
}
/*
* Last change: $Date: 2004/07/11 22:26:27 $
* $Revision: 1.30 $
*
* Copyright (c) 2004, The Black Sheep, Department of Computer Science, The University of Auckland
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
* Neither the name of The Black Sheep, The Department of Computer Science or The University of Auckland nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package rescuecore;
import java.io.*;
import rescuecore.debug.*;
import rescuecore.commands.*;
/**
This is the base class for all agents. This class handles messages from the server, provides a memory of the simulation environment and convenience methods for path planning etc. This class also enforces the message limits imposed by the robocup rescue rules.
<p>Agent implementations should provide at least one of the following three constructors:
<ol><li>A no-arg constructor - e.g. MyAgent()
<li>A String[] constructor - e.g. MyAgent(String[] args)
<li>A constructor that takes one or more String arguments - e.g. MyAgent(String arg1, String arg2)
</ol>
The reason for this is that the AgentSystem allows arguments to be passed to the Agent via the command line. When creating an instance of the agent it first looks for any constructor that accepts the right number of String arguments, followed by the String[] constructor. Failing that, the no-arg constructor will be used.
<p>
For example, assuming we have the three constructors mentioned above, if the command line provides two arguments then the AgentSystem will use the MyAgent(String arg1, String arg2) constructor. If only one argument is provided then the MyAgent(String[] args) constructor is used.
*/
public abstract class Agent extends RescueComponent {
private int[] agentTypes;
protected int type;
protected int id;
protected int timeStep;
protected Memory memory;
/*
private int numReceived, numSent;
private int sendMax,receiveMax;
*/
private int tempID;
private volatile boolean running;
private static int NEXT_ID = 0;
// private LogWriter logWriter;
// private File logFile;
// private int lastLogTime = -1;
protected boolean debug = false;
/**
Create a new agent of a particular type.
@param types The entity types this agent wants.
*/
protected Agent(int... types) {
this.agentTypes = types;
id = -1;
timeStep = -1;
this.type = -1;
// numReceived = 0;
// numSent = 0;
tempID = ++NEXT_ID;
// tempID = (int)(Math.random()*Integer.MAX_VALUE);
}
public final int getComponentType() {
return RescueConstants.COMPONENT_TYPE_AGENT;
}
public final Command generateConnectCommand() {
return new AKConnect(0,tempID,getClass().getName(),agentTypes);
}
protected void appendCommand(Command c){
super.appendCommand(c);
if(debug)
logObject(c);
}
public final boolean handleConnectOK(Command c) {
KAConnectOK ok = (KAConnectOK)c;
int requestID = ok.getRequestID();
if (requestID==tempID) {
id = ok.getAgentID();
System.out.println("Connect succeeded for "+tempID+". Kernel assigned id:"+id);
try {
RescueObject[] knowledge = ok.getKnowledge();
// Initialise
initialise(knowledge);
// Send AK_ACKNOWLEDGE
RescueMessage ack = new RescueMessage();
ack.append(new AKAcknowledge(requestID, id));
sendMessage(ack);
}
catch (Exception e) {
System.out.println(e);
e.printStackTrace();
}
timeStep = 0;
running = true;
return true;
}
else {
System.out.println("Received a KA_CONNECT_OK for agent "+requestID+", but I'm listening for a reply for "+tempID);
}
return false;
}
public final String handleConnectError(Command c) {
KAConnectError error = (KAConnectError)c;
int requestID = error.getRequestID();
String reason = error.getReason();
if (requestID==tempID)
return reason;
else
System.out.println("Received a KA_CONNECT_ERROR ("+reason+") for agent "+requestID+", but I'm listening for a reply for "+tempID);
return null;
}
public boolean isRunning() {
return running;
}
public void shutdown() {
running = false;
}
public final void handleMessage(Command c) {
// System.out.println("Handling "+c);
switch (c.getType()) {
case RescueConstants.KA_SENSE:
handleSense((KASense)c);
break;
case RescueConstants.KA_HEAR:
case RescueConstants.KA_HEAR_SAY:
case RescueConstants.KA_HEAR_TELL:
handleHear(c);
break;
case RescueConstants.KA_CONNECT_OK:
if (running) {
// Someone obviously didn't get our AK_ACKNOWLEDGE
KAConnectOK ok = (KAConnectOK)c;
int requestID = ok.getRequestID();
System.out.println(this+" just received a KA_CONNECT_OK to "+requestID+" - my tempID is "+tempID);
if (requestID==tempID) {
int newID = ok.getAgentID();
System.out.println("Old ID: "+id+", new ID: "+newID);
id = newID;
RescueMessage ack = new RescueMessage();
ack.append(new AKAcknowledge(requestID, id));
sendMessage(ack);
}
}
break;
default:
handleOtherMessage(c);
break;
}
logObject(c);
}
protected void handleOtherMessage(Command c) {
System.out.println("Timestep "+timeStep+": "+this+" received a weird command: "+Handy.getCommandTypeName(c.getType()));
}
/**
Handle a KA_SENSE message
@param c The KA_SENSE Command object
*/
private void handleSense(Command c) {
// System.out.println("Last timestep ("+timeStep+") "+this+" sent "+numSent+" messages and received "+numReceived);
KASense sense = (KASense)c;
// numSent = numReceived = 0;
try {
int newTimeStep = sense.getTime();
if (newTimeStep < timeStep) System.err.println(this+" just moved back in time! It was timestep "+timeStep+" and now it's timestep "+newTimeStep);
if (newTimeStep > timeStep+1) System.err.println(this+" just skipped ahead in time! It was timestep "+timeStep+" and now it's timestep "+newTimeStep);
timeStep = newTimeStep;
memory.update(sense); // Update the memory
}
catch (Exception e) {
e.printStackTrace();
}
// long start = System.currentTimeMillis();
sense();
// long end = System.currentTimeMillis();
// System.out.println("Sense took "+(end-start)+"ms for "+this);
flushCommands();
// Flush the log
DebugWriter.flush(this);
}
/**
Handle a KA_HEAR (or KA_HEAR_SAY, or KA_HEAR_TELL) message
@param hear The KA_HEAR Command object.
@see RescueConstants#KA_HEAR
@see RescueConstants#KA_HEAR_SAY
@see RescueConstants#KA_HEAR_TELL
*/
private void handleHear(Command c) {
KAHear hear = (KAHear)c;
int toID = hear.getToID();
int fromID = hear.getFromID();
int length = hear.getLength();
byte[] msg = hear.getData();
byte channel = hear.getChannel();
// System.out.println(Handy.getCommandTypeName(type)+" received by "+id+" from "+fromID+" - have already accepted "+numReceived+" messages of "+receiveMax+" this timestep");
// if (willListenHear(fromID) && canListen()) {
// System.out.println("Hear from "+fromID+" to "+toID+" on channel "+channel);
hear(fromID,msg,channel);
// ++numReceived;
// }
}
/*
private boolean canListen() {
if (numReceived < receiveMax) return true;
System.err.println("WARNING: "+this+" tried to receive too many messages in timestep "+timeStep+" (maximum="+receiveMax+")");
return false;
}
*/
private RescueObject me() {
return memory.lookup(id);
}
public String toString() {
if (!running) return "Unconnected agent. Temporary ID: "+tempID;
return Handy.getTypeName(type)+" ("+id+")";
}
/**
Get this agents Memory
@return The agents Memory
*/
public final Memory getMemory() {
return memory;
}
/**
Get the type of RescueObject that this agent represents
@see RescueConstants#TYPE_CIVILIAN
@see RescueConstants#TYPE_CAR
@see RescueConstants#TYPE_FIRE_BRIGADE
@see RescueConstants#TYPE_FIRE_STATION
@see RescueConstants#TYPE_POLICE_FORCE
@see RescueConstants#TYPE_POLICE_OFFICE
@see RescueConstants#TYPE_AMBULANCE_TEAM
@see RescueConstants#TYPE_AMBULANCE_CENTER
*/
public final int getType() {
return type;
}
/**
Get this agent's unique id, assigned by the kernel
*/
public final int getID() {
return id;
}
/**
Enable debugging
@param file The File to log information to.
*/
protected void enableDebug(String target) {
debug = true;
DebugWriter.register(this,this.toString(),target);
}
/**
Disable debugging
*/
protected void disableDebug() {
debug = false;
}
/**
* Writes an Update to a RescueObject to the log.
**/
// public final void logUpdate(rescuecore.debug.Update upd){
// if (debug) logWriter.addUpdate(upd, id, timeStep);
// }
/**
* Writes a transient Object to the log.
**/
public final void logObject(Object obj){
// if (debug) logWriter.addObject(obj,id,timeStep);
if (debug) DebugWriter.logUserObject(this,obj,timeStep);
}
/**
Initialise this agent. Subclasses that override this method should invoke super.initialise(knowledge,self) at some point.
@param knowledge This agent's knowledge of the world
@param self The RescueObject describing this agent
*/
protected void initialise(RescueObject[] knowledge) {
memory = generateMemory();
for (int i=0;i<knowledge.length;++i) {
memory.add(knowledge[i],0,RescueConstants.SOURCE_INITIAL);
}
type = me().getType();
if(debug){
DebugWriter.logInitialObjects(this,memory.getAllObjects());
memory.addMemoryListener(new DebugMemoryListener(this));
}
}
/**
Construct a new Memory object for use by this Agent. This method allows Agents to customise their choice of Memory object. The default implementation returns a {@link HashMemory}.
@return A new Memory object
*/
protected Memory generateMemory() {
return new HashMemory();
}
/**
Called after a KA_SENSE is received
*/
protected abstract void sense();
/**
Called after a KA_HEAR is received
@param from The agent that sent the message
@param msg The message body
@param channel The channel that this message was received on
*/
protected void hear(int from, byte[] msg, byte channel){}
// protected boolean hearTell(int from, byte[] msg){return false;}
// protected boolean hearSay(int from, byte[] msg){return false;}
// protected boolean willListenHear(int from) {return false;}
// protected boolean willListenHearSay(int from) {return false;}
// protected boolean willListenHearTell(int from) {return false;}
/**
How many messages can this agent send per timestep?
@return The maximum number of messages this agent can send per timestep
*/
// protected final int getMaxSend() {
// return sendMax;
// }
/**
How many messages can this agent receive per timestep?
@return The maximum number of messages this agent can receive per timestep
*/
// protected final int getMaxReceive() {
// return receiveMax;
// }
/**
Send an AK_SAY message to the kernel. If this agent has already send too many messages this timestep then this will be silently ignored
@param message The message
*/
protected final void say(byte[] message) {
// if (numSent < sendMax) {
appendCommand(Command.SAY(id,timeStep,message,message.length));
// ++numSent;
// }
}
/**
Send an AK_TELL message to the kernel. If this agent has already send too many messages this timestep then this will be silently ignored
@param message The message
*/
protected final void tell(byte[] message, byte channel) {
// if (numSent < sendMax) {
appendCommand(Command.TELL(id,timeStep,message,message.length,channel));
// ++numSent;
// }
}
}
/*
* Last change: $Date: 2004/05/04 03:09:37 $
* $Revision: 1.6 $
*
* Copyright (c) 2004, The Black Sheep, Department of Computer Science, The University of Auckland
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
* Neither the name of The Black Sheep, The Department of Computer Science or The University of Auckland nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package rescuecore;
import java.util.*;
/**
This is an implementation of Memory that stores the data in an array
*/
public class ArrayMemory extends Memory {
private final static int DEFAULT_MEMORY_SIZE = 3000;
private final static int DEFAULT_RESIZE_FACTOR = 1000;
protected RescueObject[] data;
private int dataSize;
private int resizeFactor;
/**
Construct a new empty memory
*/
public ArrayMemory() {
this(DEFAULT_MEMORY_SIZE,DEFAULT_RESIZE_FACTOR);
}
/**
Construct a new empty memory
@param size The initial size of the array
@param factor The amount to increase the array by if we run out of room
*/
public ArrayMemory(int size, int factor) {
data = new RescueObject[size];
resizeFactor = factor;
dataSize = 0;
}
public RescueObject lookup(int id) {
return id>=data.length?null:data[id];
}
public Collection<RescueObject> getAllObjects() {
Collection<RescueObject> result = new HashSet<RescueObject>(dataSize);
for (int i=0;i<data.length;++i) {
if (data[i]!=null) result.add(data[i]);
}
return result;
}
public void getObjectsOfType(Collection<RescueObject> result, int... types) {
for (int i=0;i<data.length;++i) {
RescueObject next = data[i];
int type = next.getType();
for (int nextType : types) {
if (type==nextType) {
result.add(next);
break;
}
}
}
}
/*
public RescueObject[] getObjectsOfInternalType(int type) {
List result = new ArrayList();
for (int i=0;i<data.length;++i) {
RescueObject next = data[i];
if (next!=null && (next.getInternalType() & type)!=0) result.add(next);
}
return (RescueObject[])result.toArray(new RescueObject[0]);
}
*/
public void add(RescueObject o, int timestamp, Object source) {
int id = o.getID();
if (id >= data.length) resizeMemory(id+1);
if (data[id]==null) ++dataSize;
data[id] = o;
super.add(o,timestamp,source);
}
public void remove(RescueObject o) {
int id = o.getID();
if (id >= data.length) resizeMemory(id+1);
data[id] = null;
super.remove(o);
}
private void resizeMemory(int sizeNeeded) {
RescueObject[] newData = new RescueObject[Math.max(sizeNeeded,data.length+resizeFactor)];
System.arraycopy(data,0,newData,0,data.length);
data = newData;
}
/**
* A deep clone of this memory.
* Any listeners on the original memory will not be registered on the new memory.
**/
public Memory copy() {
ArrayMemory m = new ArrayMemory(data.length,resizeFactor);
for(int i = 0; i< data.length; i++)
if(data[i] != null)
m.add(data[i].copy(),0,RescueConstants.SOURCE_UNKNOWN);
return m;
}
}
/*
* Last change: $Date: 2005/02/20 01:29:55 $
* $Revision: 1.15 $
*
* Copyright (c) 2004, The Black Sheep, Department of Computer Science, The University of Auckland
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
* Neither the name of The Black Sheep, The Department of Computer Science or The University of Auckland nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package rescuecore;
/**
This class encapsulates information about an array property
*/
public class ArrayProperty extends Property {
private int[] values;
private int numValues;
public ArrayProperty(int type) {
super(type);
values = new int[10];
numValues = 0;
}
public ArrayProperty(int type, int[] values) {
super(type);
this.values = new int[values.length];
numValues = values.length;
System.arraycopy(values,0,this.values,0,values.length);
lastUpdate = 0;
}
/*
public Property copy(){
ArrayProperty result = ArrayProperty(type,values,null);
result.numValues = numValues;
return result;
}
*/
public int[] getValues() {
int[] result = new int[numValues];
System.arraycopy(values,0,result,0,numValues);
return result;
}
public String getStringValue() {
StringBuffer result = new StringBuffer();
result.append("[");
for (int i=0;i<numValues;++i) {
result.append(values[i]);
if (i<numValues-1) result.append(",");
}
result.append("]");
return result.toString();
}
/**
Set the values of this property. The timestamp will also be updated. Note that this method does not check that the update is newer than the current value - it is up to the application to test for this.
@param newValues The new values
@param timestamp The timestamp of this update
@param source The source of this update
@return true if and only if the values were actually changed, i.e the new values are different from the old ones
@see #isOlderThan(int)
*/
public boolean setValues(int[] newValues, int timestamp, Object source) {
lastUpdate = timestamp;
lastUpdateSource = source;
if (!different(newValues)) return false;
values = new int[newValues.length];
System.arraycopy(newValues,0,values,0,values.length);
numValues = newValues.length;
return true;
}
/**
Update the values of this property. The timestamp will also be updated.
@param newValues The new values
@param timestamp The timestamp of this update
@param source The source of this update
@return true if and only if the values were actually changed, i.e the new values are different from the old ones and the new timestamp is greater than the old timestamp
@see #isOlderThan(int)
*/
public boolean updateValues(int[] newValues, int timestamp, Object source) {
if (timestamp <= lastUpdate) return false;
if (lastUpdate>=0 && !different(newValues)) return false;
lastUpdate = timestamp;
lastUpdateSource = source;
values = new int[newValues.length];
System.arraycopy(newValues,0,values,0,values.length);
numValues = newValues.length;
return true;
}
/**
Append a value to the list
@param value The new value
*/
public void append(int value) {
if (numValues == values.length) {
int[] newValues = new int[values.length+10];
System.arraycopy(values,0,newValues,0,values.length);
values = newValues;
}
values[numValues++] = value;
}
public void clear() {
numValues = 0;
}
/**
Merge another property into this one
@param p The Property to merge
@return true if and only if the value of this property was actually changed
*/
public boolean merge(Property p) {
if (p instanceof ArrayProperty) {
return updateValues(((ArrayProperty)p).values,p.lastUpdate,p.lastUpdateSource);
}
return false;
/*
if (p.lastUpdate <= this.lastUpdate) {
return false;
}
if (p instanceof ArrayProperty) {
lastUpdate = p.lastUpdate;
lastUpdateSource = p.lastUpdateSource;
ArrayProperty a = (ArrayProperty)p;
if (!different(a.values,a.numValues)) {
return false;
}
values = new int[a.values.length];
numValues = a.numValues;
System.arraycopy(a.values,0,values,0,values.length);
return true;
}
return false;
*/
}
/**
Write this property to an OutputBuffer
@param out The OutputBuffer to write this proprty to
*/
public void write(OutputBuffer out) {
out.writeInt(numValues);
for (int i=0;i<numValues;++i) {
out.writeInt(values[i]);
}
}
/**
Decode property data from an InputBuffer
@param in An InputBuffer to read data from
@param timestamp The timestamp of this update
@param source The source of this update
@return true if and only if a change was made
*/
public boolean read(InputBuffer in, int timestamp, Object source) {
// System.out.println("Timestep "+timestamp+": updating "+this+" from buffer");
int number = in.readInt();
int[] newValues = new int[number];
for (int i=0;i<number;++i) newValues[i] = in.readInt();
return updateValues(newValues,timestamp,source);
/*
if (lastUpdate < timestamp) {
changed = different(newValues);
if (changed) {
values = newValues;
numValues = number;
lastUpdate = timestamp;
lastUpdateSource = source;
}
}
return changed;
*/
}
private boolean different(int[] newValues) {
return different(newValues,newValues.length);
}
private boolean different(int[] newValues, int count) {
if (count != numValues) return true;
for (int i=0;i<numValues && i<count;++i) {
if (newValues[i]!=values[i]) return true;
}
return false;
}
}
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