From fe2c004913444109eccc7d7dff5f0664042b0b3c Mon Sep 17 00:00:00 2001
From: Johannes Mey <johannes.mey@tu-dresden.de>
Date: Fri, 16 Sep 2022 14:26:57 +0200
Subject: [PATCH] festival updatesfestival updatesfestival updatesfestival
 updatesfestival updatesfestival updatesfestival updatesfestival updates

---
 src/main/jastadd/cleanup/Tracing.jadd         | 33 ++++---
 src/main/jastadd/common/Tracing.jadd          |  5 +-
 .../java/de/tudresden/inf/st/mg/Main.java     | 99 +++++++++++++------
 .../inf/st/mg/common/ColorDeserializer.java   |  3 +-
 .../inf/st/mg/common/DiagramProvider.java     | 57 +++++++----
 .../inf/st/mg/common/MotionGrammarParser.java |  8 +-
 .../de/tudresden/inf/st/mg/ParserTest.java    | 12 +--
 7 files changed, 140 insertions(+), 77 deletions(-)

diff --git a/src/main/jastadd/cleanup/Tracing.jadd b/src/main/jastadd/cleanup/Tracing.jadd
index 70ef06b..806fc83 100644
--- a/src/main/jastadd/cleanup/Tracing.jadd
+++ b/src/main/jastadd/cleanup/Tracing.jadd
@@ -2,26 +2,20 @@ aspect Tracing {
 
   refine
   public void Pose.setX(double x) {
-    World.printContextOf("Pose.setX()-BEFORE", this, de.tudresden.inf.st.mg.common.MotionGrammarConfig.REMOVE_COLOR);
     refined(x);
     World.printContextOf("Pose.setX()-AFTER", this, de.tudresden.inf.st.mg.common.MotionGrammarConfig.ADD_COLOR);
-    World.printContextOf("Pose.setX()-DONE", this, de.tudresden.inf.st.mg.common.MotionGrammarConfig.DEFAULT_COLOR);
   }
 
   refine
   public void Pose.setY(double y) {
-    World.printContextOf("Pose.setY()-BEFORE", this, de.tudresden.inf.st.mg.common.MotionGrammarConfig.REMOVE_COLOR);
     refined(y);
     World.printContextOf("Pose.setY()-AFTER", this, de.tudresden.inf.st.mg.common.MotionGrammarConfig.ADD_COLOR);
-    World.printContextOf("Pose.setY()-DONE", this, de.tudresden.inf.st.mg.common.MotionGrammarConfig.DEFAULT_COLOR);
   }
 
   refine
   public void Pose.setZ(double z) {
-    World.printContextOf("Pose.setZ()-BEFORE", this, de.tudresden.inf.st.mg.common.MotionGrammarConfig.REMOVE_COLOR);
     refined(z);
     World.printContextOf("Pose.setZ()-AFTER", this, de.tudresden.inf.st.mg.common.MotionGrammarConfig.ADD_COLOR);
-    World.printContextOf("Pose.setZ()-DONE", this, de.tudresden.inf.st.mg.common.MotionGrammarConfig.DEFAULT_COLOR);
   }
 
   refine
@@ -34,45 +28,52 @@ aspect Tracing {
   // this is probably never called because each child overrides the setter method
   refine
   public PhysicalObject PhysicalObject.setPose(Pose p) {
-    World.printContextOf("PhysicalObject.setPose()-BEFORE", getPose(), de.tudresden.inf.st.mg.common.MotionGrammarConfig.REMOVE_COLOR);
     refined(p);
     World.printContextOf("PhysicalObject.setPose()-AFTER", getPose(), de.tudresden.inf.st.mg.common.MotionGrammarConfig.ADD_COLOR);
-    World.printContextOf("PhysicalObject.setPose()-DONE", getPose(), de.tudresden.inf.st.mg.common.MotionGrammarConfig.DEFAULT_COLOR);
     return this;
   }
 
   refine
   public MovableObject MovableObject.setPose(Pose p) {
-    World.printContextOf("MovableObject.setPose()-BEFORE", getPose(), de.tudresden.inf.st.mg.common.MotionGrammarConfig.REMOVE_COLOR);
     refined(p);
     World.printContextOf("MovableObject.setPose()-AFTER", getPose(), de.tudresden.inf.st.mg.common.MotionGrammarConfig.ADD_COLOR);
-    World.printContextOf("MovableObject.setPose()-DONE", getPose(), de.tudresden.inf.st.mg.common.MotionGrammarConfig.DEFAULT_COLOR);
     return this;
   }
 
   refine
   public void Robot.setIsIdle(boolean b) {
-    World.printContextOf("Robot.setIsIdle()-BEFORE", this, de.tudresden.inf.st.mg.common.MotionGrammarConfig.REMOVE_COLOR);
     refined(b);
     World.printContextOf("Robot.setIsIdle()-AFTER", this, de.tudresden.inf.st.mg.common.MotionGrammarConfig.ADD_COLOR);
-    World.printContextOf("Robot.setIsIdle()-DONE", this, de.tudresden.inf.st.mg.common.MotionGrammarConfig.DEFAULT_COLOR);
   }
 
   refine RelAstAPI
   public Robot Robot.setAttachedItem(MovableObject o) {
-    World.printContextOf("Robot.setAttachedItem()-BEFORE", this, de.tudresden.inf.st.mg.common.MotionGrammarConfig.REMOVE_COLOR);
     var result = refined(o);
     World.printContextOf("Robot.setAttachedItem()-AFTER", this, de.tudresden.inf.st.mg.common.MotionGrammarConfig.ADD_COLOR);
-    World.printContextOf("Robot.setAttachedItem()-DONE", this, de.tudresden.inf.st.mg.common.MotionGrammarConfig.DEFAULT_COLOR);
     return result;
   }
 
   refine RelAstAPI
   public MovableObject MovableObject.setAttachedRobot(Robot r) {
-    World.printContextOf("MovableObject.setAttachedRobot()-BEFORE", this, de.tudresden.inf.st.mg.common.MotionGrammarConfig.REMOVE_COLOR);
     var result = refined(r);
     World.printContextOf("MovableObject.setAttachedRobot()-AFTER", this, de.tudresden.inf.st.mg.common.MotionGrammarConfig.ADD_COLOR);
-    World.printContextOf("MovableObject.setAttachedRobot()-DONE", this, de.tudresden.inf.st.mg.common.MotionGrammarConfig.DEFAULT_COLOR);
+    return result;
+  }
+
+  // refine
+  // public RobotWorld RobotWorld.addSelection(Selection s) {
+  //   RobotWorld w = refined(s);
+  //   World.printContextOf("Robot.addSelection()-AFTER", s, de.tudresden.inf.st.mg.common.MotionGrammarConfig.ADD_COLOR);
+  //   World.printContextOf("Robot.addSelection()-DONE", s, de.tudresden.inf.st.mg.common.MotionGrammarConfig.DEFAULT_COLOR);
+  //   return w;
+  // }
+
+  refine
+  public JastAddList<T> JastAddList.addChild(T node) {
+    JastAddList<T> result = refined(node);
+    if (node != null && node instanceof Selection && getParent() != null) {
+      World.printContextOf("Robot.addSelection()-AFTER", node, de.tudresden.inf.st.mg.common.MotionGrammarConfig.ADD_COLOR);
+    }
     return result;
   }
 
diff --git a/src/main/jastadd/common/Tracing.jadd b/src/main/jastadd/common/Tracing.jadd
index bc80715..628082f 100644
--- a/src/main/jastadd/common/Tracing.jadd
+++ b/src/main/jastadd/common/Tracing.jadd
@@ -30,6 +30,8 @@ aspect Tracing {
       }
     }
     String worldName = world.getClass().getSimpleName();
+    java.util.Date now = new java.util.Date();
+    java.nio.file.Path svgPath = de.tudresden.inf.st.mg.common.MotionGrammarConfig.astDiagramDir.resolve("Context-" + worldName + "-" + new java.text.SimpleDateFormat("yyyy.MM.dd.HH.mm.ss.SSS").format(now) + "-" + step + ".svg");
 
     try {
       de.tudresden.inf.st.jastadd.dumpAst.ast.Dumper.read(world)
@@ -39,10 +41,11 @@ aspect Tracing {
           .includeAttributeWhen((node, attributeName, isNTA, value) -> isNTA)
           .<ASTNode>includeChildWhen((parentNode, childNode, contextName) -> !((contextName.equals("Pose") || contextName.equals("Robot")) && childNode.inDemonstrationTable()))
           .<ASTNode>includeRelationsWhen((sourceNode, targetNode, roleName) -> !roleName.equals("AttachedRobot") && !(sourceNode != null && sourceNode.inDemonstrationTable()) && !(targetNode != null && targetNode.inDemonstrationTable())) // !sourceNode.inDemonstrationTable()
-          .dumpAsSVG(de.tudresden.inf.st.mg.common.MotionGrammarConfig.astDiagramDir.resolve("Context-" + worldName + "-" + new java.text.SimpleDateFormat("yyyy.MM.dd.HH.mm.ss.SSS").format(new java.util.Date()) + "-" + step + ".svg"));
+          .dumpAsSVG(svgPath);
     } catch (java.io.IOException e) {
       e.printStackTrace();
     }
+    de.tudresden.inf.st.mg.common.DiagramProvider.getInstance().publish(now, 0, step, svgPath, "context");
   }
 
 }
diff --git a/src/main/java/de/tudresden/inf/st/mg/Main.java b/src/main/java/de/tudresden/inf/st/mg/Main.java
index 9dcea61..60829c7 100644
--- a/src/main/java/de/tudresden/inf/st/mg/Main.java
+++ b/src/main/java/de/tudresden/inf/st/mg/Main.java
@@ -5,9 +5,11 @@ import com.fasterxml.jackson.databind.module.SimpleModule;
 import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
 import com.google.protobuf.util.JsonFormat;
 import de.tudresden.inf.st.ceti.Scene;
+import de.tudresden.inf.st.mg.common.DiagramProvider;
 import de.tudresden.inf.st.mg.common.MotionGrammarConfig;
 import de.tudresden.inf.st.mg.common.MotionGrammarParser;
 import de.tudresden.inf.st.mg.common.TableDeserializer;
+import de.tudresden.inf.st.mg.jastadd.model.JastAddList;
 import de.tudresden.inf.st.mg.jastadd.model.RobotWorld;
 import de.tudresden.inf.st.mg.jastadd.model.Table;
 import de.tudresden.inf.st.mg.jastadd.model.World;
@@ -18,61 +20,83 @@ import java.net.URISyntaxException;
 import java.nio.file.Files;
 import java.nio.file.Path;
 import java.util.Comparator;
+import java.util.Random;
 
 public class Main {
 
   public static final Path TIDY_AST_DIAGRAM_DIR = Path.of("src", "gen", "resources", "diagrams", "parsing", "tidy");
 
-  /**
-   * Runs the parser on the actual robot. For this to work, a robot controller must be connected to an MQTT server running
-   * on localhost:1883
-   */
-  public static void main(String[] args) {
+  private final RobotWorld world;
 
+  public Main(boolean simulate) {
     MotionGrammarConfig.astDiagramDir = TIDY_AST_DIAGRAM_DIR;
     try {
       Files.walk(TIDY_AST_DIAGRAM_DIR).sorted(Comparator.reverseOrder()).map(Path::toFile).forEach(File::delete);
       Files.createDirectories(TIDY_AST_DIAGRAM_DIR);
-    } catch (IOException e) {
-      // do nothing
+    } catch (IOException ignored) {
     }
 
-    RobotWorld world = RobotWorld.initialWorld();
-
+    if (simulate) {
+      world = RobotWorld.initialWorld(new Random(1));
+    } else {
+      world = RobotWorld.initialWorld();
+    }
     try {
       SimpleModule module = new SimpleModule();
       module.addDeserializer(Table.class, new TableDeserializer());
       ObjectMapper mapper = new ObjectMapper(new YAMLFactory());
       mapper.registerModule(module);
       world.setDemonstrationTable(mapper.readValue(Main.class.getResourceAsStream("config_scene_virtual-table.yaml"), Table.class));
-    } catch (IOException ignored) {
-      ignored.printStackTrace();
+    } catch (IOException e) {
+      e.printStackTrace();
     }
 
     World.enableContextPrinting(true);
     world.printContext("initial");
 
-    org.fusesource.mqtt.client.MQTT handler = new org.fusesource.mqtt.client.MQTT();
-    try {
-      handler.setHost("tcp://localhost:1883");
-    } catch (URISyntaxException e) {
-      e.printStackTrace();
-    }
-    world.connection = handler.blockingConnection();
-    try {
-      world.connection.connect();
-    } catch (Exception e) {
-      e.printStackTrace();
+    if (!simulate) {
+      org.fusesource.mqtt.client.MQTT handler = new org.fusesource.mqtt.client.MQTT();
+      try {
+        handler.setHost("tcp://localhost:1883");
+      } catch (URISyntaxException e) {
+        e.printStackTrace();
+      }
+      world.connection = handler.blockingConnection();
+      try {
+        world.connection.connect();
+      } catch (Exception e) {
+        e.printStackTrace();
+      }
+
+      System.err.println(world.connection.isConnected());
+
+      try {
+        world.connectTable("mqtt://localhost//ceti_cell_empty/scene/update");
+      } catch (IOException e) {
+        e.printStackTrace();
+      }
+
+      try {
+        world.connectSelection("mqtt://localhost/vr_selection");
+      } catch (IOException e) {
+        e.printStackTrace();
+      }
     }
 
-    System.err.println(world.connection.isConnected());
+  }
 
-    try {
-      world.connectTable("mqtt://localhost//ceti_cell_empty/scene/update");
-    } catch (IOException e) {
-      e.printStackTrace();
+  private Thread parse;
+
+  public void startParse() {
+    if (parse != null && parse.isAlive()) {
+      parse.interrupt(); // if not working replace by stop()
     }
+    parse = new Thread(this::parse);
+    parse.start();
+  }
 
+  public void parse() {
+    System.out.println("starting to parse");
     // create a parser using the world
     RobotParser parser = new RobotParser(world);
 
@@ -82,12 +106,27 @@ public class Main {
     } catch (MotionGrammarParser.ParseException e) {
       throw new RuntimeException(e);
     }
+    System.out.println("parsing completed!");
+  }
+
+  public void resetSelections() {
+    world.setSelectionList(new JastAddList<>());
+  }
 
+  /**
+   * Runs the parser on the actual robot. For this to work, a robot controller must be connected to an MQTT server running
+   * on localhost:1883
+   */
+  public static void main(String[] args) {
+    DiagramProvider webController = DiagramProvider.getInstance();
+    webController.setController(new Main(false));
     try {
-      Thread.sleep(100000 * 1000);
-    } catch (InterruptedException e) {
-      e.printStackTrace();
+      Thread.sleep(Long.MAX_VALUE);
+    } catch (InterruptedException ignored) {
     }
   }
 
+  public void printContext(String message) {
+    world.printContext(message);
+  }
 }
diff --git a/src/main/java/de/tudresden/inf/st/mg/common/ColorDeserializer.java b/src/main/java/de/tudresden/inf/st/mg/common/ColorDeserializer.java
index 437aac1..2af744d 100644
--- a/src/main/java/de/tudresden/inf/st/mg/common/ColorDeserializer.java
+++ b/src/main/java/de/tudresden/inf/st/mg/common/ColorDeserializer.java
@@ -26,7 +26,6 @@ public class ColorDeserializer extends JsonDeserializer<String> {
         Long g = nodeG == null ? 0 : Math.round(nodeG.asDouble() * 255);
         JsonNode nodeB = node.get("b");
         Long b = nodeB == null ? 0 : Math.round(nodeB.asDouble() * 255);
-        System.out.println("#" + String.format("%02X%02X%02X", r, g, b));
-        return "\"#" + String.format("%02X%02X%02X", r, g, b) + "\""; // FIXME remove quotes
+        return "#" + String.format("%02x%02x%02x", r, g, b);
     }
 }
diff --git a/src/main/java/de/tudresden/inf/st/mg/common/DiagramProvider.java b/src/main/java/de/tudresden/inf/st/mg/common/DiagramProvider.java
index d7c7881..1a3d247 100644
--- a/src/main/java/de/tudresden/inf/st/mg/common/DiagramProvider.java
+++ b/src/main/java/de/tudresden/inf/st/mg/common/DiagramProvider.java
@@ -1,11 +1,14 @@
 package de.tudresden.inf.st.mg.common;
 
+import de.tudresden.inf.st.mg.Main;
 import io.javalin.Javalin;
+import io.javalin.core.JavalinConfig;
 import io.javalin.websocket.WsContext;
 
 import java.io.IOException;
 import java.nio.file.Files;
 import java.nio.file.Path;
+import java.time.Instant;
 import java.util.ArrayList;
 import java.util.Date;
 import java.util.List;
@@ -16,6 +19,8 @@ public class DiagramProvider {
 
   private static DiagramProvider INSTANCE;
 
+  private Main controller;
+
   private static final Map<WsContext, String> clients = new ConcurrentHashMap<>();
 
   public static DiagramProvider getInstance() {
@@ -25,16 +30,22 @@ public class DiagramProvider {
     return INSTANCE;
   }
 
-  private final List<AST> asts;
+  private AST ast;
+  private AST context;
 
   private DiagramProvider() {
-    asts = new ArrayList<>();
+    ast = new AST(new Date(), 0, "<no rule>", "", "ast");
+    context = new AST(Date.from(Instant.now()), 0, "<no rule>", "", "context");
+
+    Javalin app = Javalin.create(JavalinConfig::enableCorsForAllOrigins).start(7070);
+    app.get("/", ctx -> ctx.result("the context is delivered at /context and the ast is delivered at /ast"));
 
-    Javalin app = Javalin.create(config -> config.enableCorsForOrigin("http://localhost:3000")).start(7070);
-    app.get("/", ctx -> ctx.result("Hello World"));
+    app.get("/ast/", ctx -> {
+      ctx.json(ast);
+    });
 
-    app.get("/asts/", ctx -> {
-      ctx.json(asts);
+    app.get("/context/", ctx -> {
+      ctx.json(context);
     });
 
     app.ws("ast-events", ws -> {
@@ -47,27 +58,34 @@ public class DiagramProvider {
         clients.remove(ctx);
       });
       ws.onMessage(ctx -> {
-        System.err.println("somebody sent us a message: " + ctx.message());
+        System.out.println("got message " + ctx.message());
+        if ("parse".equals(ctx.message()) && controller != null) {
+          controller.startParse();
+        } else if ("reset".equals(ctx.message()) && controller != null) {
+          controller.resetSelections();
+          controller.printContext("reset selection");
+        }
       });
     });
   }
 
-  public void publishAst(Date timestamp, int step, String parseRule, Path diagramPath) {
-    System.err.println("publishing AST");
+  public void publish(Date timestamp, int step, String parseRule, Path diagramPath, String type) {
     try {
-      asts.add(new AST(timestamp, step, parseRule, Files.readString(diagramPath)));
-      clients.keySet().forEach(session -> {
-        System.err.println("sending");
-        session.send(asts.get(asts.size() - 1));
-      });
+      if ("ast".equals(type)) {
+        ast = new AST(timestamp, step, parseRule, Files.readString(diagramPath), type);
+        clients.keySet().forEach(session -> session.send(ast));
+      } else if ("context".equals(type)) {
+        context = new AST(timestamp, step, parseRule, Files.readString(diagramPath), type);
+        clients.keySet().forEach(session -> session.send(context));
+      }
     } catch (IOException e) {
-      System.err.println("Unable to read AST diagram file " + diagramPath);
+      System.err.println("Unable to read " + type + " diagram file " + diagramPath);
       e.printStackTrace();
     }
   }
 
-  public void publishContext() {
-
+  public void setController(Main controller) {
+    this.controller = controller;
   }
 
   public static class AST {
@@ -76,11 +94,14 @@ public class DiagramProvider {
     public String parseRule;
     public String diagram;
 
-    public AST(Date timestamp, int step, String parseRule, String diagram) {
+    public String type;
+
+    public AST(Date timestamp, int step, String parseRule, String diagram, String type) {
       this.timestamp = timestamp;
       this.step = step;
       this.parseRule = parseRule;
       this.diagram = diagram;
+      this.type = type;
     }
   }
 
diff --git a/src/main/java/de/tudresden/inf/st/mg/common/MotionGrammarParser.java b/src/main/java/de/tudresden/inf/st/mg/common/MotionGrammarParser.java
index c88be6d..6a536e5 100644
--- a/src/main/java/de/tudresden/inf/st/mg/common/MotionGrammarParser.java
+++ b/src/main/java/de/tudresden/inf/st/mg/common/MotionGrammarParser.java
@@ -22,8 +22,10 @@ public abstract class MotionGrammarParser<T extends MotionGrammarElement> {
 
   protected static void waitSomeTime() {
     try {
-      Thread.sleep(1000/*ms*/);
-    } catch(InterruptedException ignored) {
+      Thread.sleep(100/*ms*/);
+    } catch(InterruptedException e) {
+      System.err.println("received interruption while parsing");
+      Thread.currentThread().stop();
     }
   }
 
@@ -73,7 +75,7 @@ public abstract class MotionGrammarParser<T extends MotionGrammarElement> {
           .skinParam(SkinParamBooleanSetting.Shadowing, false)
           .skinParam(SkinParamStringSetting.backgroundColor, "white")
           .dumpAsSVG(svgPath);
-      DiagramProvider.getInstance().publishAst(new Date(), timeStep_, step, svgPath);
+      DiagramProvider.getInstance().publish(new Date(), timeStep_, step, svgPath, "ast");
       timeStep_++;
     } catch (IOException e) {
       e.printStackTrace();
diff --git a/src/test/java/de/tudresden/inf/st/mg/ParserTest.java b/src/test/java/de/tudresden/inf/st/mg/ParserTest.java
index 9ad07f0..cc683a6 100644
--- a/src/test/java/de/tudresden/inf/st/mg/ParserTest.java
+++ b/src/test/java/de/tudresden/inf/st/mg/ParserTest.java
@@ -56,7 +56,11 @@ public class ParserTest {
 
     // for some reason, the best random seed value here is 1 and not 0???
     RobotWorld world = RobotWorld.initialWorld(new Random(1));
-    World.printContextOf("initial", null, "");
+    world.printContext("initial");
+
+    // create a parser using the world
+    RobotParser parser = new RobotParser(world);
+    parser.setDebugDiagramDir(TIDY_AST_DIAGRAM_DIR);
 
     world.addSelection(new Selection().setObject("boxRed").setTimeStamp(java.time.Instant.now()))
         .addSelection(new Selection().setObject("boxGreen").setTimeStamp(java.time.Instant.now()))
@@ -65,12 +69,6 @@ public class ParserTest {
         .addSelection(new Selection().setObject("boxRed").setTimeStamp(java.time.Instant.now()))
         .addSelection(new Selection().setObject("boxRed").setTimeStamp(java.time.Instant.now()));
 
-    World.printContextOf("initial-with-selection", null, "");
-
-    // create a parser using the world
-    RobotParser parser = new RobotParser(world);
-    parser.setDebugDiagramDir(TIDY_AST_DIAGRAM_DIR);
-
     // parse (synchronously, long-running)
     var result = parser.parse();
 
-- 
GitLab