From bf5ffff4aa7afd163be898fc1eac24c926fc0f30 Mon Sep 17 00:00:00 2001
From: Letitia Li <letitia.li@telecom-paristech.fr>
Date: Thu, 29 Jun 2017 17:13:22 +0200
Subject: [PATCH] Avatar latency measurement in simulation

---
 .../avatartranslator/AvatarSpecification.java |   9 +-
 .../java/ui/AvatarDesignPanelTranslator.java  |   9 +
 src/main/java/ui/TToolBar.java                |   2 +-
 .../AvatarInteractiveSimulationActions.java   |   5 +-
 .../JFrameAvatarInteractiveSimulation.java    | 175 +++++++++++++++++-
 .../JFrameInteractiveSimulation.java          |  52 +++---
 .../LatencyTableModel.java                    |   6 +-
 .../SimulationLatency.java                    |   8 +-
 8 files changed, 222 insertions(+), 44 deletions(-)

diff --git a/src/main/java/avatartranslator/AvatarSpecification.java b/src/main/java/avatartranslator/AvatarSpecification.java
index 7cebaa4cc5..0bf3b87031 100644
--- a/src/main/java/avatartranslator/AvatarSpecification.java
+++ b/src/main/java/avatartranslator/AvatarSpecification.java
@@ -49,7 +49,7 @@ import java.util.HashMap;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
-
+import java.util.ArrayList;
 /**
    * Class AvatarSpecification
    * Avatar specification
@@ -75,7 +75,7 @@ public class AvatarSpecification extends AvatarElement {
     private LinkedList<AvatarPragma> pragmas;
     private LinkedList<String> safety_pragmas;
     private LinkedList<AvatarConstant> constants;
-
+	public List<String> checkedIDs;
     private boolean robustnessMade = false;
 
     private Object informationSource; // element from which the spec has been built
@@ -91,7 +91,7 @@ public class AvatarSpecification extends AvatarElement {
 	safety_pragmas = new LinkedList<String>();
         this.constants.add (AvatarConstant.FALSE);
         this.constants.add (AvatarConstant.TRUE);
-
+		checkedIDs= new ArrayList<String>();
         this.libraryFunctions = new LinkedList<AvatarLibraryFunction> ();
     }
 
@@ -640,6 +640,9 @@ public class AvatarSpecification extends AvatarElement {
 		    AvatarConstant cN = constant.advancedClone();
 		    spec.addConstant(cN);
 		}
+		for (String id:checkedIDs){
+			spec.checkedIDs.add(id);
+		}
 
 		spec.setInformationSource(getInformationSource());
 		spec.addApplicationCode(getApplicationCode());
diff --git a/src/main/java/ui/AvatarDesignPanelTranslator.java b/src/main/java/ui/AvatarDesignPanelTranslator.java
index b0f295809a..4038232401 100644
--- a/src/main/java/ui/AvatarDesignPanelTranslator.java
+++ b/src/main/java/ui/AvatarDesignPanelTranslator.java
@@ -1009,6 +1009,9 @@ public class AvatarDesignPanelTranslator {
 
         this.listE.addCor (aaos, asmdss);
         asmdss.setAVATARID (aaos.getID());
+		if (asmdss.getCheckLatency()){
+			_as.checkedIDs.add(asmdss.getName()+":"+aaos.getID());
+		}
         asm.addElement (aaos);
     }
 
@@ -1285,6 +1288,9 @@ public class AvatarDesignPanelTranslator {
         this.listE.addCor (aaos, asmdrs);
         asmdrs.setAVATARID (aaos.getID());
         asm.addElement (aaos);
+		if (asmdrs.getCheckLatency()){
+			_as.checkedIDs.add(asmdrs.getName()+":"+aaos.getID());
+		}
     }
 
     private void translateAvatarSMDState (TDiagramPanel tdp, AvatarSpecification _as, AvatarStateMachineOwner _ab, AvatarSMDState tgc) throws CheckingError {
@@ -1305,6 +1311,9 @@ public class AvatarDesignPanelTranslator {
         this.listE.addCor (astate, tgc);
         astate.addReferenceObject (tgc);
         tgc.setAVATARID (astate.getID());
+		if (tgc.getCheckLatency()){
+			_as.checkedIDs.add(tgc.getName()+":"+astate.getID());
+		}
     }
 
     private void translateAvatarSMDRandom (TDiagramPanel tdp, AvatarSpecification _as, AvatarStateMachineOwner _ab, AvatarSMDRandom asmdrand) throws CheckingError {
diff --git a/src/main/java/ui/TToolBar.java b/src/main/java/ui/TToolBar.java
index 9a998104e5..15062d8d2c 100755
--- a/src/main/java/ui/TToolBar.java
+++ b/src/main/java/ui/TToolBar.java
@@ -91,7 +91,7 @@ public abstract class TToolBar extends JToolBar {
                     String longText = p.executeRetStringMethod("CustomizerGraphicalComponent", "getLongText");
                     String veryShortText = p.executeRetStringMethod("CustomizerGraphicalComponent", "veryShortText");
                     ImageIcon img = p.executeRetImageIconMethod("CustomizerGraphicalComponent", "getImageIcon");
-                    if ((imgIcon != null)  && (shortText != null)) {
+                    if ((img != null)  && (shortText != null)) {
                         TraceManager.addDev("Plugin: " + p.getName() + " short name:" + shortText);
                         TAction t = new TAction("command-" + i, shortText, img, img, veryShortText, longText, 0);
                         TGUIAction tguia = new TGUIAction(t);
diff --git a/src/main/java/ui/avatarinteractivesimulation/AvatarInteractiveSimulationActions.java b/src/main/java/ui/avatarinteractivesimulation/AvatarInteractiveSimulationActions.java
index 26c1eabd42..7df2e86fc1 100755
--- a/src/main/java/ui/avatarinteractivesimulation/AvatarInteractiveSimulationActions.java
+++ b/src/main/java/ui/avatarinteractivesimulation/AvatarInteractiveSimulationActions.java
@@ -103,8 +103,8 @@ public class AvatarInteractiveSimulationActions extends AbstractAction {
     public static final int ACT_DELETE_ASYNC_MSG = 32;
     public static final int ACT_UP_ASYNC_MSG = 33;
     public static final int ACT_DOWN_ASYNC_MSG = 34;
-
-    public static final int NB_ACTION = 35;
+    public static final int ACT_ADD_LATENCY = 35;
+    public static final int NB_ACTION = 36;
 
 
     private  static final TAction [] actions = new TAction[NB_ACTION];
@@ -190,6 +190,7 @@ public class AvatarInteractiveSimulationActions extends AbstractAction {
         actions[ACT_DELETE_ASYNC_MSG] = new TAction("delete-async-command", "Delete", IconManager.imgic336, IconManager.imgic336, "Delete msg +", "Delete the selected message", '0');
         actions[ACT_UP_ASYNC_MSG] = new TAction("up-async-command", "Up", IconManager.imgic78, IconManager.imgic78, "Up msg", "Put a async msg closer to the FIFO exit", '0');
         actions[ACT_DOWN_ASYNC_MSG] = new TAction("up-async-command", "Down", IconManager.imgic79, IconManager.imgic79, "Down msg", "Put a async msg further from the FIFO exit", '0');
+        actions[ACT_ADD_LATENCY] = new TAction("add-latency-command", "Add latency", IconManager.imgic75, IconManager.imgic75, "Add latency", "Add latency checkpoint", '0');
     }
 
     public String getActionCommand()  {
diff --git a/src/main/java/ui/avatarinteractivesimulation/JFrameAvatarInteractiveSimulation.java b/src/main/java/ui/avatarinteractivesimulation/JFrameAvatarInteractiveSimulation.java
index 57ea772b1e..a60eb11888 100755
--- a/src/main/java/ui/avatarinteractivesimulation/JFrameAvatarInteractiveSimulation.java
+++ b/src/main/java/ui/avatarinteractivesimulation/JFrameAvatarInteractiveSimulation.java
@@ -47,6 +47,7 @@ import common.ConfigurationTTool;
 import myutil.*;
 import ui.*;
 import ui.avatarbd.AvatarBDPortConnector;
+import ui.interactivesimulation.*;
 import ui.util.IconManager;
 
 import javax.swing.*;
@@ -61,6 +62,11 @@ import java.io.File;
 import java.util.Hashtable;
 import java.util.LinkedList;
 import java.util.Vector;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Collections;
 
 /**
    * Class JFrameAvatarInteractiveSimulation
@@ -220,6 +226,20 @@ public  class JFrameAvatarInteractiveSimulation extends JFrame implements Avatar
     // Async messages
     Vector<AvatarSimulationAsynchronousTransaction> lastAsyncmsgs;
 
+    //Latency
+    JPanel latencyPanel;
+    JComboBox<String> transaction1;
+    JComboBox<String> transaction2;
+    JButton addLatencyCheckButton;
+    JButton updateLatencyButton;
+    LatencyTableModel latm;
+    public Vector<String> checkedTransactions = new Vector<String>();
+    private Vector<SimulationLatency> latencies = new Vector<SimulationLatency>();
+	List<String> toCheck = new ArrayList<String>();
+	Map<String, List<String>> transTimes = new HashMap<String, List<String>>();
+
+    private JScrollPane jspLatency;
+
     public JFrameAvatarInteractiveSimulation(/*Frame _f,*/ MainGUI _mgui, String _title, AvatarSpecification _avspec) {
         super(_title);
 
@@ -241,7 +261,10 @@ public  class JFrameAvatarInteractiveSimulation extends JFrame implements Avatar
         initActions();
 
         initSimulation();
-
+		for (String id: _avspec.checkedIDs){
+			checkedTransactions.add(id);
+			transTimes.put(id, new ArrayList<String>());		
+		}
         makeComponents();
         setComponents();
     }
@@ -772,6 +795,8 @@ public  class JFrameAvatarInteractiveSimulation extends JFrame implements Avatar
         transactionPanel.add(jspTransactionInfo, BorderLayout.CENTER);
 
 
+
+
 	// Met elements
         metElementsPanel = new JPanel();
         metElementsPanel.setLayout(new BorderLayout());
@@ -821,6 +846,71 @@ public  class JFrameAvatarInteractiveSimulation extends JFrame implements Avatar
         jspDisplayedBlocks.setPreferredSize(new Dimension(250, 300));
         infoTab.addTab("Displayed blocks", IconManager.imgic1202, jspDisplayedBlocks, "Displayed blocks");
 
+
+        // Latencies
+       	latencyPanel = new JPanel();
+		infoTab.addTab("Latencies", IconManager.imgic1202, latencyPanel, "Latencies");
+        GridBagLayout gridbag0 = new GridBagLayout();
+        GridBagConstraints c0 = new GridBagConstraints();
+        latencyPanel.setLayout(gridbag0);
+        c0.gridwidth = GridBagConstraints.REMAINDER;
+		latencyPanel.add(new JLabel("Latencies shown in number of cycles relative to the main clock"), c0);
+
+        c0.gridwidth=1;
+        c0.gridheight=1;
+        latencyPanel.add(new JLabel("Checkpoint 1:"),c0);
+        c0.gridwidth = GridBagConstraints.REMAINDER;
+        transaction1 = new JComboBox<String>(checkedTransactions);
+        latencyPanel.add(transaction1, c0);
+
+        c0.gridwidth=1;
+        latencyPanel.add(new JLabel("Checkpoint 2:"),c0);
+        c0.gridwidth= GridBagConstraints.REMAINDER;
+        transaction2 = new JComboBox<String>(checkedTransactions);
+        latencyPanel.add(transaction2, c0);
+
+
+        addLatencyCheckButton = new JButton(actions[AvatarInteractiveSimulationActions.ACT_ADD_LATENCY]);
+        latencyPanel.add(addLatencyCheckButton,c0);
+        latm = new LatencyTableModel();
+        latm.setData(latencies);
+        sorterPI = new TableSorter(latm);
+        final JTable latTable = new JTable(sorterPI);
+	/*	latTable.addMouseListener(new java.awt.event.MouseAdapter() {
+			@Override
+ 			public void mouseClicked(java.awt.event.MouseEvent evt) {
+    			int row = latTable.rowAtPoint(evt.getPoint());
+    			int col = latTable.columnAtPoint(evt.getPoint());
+    			if (row >= 0 && col >= 0 && col <2) {
+					for (TGComponent tgc: tmap.getTMLModeling().getCheckedComps().keySet()){
+						if (tmap.getTMLModeling().getCheckedComps().get(tgc).equals(latm.getValueAt(row,col).toString().split(" ")[0])){
+        				    mgui.selectTab(tgc.getTDiagramPanel());
+            				tgc.getTDiagramPanel().highlightTGComponent(tgc);
+						}
+					}
+    			}
+ 			}
+		});*/
+        sorterPI.setTableHeader(latTable.getTableHeader());
+        ((latTable.getColumnModel()).getColumn(0)).setPreferredWidth(700);
+        ((latTable.getColumnModel()).getColumn(1)).setPreferredWidth(700);
+        ((latTable.getColumnModel()).getColumn(2)).setPreferredWidth(100);
+        ((latTable.getColumnModel()).getColumn(3)).setPreferredWidth(100);
+        ((latTable.getColumnModel()).getColumn(4)).setPreferredWidth(100);
+        ((latTable.getColumnModel()).getColumn(5)).setPreferredWidth(100);
+        latTable.setAutoResizeMode(JTable.AUTO_RESIZE_ALL_COLUMNS);
+        jspLatency = new JScrollPane(latTable);
+        jspLatency.setWheelScrollingEnabled(true);
+        jspLatency.getVerticalScrollBar().setUnitIncrement(10);
+        jspLatency.setMinimumSize(new Dimension(400, 250));
+        jspLatency.setPreferredSize(new Dimension(1400, 250));
+        latencyPanel.add(jspLatency, c0);
+
+
+
+//        updateLatencyButton = new JButton(actions[InteractiveSimulationActions.ACT_UPDATE_LATENCY]);
+  //      latencyPanel.add(updateLatencyButton,c0);
+
         //Randomness
         randomPanel = new JPanel();
         randomPanel.setLayout(new GridBagLayout());
@@ -991,6 +1081,11 @@ public  class JFrameAvatarInteractiveSimulation extends JFrame implements Avatar
             ass.resetSimulation();
             //ass.backOneTransactionBunch();
         }
+	//	latencies.clear();
+		transTimes.clear();
+		for (String id: avspec.checkedIDs){
+			transTimes.put(id, new ArrayList<String>());		
+		}
         //ass.killSimulation();
     }
 
@@ -1332,10 +1427,84 @@ public  class JFrameAvatarInteractiveSimulation extends JFrame implements Avatar
         //nbOfAllExecutedElements = hashOfAllElements.hashCode();
     }
 
+	public void addLatency(){
+		toCheck.add(transaction1.getSelectedItem().toString()+"--"+transaction2.getSelectedItem().toString());
+		updateTransactionsTable();
+	}
+
     public void updateTransactionsTable() {
         if (transactiontm != null) {
             transactiontm.fireTableStructureChanged();
         }
+		if (ass!=null && latm!=null){
+			latencies.clear();
+			if (ass.getAllTransactions()!=null){
+				for (AvatarSimulationTransaction trans: ass.getAllTransactions()){
+					String id = ((TGComponent)trans.executedElement.getReferenceObject()).getName() + ":"+Integer.toString(trans.executedElement.getID());
+				//	System.out.println(id + " " + transTimes.keySet());
+				//	System.out.println("transaction " + trans.executedElement.getID() + " " + trans.initialClockValue);
+					if (transTimes.containsKey(id)){
+						if (!transTimes.get(id).contains(Long.toString(trans.initialClockValue))){
+							transTimes.get(id).add(Long.toString(trans.initialClockValue));
+						}
+					}
+				}
+			}
+		//	System.out.println(transTimes);
+			 for (String st1:transTimes.keySet()){
+                for (String st2:transTimes.keySet()){
+                    if (st1!=st2 && toCheck.contains(st1 +"--"+st2)){
+                            if (transTimes.get(st1) !=null && transTimes.get(st2)!=null){
+
+    	                        ArrayList<Integer> minTimes = new ArrayList<Integer>();
+								SimulationLatency sl = new SimulationLatency();
+								sl.trans1=st1;
+								sl.trans2=st2;
+                                for(String time1: transTimes.get(st1)){
+                                    //Find the first subsequent transaction
+                                    int time = Integer.MAX_VALUE;
+                                    for (String time2: transTimes.get(st2)){
+                                        int diff = Integer.valueOf(time2) - Integer.valueOf(time1);
+                                        if (diff < time && diff >=0){
+                                            time=diff;
+                                        }
+								//		System.out.println("diff " + diff + " " + transTimes.get(st1) + " " + transTimes.get(st2));
+                                    }
+                                    if (time!=Integer.MAX_VALUE){
+                                        minTimes.add(time);
+                                    }
+                                }
+							//	System.out.println("Min times " + minTimes);
+                                if (minTimes.size()>0){
+                                    int sum=0;
+                                    sl.minTime=Integer.toString(Collections.min(minTimes));
+                                    sl.maxTime=Integer.toString(Collections.max(minTimes));
+                                    for (int time: minTimes){
+                                        sum+=time;
+                                    }
+                                    double average = (double) sum/ (double) minTimes.size();
+                                    double stdev =0.0;
+                                    for (int time:minTimes){
+                                        stdev +=(time - average)*(time-average);
+                                    }
+                                    stdev= stdev/minTimes.size();
+                                    stdev = Math.sqrt(stdev);
+                                    sl.avTime= String.format("%.1f",average);
+                                    sl.stDev = String.format("%.1f",stdev);
+                                }
+								latencies.add(sl);
+
+                            }
+
+                        }
+
+                    }
+                }
+
+			if (latm !=null && latencies.size()>0){
+				latm.setData(latencies);
+     		}
+		}
     }
 
 
@@ -1789,7 +1958,9 @@ public  class JFrameAvatarInteractiveSimulation extends JFrame implements Avatar
         } else if (command.equals(actions[AvatarInteractiveSimulationActions.ACT_ZOOM_OUT].getActionCommand())) {
             zoomOut();
             return;
-
+        } else if (command.equals(actions[AvatarInteractiveSimulationActions.ACT_ADD_LATENCY].getActionCommand())) {
+            addLatency();
+            return;
         } else if (evt.getSource() == displayedTransactionsText) {
             TraceManager.addDev("Entered text:" + displayedTransactionsText.getText());
 
diff --git a/src/main/java/ui/interactivesimulation/JFrameInteractiveSimulation.java b/src/main/java/ui/interactivesimulation/JFrameInteractiveSimulation.java
index 48a86588f8..613c90e1ac 100755
--- a/src/main/java/ui/interactivesimulation/JFrameInteractiveSimulation.java
+++ b/src/main/java/ui/interactivesimulation/JFrameInteractiveSimulation.java
@@ -269,24 +269,7 @@ public class JFrameInteractiveSimulation extends JFrame implements ActionListene
         diagramTable = new Hashtable<String, String>();
 
 
-		tmlSimPanel = new JFrameTMLSimulationPanel(new Frame(), _mgui, "Simulation Transactions");
-		try {
-		pos = new PipedOutputStream();
-		pis = new PipedInputStream(pos, 4096);
-		tmlSimPanel.setFileReference(new BufferedReader(new InputStreamReader(pis)));
-		bw = new BufferedWriter(new OutputStreamWriter(pos));
 
-		//bw.close();
-		//pos.close();
-		}
-		catch (Exception e){
-			System.out.println("failed " + e);
-		}
-		for (TMLTask task : tmap.getTMLModeling().getTasks()){
-			simtraces.add("time=0 block="+ task.getName()+" type=state_entering state=startState");
-			simIndex++;
-		}
-		tmlSimPanel.setVisible(true);
 
         mgui.resetRunningID();
         mgui.resetLoadID();
@@ -967,7 +950,7 @@ public class JFrameInteractiveSimulation extends JFrame implements ActionListene
         addLatencyCheckButton = new JButton(actions[InteractiveSimulationActions.ACT_ADD_LATENCY]);
         latencyPanel.add(addLatencyCheckButton,c0);
 
-        latm = new LatencyTableModel(this);
+        latm = new LatencyTableModel();
         latm.setData(latencies);
         sorterPI = new TableSorter(latm);
         final JTable latTable = new JTable(sorterPI);
@@ -1397,24 +1380,35 @@ public class JFrameInteractiveSimulation extends JFrame implements ActionListene
     }
 	public void writeSimTrace(){
 		try {
-		Collections.sort(simtraces, new Comparator<String>() {
-
-    	@Override
-    	public int compare(String o1, String o2) {
-       		int i = Integer.valueOf((o1.split(" ")[0]).split("=")[1]);
-			int j = Integer.valueOf((o2.split(" ")[0]).split("=")[1]);
-			return i-j;
-    	}
-	});
-
+			tmlSimPanel = new JFrameTMLSimulationPanel(new Frame(), mgui, "Simulation Transactions");
+			pos = new PipedOutputStream();
+			pis = new PipedInputStream(pos, 4096);
+			tmlSimPanel.setFileReference(new BufferedReader(new InputStreamReader(pis)));
+			bw = new BufferedWriter(new OutputStreamWriter(pos));	
+			for (TMLTask task : tmap.getTMLModeling().getTasks()){
+				simtraces.add("time=0 block="+ task.getName()+" type=state_entering state=startState");
+				simIndex++;
+			}
+			//Sort simtraces by end time
+			Collections.sort(simtraces, new Comparator<String>() {
+    			@Override
+    			public int compare(String o1, String o2) {
+       				int i = Integer.valueOf((o1.split(" ")[0]).split("=")[1]);
+					int j = Integer.valueOf((o2.split(" ")[0]).split("=")[1]);
+					return i-j;
+    			}
+			});
 			//System.out.println(simtraces);
 			for (String s: simtraces){
-				bw.write("#0 " +s);
+				bw.write("#"+simIndex+ " "+s);
 				bw.newLine();
 				bw.flush();
+				simIndex++;
 			}
 			bw.close();
 			pos.close();
+			tmlSimPanel.setVisible(true);
+	
 		}
 		catch (Exception e){
 			System.out.println("Could not write sim trace " + e);
diff --git a/src/main/java/ui/interactivesimulation/LatencyTableModel.java b/src/main/java/ui/interactivesimulation/LatencyTableModel.java
index 01c710084b..9df771fe36 100755
--- a/src/main/java/ui/interactivesimulation/LatencyTableModel.java
+++ b/src/main/java/ui/interactivesimulation/LatencyTableModel.java
@@ -52,13 +52,13 @@ import java.util.Vector;
    * @author Ludovic APVRILLE
  */
 public class LatencyTableModel extends AbstractTableModel {
-    private JFrameInteractiveSimulation jfis;
+   // private JFrameInteractiveSimulation jfis;
     private int nbOfRows;
     private SimulationLatency data[];
 	
     //private String [] names;
-    public LatencyTableModel(JFrameInteractiveSimulation _jfis) {
-	jfis = jfis;
+    public LatencyTableModel() {
+//	jfis = jfis;
 	SimulationLatency sl = new SimulationLatency();
 	data = new SimulationLatency[]{sl};
 	
diff --git a/src/main/java/ui/interactivesimulation/SimulationLatency.java b/src/main/java/ui/interactivesimulation/SimulationLatency.java
index 109895c32e..64f8447b29 100644
--- a/src/main/java/ui/interactivesimulation/SimulationLatency.java
+++ b/src/main/java/ui/interactivesimulation/SimulationLatency.java
@@ -52,10 +52,10 @@ public class SimulationLatency  {
 
     public String trans1;
     public String trans2;
-    public String minTime=""; 
-	public String maxTime="";
-	public String avTime="";
-	public String stDev="";
+    public String minTime="N/A"; 
+	public String maxTime="N/A";
+	public String avTime="N/A";
+	public String stDev="N/A";
 
     public SimulationLatency() {
     }
-- 
GitLab