diff --git a/.classpath b/.classpath
index fd645472..fb2341ef 100644
--- a/.classpath
+++ b/.classpath
@@ -1,15 +1,16 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/config/plotting/gnuplot.properties b/config/plotting/gnuplot.properties
index 75c59ee3..889b275c 100644
--- a/config/plotting/gnuplot.properties
+++ b/config/plotting/gnuplot.properties
@@ -1,5 +1,5 @@
## GENERAL PLOT SETTINGS ###############
-GNUPLOT_PATH = /usr/bin/gnuplot
+GNUPLOT_PATH = C:\\Users\\Maurice\\gnuplot\\bin\\gnuplot.exe
GNUPLOT_TERMINAL = png large
GNUPLOT_EXTENSION = png
GNUPLOT_DIR = null
@@ -39,4 +39,4 @@ GNUPLOT_DEFAULT_PLOTSTYLE = linespoint
GNUPLOT_DEFAULT_NVL_ORDER = ascending
GNUPLOT_DEFAULT_NVL_ORDERBY = average
-GNUPLOT_DEFAULT_DIST_PLOTTYPE = distANDcdf
\ No newline at end of file
+GNUPLOT_DEFAULT_DIST_PLOTTYPE = distANDcdf
diff --git a/src/dna/graph/generators/traffic/CardinalDirection.java b/src/dna/graph/generators/traffic/CardinalDirection.java
new file mode 100644
index 00000000..53c6b19e
--- /dev/null
+++ b/src/dna/graph/generators/traffic/CardinalDirection.java
@@ -0,0 +1,5 @@
+package dna.graph.generators.traffic;
+
+public enum CardinalDirection {
+ NORTH, EAST,SOUTH,WEST
+}
diff --git a/src/dna/graph/generators/traffic/Crossroad.java b/src/dna/graph/generators/traffic/Crossroad.java
new file mode 100644
index 00000000..887c1402
--- /dev/null
+++ b/src/dna/graph/generators/traffic/Crossroad.java
@@ -0,0 +1,132 @@
+package dna.graph.generators.traffic;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+
+public class Crossroad {
+ private HashMap inputWays;
+ private HashMap outputWays;
+ private HashMap> inputToOutput;
+ private HashMap outputToInput;
+ private int crossroadID;
+ private DB db;
+
+ public Crossroad(int crossroadID, DB db){
+ this.inputToOutput=new HashMap<>();
+ this.crossroadID=crossroadID;
+ this.db=db;
+ this.outputToInput = new HashMap<>();
+ }
+ /**
+ * speichert die übergebene HashMap von Einfahrtswegen
+ * @param newInputWays
+ * @return Setzen = true, Ersetzen = False
+ */
+ public boolean setInputWays(HashMap newInputWays) {
+ boolean wasNull = inputWays==null;
+ inputWays=newInputWays;
+ return wasNull;
+ }
+ /**
+ * speichert die übergebene HashMap von Ausfahrtswegen
+ * @param newOutputWays
+ * @return Setzen = true, Ersetzen = False
+ */
+ public boolean setOutputWays(HashMap newOutputWays) {
+ boolean wasNull = outputWays==null;
+ outputWays=newOutputWays;
+ return wasNull;
+ }
+ /**
+ * Verbindet einen Einfahrtsweg mit einem Ausfahrtsweg
+ * @param inDir CardinalDirection des Einfahrtsweges
+ * @param outDir CardinalDirection des Ausfahrtsweges
+ * @return Wert neu gesetzt = true, Wert bereits vorhanden = false
+ */
+ public boolean setOutputWay(CardinalDirection inDir, CardinalDirection outDir){
+ if(!inputToOutput.containsKey(inDir)){
+ inputToOutput.put(inDir, new HashSet());
+ }
+ return inputToOutput.get(inDir).add(outDir);
+ }
+ /**
+ * liefert den Identifier eines Weges
+ * @param direction, Himmelsrichtung des Weges
+ * @param isInputWay, Einfahrtsweg = true, Ausfahrtsweg = false
+ * @return
+ */
+ public Integer getWay(CardinalDirection direction, boolean isInputWay) {
+ if(isInputWay)
+ return (inputWays.containsKey(direction)) ? inputWays.get(direction) : -1;
+ else
+ return (outputWays.containsKey(direction)) ? outputWays.get(direction) : -1;
+ }
+
+ /**
+ * verbindet die Ausfahrtswege mit den Einfahrtswegen benachbarter Kreuzungen
+ */
+ public void connectWays () {
+ for (CardinalDirection outDir : outputWays.keySet()) {
+ List connectedWays = db.getConnectedInputWays(getWay(outDir,false), crossroadID);
+ for (InputWay integers : connectedWays) {
+ if(integers!=null) {
+ outputToInput.put(outDir, integers);
+ }
+ }
+ }
+ }
+ /**
+ * liefert eine Menge von Verbindungen von Einfahrtswegen zu benachbarten Einfahrtswegen
+ * @return
+ */
+ public Set getConnections(){
+ Set connectedOutputways;
+ Set connectedCrossroads = new HashSet<>();
+ InputWay connection;
+ for (Map.Entry> innerConnection : inputToOutput.entrySet()) {
+ connectedOutputways = innerConnection.getValue();
+ for (CardinalDirection outputDirection : connectedOutputways) {
+ if(outputToInput.containsKey(outputDirection)) {
+ connection = outputToInput.get(outputDirection);
+ connectedCrossroads.add(new InputWayConnection(this.crossroadID, inputWays.get(innerConnection.getKey()),innerConnection.getKey(), connection.getWayID() , connection.getCrossroadID() ,outputDirection));
+ }
+ }
+ }
+ return connectedCrossroads;
+ }
+
+ /**
+ * Kontrollausgabe für die Einfahrtswege
+ */
+ public void printInputWays(){
+ System.out.println("InputWays von:\t"+this.crossroadID);
+ for (Map.Entry inputWay : inputWays.entrySet()) {
+ System.out.println(inputWay.getKey() +"\t"+inputWay.getValue());
+ }
+ }
+ /**
+ * Kontrollausgabe für die innere Verbindung von Wegen
+ */
+ public void printInput2Output(){
+ System.out.println("Input2Output von:\t"+this.crossroadID);
+ for (Map.Entry> inputWay : inputToOutput.entrySet()) {
+ System.out.println(inputWay.getKey());
+ for (CardinalDirection outputWay : inputWay.getValue()) {
+ System.out.println("\t"+outputWay);
+ }
+ }
+ }
+ /**
+ * Kontrollausgabe für die Ausfahrtswege
+ */
+ public void printOutputWays(){
+ System.out.println("OutputWays von:\t"+this.crossroadID);
+ for (Map.Entry outputWay : outputWays.entrySet()) {
+ System.out.println(outputWay.getKey() +"\t"+outputWay.getValue());
+ }
+ }
+}
diff --git a/src/dna/graph/generators/traffic/CrossroadWeight.java b/src/dna/graph/generators/traffic/CrossroadWeight.java
new file mode 100644
index 00000000..fe26b6ae
--- /dev/null
+++ b/src/dna/graph/generators/traffic/CrossroadWeight.java
@@ -0,0 +1,197 @@
+package dna.graph.generators.traffic;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class CrossroadWeight {
+ public int crossroadID;
+ private String crossroadName;
+ public HashMap inputWayWeights;
+ private HashMap inputWayMaxWeights;
+ private double maxCount;
+ private double maxLoad;
+ private double threshold;
+ private long timestamp;
+
+ public CrossroadWeight(int crossroadID,String crossroadName, double treshold){
+ this.crossroadID = crossroadID;
+ this.crossroadName = crossroadName;
+ this.inputWayWeights = new HashMap<>();
+ this.inputWayMaxWeights = new HashMap<>();
+ this.threshold = treshold;
+ this.timestamp=0;
+ }
+ /**
+ * liefert den Schwellwert für die Überlastung
+ * @return
+ */
+ public double getThreshold(){
+ return threshold;
+ }
+ /**
+ * liefert den Namen der Kreuzung im Format "A ..."
+ * @return
+ */
+ public String getCrossroadName(){
+ return crossroadName;
+ }
+ /**
+ * fügt Gewichte zu einem Einfahrtsweg hinzu
+ * @param osmWayID, OSM-ID des Einfahrtsweges
+ * @param weights, Gewichte des Einfahrtsweges
+ */
+ public void addWeightWay(int osmWayID, double[] weights) {
+ inputWayWeights.put(osmWayID, weights);
+ }
+ /**
+ * fügt die maximalen Gewichte des Einfahrtsweges hinzu
+ * @param osmWayID - OSM-ID des Einfahrtsweges
+ * @param maxWeights
+ */
+ public void setMaxWeightWay(int osmWayID, double[] maxWeights) {
+ inputWayMaxWeights.put(osmWayID, maxWeights);
+ }
+
+ /**
+ * liefert die maximalen Gewichte des Einfahrtsweges
+ * @param osmWayID, OSM-ID des Einfahrtsweges
+ * @return
+ */
+ public double[] getMaxWeightWay(int osmWayID) {
+ return inputWayMaxWeights.get(osmWayID);
+ }
+
+ /**
+ * setzt den Zeitstempel, für den das letzte Gewicht vorliegt
+ * @param timestampInit
+ */
+ public void setTimestamp(long timestampInit){
+ this.timestamp = timestampInit;
+ }
+
+ /**
+ * liefert den Zeitstempel, für den das letzte Gewicht vorliegt
+ * @return
+ */
+ public long getTimestamp(){
+ return timestamp;
+ }
+
+ /**
+ * setzt die maximalen Gewichte für die gesamte Kreuzung
+ * @param maxWeights
+ */
+ public void setMaxWeight(double[] maxWeights) {
+ this.maxCount=maxWeights[0];
+ this.maxLoad=maxWeights[1];
+ }
+
+ /**
+ * liefert die maximalen Werte für die gesamte Kreuzung
+ * @return
+ */
+ public double[] getMaxWeight() {
+ return new double[] {maxCount,maxLoad};
+ }
+
+ /**
+ * verteilt das Knotengewicht gleichmäßig auf die Einfahrtswege, wird bei der Simulation verwendet
+ * @param count
+ * @param load
+ */
+ public void resetInputWayWeight(double count, double load){
+ double numOfInputWays = inputWayWeights.keySet().size();
+ double count_value = count/numOfInputWays;
+ double load_value = load/numOfInputWays;
+ for (Map.Entry entry : inputWayWeights.entrySet()) {
+ entry.setValue(new double[]{count_value,load_value,(count_value/inputWayMaxWeights.get(entry.getKey())[0])*100});
+ }
+ }
+
+ /**
+ * berechnet das Gewicht des Kreuzungsknotens
+ * Index 0 - count
+ * Index 1 - load
+ * Index 2 - count/maxcount
+ * @return 3D-double
+ */
+ public double[] getWeight(){
+ double[] sum = new double[3];
+ for (double[] entry : inputWayWeights.values()) {
+ sum[0]+=entry[0];
+ sum[1]+=entry[1];
+ }
+ int numOfinputWays = inputWayWeights.size();
+ if(numOfinputWays>0){
+ sum[1]/=numOfinputWays;
+ }
+
+ // Normierte Werte
+ if(maxCount>0)
+ sum[2]=(sum[0]/maxCount)*100;
+ else
+ sum[2]=0;
+
+ return sum;
+ }
+
+ /**
+ * liefert alle Einfahrtswege, deren Gewicht den Schwellwert überschritten hat
+ * @return
+ */
+ public HashMap getOverladedEdges() {
+ HashMap result = new HashMap<>();
+ for (Map.Entry inputWay : inputWayWeights.entrySet()) {
+ if(inputWay.getValue()[2] >threshold){
+ result.put(inputWay.getKey(), inputWay.getValue());
+ }
+ }
+ return result;
+ }
+
+ /**
+ * liefert alle Einfahrtswege mit ihren Gewichten
+ * @return
+ */
+ public HashMap getWayWeights(){
+ return inputWayWeights;
+ }
+
+ /**
+ * addiert die übergebenen Gewichte auf die Gewichte der Einfahrtswege
+ * @param wayWeights
+ * @return
+ */
+ public boolean addWeights(HashMap wayWeights){
+ for (Integer keys : wayWeights.keySet()) {
+ if(!inputWayWeights.containsKey(keys))
+ return false;
+ }
+ for (Map.Entry entry : wayWeights.entrySet()) {
+ double[] value = inputWayWeights.get(entry.getKey());
+ double[] newValue = entry.getValue();
+ for (int i = 0; i < value.length; i++) {
+ value[i]+=newValue[i];
+ }
+ inputWayWeights.put(entry.getKey(), value);
+ }
+ return true;
+ }
+
+ /**
+ * bildet den Durchschnitt der aufsummierten Gewichte
+ * @param divisor, Anzahl der Batches/Tage über die aggregiert wurde
+ */
+ public void divWays(int divisor){
+ if(divisor>0){
+ for (Map.Entry entry : inputWayWeights.entrySet()) {
+ double[] value = entry.getValue();
+ for (int i = 0; i < value.length; i++) {
+ value[i] = value[i]/divisor;
+ }
+ inputWayWeights.put(entry.getKey(), value);
+ }
+ }
+ }
+
+}
diff --git a/src/dna/graph/generators/traffic/DB.java b/src/dna/graph/generators/traffic/DB.java
new file mode 100644
index 00000000..1f2932f7
--- /dev/null
+++ b/src/dna/graph/generators/traffic/DB.java
@@ -0,0 +1,1545 @@
+package dna.graph.generators.traffic;
+
+
+import java.io.BufferedReader;
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.io.IOException;
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.sql.Timestamp;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Random;
+import java.util.Set;
+
+import org.joda.time.DateTime;
+
+import dna.graph.datastructures.GraphDataStructure;
+import dna.graph.edges.Edge;
+import dna.graph.nodes.INode;
+import dna.graph.nodes.Node;
+
+public class DB {
+ private static Connection con = null;
+ private static String dbHost = "127.0.0.1"; // Hostname
+ private static String dbPort = "3306"; // Port -- Standard: 3306
+ private static String dbName = "dbName"; // Datenbankname
+ private static String dbUser = "dbUser"; // Datenbankuser
+ private static String dbPass = "dbPass"; // Datenbankpasswort
+
+
+ private GraphDataStructure gds;
+ public DateTime initDateTime;
+ private HashMap maxValuesCrossroad;
+ private HashMap maxValuesInputWays;
+ private HashMap maxValuesSensors;
+ private HashMap sensorModelNodes;
+ private HashMap crossroadModelNodes;
+ public HashMap inputWays;
+ public HashMap inputWaysToID;
+ public HashMap> inputWayConnections; //Key: ToCrossroad,ToWay - Value: List
+
+ private double treshold;
+ private HashMap disabledEdges;
+ private HashMap> disabledEdgesInputWay;
+ private boolean dummyMax;
+ private boolean backupWays = false;
+ private boolean improvedMax = true;
+ private boolean newMaxValues = false;
+
+ /**
+ * Konstruktur der Datenbank, die Login-Daten werden entweder aus einer Txt-Datei gelesen,
+ * oder falls diese nicht vorhanden ist, aus den Parametern übernommen.
+ * @param gds, Datenstruktur, welcher der Verwendung von DNA zugrunde liegt (für Knotentypen, Kantentypen ..)
+ * @param initTDateTime, Startzeitpunkt für die Modi mit realen Daten
+ * @param daySelection, Boolean-Array mit 7 Einträgen für die Wochentage
+ * @param timeRange, Intervalllänge für den Tages und Aggregationsmodus
+ * @param treshold, Schwellwert für die Überlastungserkennung
+ * @param trafficUpdate, statische Daten für den Simulationsmodus
+ * @param dummyMax, Verwendung von synthetischen Max-Werten oder realen Max-Werten
+ */
+ public DB(GraphDataStructure gds, DateTime initTDateTime, boolean[] daySelection, double treshold,boolean dummyMax, boolean newMaxValues) {
+ try {
+ FileReader fr = new FileReader("db.txt");
+ BufferedReader br = new BufferedReader(fr);
+ String line = br.readLine();
+ String[] values;
+ while (line != null) {
+ values = line.split(" ");
+ if(values.length != 2)
+ System.out.println("Falsche Anzahl an Parametern");
+ switch (values[0]) {
+ case "dbHost":
+ dbHost = values[1];
+ break;
+ case "dbPort":
+ dbPort = values[1];
+ break;
+ case "dbName":
+ dbName = values[1];
+ break;
+ case "dbUser":
+ dbUser = values[1];
+ break;
+ case "dbPass":
+ dbPass = values[1];
+ break;
+ default:
+ break;
+ }
+ line = br.readLine();
+ }
+ br.close();
+ System.out.println("Datenbank-Logindaten aus Datei gelesen");
+ } catch (FileNotFoundException e1) {
+ System.out.println("Keine Daten für Datenbank gefunden - verwende Dummy-Daten");
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ try {
+ System.out.println("Versuche zur Datenbank zu verbinden");
+ Class.forName("com.mysql.jdbc.Driver");
+ con = DriverManager.getConnection("jdbc:mysql://"+dbHost+":"+dbPort+"/"+dbName,dbUser,dbPass);
+ } catch (ClassNotFoundException e) {
+ System.out.println("Treiber nicht gefunden");
+ } catch (SQLException e) {
+ System.out.println("Verbindung nicht moglich");
+ System.out.println("SQLException: " + e.getMessage());
+ System.out.println("SQLState: " + e.getSQLState());
+ System.out.println("VendorError: " + e.getErrorCode());
+ }
+ this.gds = gds;
+ this.initDateTime = initTDateTime;
+
+ this.maxValuesInputWays = new HashMap<>();
+ this.maxValuesCrossroad = new HashMap<>();
+ this.maxValuesSensors = new HashMap<>();
+ this.sensorModelNodes = new HashMap<>();
+ this.crossroadModelNodes = new HashMap<>();
+ this.inputWayConnections = new HashMap<>();
+ this.inputWaysToID = new HashMap<>();
+ this.inputWays= new HashMap<>();
+ this.treshold = treshold;
+ this.disabledEdges = new HashMap<>();
+ this.disabledEdgesInputWay = new HashMap<>();
+ this.dummyMax = dummyMax;
+ this.newMaxValues = newMaxValues;
+ getInputWays();
+ getMaximalWeightCrossroad();
+ getMaximalWeightInputWay();
+ getMaximalWeightSensor();
+ loadFromWays();
+
+ }
+ /**
+ * schreibt das maximale Gewicht für eine Kreuzung in die Tabelle mw_MaxValues_Crossroad,
+ * die Daten sind auf 1x Stepsize berechnet, ACHTUNG: Datenbankabfrage nicht mehr durchführbar, da zu viele Daten
+ * @param crossroadID
+ * @return
+ */
+ public double[] writeMaximalWeightsCrossroad(int crossroadID) {
+ System.out.println("Schreibe reale Maximalwerte (Dauer 1x stepSize) für Kreuzung mit ID " +crossroadID);
+ if(crossroadID==43 || crossroadID == 44 || crossroadID == 63 || crossroadID == 99 || crossroadID == 147 || crossroadID == 93) {
+ return new double[]{0.0,0.0};
+ }
+ String crossroadName = getCrossroadName(crossroadID);
+ double count = 0;
+ double load = 0;
+ ResultSet rs;
+ String selectStmt = null;
+ try {
+ String sensorsOfCrossroad = "SELECT ID AS SENSOR_ID, CSVOFFSET, REALNAME, CROSSROAD_ID FROM jee_crmodel_SensorDim S WHERE S.CROSSROAD_ID="+crossroadID;
+ String sensorWaysOfCrossroad = "SELECT * FROM mw_SensorWays SW WHERE crossroadID = "+crossroadID+" AND wayID IS NOT NULL";
+ String eventData = "SELECT DATETIME, ID AS EVENT_ID, cr_count AS COUNT_VALUE, cr_load AS LOAD_VALUE, RE.CSVOFFSET FROM jee_trafficlight_rawevents RE WHERE CROSSROAD = '"+crossroadName+"'";
+ String crossroadWeight = "SELECT EVENT_ID,DATETIME,COUNT_VALUE, LOAD_VALUE,sensorName as SENSOR_NAME, sensorID as SENSOR_ID, SENSORS.CSVOFFSET, crossroadID as CROSSROAD_ID, crossroadName as CROSSROAD_NAME FROM (SELECT sensorID,sensorName, CSVOFFSET,crossroadID,crossroadName FROM ("+sensorsOfCrossroad+") SENSORS RIGHT JOIN ("+sensorWaysOfCrossroad+") SENSORS_MAPPED ON SENSORS.SENSOR_ID = SENSORS_MAPPED.sensorID) SENSORS LEFT JOIN ("+eventData+") EVENT_DATA on SENSORS.CSVOFFSET = EVENT_DATA.CSVOFFSET";
+ selectStmt = "SELECT * FROM (SELECT SUM(COUNT_VALUE) AS ANZAHL, SUM(LOAD_VALUE)/COUNT(LOAD_VALUE) as BELEGUNG, DATETIME,CROSSROAD_ID, CROSSROAD_NAME FROM (SELECT CROSSROAD_WEIGHT.*,mw_SensorConnection.FRONT_BACK,mw_SensorConnection.FROM_DIRECTION, mw_SensorConnection.TO_LEFT,mw_SensorConnection.TO_STRAIGHT,mw_SensorConnection.TO_RIGHT FROM ("+crossroadWeight+") CROSSROAD_WEIGHT JOIN mw_SensorConnection ON CROSSROAD_WEIGHT.SENSOR_ID = mw_SensorConnection.SENSOR_ID) RESULT WHERE FRONT_BACK = 0 GROUP BY DATETIME ORDER BY ANZAHL DESC LIMIT 1) GROUPED";
+ // COUNT
+ Statement stmt = con.createStatement();
+ rs= stmt.executeQuery(selectStmt);
+ if(rs.first() && rs.getTime("DATETIME")!=null){
+ String inserTableSQL = "REPLACE INTO mw_MaxValues_Crossroad VALUES (?,?,?,?,?,?,DEFAULT)";
+ PreparedStatement insertStmt = con.prepareStatement(inserTableSQL);
+ insertStmt.setInt(1, rs.getInt("CROSSROAD_ID"));
+ insertStmt.setString(2, rs.getString("CROSSROAD_NAME"));
+ insertStmt.setInt(3, rs.getInt("ANZAHL"));
+ insertStmt.setInt(4, rs.getInt("BELEGUNG"));
+ insertStmt.setTimestamp(5, rs.getTimestamp("DATETIME"));
+ insertStmt.setInt(6, 0);
+ System.out.println(insertStmt);
+ insertStmt.executeUpdate();
+ count = rs.getDouble("ANZAHL");
+ return new double[]{count,load};
+ }
+ } catch (SQLException e) {
+ e.printStackTrace();
+ System.out.println("SQLException bei " +crossroadID+"\t\t"+selectStmt);
+ }
+ return new double[]{0.0,0.0};
+ }
+
+ /**
+ * aktualisiert die maximalen Wert der Kreuzung, sofern dies nötig ist
+ * - wird nur ausgeführt, wenn newMaxValues auf TRUE gesetzt ist
+ * @param crossroadID - ID der Kreuzung
+ * @param count - neuer Count-Wert
+ * @param load - neuer Load-Wert
+ * @param time - Beginn der Aggregation
+ * @param timeRange - Zeitintervall der Aggregation
+ * @return
+ */
+ public boolean setMaximalWeightsCrossroadImproved(int crossroadID, double count, double load, DateTime time, int timeRange){
+ String inserTableSQL = "UPDATE mw_MaxValues_CrossroadImproved SET COUNT_VALUE = ?, LOAD_VALUE = ?, DATETIME = ?,timeRange = ? WHERE CROSSROAD_ID ="+crossroadID+" AND COUNT_VALUE<"+count;
+ try {
+ PreparedStatement insertStmt = con.prepareStatement(inserTableSQL);
+ insertStmt.setDouble(1,count);
+ insertStmt.setDouble(2, load);
+ insertStmt.setTimestamp(3, Timestamp.valueOf(toSql(time)));
+ insertStmt.setInt(4, timeRange*2);
+ if(newMaxValues)
+ insertStmt.execute();
+ } catch (SQLException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ return true;
+ }
+
+ /**
+ * Aktualisiert die maximalen Werte des Einfahrtsweges, sofern dies nötig ist
+ * - wird nur ausgeführt, wenn newMaxValues auf TRUE gesetzt ist
+ * @param inputWayID - globale ID des Einfahrtsweges
+ * @param count - neuer Count-Wert
+ * @param load - neuer Load-Wert
+ * @param time Beginn der Aggregation
+ * @param timeRange Zeitintervall der Aggregation
+ * @return
+ */
+ public boolean setMaximalWeightsInputWayImproved(int inputWayID, double count, double load, DateTime time, int timeRange){
+ String inserTableSQL = "UPDATE mw_MaxValues_InputWaysImproved SET COUNT_VALUE = ?, LOAD_VALUE = ?, DATETIME = ?, timeRange = ? WHERE INPUT_WAY_ID ="+inputWayID+" AND COUNT_VALUE<"+count;
+ try {
+ PreparedStatement insertStmt = con.prepareStatement(inserTableSQL);
+ insertStmt.setDouble(1,count);
+ insertStmt.setDouble(2, load);
+ insertStmt.setTimestamp(3, Timestamp.valueOf(toSql(time)));
+ insertStmt.setInt(4, timeRange*2);
+ if(newMaxValues)
+ insertStmt.execute();
+ } catch (SQLException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ return true;
+ }
+
+ /**
+ * schreibt einen neuen Zufallswert für die Kreuzung in mw_MaxValues_Crossroad_Random
+ * @param crossroadID - globale ID der Kreuzung
+ * @param random - Count-Wert als Zufallswert
+ */
+ public void writeMaximalWeightsCrossroadsRandom(int crossroadID,double random){
+ java.sql.PreparedStatement stmt;
+ try {
+ String inserTableSQL = "REPLACE INTO mw_MaxValues_Crossroad_Random VALUES (?,?)";
+ stmt = con.prepareStatement(inserTableSQL);
+ stmt.setInt(1, crossroadID);
+ stmt.setDouble(2, random);
+ stmt.execute();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * schreibt das maximale Gewicht (nur Count) für einen Einfahrtsweg in die Tabelle mw_MaxValues_InputWays,
+ * die Daten sind auf 1x Stepsize berechnet, ACHTUNG: Datenbankabfrage nicht mehr durchführbar, da zu viele Daten
+ * @param inputwayID globale ID des Einfahrtsweges
+ * @return
+ */
+ public double[] writeMaximalWeightsInputWays(int inputwayID) {
+ System.out.println("Prüfe ID MaximalWeightsInputWays " +inputwayID);
+ int count = 0;
+ int load = 0;
+ ResultSet rs;
+ int[] inputData = inputWays.get(inputwayID);
+ int crossroadID = inputData[1];
+ System.out.println("InputWay:\t"+inputwayID+"CrossroadID:\t"+crossroadID);
+ String selectStmt = null;
+ try {
+ selectStmt = "SELECT SUM(cr_count) as ANZAHL,SUM(cr_load)/COUNT(cr_load) AS BELEGUNG, DATETIME,SENSORS_ON_WAY.* FROM (SELECT * FROM (SELECT ID AS SENSOR_ID, REALNAME AS SENSOR_NAME, CSVOFFSET, wayID AS WAY_ID, CROSSROAD_ID, crossroadName AS CROSSROAD_NAME FROM (SELECT ID, CSVOFFSET, REALNAME, CROSSROAD_ID FROM jee_crmodel_SensorDim S WHERE S.CROSSROAD_ID='"+crossroadID+"') GLOBALSENSORS RIGHT JOIN (SELECT * FROM mw_SensorWays WHERE crossroadID = '"+crossroadID+"' AND wayID IS NOT NULL) SENSORS_MAPPED ON GLOBALSENSORS.ID = SENSORS_MAPPED.sensorID) SENSORS JOIN (SELECT * FROM mw_InputWaysGlobal IWG WHERE IWG.ID = '"+inputwayID+"') INPUT_WAYS ON SENSORS.WAY_ID = INPUT_WAYS.wayID) SENSORS_ON_WAY LEFT JOIN jee_trafficlight_rawevents RE ON RE.CSVOFFSET = SENSORS_ON_WAY.CSVOFFSET AND RE.CROSSROAD = SENSORS_ON_WAY.CROSSROAD_NAME GROUP BY DATETIME ORDER BY ANZAHL DESC LIMIT 1";
+ // COUNT
+ Statement stmt = con.createStatement();
+ rs= stmt.executeQuery(selectStmt);
+ if(rs.first() && rs.getTime("DATETIME")!=null){
+ String inserTableSQL = "REPLACE INTO mw_MaxValues_InputWays VALUES (?,?,?,?,?,?,?,DEFAULT)";
+ java.sql.PreparedStatement insertStmt = con.prepareStatement(inserTableSQL);
+ insertStmt.setInt(1,inputwayID);
+ insertStmt.setInt(2, rs.getInt("CROSSROAD_ID"));
+ insertStmt.setString(3, rs.getString("CROSSROAD_NAME"));
+ insertStmt.setInt(4, rs.getInt("ANZAHL"));
+ insertStmt.setInt(5, rs.getInt("BELEGUNG"));
+ insertStmt.setTimestamp(6, rs.getTimestamp("DATETIME"));
+ insertStmt.setInt(7, 0);
+ System.out.println(insertStmt);
+ insertStmt.executeUpdate();
+ count = rs.getInt("ANZAHL");
+ return new double[]{count,load};
+ }
+ } catch (SQLException e) {
+ e.printStackTrace();
+ System.out.println("SQLException in writeMaximalWeightsInputWays mit ID"+ inputwayID+"\t\t"+selectStmt);
+ }
+ return new double[]{count,load};
+ }
+
+ /**
+ * berechnet das Gewicht (als CrossroadWeight-Objekt) für die Kreuzung
+ * @param crossroadID - globale ID der Kreuzung
+ * @param from - Startzeitpunkt
+ * @param to - Endzeitpunkt
+ * @param timestampInit - Zeitstempel für den das Gewicht berechnet wird
+ * @return
+ */
+ public CrossroadWeight getCrossroadWeight(int crossroadID, DateTime from, DateTime to,long timestampInit) {
+ String crossroadName = getCrossroadName(crossroadID);
+ if(!maxValuesCrossroad.containsKey(crossroadID)){
+ maxValuesCrossroad.put(crossroadID, getMaximalWeightCrossroad(crossroadID) );
+ }
+ CrossroadWeight crw = new CrossroadWeight(crossroadID, crossroadName,treshold);
+ try {
+ // Wählt alle Sensoren aus, die zur Kreuzung gehören
+ String sensors = "SELECT ID as SENSOR_ID, CSVOFFSET, REALNAME, CROSSROAD_ID FROM jee_crmodel_SensorDim S WHERE S.CROSSROAD_ID='"+crossroadID+"'";
+ // Wählt die Wege der Kreuzung aus, um die Sensoren darauf zu mappen
+ String sensorWays = "SELECT * FROM mw_SensorWays SW WHERE crossroadID ='"+crossroadID+"' AND wayID IS NOT NULL";
+ // Lädt die entsprechenden Sensordaten für den definierten Zeitraum
+ String eventData = "SELECT ID as EVENT_ID,cr_count as COUNT_VALUE, cr_load as LOAD_VALUE, RE.CSVOFFSET,DATETIME FROM jee_trafficlight_rawevents RE WHERE RE.DATETIME >= '"+toSql(from)+"'AND RE.DATETIME < '"+toSql(to)+"' AND CROSSROAD = '"+crossroadName+"'";
+ // Filtert aus den Sensordaten die Daten für die Sensoren raus
+ String crossroadWeight ="SELECT EVENT_ID,DATETIME,COUNT_VALUE, LOAD_VALUE,sensorName as SENSOR_NAME, sensorID as SENSOR_ID, SENSORS.CSVOFFSET, crossroadID as CROSSROAD_ID, crossroadName as CROSSROAD_NAME FROM (SELECT sensorID,sensorName, CSVOFFSET,crossroadID,crossroadName FROM ("+sensors+") SENSORS RIGHT JOIN ("+sensorWays+") SENSORS_MAPPED ON SENSORS.SENSOR_ID = SENSORS_MAPPED.sensorID) SENSORS LEFT JOIN ("+eventData+") EVENT_DATA on SENSORS.CSVOFFSET = EVENT_DATA.CSVOFFSET";
+ // Mapped die Sensoren auf die Richtung des Einfahrtsweges für die Gruppierung
+ String resultData = "SELECT CROSSROAD_WEIGHT.*,mw_SensorConnection.FRONT_BACK,mw_SensorConnection.FROM_DIRECTION, mw_SensorConnection.TO_LEFT,mw_SensorConnection.TO_STRAIGHT,mw_SensorConnection.TO_RIGHT FROM ("+crossroadWeight+") CROSSROAD_WEIGHT JOIN mw_SensorConnection ON CROSSROAD_WEIGHT.SENSOR_ID = mw_SensorConnection.SENSOR_ID";
+ // Kombiniert die ermittelten Sensorwert mit den Einfahrtswegen (aus OSM) der Kreuzung und summiert die Werte auf
+ String selectStmt = "SELECT SUM(COUNT_VALUE)/COUNT(DISTINCT DATETIME) as ANZAHL, SUM(LOAD_VALUE)/COUNT(LOAD_VALUE) as BELEGUNG ,FROM_DIRECTION, OSMWAY_ID FROM ("+resultData+") RESULT LEFT JOIN (SELECT * FROM mw_CrossroadWays WHERE TYPE = '0')CRW on RESULT.FROM_DIRECTION = CRW.DIRECTION AND RESULT.CROSSROAD_ID = CRW.CROSSROAD_ID WHERE FRONT_BACK = 0 GROUP BY OSMWAY_ID";
+ Statement stmt = con.createStatement();
+ ResultSet rs = stmt.executeQuery(selectStmt);
+ while (rs.next()) {
+ int wayID = rs.getInt("OSMWAY_ID");
+ double[] maxValue = getMaximalWeightInputWayFromMap(wayID,crossroadID); //Index 0 = MaxCount, Index 1 = MaxLoad
+ if(maxValue == null){
+ maxValue = new double[]{Double.MAX_VALUE,Double.MAX_VALUE};
+ }
+ crw.setMaxWeightWay(wayID, maxValue);
+ double count = rs.getDouble("ANZAHL");
+ double load = rs.getDouble("BELEGUNG");
+ //TODO: Verbindung zur TimeRange, war zuvor als Parameter in Datenbank, nun nur noch im TrafficConfig
+ setMaximalWeightsInputWayImproved(getInputWay(crossroadID, wayID), count, load, from, 5); // aktualisiert den maximalen Count-Wert, sofern dies notwendig ist
+ crw.addWeightWay(wayID, new double[]{count,load,(count/maxValue[0])*100});
+ crw.setTimestamp(timestampInit);
+
+ }
+ } catch (SQLException e) {
+ e.printStackTrace();
+ }
+ crw.setMaxWeight(maxValuesCrossroad.get(crossroadID));
+ crossroadModelNodes.put(crossroadID, crw);
+ return crw;
+ }
+
+ /**
+ * berechnet das synthetische InitialGewicht im Simulationsmodus, beinhaltet eine DB-Abfrage zur Erstellung des CrossroadWeight-Objekts
+ * @param crossroadID, globale KreuzungsID
+ * @param from Startzeitpunkt für DB-Abfrage
+ * @param to Entzeitpunkt für DB-Abfrage
+ * @param timestamp, Zeitstempel für die Definition im CrossroadWeightObjekt
+ * @param trafficUpdate, beinhaltet die synthetischen Daten
+ * @return
+ */
+ public CrossroadWeight getCrossroadWeightStaticInit(int crossroadID,DateTime from, DateTime to, long timestampInit,TrafficUpdate trafficUpdate) {
+ CrossroadWeight crw = getCrossroadWeight(crossroadID, from, to,timestampInit);
+ crw.resetInputWayWeight(trafficUpdate.getInitCount(), trafficUpdate.getInitLoad());
+ return crw;
+ }
+
+ /**
+ * berechnet das synthetische Gewicht im Simulationsmodus für fortlaufende Batches
+ * @param crossroadID gloable KreuzungsID
+ * @param update beinhaltet die synthetischen Daten
+ * @return
+ */
+ public CrossroadWeight getCrossroadWeightStaticBatch(int crossroadID,TrafficUpdate update) {
+ CrossroadWeight crw = crossroadModelNodes.get(crossroadID);
+ crw.setTimestamp(crw.getTimestamp()+1);
+ if(update.isAffected(crossroadID)){
+ crw.resetInputWayWeight((update.getSleepTillUpdate()*update.getInitCount()+update.getUpdateCount())/(update.getSleepTillUpdate()+1), (update.getSleepTillUpdate()*update.getInitLoad()+update.getUpdateLoad())/(update.getSleepTillUpdate()+1));
+ }
+ return crw;
+ }
+
+ /**
+ * liest das maximale Gewicht aus der Tabelle mw_MaxValues_Crossroad (auf 1xTimestep berechnet)
+ * @param crossroadID
+ * @return
+ */
+ public double[] getMaximalWeightCrossroad(int crossroadID) {
+ try {
+ String selectStmt = "SELECT * FROM mw_MaxValues_Crossroad WHERE CROSSROAD_ID = "+crossroadID+" AND COUNT_OR_LOAD =0";
+ Statement stmt = con.createStatement();
+ ResultSet rs = stmt.executeQuery(selectStmt);
+ if(rs.first()){
+ return new double[]{rs.getDouble("COUNT"),0};
+ }
+ else
+ return writeMaximalWeightsCrossroad(crossroadID);
+ } catch (SQLException e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
+
+ /**
+ * liest Maximalwerte des Einfahrtsweges aus der HashMap (zwischengespeichert nach DB-Abfrage)
+ * @param wayID
+ * @param crossroadID
+ * @return
+ */
+ private double[] getMaximalWeightInputWayFromMap(int wayID,int crossroadID){
+ int inputWayID = getInputWay(crossroadID, wayID);
+ double[] result = maxValuesInputWays.get(inputWayID);
+ return result;
+ }
+
+ /**
+ * liest den Maximalwert für einen Einfahrtsweg direkt aus der Datenbank (aus mw_MaxValues_InputWays)
+ * @param osmWayID
+ * @param crossroadRoad
+ * @return
+ */
+ private double[] getMaximalWeightInputWay(int inputWayID) {
+ try {
+ String selectStmt = "SELECT * FROM mw_MaxValues_InputWays WHERE INPUT_WAY_ID = "+inputWayID+" AND COUNT_OR_LOAD =0";
+ Statement stmt = con.createStatement();
+ ResultSet rs = stmt.executeQuery(selectStmt);
+ if(rs.first()){
+ return new double[]{rs.getDouble("COUNT"),0};
+ }
+ else
+ return writeMaximalWeightsInputWays(inputWayID);
+ } catch (SQLException e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
+
+ /**
+ * liest den Maximalwert für einen Einfahrtsweg direkt aus der Datenbank
+ * @param osmWayID
+ * @param crossroadRoad
+ * @return
+ */
+ private double[] getMaximalWeightInputWay(int osmWayID, int crossroadRoad) {
+ try {
+ String selectStmt = "SELECT IW.*,wayID FROM mw_MaxValues_InputWays IW LEFT JOIN mw_InputWaysGlobal IWG ON IW.INPUT_WAY_ID = IWG.ID WHERE wayID ='"+osmWayID+"' AND CROSSROAD_ID ="+crossroadRoad;
+ Statement stmt = con.createStatement();
+ ResultSet rs = stmt.executeQuery(selectStmt);
+ if(rs.first()){
+ return new double[]{rs.getDouble("COUNT"),0};
+ }
+ else
+ return new double[]{Double.MAX_VALUE,Double.MAX_VALUE};
+ } catch (SQLException e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
+
+ /**
+ * liest die Maximalwerte der Einfahrtswege aus der, durch die Parameter festgelegten Tabelle
+ * Random-Werte wenn dummyMax=true, sonst die MaximalWerte für den Berufsverkehr
+ */
+ public void getMaximalWeightInputWay() {
+ try {
+ String selectStmt = null;
+ if(dummyMax)
+ selectStmt = "SELECT * FROM mw_MaxValues_InputWay_Random JOIN mw_InputWaysGlobal on INPUTWAY_ID = ID";
+ else
+ selectStmt = "SELECT * FROM mw_MaxValues_InputWaysImproved WHERE COUNT_OR_LOAD =0";
+ Statement stmt = con.createStatement();
+ ResultSet rs = stmt.executeQuery(selectStmt);
+ while(rs.next()) {
+ if(dummyMax)
+ maxValuesInputWays.put(rs.getInt("INPUTWAY_ID"), new double[]{rs.getDouble("MAX_COUNT"),0});
+ else{
+ double maxCount = rs.getDouble("COUNT_VALUE");
+ if(maxCount <1)
+ maxCount= 1;
+ maxValuesInputWays.put(rs.getInt(1), new double[]{maxCount,rs.getDouble("LOAD_VALUE")});
+ }
+ }
+ } catch (SQLException e) {
+ e.printStackTrace();
+ }
+ }
+ /**
+ * schreibt maximale Werte für die Einfahrtswege einer Kreuzung, die Werte orientieren sich dabei an den Maximalwerten der Kreuzung
+ */
+ public void writeMaximalWeightInputWayRandom() {
+ Random rand = new Random();
+ try {
+ String selectStmt = "SELECT ID, crossroadID,MAX_COUNT as MAX_COUNT_CROSSROAD FROM mw_InputWaysGlobal IWG LEFT JOIN mw_MaxValues_Crossroad_Random MAX_C_RANDOM ON IWG.crossroadID = MAX_C_RANDOM.CROSSROAD_ID";
+ Statement stmt = con.createStatement();
+ String insertString = "REPLACE INTO mw_MaxValues_InputWay_Random VALUES (?,?)";
+ java.sql.PreparedStatement insertStmt = con.prepareStatement(insertString);
+ ResultSet rs = stmt.executeQuery(selectStmt);
+ while(rs.next()) {
+ double randMax = rand.nextDouble()*(rs.getDouble("MAX_COUNT_CROSSROAD")/2)+rs.getDouble("MAX_COUNT_CROSSROAD")/4;
+ insertStmt.setInt(1, rs.getInt("ID"));
+ insertStmt.setDouble(2, randMax);
+ insertStmt.addBatch();
+ }
+ insertStmt.executeBatch();
+ } catch (SQLException e) {
+ e.printStackTrace();
+ }
+
+ }
+
+ /**
+ * schreibt maximale Werte für die realen Sensoren in die Datenbank, welche sich grob an den Werten für den passenden virtuellen Sensor orientieren
+ */
+ public void writeMaximalWeightSensorRandom() {
+ Random rand = new Random();
+ try {
+ String selectStmt = "SELECT NODE_ID as REALSENSOR_INDEX , R2.* FROM (SELECT * FROM mw_SensorGlobal WHERE SENSOR_TYPE = 0) R3 LEFT JOIN (SELECT R1.*,MAX_COUNT FROM (SELECT INPUTWAY_INDEX, ANZAHL_SENSORS,WAY_ID,CROSSROAD_ID,DIRECTION, ID as INPUTWAY_ID_GLOBAL FROM (SELECT NODE_ID as INPUTWAY_INDEX, COUNT(VS) as ANZAHL_SENSORS,WAY_ID,CROSSROAD_ID,DIRECTION FROM (SELECT * FROM mw_SensorGlobal WHERE SENSOR_TYPE = 1) WAYS LEFT JOIN (SELECT SG2.NODE_ID as VS, SG1.NODE_ID as RS FROM (SELECT * FROM mw_SensorGlobal WHERE SENSOR_TYPE = 0) SG1 JOIN (SELECT * FROM mw_SensorGlobal WHERE SENSOR_TYPE = 1) SG2 ON SG1.WAY_ID = SG2.WAY_ID AND SG1.CROSSROAD_ID = SG2.CROSSROAD_ID AND SG1.DIRECTION = SG2.DIRECTION) VS_TO_RS ON WAYS.NODE_ID = VS_TO_RS.VS GROUP BY VS) ANZAHL LEFT JOIN mw_InputWaysGlobal IWG ON ANZAHL.WAY_ID = IWG.wayID AND ANZAHL.CROSSROAD_ID = IWG.crossroadID) R1 LEFT JOIN mw_MaxValues_InputWay_Random MWIWR ON R1.INPUTWAY_ID_GLOBAL=MWIWR.INPUTWAY_ID) R2 ON R3.WAY_ID = R2.WAY_ID AND R3.CROSSROAD_ID = R2.CROSSROAD_ID AND R3.DIRECTIOn = R2.DIRECTION";
+ Statement stmt = con.createStatement();
+ String insertString = "REPLACE INTO mw_MaxValues_Sensor_Random VALUES (?,?)";
+ java.sql.PreparedStatement insertStmt = con.prepareStatement(insertString);
+ ResultSet rs = stmt.executeQuery(selectStmt);
+ while(rs.next()) {
+ double randMax = rand.nextDouble()*(rs.getDouble("MAX_COUNT")/rs.getDouble("ANZAHL_SENSORS"))+2;
+ if(rs.getDouble("MAX_COUNT")==0)
+ randMax = rand.nextDouble()*5+2;
+ insertStmt.setInt(1, rs.getInt("REALSENSOR_INDEX"));
+ insertStmt.setDouble(2, randMax);
+ insertStmt.addBatch();
+ }
+ insertStmt.executeBatch();
+ } catch (SQLException e) {
+ e.printStackTrace();
+ }
+
+ }
+
+
+ /**
+ * liest die Maximalwerte der Kreuzungen aus der, durch die Parameter festgelegten Tabelle
+ * Random-Werte wenn dummyMax=true, sonst die MaximalWerte für den Berufsverkehr
+ */
+ public void getMaximalWeightCrossroad() {
+ try {
+ String selectStmt;
+
+ if(dummyMax)
+ selectStmt = "SELECT * FROM mw_MaxValues_Crossroad_Random";
+ else
+ selectStmt = "SELECT * FROM mw_MaxValues_CrossroadImproved";
+
+ Statement stmt = con.createStatement();
+ ResultSet rs = stmt.executeQuery(selectStmt);
+
+ while(rs.next()){
+ if(dummyMax)
+ maxValuesCrossroad.put(rs.getInt("CROSSROAD_ID"), new double[] {rs.getDouble("MAX_COUNT"),0});
+ else{
+ double maxCount = rs.getDouble("COUNT_VALUE");
+ if(maxCount <1)
+ maxCount = 1;
+ maxValuesCrossroad.put(rs.getInt("CROSSROAD_ID"), new double[] {maxCount,rs.getDouble("LOAD_VALUE")});
+ }
+ }
+
+ } catch (SQLException e) {
+ e.printStackTrace();
+ }
+ }
+ /**
+ * liest die hinterlegten, zufälligen Maximalwerte für die Sensoren
+ */
+ public void getMaximalWeightSensor() {
+ try {
+ String selectStmt = "SELECT * FROM mw_MaxValues_Sensor_Random";
+ Statement stmt = con.createStatement();
+ ResultSet rs = stmt.executeQuery(selectStmt);
+ while(rs.next()){
+ maxValuesSensors.put(rs.getInt("SENSOR_ID"), new double[] {rs.getDouble("MAX_COUNT"),0});
+ }
+ } catch (SQLException e) {
+ e.printStackTrace();
+ }
+ }
+
+
+ /**
+ * Aufruf von setID für Startknoten
+ * @param id - globale ID des Einfahrtsweges
+ * @return
+ */
+ public int setFromID(int id) {
+ return setID(id,"from");
+ }
+
+ /**
+ * Aufruf von setID für Zielknoten
+ * @param id - globale ID des Einfahrtsweges
+ * @return
+ */
+ public int setToID(int id) {
+ return setID(id,"to");
+ }
+
+ /**
+ * Hilfsmethode zur Generierung der Tabelle mw_InputWayConnection aus den Informationen der innerern Kreuzungsverbindung
+ * Einfahrtsweg -> Ausfahrtswege -> Einfahrtswege
+ * @param id globale ID des Einfahrtsweges
+ * @param mode from = Startknoten, to = Zielknoten
+ * @return
+ */
+ public int setID(int id,String mode) {
+ try {
+ String selectStmtString = "SELECT * FROM mw_InputWaysGlobal WHERE ID = "+ id;
+ Statement selectStmt = con.createStatement();
+ ResultSet rs = selectStmt.executeQuery(selectStmtString);
+ rs.first();
+ String updateString = "UPDATE mw_InputWayConnection A SET "+mode+"ID = "+id+" WHERE A."+mode+"Way = "+rs.getInt(2) +" AND A."+mode+"Crossroad = " +rs.getInt(3);
+ Statement updateStmt = con.createStatement();
+ return updateStmt.executeUpdate(updateString);
+
+ } catch (SQLException e) {
+ e.printStackTrace();
+ }
+ return 0;
+ }
+
+ /**
+ * liest die Verbindungen der Kreuzungsknoten aus der Tabelle mw_CrossroadConnection
+ * @param nodesFilter Array von KnotenID, die als Startknoten oder Endknoten fungieren dürfen
+ * @return Liste von EdgeContainern mit (from,to)
+ */
+ public List getCrossroadConnectionForDNA(int[] nodesFilter) {
+ List connection = new ArrayList<>();
+
+ String filterString ="";
+ if(nodesFilter!= null && nodesFilter.length>0){
+ StringBuffer sb = new StringBuffer(" IN (");
+ for (int i = 0; i < nodesFilter.length; i++) {
+ sb.append(nodesFilter[i]);
+ if(i getInputWays(int crossroadID) {
+ return getWays(crossroadID,0);
+ }
+
+ /**
+ * liest alle Ausfahrtswege einer Kreuzung
+ * @param crossroadID - globale KreuzungsID
+ * @return
+ */
+ public HashMap getOutputWays(int crossroadID) {
+ return getWays(crossroadID,1);
+ }
+
+ /**
+ * liest alle Wege des übergebenen Typs aus der Tabelle mw_CrossroadWays
+ * @param crossroadID - globale KreuzungsID
+ * @param type - 0 = Einfahrtsweg, 1 = Ausfahrtsweg
+ * @return HashMap mit Himmelsrichtung als Key, und OSM-ID des Weges als Value
+ */
+ private HashMap getWays(int crossroadID, int type) {
+ HashMap ways = new HashMap<>();
+
+ try {
+ Statement stmt = con.createStatement();
+ String statementString = "SELECT DIRECTION , OSMWAY_ID FROM mw_CrossroadWays WHERE CROSSROAD_ID ="+crossroadID+" AND TYPE =" +type;
+ ResultSet rs = stmt.executeQuery(statementString);
+
+ while(rs.next()){
+ ways.put(CardinalDirection.valueOf(rs.getString("DIRECTION")), rs.getInt("OSMWAY_ID"));
+ }
+
+ } catch (SQLException e) {
+ e.printStackTrace();
+ }
+
+ return ways;
+ }
+
+ /**
+ * liefert eine Liste von Ausfahrtswegen, von denen der übergebene Einfahrtsweg direkt zu erreichen ist
+ * @param crossroadID
+ * @param toWay
+ * @return
+ */
+ public List getFromWays(int crossroadID, int toWay) {
+ return inputWayConnections.get(new InputWay(toWay, crossroadID));
+
+ }
+
+ /**
+ * erstellt eine Hashmap mit Einfahrtswegen als Keys und Listen von Einfahrtswegen als Values
+ */
+ public void loadFromWays(){
+ InputWay key;
+ int[] value;
+
+ try {
+ String selectStmt = "SELECT FROM_CROSSROAD,FROM_WAY,TO_CROSSROAD,TO_WAY FROM mw_CrossroadConnection";
+ Statement stmt = con.createStatement();
+ ResultSet rs = stmt.executeQuery(selectStmt);
+
+ while(rs.next()) {
+ key = new InputWay(rs.getInt("TO_WAY"),rs.getInt("TO_CROSSROAD"));
+ value = new int[]{rs.getInt("FROM_CROSSROAD"), rs.getInt("FROM_WAY")};
+ if(!this.inputWayConnections.containsKey(key)){
+ this.inputWayConnections.put(key,new ArrayList());
+ }
+ this.inputWayConnections.get(key).add(value);
+ }
+
+ } catch (SQLException e) {
+ e.printStackTrace();
+ }
+ }
+
+
+ /**
+ * liest alle Sensoren, die auf den überlieferten Weg gemappt wurden
+ * @param crossroadID - globale KreuzungsID
+ * @param wayID - OSM-ID für den Weg
+ * @return, Liste von Sensoren
+ */
+ public List getSensors(int crossroadID, int wayID) {
+ List sensors = new ArrayList<>();
+ try {
+ Statement stmt = con.createStatement();
+ String statementString = "SELECT * FROM mw_SensorWays WHERE crossroadID ="+crossroadID+" AND wayID =" +wayID;
+ ResultSet rs = stmt.executeQuery(statementString);
+ while(rs.next()){
+ sensors.add(new Sensor(rs.getInt(1),rs.getString(2),rs.getInt(3),rs.getString(4),rs.getInt(5)));
+ }
+ } catch (SQLException e) {
+ e.printStackTrace();
+ }
+ return sensors;
+ }
+
+ /**
+ * liefert ein Sensor-Objekt für einen modellierten Sensor
+ * @param sensorID - globale Sensor-ID
+ * @return
+ */
+ public Sensor getSensor(int sensorID) {
+ Set directions= new HashSet<>();
+ try {
+ Statement stmt = con.createStatement();
+ String statementString = "SELECT * FROM mw_SensorConnection WHERE SENSOR_ID = "+sensorID;
+ ResultSet rs = stmt.executeQuery(statementString);
+ if(rs.first()) {
+
+ // Abfrage der Abbiegemöglichkeiten
+ if(rs.getString("TO_LEFT")!=null) {
+ directions.add(CardinalDirection.valueOf(rs.getString("TO_LEFT")));
+ }
+ if(rs.getString("TO_STRAIGHT")!=null) {
+ directions.add(CardinalDirection.valueOf(rs.getString("TO_STRAIGHT")));
+ }
+ if(rs.getString("TO_RIGHT")!=null) {
+ directions.add(CardinalDirection.valueOf(rs.getString("TO_RIGHT")));
+ }
+
+ return new Sensor(rs.getInt("sensorID"), rs.getString("sensorName"), rs.getInt("crossroadID"), rs.getString("crossroadName"), rs.getInt("wayID"),directions);
+ }
+ } catch (SQLException e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
+
+ /**
+ * liefert alle Ausfahrtswege, die durch die Abbiegemöglichkeiten des Sensors erreichbar sind
+ * @param sensorID - globale SensorID
+ * @param crossroadID - globale KreuzungsID
+ * @return HashMap mit Abbiegerichtung und WegeID
+ */
+ public HashMap getOutputWays(int sensorID, int crossroadID) {
+ HashMap outputDirection = new HashMap<>();
+ try {
+ String[] direction = new String[] {"LEFT","STRAIGHT", "RIGHT"};
+ Statement stmt = con.createStatement();
+ int wayID;
+ String statementString;
+
+ // Eine Abfrage je Abbiegemöglichkeit
+ for (int i = 0; i < direction.length; i++) {
+ statementString = "SELECT SC.CROSSROAD_ID, SC.CROSSROAD_NAME, SC.SENSOR_ID, SC.SENSOR_NAME, SC.FROM_WAY, SC.FROM_DIRECTION, SC.TO_LEFT, CW.OSMWAY_ID as OUT_WAYID, CW.DIRECTION as OUTDIRECTION FROM mw_SensorConnection SC , mw_CrossroadWays CW WHERE SC.CROSSROAD_ID = CW.CROSSROAD_ID AND SC.TO_"+direction[i]+" = CW.DIRECTION AND SC.CROSSROAD_ID = "+crossroadID+" AND CW.TYPE=1 AND SC.SENSOR_ID = "+sensorID;
+ ResultSet rs = stmt.executeQuery(statementString);
+ while(rs.next() ) {
+ wayID = rs.getInt("OUT_WAYID");
+ if( wayID >0 )
+ outputDirection.put(direction[i],wayID);
+ }
+ }
+
+ } catch (SQLException e) {
+ e.printStackTrace();
+ }
+ return outputDirection;
+ }
+
+ /**
+ * liefert alle Einfahrtswege, die mit dem übergebenen Ausfahrtsweg verbunden sind
+ * @param outputOSM, OSM-ID des Weges
+ * @param outputCrossroad, ID der Kreuzung, zu der der Weg gehört
+ * @return
+ */
+ public List getConnectedInputWays(int outputOSM, int outputCrossroad) {
+ List connections = new ArrayList<>();
+ try {
+ Statement stmt = con.createStatement();
+ int wayID;
+ String statementString;
+ statementString = "SELECT TO_CROSSROAD,TO_WAY FROM mw_CrossroadConnection CC WHERE CC.FROM_WAY = "+outputOSM+" AND CC.FROM_CROSSROAD = " +outputCrossroad;
+ ResultSet rs = stmt.executeQuery(statementString);
+ while(rs.next() ) {
+ wayID = rs.getInt("TO_WAY");
+ if( wayID >0 ) {
+ connections.add(new InputWay(rs.getInt(1), rs.getInt(2)));
+ }
+ }
+ } catch (SQLException e) {
+ e.printStackTrace();
+ }
+ return connections;
+ }
+
+ /**
+ * liefert die IDs aller Sensoren, die auf dieser Kreuzung modelliert wurden
+ * @param crossroadID - globale ID der Kreuzung
+ * @return
+ */
+ public List getSensorIDs(int crossroadID) {
+ List sensors = new ArrayList<>();
+ try {
+ Statement stmt = con.createStatement();
+ ResultSet rs = stmt.executeQuery("SELECT SENSOR_ID FROM mw_SensorConnection WHERE CROSSROAD_ID = "+crossroadID);
+
+ while(rs.next()) {
+ sensors.add(rs.getInt(1));
+ }
+
+ } catch (SQLException e) {
+ e.printStackTrace();
+ }
+ return sensors;
+ }
+
+ /**
+ * liest die Einfahrtswege für die interne Speicherung in der DB-Klasse
+ * erstellt daraus HashMaps für den schnellen Zugriff anhand der ID
+ */
+ private void getInputWays(){
+ try {
+ Statement stmt = con.createStatement();
+ String statementString = "SELECT * FROM mw_InputWaysGlobal";
+ ResultSet rs = stmt.executeQuery(statementString);
+
+ while(rs.next() ) {
+
+ int wayID = rs.getInt("wayID");
+ int crossroadID = rs.getInt("crossroadID");
+
+ inputWays.put(rs.getInt("ID"), new int[]{wayID,crossroadID});
+ inputWaysToID.put(new InputWay(wayID,crossroadID), rs.getInt(1));
+ }
+
+ } catch (SQLException e) {
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * liest die globale ID des Einfahrtsweges aus der HashMap
+ * @param crossroadID - globale KreuzungsID
+ * @param wayID - OSMWay-ID
+ * @return globale ID des Einfahrtsweges
+ */
+ public int getInputWay(int crossroadID,int wayID){
+ InputWay key = new InputWay(wayID, crossroadID);
+ if(inputWaysToID.containsKey(key)){
+ return inputWaysToID.get(key);
+ }
+ else{
+ return -1;
+ }
+ }
+
+ /**
+ * liefert eine Liste von Knoten, die alle Einfahrtsweges für den Wegegraph beinhaltet
+ * @param nodesFilter - Array mit den zu berücksichtigenden Knoten
+ * @return
+ */
+ public List getInputWaysForDNA(int[] nodesFilter) {
+ List nodes = new ArrayList();
+ Node currentWeighted = null;
+
+ String filterString = "";
+
+ // Filter aktiviert, baue Filterstring auf
+ if(nodesFilter != null && nodesFilter.length>0){
+ StringBuffer sb = new StringBuffer("WHERE ID IN (");
+ for (int i = 0; i < nodesFilter.length; i++) {
+ sb.append(nodesFilter[i]);
+ if(i getInputWaysConnectionForDNA(int[] nodesFilter) {
+ List edges = new ArrayList<>();
+
+ String filterString = "";
+
+ // Filter aktiviert, baue Filterstring auf
+ if(nodesFilter != null && nodesFilter.length>0){
+ StringBuffer sb = new StringBuffer("IN (");
+ for (int i = 0; i < nodesFilter.length; i++) {
+ sb.append(nodesFilter[i]);
+ if(i getCrossroadsForDNA(int[] nodesFilter) {
+ List nodes = new ArrayList();
+ Node current = null;
+
+ String filterString = "";
+
+ // Filter aktiviert, baue Filterstring auf
+ if(nodesFilter != null && nodesFilter.length>0){
+ StringBuffer sb = new StringBuffer("WHERE CROSSROAD IN (");
+ for (int i = 0; i < nodesFilter.length; i++) {
+ sb.append(nodesFilter[i]);
+ if(i connections) {
+ java.sql.PreparedStatement stmt;
+ try {
+ String inserTableSQL = "INSERT IGNORE INTO mw_InputWayConnection VALUES (?,?,?,?,?,?,DEFAULT)";
+ stmt = con.prepareStatement(inserTableSQL);
+ for (InputWayConnection connection : connections) {
+ stmt.setInt(1, connection.getFromWayID());
+ stmt.setInt(2, connection.getFromCrossroad());
+ stmt.setString(3, getCrossroadName(connection.getFromCrossroad()));
+ stmt.setInt(4, connection.getToWayID());
+ stmt.setInt(5, connection.getToCrossroad());
+ stmt.setString(6, getCrossroadName(connection.getToCrossroad()));
+ stmt.addBatch();
+ }
+ stmt.executeBatch();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return connections.size();
+ }
+
+ /**
+ * erstellt das Modell einer Kreuzungs mit den internen Verbindungen zwischen Einfahrtswegen und Ausfahrtswegen
+ * @param crossroadID - globale KreuzungsID
+ * @return
+ */
+ public Crossroad innerconnectionForCrossroad(int crossroadID){
+ HashMap inputWays = getInputWays(crossroadID);
+ HashMap outputWays = getOutputWays(crossroadID);
+
+ if(inputWays.size()==0){
+ System.out.println("Keine Einfahrtswege");
+ return null;
+ }
+
+ Crossroad crossroad = new Crossroad(crossroadID,this);
+ crossroad.setInputWays(inputWays);
+ crossroad.setOutputWays(outputWays);
+
+ // Verbindung innerhalb der Kreuzung
+ HashMap connectedOutputWays;
+ for (Map.Entry way : inputWays.entrySet()) {
+ connectedOutputWays = getConnectedOutputWays(crossroadID, way.getValue(), way.getKey());
+ if(connectedOutputWays==null) {
+ continue;
+ }
+ for (Map.Entry outputWay : connectedOutputWays.entrySet()) {
+ crossroad.setOutputWay(way.getKey(), outputWay.getKey());
+ }
+ }
+ return crossroad;
+ }
+
+ /**
+ * liefert für einen Einfahrtsweg alle Ausfahrtswege die innerhalb der Kreuzung zu erreichen sind
+ * @param crossroadID - globale Kreuzungs-ID
+ * @param wayID - OSMWay-ID
+ * @param wayDirection - Direction des Einfahrtsweges
+ * @return
+ */
+ public HashMap getConnectedOutputWays(int crossroadID, int wayID, CardinalDirection wayDirection) {
+ List sensors = getSensors(crossroadID, wayID);
+ HashMap outputWaysCrossroad = new HashMap<>();
+ HashMap outputWaysSensor;
+ CardinalDirection cd;
+
+ // Für alle Sensoren auf den Einfahrtsweg
+ for (Sensor sensor : sensors) {
+ outputWaysSensor = getOutputWays(sensor.getSensorID(), crossroadID); // Abbiegemöglichkeiten des Sensors
+ for (Map.Entry integer : outputWaysSensor.entrySet()) {
+ cd = transposeDirection(wayDirection, integer.getKey());
+ if(!outputWaysCrossroad.containsKey(cd))
+ outputWaysCrossroad.put(cd, integer.getValue());
+ }
+ }
+ return (outputWaysCrossroad.size()>0) ? outputWaysCrossroad : null;
+ }
+
+ /**
+ * übersetzt Himmelsrichtung und Abbiegemöglickeiten in neue Himmelsrichtung
+ * @param inDir - eigende Himmelsrichtung
+ * @param goDir - Abbiegerichtung
+ * @return - ausgehende Himmelsrichtung
+ */
+ public CardinalDirection transposeDirection (CardinalDirection inDir, String goDir) {
+ String[] directions = new String[]{"LEFT","STRAIGHT"};
+ switch (inDir) {
+ case NORTH:
+ if(goDir.equals(directions[0]))
+ return CardinalDirection.EAST;
+ else if(goDir.equals(directions[1]))
+ return CardinalDirection.SOUTH;
+ else
+ return CardinalDirection.WEST;
+ case EAST:
+ if(goDir.equals(directions[0]))
+ return CardinalDirection.SOUTH;
+ else if(goDir.equals(directions[1]))
+ return CardinalDirection.WEST;
+ else
+ return CardinalDirection.NORTH;
+ case SOUTH:
+ if(goDir.equals(directions[0]))
+ return CardinalDirection.WEST;
+ else if(goDir.equals(directions[1]))
+ return CardinalDirection.NORTH;
+ else
+ return CardinalDirection.EAST;
+ default:
+ if(goDir.equals(directions[0]))
+ return CardinalDirection.NORTH;
+ else if(goDir.equals(directions[1]))
+ return CardinalDirection.EAST;
+ else
+ return CardinalDirection.SOUTH;
+ }
+ }
+
+ /**
+ * liefert den Name den Kreuzung mit übergebener ID in der Datenbank
+ * @param crossroadID
+ * @return
+ */
+ public String getCrossroadName(int crossroadID) {
+ String selectStmt = "SELECT REALNAME FROM jee_crmodel_CrossroadDim WHERE ID = " + crossroadID;
+ Statement stmt;
+ try {
+ stmt = con.createStatement();
+ ResultSet rs = stmt.executeQuery(selectStmt);
+ while(rs.next()){
+ return rs.getString("REALNAME");
+ }
+ } catch (SQLException e) {
+ e.printStackTrace();
+ }
+ return "Not Found";
+ }
+
+ /**
+ * wandelt ein DateTime in eine SQL-konforme Stringrepräsentation um.
+ * @param dateTime
+ * @return
+ */
+ public static String toSql(DateTime dateTime) {
+ return new Timestamp( dateTime.getMillis() ).toString();
+ }
+
+ /**
+ * schließt die Verbindung zur Datenbank
+ */
+ public void disconnect() {
+ try {
+ con.close();
+ } catch (SQLException e) {
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * liefert die Knoten für das SensorModell, speichert diese für weitere Abfragen in HashMap sensorModelNodes
+ * @return Liste von Knoten mit NODE_ID als Label und Key in sensorModelNodes
+ */
+ public List getSensorsForDNA() {
+ System.out.println("Erstelle den Graph ... ");
+ List nodes = new ArrayList();
+ try {
+ Statement stmt = con.createStatement();
+ String statementString;
+ statementString = "SELECT SG.*, ID as INPUT_WAY_ID FROM (SELECT * FROM mw_SensorGlobal_bak) SG LEFT JOIN (SELECT * FROM mw_InputWaysGlobal) IWG ON SG.WAY_ID = IWG.wayID AND SG.CROSSROAD_ID = IWG.crossroadID";
+ ResultSet rs = stmt.executeQuery(statementString);
+ int label;
+
+ while (rs.next()) {
+ label = rs.getInt("NODE_ID");
+ nodes.add(gds.newNodeInstance(label));
+ sensorModelNodes.put(label, new SensorModelNode(label, !rs.getBoolean("SENSOR_TYPE"),rs.getInt("INPUT_WAY_ID"),CardinalDirection.valueOf(rs.getString("DIRECTION"))));
+ }
+
+ } catch (SQLException e) {
+ e.printStackTrace();
+ }
+ return nodes;
+ }
+
+ /**
+ * liefert das Gewicht für einen Knoten mit Sensormodell
+ * @param nodeID - globale KnotenID im Sensormodel (kann realer oder virtueller Sensor sein)
+ * @param from - Startzeitpunkt der Aggregation
+ * @param to - Endzeitpunkt der Aggregation
+ * @param timestemp - Zeitstempel für den das Gewicht berechnet wird
+ * @return
+ */
+ public double[] getSensorModelWeight(int nodeID,DateTime from, DateTime to,int timestemp){
+
+ if(sensorModelNodes.containsKey(nodeID)){
+ SensorModelNode sensorModelNode = sensorModelNodes.get(nodeID);
+ // Sensorknoten ist ein realer Sensor, Gewicht wurde bereits für alle realen Sensoren vorberechnet
+ if(sensorModelNode.isReal()){
+ if(sensorModelNode.getTimestep()==timestemp){
+ return sensorModelNode.getWeight();
+ }
+ else{
+ System.out.println("Not found");
+ double[] weight = new double[]{0,0,0};
+ sensorModelNode.setWeight(weight, timestemp);
+ return weight;
+ }
+ }
+ //Sensorknoten ist virtueller Sensor, Gewicht wird wie beim Wegemodell abgefragt und in SensorModelNode zwischengespeichert
+ else {
+ int inputWayID = sensorModelNode.getInputWayID();
+ if(inputWayID>0){
+ double[] weight = getInputWayWeight(inputWayID, from, to);
+ sensorModelNode.setWeight(weight, timestemp);
+ return weight;
+ }
+ else
+ return new double[]{0,0,0};
+ }
+ }
+ else
+ return new double[]{0,0,0};
+ }
+
+ /**
+ * liefert die Gewichte für den Einfahrtsweg
+ * @param inputWayID
+ * @param timestamp
+ * @return [0] = count, [1] = load, [2] = count/maxCount
+ */
+ public double[] getInputWayWeight(int inputWayID, DateTime timestamp) {
+ return getInputWayWeight(inputWayID, timestamp, timestamp.plusMinutes(5));
+ }
+
+ /**
+ * liefert die Gewichte für den Einfahrtsweg
+ * @param inputWayID
+ * @param timestamp
+ * @return Index 0: count/maxCount, Index 1: load
+ */
+ public double[] getInputWayWeight(int inputWayID, DateTime from, DateTime to) {
+ //leeres Intervall auf Minimallänge setzen
+ if(from.equals(to)){
+ to = from.plusMinutes(1);
+ }
+
+ double count =0;
+ double load = 0;
+
+ // Nachladen von Maximalwerten
+ if(!maxValuesInputWays.containsKey(inputWayID)){
+ maxValuesInputWays.put(inputWayID, getMaximalWeightInputWay(inputWayID) );
+ }
+ String statementString = null;
+ try {
+ int[] inputData = inputWays.get(inputWayID);
+ int crossroadID = inputData[1];
+ Statement stmt = con.createStatement();
+ // Selection des Einfahrtsweges (neueste Tabelle)
+ String inputWay = "SELECT * FROM mw_InputWaysGlobal_bak2 IWG WHERE IWG.ID ='"+inputWayID+"'";
+ // Selection der Sensordaten für den vorgegebenen Zeitraum
+ String rawData = "SELECT * FROM jee_trafficlight_rawevents RE WHERE DATETIME < '"+toSql(to)+"' AND DATETIME>='"+toSql(from)+"'";
+ // Selection der für die Gewichtsberechnung relevanten Sensoren
+ String rawSensors = "SELECT * FROM jee_crmodel_SensorDim SENSOR_DIM WHERE CROSSROAD_ID ='"+crossroadID+"'";
+ // Selection der frontSensoren
+ String frontSensors = "SELECT * FROM mw_SensorConnection FR WHERE FR.FRONT_BACK = 0";
+ // Selection aller benätigten Sensoren
+ String sensors = "SELECT SENSORS.*,DATETIME,cr_count,cr_load FROM (SELECT FRONT_AND_BACK.* FROM (SELECT S1.*, CSVOFFSET FROM (SELECT ID AS INPUTWAY_ID, IWG.wayID AS OSMWAY_ID, IWG.crossroadID AS CROSSROAD_ID, crossroadName AS CROSSROAD_NAME, sensorID AS SENSOR_ID, sensorName AS SENSOR_NAME FROM ("+inputWay+") IWG LEFT JOIN mw_SensorWays_bak SW ON IWG.wayID = SW.wayID AND IWG.crossroadID= SW.crossroadID) S1 JOIN ("+rawSensors+") S2 ON S1.SENSOR_ID = S2.ID) FRONT_AND_BACK JOIN ("+frontSensors+") ONLY_FRONT ON FRONT_AND_BACK.SENSOR_ID = ONLY_FRONT.SENSOR_ID";
+ // Abfrage des Gewichts aus den zuvor selektierten Daten
+ statementString = "SELECT SUM(ANZAHL)/COUNT(ANZAHL),SUM(BELEGUNG)/COUNT(BELEGUNG) FROM (SELECT SUM(cr_count) as ANZAHL, SUM(cr_load)/COUNT(cr_load) as BELEGUNG, DATETIME FROM ("+sensors+") SENSORS LEFT JOIN ("+rawData+") EVENTS_DAY ON SENSORS.CROSSROAD_NAME = EVENTS_DAY.CROSSROAD AND SENSORS.CSVOFFSET=EVENTS_DAY.CSVOFFSET) FINAL GROUP BY DATETIME) GROUPED";
+ ResultSet rs = stmt.executeQuery(statementString);
+ if(rs.first()){
+ count=rs.getDouble(1);
+ load=rs.getDouble(2);
+ }
+ else
+ System.out.println("ERROR - " +statementString);
+ if(count == 0 && load == 0){
+ System.out.println("InputWayWeight ist 0/0/0");
+ }
+ } catch (SQLException e) {
+ e.printStackTrace();
+ }
+ double savedMax = maxValuesInputWays.get(inputWayID)[0]; // maxCount
+ double countNorm = savedMax> 0 ? count/savedMax : 0; // keine Normierung wegen div0
+ return new double[]{count,load,countNorm*100};
+ }
+
+ /**
+ * Liefert TRUE, wenn es sich um einen realen Sensor handel, sonst FALSE
+ * @param nodeID - globale KnotenID im Sensormodell
+ * @return
+ */
+ public boolean getSensorType(int nodeID){
+ return sensorModelNodes.get(nodeID).isReal();
+ }
+
+ /**
+ * liefert die Werte für alle tatsächlichen Sensoren
+ * @param from - Startzeitpunkt der Aggregation
+ * @param to - Endzeitpunkt der Aggreagtion
+ * @return
+ */
+ public void getSensorWeights(DateTime from, DateTime to,int timestemp){
+ try {
+ Statement stmt = con.createStatement();
+ String statementString;
+ // Selection der betrachteten Sensordaten
+ String rawData = "SELECT * FROM jee_trafficlight_rawevents RE WHERE DATETIME < '"+toSql(to)+"' AND DATETIME >= '"+toSql(from)+"'";
+ // Selection der betrachteten Sensoren aus dem Modell
+ String realSensors = "SELECT * FROM mw_SensorGlobal SG WHERE SG.SENSOR_TYPE=0";
+ // Selection für die Berechnung des Gewichts
+ String endSelection = "NODE_ID,SUM(cr_count)/COUNT(cr_count) as ANZAHL, SUM(cr_load)/COUNT(cr_load) as BELEGUNG, SENSOR_ID,SENSOR_NAME,WAY_ID,CROSSROAD_ID,CROSSROAD_NAME,SENSOR_TYPE,CSVOFFSET";
+ statementString = "SELECT "+endSelection+" FROM (SELECT NODE_ID,SENSOR_ID,SENSOR_NAME,WAY_ID,CROSSROAD_ID,CROSSROAD_NAME,SENSOR_TYPE,SENSORS.CSVOFFSET,cr_count,DATETIME,cr_load FROM (SELECT NODES.*,CSVOFFSET FROM ("+realSensors+") NODES JOIN jee_crmodel_SensorDim SD ON NODES.SENSOR_ID = SD.ID) SENSORS LEFT JOIN ("+rawData+") RE ON SENSORS.CSVOFFSET = RE.CSVOFFSET AND SENSORS.CROSSROAD_NAME = RE.CROSSROAD) RESULT GROUP BY NODE_ID ";
+ ResultSet rs = stmt.executeQuery(statementString);
+ while(rs.next()){
+ if(!rs.getBoolean("SENSOR_TYPE")){
+ double[] max = maxValuesSensors.get(rs.getInt("NODE_ID"));
+ if(max == null)
+ max = new double[]{10,0};
+ sensorModelNodes.put(rs.getInt("NODE_ID"), new SensorModelNode(rs.getInt("NODE_ID"),true,new double[]{rs.getDouble("ANZAHL"), rs.getDouble("BELEGUNG"),(rs.getDouble("ANZAHL")/max[0])*100},timestemp));
+ }
+ }
+ } catch (SQLException e) {
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * liefert die Verbindungen für das Sensorenmodell (Zwischen Virtuellen Sensoren zu realen Sensoren
+ * und von realen Sensoren zu virtuellen Sensoren )
+ * @return
+ */
+ public List getSensorConnectionForDNA() {
+ List edges = new ArrayList<>();
+ try {
+ Statement vStmt = con.createStatement();
+ String statementString;
+
+ statementString = "SELECT * FROM mw_SensorConnection_Global";
+ ResultSet sensor_con = vStmt.executeQuery(statementString);
+ while(sensor_con.next() ) {
+ edges.add(new EdgeContainer(sensor_con.getInt("FROM_NODE"), sensor_con.getInt("TO_NODE")));
+ }
+ } catch (SQLException e) {
+ e.printStackTrace();
+ }
+ return edges;
+ }
+
+ /**
+ * schreibt eine Verbindung zwischen realem Sensor und virtuellem Sensor in die Datenbank
+ * @param s
+ */
+ public void writeSensorConnection(Sensor s) {
+ try {
+ Statement stmt = con.createStatement();
+ String insertString;
+
+ int wayID;
+ int crossroadID;
+ for (InputWay connectedInputWay : s.getConnections().values()) {
+
+ wayID = connectedInputWay.getWayID();
+ crossroadID = connectedInputWay.getCrossroadID();
+
+ // realer Sensor
+ String from = "SELECT NODE_ID as FROM_NODE_ID FROM mw_SensorGlobal WHERE mw_SensorGlobal.SENSOR_ID ='"+s.getSensorID()+"' AND CROSSROAD_ID = '"+s.getCrossroadID()+"'";
+ // virtueller Sensor
+ String to = "SELECT NODE_ID as TO_NODE_ID FROM mw_SensorGlobal SG WHERE SG.SENSOR_TYPE=1 AND SG.CROSSROAD_ID = '"+crossroadID+"' AND SG.WAY_ID = '"+wayID+"'";
+ insertString="INSERT IGNORE INTO mw_SensorGlobalConnection SELECT * FROM ("+from+") A , ("+to+") B ";
+ stmt.executeUpdate(insertString);
+ }
+ } catch (SQLException e) {
+ e.printStackTrace();
+ }
+
+ }
+
+
+ /**
+ * setzt die temporär deaktiveren Kanten für die Zwischenspeicherung
+ * @param disabledEdges
+ */
+ public void setDisabledEdges(HashMap disabledEdges){
+ this.disabledEdges=disabledEdges;
+ }
+ /**
+ * setzt die temporär deaktiveren Kanten für die Zwischenspeicherung für das Wegemodell
+ * @param disabledEdges
+ */
+ public void setDisabledEdgesInputWay(HashMap> disabledEdges){
+ this.disabledEdgesInputWay=disabledEdges;
+ }
+
+ /**
+ * liefert die temporär deaktiveren Kanten aus der Zwischenspeicherung
+ * @return
+ */
+ public HashMap getDisabledEdges(){
+ return disabledEdges;
+ }
+
+ /**
+ * liefert die temporär deaktiveren Kanten aus der Zwischenspeicherung für das Wegemodell
+ * @return
+ */
+ public HashMap> getDisabledEdgesInputWay(){
+ return disabledEdgesInputWay;
+ }
+
+
+ /**
+ * liefert das statische Gewicht im Wegemodell für die Initialisierung
+ * @param index - Knotenindex
+ * @param trafficUpdate - beinhaltet die statischen Daten
+ * @return
+ */
+ public double[] getInputWayWeightStaticInit(int index,TrafficUpdate trafficUpdate) {
+ double count = trafficUpdate.getInitCount();
+ double load = trafficUpdate.getInitLoad();
+ double savedMax = (maxValuesInputWays.containsKey(index)) ?(double) maxValuesInputWays.get(index)[0] : 0;
+ double countNorm = savedMax> 0 ? Double.valueOf(count)/savedMax : 0;
+ return new double[]{count,load,countNorm*100};
+ }
+
+ /**
+ * liefert das statische Gewicht im Wegemodell für den Batch
+ * @param index - Knotenindex
+ * @param trafficUpdate - beinhaltet die statischen Daten
+ * @return
+ */
+ public double[] getInputWayWeightStaticBatch(int index,TrafficUpdate trafficUpdate) {
+ double count = (trafficUpdate.getSleepTillUpdate()*trafficUpdate.getInitCount()+trafficUpdate.getUpdateCount())/(trafficUpdate.getSleepTillUpdate()+1);
+ double load = (trafficUpdate.getSleepTillUpdate()*trafficUpdate.getInitLoad()+trafficUpdate.getUpdateLoad())/(trafficUpdate.getSleepTillUpdate()+1);
+ double savedMax = (maxValuesInputWays.containsKey(index)) ? maxValuesInputWays.get(index)[0] : 0;
+ double countNorm = savedMax> 0 ? count/savedMax : 0;
+ return new double[]{count,load,countNorm*100};
+ }
+
+ /**
+ * liefert das statische Gewicht im Sensormodell für die Initialisierung
+ * @param index - Knotenindex
+ * @param trafficUpdate - beinhaltet die statischen Daten
+ * @return
+ */
+ public double[] getSensorModelWeightStaticInit(int index,TrafficUpdate trafficUpdate) {
+ if(trafficUpdate.getModus()==0){
+ if(sensorModelNodes.containsKey(index)){
+ SensorModelNode sensorModelNode = sensorModelNodes.get(index);
+ double count = trafficUpdate.getInitCount();
+ double load = trafficUpdate.getInitLoad();
+ double countNorm;
+ if(getSensorType(index)){
+ if(maxValuesSensors.containsKey(index))
+ countNorm = (count/maxValuesSensors.get(index)[0]);
+ else
+ countNorm = (count/50);
+ }
+ else{
+ double savedMax = (maxValuesInputWays.containsKey(sensorModelNode.getInputWayID())) ? maxValuesInputWays.get(sensorModelNode.getInputWayID())[0] : 0;
+ countNorm = savedMax> 0 ? count/savedMax : 0;
+ }
+ return new double[]{count,load,countNorm*100};
+ }
+ else
+ return new double[]{0,0,0};
+ }
+ else{
+ return new double[]{-1,-1,trafficUpdate.getInitUtilization()*100};
+ }
+ }
+
+ /**
+ * liefert das statische Gewicht im Sensormodell für den Batch
+ * @param index - Knotenindex
+ * @param trafficUpdate - beinhaltet die statischen Daten
+ * @return
+ */
+ public double[] getSensorModelWeightStaticBatch(int index,TrafficUpdate trafficUpdate) {
+ if(trafficUpdate.getModus()==0){
+ if(sensorModelNodes.containsKey(index)){
+ SensorModelNode sensorModelNode = sensorModelNodes.get(index);
+ if(sensorModelNode.isReal()){
+ // Count-Wert des Sensors
+ double count = (trafficUpdate.getSleepTillUpdate()*trafficUpdate.getInitCount()+trafficUpdate.getUpdateCount())/(trafficUpdate.getSleepTillUpdate()+1);
+ // Load-Wert des Sensors
+ double load = (trafficUpdate.getSleepTillUpdate()*trafficUpdate.getInitLoad()+trafficUpdate.getUpdateLoad())/(trafficUpdate.getSleepTillUpdate()+1);
+ // Maximalwert des sensors (hier statisch)
+ double savedMax = maxValuesSensors.get(sensorModelNode.getNodeID())[0];
+ // Normierter Count-Wert
+ double countNorm = savedMax> 0 ? count/savedMax : 0;
+ return new double[]{count,load,countNorm*100};
+ }
+ else
+ return getInputWayWeightStaticBatch(sensorModelNode.getInputWayID(), trafficUpdate);
+ }
+ else
+ return new double[]{0,0,0};
+ }
+ else{
+ return new double[]{-1,-1,trafficUpdate.getUpdateUtilization()*100};
+ }
+ }
+
+}
diff --git a/src/dna/graph/generators/traffic/EdgeContainer.java b/src/dna/graph/generators/traffic/EdgeContainer.java
new file mode 100644
index 00000000..b17fda14
--- /dev/null
+++ b/src/dna/graph/generators/traffic/EdgeContainer.java
@@ -0,0 +1,67 @@
+package dna.graph.generators.traffic;
+
+import java.util.Arrays;
+
+/**
+ * Container-Klasse für Edge-Information
+ * @author Maurice
+ *
+ */
+public class EdgeContainer {
+ private int from;
+ private int to;
+
+ /**
+ * Konstruktur für den EdgeContainer
+ * @param from - Startknoten der Kante
+ * @param to - Endknoten der Kante
+ */
+ public EdgeContainer(int from, int to){
+ this.from = from;
+ this.to = to;
+ }
+
+ /**
+ * liefert den HashCode des Containers, abgeleitet aus der Array-Darstellung
+ */
+ public int hashCode(){
+ return Arrays.hashCode(new int[]{from,to});
+ }
+
+ /**
+ * vergleicht das Objekt mit einem übergebenen Objekt
+ * @return true, wenn Startknoten und Endknoten identisch, sonst false
+ */
+ public boolean equals(Object obj) {
+ if( obj instanceof EdgeContainer){
+ EdgeContainer ec = (EdgeContainer) obj;
+ return Arrays.equals(new int[]{from, to},new int[]{ec.from,ec.to});
+ }
+ else
+ return false;
+ }
+
+ /**
+ * Ausgabe für die manuelle Kontrolle
+ * @return
+ */
+ public String toString(){
+ return "FROM:"+from+"\tTO:"+to;
+ }
+
+ /**
+ * liefert den Startknoten
+ * @return
+ */
+ public int getFrom(){
+ return from;
+ }
+
+ /**
+ * liefert den Zielknoten
+ * @return
+ */
+ public int getTo(){
+ return to;
+ }
+}
diff --git a/src/dna/graph/generators/traffic/InputWay.java b/src/dna/graph/generators/traffic/InputWay.java
new file mode 100644
index 00000000..3840e37a
--- /dev/null
+++ b/src/dna/graph/generators/traffic/InputWay.java
@@ -0,0 +1,64 @@
+package dna.graph.generators.traffic;
+
+import java.util.Arrays;
+
+/**
+ * Containerklasse für einen Einfahrtsweg
+ * @author Maurice
+ *
+ */
+public class InputWay {
+
+ private int wayID; // OSM-WayID
+ private int crossroadID; // globale Kreuzungs-ID
+
+ public InputWay(int wayID, int crossroadID) {
+ this.wayID=wayID;
+ this.crossroadID=crossroadID;
+ }
+
+ /**
+ * Kontrollausgbae
+ */
+ public String toString(){
+ return "Einfahrtsweg: wayID:"+String.valueOf(wayID) + "\t crossroadID:"+crossroadID;
+ }
+
+ /**
+ * liefert den HashCode des Einfahrtsweges basierend auf der Array-Darstellung
+ */
+ public int hashCode(){
+ return Arrays.hashCode(new int[]{wayID,crossroadID});
+ }
+
+ /**
+ * liefert die OSM-ID für den Weg
+ * @return
+ */
+ public int getWayID(){
+ return wayID;
+ }
+
+ /**
+ * liefert die KreuzungsID für den Weg
+ * @return
+ */
+ public int getCrossroadID(){
+ return crossroadID;
+ }
+
+ /**
+ * vergleicht das Objekt mit dem übergebenen Objekt auf Gleichheit
+ * @param obj, zu vergleichendes Objekt
+ * @return true, wenn das übergebene Objekt den gleichen Einfahrtsweg repräsentiert
+ */
+ public boolean equals(Object obj) {
+ if(obj instanceof InputWay){
+ InputWay inputWay = (InputWay) obj;
+ return Arrays.equals(new int[]{wayID,crossroadID}, new int[]{inputWay.wayID,inputWay.crossroadID});
+ }
+ else
+ return false;
+ }
+
+}
diff --git a/src/dna/graph/generators/traffic/InputWayConnection.java b/src/dna/graph/generators/traffic/InputWayConnection.java
new file mode 100644
index 00000000..b1abcc03
--- /dev/null
+++ b/src/dna/graph/generators/traffic/InputWayConnection.java
@@ -0,0 +1,78 @@
+package dna.graph.generators.traffic;
+
+/**
+ * Container-Klasse für Verbindungen zwischen Einfahrtswegen
+ * @author Maurice
+ *
+ */
+public class InputWayConnection {
+ private int fromCrossroad;
+ private int fromWayID;
+ private CardinalDirection fromWayDirection;
+ private int toCrossroad;
+ private int toWayID;
+ private CardinalDirection toWayDirection;
+
+
+ public InputWayConnection(int fromCrossroad, int fromWayID,CardinalDirection fromWayDirection, int toCrossroad, int toWayID,CardinalDirection toWayDirection) {
+ this.fromCrossroad=fromCrossroad;
+ this.fromWayID=fromWayID;
+ this.toCrossroad=toCrossroad;
+ this.toWayID=toWayID;
+ }
+
+ /**
+ * liefert die Startkreuzung
+ * @return
+ */
+ public int getFromCrossroad(){
+ return fromCrossroad;
+ }
+
+ /**
+ * liefert den Startweg
+ * @return
+ */
+ public int getFromWayID(){
+ return fromWayID;
+ }
+
+ /**
+ * liefert die Startrichtung
+ * @return
+ */
+ public CardinalDirection getFromWayDirection(){
+ return fromWayDirection;
+ }
+
+ /**
+ * liefert die Zielkreuzung
+ * @return
+ */
+ public int getToCrossroad(){
+ return toCrossroad;
+ }
+
+ /**
+ * liefert den Zielweg
+ * @return
+ */
+ public int getToWayID(){
+ return toWayID;
+ }
+
+ /**
+ * liefert die Richtung des Zielweges
+ * @return
+ */
+ public CardinalDirection getToWayDirection(){
+ return toWayDirection;
+ }
+
+ /**
+ * Kontrollausgabe für die Verbindung von Wegen
+ */
+ public String toString() {
+ return "Connected " + fromWayID + " on " +fromCrossroad + " with " +toWayID + " on " + toCrossroad;
+ }
+}
diff --git a/src/dna/graph/generators/traffic/Sensor.java b/src/dna/graph/generators/traffic/Sensor.java
new file mode 100644
index 00000000..e2eb81a1
--- /dev/null
+++ b/src/dna/graph/generators/traffic/Sensor.java
@@ -0,0 +1,128 @@
+package dna.graph.generators.traffic;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Container-Klasse für einen realen Sensor
+ * @author Maurice
+ *
+ */
+public class Sensor {
+ private int sensorID;
+ private String sensorName;
+ private int crossroadID;
+ private String crossroadName;
+ private int wayID;
+ private Set outputDiretions;
+ private HashMap connections;
+
+ /**
+ * Konstruktur für die nachträgliche Berechnung
+ * @param sensorID
+ * @param sensorName
+ * @param crossroadID
+ * @param crossroadName
+ * @param wayID
+ * @param outputDirections
+ */
+ public Sensor(int sensorID, String sensorName, int crossroadID, String crossroadName, int wayID,Set outputDirections){
+ this.sensorID=sensorID;
+ this.sensorName=sensorName;
+ this.crossroadID=crossroadID;
+ this.crossroadName=crossroadName;
+ this.wayID=wayID;
+ this.outputDiretions=outputDirections;
+ }
+
+ /**
+ * Konstruktur für die Nutzung als Container
+ * @param sensorID
+ * @param sensorName
+ * @param crossroadID
+ * @param crossroadName
+ * @param wayID
+ */
+ public Sensor(int sensorID, String sensorName, int crossroadID, String crossroadName, int wayID){
+ this.sensorID=sensorID;
+ this.sensorName=sensorName;
+ this.crossroadID=crossroadID;
+ this.crossroadName=crossroadName;
+ this.wayID=wayID;
+ }
+ /**
+ * liefert die globale ID des Sensors
+ * @return
+ */
+ public int getSensorID(){
+ return sensorID;
+ }
+
+ /**
+ * liefert den Namen des Sensors
+ * @return
+ */
+ public String getSensorName(){
+ return sensorName;
+ }
+
+ /**
+ * liefert die globale Kreuzungs-ID
+ * @return
+ */
+ public int getCrossroadID(){
+ return crossroadID;
+ }
+
+ /**
+ * liefert den Namen der Kreuzung
+ * @return
+ */
+ public String getCrossroadName(){
+ return crossroadName;
+ }
+
+ public int getWayID(){
+ return wayID;
+ }
+
+ /**
+ * berechnet die Verbindungen zwischen den Ausfahrtswegen des Sensors und den Einfahrtswegen benachbarter Kreuzungen
+ * @param outputConnection Abbiegemöglichkeiten des Sensors
+ * @return Verbindungen mit Einfahrtswegen
+ */
+ public HashMap calculateConnections(HashMap outputConnection) {
+ HashMap connections = new HashMap<>();
+ // Über alle Abbiegemöglichkeiten
+ for (CardinalDirection output : outputDiretions) {
+ // Ausfahrtsweg ist mit Einfahrtsweg benachbarter Kreuzung verbunden
+ if(outputConnection.containsKey(output))
+ connections.put(output, outputConnection.get(output));
+ }
+ this.connections=connections;
+ return connections;
+ }
+
+ /**
+ * liefert die berechneten Verbindungen aus {@link #calculateConnections(HashMap)}
+ * @return
+ */
+ public HashMap getConnections() {
+ return connections;
+ }
+
+
+ /**
+ * Kontrollausgabe
+ */
+ public void printConnection() {
+ System.out.println("Verbindungen von:\t"+sensorID+"("+sensorName+") on " +crossroadID+"("+crossroadName+")");
+ for (Map.Entry connection : connections.entrySet()) {
+ System.out.println("\t\t"+connection.getKey()+"\t"+connection.getValue());
+ }
+
+ }
+
+
+}
diff --git a/src/dna/graph/generators/traffic/SensorModelNode.java b/src/dna/graph/generators/traffic/SensorModelNode.java
new file mode 100644
index 00000000..5d5659a3
--- /dev/null
+++ b/src/dna/graph/generators/traffic/SensorModelNode.java
@@ -0,0 +1,69 @@
+package dna.graph.generators.traffic;
+
+
+public class SensorModelNode {
+ private double[] weight;
+ private boolean isReal;
+ private int nodeID;
+ private int timestep;
+ private int inputWayID;
+ private CardinalDirection direction;
+
+ public SensorModelNode(int nodeID, boolean isReal){
+ this.nodeID=nodeID;
+ this.isReal=isReal;
+ this.timestep=-1;
+ }
+
+ public SensorModelNode(int nodeID, boolean isReal,double[] weight,int timestep){
+ this.nodeID=nodeID;
+ this.isReal=isReal;
+ this.weight=weight;
+ this.timestep=timestep;
+ }
+
+ public SensorModelNode(int nodeID, boolean isReal,double[] weight,int timestep,int inputWayID){
+ this.nodeID=nodeID;
+ this.isReal=isReal;
+ this.weight=weight;
+ this.timestep=timestep;
+ this.inputWayID = inputWayID;
+ }
+
+ public SensorModelNode(int nodeID, boolean isReal,int inputWayID, CardinalDirection direction){
+ this.nodeID=nodeID;
+ this.isReal=isReal;
+ this.inputWayID = inputWayID;
+ this.direction = direction;
+ this.timestep=-1;
+ }
+
+ public double[] getWeight(){
+ return weight;
+ }
+
+ public void setWeight(double[] weight, int timestep){
+ this.weight=weight;
+ this.timestep=timestep;
+ }
+
+ public boolean isReal(){
+ return isReal;
+ }
+
+ public int getNodeID(){
+ return nodeID;
+ }
+
+ public int getTimestep(){
+ return timestep;
+ }
+
+ public int getInputWayID(){
+ return inputWayID;
+ }
+
+ public CardinalDirection getDirection(){
+ return direction;
+ }
+}
diff --git a/src/dna/graph/generators/traffic/TrafficConfig.java b/src/dna/graph/generators/traffic/TrafficConfig.java
new file mode 100644
index 00000000..6b2b77c0
--- /dev/null
+++ b/src/dna/graph/generators/traffic/TrafficConfig.java
@@ -0,0 +1,223 @@
+package dna.graph.generators.traffic;
+
+
+import org.joda.time.DateTime;
+
+import dna.updates.generators.traffic.Helpers;
+
+public class TrafficConfig {
+
+ private DateTime initDateTime;
+ private int stepSize;
+
+ // Auswahl des Modells und Modus
+ private TrafficModel model;
+ private String graphGeneratorName;
+ private String batchGeneratorName;
+ private TrafficModi modus;
+ private double treshold; // Schwellwert, ab dem ein Knoten �berlastet ist
+
+ // Parameter f�r Tages-Modus
+ private boolean[] daySelection;
+ private int timeRange;
+ private DateTime holidayStart = new DateTime(2014,10,6,7,0,0);
+ private int observationWeeks = 1;
+
+ private int[] nodesFilter;
+
+ // Parameter f�r die Simulation
+ private TrafficUpdate trafficUpdate;
+
+ /**
+ * Basis-Konstruktor
+ * @param modus
+ * @param nodesFilter
+ * @param initDateTime
+ */
+ private TrafficConfig(TrafficModi modus, TrafficModel model, double treshold, int[] nodesFilter, DateTime initDateTime ){
+ this.modus = modus;
+ this.model = model;
+ this.treshold = treshold;
+ this.nodesFilter = nodesFilter;
+ this.initDateTime = initDateTime;
+
+ // Namensgenerierung
+
+ switch (model) {
+ case CrossroadModel:
+ graphGeneratorName = "CrossroadGraph";
+ batchGeneratorName = "CrossroadBatch";
+ break;
+
+ case WayModel:
+ graphGeneratorName = "InputWayGraph";
+ batchGeneratorName = "InputWayBatch";
+ break;
+
+ case SensorModel:
+ graphGeneratorName = "SensorGraph";
+ batchGeneratorName = "SensorBatch";
+ break;
+
+ default:
+ graphGeneratorName = "DefaultTrafficGraph";
+ batchGeneratorName = "DefaultTrafficBatch";
+ break;
+ }
+ }
+
+ /**
+ * Konstruktor für den Continuous-Modus
+ * @param modus
+ * @param nodesFilter
+ * @param initDateTime
+ * @param stepsize
+ */
+ private TrafficConfig(TrafficModi modus, TrafficModel model, double treshold, int[] nodesFilter, DateTime initDateTime, int stepsize){
+ this(modus,model,treshold,nodesFilter,initDateTime);
+ this.stepSize = stepsize;
+ }
+ /**
+ * Konstruktor für den DayTimeRange-Modus und den Aggregation-Modus
+ * @param modus
+ * @param treshold
+ * @param nodesFilter
+ * @param initDateTime
+ * @param timeRange
+ * @param daySelection
+ * @param holidayStart
+ */
+ private TrafficConfig(TrafficModi modus, TrafficModel model, double treshold, int[] nodesFilter, DateTime initDateTime, int timeRange, boolean[] daySelection, DateTime holidayStart){
+ this(modus,model,treshold,nodesFilter,initDateTime);
+ this.timeRange = timeRange;
+ this.daySelection = daySelection;
+ this.holidayStart = holidayStart;
+ }
+
+ /**
+ * Konsruktor für den Simulations-Modus
+ * @param modus
+ * @param treshold
+ * @param nodesFilter
+ * @param initDateTime
+ * @param trafficUpdate
+ */
+ private TrafficConfig(TrafficModi modus, TrafficModel model, double treshold, int[] nodesFilter, DateTime initDateTime, TrafficUpdate trafficUpdate){
+ this(modus,model,treshold,nodesFilter,initDateTime);
+ this.trafficUpdate = trafficUpdate;
+ }
+
+
+ /**
+ * liefert eine gültige TrafficConfig für die Verwendung des Continous-Modus
+ * @param model
+ * @param treshold
+ * @param nodesFilter
+ * @param initDateTime
+ * @param stepsize
+ * @return
+ */
+ public static TrafficConfig getContinousConfig(TrafficModel model, double treshold, int[] nodesFilter, DateTime initDateTime, int stepSize){
+ return new TrafficConfig(TrafficModi.Continuous,model,treshold, nodesFilter, initDateTime, stepSize);
+ }
+
+ /**
+ * liefert eine gültige TrafficConfig für die Verwendung des DayTimeRange-Modus
+ * @param model
+ * @param treshold
+ * @param nodesFilter
+ * @param initDateTime
+ * @param timeRange
+ * @param daySelection
+ * @param holidayStart
+ * @return
+ */
+ public static TrafficConfig getDayTimeRangeConfig(TrafficModel model, double treshold, int[] nodesFilter, DateTime initDateTime, int timeRange, boolean[] daySelection, DateTime holidayStart){
+ return new TrafficConfig(TrafficModi.DayTimeRange, model, treshold, nodesFilter, initDateTime, timeRange, daySelection, holidayStart);
+ }
+
+ /**
+ * liefert eine gültige TrafficConfig für die Verwendung des Aggregations-Modus
+ * @param model
+ * @param treshold
+ * @param nodesFilter
+ * @param initDateTime
+ * @param holidayStart2
+ * @param daySelection2
+ * @param timeRange2
+ * @return
+ */
+ public static TrafficConfig getAggregationConfig(TrafficModel model, double treshold, int[] nodesFilter, DateTime initDateTime, int timeRange, boolean[] daySelection, DateTime holidayStart){
+ return new TrafficConfig(TrafficModi.Aggregation, model, treshold, nodesFilter,initDateTime, timeRange, daySelection,holidayStart);
+ }
+
+ /**
+ * liefert eine gültige TrafficConfig für die Verwendung des Simulations-Modus
+ * @param model
+ * @param treshold
+ * @param nodesFilter
+ * @param initDateTime
+ * @param trafficUpdate
+ * @return
+ */
+ public static TrafficConfig getSimulationConfig(TrafficModel model, double treshold, int[] nodesFilter, DateTime initDateTime, TrafficUpdate trafficUpdate){
+ return new TrafficConfig(TrafficModi.Simulation, model, treshold, nodesFilter, initDateTime, trafficUpdate);
+ }
+
+ public TrafficModel getModel(){
+ return model;
+ }
+
+ public TrafficModi getModus(){
+ return modus;
+ }
+
+ public String getGraphName(){
+ return graphGeneratorName;
+ }
+
+ public String getBatchName(){
+ return batchGeneratorName;
+ }
+
+ public DateTime getInitDateTime(){
+ return initDateTime;
+ }
+
+ public int getStepSize(){
+ return stepSize;
+ }
+
+ public int getTimeRange(){
+ return timeRange;
+ }
+
+ public TrafficUpdate getTrafficUpdate(){
+ return trafficUpdate;
+ }
+
+ public int[] getNodesFilter(){
+ return nodesFilter;
+ }
+
+ public double getTreshold(){
+ return treshold;
+ }
+
+ public DateTime getHolidayStart(){
+ return holidayStart;
+ }
+
+ public boolean[] getDaySelection(){
+ return daySelection;
+ }
+
+ public int getOberservationDays(){
+ if(modus == TrafficModi.Aggregation)
+ return Helpers.weekToDay(observationWeeks, daySelection);
+ else
+ return 1;
+
+ }
+
+}
diff --git a/src/dna/graph/generators/traffic/TrafficCrossroadGraphGenerator.java b/src/dna/graph/generators/traffic/TrafficCrossroadGraphGenerator.java
new file mode 100644
index 00000000..5b2d3070
--- /dev/null
+++ b/src/dna/graph/generators/traffic/TrafficCrossroadGraphGenerator.java
@@ -0,0 +1,165 @@
+package dna.graph.generators.traffic;
+
+import java.util.HashMap;
+import java.util.List;
+
+import org.joda.time.DateTime;
+
+import dna.graph.Graph;
+import dna.graph.datastructures.GraphDataStructure;
+import dna.graph.edges.Edge;
+import dna.graph.generators.GraphGenerator;
+import dna.graph.nodes.DirectedWeightedNode;
+import dna.graph.nodes.INode;
+import dna.graph.nodes.Node;
+import dna.graph.weights.Double3dWeight;
+import dna.util.parameters.Parameter;
+
+public class TrafficCrossroadGraphGenerator extends GraphGenerator{
+
+ private DB db;
+
+ // Allgemeine Parameter
+ private TrafficModi modus;
+ private DateTime initDateTime;
+ private int[] nodesFilter;
+
+ // Continuous
+ private int stepsize;
+
+ // Daytime-Range Aggregation
+ private int timeRange;
+
+ // Simulation
+ private TrafficUpdate trafficUpdate;
+
+
+ public TrafficCrossroadGraphGenerator(String name, GraphDataStructure gds, DB db,long timeStampInit,TrafficModi modus, DateTime initDateTime, int stepsize,int timeRange,TrafficUpdate trafficupdate, int[] nodesFilter) {
+ this(name, null, gds,timeStampInit, 0, 0,db,modus,initDateTime,stepsize,timeRange,trafficupdate,nodesFilter);
+ }
+
+ public TrafficCrossroadGraphGenerator(String name, Parameter[] params,
+ GraphDataStructure gds, long timestampInit, int nodesInit,
+ int edgesInit,DB db,TrafficModi modus,DateTime initDateTime,int stepsize,int timeRange,TrafficUpdate trafficUpdate, int[] nodesFilter) {
+ super(name, params, gds, timestampInit, nodesInit, edgesInit);
+ this.db= db;
+ this.modus=modus;
+ this.initDateTime=initDateTime;
+ this.stepsize = stepsize;
+ this.timeRange = timeRange;
+ this.trafficUpdate = trafficUpdate;
+ this.nodesFilter = nodesFilter;
+ }
+
+ public TrafficCrossroadGraphGenerator(TrafficConfig tc, GraphDataStructure gds, DB db, long timeStampInit){
+ super(tc.getGraphName(), null, gds, timeStampInit,0,0);
+ this.db = db;
+ this.modus = tc.getModus();
+ this.initDateTime = tc.getInitDateTime();
+ this.stepsize = tc.getStepSize();
+ this.timeRange = tc.getTimeRange();
+ this.trafficUpdate = tc.getTrafficUpdate();
+ this.nodesFilter = tc.getNodesFilter();
+ }
+
+ @Override
+ public Graph generate() {
+
+ Graph g = this.newGraphInstance();
+ List nodes = null;
+ HashMap disabledEdges = new HashMap<>();
+
+ // Lade abstrakte Knoten gemäß dem NodesFilter
+ nodes = db.getCrossroadsForDNA(nodesFilter);
+
+ CrossroadWeight crossroadWeight = null;
+ Node currentNode = null;
+ DirectedWeightedNode currentWeighted = null;
+
+ // Berechne das Gewicht des abstrakten Knoten gemäß definiertem Modus
+ for (int i = 0; i < nodes.size(); i++) {
+
+ currentNode = (Node) nodes.get(i);
+ if(currentNode instanceof DirectedWeightedNode)
+ currentWeighted = (DirectedWeightedNode) currentNode;
+ else{
+ continue;
+ }
+
+ switch (modus) {
+
+ case Continuous:
+ crossroadWeight = db.getCrossroadWeight(currentWeighted.getIndex(),initDateTime,initDateTime.plusMinutes(stepsize),timestampInit);
+ break;
+
+ case DayTimeRange: case Aggregation:
+ crossroadWeight = db.getCrossroadWeight(currentWeighted.getIndex(),initDateTime.minusMinutes(timeRange),initDateTime.plusMinutes(timeRange),timestampInit);
+ break;
+
+ case Simulation:
+ crossroadWeight = db.getCrossroadWeightStaticInit(currentWeighted.getIndex(),initDateTime,initDateTime.plusMinutes(1),timestampInit,trafficUpdate);
+ break;
+
+ default:
+ System.out.println("error - Modus nicht definiert");
+ break;
+
+ }
+
+ double[] weight = crossroadWeight.getWeight();
+
+ if(modus == TrafficModi.DayTimeRange)
+ db.setMaximalWeightsCrossroadImproved(currentWeighted.getIndex(), weight[0], weight[1], initDateTime, timeRange);
+
+ currentWeighted.setWeight(new Double3dWeight(weight[0],weight[1],weight[2]));
+
+ g.addNode(currentWeighted);
+
+ // Entferne die ueberlasteten Kanten
+ EdgeContainer ec = null;
+ for (Integer wayId : crossroadWeight.getOverladedEdges().keySet()) {
+ List edgesToRemove = db.getFromWays(currentWeighted.getIndex(), wayId);
+ if(edgesToRemove != null){
+ for (int[] way : edgesToRemove) {
+ ec = new EdgeContainer(way[0], currentNode.getIndex());
+ disabledEdges.put(ec, null);
+ }
+ }
+ }
+ }
+
+ // Kanten
+
+ List connection = db.getCrossroadConnectionForDNA(nodesFilter);
+ EdgeContainer current = null;
+
+ Node fromNode;
+ Node toNode;
+ Edge e;
+ for (int i = 0; i < connection.size(); i++) {
+
+ current = connection.get(i);
+ fromNode = g.getNode(current.getFrom());
+ toNode = g.getNode(current.getTo());
+
+ if(fromNode!= null && toNode!=null)
+ e = gds.newEdgeInstance(fromNode, toNode);
+ else
+ continue;
+
+ if(disabledEdges.containsKey(current)){
+ disabledEdges.put(current, e);
+ }
+ else{
+ e.connectToNodes();
+ g.addEdge(e);
+ }
+
+ }
+
+ // Speichere die deaktiverten Kanten für den Batch in die DB-Klasse
+ db.setDisabledEdges(disabledEdges);
+ return g;
+ }
+
+}
diff --git a/src/dna/graph/generators/traffic/TrafficInputWayGraphGenerator.java b/src/dna/graph/generators/traffic/TrafficInputWayGraphGenerator.java
new file mode 100644
index 00000000..5bdb888e
--- /dev/null
+++ b/src/dna/graph/generators/traffic/TrafficInputWayGraphGenerator.java
@@ -0,0 +1,190 @@
+package dna.graph.generators.traffic;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.joda.time.DateTime;
+
+import dna.graph.Graph;
+import dna.graph.datastructures.GraphDataStructure;
+import dna.graph.edges.Edge;
+import dna.graph.generators.GraphGenerator;
+import dna.graph.nodes.DirectedWeightedNode;
+import dna.graph.nodes.INode;
+import dna.graph.nodes.Node;
+import dna.graph.weights.Double3dWeight;
+import dna.util.parameters.Parameter;
+
+public class TrafficInputWayGraphGenerator extends GraphGenerator{
+
+ private DB db;
+
+ // Allgemeine Parameter
+ private TrafficModi modus;
+ private DateTime initDateTime;
+ private int[] nodesFilter;
+
+ // Continuous-Modus
+ private int stepSize;
+
+ // DayTimeRange / Aggregation
+ private int timeRange;
+ private double treshold;
+
+ // Simulation
+ private TrafficUpdate trafficUpdate;
+
+
+ private HashMap> disabledEdges = new HashMap<>();
+
+
+ public TrafficInputWayGraphGenerator(String name, GraphDataStructure gds, DB db, long timeStamp, TrafficModi modus, DateTime initDateTime, int stepsize,int timeRange,TrafficUpdate trafficupdate,double treshold, int[] nodesFilter) {
+ this(name, null, gds,timeStamp, 0, 0,db, modus,initDateTime,stepsize,timeRange,trafficupdate,treshold, nodesFilter);
+ }
+
+ public TrafficInputWayGraphGenerator(String name, Parameter[] params,
+ GraphDataStructure gds, long timestampInit, int nodesInit,
+ int edgesInit,DB db,TrafficModi modus, DateTime initDateTime, int stepsize,int timeRange,TrafficUpdate trafficupdate,double treshold, int[] nodesFilter) {
+ super(name, params, gds, timestampInit, nodesInit, edgesInit);
+ this.db= db;
+ this.modus = modus;
+ this.initDateTime = initDateTime;
+ this.stepSize = stepsize;
+ this.timeRange = timeRange;
+ this.trafficUpdate = trafficupdate;
+ this.treshold = treshold;
+ this.nodesFilter = nodesFilter;
+ }
+
+ /**
+ * Erstellt einen GraphGenerator für das WayModel für die übergebene TrafficConfig
+ * @param tc
+ * @param gds
+ * @param db
+ * @param timeStampInit
+ */
+ public TrafficInputWayGraphGenerator(TrafficConfig tc, GraphDataStructure gds, DB db, long timeStampInit){
+ super(tc.getGraphName(), null, gds, timeStampInit,0,0);
+ this.db = db;
+ this.modus = tc.getModus();
+ this.initDateTime = tc.getInitDateTime();
+ this.stepSize = tc.getStepSize();
+ this.timeRange = tc.getTimeRange();
+ this.trafficUpdate = tc.getTrafficUpdate();
+ this.treshold = tc.getTreshold();
+ this.nodesFilter = tc.getNodesFilter();
+ }
+
+ @Override
+ public Graph generate() {
+ Graph g = this.newGraphInstance();
+
+
+ List nodes = null;
+ Set overloaded = new HashSet<>();
+
+
+ // Knoten
+
+ // Lade abstrakte Knoten gemäß NodesFilter
+ nodes = db.getInputWaysForDNA(nodesFilter);
+
+ Node currentNode = null;
+ DirectedWeightedNode currentWeighted = null;
+ double[] weight = null;
+
+ // Berechne für jeden abstrakten Knoten das Gewicht gemäß des ausgewählten Modus
+ for (int i = 0; i < nodes.size(); i++) {
+ currentNode = (Node) nodes.get(i);
+
+ if(currentNode instanceof DirectedWeightedNode)
+ currentWeighted = (DirectedWeightedNode) currentNode;
+ else{
+ continue;
+ }
+
+ switch (modus) {
+ case Continuous:
+ weight = db.getInputWayWeight(currentWeighted.getIndex(), initDateTime, initDateTime.plusMinutes(stepSize));
+ break;
+
+ case DayTimeRange: case Aggregation:
+ weight = db.getInputWayWeight(currentWeighted.getIndex(),initDateTime.minusMinutes(timeRange),initDateTime.plusMinutes(timeRange));
+ break;
+
+ case Simulation:
+ weight = db.getInputWayWeightStaticInit(currentWeighted.getIndex(),trafficUpdate);
+ break;
+
+ default:
+ System.out.println("error - Modus nicht definiert @ TrafficInputwayGraphGenerator");
+ break;
+
+ }
+
+ // Knoten ist überlastet
+ if(weight[2] > treshold){
+ overloaded.add(currentWeighted.getIndex());
+ }
+
+ currentWeighted.setWeight(new Double3dWeight(weight[0],weight[1],weight[2]));
+ g.addNode(currentWeighted);
+
+ }
+
+ // Kanten
+
+ // Lade die Kanten für die durch NodesFilter definierten Knoten
+ List connection = db.getInputWaysConnectionForDNA(nodesFilter);
+
+ DirectedWeightedNode fromNode = null;
+ DirectedWeightedNode toNode = null;
+ Edge e = null;
+ EdgeContainer ec = null;
+
+ // Prüfe für jede Kante, ob sie gültig oder überlastet ist, sortiere dementsprechend ein
+ for (int i = 0; i < connection.size(); i++) {
+ ec = connection.get(i);
+ fromNode = (DirectedWeightedNode) g.getNode(ec.getFrom());
+ toNode = (DirectedWeightedNode) g.getNode(ec.getTo());
+
+ if(fromNode != null && toNode != null)
+ e = gds.newEdgeInstance(fromNode,toNode);
+ else
+ continue;
+
+ // einer der Enknoten ist ueberlastet
+ if(overloaded.contains(fromNode.getIndex()) || overloaded.contains((toNode.getIndex()))){
+ addEdge(fromNode.getIndex(),ec,e);
+ addEdge(toNode.getIndex(),ec,e);
+ }
+ // Gültige Kante
+ else{
+ g.addEdge(e);
+ e.connectToNodes();
+ }
+ }
+ // Zwischenspeichern der überlasteten Kanten in der DB
+ db.setDisabledEdgesInputWay(disabledEdges);
+ return g;
+ }
+
+ /**
+ * fügt eine Kante in den Zwischenspeicher ein, der über die DB-Klasse an den Batch übergeben wird.
+ * @param index Knotenindex des Endknoten
+ * @param ec ContainerKlasse der Kante
+ * @param e Kante
+ */
+ public void addEdge(int index,EdgeContainer ec, Edge e){
+ if(disabledEdges.containsKey(index))
+ disabledEdges.get(index).put(ec,e);
+ else{
+ HashMap newEdgeList = new HashMap<>();
+ newEdgeList.put(ec,e);
+ disabledEdges.put(index,newEdgeList);
+ }
+ }
+
+}
diff --git a/src/dna/graph/generators/traffic/TrafficModel.java b/src/dna/graph/generators/traffic/TrafficModel.java
new file mode 100644
index 00000000..82345aff
--- /dev/null
+++ b/src/dna/graph/generators/traffic/TrafficModel.java
@@ -0,0 +1,5 @@
+package dna.graph.generators.traffic;
+
+public enum TrafficModel {
+ CrossroadModel, WayModel, SensorModel
+}
diff --git a/src/dna/graph/generators/traffic/TrafficModi.java b/src/dna/graph/generators/traffic/TrafficModi.java
new file mode 100644
index 00000000..8d41c8a0
--- /dev/null
+++ b/src/dna/graph/generators/traffic/TrafficModi.java
@@ -0,0 +1,26 @@
+package dna.graph.generators.traffic;
+
+public enum TrafficModi {
+ /**
+ * Kontinuierlicher Modus, bei dem ausgehend von einem Startzeitpunkt,
+ * in jedem Batch ein Zeitschritt festgelegter Dauer addiert wird
+ */
+ Continuous,
+ /**
+ * Tagesmodus, bei dem ausgehend von einem Startzeitpunkt und eines
+ * Zeitintervall, für jeden der durch daySelection ausgewählten Tage
+ * das entsprechende Intervall berechnet wird
+ */
+ DayTimeRange,
+ /**
+ * Statischer Simulationsmodus, bei dem die Daten anhand des TrafficUpdate-
+ * Objekt geändert werden
+ */
+ Simulation,
+ /**
+ * Aggregationmodus für den Vergleich, bei dem für den Batch die Tage eines
+ * festgelegten Zeitraums aggregiert werden, und dann ein Vergleichsmaß (z.b.
+ * Durchschnitt) berechnet wird
+ */
+ Aggregation
+}
diff --git a/src/dna/graph/generators/traffic/TrafficSensorGraphGenerator.java b/src/dna/graph/generators/traffic/TrafficSensorGraphGenerator.java
new file mode 100644
index 00000000..96433d33
--- /dev/null
+++ b/src/dna/graph/generators/traffic/TrafficSensorGraphGenerator.java
@@ -0,0 +1,186 @@
+package dna.graph.generators.traffic;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.joda.time.DateTime;
+
+import dna.graph.Graph;
+import dna.graph.datastructures.GraphDataStructure;
+import dna.graph.edges.Edge;
+import dna.graph.generators.GraphGenerator;
+import dna.graph.nodes.DirectedWeightedNode;
+import dna.graph.nodes.INode;
+import dna.graph.nodes.Node;
+import dna.graph.weights.Double3dWeight;
+
+import dna.util.parameters.Parameter;
+
+public class TrafficSensorGraphGenerator extends GraphGenerator{
+
+ private DB db;
+
+ // Allgemeine Parameter
+ private TrafficModi modus;
+ private DateTime initDateTime;
+ private double treshold;
+
+ // Continous
+ private int stepsize;
+
+ // DayTimeRange
+ private int timeRange;
+
+ // Simulation
+ private TrafficUpdate trafficUpdate;
+
+
+ private HashMap> disabledEdges = new HashMap<>();
+
+ public TrafficSensorGraphGenerator(String name, GraphDataStructure gds, DB db,long timeStamp,TrafficModi modus,DateTime initDateTime, int stepsize,int timeRange,TrafficUpdate trafficupdate,double treshold) {
+ this(name, null, gds,timeStamp, 0, 0,db,modus,initDateTime,stepsize,timeRange,trafficupdate,treshold);
+ }
+
+ public TrafficSensorGraphGenerator(String name, Parameter[] params,
+ GraphDataStructure gds, long timestampInit, int nodesInit,
+ int edgesInit,DB db, TrafficModi modus,DateTime initDateTime,int stepsize,int timeRange,TrafficUpdate trafficUpdate,double treshold) {
+ super(name, params, gds, timestampInit, nodesInit, edgesInit);
+ this.db= db;
+ this.modus = modus;
+ this.initDateTime=initDateTime;
+ this.stepsize = stepsize;
+ this.timeRange = timeRange;
+ this.trafficUpdate = trafficUpdate;
+ this.treshold = treshold;
+ }
+
+ public TrafficSensorGraphGenerator(TrafficConfig tc, GraphDataStructure gds, DB db, long timeStampInit){
+ super(tc.getGraphName(), null, gds, timeStampInit,0,0);
+ this.db = db;
+ this.modus = tc.getModus();
+ this.initDateTime=tc.getInitDateTime();
+ this.stepsize = tc.getStepSize();
+ this.timeRange = tc.getTimeRange();
+ this.trafficUpdate = tc.getTrafficUpdate();
+ this.treshold = tc.getTreshold();
+ }
+
+ @Override
+ public Graph generate() {
+ Graph g = this.newGraphInstance();
+ Set overloaded = new HashSet<>();
+
+ // Lade Sensoren aus der Datenbank
+ List nodes = db.getSensorsForDNA();
+
+ double[] weight = null;
+ Node currentNode = null;
+ DirectedWeightedNode currentWeighted = null;
+
+ // Vorabberechnung der Knotengewichte für alle realen Sensoren
+ switch (modus) {
+
+ case Continuous:
+ db.getSensorWeights(initDateTime, initDateTime.plusMinutes(stepsize), 0);
+ break;
+
+ case DayTimeRange:
+ db.getSensorWeights(initDateTime.minusMinutes(timeRange),initDateTime.plusMinutes(timeRange),0);
+ break;
+
+ default:
+ break;
+ }
+
+ // Berechne das Knotengewicht für alle Knoten
+ for (int i = 0; i < nodes.size(); i++) {
+
+ currentNode = (Node) nodes.get(i);
+ if(currentNode instanceof DirectedWeightedNode)
+ currentWeighted = (DirectedWeightedNode) currentNode;
+ else{
+ continue;
+ }
+
+ switch (modus) {
+
+ case Continuous:
+ weight = db.getSensorModelWeight(currentWeighted.getIndex(),initDateTime,initDateTime.plusMinutes(stepsize),0);
+ break;
+
+ case DayTimeRange:
+ weight = db.getSensorModelWeight(currentWeighted.getIndex(),initDateTime.minusMinutes(timeRange),initDateTime.plusMinutes(timeRange),0);
+ break;
+
+ case Simulation:
+ weight = db.getSensorModelWeightStaticInit(currentWeighted.getIndex(),trafficUpdate);
+ break;
+
+ default:
+ System.out.println("error - TrafficSensorGraphGenerator- Modus nicht definiert");
+ break;
+ }
+
+ if(weight== null){
+ weight = new double[]{0,0,0};
+ }
+
+ // Knoten überlastet
+ if(weight[2] > treshold){
+ overloaded.add(currentWeighted.getIndex());
+ }
+ currentWeighted.setWeight(new Double3dWeight(weight[0],weight[1],weight[2]));
+ g.addNode(currentWeighted);
+ }
+
+ // Kanten
+ List connection = db.getSensorConnectionForDNA();
+ DirectedWeightedNode fromNode;
+ DirectedWeightedNode toNode;
+ Edge e = null;
+ EdgeContainer ec = null;
+
+ // Prüfe ob Kante gültig ist
+ for (int i = 0; i < connection.size(); i++) {
+ ec = connection.get(i);
+ fromNode = (DirectedWeightedNode) g.getNode(ec.getFrom());
+ toNode = (DirectedWeightedNode) g.getNode(ec.getTo());
+ try {
+ e = gds.newEdgeInstance(fromNode,toNode);
+ } catch (Exception e2) {
+ System.out.println("Problem: \t" +ec.getFrom()+"\t"+ec.getTo());
+ }
+
+ if(overloaded.contains(fromNode.getIndex()) || overloaded.contains((toNode.getIndex()))){
+ addEdge(fromNode.getIndex(),ec,e);
+ addEdge(toNode.getIndex(),ec,e);
+ }
+ else{
+ g.addEdge(e);
+ e.connectToNodes();
+ }
+
+ }
+ db.setDisabledEdgesInputWay(disabledEdges);
+ return g;
+ }
+
+ /**
+ * Füge Kante zum Zwischenspeicher hinzu
+ * @param index Kontenindex eines Endknotens
+ * @param ec ContainerKlasse der Kante
+ * @param e Kante
+ */
+ private void addEdge(int index,EdgeContainer ec, Edge e){
+ if(disabledEdges.containsKey(index))
+ disabledEdges.get(index).put(ec,e);
+ else{
+ HashMap newEdgeList = new HashMap<>();
+ newEdgeList.put(ec,e);
+ disabledEdges.put(index,newEdgeList);
+ }
+ }
+
+}
diff --git a/src/dna/graph/generators/traffic/TrafficUpdate.java b/src/dna/graph/generators/traffic/TrafficUpdate.java
new file mode 100644
index 00000000..43c4950e
--- /dev/null
+++ b/src/dna/graph/generators/traffic/TrafficUpdate.java
@@ -0,0 +1,144 @@
+package dna.graph.generators.traffic;
+
+import java.util.List;
+
+public class TrafficUpdate {
+
+ // Werte für die Initialiserung in NORMALIZATION
+ private double initCount;
+ private double initLoad;
+
+ // Werte für das UPDATE in NORMALIZATION
+ private double updateCount;
+ private double updateLoad;
+
+ // Werte in FINAL_VALUE
+ private double initUtilization;
+ private double updateUtilization;
+
+ // Knoten für die im Update ein neuer Wert übernommen wird
+ private List nodesToUpdate;
+
+ public final static int NORMALIZATION = 0; // für jeden Knoten werden getrennt Count- und Load-Werte bestimmt, aus denen das Knotengewicht durch Normalisierung bestimmt werden kann
+ public final static int FINAL_VALUE = 1; // für jeden Knoten wird ein Knotengewicht als Auslastung übergeben
+
+ private int modus; // Entweder NORMALITAT oder Final-Value
+ private int sleeptillUpdate; // Anzahl der vergangenen Batches bis das Update angewendet wird
+
+ /**
+ * Konstruktur für den Modus mit festgelegten Count und Load-Wert,
+ * die Berechnung des Knotengewichts erfolgt als normierter Wert mit dem maximalen Count-Wert
+ * @param initCount Count-Wert für die Initialisierung
+ * @param initLoad Load-Wert für die Initialisierung
+ * @param updateCount - Count-Wert für das Update
+ * @param updateLoad - Load-Wert für das Update
+ * @param sleeptillUpdate - Dauer des Aggregationszeitraums (Anzahl Batches)
+ * @param affectedNodes - Knoten für die eine Aktualisierung vorgenommen werden soll
+ */
+ public TrafficUpdate(double initCount,double initLoad,double updateCount,double updateLoad,int sleeptillUpdate, List affectedNodes){
+ this.initCount=initCount;
+ this.initLoad=initLoad;
+ this.updateCount=updateCount;
+ this.updateLoad=updateLoad;
+ this.nodesToUpdate = affectedNodes;
+ this.modus=NORMALIZATION;
+ this.sleeptillUpdate = sleeptillUpdate;
+ }
+
+ /**
+ * Konstruktur für den Modus mit übergebenen normalisierten Werten,
+ * es erfolgte keine weitere Normalisierung mittels Count-Werten
+ * count und load werden als Dummy auf den Knoten mitgeführt
+ * @param initUtilization - Knotengewicht bei der Initialisierung
+ * @param updateUtilization - Knotengewicht für das Update
+ * @param sleepTilleTimestamp - Dauer des Aggregationszeitraums (Anzahl Batches)
+ * @param affectedNodes - Knoten für die eine Aktualisierung vorgenommen werden soll
+ */
+ public TrafficUpdate(double initUtilization, double updateUtilization,int sleepTilleTimestamp,List affectedNodes){
+ this.initUtilization = initUtilization;
+ this.updateUtilization = updateUtilization;
+ this.nodesToUpdate = affectedNodes;
+ this.modus=FINAL_VALUE;
+ }
+
+ /**
+ * liefert den Modus für den das Objekt erstellt wurde
+ * @return 0 = Normalization, 1 = Final_Values als Konstanten
+ */
+ public int getModus(){
+ return modus;
+ }
+
+ /**
+ * liefert den Count-Wert für die Initialisierung
+ * @return
+ */
+ public double getInitCount(){
+ return initCount;
+ }
+
+ /**
+ * liefert den Load-Wert für die Initialisierung
+ * @return
+ */
+ public double getInitLoad(){
+ return initLoad;
+ }
+
+ /**
+ * liefert den Count-Wert für das Update
+ * @return
+ */
+ public double getUpdateCount(){
+ return updateCount;
+ }
+
+ /**
+ * liefert den Load-Wert für das Update
+ * @return
+ */
+ public double getUpdateLoad(){
+ return updateLoad;
+ }
+
+ /**
+ * prüft ob der übergebene Knoten für das Update berücksichtigt werden soll
+ * @param nodeID - globale ID des Knoten
+ * @return
+ */
+ public boolean isAffected(int nodeID){
+ return nodesToUpdate.contains(nodeID);
+ }
+ /**
+ * prüft ob das Update angewendet werden soll
+ * @param timeStamp - aktuelle Zeitschritt
+ * @return
+ */
+ public boolean changeToUpdate(int timeStamp){
+ return sleeptillUpdate<=timeStamp;
+ }
+
+ /**
+ * liefert das initiale Knotengewicht
+ * @return
+ */
+ public double getInitUtilization(){
+ return initUtilization;
+ }
+
+ /**
+ * liefert das Knotengewicht im Update
+ * @return
+ */
+ public double getUpdateUtilization(){
+ return updateUtilization;
+ }
+
+ /**
+ * liefert den Zeitraum für die Aggregation
+ * @return
+ */
+ public int getSleepTillUpdate(){
+ return sleeptillUpdate;
+ }
+}
diff --git a/src/dna/graph/weights/Double3dWeight.java b/src/dna/graph/weights/Double3dWeight.java
index a311cb4c..49701820 100644
--- a/src/dna/graph/weights/Double3dWeight.java
+++ b/src/dna/graph/weights/Double3dWeight.java
@@ -65,5 +65,16 @@ public String asString() {
return this.x + Weight.WeightSeparator + this.y
+ Weight.WeightSeparator + this.z;
}
+
+
+ public boolean equals(Object o){
+ if (o == null)
+ return false;
+ if (!(o instanceof Double3dWeight))
+ return false;
+
+ Double3dWeight oCasted = (Double3dWeight) o;
+ return this.x == oCasted.getX() && this.y == oCasted.getY() && this.z == oCasted.getZ();
+ }
}
diff --git a/src/dna/metrics/centrality/BetweennessCentrality.java b/src/dna/metrics/centrality/BetweennessCentrality.java
index 72e204de..bd959c2d 100644
--- a/src/dna/metrics/centrality/BetweennessCentrality.java
+++ b/src/dna/metrics/centrality/BetweennessCentrality.java
@@ -46,7 +46,8 @@ public BetweennessCentrality(String name) {
public Value[] getValues() {
// Value v1 = new Value("median", getMedian());
Value v2 = new Value("avg_bc", bCSum / (double) g.getNodeCount());
- return new Value[] { v2 };
+ Value v3 = new Value("sum_of_path", sumShortestPaths);
+ return new Value[] { v2,v3 };
}
@Override
diff --git a/src/dna/metrics/connectivity/StrongConnectivity.java b/src/dna/metrics/connectivity/StrongConnectivity.java
index b1b636de..0b446d6e 100644
--- a/src/dna/metrics/connectivity/StrongConnectivity.java
+++ b/src/dna/metrics/connectivity/StrongConnectivity.java
@@ -121,7 +121,7 @@ protected int lookup(DirectedNode n) {
@Override
public Value[] getValues() {
Value v1 = new Value("NumberofComponents", countComponents());
- Value v2 = new Value("average size", getaverageSize());
+ Value v2 = new Value("averagesize", getaverageSize());
return new Value[] { v1, v2 };
}
diff --git a/src/dna/metrics/paths/AllPairsShortestPathsDouble.java b/src/dna/metrics/paths/AllPairsShortestPathsDouble.java
new file mode 100644
index 00000000..3d5a27df
--- /dev/null
+++ b/src/dna/metrics/paths/AllPairsShortestPathsDouble.java
@@ -0,0 +1,74 @@
+package dna.metrics.paths;
+
+import dna.metrics.IMetric;
+import dna.metrics.Metric;
+import dna.series.data.BinnedDistributionDouble;
+import dna.series.data.Distribution;
+import dna.series.data.DistributionLong;
+import dna.series.data.NodeNodeValueList;
+import dna.series.data.NodeValueList;
+import dna.series.data.Value;
+import dna.util.ArrayUtils;
+
+/**
+ * works nearly similar to AllPairsShortestPathsDouble except it
+ * uses BinnedDistributionDouble instead of DistributionLong
+ *
+ * maybe this can be combined with the parent class distribution
+ * @author barracuda317 (Maurice Wendt)
+ * @date 25.10.2014
+ */
+public abstract class AllPairsShortestPathsDouble extends Metric {
+
+ // TODO INIT!!!
+ // this.apsp = new DistributionLong("APSP");
+ double binsize;
+
+ protected BinnedDistributionDouble apsp;
+
+ public AllPairsShortestPathsDouble(String name) {
+ super(name);
+ }
+ public AllPairsShortestPathsDouble(String name,double binsize) {
+ super(name);
+ this.binsize = binsize;
+ }
+
+ @Override
+ public Value[] getValues() {
+ this.apsp.truncate();
+
+ Value v1 = new Value("existingPaths", this.apsp.getDenominator());
+ Value v2 = new Value("possiblePaths", this.g.getNodeCount()
+ * (this.g.getNodeCount() - 1));
+ Value v3 = new Value("characteristicPathLength",
+ this.apsp.computeAverage()*binsize);
+ Value v4 = new Value("diameter", this.apsp.getMax()*binsize);
+
+ return new Value[] { v1, v2, v3, v4 };
+ }
+
+ @Override
+ public Distribution[] getDistributions() {
+ return new Distribution[] { this.apsp };
+ }
+
+ @Override
+ public NodeValueList[] getNodeValueLists() {
+ return new NodeValueList[] {};
+ }
+
+ @Override
+ public NodeNodeValueList[] getNodeNodeValueLists() {
+ return new NodeNodeValueList[] {};
+ }
+
+ @Override
+ public boolean equals(IMetric m) {
+ return this.isComparableTo(m)
+ && ArrayUtils.equals(this.apsp.getDoubleValues(),
+ ((AllPairsShortestPathsDouble) m).apsp.getDoubleValues(),
+ "APSP");
+ }
+
+}
diff --git a/src/dna/metrics/paths/DoubleWeightedAllPairsShortestPaths.java b/src/dna/metrics/paths/DoubleWeightedAllPairsShortestPaths.java
new file mode 100644
index 00000000..f4fb3a4b
--- /dev/null
+++ b/src/dna/metrics/paths/DoubleWeightedAllPairsShortestPaths.java
@@ -0,0 +1,43 @@
+package dna.metrics.paths;
+
+import dna.graph.Graph;
+import dna.graph.weights.Double3dWeight;
+import dna.graph.weights.IWeightedEdge;
+import dna.graph.weights.IWeightedNode;
+import dna.graph.weights.IntWeight;
+import dna.metrics.IMetric;
+import dna.updates.batch.Batch;
+/**
+ *
+ * Adaption of IntWeightedAllPairsShortestPath
+ *
+ * using NodeWeights and DoubleValues
+ *
+ * @author barracuda317 (Maurice Wendt)
+ * @date 25.10.2014
+ */
+public abstract class DoubleWeightedAllPairsShortestPaths extends
+ AllPairsShortestPathsDouble {
+
+ public DoubleWeightedAllPairsShortestPaths(String name,double binsize) {
+ super(name,binsize);
+ }
+
+ @Override
+ public boolean isComparableTo(IMetric m) {
+ return m != null && m instanceof DoubleWeightedAllPairsShortestPaths;
+ }
+
+ @Override
+ public boolean isApplicable(Graph g) {
+ return g.getGraphDatastructures().isNodeType(IWeightedNode.class)
+ && g.getGraphDatastructures().isNodeWeightType(Double3dWeight.class); //TODO fragt den Z-Wert von Double3dWeight ab
+ }
+
+ @Override
+ public boolean isApplicable(Batch b) {
+ return b.getGraphDatastructures().isNodeType(IWeightedNode.class)
+ && b.getGraphDatastructures().isNodeWeightType(Double3dWeight.class); //TODO fragt den Z-Wert von Double3dWeight ab
+ }
+
+}
diff --git a/src/dna/metrics/paths/DoubleWeightedAllPairsShortestPathsR.java b/src/dna/metrics/paths/DoubleWeightedAllPairsShortestPathsR.java
new file mode 100644
index 00000000..979f3264
--- /dev/null
+++ b/src/dna/metrics/paths/DoubleWeightedAllPairsShortestPathsR.java
@@ -0,0 +1,130 @@
+package dna.metrics.paths;
+
+import java.util.Comparator;
+import java.util.PriorityQueue;
+
+import dna.graph.IElement;
+import dna.graph.edges.DirectedEdge;
+import dna.graph.edges.UndirectedEdge;
+import dna.graph.nodes.DirectedNode;
+import dna.graph.nodes.Node;
+import dna.graph.nodes.UndirectedNode;
+import dna.graph.weights.Double3dWeight;
+import dna.graph.weights.IWeighted;
+import dna.graph.weights.IntWeight;
+import dna.metrics.algorithms.IRecomputation;
+import dna.series.data.BinnedDistributionDouble;
+import dna.series.data.DistributionLong;
+/**
+ *
+ * Adaption of IntWeightedAllPairsShortestPathR
+ *
+ * using NodeWeights and DoubleValues
+ *
+ * @author barracuda317 (Maurice Wendt)
+ * @date 25.10.2014
+ */
+public class DoubleWeightedAllPairsShortestPathsR extends
+ DoubleWeightedAllPairsShortestPaths implements IRecomputation {
+
+
+
+ public DoubleWeightedAllPairsShortestPathsR(double binsize) {
+ super("DoubleWeightedAllPairsShortestPathsR", binsize);
+ this.binsize=binsize;
+ }
+
+ @Override
+ public boolean recompute() {
+ this.apsp = new BinnedDistributionDouble("APSP", binsize);
+ for (IElement source_ : this.g.getNodes()) {
+ Node source = (Node) source_;
+
+ double[] dist = this.getInitialDist(this.g.getMaxNodeIndex() + 1);
+ Node[] previous = new Node[this.g.getMaxNodeIndex() + 1];
+ boolean[] visited = new boolean[g.getMaxNodeIndex() + 1];
+ PriorityQueue Q = new PriorityQueue(g.getNodeCount(),
+ new DistComparator(dist));
+
+ dist[source.getIndex()] = 0;
+ Q.add(source);
+
+ while (!Q.isEmpty()) {
+ Node current = (Node) Q.remove();
+
+ if (visited[current.getIndex()]) {
+ continue;
+ }
+ visited[current.getIndex()] = true;
+
+ if (current instanceof DirectedNode) {
+ for (IElement e : ((DirectedNode) current)
+ .getOutgoingEdges()) {
+ Node n = ((DirectedEdge) e).getDst();
+ Double3dWeight w = (Double3dWeight) ((IWeighted) n).getWeight();
+ this.process(source, current, n, w.getZ(),
+ dist, previous, visited, Q);
+ }
+ } else if (current instanceof UndirectedNode) {
+ for (IElement e : ((UndirectedNode) current).getEdges()) {
+ Node n = ((UndirectedEdge) e).getDifferingNode(current);
+ Double3dWeight w = (Double3dWeight) ((IWeighted) e).getWeight();
+ this.process(source, current, n, w.getZ(),
+ dist, previous, visited, Q);
+ }
+ }
+ }
+
+ for (double d : dist) {
+ if (d > 0 && d != Integer.MAX_VALUE) {
+ this.apsp.incr(d);
+ }
+ }
+ }
+
+ return true;
+ }
+
+ protected class DistComparator implements Comparator {
+
+ private double[] dist;
+
+ public DistComparator(double[] dist) {
+ this.dist = dist;
+ }
+
+ @Override
+ public int compare(Node o1, Node o2) {
+ double diff = this.dist[o1.getIndex()] - this.dist[o2.getIndex()];
+ if(diff > 0)
+ return 1;
+ else if (diff < 0)
+ return -1;
+ else
+ return 0;
+ }
+ }
+
+ protected void process(Node source, Node current, Node n, double weight,
+ double[] dist, Node[] previous, boolean[] visited,
+ PriorityQueue Q) {
+ if (n.getIndex() == source.getIndex()) {
+ return;
+ }
+ double newDist = dist[current.getIndex()] + weight;
+ if (previous[n.getIndex()] == null || newDist < dist[n.getIndex()]) {
+ dist[n.getIndex()] = newDist;
+ previous[n.getIndex()] = current;
+ Q.add(n);
+ }
+ }
+
+ protected double[] getInitialDist(int size) {
+ double[] dist = new double[size];
+ for (int i = 0; i < dist.length; i++) {
+ dist[i] = Integer.MAX_VALUE;
+ }
+ return dist;
+ }
+
+}
diff --git a/src/dna/metrics/weights/NodeWeights.java b/src/dna/metrics/weights/NodeWeights.java
index 8329d708..bca0b896 100644
--- a/src/dna/metrics/weights/NodeWeights.java
+++ b/src/dna/metrics/weights/NodeWeights.java
@@ -3,6 +3,7 @@
import dna.graph.Graph;
import dna.graph.IElement;
import dna.graph.nodes.INode;
+import dna.graph.weights.Double3dWeight;
import dna.graph.weights.DoubleWeight;
import dna.graph.weights.IWeightedNode;
import dna.graph.weights.IntWeight;
@@ -34,14 +35,14 @@ public boolean isComparableTo(IMetric m) {
public boolean isApplicable(Graph g) {
return g.getGraphDatastructures().isNodeType(IWeightedNode.class)
&& g.getGraphDatastructures().isNodeWeightType(IntWeight.class,
- DoubleWeight.class);
+ DoubleWeight.class,Double3dWeight.class);
}
@Override
public boolean isApplicable(Batch b) {
return b.getGraphDatastructures().isNodeType(IWeightedNode.class)
&& b.getGraphDatastructures().isNodeWeightType(IntWeight.class,
- DoubleWeight.class);
+ DoubleWeight.class,Double3dWeight.class);
}
protected double getWeight(INode n) {
diff --git a/src/dna/metrics/weights/Weights.java b/src/dna/metrics/weights/Weights.java
index b824a1f9..f442af59 100644
--- a/src/dna/metrics/weights/Weights.java
+++ b/src/dna/metrics/weights/Weights.java
@@ -1,5 +1,6 @@
package dna.metrics.weights;
+import dna.graph.weights.Double3dWeight;
import dna.graph.weights.DoubleWeight;
import dna.graph.weights.IntWeight;
import dna.graph.weights.Weight;
@@ -62,6 +63,8 @@ protected double getWeight(Weight w) {
return (double) ((IntWeight) w).getWeight();
} else if (w instanceof DoubleWeight) {
return ((DoubleWeight) w).getWeight();
+ } else if (w instanceof Double3dWeight) {
+ return ((Double3dWeight) w).getZ();
} else {
return Double.NaN;
}
diff --git a/src/dna/series/data/DistributionDouble.java b/src/dna/series/data/DistributionDouble.java
index d866a3f2..5e9b5846 100644
--- a/src/dna/series/data/DistributionDouble.java
+++ b/src/dna/series/data/DistributionDouble.java
@@ -21,6 +21,7 @@ public class DistributionDouble extends Distribution {
// member variables
private double[] values;
+ private long denominator;
// values for comparison
private double comparedSum;
@@ -105,6 +106,7 @@ public double getComparedAvg() {
*/
public void incr(int index) {
this.values = ArrayUtils.incr(this.values, index);
+ this.denominator++;
}
/**
@@ -115,6 +117,7 @@ public void incr(int index) {
*/
public void decr(int index) {
this.values = ArrayUtils.decr(this.values, index);
+ this.denominator--;
}
/**
@@ -213,5 +216,17 @@ public static DistributionDouble read(String dir, String filename,
public static boolean equals(DistributionDouble d1, DistributionDouble d2) {
return ArrayUtils.equals(d1.getDoubleValues(), d2.getDoubleValues());
}
+
+ public double getDenominator() {
+ return denominator;
+ }
+
+ public double computeAverage() {
+ double avg = 0;
+ for (int i = 0; i < this.values.length; i++) {
+ avg += i * this.values[i];
+ }
+ return avg / this.denominator;
+ }
}
diff --git a/src/dna/updates/generators/traffic/CrossroadWeightList.java b/src/dna/updates/generators/traffic/CrossroadWeightList.java
new file mode 100644
index 00000000..bf460d9e
--- /dev/null
+++ b/src/dna/updates/generators/traffic/CrossroadWeightList.java
@@ -0,0 +1,50 @@
+package dna.updates.generators.traffic;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import dna.graph.generators.traffic.CrossroadWeight;
+
+public class CrossroadWeightList {
+ int crossroadID;
+ String crossroadName;
+ double threshold;
+ List objects;
+ List weights;
+ CrossroadWeight sum;
+
+ public CrossroadWeightList(int index, String crossroadName, double threshold){
+ this.crossroadID=index;
+ this.crossroadName=crossroadName;
+ this.threshold = threshold;
+ this.objects = new ArrayList<>();
+ this.weights = new ArrayList<>();
+ }
+
+ public boolean add(CrossroadWeight crw){
+ if(crw.crossroadID != crossroadID || !crw.getCrossroadName().equals(crossroadName) )
+ return false;
+ else{
+ if(sum==null){
+ sum = new CrossroadWeight(crossroadID, crossroadName, threshold);
+ for (Map.Entry entry : crw.getWayWeights().entrySet()) {
+ sum.addWeightWay(entry.getKey(), entry.getValue());
+ sum.setMaxWeightWay(entry.getKey(), crw.getMaxWeightWay(entry.getKey()));
+ }
+ sum.setMaxWeight(crw.getMaxWeight());
+ }
+ else{
+ sum.addWeights(crw.inputWayWeights);
+ }
+ objects.add(crw);
+ weights.add(crw.getWeight()[2]);
+ return true;
+ }
+ }
+
+ public CrossroadWeight getAverage(){
+ sum.divWays(objects.size());
+ return sum;
+ }
+}
diff --git a/src/dna/updates/generators/traffic/Days.java b/src/dna/updates/generators/traffic/Days.java
new file mode 100644
index 00000000..193ba2f5
--- /dev/null
+++ b/src/dna/updates/generators/traffic/Days.java
@@ -0,0 +1,9 @@
+package dna.updates.generators.traffic;
+
+public enum Days {
+ MONDAY,TUESDAY,WEDNESDAY,THURSDAY,FRIDAY,SATURDAY,SUNDAY;
+
+ static Days getDay(int i){
+ return values()[i-1];
+ }
+}
\ No newline at end of file
diff --git a/src/dna/updates/generators/traffic/Helpers.java b/src/dna/updates/generators/traffic/Helpers.java
new file mode 100644
index 00000000..6c6e874e
--- /dev/null
+++ b/src/dna/updates/generators/traffic/Helpers.java
@@ -0,0 +1,56 @@
+package dna.updates.generators.traffic;
+
+import org.joda.time.DateTime;
+
+public class Helpers {
+ public static boolean isWorkDay(Days d) {
+ return !(d == Days.SATURDAY || d==Days.SUNDAY);
+ }
+
+ /**
+ * berechnet ausgehend von "start" den nächsten Werktag in der Zukunft(forward) oder Vergangenheit (!forward)
+ * @param start - Startdatum
+ * @param l - Timestep
+ * @param forward - true = in der Zukunft, false = in der Vergangenheit
+ * @return
+ */
+ public static DateTime calculateNextWorkDay(DateTime start,long l, boolean forward){
+ return calculateNextDay(start, l, new boolean[]{true,true,true,true,true,false,false},null,forward);
+ }
+
+ /**
+ * berechnet ausgehend von "start" den nächsten Tag in der Zukunft(forward) oder Vergangenheit (!forward)
+ * @param start - Startdatum
+ * @param timestep - Zeitschritt für den der nächste Tag berechnet werden soll
+ * @param daySelection - Array mit Wochentagen, die für die Berechnung berücksichtigt werden sollen
+ * @param ignoreTo - Zeitpunkt bis zu welchem die Berechnung ignoriert wird
+ * @param forward - true = in der Zukunft, false = in der Vergangenheit
+ * @return
+ */
+ public static DateTime calculateNextDay(DateTime start, long timestep, boolean[] daySelection,DateTime ignoreTo, boolean forward){
+ DateTime current = start;
+ int count = 0;
+ while(count <= timestep) {
+ current = forward ? current.plusDays(1) : current.minusDays(1);
+ if(daySelection[current.getDayOfWeek()-1] && (current.isBefore(ignoreTo) || forward)){
+ count++;
+ }
+ }
+ return current;
+ }
+ /**
+ * Wandelt die Beobachtungswochen in die Beobachtungstage um (=#Batches)
+ * @param weeks, Wochen die beobachtet werden sollen
+ * @param daySelection , Tage die in einer Woche beobachtet werden sollen
+ * @return
+ */
+ public static int weekToDay(int weeks, boolean[] daySelection){
+ int i =0;
+ for (int j = 0; j < daySelection.length; j++) {
+ if(daySelection[j])
+ i++;
+ }
+ return i*weeks;
+ }
+
+}
diff --git a/src/dna/updates/generators/traffic/TrafficCrossroadBatchGenerator.java b/src/dna/updates/generators/traffic/TrafficCrossroadBatchGenerator.java
new file mode 100644
index 00000000..2e308690
--- /dev/null
+++ b/src/dna/updates/generators/traffic/TrafficCrossroadBatchGenerator.java
@@ -0,0 +1,236 @@
+package dna.updates.generators.traffic;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.joda.time.DateTime;
+
+import dna.graph.Graph;
+import dna.graph.IElement;
+import dna.graph.edges.Edge;
+import dna.graph.generators.traffic.CrossroadWeight;
+import dna.graph.generators.traffic.DB;
+import dna.graph.generators.traffic.EdgeContainer;
+import dna.graph.generators.traffic.TrafficConfig;
+import dna.graph.generators.traffic.TrafficModi;
+import dna.graph.generators.traffic.TrafficUpdate;
+import dna.graph.nodes.DirectedWeightedNode;
+import dna.graph.weights.Double3dWeight;
+import dna.updates.batch.Batch;
+import dna.updates.generators.BatchGenerator;
+import dna.updates.update.EdgeAddition;
+import dna.updates.update.EdgeRemoval;
+import dna.updates.update.NodeWeight;
+import dna.util.parameters.IntParameter;
+import dna.util.parameters.ObjectParameter;
+
+public class TrafficCrossroadBatchGenerator extends BatchGenerator{
+
+ private DB db;
+
+ //Allgemeine Parameter
+ private DateTime initDateTime;
+ private TrafficModi modus;
+
+ // Continous
+ private int stepSize;
+
+ //DayTimeRange - Aggregation
+ private DateTime holidayStart;
+ private boolean[] daySelection;
+ private int timeRange;
+
+ //Aggregation
+ private int observationDays;
+
+ //Simulation
+ private TrafficUpdate trafficUpdate;
+
+ private HashMap disabledEdges = new HashMap<>();
+ private HashMap nodeHistory;
+
+
+ public TrafficCrossroadBatchGenerator(String name,DB db, DateTime initDateTime, int stepSize, TrafficModi modus, DateTime holidayStart, boolean [] daySelection,TrafficUpdate trafficUpdate,int timeRange, int observationDays) {
+ super(name, new IntParameter("NA", 0), new IntParameter("NR",
+ 0), new IntParameter("NW", 0),
+ new ObjectParameter("NWS", 0), new IntParameter("EA", 0),
+ new IntParameter("ER", 0));
+ this.db = db;
+ this.initDateTime = initDateTime;
+ this.stepSize = stepSize;
+ this.modus = modus;
+ this.holidayStart = holidayStart;
+ this.daySelection = daySelection;
+ this.trafficUpdate = trafficUpdate;
+ this.timeRange = timeRange;
+ this.observationDays = observationDays;
+ }
+
+ /**
+ * Erstellt einen TrafficCrossroadBatchGeneratur unter Verwendung der Paramtere auf TrafficConfig
+ * @param db
+ * @param tc
+ */
+ public TrafficCrossroadBatchGenerator(DB db, TrafficConfig tc){
+ super(tc.getBatchName(), new IntParameter("NA", 0), new IntParameter("NR",
+ 0), new IntParameter("NW", 0),
+ new ObjectParameter("NWS", 0), new IntParameter("EA", 0),
+ new IntParameter("ER", 0));
+ this.db = db;
+ this.initDateTime = tc.getInitDateTime();
+ this.stepSize = tc.getStepSize();
+ this.modus = tc.getModus();
+ this.holidayStart = tc.getHolidayStart();
+ this.daySelection = tc.getDaySelection();
+ this.trafficUpdate = tc.getTrafficUpdate();
+ this.timeRange = tc.getTimeRange();
+ this.observationDays = tc.getOberservationDays();
+ }
+
+ @Override
+ public Batch generate(Graph g) {
+
+ Batch b = new Batch(g.getGraphDatastructures(), g.getTimestamp(),
+ g.getTimestamp() + 1, 0, 0, 0, 0,
+ 0, 0);
+
+ // Infos aus Initialisierungsschritt holen
+ if(g.getTimestamp()==0){
+ disabledEdges = db.getDisabledEdges();
+ }
+
+ HashMap newDisabled = new HashMap<>();
+ Iterable nodes = g.getNodes();
+ CrossroadWeight crossroadWeight = null;
+ DateTime time = null;
+
+
+ // Spezialkonfigurationen für bestimmte Modi
+ switch (modus) {
+
+ case DayTimeRange:
+ time = initDateTime;
+ time = Helpers.calculateNextDay(time, g.getTimestamp(),daySelection,holidayStart,true);
+ break;
+
+ case Aggregation:
+ nodeHistory = new HashMap<>();
+ break;
+
+ default:
+ break;
+ }
+
+ // neuer Timestamp durch Batch-Generierung
+ long newTimeStamp = (int) g.getTimestamp() + 1;
+
+ // Berechne neues Gewicht für jeden Knoten
+ for (IElement currentNode : nodes) {
+ DirectedWeightedNode n = (DirectedWeightedNode) currentNode;
+ double[] update = null;
+
+ // Gewichts-Update
+ switch (modus) {
+
+ case Continuous:
+ crossroadWeight =db.getCrossroadWeight(n.getIndex(), initDateTime.plusMinutes((int) (g.getTimestamp()*stepSize)),initDateTime.plusMinutes((int) (g.getTimestamp()+stepSize)*stepSize),newTimeStamp);
+ break;
+
+ case DayTimeRange:
+ crossroadWeight = db.getCrossroadWeight(n.getIndex(),time.minusMinutes(timeRange),time.plusMinutes(timeRange),newTimeStamp);
+ break;
+
+ case Simulation:
+ crossroadWeight = db.getCrossroadWeightStaticBatch(n.getIndex(),trafficUpdate);
+ break;
+
+ case Aggregation:
+ //Initialisierung auf Starttag
+ time = initDateTime;
+ int index = n.getIndex();
+ long start = g.getTimestamp();
+
+ // Aggregiere für observationDays-viele Tage
+ for (int i = 0; i < observationDays; i++) {
+
+ // Gehe einen Tag zurück (gemäß daySelection) und berechne den entsprechenden Wert
+ time = Helpers.calculateNextDay(initDateTime, start++,daySelection,holidayStart,false);
+ CrossroadWeight weightOfDay = db.getCrossroadWeight(n.getIndex(),time.minusMinutes(timeRange*2),time.plusMinutes(timeRange*2),newTimeStamp);
+
+ // Sammler für jeden Knoten die Gewichte der einzelnen Tage
+ if(nodeHistory.containsKey(index)){
+ nodeHistory.get(index).add(weightOfDay);
+ }
+ else{
+ CrossroadWeightList weightList = new CrossroadWeightList(weightOfDay.crossroadID,weightOfDay.getCrossroadName(),weightOfDay.getThreshold());
+ weightList.add(weightOfDay);
+ nodeHistory.put(index, weightList);
+ }
+
+ }
+
+ // Nach der Aggregation, berechne den Average
+ crossroadWeight = nodeHistory.get(index).getAverage();
+ break;
+
+ default:
+ System.out.println("error - Modus nicht definiert");
+ break;
+ }
+
+ update = crossroadWeight.getWeight();
+ Double3dWeight oldWeight = (Double3dWeight) n.getWeight();
+ Double3dWeight newWeight = new Double3dWeight(update[0],update[1],update[2]);
+
+ db.setMaximalWeightsCrossroadImproved(n.getIndex(), update[0], update[1], time, timeRange);
+ if(!oldWeight.equals(newWeight))
+ b.add(new NodeWeight((dna.graph.weights.IWeightedNode) currentNode,newWeight));
+
+ //Edge-Removal
+ Edge disabledEdge = null;
+ for (Integer wayId : crossroadWeight.getOverladedEdges().keySet()) {
+ List edgesToRemove = db.getFromWays(n.getIndex(), wayId);
+ if(edgesToRemove != null){
+ for (int[] edge : edgesToRemove) {
+ disabledEdge = g.getEdge(g.getNode(edge[0]), n);
+ EdgeContainer ec = new EdgeContainer(edge[0], n.getIndex());
+ if(disabledEdge==null){
+ disabledEdge = disabledEdges.remove(ec);
+ if(disabledEdge==null){
+ for (EdgeContainer e : disabledEdges.keySet()) {
+ System.out.println(e);
+ }
+ }
+ }
+ else
+ b.add(new EdgeRemoval(disabledEdge));
+ newDisabled.put(ec, disabledEdge);
+ }
+ }
+ }
+ }
+
+ //Edge-Addition, falls diese wieder frei sind
+ for (Map.Entry oldDeletedEdge : disabledEdges.entrySet()) {
+ b.add(new EdgeAddition(oldDeletedEdge.getValue()));
+ }
+
+ disabledEdges=newDisabled;
+
+ return b;
+ }
+
+ @Override
+ public void reset() {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public boolean isFurtherBatchPossible(Graph g) {
+ // TODO Auto-generated method stub
+ return true;
+ }
+
+}
diff --git a/src/dna/updates/generators/traffic/TrafficInputWayBatchGenerator.java b/src/dna/updates/generators/traffic/TrafficInputWayBatchGenerator.java
new file mode 100644
index 00000000..442d549c
--- /dev/null
+++ b/src/dna/updates/generators/traffic/TrafficInputWayBatchGenerator.java
@@ -0,0 +1,292 @@
+package dna.updates.generators.traffic;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map.Entry;
+import java.util.Set;
+
+import org.joda.time.DateTime;
+
+import dna.graph.Graph;
+import dna.graph.IElement;
+import dna.graph.edges.Edge;
+import dna.graph.generators.traffic.DB;
+import dna.graph.generators.traffic.EdgeContainer;
+import dna.graph.generators.traffic.TrafficConfig;
+import dna.graph.generators.traffic.TrafficModi;
+import dna.graph.generators.traffic.TrafficUpdate;
+import dna.graph.nodes.DirectedWeightedNode;
+import dna.graph.weights.Double3dWeight;
+import dna.updates.batch.Batch;
+import dna.updates.generators.BatchGenerator;
+import dna.updates.update.EdgeAddition;
+import dna.updates.update.EdgeRemoval;
+import dna.updates.update.NodeWeight;
+import dna.util.parameters.IntParameter;
+import dna.util.parameters.ObjectParameter;
+
+public class TrafficInputWayBatchGenerator extends BatchGenerator{
+
+ private DB db;
+
+ // Allgemeine Parameter
+ private DateTime initDateTime;
+ private TrafficModi modus;
+ private double treshold;
+
+ // Continous
+ private int stepSize;
+
+ // DayTimeRange / Aggregation
+ private DateTime holidayStart;
+ private boolean[] daySelection;
+ private int timeRange;
+
+ // Aggregation
+ private int observationDays;
+
+ // Simulation
+ private TrafficUpdate trafficUpdate;
+
+ private HashMap> nodeHistory = new HashMap<>();
+ private HashMap> disabledEdges = new HashMap<>();
+ private HashMap> newDisabledEdges = new HashMap<>();
+
+
+ public TrafficInputWayBatchGenerator(String name,DB db, DateTime initDateTime, int stepSize, TrafficModi modus, DateTime holidayStart, boolean [] daySelection, double treshold, TrafficUpdate trafficUpdate, int timeRange, int observationDays) {
+ super(name, new IntParameter("NA", 0), new IntParameter("NR",
+ 0), new IntParameter("NW", 10),
+ new ObjectParameter("NWS", 0), new IntParameter("EA", 0),
+ new IntParameter("ER", 0));
+ this.db = db;
+ this.initDateTime = initDateTime;
+ this.stepSize = stepSize;
+ this.modus = modus;
+ this.holidayStart = holidayStart;
+ this.daySelection = daySelection;
+ this.treshold = treshold;
+ this.trafficUpdate = trafficUpdate;
+ this.timeRange = timeRange;
+ this.observationDays = observationDays;
+ }
+
+ public TrafficInputWayBatchGenerator(DB db, TrafficConfig tc){
+ super(tc.getBatchName(), new IntParameter("NA", 0), new IntParameter("NR",
+ 0), new IntParameter("NW", 0),
+ new ObjectParameter("NWS", 0), new IntParameter("EA", 0),
+ new IntParameter("ER", 0));
+ this.db = db;
+ this.initDateTime = tc.getInitDateTime();
+ this.stepSize = tc.getStepSize();
+ this.modus = tc.getModus();
+ this.holidayStart = tc.getHolidayStart();
+ this.daySelection = tc.getDaySelection();
+ this.treshold = tc.getTreshold();
+ this.trafficUpdate = tc.getTrafficUpdate();
+ this.timeRange = tc.getTimeRange();
+ this.observationDays = tc.getOberservationDays();
+ }
+
+ @Override
+ public Batch generate(Graph g) {
+ Batch b = new Batch(g.getGraphDatastructures(), g.getTimestamp(),
+ g.getTimestamp() + 1, 0, 0, 0, 0,
+ 0, 0);
+
+ Set toDisable = new HashSet<>();
+
+ // Knoten
+
+ Iterable nodes = g.getNodes();
+ DateTime time = null;
+
+ if(modus == TrafficModi.DayTimeRange){
+ time = initDateTime;
+ time = Helpers.calculateNextDay(time, g.getTimestamp(),daySelection,holidayStart,true);
+ }
+
+ // Aktualisiere das Gewicht für jeden Knoten, gemäß dem aktuellen Modus
+ for (IElement currentNode : nodes) {
+
+ DirectedWeightedNode n = (DirectedWeightedNode) currentNode;
+ double[] update =null;
+
+ //WeightUpdate
+ switch (modus) {
+
+ case Continuous:
+ update = db.getInputWayWeight(n.getIndex(),initDateTime.plusMinutes((int) (g.getTimestamp()+1)*stepSize),initDateTime.plusMinutes((int) (g.getTimestamp()+2)*stepSize));
+ break;
+
+ case DayTimeRange:
+ update = db.getInputWayWeight(n.getIndex(),time.minusMinutes(timeRange),time.plusMinutes(timeRange));
+ break;
+
+ case Simulation:
+ update = (trafficUpdate.isAffected(n.getIndex()))? db.getInputWayWeightStaticBatch(n.getIndex(),trafficUpdate) : null;
+ break;
+
+ case Aggregation:
+ time = initDateTime;
+ int index = n.getIndex();
+ long start = g.getTimestamp();
+
+ // Summiere für alle Beobachtungstage auf
+ for (int i = 0; i < observationDays; i++) {
+ time = Helpers.calculateNextDay(initDateTime, start++, daySelection, holidayStart, false);
+ double[] weightOfDay = db.getInputWayWeight(n.getIndex(),time.minusMinutes(timeRange),time.plusMinutes(timeRange));
+ if(nodeHistory.containsKey(index)){
+ nodeHistory.get(index).add(weightOfDay[2]);
+ }
+ else {
+ List weightList = new ArrayList<>();
+ weightList.add(weightOfDay[2]);
+ nodeHistory.put(index, weightList);
+ }
+ }
+
+ //Berechne das Knotengewicht aus der Aggregation
+ double sum = 0;
+ List values = nodeHistory.get(index);
+ for (int i = 0; i < values.size(); i++) {
+ sum+=values.get(i);
+ }
+ double value = (values.isEmpty())? 0 : sum/values.size();
+ update = new double[]{0,0,value};
+
+ break;
+ default:
+ System.out.println("error - Modus nicht definiert");
+ break;
+ }
+
+ // Wende das Update des Gewichts auf den Knoten an
+ Double3dWeight oldWeight = (Double3dWeight) n.getWeight();
+ if(update!=null){
+ Double3dWeight newWeight = new Double3dWeight(update[0],update[1],update[2]);
+ if(!oldWeight.equals(newWeight))
+ b.add(new NodeWeight((dna.graph.weights.IWeightedNode) currentNode,new Double3dWeight(update[0],update[1],update[2])));
+ }
+ else{
+ update = new double[]{oldWeight.getX(),oldWeight.getY(),oldWeight.getZ()};
+ }
+
+ EdgeContainer ec = null;
+ Integer newKey = null;
+ Edge edge = null;
+
+ // Infos aus Initialisierungsschritt holen
+ if(g.getTimestamp()==0){
+ disabledEdges=db.getDisabledEdgesInputWay();
+ }
+ newDisabledEdges = new HashMap<>();
+
+ // Knoten ist ueberlastet
+ if(update[2] > treshold) {
+
+ newKey = n.getIndex();
+ int from;
+ int to;
+
+ // Verhindere das Hinzufügen bereits gelöschter Kante
+ if(disabledEdges.containsKey(newKey)){
+ HashMap oldMap = disabledEdges.get(newKey);
+ for (Entry entry : oldMap.entrySet()) {
+ EdgeContainer key = entry.getKey();
+ Edge value = entry.getValue();
+ if(key.getFrom()==newKey){
+ removeEdge(key.getTo(),key,value);
+ addEdge(key.getTo(), key, value);
+ }
+ else{
+ removeEdge(key.getFrom(),key,value);
+ addEdge(key.getFrom(),key,value);
+ }
+ }
+ disabledEdges.remove(newKey);
+ }
+
+ // Lösche neue Kanten
+ for (IElement elem : n.getEdges()) {
+ edge = (Edge) elem;
+ from = edge.getN1Index();
+ to = edge.getN2Index();
+ ec = new EdgeContainer(from, to);
+ removeEdge(from,ec,edge);
+ removeEdge(to, ec, edge);
+ addEdge(from,ec,edge);
+ addEdge(to, ec, edge);
+ toDisable.add(edge);
+ }
+ }
+
+ }
+
+ // Füge die Löschoperation in den Batch hinzu
+ for (Edge e : toDisable) {
+ b.add(new EdgeRemoval(e));
+ }
+
+ // Füge nicht mehr ueberlastet Knoten wieder dem Graph hinzu
+ for (Entry> freeEdges : disabledEdges.entrySet()) {
+ int node = freeEdges.getKey();
+ for (Entry elem : freeEdges.getValue().entrySet()) {
+ if(node == elem.getKey().getFrom())
+ b.add(new EdgeAddition(elem.getValue()));
+ }
+ }
+
+ disabledEdges=newDisabledEdges;
+
+ return b;
+ }
+
+ @Override
+ public void reset() {
+ // TODO Auto-generated method stub
+ }
+
+ @Override
+ public boolean isFurtherBatchPossible(Graph g) {
+ // TODO Auto-generated method stub
+ return true;
+ }
+
+ /**
+ * Entfernt eine Kante aus dem Zwischenspeicher
+ * @param index
+ * @param ec
+ * @param e
+ */
+ private void removeEdge(int index, EdgeContainer ec, Edge e){
+ if(disabledEdges.containsKey(index)){
+ HashMap oldMap = disabledEdges.get(index);
+ oldMap.remove(ec);
+ if(oldMap.isEmpty()){
+ disabledEdges.remove(index);
+ }
+ }
+ }
+
+ /**
+ * fügte eine Kante zum Zwischenspeicher hinzu
+ * @param index
+ * @param ec
+ * @param e
+ */
+ private void addEdge(int index, EdgeContainer ec, Edge e){
+ if(newDisabledEdges.containsKey(index)){
+ HashMap oldMap = newDisabledEdges.get(index);
+ oldMap.put(ec, e);
+ }
+ else {
+ HashMap newMap = new HashMap<>();
+ newMap.put(ec, e);
+ newDisabledEdges.put(index,newMap);
+ }
+ }
+
+
+}
diff --git a/src/dna/updates/generators/traffic/TrafficSensorBatchGenerator.java b/src/dna/updates/generators/traffic/TrafficSensorBatchGenerator.java
new file mode 100644
index 00000000..0cd11183
--- /dev/null
+++ b/src/dna/updates/generators/traffic/TrafficSensorBatchGenerator.java
@@ -0,0 +1,229 @@
+package dna.updates.generators.traffic;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.Map.Entry;
+
+import org.joda.time.DateTime;
+
+import dna.graph.Graph;
+import dna.graph.IElement;
+import dna.graph.edges.Edge;
+import dna.graph.generators.traffic.DB;
+import dna.graph.generators.traffic.EdgeContainer;
+import dna.graph.generators.traffic.TrafficModi;
+import dna.graph.generators.traffic.TrafficUpdate;
+import dna.graph.nodes.DirectedWeightedNode;
+import dna.graph.weights.Double3dWeight;
+import dna.io.GraphWriter;
+import dna.updates.batch.Batch;
+import dna.updates.generators.BatchGenerator;
+import dna.updates.update.EdgeAddition;
+import dna.updates.update.EdgeRemoval;
+import dna.updates.update.NodeWeight;
+import dna.util.parameters.IntParameter;
+import dna.util.parameters.ObjectParameter;
+
+public class TrafficSensorBatchGenerator extends BatchGenerator{
+ private DB db;
+ private DateTime initDateTime;
+ private int stepSize;
+ private int step=0;
+ private TrafficModi modus;
+ private DateTime holidayStart;
+ private boolean[] daySelection;
+ private double treshold;
+ private int timeRange;
+
+ private HashMap> disabledEdges;
+ private HashMap> newDisabledEdges;
+ private TrafficUpdate trafficUpdate;
+
+ public TrafficSensorBatchGenerator(String name,DB db, DateTime initDateTime, int stepSize, TrafficModi modus, DateTime holidayStart, boolean [] daySelection, double treshold,int timeRange,TrafficUpdate trafficUpdate) {
+ super(name, new IntParameter("NA", 0), new IntParameter("NR",
+ 0), new IntParameter("NW", 0),
+ new ObjectParameter("NWS", 0), new IntParameter("EA", 0),
+ new IntParameter("ER", 0));
+ this.db = db;
+ this.initDateTime = initDateTime;
+ this.stepSize = stepSize;
+ this.modus=modus;
+ this.holidayStart=holidayStart;
+ this.daySelection = daySelection;
+ this.treshold = treshold;
+ this.timeRange = timeRange;
+ this.trafficUpdate = trafficUpdate;
+ disabledEdges=new HashMap<>();
+ newDisabledEdges = new HashMap<>();
+ }
+
+ @Override
+ public Batch generate(Graph g) {
+ Batch b = new Batch(g.getGraphDatastructures(), g.getTimestamp(),
+ g.getTimestamp() + 1, 0, 0, 0, 0,
+ 0, 0);
+ if(g.getTimestamp()==0){
+ disabledEdges = db.getDisabledEdgesInputWay();
+ }
+ GraphWriter.write(g, "SensorGraph/", "batch"+step+++".txt");
+ Integer newKey = null;
+ int newTimestamp = (int)g.getTimestamp() + 1;
+
+ DateTime time = initDateTime;
+ time = Helpers.calculateNextDay(time, g.getTimestamp(),daySelection,holidayStart,true);
+ DateTime fromTime = null;
+ DateTime toTime = null;
+
+ Set toDisable = new HashSet<>();
+ Edge edge = null;
+
+ switch (modus) {
+ case Continuous:
+ fromTime = initDateTime.plusMinutes((int) (g.getTimestamp()+1)*stepSize);
+ toTime = initDateTime.plusMinutes((int) (g.getTimestamp()+2)*stepSize);
+ break;
+ case DayTimeRange:
+ time = Helpers.calculateNextDay(time, g.getTimestamp(),daySelection,holidayStart,true);
+ fromTime = time.minusMinutes(timeRange);
+ toTime = time.plusMinutes(timeRange);
+ break;
+
+ default:
+ break;
+ }
+ // Vorabberechnung aller Gewichte der Realen Sensoren
+ if(modus == TrafficModi.Continuous || modus == TrafficModi.DayTimeRange){
+ db.getSensorWeights(fromTime,toTime, newTimestamp);
+ }
+
+ double[] update = null;
+ for (IElement currentNode : g.getNodes()) {
+
+ // Get Node
+ DirectedWeightedNode currentWeighted = null;
+ if(currentNode instanceof DirectedWeightedNode)
+ currentWeighted= (DirectedWeightedNode) currentNode;
+ else
+ continue;
+
+ // Get Weight
+ switch (modus) {
+ case Continuous:
+ update = db.getSensorModelWeight(currentWeighted.getIndex(),fromTime,toTime,newTimestamp);
+ break;
+ case DayTimeRange:
+ update = db.getSensorModelWeight(currentWeighted.getIndex(),fromTime,toTime,newTimestamp);
+ break;
+ case Simulation:
+ update = trafficUpdate.isAffected(currentWeighted.getIndex()) ? db.getSensorModelWeightStaticBatch(currentWeighted.getIndex(),trafficUpdate) : null;
+ break;
+ default:
+ System.out.println("error - Modus nicht definiert @ TrafficSensorBatchGenerator");
+ break;
+ }
+ Double3dWeight oldWeight = (Double3dWeight) currentWeighted.getWeight();
+ if(update!=null){
+ Double3dWeight newWeight = new Double3dWeight(update[0],update[1],update[2]);
+
+ // Set Weight
+ if(!oldWeight.equals(newWeight))
+ b.add(new NodeWeight((dna.graph.weights.IWeightedNode) currentNode,newWeight));
+ }
+ else{
+ update = new double[]{oldWeight.getX(),oldWeight.getY(),oldWeight.getZ()};
+ }
+
+
+ // Edge Removal
+ EdgeContainer ec = null;
+ if(update[2] > treshold) {
+ newKey = currentWeighted.getIndex();
+ int from;
+ int to;
+ // Verhindere das Hinzufügen bereits gelöschter Kante
+ if(disabledEdges.containsKey(newKey)){
+ HashMap oldMap = disabledEdges.get(newKey);
+ for (Entry entry : oldMap.entrySet()) {
+ EdgeContainer key = entry.getKey();
+ Edge value = entry.getValue();
+ removeEdge(key.getTo(),key,value);
+ addEdge(key.getTo(), key, value);
+ removeEdge(key.getFrom(),key,value);
+ addEdge(key.getFrom(),key,value);
+ }
+ disabledEdges.remove(newKey);
+ }
+
+ // Lösche neue Kanten
+ for (IElement elem : currentWeighted.getEdges()) {
+ edge = (Edge) elem;
+ from = edge.getN1Index();
+ to = edge.getN2Index();
+ ec = new EdgeContainer(from, to);
+ removeEdge(from,ec,edge);
+ removeEdge(to, ec, edge);
+ addEdge(from,ec,edge);
+ addEdge(to, ec, edge);
+ toDisable.add(edge);
+ }
+ }
+ }
+
+ for (Edge e : toDisable) {
+ b.add(new EdgeRemoval(e));
+ }
+
+ for (Entry> freeEdges : disabledEdges.entrySet()) {
+ int node = freeEdges.getKey();
+ for (Entry elem : freeEdges.getValue().entrySet()) {
+ if(node == elem.getKey().getFrom())
+ b.add(new EdgeAddition(elem.getValue()));
+ }
+ }
+
+ disabledEdges=newDisabledEdges;
+
+ return b;
+ }
+
+ @Override
+ public void reset() {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public boolean isFurtherBatchPossible(Graph g) {
+ // TODO Auto-generated method stub
+ return true;
+ }
+
+ /**
+ *
+ * @param index
+ * @param ec
+ * @param e
+ */
+ public void removeEdge(int index, EdgeContainer ec, Edge e){
+ if(disabledEdges.containsKey(index)){
+ HashMap oldMap = disabledEdges.get(index);
+ oldMap.remove(ec);
+ if(oldMap.isEmpty()){
+ disabledEdges.remove(index);
+ }
+ }
+ }
+ public void addEdge(int index, EdgeContainer ec, Edge e){
+ if(newDisabledEdges.containsKey(index)){
+ HashMap oldMap = newDisabledEdges.get(index);
+ oldMap.put(ec, e);
+ }
+ else {
+ HashMap newMap = new HashMap<>();
+ newMap.put(ec, e);
+ newDisabledEdges.put(index,newMap);
+ }
+ }
+
+}