package vnsim.vehicular.routePlan.cityRouting; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.File; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import java.util.ArrayList; import java.util.StringTokenizer; import vnsim.map.object.Globals; public class Server { // server is processing data x time faster public static final int kTimeCompression = 5; // threshold private static final double kCongestionThresh = 5.0; // congestion for every cross roads private ArrayList crCongestion; // list of segments with their actual congestion; private ArrayList updatedCongestion; // true if lastWeek was generated or loaded private boolean isLastWeekSet; public Server() { crCongestion = new ArrayList(); updatedCongestion = new ArrayList(); isLastWeekSet = false; } // mediate real time data and store it into lastWeek db private void updateLastWeekCongestions(int day, int hour) { if (hour == 0) { // store to the previews hour entry; if (day > 0) { day--; hour = 23; } else { return; } } else { hour--; } for (int i = 0; i < crCongestion.size(); i++) { crCongestion.get(i).updateLastWeekCongestion(day, hour); } } // make last week public by storing it in Globals.lastWeekCongestions private void publishLastWeekCongestions() { ArrayList> lastWeekCongestions = new ArrayList>(); for (int i = 0; i < crCongestion.size(); i++) { lastWeekCongestions.add(crCongestion.get(i).cloneLastWeek()); } Globals.lastWeekCongestions = lastWeekCongestions; isLastWeekSet = true; } // set real time data public void setCongestion(int crossIndex, int segmentIndex, int crtTime, Double congestion) { crCongestion.get(crossIndex).setCongestion(segmentIndex, congestion); if (isLastWeekSet) { int time = crtTime / kTimeCompression; // secs time = time / 3600; // hours int hour = time % 24; time = time / 24; // days int day = time % 7; Double lastCongestion = crCongestion.get(crossIndex) .getLastWeekCongestion(segmentIndex, day, hour); RoadSegmentCongestion rsc = new RoadSegmentCongestion(crossIndex, segmentIndex, congestion); if (isDifferent(congestion, lastCongestion)) { RoadSegmentCongestion existingRSC = null; for (int i = 0; i < updatedCongestion.size(); i++) { if (updatedCongestion.get(i).equals(rsc)) { existingRSC = updatedCongestion.get(i); break; } } if (existingRSC == null) { // entry does not exist -> add // congestion updatedCongestion.add(rsc); broadcastUpdatedCongestions(); } else { if (isDifferent(congestion, existingRSC.getCongestion())) { existingRSC.setCongestion(congestion); broadcastUpdatedCongestions(); } } } else { for (int i = 0; i < updatedCongestion.size(); i++) { if (updatedCongestion.get(i).equals(rsc)) { updatedCongestion.remove(i); broadcastUpdatedCongestions(); break; } } } } } private boolean isDifferent(Double current, Double previous) { return (Math.abs(current - previous) > kCongestionThresh); } private void broadcastUpdatedCongestions() { ArrayList toSend = new ArrayList(); for (int i = 0; i < updatedCongestion.size(); i++) { toSend.add(updatedCongestion.get(i).clone()); } IntersectionNode in; for (int i = 0; i < crCongestion.size(); i++) { in = crCongestion.get(i).getIntersectionNode(); in.updateCongestions(toSend); } } // IntersectionNode subscribes to the server for server replies public int addIntersectionNode(IntersectionNode inode) { crCongestion.add(new CrossRoadCongestion(inode)); return crCongestion.size() - 1; } // to be called after the Intersection nodes were registered to the server public void init() { if (!isLastWeekSet) { isLastWeekSet = loadCongestions(null); publishLastWeekCongestions(); } } public void step(int crtTime) { if (crtTime % kTimeCompression != 0) { return; } int time = crtTime / kTimeCompression; // seconds time = time / 3600; // hours int hour = time % 24; time = time / 24; // days int day = time % 7; time = crtTime / kTimeCompression; // for each hour if (time % 3600 == 0) { updateLastWeekCongestions(day, hour); updatedCongestion.clear(); broadcastUpdatedCongestions(); } // for each week //if (time % 604800 == 0) { if (time % 86400 == 0) { saveCongestions(null); publishLastWeekCongestions(); } } // save lastWeek congestion into filename file private boolean saveCongestions(String filename) { if (filename == null) { filename = System.getProperty("user.home") + File.separatorChar + "maps" + File.separatorChar + "rt" + File.separatorChar + Globals.scenarioName + ".cng.txt"; } BufferedWriter out = null; try { out = new BufferedWriter(new FileWriter(filename)); String str; StringTokenizer st; out.write("crosses_nb " + crCongestion.size()); out.newLine(); for (int i = 0; i < crCongestion.size(); i++) { out.write("cross " + i); out.newLine(); str = crCongestion.get(i).toString(); st = new StringTokenizer(str, "\n"); while (st.hasMoreTokens()) { out.write(st.nextToken()); out.newLine(); } } out.close(); } catch (IOException e) { System.out.println("Could not save congestion file " + filename); return false; } return true; } // load lastWeek congestion from filename private boolean loadCongestions(String filename) { if (filename == null) { filename = System.getProperty("user.home") + File.separatorChar + "maps" + File.separatorChar + "rt" + File.separatorChar + Globals.scenarioName + ".cng.txt"; } BufferedReader in = null; try { in = new BufferedReader(new FileReader(filename)); String line = ""; StringTokenizer st; int crossIndex, segmentIndex, day, hour; int crosses_nb, segments_nb; Double congestion; line = in.readLine(); while (line != null) { st = new StringTokenizer(line, " "); st.nextToken(); // crosses_nb crosses_nb = Integer.parseInt(st.nextToken()); for (crossIndex = 0; crossIndex < crosses_nb; crossIndex++) { line = in.readLine(); // cross i line = in.readLine(); st = new StringTokenizer(line, " "); st.nextToken(); // segments_nb; segments_nb = Integer.parseInt(st.nextToken()); for (segmentIndex = 0; segmentIndex < segments_nb; segmentIndex++) { line = in.readLine(); // segment i for (day = 0; day < 7; day++) { line = in.readLine(); st = new StringTokenizer(line, " "); for (hour = 0; hour < 24; hour++) { congestion = Double.parseDouble(st.nextToken()); crCongestion.get(crossIndex) .setLastWeekCongestion(segmentIndex, day, hour, congestion); } } } } line = in.readLine(); } in.close(); } catch (IOException e) { System.out.println("Could not load congestion file " + filename); return false; } return true; } }