bugfixes
This commit is contained in:
2
pom.xml
2
pom.xml
@@ -4,7 +4,7 @@
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>de.srsoftware</groupId>
|
||||
<artifactId>web4rail</artifactId>
|
||||
<version>1.4.2</version>
|
||||
<version>1.4.3</version>
|
||||
<name>Web4Rail</name>
|
||||
<packaging>jar</packaging>
|
||||
<description>Java Model Railway Control</description>
|
||||
|
||||
@@ -886,31 +886,38 @@ public class Plan extends BaseClass{
|
||||
* @param data
|
||||
*/
|
||||
public synchronized void stream(String data) {
|
||||
data = data.replaceAll("\n", "").replaceAll("\r", "");
|
||||
//if (!data.startsWith("heartbeat")) LOG.debug("streaming: {}",data);
|
||||
Vector<OutputStreamWriter> badClients = null;
|
||||
for (Entry<OutputStreamWriter, Integer> entry : clients.entrySet()) {
|
||||
OutputStreamWriter client = entry.getKey();
|
||||
try {
|
||||
client.write("data: "+data+"\n\n");
|
||||
client.flush();
|
||||
clients.put(client,0);
|
||||
} catch (IOException e) {
|
||||
int errorCount = entry.getValue()+1;
|
||||
LOG.info("Error #{} on client: {}",errorCount,e.getMessage());
|
||||
if (errorCount > 4) {
|
||||
if (isNull(badClients)) badClients = new Vector<OutputStreamWriter>();
|
||||
String fixedData = data.replaceAll("\n", "").replaceAll("\r", "");
|
||||
new Thread("Plan") {
|
||||
@Override
|
||||
public void run() {
|
||||
//if (!data.startsWith("heartbeat")) LOG.debug("streaming: {}",data);
|
||||
Vector<OutputStreamWriter> badClients = null;
|
||||
for (Entry<OutputStreamWriter, Integer> entry : clients.entrySet()) {
|
||||
OutputStreamWriter client = entry.getKey();
|
||||
try {
|
||||
client.close();
|
||||
} catch (IOException e1) {}
|
||||
badClients.add(client);
|
||||
} else clients.put(client,errorCount);
|
||||
client.write("data: "+fixedData+"\n\n");
|
||||
client.flush();
|
||||
clients.put(client,0);
|
||||
} catch (IOException e) {
|
||||
int errorCount = entry.getValue()+1;
|
||||
LOG.info("Error #{} on client: {}",errorCount,e.getMessage());
|
||||
if (errorCount > 4) {
|
||||
if (isNull(badClients)) badClients = new Vector<OutputStreamWriter>();
|
||||
try {
|
||||
client.close();
|
||||
} catch (IOException e1) {}
|
||||
badClients.add(client);
|
||||
} else clients.put(client,errorCount);
|
||||
}
|
||||
}
|
||||
if (badClients != null) for (OutputStreamWriter client: badClients) {
|
||||
LOG.info("Disconnecting client.");
|
||||
clients.remove(client);
|
||||
}
|
||||
// TODO Auto-generated method stub
|
||||
}
|
||||
}
|
||||
if (badClients != null) for (OutputStreamWriter client: badClients) {
|
||||
LOG.info("Disconnecting client.");
|
||||
clients.remove(client);
|
||||
}
|
||||
}.start();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -232,9 +232,7 @@ public class Route extends BaseClass {
|
||||
}
|
||||
|
||||
public Integer brakeTime(String brakeId) {
|
||||
Integer result = brakeTimes.get(brakeId);
|
||||
Collection<Integer> values = brakeTimes.values();
|
||||
return values.isEmpty() ? BrakeProcess.defaultTimeStep : values.stream().mapToInt(Integer::intValue).sum()/values.size();
|
||||
return brakeTimes.get(brakeId);
|
||||
}
|
||||
|
||||
public void brakeTime(String brakeId, Integer newTimeStep) {
|
||||
@@ -392,6 +390,7 @@ public class Route extends BaseClass {
|
||||
public void finish(Train train) {
|
||||
LOG.debug("{}.finish()",this);
|
||||
train.endRoute(endBlock,endDirection);
|
||||
setSignals(Signal.RED);
|
||||
freeIgnoring(null);
|
||||
train = null;
|
||||
}
|
||||
|
||||
@@ -362,7 +362,7 @@ public class Train extends BaseClass implements Comparable<Train> {
|
||||
|
||||
public String directedName(Direction dir) {
|
||||
String result = name();
|
||||
String mark = ""; //isSet(autopilot) ? "ⓐ" : "";
|
||||
String mark = autopilot ? "ⓐ" : "";
|
||||
if (isNull(dir)) return result;
|
||||
switch (dir) {
|
||||
case NORTH:
|
||||
@@ -418,6 +418,10 @@ public class Train extends BaseClass implements Comparable<Train> {
|
||||
|
||||
public void endRoute(Block endBlock, Direction endDirection) {
|
||||
BrakeProcess brake = endBrake();
|
||||
if (endBlock == destination) {
|
||||
quitAutopilot();
|
||||
destination = null;
|
||||
}
|
||||
if (isSet(brake)) brake.updateTime();
|
||||
Integer waitTime = route.waitTime();
|
||||
nextPreparedRoute = route.dropNextPreparedRoute();
|
||||
@@ -721,11 +725,11 @@ public class Train extends BaseClass implements Comparable<Train> {
|
||||
|
||||
public String quitAutopilot() {
|
||||
if (isSet(routePrepper)) routePrepper.stop();
|
||||
try {
|
||||
return autopilot ? t("Autopilot disabled") : t("Autopilot already was disabled!");
|
||||
} finally {
|
||||
if (autopilot) {
|
||||
autopilot = false;
|
||||
}
|
||||
if (isSet(currentBlock)) plan.place(currentBlock);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -826,7 +830,7 @@ public class Train extends BaseClass implements Comparable<Train> {
|
||||
if (isNull(tile)) return properties(t("Tile {} not known!",dest));
|
||||
if (tile instanceof Block) {
|
||||
destination = (Block) tile;
|
||||
start(false);
|
||||
start(true);
|
||||
return t("{} now heading for {}",this,destination);
|
||||
}
|
||||
return properties(t("{} is not a block!",tile));
|
||||
|
||||
@@ -5,11 +5,14 @@ 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 BrakeProcess extends BaseClass implements Runnable{
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(BrakeProcess.class);
|
||||
|
||||
private static final int SPEED_STEP = 10;
|
||||
|
||||
public static int defaultTimeStep = 500;
|
||||
private Train train;
|
||||
@@ -19,12 +22,31 @@ public class BrakeProcess extends BaseClass implements Runnable{
|
||||
private int startSpeed;
|
||||
private int lastSpeed;
|
||||
private long lastTime;
|
||||
|
||||
private Integer timeStep;
|
||||
|
||||
private Route route;
|
||||
|
||||
private String brakeId;
|
||||
|
||||
public BrakeProcess(Train train) {
|
||||
this.train = train;
|
||||
this.train = train;
|
||||
this.brakeId = train.brakeId();
|
||||
this.route = train.route();
|
||||
new Thread(this, Application.threadName(this)).start();
|
||||
}
|
||||
|
||||
private long calcDistance(Integer ts) {
|
||||
long dist = 0;
|
||||
int s = startSpeed;
|
||||
while (s > Train.defaultEndSpeed) {
|
||||
s -= SPEED_STEP;
|
||||
dist += s*ts;
|
||||
}
|
||||
LOG.debug("Estimated distamce with {} ms timestep: {}",ts,dist);
|
||||
return dist;
|
||||
}
|
||||
|
||||
public BrakeProcess end() {
|
||||
LOG.debug("{}.end()",this);
|
||||
ended = true;
|
||||
@@ -33,14 +55,15 @@ public class BrakeProcess extends BaseClass implements Runnable{
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
Integer delay = train.route().brakeTime(train.brakeId());
|
||||
timeStep = train.route().brakeTime(train.brakeId());
|
||||
if (timeStep == null) timeStep = defaultTimeStep;
|
||||
startSpeed = train.speed;
|
||||
lastTime = timestamp();
|
||||
while (!train.hasNextPreparedRoute()) {
|
||||
sleep(delay);
|
||||
sleep(timeStep);
|
||||
lastSpeed = train.speed;
|
||||
updateDistance();
|
||||
if (lastSpeed > targetSpeed) lastSpeed -= 10;
|
||||
if (lastSpeed > targetSpeed) lastSpeed -= SPEED_STEP;
|
||||
if (ended) break;
|
||||
if (lastSpeed <= targetSpeed && (ended = true)) lastSpeed = targetSpeed;
|
||||
train.setSpeed(lastSpeed);
|
||||
@@ -62,6 +85,23 @@ public class BrakeProcess extends BaseClass implements Runnable{
|
||||
public void updateTime() {
|
||||
updateDistance();
|
||||
LOG.debug("updateTime(): start speed was {} {}.",startSpeed,BaseClass.speedUnit);
|
||||
// TODO
|
||||
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 > distance ? -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: {} ({}%)",distance-calculated,100*(distance-calculated)/(float)distance);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -318,7 +318,7 @@ public class ControlUnit extends Thread implements Constants{
|
||||
case FEEDBACK:
|
||||
int addr = Integer.parseInt(parts[5]);
|
||||
boolean active = !parts[6].equals("0");
|
||||
new Thread(Application.threadName("CU.FeedBack("+addr+")")) {
|
||||
new Thread(Application.threadName("CU.Feedback("+addr+")")) {
|
||||
@Override
|
||||
public void run() {
|
||||
plan.sensor(addr,active);
|
||||
|
||||
@@ -51,13 +51,13 @@ public class RoutePrepper extends BaseClass implements Runnable{
|
||||
LOG.warn("{}→ {}.availableRoutes called without context.train!", inset, Train.class.getSimpleName());
|
||||
if (error) return availableRoutes;
|
||||
|
||||
Block destination = train.destination();
|
||||
if (isSet(startDirection)) {
|
||||
LOG.debug("{}- Looking for {}-bound routes from {}", inset, startDirection, block);
|
||||
} else {
|
||||
LOG.debug("{}- Looking for all routes from {}", inset, block);
|
||||
}
|
||||
|
||||
|
||||
Block destination = train.destination();
|
||||
if (isSet(destination) && visitedRoutes.isEmpty()) LOG.debug("{}- Destination: {}", inset, destination);
|
||||
|
||||
for (Route routeCandidate : block.leavingRoutes()) {
|
||||
@@ -68,9 +68,9 @@ public class RoutePrepper extends BaseClass implements Runnable{
|
||||
}
|
||||
|
||||
HashSet<Tile> stuckTrace = train.stuckTrace(); // if train has been stopped in between two blocks lastly:
|
||||
// only allow routes that do not conflict with current train
|
||||
// only allow starting routes that do not conflict with current train
|
||||
// position
|
||||
if (isSet(stuckTrace) && !routeCandidate.path().containsAll(stuckTrace)) {
|
||||
if (isSet(stuckTrace) && visitedRoutes.isEmpty() && !routeCandidate.path().containsAll(stuckTrace)) {
|
||||
LOG.debug("Stuck train occupies tiles ({}) outside of {} – not allowed.", stuckTrace, routeCandidate);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -84,17 +84,16 @@ public class Contact extends Tile{
|
||||
} else {
|
||||
LOG.debug("{} activated.",this);
|
||||
state = true;
|
||||
stream();
|
||||
if (isSet(timer)) timer.abort();
|
||||
Train train = train();
|
||||
Context context = isSet(train) ? train.contact(this) : new Context(this);
|
||||
actions.fire(context,"Contact("+addr+")");
|
||||
|
||||
for (Listener listener : listeners) listener.fired("Contact("+addr+")");
|
||||
|
||||
stream();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public int addr() {
|
||||
return addr;
|
||||
}
|
||||
@@ -112,12 +111,7 @@ public class Contact extends Tile{
|
||||
|
||||
@Override
|
||||
public Object click(boolean shift) throws IOException {
|
||||
if (!shift) new Thread(Application.threadName(this)) {
|
||||
@Override
|
||||
public void run() {
|
||||
trigger(200);
|
||||
}
|
||||
}.start();
|
||||
if (!shift) trigger(200);
|
||||
return super.click(shift);
|
||||
}
|
||||
|
||||
|
||||
@@ -540,7 +540,11 @@ public abstract class Tile extends BaseClass implements Comparable<Tile> {
|
||||
oneWay = null;
|
||||
}
|
||||
}
|
||||
if ("on".equals(params.get(DISABLED))) status = Status.DISABLED;
|
||||
if ("on".equals(params.get(DISABLED))) {
|
||||
status = Status.DISABLED;
|
||||
} else {
|
||||
status = isSet(train) ? Status.OCCUPIED : Status.FREE;
|
||||
}
|
||||
String len = params.get(LENGTH);
|
||||
if (isSet(len)) length(Integer.parseInt(len));
|
||||
super.update(params);
|
||||
|
||||
Reference in New Issue
Block a user