1 package net.mograsim.logic.model.examples;
3 import java.io.IOException;
4 import java.nio.file.Files;
5 import java.nio.file.Path;
6 import java.nio.file.Paths;
7 import java.util.Arrays;
8 import java.util.Collection;
9 import java.util.Comparator;
10 import java.util.HashMap;
11 import java.util.HashSet;
13 import java.util.Map.Entry;
14 import java.util.Optional;
15 import java.util.Scanner;
17 import java.util.function.Function;
18 import java.util.stream.Collectors;
19 import java.util.stream.Stream;
21 import net.haspamelodica.swt.helper.swtobjectwrappers.Point;
22 import net.mograsim.logic.model.am2900.Am2900Loader;
23 import net.mograsim.logic.model.model.LogicModelModifiable;
24 import net.mograsim.logic.model.model.components.ModelComponent;
25 import net.mograsim.logic.model.model.components.submodels.SubmodelComponent;
26 import net.mograsim.logic.model.model.components.submodels.SubmodelInterface;
27 import net.mograsim.logic.model.model.wires.ModelWire;
28 import net.mograsim.logic.model.model.wires.ModelWireCrossPoint;
29 import net.mograsim.logic.model.model.wires.MovablePin;
30 import net.mograsim.logic.model.model.wires.Pin;
31 import net.mograsim.logic.model.model.wires.PinUsage;
32 import net.mograsim.logic.model.serializing.DeserializedSubmodelComponent;
33 import net.mograsim.logic.model.serializing.IdentifyParams;
34 import net.mograsim.logic.model.serializing.IndirectModelComponentCreator;
35 import net.mograsim.logic.model.serializing.SubmodelComponentSerializer;
36 import net.mograsim.logic.model.snippets.highlevelstatehandlers.DefaultHighLevelStateHandler;
38 public class ReserializeAndVerifyJSONs
40 public static double GRIDSIZE = 2.5;
41 public static boolean changePinUsages = false;
42 public static boolean changeComponentNames = false;
43 public static boolean snapWCPs = true;
44 public static boolean warnNonSnappedPoints = true;
45 public static boolean warnNonVertHorizLines = true;
46 public static boolean warnRedundantWires = true;
48 public static void main(String[] args) throws IOException
51 try (Scanner sysin = new Scanner(System.in))
53 System.out.print("Directory to search for JSONs in / JSON file to reserialize >");
54 Path root = Paths.get(sysin.nextLine());
55 if (!Files.exists(root))
56 throw new IllegalArgumentException("Path doesn't exist");
57 if (Files.isRegularFile(root))
58 reserializeJSON(root, sysin);
61 System.out.print("Recursive? >");
62 boolean recursive = Boolean.valueOf(sysin.nextLine());
63 try (Stream<Path> jsons = recursive ? Files.walk(root) : Files.list(root))
65 jsons.filter(Files::isRegularFile).filter(p -> p.getFileName().toString().endsWith(".json"))
66 .forEach(j -> reserializeJSON(j, sysin));
72 public static void reserializeJSON(Path componentPath, Scanner sysin)
76 DeserializedSubmodelComponent comp = (DeserializedSubmodelComponent) IndirectModelComponentCreator
77 .createComponent(new LogicModelModifiable(), "jsonfile:" + componentPath.toString());
78 System.out.println("Reserializing " + componentPath);
79 LogicModelModifiable submodelModifiable = comp.getSubmodelModifiable();
80 Map<String, String> componentNameRemapping = new HashMap<>();
83 changePinUsages(sysin, comp);
84 if (changeComponentNames)
85 changeComponentNames(sysin, submodelModifiable, componentNameRemapping);
87 snapWCPs(submodelModifiable);
88 if (warnNonSnappedPoints)
89 warnNonSnappedPoints(comp, submodelModifiable);
90 if (warnNonVertHorizLines)
91 warnNonVertHorizLines(submodelModifiable);
92 if (warnRedundantWires)
93 warnRedundantWires(submodelModifiable);
95 SubmodelComponentSerializer.serialize(comp, componentPath.toString());
97 if (changeComponentNames)
98 changeComponentNames_AfterSerialization(sysin, comp, componentNameRemapping);
102 System.err.println("An error occurred visiting " + componentPath + ":");
107 private static void warnRedundantWires(LogicModelModifiable submodelModifiable)
109 Map<Pin, Set<Pin>> connectedPinGroups = new HashMap<>();
110 submodelModifiable.getComponentsByName().values().stream().map(ModelComponent::getPins).map(Map::values).flatMap(Collection::stream)
111 .forEach(p -> connectedPinGroups.put(p, new HashSet<>(Arrays.asList(p))));
112 submodelModifiable.getWiresByName().values().forEach(w ->
114 Pin pin1 = w.getPin1();
115 Pin pin2 = w.getPin2();
116 Set<Pin> pin1Group = connectedPinGroups.get(pin1);
117 Set<Pin> pin2Group = connectedPinGroups.get(pin2);
118 if (pin1Group == pin2Group)
119 System.out.println(" Wire " + w.name + " connecting " + pin1 + " and " + pin2 + " is redundant");
122 pin1Group.addAll(pin2Group);
123 pin2Group.forEach(p -> connectedPinGroups.put(p, pin1Group));
128 private static void changePinUsages(Scanner sysin, DeserializedSubmodelComponent comp)
130 comp.getSupermodelPins().entrySet().stream().sorted(Comparator.comparing(Entry::getKey)).map(Entry::getValue).forEach(pin ->
132 PinUsage usage = null;
133 while (usage == null)
136 System.out.print(" Usage for interface pin " + pin.name + " (empty: " + pin.usage + ") >");
137 String usageStr = sysin.nextLine().toUpperCase();
138 usage = usageStr.equals("") ? pin.usage
139 : usageStr.equals("I") ? PinUsage.INPUT
140 : usageStr.equals("O") ? PinUsage.OUTPUT
141 : usageStr.equals("T") ? PinUsage.TRISTATE : PinUsage.valueOf(usageStr);
143 catch (@SuppressWarnings("unused") IllegalArgumentException e)
145 System.err.println(" Illegal usage");
147 setInterfacePinUsage(comp, pin, usage);
151 private static void changeComponentNames(Scanner sysin, LogicModelModifiable submodelModifiable,
152 Map<String, String> componentNameRemapping)
154 componentNameRemapping.put(SubmodelComponent.SUBMODEL_INTERFACE_NAME, SubmodelComponent.SUBMODEL_INTERFACE_NAME);
155 LogicModelModifiable tempModel = new LogicModelModifiable();
156 IdentifyParams iP = new IdentifyParams();
157 submodelModifiable.getComponentsByName().entrySet().stream()
158 .filter(e -> !e.getKey().equals(SubmodelComponent.SUBMODEL_INTERFACE_NAME))
159 .sorted(Comparator.comparing(Entry::getKey, ReserializeAndVerifyJSONs::compareStringsWithIntegers)).forEach(e ->
161 String oldName = e.getKey();
162 ModelComponent subcomp = e.getValue();
163 String defaultName = tempModel.getDefaultComponentName(subcomp);
164 String newName = null;
165 while (newName == null)
167 System.out.print(" New name for component " + oldName + " of type " + subcomp.getIDForSerializing(iP) + " (empty: "
168 + defaultName + ") >");
169 newName = sysin.nextLine();
170 if (newName.equals(""))
171 newName = defaultName;
172 if (tempModel.getComponentsByName().containsKey(newName))
174 System.err.println(" There already is a component with that name");
178 componentNameRemapping.put(oldName, newName);
179 IndirectModelComponentCreator
180 .createComponent(tempModel, subcomp.getIDForSerializing(iP), subcomp.getParamsForSerializingJSON(iP), newName)
181 .moveTo(subcomp.getPosX(), subcomp.getPosY());
183 SubmodelInterface tempSubmodelInterface = new SubmodelInterface(tempModel);
184 for (Pin p : submodelModifiable.getComponentsByName().get(SubmodelComponent.SUBMODEL_INTERFACE_NAME).getPins().values())
185 tempSubmodelInterface
186 .addPin(new Pin(tempModel, tempSubmodelInterface, p.name, p.logicWidth, p.usage, p.getRelX(), p.getRelY()));
187 for (ModelWire w : submodelModifiable.getWiresByName().values())
188 createWire(componentNameRemapping::get, tempModel, w);
190 Optional<ModelComponent> o;
191 while ((o = submodelModifiable.getComponentsByName().values().stream()
192 .filter(c -> !c.getName().equals(SubmodelComponent.SUBMODEL_INTERFACE_NAME)).findAny()).isPresent())
193 submodelModifiable.destroyComponent(o.get());
195 tempModel.getComponentsByName().values().stream().filter(c -> !c.getName().equals(SubmodelComponent.SUBMODEL_INTERFACE_NAME))
196 .forEach(c -> IndirectModelComponentCreator
197 .createComponent(submodelModifiable, c.getIDForSerializing(iP), c.getParamsForSerializingJSON(iP), c.getName())
198 .moveTo(c.getPosX(), c.getPosY()));
199 for (ModelWire w : tempModel.getWiresByName().values())
200 createWire(Function.identity(), submodelModifiable, w);
203 private static void changeComponentNames_AfterSerialization(Scanner sysin, DeserializedSubmodelComponent comp,
204 Map<String, String> componentNameRemapping)
206 if (comp.getHighLevelStateHandler() == null || !(comp.getHighLevelStateHandler() instanceof DefaultHighLevelStateHandler))
208 System.out.println(" A non-default HighLevelStateHandler was detected. Check for changes there manually.");
209 System.out.print(" Empty line to continue to next component, old component name to get new component name >");
210 for (String line = sysin.nextLine(); !line.equals(""); line = sysin.nextLine())
211 System.out.println(" " + line + "->" + componentNameRemapping.get(line) + " >");
215 private static void snapWCPs(LogicModelModifiable submodelModifiable)
217 submodelModifiable.getComponentsByName().values().stream().filter(c -> c instanceof ModelWireCrossPoint).forEach(c ->
219 double x = c.getPosX();
220 double y = c.getPosY();
221 double newX = x % GRIDSIZE == 0 ? x - 1 : x;
222 double newY = y % GRIDSIZE == 0 ? y - 1 : y;
223 if (x != newX || y != newY)
225 c.moveTo(newX, newY);
226 System.out.println(" Snapping WCP " + c.getName());
231 private static void warnNonSnappedPoints(DeserializedSubmodelComponent comp, LogicModelModifiable submodelModifiable)
233 if (comp.getWidth() % GRIDSIZE != 0 || comp.getHeight() % GRIDSIZE != 0)
234 System.out.println(" Size is not snapped to grid: " + comp.getWidth() + "," + comp.getHeight());
235 submodelModifiable.getComponentsByName().values().forEach(c ->
237 double x = c.getPosX();
238 double y = c.getPosY();
239 if (c instanceof ModelWireCrossPoint)
244 if (x % GRIDSIZE != 0 || y % GRIDSIZE != 0)
245 System.out.println(" Component " + c.getName() + " (type " + c.getIDForSerializing(new IdentifyParams())
246 + ") is not snapped to grid: " + x + "," + y);
248 submodelModifiable.getWiresByName().values().forEach(w ->
250 Point[] p = w.getPath();
252 for (int i = 0; i < p.length; i++)
253 if (p[i].x % GRIDSIZE != 0 || p[i].y % GRIDSIZE != 0)
254 System.out.println(" Wire " + w.name + " path point #" + i + " is not snapped to grid: " + p[i].x + "," + p[i].y);
256 comp.getPins().values().forEach(p ->
258 if (p.getRelX() % GRIDSIZE != 0 || p.getRelY() % GRIDSIZE != 0)
259 System.out.println(" Interface point " + p.name + " is not snapped to grid: " + p.getRelX() + "," + p.getRelY());
263 private static void warnNonVertHorizLines(LogicModelModifiable submodelModifiable)
265 submodelModifiable.getWiresByName().values().forEach(w ->
267 double[] p = w.getEffectivePath();
268 for (int i = 1; i < p.length / 2; i++)
270 double x1 = p[2 * i - 2];
271 double y1 = p[2 * i - 1];
272 double x2 = p[2 * i + 0];
273 double y2 = p[2 * i + 1];
274 if (x1 != x2 && y1 != y2)
275 System.out.println(" Wire " + w.name + " part #" + (i - 1) + " is neither vertical nor horizontal");
280 private static ModelWire createWire(Function<String, String> componentNameRemapping, LogicModelModifiable tempModelForDefaultNames,
283 return new ModelWire(tempModelForDefaultNames, w.name,
284 getRemappedPin(componentNameRemapping, tempModelForDefaultNames, w.getPin1()),
285 getRemappedPin(componentNameRemapping, tempModelForDefaultNames, w.getPin2()), w.getPath());
288 private static Pin getRemappedPin(Function<String, String> componentNameRemapping, LogicModelModifiable tempModelForDefaultNames,
291 return tempModelForDefaultNames.getComponentsByName().get(componentNameRemapping.apply(pin.component.getName())).getPin(pin.name);
294 private static int compareStringsWithIntegers(String a, String b)
300 if (aLoc == a.length())
302 if (bLoc == b.length())
306 if (bLoc == b.length())
313 nextCharA = a.charAt(aLoc++);
314 if (nextCharA < '0' || nextCharA > '9')
317 aInt = aInt * 10 + nextCharA - '0';
318 if (aLoc == a.length())
326 nextCharB = b.charAt(bLoc++);
327 if (nextCharB < '0' || nextCharB > '9')
330 bInt = bInt * 10 + nextCharB - '0';
331 if (bLoc == b.length())
338 int comp = Integer.compare(aInt, bInt);
345 int comp = Character.compare(nextCharA, nextCharB);
352 private static void setInterfacePinUsage(DeserializedSubmodelComponent comp, Pin interfacePin, PinUsage usage)
354 Set<ModelWire> wiresConnectedToPin = comp.submodel.getWiresByName().values().stream()
355 .filter(w -> w.getPin1() == interfacePin || w.getPin2() == interfacePin).collect(Collectors.toSet());
356 LogicModelModifiable submodelModifiable = comp.getSubmodelModifiable();
357 wiresConnectedToPin.forEach(submodelModifiable::destroyWire);
358 comp.removeSubmodelInterface(interfacePin.name);
359 comp.addSubmodelInterface(new MovablePin(submodelModifiable, comp, interfacePin.name, interfacePin.logicWidth, usage,
360 interfacePin.getRelX(), interfacePin.getRelY()));
361 wiresConnectedToPin.forEach(w -> new ModelWire(submodelModifiable, w.getPin1(), w.getPin2()));