moved Thrads to separate package

This commit is contained in:
Stephan Richter
2021-02-28 18:00:34 +01:00
parent dc378b107b
commit c549f7364d
26 changed files with 260 additions and 229 deletions

View File

@@ -39,7 +39,7 @@ import de.srsoftware.web4rail.tiles.Tile;
* @author Stephan Richter, SRSoftware 2020…2021
*/
public abstract class BaseClass implements Constants{
protected static Plan plan; // the track layout in use
public static Plan plan; // the track layout in use
public static final Random random = new Random();
public static String speedUnit = DEFAULT_SPEED_UNIT;
public static String lengthUnit = DEFAULT_LENGTH_UNIT;
@@ -511,7 +511,7 @@ public abstract class BaseClass implements Constants{
}
protected static String t(String txt, Object...fills) {
public static String t(String txt, Object...fills) {
if (isSet(fills)) for (int i=0; i<fills.length; i++) {
if ("\\".equals(fills[i])) fills[i]="\\\\";
}

View File

@@ -36,6 +36,8 @@ import de.srsoftware.web4rail.tags.Input;
import de.srsoftware.web4rail.tags.Label;
import de.srsoftware.web4rail.tags.Table;
import de.srsoftware.web4rail.tags.Window;
import de.srsoftware.web4rail.threads.BrakeProcessor;
import de.srsoftware.web4rail.threads.ControlUnit;
import de.srsoftware.web4rail.tiles.Block;
import de.srsoftware.web4rail.tiles.BlockContact;
import de.srsoftware.web4rail.tiles.BlockH;
@@ -355,7 +357,7 @@ public class Plan extends BaseClass{
new Input(ACTION,ACTION_UPDATE).hideIn(form);
new Input(LENGTH_UNIT, lengthUnit).addTo(new Label(t("Length unit")+COL)).addTo(form);
new Input(SPEED_UNIT, speedUnit).addTo(new Label(t("Speed unit")+COL)).addTo(form);
new Input(FINAL_SPEED, Route.defaultEndSpeed).addTo(new Label(t("Lower speed limit")+COL)).attr("title", t("Final speed after breaking, before halting")).addTo(form);
new Input(FINAL_SPEED, BrakeProcessor.defaultEndSpeed).addTo(new Label(t("Lower speed limit")+COL)).attr("title", t("Final speed after breaking, before halting")).addTo(form);
new Checkbox(FREE_BEHIND_TRAIN, t("Free tiles behind train"), Route.freeBehindTrain).attr("title", t("If checked, tiles behind the train are freed according to the length of the train and the tiles. If it is unchecked, tiles will not get free before route is finished.")).addTo(form);
new Button(t("Save"), form).addTo(form);
form.addTo(fieldset);
@@ -489,7 +491,7 @@ public class Plan extends BaseClass{
.forEach(jTiles::put);
return new JSONObject()
.put(FINAL_SPEED, Route.defaultEndSpeed)
.put(FINAL_SPEED, BrakeProcessor.defaultEndSpeed)
.put(FREE_BEHIND_TRAIN, Route.freeBehindTrain)
.put(LENGTH_UNIT, lengthUnit)
.put(SPEED_UNIT, speedUnit)
@@ -523,7 +525,7 @@ public class Plan extends BaseClass{
if (json.has(TILE)) json.getJSONArray(TILE).forEach(object -> Tile.load(object, plan));
if (json.has(LENGTH_UNIT)) lengthUnit = json.getString(LENGTH_UNIT);
if (json.has(SPEED_UNIT)) speedUnit = json.getString(SPEED_UNIT);
if (json.has(FINAL_SPEED)) Route.defaultEndSpeed = json.getInt(FINAL_SPEED);
if (json.has(FINAL_SPEED)) BrakeProcessor.defaultEndSpeed = json.getInt(FINAL_SPEED);
if (json.has(FREE_BEHIND_TRAIN)) Route.freeBehindTrain = json.getBoolean(FREE_BEHIND_TRAIN);
try {
@@ -982,7 +984,7 @@ public class Plan extends BaseClass{
if (params.containsKey(LENGTH_UNIT)) lengthUnit = params.get(LENGTH_UNIT);
if (params.containsKey(SPEED_UNIT)) speedUnit = params.get(SPEED_UNIT);
if (params.containsKey(FINAL_SPEED)) Route.defaultEndSpeed = Integer.parseInt(params.get(FINAL_SPEED));
if (params.containsKey(FINAL_SPEED)) BrakeProcessor.defaultEndSpeed = Integer.parseInt(params.get(FINAL_SPEED));
Route.freeBehindTrain = "on".equalsIgnoreCase(params.get(FREE_BEHIND_TRAIN));
return t("Plan updated.");

View File

@@ -18,7 +18,6 @@ import org.json.JSONTokener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import de.keawe.tools.translations.Translation;
import de.srsoftware.tools.Tag;
import de.srsoftware.web4rail.Plan.Direction;
import de.srsoftware.web4rail.actions.Action;
@@ -38,6 +37,7 @@ import de.srsoftware.web4rail.tags.Fieldset;
import de.srsoftware.web4rail.tags.Input;
import de.srsoftware.web4rail.tags.Table;
import de.srsoftware.web4rail.tags.Window;
import de.srsoftware.web4rail.threads.BrakeProcessor;
import de.srsoftware.web4rail.tiles.Block;
import de.srsoftware.web4rail.tiles.BlockContact;
import de.srsoftware.web4rail.tiles.Contact;
@@ -71,7 +71,6 @@ public class Route extends BaseClass {
static final String SIGNALS = "signals";
static final String TURNOUTS = "turnouts";
private State state = State.FREE;
public static int defaultEndSpeed = 10;
public static boolean freeBehindTrain = true;
private static final String ROUTE_START = "route_start";
@@ -79,138 +78,6 @@ public class Route extends BaseClass {
private static final String ROUTE_SETUP = "route_setup";
private static HashMap<Id, String> names = new HashMap<Id, String>(); // maps id to name. needed to keep names during plan.analyze()
private class BrakeProcessor extends Thread {
private long latestTick;
private static final int SPEED_STEP = 5;
private Integer timeStep;
private Route route;
private Train train;
private String brakeId;
private long estimatedDistance; // Unit: s*km/h "km/h-Sekunden"
private int startSpeed,endSpeed;
private boolean aborted,modified,finished;
public BrakeProcessor(Route route, Train train) {
this.train = train;
this.route = route;
aborted = false;
modified = false;
finished = false;
brakeId = train.brakeId();
startSpeed = train.speed;
endSpeed = defaultEndSpeed;
timeStep = brakeTimes.get(brakeId);
if (isNull(timeStep) || timeStep>1000000) timeStep = 256; // if no brake time is available for this train
setName(Application.threadName("BrakeProcessor("+train+")"));
start();
}
protected void abort() {
aborted = true;
}
private long calcDistance(Integer ts) {
long dist = 0;
int s = startSpeed;
while (s > defaultEndSpeed) {
s -= SPEED_STEP;
dist += s*ts;
}
LOG.debug("Estimated distamce with {} ms timestep: {}",ts,dist);
return dist;
}
private void checkNextRoute() {
Route nextRoute = train.nextRoute();
if (isSet(nextRoute) && nextRoute.state == Route.State.PREPARED) { // auf Startgeschwindigkeit der Nachfolgeroute bremsen
Integer nextRouteStartSpeed = nextRoute.startSpeed();
if (isSet(nextRouteStartSpeed)) {
LOG.debug("updating target velocity from {} to {}!",endSpeed,nextRouteStartSpeed);
endSpeed = nextRouteStartSpeed;
modified = true;
if (endSpeed > train.speed) train.setSpeed(endSpeed);
}
}
}
/**
* This is called from route.finish when train came to stop
*/
public void finish() {
LOG.debug("BrakeProcessor.finish()");
finished = true;
if (aborted || modified) return;
increaseDistance();
train.setSpeed(0);
LOG.debug("Estimated distance: {}",estimatedDistance);
if (startSpeed <= endSpeed) return;
if (timeStep<0) timeStep = 100;
Integer newTimeStep = timeStep;
long calculated;
int step = 32*newTimeStep;
for (int i=0; i<20; i++) {
step = step/2;
if (step<1) step = 1;
calculated = calcDistance(newTimeStep);
LOG.debug("Calculated distance for step = {} ms: {}",newTimeStep,calculated);
LOG.debug("Update step: {}",step);
newTimeStep = newTimeStep + (calculated > estimatedDistance ? -step : step);
}
if (!newTimeStep.equals(timeStep)) {
route.brakeTimes.put(brakeId,newTimeStep);
calculated = calcDistance(newTimeStep);
LOG.debug("Corrected brake timestep for {} @ {} from {} to {} ms.",train,route,timeStep,newTimeStep);
LOG.debug("Differemce from estimated distance: {} ({}%)",estimatedDistance-calculated,100*(estimatedDistance-calculated)/(float)estimatedDistance);
}
}
private void increaseDistance(){
long tick = timestamp();
estimatedDistance += train.speed * (3+tick-latestTick);
latestTick = tick;
}
@Override
public void run() {
setName(Application.threadName("BreakeProcessor("+train+")"));
LOG.debug("started BrakeProcessor ({} → {}) for {} with timestep = {} ms.",train.speed,endSpeed,train,timeStep);
estimatedDistance = 0;
latestTick = timestamp();
while (train.speed > endSpeed) {
if (finished || aborted) return;
increaseDistance();
LOG.debug("BrakeProcessor({}) setting Speed of {}.",route,train);
train.setSpeed(Math.max(train.speed - SPEED_STEP,endSpeed));
if (!modified) checkNextRoute();
try {
sleep(timeStep);
} catch (InterruptedException e) {
LOG.warn("BrakeProcessor interrupted!", e);
}
}
while (!finished && !aborted && !modified) {
try {
sleep(1000);
} catch (InterruptedException e) {
LOG.warn("BrakeProcessor interrupted!", e);
}
checkNextRoute();
}
}
public void setEndSpeed(Integer newEndSpeed) {
if (isNull(newEndSpeed)) return;
endSpeed = newEndSpeed;
modified = true;
}
}
private BrakeProcessor brakeProcessor = null;
private HashMap<String,Integer> brakeTimes = new HashMap<String, Integer>();
@@ -367,6 +234,14 @@ public class Route extends BaseClass {
return fieldset;
}
public Integer brakeTime(String brakeId) {
return brakeTimes.get(brakeId);
}
public void brakeTime(String brakeId, Integer newTimeStep) {
brakeTimes.put(brakeId,newTimeStep);
}
private Fieldset brakeTimes() {
Fieldset fieldset = new Fieldset(t("Brake time table"));
Table table = new Table();
@@ -1066,11 +941,6 @@ public class Route extends BaseClass {
return isSet(startActions) ? startActions.getSpeed(context) : null;
}
protected static String t(String txt, Object...fills) {
return Translation.get(Application.class, txt, fills);
}
@Override
public String toString() {
return getClass().getSimpleName()+"("+(isSet(train)?train+":":"")+name()+")";
@@ -1136,8 +1006,4 @@ public class Route extends BaseClass {
super.update(params);
return properties();
}
public Integer brakeTime(String brakeId) {
return brakeTimes.get(brakeId);
}
}

View File

@@ -10,9 +10,7 @@ import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import de.keawe.tools.translations.Translation;
import de.srsoftware.tools.Tag;
import de.srsoftware.web4rail.Application;
import de.srsoftware.web4rail.BaseClass;
import de.srsoftware.web4rail.tags.Button;
import de.srsoftware.web4rail.tags.Fieldset;
@@ -159,10 +157,6 @@ public abstract class Action extends BaseClass {
return select.addTo(new Label(t("Action type")+COL));
}
protected static String t(String tex,Object...fills) {
return Translation.get(Application.class, tex, fills);
}
@Override
public String toString() {
return t(getClass().getSimpleName());

View File

@@ -9,11 +9,11 @@ import org.json.JSONObject;
import de.srsoftware.tools.Tag;
import de.srsoftware.web4rail.BaseClass;
import de.srsoftware.web4rail.DelayedExecution;
import de.srsoftware.web4rail.moving.Train;
import de.srsoftware.web4rail.tags.Checkbox;
import de.srsoftware.web4rail.tags.Fieldset;
import de.srsoftware.web4rail.tags.Window;
import de.srsoftware.web4rail.threads.DelayedExecution;
import de.srsoftware.web4rail.tiles.Block;
import de.srsoftware.web4rail.tiles.Tile;

View File

@@ -7,10 +7,10 @@ import org.json.JSONObject;
import de.srsoftware.tools.Tag;
import de.srsoftware.web4rail.BaseClass;
import de.srsoftware.web4rail.DelayedExecution;
import de.srsoftware.web4rail.tags.Fieldset;
import de.srsoftware.web4rail.tags.Input;
import de.srsoftware.web4rail.tags.Window;
import de.srsoftware.web4rail.threads.DelayedExecution;
public class DelayedAction extends ActionList {

View File

@@ -7,9 +7,9 @@ import java.util.Map;
import org.json.JSONObject;
import de.srsoftware.web4rail.BaseClass;
import de.srsoftware.web4rail.DelayedExecution;
import de.srsoftware.web4rail.tags.Fieldset;
import de.srsoftware.web4rail.tags.Window;
import de.srsoftware.web4rail.threads.DelayedExecution;
import de.srsoftware.web4rail.tiles.Block;
import de.srsoftware.web4rail.tiles.Tile;

View File

@@ -8,10 +8,10 @@ import org.json.JSONObject;
import de.srsoftware.tools.Tag;
import de.srsoftware.web4rail.BaseClass;
import de.srsoftware.web4rail.DelayedExecution;
import de.srsoftware.web4rail.tags.Fieldset;
import de.srsoftware.web4rail.tags.Radio;
import de.srsoftware.web4rail.tags.Window;
import de.srsoftware.web4rail.threads.DelayedExecution;
import de.srsoftware.web4rail.tiles.Block;
import de.srsoftware.web4rail.tiles.Shadow;
import de.srsoftware.web4rail.tiles.Tile;

View File

@@ -7,9 +7,9 @@ import java.util.Map;
import org.json.JSONObject;
import de.srsoftware.web4rail.BaseClass;
import de.srsoftware.web4rail.DelayedExecution;
import de.srsoftware.web4rail.tags.Fieldset;
import de.srsoftware.web4rail.tags.Window;
import de.srsoftware.web4rail.threads.DelayedExecution;
import de.srsoftware.web4rail.tiles.Decoupler;
import de.srsoftware.web4rail.tiles.Tile;

View File

@@ -6,10 +6,10 @@ import java.util.List;
import org.json.JSONObject;
import de.srsoftware.web4rail.BaseClass;
import de.srsoftware.web4rail.DelayedExecution;
import de.srsoftware.web4rail.moving.Train;
import de.srsoftware.web4rail.tags.Fieldset;
import de.srsoftware.web4rail.tags.Window;
import de.srsoftware.web4rail.threads.DelayedExecution;
public class SetContextTrain extends Action {

View File

@@ -7,10 +7,10 @@ import java.util.Map;
import org.json.JSONObject;
import de.srsoftware.web4rail.BaseClass;
import de.srsoftware.web4rail.DelayedExecution;
import de.srsoftware.web4rail.tags.Fieldset;
import de.srsoftware.web4rail.tags.Label;
import de.srsoftware.web4rail.tags.Window;
import de.srsoftware.web4rail.threads.DelayedExecution;
import de.srsoftware.web4rail.tiles.TextDisplay;
import de.srsoftware.web4rail.tiles.Tile;

View File

@@ -7,10 +7,10 @@ import org.json.JSONObject;
import de.srsoftware.tools.Tag;
import de.srsoftware.web4rail.BaseClass;
import de.srsoftware.web4rail.ControlUnit;
import de.srsoftware.web4rail.tags.Fieldset;
import de.srsoftware.web4rail.tags.Radio;
import de.srsoftware.web4rail.tags.Window;
import de.srsoftware.web4rail.threads.ControlUnit;
public class SetPower extends Action{

View File

@@ -8,10 +8,10 @@ import org.json.JSONObject;
import de.srsoftware.tools.Tag;
import de.srsoftware.web4rail.BaseClass;
import de.srsoftware.web4rail.DelayedExecution;
import de.srsoftware.web4rail.tags.Fieldset;
import de.srsoftware.web4rail.tags.Select;
import de.srsoftware.web4rail.tags.Window;
import de.srsoftware.web4rail.threads.DelayedExecution;
import de.srsoftware.web4rail.tiles.Relay;
import de.srsoftware.web4rail.tiles.Switch;
import de.srsoftware.web4rail.tiles.Tile;

View File

@@ -8,10 +8,10 @@ import org.json.JSONObject;
import de.srsoftware.tools.Tag;
import de.srsoftware.web4rail.BaseClass;
import de.srsoftware.web4rail.DelayedExecution;
import de.srsoftware.web4rail.tags.Fieldset;
import de.srsoftware.web4rail.tags.Select;
import de.srsoftware.web4rail.tags.Window;
import de.srsoftware.web4rail.threads.DelayedExecution;
import de.srsoftware.web4rail.tiles.Turnout;
import de.srsoftware.web4rail.tiles.Turnout.State;

View File

@@ -8,10 +8,10 @@ import org.json.JSONObject;
import de.srsoftware.tools.Tag;
import de.srsoftware.web4rail.BaseClass;
import de.srsoftware.web4rail.DelayedExecution;
import de.srsoftware.web4rail.tags.Fieldset;
import de.srsoftware.web4rail.tags.Input;
import de.srsoftware.web4rail.tags.Window;
import de.srsoftware.web4rail.threads.DelayedExecution;
import de.srsoftware.web4rail.tiles.Contact;
import de.srsoftware.web4rail.tiles.Contact.Listener;
import de.srsoftware.web4rail.tiles.Tile;

View File

@@ -7,9 +7,9 @@ import java.util.Map;
import org.json.JSONObject;
import de.srsoftware.web4rail.BaseClass;
import de.srsoftware.web4rail.DelayedExecution;
import de.srsoftware.web4rail.tags.Fieldset;
import de.srsoftware.web4rail.tags.Window;
import de.srsoftware.web4rail.threads.DelayedExecution;
import de.srsoftware.web4rail.tiles.Block;
import de.srsoftware.web4rail.tiles.Tile;

View File

@@ -7,10 +7,10 @@ import java.util.Map;
import org.json.JSONObject;
import de.srsoftware.web4rail.BaseClass;
import de.srsoftware.web4rail.DelayedExecution;
import de.srsoftware.web4rail.Route;
import de.srsoftware.web4rail.tags.Fieldset;
import de.srsoftware.web4rail.tags.Window;
import de.srsoftware.web4rail.threads.DelayedExecution;
import de.srsoftware.web4rail.tiles.Block;
import de.srsoftware.web4rail.tiles.Tile;

View File

@@ -8,10 +8,10 @@ import org.json.JSONObject;
import de.srsoftware.tools.Tag;
import de.srsoftware.web4rail.BaseClass;
import de.srsoftware.web4rail.DelayedExecution;
import de.srsoftware.web4rail.tags.Fieldset;
import de.srsoftware.web4rail.tags.Radio;
import de.srsoftware.web4rail.tags.Window;
import de.srsoftware.web4rail.threads.DelayedExecution;
import de.srsoftware.web4rail.tiles.Switch;
import de.srsoftware.web4rail.tiles.Tile;

View File

@@ -18,9 +18,7 @@ import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import de.keawe.tools.translations.Translation;
import de.srsoftware.tools.Tag;
import de.srsoftware.web4rail.Application;
import de.srsoftware.web4rail.BaseClass;
import de.srsoftware.web4rail.Plan;
import de.srsoftware.web4rail.tags.Button;
@@ -273,10 +271,6 @@ public class Car extends BaseClass implements Comparable<Car>{
file.close();
}
protected static String t(String txt, Object...fills) {
return Translation.get(Application.class, txt, fills);
}
public TreeSet<String> tags() {
return new TreeSet<String>(tags);
}

View File

@@ -39,6 +39,7 @@ import de.srsoftware.web4rail.tags.Label;
import de.srsoftware.web4rail.tags.Select;
import de.srsoftware.web4rail.tags.Table;
import de.srsoftware.web4rail.tags.Window;
import de.srsoftware.web4rail.threads.Autopilot;
import de.srsoftware.web4rail.tiles.Block;
import de.srsoftware.web4rail.tiles.Contact;
import de.srsoftware.web4rail.tiles.Tile;
@@ -88,55 +89,13 @@ public class Train extends BaseClass implements Comparable<Train> {
private Vector<Block> lastBlocks = new Vector<Block>();
public int speed = 0;
private Autopilot autopilot = null;
public Autopilot autopilot = null;
private Route nextRoute;
private static final String SHUNTING = "shunting";
private boolean shunting = false;
private boolean reserving; // used to prevent recursive calls of reserveNext
private class Autopilot extends Thread{
boolean stop = false;
int waitTime = 100;
public Autopilot() {
setName(Application.threadName("Autopilot("+Train.this+")"));
start();
}
@Override
public void run() {
try {
stop = false;
while (true) {
if (isNull(route)) {
Thread.sleep(waitTime);
if (waitTime > 100) waitTime /=2;
if (stop) break;
if (isNull(route)) { // may have been set by start action in between
String message = Train.this.start();
if (isSet(route)) {
LOG.debug("{}.start called, route now is {}",Train.this,route);
plan.stream(message);
//if (isSet(destination)) Thread.sleep(1000); // limit load on PathFinder
} else {
LOG.debug(message);
waitTime = 1000; // limit load on PathFinder
}
}
} else {
if (stop) break;
Thread.sleep(250);
}
}
} catch (Exception e) {
e.printStackTrace();
}
autopilot = null;
if (isSet(currentBlock)) plan.place(currentBlock);
}
}
public static Object action(HashMap<String, String> params, Plan plan) throws IOException {
String action = params.get(ACTION);
if (isNull(action)) return t("No action passed to Train.action!");
@@ -220,7 +179,7 @@ public class Train extends BaseClass implements Comparable<Train> {
public String automatic() {
if (isNull(autopilot)) {
autopilot = new Autopilot();
autopilot = new Autopilot(this);
if (isSet(currentBlock)) plan.place(currentBlock);
}
return t("{} now in auto-mode",this);
@@ -727,7 +686,7 @@ public class Train extends BaseClass implements Comparable<Train> {
nextRoute = null;
}
if (isSet(autopilot)) {
autopilot.stop = true;
autopilot.doStop();
autopilot = null;
if (isSet(currentBlock)) plan.place(currentBlock);
return t("{} stopping at next block.",this);
@@ -925,11 +884,8 @@ public class Train extends BaseClass implements Comparable<Train> {
}
public void setWaitTime(Range waitTime) {
if (isNull(autopilot)) return;
autopilot.waitTime = waitTime.random();
String msg = t("{} waiting {} secs...",this,autopilot.waitTime/1000d);
LOG.debug(msg);
plan.stream(msg);
if (isNull(autopilot)) return;
autopilot.waitTime(waitTime);
}
private Tag slower(int steps) {

View File

@@ -0,0 +1,68 @@
package de.srsoftware.web4rail.threads;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import de.srsoftware.web4rail.Application;
import de.srsoftware.web4rail.BaseClass;
import de.srsoftware.web4rail.Range;
import de.srsoftware.web4rail.moving.Train;
public class Autopilot extends Thread{
private static final Logger LOG = LoggerFactory.getLogger(Autopilot.class);
boolean stop = false;
private Train train;
int waitTime = 100;
public Autopilot(Train train) {
this.train = train;
setName(Application.threadName("Autopilot("+train+")"));
start();
}
public void doStop() {
stop = true;
}
@Override
public void run() {
try {
stop = false;
while (true) {
if (BaseClass.isNull(train.route())) {
Thread.sleep(waitTime);
if (waitTime > 100) waitTime /=2;
if (stop) break;
if (BaseClass.isNull(train.route())) { // may have been set by start action in between
String message = train.start();
if (BaseClass.isSet(train.route())) {
LOG.debug("{}.start called, route now is {}",train,train.route());
BaseClass.plan.stream(message);
//if (isSet(destination)) Thread.sleep(1000); // limit load on PathFinder
} else {
LOG.debug(message);
waitTime = 1000; // limit load on PathFinder
}
}
} else {
if (stop) break;
Thread.sleep(250);
}
}
} catch (Exception e) {
e.printStackTrace();
}
train.autopilot = null;
if (BaseClass.isSet(train.currentBlock())) BaseClass.plan.place(train.currentBlock());
}
public void waitTime(Range wt) {
this.waitTime = wt.random();
String msg = BaseClass.t("{} waiting {} secs...",this,waitTime/1000d);
LOG.debug(msg);
BaseClass.plan.stream(msg);
}
}

View File

@@ -0,0 +1,145 @@
package de.srsoftware.web4rail.threads;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import de.srsoftware.web4rail.Application;
import de.srsoftware.web4rail.BaseClass;
import de.srsoftware.web4rail.Route;
import de.srsoftware.web4rail.moving.Train;
public class BrakeProcessor extends Thread {
public static final Logger LOG = LoggerFactory.getLogger(BrakeProcessor.class);
private long latestTick;
private static final int SPEED_STEP = 5;
private Integer timeStep;
private Route route;
private Train train;
private String brakeId;
private long estimatedDistance; // Unit: s*km/h "km/h-Sekunden"
private int startSpeed,endSpeed;
private boolean aborted,modified,finished;
public static int defaultEndSpeed = 10;
public BrakeProcessor(Route route, Train train) {
this.train = train;
this.route = route;
aborted = false;
modified = false;
finished = false;
brakeId = train.brakeId();
startSpeed = train.speed;
endSpeed = defaultEndSpeed;
timeStep = route.brakeTime(brakeId);
if (BaseClass.isNull(timeStep) || timeStep>1000000) timeStep = 256; // if no brake time is available for this train
setName(Application.threadName("BrakeProcessor("+train+")"));
start();
}
public void abort() {
aborted = true;
}
private long calcDistance(Integer ts) {
long dist = 0;
int s = startSpeed;
while (s > defaultEndSpeed) {
s -= SPEED_STEP;
dist += s*ts;
}
LOG.debug("Estimated distamce with {} ms timestep: {}",ts,dist);
return dist;
}
private void checkNextRoute() {
Route nextRoute = train.nextRoute();
if (BaseClass.isSet(nextRoute) && nextRoute.state() == Route.State.PREPARED) { // auf Startgeschwindigkeit der Nachfolgeroute bremsen
Integer nextRouteStartSpeed = nextRoute.startSpeed();
if (BaseClass.isSet(nextRouteStartSpeed)) {
LOG.debug("updating target velocity from {} to {}!",endSpeed,nextRouteStartSpeed);
endSpeed = nextRouteStartSpeed;
modified = true;
if (endSpeed > train.speed) train.setSpeed(endSpeed);
}
}
}
/**
* This is called from route.finish when train came to stop
*/
public void finish() {
LOG.debug("BrakeProcessor.finish()");
finished = true;
if (aborted || modified) return;
increaseDistance();
train.setSpeed(0);
LOG.debug("Estimated distance: {}",estimatedDistance);
if (startSpeed <= endSpeed) return;
if (timeStep<0) timeStep = 100;
Integer newTimeStep = timeStep;
long calculated;
int step = 32*newTimeStep;
for (int i=0; i<20; i++) {
step = step/2;
if (step<1) step = 1;
calculated = calcDistance(newTimeStep);
LOG.debug("Calculated distance for step = {} ms: {}",newTimeStep,calculated);
LOG.debug("Update step: {}",step);
newTimeStep = newTimeStep + (calculated > estimatedDistance ? -step : step);
}
if (!newTimeStep.equals(timeStep)) {
route.brakeTime(brakeId,newTimeStep);
calculated = calcDistance(newTimeStep);
LOG.debug("Corrected brake timestep for {} @ {} from {} to {} ms.",train,route,timeStep,newTimeStep);
LOG.debug("Differemce from estimated distance: {} ({}%)",estimatedDistance-calculated,100*(estimatedDistance-calculated)/(float)estimatedDistance);
}
}
private void increaseDistance(){
long tick = BaseClass.timestamp();
estimatedDistance += train.speed * (3+tick-latestTick);
latestTick = tick;
}
@Override
public void run() {
setName(Application.threadName("BreakeProcessor("+train+")"));
LOG.debug("started BrakeProcessor ({} → {}) for {} with timestep = {} ms.",train.speed,endSpeed,train,timeStep);
estimatedDistance = 0;
latestTick = BaseClass.timestamp();
while (train.speed > endSpeed) {
if (finished || aborted) return;
increaseDistance();
LOG.debug("BrakeProcessor({}) setting Speed of {}.",route,train);
train.setSpeed(Math.max(train.speed - SPEED_STEP,endSpeed));
if (!modified) checkNextRoute();
try {
sleep(timeStep);
} catch (InterruptedException e) {
LOG.warn("BrakeProcessor interrupted!", e);
}
}
while (!finished && !aborted && !modified) {
try {
sleep(1000);
} catch (InterruptedException e) {
LOG.warn("BrakeProcessor interrupted!", e);
}
checkNextRoute();
}
}
public void setEndSpeed(Integer newEndSpeed) {
if (BaseClass.isNull(newEndSpeed)) return;
endSpeed = newEndSpeed;
modified = true;
}
}

View File

@@ -1,4 +1,4 @@
package de.srsoftware.web4rail;
package de.srsoftware.web4rail.threads;
import java.io.BufferedReader;
import java.io.BufferedWriter;
@@ -17,6 +17,10 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import de.keawe.tools.translations.Translation;
import de.srsoftware.web4rail.Application;
import de.srsoftware.web4rail.Command;
import de.srsoftware.web4rail.Constants;
import de.srsoftware.web4rail.Plan;
import de.srsoftware.web4rail.tags.Button;
import de.srsoftware.web4rail.tags.Fieldset;
import de.srsoftware.web4rail.tags.Form;

View File

@@ -1,4 +1,6 @@
package de.srsoftware.web4rail;
package de.srsoftware.web4rail.threads;
import de.srsoftware.web4rail.Application;
public abstract class DelayedExecution extends Thread {
private int delay;

View File

@@ -9,11 +9,11 @@ import org.json.JSONObject;
import de.srsoftware.tools.Tag;
import de.srsoftware.web4rail.BaseClass;
import de.srsoftware.web4rail.Connector;
import de.srsoftware.web4rail.DelayedExecution;
import de.srsoftware.web4rail.Route;
import de.srsoftware.web4rail.moving.Train;
import de.srsoftware.web4rail.tags.Fieldset;
import de.srsoftware.web4rail.tags.Window;
import de.srsoftware.web4rail.threads.DelayedExecution;
public abstract class Bridge extends Tile {
private static final String COUNTERPART = "counterpart";

View File

@@ -16,7 +16,6 @@ import org.slf4j.LoggerFactory;
import de.srsoftware.tools.Tag;
import de.srsoftware.web4rail.Application;
import de.srsoftware.web4rail.BaseClass;
import de.srsoftware.web4rail.DelayedExecution;
import de.srsoftware.web4rail.Route;
import de.srsoftware.web4rail.actions.Action;
import de.srsoftware.web4rail.actions.ActionList;
@@ -24,6 +23,7 @@ import de.srsoftware.web4rail.tags.Fieldset;
import de.srsoftware.web4rail.tags.Input;
import de.srsoftware.web4rail.tags.Select;
import de.srsoftware.web4rail.tags.Window;
import de.srsoftware.web4rail.threads.DelayedExecution;
public class Contact extends Tile{
private static Logger LOG = LoggerFactory.getLogger(Contact.class);