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.Hashtable; import java.util.Iterator; import java.util.LinkedList; import java.util.HashSet; import firesimulator.simulator.ExtinguishRequest; import firesimulator.util.Configuration; import rescuecore.InputBuffer; import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.Log; /** * @author tn * */ public class World implements WorldConstants { private static final Log LOG = LogFactory.getLog(World.class); private Hashtable pool; private Collection extinguishRequests; private int time; private Collection updatelist; private Collection<Building> buildings; private Collection firebrigades; // private Collection streetNodes; // private Collection roads; 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 INITIAL_TEMP=20; 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>(); // streetNodes=new HashSet(); // roads=new HashSet(); 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=new Integer(Configuration.getValue("resq-fire.cell_size")).intValue(); Building.concreteBurning=new Float(Configuration.getValue("resq-fire.concrete_burning")).floatValue(); Building.concreteCapacity=new Float(Configuration.getValue("resq-fire.concrete_capacity")).floatValue(); Building.concreteEnergie=new Float(Configuration.getValue("resq-fire.concrete_energy")).floatValue(); Building.concreteIgnition=new Float(Configuration.getValue("resq-fire.concrete_ignition")).floatValue(); Building.concreteSpeed=new Float(Configuration.getValue("resq-fire.concrete_speed")).floatValue(); Building.steelBurning=new Float(Configuration.getValue("resq-fire.steel_burning")).floatValue(); Building.steelCapacity=new Float(Configuration.getValue("resq-fire.steel_capacity")).floatValue(); Building.steelEnergie=new Float(Configuration.getValue("resq-fire.steel_energy")).floatValue(); Building.steelIgnition=new Float(Configuration.getValue("resq-fire.steel_ignition")).floatValue(); Building.steelSpeed=new Float(Configuration.getValue("resq-fire.steel_speed")).floatValue(); Building.woodBurning=new Float(Configuration.getValue("resq-fire.wooden_burning")).floatValue(); Building.woodCapacity=new Float(Configuration.getValue("resq-fire.wooden_capacity")).floatValue(); Building.woodEnergie=new Float(Configuration.getValue("resq-fire.wooden_energy")).floatValue(); Building.woodIgnition=new Float(Configuration.getValue("resq-fire.wooden_ignition")).floatValue(); Building.woodSpeed=new Float(Configuration.getValue("resq-fire.wooden_speed")).floatValue(); Building.FIRE_INFALMEABLE=new Boolean(Configuration.getValue("resq-fire.fire_station_inflammable")).booleanValue(); Building.AMBULANCE_INFALMEABLE=new Boolean(Configuration.getValue("resq-fire.ambulance_center_inflammable")).booleanValue(); Building.POLICE_INFALMEABLE=new Boolean(Configuration.getValue("resq-fire.police_office_inflammable")).booleanValue(); Building.REFUGE_INFALMEABLE=new Boolean(Configuration.getValue("resq-fire.refuge_inflammable")).booleanValue(); Wall.RAY_RATE=new Float(Configuration.getValue("resq-fire.ray_rate")).floatValue(); Wall.MAX_SAMPLE_DISTANCE=new Integer(Configuration.getValue("resq-fire.max_ray_distance")).intValue(); FireBrigade.REFILL_QUANTITY=new Integer(Configuration.getValue("resq-fire.water_refill_rate")).intValue(); FireBrigade.MAX_WATER_QUANTITY=new Integer(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 initializeRoads() { for(Iterator i=streetNodes.iterator();i.hasNext();){ StreetNode sn=(StreetNode)i.next(); if(sn.getX()>maxX)maxX=sn.getX(); if(sn.getX()<minX)minX=sn.getX(); if(sn.getY()>maxY)maxY=sn.getY(); if(sn.getY()<minY)minY=sn.getY(); } for(Iterator i=roads.iterator();i.hasNext();((Road)i.next()).initialize(this)); } */ 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(new Integer(ID)); } public void putObject(RescueObject obj){ pool.put(new Integer(obj.getID()),obj); if (obj instanceof FireBrigade) { firebrigades.add(obj); } if (obj instanceof Building) { buildings.add((Building)obj); } // if (obj instanceof StreetNode) { // streetNodes.add(obj); // } // if (obj instanceof Road) { // roads.add(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 processChangeSet(InputBuffer data, int time){ setTime(time); int count = data.readInt(); for (int i = 0; i < count; ++i) { int id = data.readInt(); int propCount = data.readInt(); RescueObject obj = getObject(id); if (obj == null) { LOG.warn("Unknown object (id:"+id+")"); } for (int j = 0; j < propCount; ++j) { String propUrn = data.readString(); setProperty(data, obj, propUrn); } } } private void setProperty(InputBuffer data, RescueObject obj, String urn) { int size = data.readInt(); int[] val; if (urn.equals("SIGNAL_TIMING") || urn.equals("POSITION_HISTORY") || urn.equals("EDGES") || urn.equals("SHORTCUT_TO_TURN") || urn.equals("ENTRANCES") || urn.equals("BUILDING_APEXES") || urn.equals("POCKET_TO_TURN_ACROSS")) { val = new int[data.readInt()]; for (int i = 0; i < val.length; ++i) { val[i] = data.readInt(); } } else { val = new int[] {data.readInt()}; } if (obj != null) { obj.input(urn, val); } } private RescueObject createObject(String urn, int id){ RescueObject obj=null; if (urn.equals("BUILDING")) { obj=new Building(id); buildings.add((Building)obj); } else if (urn.equals("REFUGE")) { obj=new Refuge(id); buildings.add((Building)obj); } else if (urn.equals("WORLD")) { obj=new WorldInfo(id); } // else if (urn.equals("ROAD")) { // obj=new Road(id); // roads.add(obj); // } // else if (urn.equals("NODE")) { // obj=new StreetNode(id); // streetNodes.add(obj); // } else if (urn.equals("CIVILIAN")) { obj=new Civilian(id); } else if (urn.equals("CAR")) { obj=new Civilian(id); } else if (urn.equals("AMBULANCE_TEAM")) { obj=new AmbulanceTeam(id); } else if (urn.equals("FIRE_BRIGADE")) { obj=new FireBrigade(id); firebrigades.add(obj); } else if (urn.equals("POLICE_FORCE")) { obj=new PoliceForce(id); } else if (urn.equals("AMBULANCE_CENTRE")) { obj=new AmbulanceCenter(id); buildings.add((Building)obj); } else if (urn.equals("FIRE_STATION")) { obj=new FireStation(id); buildings.add((Building)obj); } else if (urn.equals("POLICE_OFFICE")) { obj=new PoliceOffice(id); buildings.add((Building)obj); } // Moving objects need the world to get their position if (obj instanceof MovingObject) ((MovingObject) obj).setWorld(this); return obj; } */ // public Collection getRoads() { // return roads; // } // public Collection getNodes() { // return streetNodes; // } 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 processCommands(InputBuffer data) { LOG.info("processing commands..."); data.readInt(); // Skip the size data.readInt(); // Skip the simulator ID int time = data.readInt(); setTime(time); int count = data.readInt(); for (int i = 0; i < count; ++i) { String cmd = data.readString(); int size = data.readInt(); if ("AK_EXTINGUISH".equals(cmd)) { LOG.debug("EXTINGUISH"); int agentID = data.readInt(); data.readInt(); // Skip the command time LOG.debug("fb.id="+agentID); FireBrigade source=(FireBrigade)getObject(agentID); source.setCurrentAction(cmd); int targetID = data.readInt(); Building target=(Building)getObject(targetID); int quantity=data.readInt(); ExtinguishRequest er=new ExtinguishRequest(source,target,quantity); extinguishRequests.add(er); } else if ("AK_MOVE".equals(cmd)) { int agentID = data.readInt(); LOG.debug("MOVE (id="+agentID+")"); MovingObject obj = (MovingObject)getObject(agentID); obj.setCurrentAction(cmd); data.skip(size - 4); } else { LOG.debug("Ignoring " + cmd); LOG.debug("Skipping " + size + " bytes"); data.skip(size); } } } */ 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=new Long(sum); } return hashValue.longValue(); } }