@ -12,8 +12,8 @@ import java.util.LinkedList;
import java.util.List ;
import java.util.List ;
import java.util.Map ;
import java.util.Map ;
import java.util.Map.Entry ;
import java.util.Map.Entry ;
import java.util.Random ;
import java.util.SortedSet ;
import java.util.SortedSet ;
import java.util.TreeMap ;
import java.util.TreeSet ;
import java.util.TreeSet ;
import java.util.Vector ;
import java.util.Vector ;
@ -76,7 +76,7 @@ public class Train extends BaseClass implements Comparable<Train> {
private HashSet < String > tags = new HashSet < String > ( ) ;
private HashSet < String > tags = new HashSet < String > ( ) ;
private Block b lock, destination = null ;
private Block currentB lock, destination = null ;
LinkedList < Tile > trace = new LinkedList < Tile > ( ) ;
LinkedList < Tile > trace = new LinkedList < Tile > ( ) ;
private class Autopilot extends Thread {
private class Autopilot extends Thread {
@ -171,28 +171,55 @@ public class Train extends BaseClass implements Comparable<Train> {
}
}
showTrace ( ) ;
showTrace ( ) ;
}
}
private Route chooseRoute ( Context context ) {
private static Route chooseRoute ( Context context ) {
HashSet < Route > routes = block . routes ( ) ;
TreeMap < Integer , List < Route > > availableRoutes = availableRoutes ( context ) ;
Vector < Route > availableRoutes = new Vector < Route > ( ) ;
if ( availableRoutes . isEmpty ( ) ) return null ;
Entry < Integer , List < Route > > entry = availableRoutes . firstEntry ( ) ;
List < Route > preferredRoutes = entry . getValue ( ) ;
Route selectetRoute = preferredRoutes . get ( random . nextInt ( preferredRoutes . size ( ) ) ) ;
LOG . debug ( "Chose \"{}\" with priority {}." , selectetRoute , entry . getKey ( ) ) ;
return selectetRoute ;
}
private static TreeMap < Integer , List < Route > > availableRoutes ( Context context ) {
TreeMap < Integer , List < Route > > availableRoutes = new TreeMap < Integer , List < Route > > ( ) ;
boolean error = false ;
if ( isNull ( context . block ) ) {
LOG . warn ( "{}.availableRoutes called without context.block!" , Train . class . getSimpleName ( ) ) ;
error = true ;
}
if ( isNull ( context . train ) ) {
LOG . warn ( "{}.availableRoutes called without context.train!" , Train . class . getSimpleName ( ) ) ;
error = true ;
}
if ( error ) return availableRoutes ;
Collection < Route > routes = context . block . routes ( ) ;
for ( Route rt : routes ) {
for ( Route rt : routes ) {
if ( rt = = route ) continue ; // andere Route als zuvor wählen
if ( rt . path ( ) . firstElement ( ) ! = context . block ) continue ; // routen, die nicht vom aktuellen Block starten sind bubu
if ( rt . path ( ) . firstElement ( ) ! = block ) continue ; // keine Route wählen, die nicht vom aktuellen Block des Zuges startet
int priority = 0 ;
if ( isSet ( direction ) & & rt . startDirection ! = direction ) { // Route ist entgegen der Startrichtung des Zuges
if ( rt = = context . route ) priority - = 10 ; // möglichst andere Route als zuvor wählen // TODO: den Routen einen "last-used" Zeitstempel hinzufügen, und diesen mit in die Priorisierung einbeziehen
if ( ! pushPull | | ! block . turnAllowed ) { // Zug ist kein Wendezug oder Block erlaubt kein Wenden
if ( isSet ( context . train . direction ) & & rt . startDirection ! = context . train . direction ) { // Route startet entgegen der aktuellen Fahrtrichtung des Zuges
continue ;
if ( ! context . train . pushPull ) continue ; // Zug kann nicht wenden
}
if ( ! context . block . turnAllowed ) continue ; // Wenden im Block nicht gestattet
priority - = 5 ;
}
}
if ( ! rt . isFreeFor ( this ) ) { // keine belegten Routen wählen
if ( ! rt . isFreeFor ( context . train ) ) continue ; // Route ist nicht frei
// LOG.debug("{} is not free!",rt);
if ( ! rt . allowed ( context ) ) continue ; // Zug darf auf Grund einer nicht erfüllten Bedingung nicht auf die Route
continue ;
List < Route > routeSet = availableRoutes . get ( priority ) ;
if ( isNull ( routeSet ) ) {
routeSet = new Vector < Route > ( ) ;
availableRoutes . put ( priority , routeSet ) ;
}
}
if ( ! rt . allowed ( context ) ) continue ;
routeSet . add ( rt ) ;
availableRoutes . add ( rt ) ;
}
}
Random rand = new Random ( ) ;
if ( availableRoutes . isEmpty ( ) ) return null ;
return availableRoutes ;
return availableRoutes . get ( rand . nextInt ( availableRoutes . size ( ) ) ) ;
}
}
@Override
@Override
@ -303,7 +330,7 @@ public class Train extends BaseClass implements Comparable<Train> {
public Train heading ( Direction dir ) {
public Train heading ( Direction dir ) {
direction = dir ;
direction = dir ;
if ( isSet ( b lock) ) plan . place ( b lock) ;
if ( isSet ( currentB lock) ) plan . place ( currentB lock) ;
return this ;
return this ;
}
}
@ -316,7 +343,7 @@ public class Train extends BaseClass implements Comparable<Train> {
json . put ( ID , id ) ;
json . put ( ID , id ) ;
json . put ( PUSH_PULL , pushPull ) ;
json . put ( PUSH_PULL , pushPull ) ;
if ( isSet ( b lock) ) json . put ( BLOCK , b lock. id ( ) ) ;
if ( isSet ( currentB lock) ) json . put ( BLOCK , currentB lock. id ( ) ) ;
if ( isSet ( name ) ) json . put ( NAME , name ) ;
if ( isSet ( name ) ) json . put ( NAME , name ) ;
if ( isSet ( route ) ) json . put ( ROUTE , route . id ( ) ) ;
if ( isSet ( route ) ) json . put ( ROUTE , route . id ( ) ) ;
if ( isSet ( direction ) ) json . put ( DIRECTION , direction ) ;
if ( isSet ( direction ) ) json . put ( DIRECTION , direction ) ;
@ -374,7 +401,7 @@ public class Train extends BaseClass implements Comparable<Train> {
if ( json . has ( NAME ) ) name = json . getString ( NAME ) ;
if ( json . has ( NAME ) ) name = json . getString ( NAME ) ;
if ( json . has ( TAGS ) ) json . getJSONArray ( TAGS ) . forEach ( elem - > { tags . add ( elem . toString ( ) ) ; } ) ;
if ( json . has ( TAGS ) ) json . getJSONArray ( TAGS ) . forEach ( elem - > { tags . add ( elem . toString ( ) ) ; } ) ;
if ( json . has ( TRACE ) ) json . getJSONArray ( TRACE ) . forEach ( elem - > { trace . add ( plan . get ( elem . toString ( ) , false ) . set ( this ) ) ; } ) ;
if ( json . has ( TRACE ) ) json . getJSONArray ( TRACE ) . forEach ( elem - > { trace . add ( plan . get ( elem . toString ( ) , false ) . set ( this ) ) ; } ) ;
if ( json . has ( BLOCK ) ) b lock = ( Block ) plan . get ( json . getString ( BLOCK ) , false ) . set ( this ) ; // do not move this up! during set, other fields will be referenced!
if ( json . has ( BLOCK ) ) currentB lock = ( Block ) plan . get ( json . getString ( BLOCK ) , false ) . set ( this ) ; // do not move this up! during set, other fields will be referenced!
for ( Object id : json . getJSONArray ( CARS ) ) add ( Car . get ( id ) ) ;
for ( Object id : json . getJSONArray ( CARS ) ) add ( Car . get ( id ) ) ;
for ( Object id : json . getJSONArray ( LOCOS ) ) add ( ( Locomotive ) Car . get ( id ) ) ;
for ( Object id : json . getJSONArray ( LOCOS ) ) add ( ( Locomotive ) Car . get ( id ) ) ;
return this ;
return this ;
@ -494,8 +521,8 @@ public class Train extends BaseClass implements Comparable<Train> {
}
}
dest . addTo ( propList ) ;
dest . addTo ( propList ) ;
if ( isSet ( b lock) ) {
if ( isSet ( currentB lock) ) {
link ( "li" , Map . of ( REALM , REALM_PLAN , ID , b lock. id ( ) , ACTION , ACTION_CLICK ) , t ( "Current location: {}" , b lock) ) . addTo ( propList ) ;
link ( "li" , Map . of ( REALM , REALM_PLAN , ID , currentB lock. id ( ) , ACTION , ACTION_CLICK ) , t ( "Current location: {}" , currentB lock) ) . addTo ( propList ) ;
Tag actions = new Tag ( "li" ) . clazz ( ) . content ( t ( "Actions:" ) + NBSP ) ;
Tag actions = new Tag ( "li" ) . clazz ( ) . content ( t ( "Actions:" ) + NBSP ) ;
props . put ( ACTION , ACTION_START ) ;
props . put ( ACTION , ACTION_START ) ;
new Button ( t ( "start" ) , props ) . addTo ( actions ) ;
new Button ( t ( "start" ) , props ) . addTo ( actions ) ;
@ -556,8 +583,8 @@ public class Train extends BaseClass implements Comparable<Train> {
}
}
public void set ( Block newBlock ) {
public void set ( Block newBlock ) {
b lock = newBlock ;
currentB lock = newBlock ;
if ( isSet ( block ) ) b lock. set ( this ) ;
if ( isSet ( currentBlock ) ) currentB lock. set ( this ) ;
}
}
private String setDestination ( HashMap < String , String > params ) {
private String setDestination ( HashMap < String , String > params ) {
@ -594,13 +621,12 @@ public class Train extends BaseClass implements Comparable<Train> {
}
}
public String start ( ) throws IOException {
public String start ( ) throws IOException {
if ( isNull ( b lock) ) return t ( "{} not in a block" , this ) ;
if ( isNull ( currentB lock) ) return t ( "{} not in a block" , this ) ;
Context context = isSet ( route ) ? new Context ( route ) : new Context ( this ) ;
Context context = isSet ( route ) ? new Context ( route ) : new Context ( this ) ;
if ( isSet ( context . route ) ) context . route . reset ( ) ; // reset route previously chosen
if ( isSet ( context . route ) ) context . route . reset ( ) ; // reset route previously chosen
route = chooseRoute ( context ) ;
route = chooseRoute ( context ) ;
if ( isNull ( route ) ) return t ( "No free routes from {}" , b lock) ;
if ( isNull ( route ) ) return t ( "No free routes from {}" , currentB lock) ;
if ( ! route . lock ( ) ) return t ( "Was not able to lock {}" , route ) ;
if ( ! route . lock ( ) ) return t ( "Was not able to lock {}" , route ) ;
if ( direction ! = route . startDirection ) turn ( ) ;
if ( direction ! = route . startDirection ) turn ( ) ;
@ -648,7 +674,7 @@ public class Train extends BaseClass implements Comparable<Train> {
direction = direction . inverse ( ) ;
direction = direction . inverse ( ) ;
for ( Locomotive loco : locos ) loco . turn ( ) ;
for ( Locomotive loco : locos ) loco . turn ( ) ;
reverseTrace ( ) ;
reverseTrace ( ) ;
if ( isSet ( b lock) ) plan . place ( b lock) ;
if ( isSet ( currentB lock) ) plan . place ( currentB lock) ;
}
}
return t ( "{} turned." , this ) ;
return t ( "{} turned." , this ) ;
}
}
@ -676,4 +702,8 @@ public class Train extends BaseClass implements Comparable<Train> {
public void setWaitTime ( Range waitTime ) {
public void setWaitTime ( Range waitTime ) {
if ( autopilot ! = null ) autopilot . waitTime = waitTime . random ( ) ;
if ( autopilot ! = null ) autopilot . waitTime = waitTime . random ( ) ;
}
}
public Block currentBlock ( ) {
return currentBlock ;
}
}
}