Browse Source

refactored tiles data structure in plan

lookup-tables
Stephan Richter 5 years ago
parent
commit
67623f49bc
  1. 2
      pom.xml
  2. 11
      resources/js/plan.js
  3. 104
      src/main/java/de/srsoftware/web4rail/Plan.java
  4. 34
      src/main/java/de/srsoftware/web4rail/Route.java
  5. 19
      src/main/java/de/srsoftware/web4rail/tiles/Tile.java

2
pom.xml

@ -4,7 +4,7 @@
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<groupId>de.srsoftware</groupId> <groupId>de.srsoftware</groupId>
<artifactId>web4rail</artifactId> <artifactId>web4rail</artifactId>
<version>0.3.5</version> <version>0.3.6</version>
<name>Web4Rail</name> <name>Web4Rail</name>
<description>Java Model Railway Control</description> <description>Java Model Railway Control</description>
<url>https://github.com/StephanRichter/Web4Rail</url> <url>https://github.com/StephanRichter/Web4Rail</url>

11
resources/js/plan.js

@ -24,8 +24,9 @@ function addTile(x,y){
} }
function clickTile(x,y){ function clickTile(x,y){
console.log("clickTile:",x,y); var id = x+"-"+y;
if ($('#tile-'+x+'-'+y).length > 0) request({action:'click',x:x,y:y}); console.log("clickTile:",id);
if ($('#'+id).length > 0) request({action:'click',id:id});
return false; return false;
} }
@ -84,8 +85,9 @@ function heartbeat(data){
} }
function moveTile(x,y){ function moveTile(x,y){
console.log("moveTile:",selected.id,x,y); var id = x+"-"+y;
return request({action:mode,direction:selected.id,x:x,y:y}); console.log("moveTile:",selected.id,id);
return request({action:mode,direction:selected.id,id:id});
} }
function openRoute(id){ function openRoute(id){
@ -153,6 +155,7 @@ function train(id,mode){
function stream(ev){ function stream(ev){
var data = ev.data; var data = ev.data;
console.log("received: ",data);
if (data.startsWith("heartbeat")) return heartbeat(data); if (data.startsWith("heartbeat")) return heartbeat(data);
if (data.startsWith("place ")) return place(data.substring(6)); if (data.startsWith("place ")) return place(data.substring(6));
if (data.startsWith("remove")) return remove(data.substring(7)); if (data.startsWith("remove")) return remove(data.substring(7));

104
src/main/java/de/srsoftware/web4rail/Plan.java

@ -106,7 +106,7 @@ public class Plan {
private static final HashMap<OutputStreamWriter,Integer> clients = new HashMap<OutputStreamWriter, Integer>(); private static final HashMap<OutputStreamWriter,Integer> clients = new HashMap<OutputStreamWriter, Integer>();
private static final String ACTION_TRAIN = "train"; private static final String ACTION_TRAIN = "train";
public HashMap<Integer,HashMap<Integer,Tile>> tiles = new HashMap<Integer,HashMap<Integer,Tile>>(); public HashMap<String,Tile> tiles = new HashMap<String,Tile>();
private HashSet<Block> blocks = new HashSet<Block>(); private HashSet<Block> blocks = new HashSet<Block>();
private HashMap<String, Route> routes = new HashMap<String, Route>(); private HashMap<String, Route> routes = new HashMap<String, Route>();
@ -139,7 +139,7 @@ public class Plan {
clazz = tc.getName().replace(".Tile", "."+clazz); clazz = tc.getName().replace(".Tile", "."+clazz);
Tile tile = (Tile) tc.getClassLoader().loadClass(clazz).getDeclaredConstructor().newInstance(); Tile tile = (Tile) tc.getClassLoader().loadClass(clazz).getDeclaredConstructor().newInstance();
if (tile instanceof Eraser) { if (tile instanceof Eraser) {
Tile erased = get(x,y,true); Tile erased = get(Tile.id(x,y),true);
remove(erased); remove(erased);
return erased == null ? null : t("Removed {}.",erased); return erased == null ? null : t("Removed {}.",erased);
} }
@ -154,9 +154,7 @@ public class Plan {
for (Connector con : block.startPoints()) routes.addAll(follow(new Route().start(block,con.from.inverse()),con)); for (Connector con : block.startPoints()) routes.addAll(follow(new Route().start(block,con.from.inverse()),con));
} }
this.routes.clear(); this.routes.clear();
for (HashMap<Integer, Tile> column: tiles.values()) { for (Tile tile : tiles.values()) tile.routes().clear();
for (Tile tile : column.values()) tile.routes().clear();
}
for (Route route : routes) { for (Route route : routes) {
route.complete(); route.complete();
registerRoute(route); registerRoute(route);
@ -174,7 +172,7 @@ public class Plan {
} }
private Collection<Route> follow(Route route, Connector connector) { private Collection<Route> follow(Route route, Connector connector) {
Tile tile = get(connector.x,connector.y,false); Tile tile = get(Tile.id(connector.x,connector.y),false);
Vector<Route> results = new Vector<>(); Vector<Route> results = new Vector<>();
if (tile == null) return results; if (tile == null) return results;
Tile addedTile = route.add(tile,connector.from); Tile addedTile = route.add(tile,connector.from);
@ -183,7 +181,7 @@ public class Plan {
LOG.debug("Found {}, coming from {}.",addedTile,connector.from); LOG.debug("Found {}, coming from {}.",addedTile,connector.from);
for (Connector con : cons.keySet()) { // falls direkt nach dem Block noch ein Kontakt kommt: diesen mit zu Route hinzufügen for (Connector con : cons.keySet()) { // falls direkt nach dem Block noch ein Kontakt kommt: diesen mit zu Route hinzufügen
LOG.debug("This is connected to {}",con); LOG.debug("This is connected to {}",con);
Tile nextTile = get(con.x,con.y,false); Tile nextTile = get(Tile.id(con.x,con.y),false);
if (nextTile instanceof Contact) { if (nextTile instanceof Contact) {
LOG.debug("{} is followed by {}",addedTile,nextTile); LOG.debug("{} is followed by {}",addedTile,nextTile);
route.add(nextTile, con.from); route.add(nextTile, con.from);
@ -208,13 +206,8 @@ public class Plan {
return results; return results;
} }
private Tile get(String x, String y,boolean resolveShadows) { public Tile get(String tileId,boolean resolveShadows) {
return get(Integer.parseInt(x),Integer.parseInt(y),resolveShadows); Tile tile = tiles.get(tileId);
}
public Tile get(int x, int y,boolean resolveShadows) {
HashMap<Integer, Tile> column = tiles.get(x);
Tile tile = (column == null) ? null : column.get(y);
if (resolveShadows && tile instanceof Shadow) tile = ((Shadow)tile).overlay(); if (resolveShadows && tile instanceof Shadow) tile = ((Shadow)tile).overlay();
return tile; return tile;
} }
@ -229,14 +222,9 @@ public class Plan {
public Page html() throws IOException { public Page html() throws IOException {
Page page = new Page().append("<div id=\"plan\">"); Page page = new Page().append("<div id=\"plan\">");
for (Entry<Integer, HashMap<Integer, Tile>> column : tiles.entrySet()) { for (Tile tile: tiles.values()) {
int x = column.getKey(); if (tile == null) continue;
for (Entry<Integer, Tile> row : column.getValue().entrySet()) { page.append("\t\t"+tile.tag(null)+"\n");
int y = row.getKey();
Tile tile = row.getValue().position(x, y);
if (tile == null) continue;
page.append("\t\t"+tile.tag(null)+"\n");
}
} }
return page return page
.append(menu()) .append(menu())
@ -281,54 +269,54 @@ public class Plan {
return new Tag("div").clazz("list").content(tiles.toString()).addTo(tileMenu); return new Tag("div").clazz("list").content(tiles.toString()).addTo(tileMenu);
} }
private String moveTile(String direction, String x, String y) throws NumberFormatException, IOException { private String moveTile(String direction, String tileId) throws NumberFormatException, IOException {
switch (direction) { switch (direction) {
case "south": case "south":
return moveTile(Direction.SOUTH,Integer.parseInt(x),Integer.parseInt(y)); return moveTile(get(tileId,false),Direction.SOUTH);
case "north": case "north":
return moveTile(Direction.NORTH,Integer.parseInt(x),Integer.parseInt(y)); return moveTile(get(tileId,false),Direction.NORTH);
case "east": case "east":
return moveTile(Direction.EAST,Integer.parseInt(x),Integer.parseInt(y)); return moveTile(get(tileId,false),Direction.EAST);
case "west": case "west":
return moveTile(Direction.WEST,Integer.parseInt(x),Integer.parseInt(y)); return moveTile(get(tileId,false),Direction.WEST);
} }
throw new InvalidParameterException(t("\"{}\" is not a known direction!")); throw new InvalidParameterException(t("\"{}\" is not a known direction!"));
} }
private String moveTile(Direction direction, int x, int y) throws IOException { private String moveTile(Tile tile, Direction direction) throws IOException {
//LOG.debug("moveTile({},{},{})",direction,x,y);
boolean moved = false; boolean moved = false;
switch (direction) { if (tile != null) {
case EAST: LOG.debug("moveTile({},{},{})",direction,tile.x,tile.y);
moved = moveTile(x,y,+1,0); switch (direction) {
break; case EAST:
case WEST: moved = moveTile(tile,+1,0);
moved = moveTile(x,y,-1,0); break;
break; case WEST:
case NORTH: moved = moveTile(tile,-1,0);
moved = moveTile(x,y,0,-1); break;
break; case NORTH:
case SOUTH: moved = moveTile(tile,0,-1);
moved = moveTile(x,y,0,+1); break;
break; case SOUTH:
moved = moveTile(tile,0,+1);
break;
}
} }
return t(moved ? "Tile(s) moved.":"No tile(s) moved."); return t(moved ? "Tile(s) moved.":"No tile(s) moved.");
} }
private boolean moveTile(int x, int y,int xstep,int ystep) throws IOException { private boolean moveTile(Tile tile,int xstep,int ystep) throws IOException {
LOG.error("moveTile({}+ {},{}+ {})",x,xstep,y,ystep); LOG.error("moveTile({} +{}/+{})",tile,xstep,ystep);
Stack<Tile> stack = new Stack<Tile>(); Stack<Tile> stack = new Stack<Tile>();
Tile tile = get(x,y,false);
while (tile != null) { while (tile != null) {
LOG.debug("scheduling tile for movement: {} @ {},{}",tile,x,y); LOG.debug("scheduling tile for movement: {}",tile);
stack.add(tile); stack.add(tile);
x+=xstep; tile = get(Tile.id(tile.x+xstep, tile.y+ystep),false);
y+=ystep;
tile = get(x,y,false);
} }
while (!stack.isEmpty()) { while (!stack.isEmpty()) {
tile = stack.pop(); tile = stack.pop();
if (!(tile instanceof Shadow)) { if (!(tile instanceof Shadow)) {
LOG.debug("altering position of {}",tile);
remove(tile); remove(tile);
set(tile.x+xstep,tile.y+ystep,tile); set(tile.x+xstep,tile.y+ystep,tile);
} }
@ -349,11 +337,11 @@ public class Plan {
case ACTION_ADD: case ACTION_ADD:
return addTile(params.get(TILE),params.get(X),params.get(Y),null); return addTile(params.get(TILE),params.get(X),params.get(Y),null);
case ACTION_CLICK: case ACTION_CLICK:
return click(get(params.get(X),params.get(Y),true)); return click(get(params.get(Tile.ID),true));
case ACTION_ANALYZE: case ACTION_ANALYZE:
return analyze(); return analyze();
case ACTION_MOVE: case ACTION_MOVE:
return moveTile(params.get(DIRECTION),params.get(X),params.get(Y)); return moveTile(params.get(DIRECTION),params.get(Tile.ID));
case ACTION_ROUTE: case ACTION_ROUTE:
return routeProperties(params.get(ID)); return routeProperties(params.get(ID));
case ACTION_SAVE: case ACTION_SAVE:
@ -395,12 +383,11 @@ public class Plan {
if (tile instanceof Block) blocks.remove(tile); if (tile instanceof Block) blocks.remove(tile);
for (int i=1; i<tile.len(); i++) remove_intern(tile.x+i, tile.y); // remove shadow tiles for (int i=1; i<tile.len(); i++) remove_intern(tile.x+i, tile.y); // remove shadow tiles
for (int i=1; i<tile.height(); i++) remove_intern(tile.x, tile.y+i); // remove shadow tiles for (int i=1; i<tile.height(); i++) remove_intern(tile.x, tile.y+i); // remove shadow tiles
if (tile != null) stream("remove tile-"+tile.x+"-"+tile.y); if (tile != null) stream("remove "+tile.id());
} }
private void remove_intern(int x, int y) { private void remove_intern(int x, int y) {
HashMap<Integer, Tile> column = tiles.get(x); LOG.debug("removed {} from tile list",tiles.remove(Tile.id(x, y)));
if (column != null) column.remove(y);
} }
private String saveTo(String name) throws IOException { private String saveTo(String name) throws IOException {
@ -422,13 +409,8 @@ public class Plan {
} }
private void set_intern(int x, int y, Tile tile) { private void set_intern(int x, int y, Tile tile) {
HashMap<Integer, Tile> column = tiles.get(x);
if (column == null) {
column = new HashMap<Integer, Tile>();
tiles.put(x,column);
}
tile.position(x, y).plan(this); tile.position(x, y).plan(this);
column.put(y,tile); tiles.put(tile.id(),tile);
} }
public synchronized void stream(String data) { public synchronized void stream(String data) {
@ -510,7 +492,7 @@ public class Plan {
} }
private void update(int x,int y, HashMap<String, String> params) throws IOException { private void update(int x,int y, HashMap<String, String> params) throws IOException {
Tile tile = get(x,y,true); Tile tile = get(Tile.id(x, y),true);
if (tile != null) set(x,y,tile.update(params)); if (tile != null) set(x,y,tile.update(params));
} }

34
src/main/java/de/srsoftware/web4rail/Route.java

@ -1,6 +1,8 @@
package de.srsoftware.web4rail; package de.srsoftware.web4rail;
import java.io.BufferedReader;
import java.io.BufferedWriter; import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter; import java.io.FileWriter;
import java.io.IOException; import java.io.IOException;
import java.util.HashMap; import java.util.HashMap;
@ -35,7 +37,6 @@ import de.srsoftware.web4rail.tiles.Turnout.State;
public class Route { public class Route {
private static final Logger LOG = LoggerFactory.getLogger(Route.class); private static final Logger LOG = LoggerFactory.getLogger(Route.class);
static final String NAME = "name"; static final String NAME = "name";
private static final HashMap<String,String> names = new HashMap<String, String>();
static final String PATH = "path"; static final String PATH = "path";
static final String SIGNALS = "signals"; static final String SIGNALS = "signals";
static final String TURNOUTS = "turnouts"; static final String TURNOUTS = "turnouts";
@ -45,6 +46,7 @@ public class Route {
private HashMap<Turnout,Turnout.State> turnouts; private HashMap<Turnout,Turnout.State> turnouts;
private HashMap<Object,Vector<Action>> triggers = new HashMap<Object, Vector<Action>>(); private HashMap<Object,Vector<Action>> triggers = new HashMap<Object, Vector<Action>>();
private String id; private String id;
private String name;
public Train train; public Train train;
private Block startBlock = null,endBlock; private Block startBlock = null,endBlock;
public Direction startDirection; public Direction startDirection;
@ -190,16 +192,31 @@ public class Route {
} }
props.put(TURNOUTS, turnouts); props.put(TURNOUTS, turnouts);
if (names.containsKey(id())) props.put(NAME, names.get(id)); if (name != null) props.put(NAME, name);
return props.toString(); return props.toString();
} }
public static void loadAll(String string, Plan plan) { private Route load(JSONObject json,Plan plan) {
// TODO Auto-generated method stub JSONArray pathIds = json.getJSONArray(PATH);
for (Object tileId : pathIds) {
plan.get((String) tileId,false);
}
return this;
} }
public static void loadAll(String filename, Plan plan) throws IOException {
BufferedReader file = new BufferedReader(new FileReader(filename));
String line = file.readLine();
while (line != null) {
JSONObject json = new JSONObject(line);
new Route().load(json,plan);
line = file.readLine();
}
file.close();
}
public Route lock(Train train) throws IOException { public Route lock(Train train) throws IOException {
this.train = train; this.train = train;
for (Entry<Turnout, State> entry : turnouts.entrySet()) { for (Entry<Turnout, State> entry : turnouts.entrySet()) {
@ -216,14 +233,11 @@ public class Route {
} }
public String name() { public String name() {
String name = names.get(id());
return name == null ? id() : name; return name == null ? id() : name;
} }
public void name(String name) { public void name(String name) {
if (name.isEmpty()) { this.name = name;
names.remove(id());
} else names.put(id(),name);
} }
public Vector<Tile> path() { public Vector<Tile> path() {

19
src/main/java/de/srsoftware/web4rail/tiles/Tile.java

@ -96,7 +96,11 @@ public abstract class Tile {
} }
public String id() { public String id() {
return x+":"+y; return Tile.id(x, y);
}
public static String id(int x, int y) {
return x+"-"+y;
} }
private static void inflate(String clazz, JSONObject json, Plan plan) throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException, ClassNotFoundException, IOException { private static void inflate(String clazz, JSONObject json, Plan plan) throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException, ClassNotFoundException, IOException {
@ -237,14 +241,11 @@ public abstract class Tile {
return routes; return routes;
} }
public static void saveAll(HashMap<Integer, HashMap<Integer, Tile>> tiles ,String filename) throws IOException { public static void saveAll(HashMap<String, Tile> tiles ,String filename) throws IOException {
BufferedWriter file = new BufferedWriter(new FileWriter(filename)); BufferedWriter file = new BufferedWriter(new FileWriter(filename));
for (Entry<Integer, HashMap<Integer, Tile>> column : tiles.entrySet()) { for (Tile tile : tiles.values()) {
for (Entry<Integer, Tile> row : column.getValue().entrySet()) { if (tile == null || tile instanceof Shadow) continue;
Tile tile = row.getValue(); file.append(tile.json()+"\n");
if (tile == null || tile instanceof Shadow) continue;
file.append(tile.json()+"\n");
}
} }
file.close(); file.close();
} }
@ -261,7 +262,7 @@ public abstract class Tile {
replacements.put("%height%",height); replacements.put("%height%",height);
String style = ""; String style = "";
Tag svg = new Tag("svg") Tag svg = new Tag("svg")
.id((x!=-1 && y!=-1)?("tile-"+x+"-"+y):(getClass().getSimpleName())) .id((x!=-1 && y!=-1)?(id()):(getClass().getSimpleName()))
.clazz(classes()) .clazz(classes())
.size(100,100) .size(100,100)
.attr("name", getClass().getSimpleName()) .attr("name", getClass().getSimpleName())

Loading…
Cancel
Save