From aaeddd0a824e82deef982128573d652ececea0d7 Mon Sep 17 00:00:00 2001
From: Stephan Richter <github@keawe.de>
Date: Mon, 30 Nov 2020 19:57:59 +0100
Subject: [PATCH] implemented bridge

---
 pom.xml                                       |  2 +-
 resources/css/style.css                       | 10 ++++
 resources/svg/BridgeE.svg                     |  4 ++
 resources/svg/BridgeN.svg                     |  4 ++
 resources/svg/BridgeS.svg                     |  4 ++
 resources/svg/BridgeW.svg                     |  4 ++
 .../java/de/srsoftware/web4rail/Plan.java     | 16 +++++
 .../java/de/srsoftware/web4rail/Route.java    |  4 +-
 .../de/srsoftware/web4rail/tiles/Bridge.java  | 59 +++++++++++++++++++
 .../de/srsoftware/web4rail/tiles/BridgeE.java | 30 ++++++++++
 .../de/srsoftware/web4rail/tiles/BridgeN.java | 30 ++++++++++
 .../de/srsoftware/web4rail/tiles/BridgeS.java | 30 ++++++++++
 .../de/srsoftware/web4rail/tiles/BridgeW.java | 31 ++++++++++
 13 files changed, 225 insertions(+), 3 deletions(-)
 create mode 100644 resources/svg/BridgeE.svg
 create mode 100644 resources/svg/BridgeN.svg
 create mode 100644 resources/svg/BridgeS.svg
 create mode 100644 resources/svg/BridgeW.svg
 create mode 100644 src/main/java/de/srsoftware/web4rail/tiles/Bridge.java
 create mode 100644 src/main/java/de/srsoftware/web4rail/tiles/BridgeE.java
 create mode 100644 src/main/java/de/srsoftware/web4rail/tiles/BridgeN.java
 create mode 100644 src/main/java/de/srsoftware/web4rail/tiles/BridgeS.java
 create mode 100644 src/main/java/de/srsoftware/web4rail/tiles/BridgeW.java

diff --git a/pom.xml b/pom.xml
index b4506e1..dc87e21 100644
--- a/pom.xml
+++ b/pom.xml
@@ -4,7 +4,7 @@
 	<modelVersion>4.0.0</modelVersion>
 	<groupId>de.srsoftware</groupId>
 	<artifactId>web4rail</artifactId>
-	<version>1.1.9</version>
+	<version>1.1.10</version>
 	<name>Web4Rail</name>
 	<packaging>jar</packaging>
 	<description>Java Model Railway Control</description>
diff --git a/resources/css/style.css b/resources/css/style.css
index a00c6ee..b34d286 100644
--- a/resources/css/style.css
+++ b/resources/css/style.css
@@ -309,4 +309,14 @@ table.brake-times th{
 	border-color: black;
 	border-style: solid;
 	border-width: 1px 0 0;
+}
+
+polyline{
+	stroke: black;
+	stroke-width: 5px;
+	fill: none;
+}
+
+svg.disconnected rect{
+	fill: red;
 }
\ No newline at end of file
diff --git a/resources/svg/BridgeE.svg b/resources/svg/BridgeE.svg
new file mode 100644
index 0000000..c82f337
--- /dev/null
+++ b/resources/svg/BridgeE.svg
@@ -0,0 +1,4 @@
+<svg width="100" height="" viewbox="0 0 100 100">
+	<rect x="20" y="35" width="80" height="30" />	
+	<polyline points="30,10 20,20 20,80 30,90" />
+</svg>
\ No newline at end of file
diff --git a/resources/svg/BridgeN.svg b/resources/svg/BridgeN.svg
new file mode 100644
index 0000000..35ef77c
--- /dev/null
+++ b/resources/svg/BridgeN.svg
@@ -0,0 +1,4 @@
+<svg width="100" height="" viewbox="0 0 100 100">
+	<rect x="35" y="0" width="30" height="80" />	
+	<polyline points="10,70 20,80 80,80 90,70" />
+</svg>
\ No newline at end of file
diff --git a/resources/svg/BridgeS.svg b/resources/svg/BridgeS.svg
new file mode 100644
index 0000000..ef6d9ca
--- /dev/null
+++ b/resources/svg/BridgeS.svg
@@ -0,0 +1,4 @@
+<svg width="100" height="" viewbox="0 0 100 100">
+	<rect x="35" y="20" width="30" height="80" />	
+	<polyline points="10,30 20,20 80,20 90,30" />
+</svg>
\ No newline at end of file
diff --git a/resources/svg/BridgeW.svg b/resources/svg/BridgeW.svg
new file mode 100644
index 0000000..5b46d6e
--- /dev/null
+++ b/resources/svg/BridgeW.svg
@@ -0,0 +1,4 @@
+<svg width="100" height="" viewbox="0 0 100 100">
+	<rect x="0" y="35" width="80" height="30" />	
+	<polyline points="70,10 80,20 80,80 70,90" />
+</svg>
\ No newline at end of file
diff --git a/src/main/java/de/srsoftware/web4rail/Plan.java b/src/main/java/de/srsoftware/web4rail/Plan.java
index a950041..98c35bb 100644
--- a/src/main/java/de/srsoftware/web4rail/Plan.java
+++ b/src/main/java/de/srsoftware/web4rail/Plan.java
@@ -40,6 +40,11 @@ import de.srsoftware.web4rail.tags.Table;
 import de.srsoftware.web4rail.tiles.Block;
 import de.srsoftware.web4rail.tiles.BlockH;
 import de.srsoftware.web4rail.tiles.BlockV;
+import de.srsoftware.web4rail.tiles.Bridge;
+import de.srsoftware.web4rail.tiles.BridgeE;
+import de.srsoftware.web4rail.tiles.BridgeN;
+import de.srsoftware.web4rail.tiles.BridgeS;
+import de.srsoftware.web4rail.tiles.BridgeW;
 import de.srsoftware.web4rail.tiles.Contact;
 import de.srsoftware.web4rail.tiles.ContactH;
 import de.srsoftware.web4rail.tiles.ContactV;
@@ -171,6 +176,10 @@ public class Plan extends BaseClass{
 			return analyze();
 		case ACTION_CLICK:
 			return click(get(params.get(ID),true));
+		case ACTION_CONNECT:
+			Tile tile = get(params.get(ID), false);
+			if (tile instanceof Bridge) return ((Bridge)tile).requestConnect();
+			break;
 		case ACTION_MOVE:
 			return moveTile(params.get(DIRECTION),params.get(ID));
 		case ACTION_PROPS:
@@ -248,6 +257,9 @@ public class Plan extends BaseClass{
 	private String analyze() {
 		Vector<Route> routes = new Vector<Route>();
 		for (Block block : blocks) {
+			if (block.name.equals("Huhu")) {
+				System.err.println("Here we go!");
+			}
 			for (Connector con : block.startPoints()) {
 				routes.addAll(follow(new Route().begin(block,con.from.inverse()),con));
 			}
@@ -859,6 +871,10 @@ public class Plan extends BaseClass{
 		new CrossV().tag(null).addTo(tiles);
 		new CrossH().tag(null).addTo(tiles);
 		new CrossPlus().tag(null).addTo(tiles);
+		new BridgeE().tag(null).addTo(tiles);
+		new BridgeN().tag(null).addTo(tiles);
+		new BridgeS().tag(null).addTo(tiles);
+		new BridgeW().tag(null).addTo(tiles);
 		new StraightH().tag(null).addTo(tiles);
 		new StraightV().tag(null).addTo(tiles);
 		new ContactH().tag(null).addTo(tiles);
diff --git a/src/main/java/de/srsoftware/web4rail/Route.java b/src/main/java/de/srsoftware/web4rail/Route.java
index 5b03967..9066597 100644
--- a/src/main/java/de/srsoftware/web4rail/Route.java
+++ b/src/main/java/de/srsoftware/web4rail/Route.java
@@ -367,14 +367,14 @@ public class Route extends BaseClass implements Comparable<Route>{
 		return true;
 	}
 	
-	public Route begin(Block block,Direction from) {
+	public Route begin(Block block,Direction to) {
 		// add those fields to clone, too!
 		contacts = new Vector<Contact>();
 		signals = new Vector<Signal>();
 		path = new Vector<Tile>();
 		turnouts = new HashMap<>();
 		startBlock = block;
-		startDirection = from;
+		startDirection = to;
 		path.add(block);
 		return this;
 	}
diff --git a/src/main/java/de/srsoftware/web4rail/tiles/Bridge.java b/src/main/java/de/srsoftware/web4rail/tiles/Bridge.java
new file mode 100644
index 0000000..396843f
--- /dev/null
+++ b/src/main/java/de/srsoftware/web4rail/tiles/Bridge.java
@@ -0,0 +1,59 @@
+package de.srsoftware.web4rail.tiles;
+
+import java.io.IOException;
+import java.util.Map;
+
+import de.srsoftware.tools.Tag;
+import de.srsoftware.web4rail.Connector;
+import de.srsoftware.web4rail.Window;
+import de.srsoftware.web4rail.tags.Button;
+import de.srsoftware.web4rail.tiles.Turnout.State;
+
+public abstract class Bridge extends Tile {
+	private static Bridge pendingConnection = null;
+	protected Bridge counterpart = null;
+	
+	@Override
+	public Object click() throws IOException {
+		if (pendingConnection != null) return connect();
+		return super.click();
+	}
+	
+	private Object connect() {
+		if (this == pendingConnection) return t("Cannot connect {} to itself!",this);
+		if (isSet(counterpart)) {
+			counterpart.counterpart = null; // drop other connection
+			plan.place(counterpart);
+		}
+		counterpart = pendingConnection;
+		counterpart.counterpart = this;
+		pendingConnection = null;
+		plan.place(this);
+		plan.place(counterpart);
+		return t("Connected {} and {}.",this,counterpart);
+	}
+	
+	protected abstract Connector connector();
+
+	@Override
+	public Window propMenu() {
+		Window win = super.propMenu();
+		Map<String, String> props = Map.of(REALM,REALM_PLAN,ID,id(),ACTION,ACTION_CONNECT);
+		new Tag("h4").content("Counterpart").addTo(win);
+		new Tag("p").content(isSet(counterpart) ? t("Connected to {}.",counterpart) : t("Not connected to other bridge part!")).addTo(win);
+		new Button(t("Select counterpart"), props).addTo(win);
+		return win;
+	}
+
+	public Object requestConnect() {
+		pendingConnection = this;
+		return t("Click other bridge to connect to!");
+	}
+	
+	@Override
+	public Tag tag(Map<String, Object> replacements) throws IOException {
+		Tag tag = super.tag(replacements);
+		if (isNull(counterpart)) tag.clazz(tag.get("class")+" disconnected");
+		return tag;
+	}
+}
diff --git a/src/main/java/de/srsoftware/web4rail/tiles/BridgeE.java b/src/main/java/de/srsoftware/web4rail/tiles/BridgeE.java
new file mode 100644
index 0000000..5539031
--- /dev/null
+++ b/src/main/java/de/srsoftware/web4rail/tiles/BridgeE.java
@@ -0,0 +1,30 @@
+package de.srsoftware.web4rail.tiles;
+
+import java.util.List;
+import java.util.Map;
+
+import de.srsoftware.web4rail.Connector;
+import de.srsoftware.web4rail.Plan.Direction;
+import de.srsoftware.web4rail.tiles.Turnout.State;
+
+public class BridgeE extends Bridge {
+	@Override
+	public List<Direction> possibleDirections() {
+		return List.of(Direction.EAST);
+	}
+	
+	@Override
+	public Map<Connector, State> connections(Direction from) {
+		if (isSet(counterpart)) switch (from) {
+			case EAST:
+				return Map.of(counterpart.connector(),State.UNDEF);
+			default:					
+		}
+		return super.connections(from);
+	}
+	
+	@Override
+	protected Connector connector() {
+		return new Connector(x+1, y, Direction.WEST);
+	}
+}
diff --git a/src/main/java/de/srsoftware/web4rail/tiles/BridgeN.java b/src/main/java/de/srsoftware/web4rail/tiles/BridgeN.java
new file mode 100644
index 0000000..f95ea9f
--- /dev/null
+++ b/src/main/java/de/srsoftware/web4rail/tiles/BridgeN.java
@@ -0,0 +1,30 @@
+package de.srsoftware.web4rail.tiles;
+
+import java.util.List;
+import java.util.Map;
+
+import de.srsoftware.web4rail.Connector;
+import de.srsoftware.web4rail.Plan.Direction;
+import de.srsoftware.web4rail.tiles.Turnout.State;
+
+public class BridgeN extends Bridge {
+	@Override
+	public List<Direction> possibleDirections() {
+		return List.of(Direction.NORTH);
+	}
+	
+	@Override
+	public Map<Connector, State> connections(Direction from) {
+		if (isSet(counterpart)) switch (from) {
+			case NORTH:
+				return Map.of(counterpart.connector(),State.UNDEF);
+			default:					
+		}
+		return super.connections(from);
+	}
+	
+	@Override
+	protected Connector connector() {
+		return new Connector(x, y-1, Direction.SOUTH);
+	}
+}
diff --git a/src/main/java/de/srsoftware/web4rail/tiles/BridgeS.java b/src/main/java/de/srsoftware/web4rail/tiles/BridgeS.java
new file mode 100644
index 0000000..a4803f5
--- /dev/null
+++ b/src/main/java/de/srsoftware/web4rail/tiles/BridgeS.java
@@ -0,0 +1,30 @@
+package de.srsoftware.web4rail.tiles;
+
+import java.util.List;
+import java.util.Map;
+
+import de.srsoftware.web4rail.Connector;
+import de.srsoftware.web4rail.Plan.Direction;
+import de.srsoftware.web4rail.tiles.Turnout.State;
+
+public class BridgeS extends Bridge {
+	@Override
+	public List<Direction> possibleDirections() {
+		return List.of(Direction.SOUTH);
+	}
+	
+	@Override
+	public Map<Connector, State> connections(Direction from) {
+		if (isSet(counterpart)) switch (from) {
+			case SOUTH:
+				return Map.of(counterpart.connector(),State.UNDEF);
+			default:					
+		}
+		return super.connections(from);
+	}
+	
+	@Override
+	protected Connector connector() {
+		return new Connector(x, y+1, Direction.NORTH);
+	}
+}
diff --git a/src/main/java/de/srsoftware/web4rail/tiles/BridgeW.java b/src/main/java/de/srsoftware/web4rail/tiles/BridgeW.java
new file mode 100644
index 0000000..8e95ff9
--- /dev/null
+++ b/src/main/java/de/srsoftware/web4rail/tiles/BridgeW.java
@@ -0,0 +1,31 @@
+package de.srsoftware.web4rail.tiles;
+
+import java.util.List;
+import java.util.Map;
+
+import de.srsoftware.web4rail.Connector;
+import de.srsoftware.web4rail.Plan.Direction;
+import de.srsoftware.web4rail.tiles.Turnout.State;
+
+public class BridgeW extends Bridge {
+	@Override
+	public List<Direction> possibleDirections() {
+		return List.of(Direction.WEST);
+	}
+
+	@Override
+	public Map<Connector, State> connections(Direction from) {
+		if (isSet(counterpart))
+			switch (from) {
+			case WEST:
+				return Map.of(counterpart.connector(), State.UNDEF);
+			default:
+		}
+		return super.connections(from);
+	}
+
+	@Override
+	protected Connector connector() {
+		return new Connector(x - 1, y, Direction.EAST);
+	}
+}