2595 lines
124 KiB
Python
2595 lines
124 KiB
Python
###############################################################################
|
|
#
|
|
# class MoveTrain
|
|
# Calls dispatcher to e train from one station to another
|
|
# given engine and start and end positions
|
|
#
|
|
###############################################################################
|
|
|
|
import os
|
|
import java
|
|
import jmri
|
|
import math
|
|
import time
|
|
|
|
from javax.swing import JTable, JScrollPane, JFrame, JPanel, JComboBox, BorderFactory, DefaultCellEditor, JLabel, UIManager, SwingConstants, JFileChooser
|
|
from javax.swing.table import TableCellRenderer, DefaultTableCellRenderer
|
|
from java.awt.event import MouseAdapter,MouseEvent, WindowListener, WindowEvent
|
|
from java.awt import GridLayout, Dimension, BorderLayout, Color
|
|
from javax.swing.table import AbstractTableModel, DefaultTableModel
|
|
from java.lang.Object import getClass
|
|
from jmri.jmrit.logix import WarrantPreferences
|
|
import jarray
|
|
from javax.swing.event import TableModelListener, TableModelEvent
|
|
from javax.swing.filechooser import FileNameExtensionFilter
|
|
from org.apache.commons.io import FilenameUtils
|
|
from java.io import File
|
|
#, defaultTableModel
|
|
|
|
global MoveTrain_index
|
|
MoveTrain_index = 0
|
|
|
|
|
|
class MoveTrain(jmri.jmrit.automat.AbstractAutomaton):
|
|
|
|
global trains_dispatched
|
|
global trains
|
|
global time_last_train
|
|
|
|
def __init__(self, station_from_name, station_to_name, train_name, graph, stop_mode = None, mode = "not_scheduling", route = None):
|
|
self.logLevel = 0
|
|
if self.logLevel > 0: print "station_from_name", station_from_name, "station_to_name",station_to_name, "train_name", train_name, "stop_mode", stop_mode
|
|
self.station_from_name = station_from_name
|
|
self.station_to_name = station_to_name
|
|
self.train_name = train_name
|
|
self.graph = graph
|
|
self.route = route
|
|
# if there is a stop sensor at the last station, get the stop mode at the last station if it has been set up
|
|
if self.route != None:
|
|
self.stop_mode = self.get_route_location_stop_mode(station_to_name)
|
|
else:
|
|
self.stop_mode = ""
|
|
self.mode = mode
|
|
|
|
def setup(self):
|
|
return True
|
|
|
|
def handle(self):
|
|
# move between stations in the thread
|
|
if self.logLevel > 1: print"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
|
|
if self.logLevel > 1: print "move between stations in the thread"
|
|
if self.logLevel > 1: print"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
|
|
|
|
result = self.move_between_stations(self.station_from_name, self.station_to_name, self.train_name, self.graph, self.mode)
|
|
return False
|
|
|
|
def get_route_location_stop_mode(self, station_to_name):
|
|
route_location = self.route.getLastLocationByName(station_to_name)
|
|
if self.logLevel > 0: print "get_stop_mode" , "route location", route_location
|
|
comment = route_location.getComment()
|
|
stop_mode = self.find_between(comment, "[stopMode-", "-stopMode]")
|
|
if self.logLevel > 0: print "routeLocation stop_mode", stop_mode
|
|
return stop_mode
|
|
|
|
def find_between(self, s, first, last):
|
|
try:
|
|
start = s.index(first) + len(first)
|
|
end = s.index(last, start)
|
|
return s[start:end]
|
|
except ValueError:
|
|
return ""
|
|
|
|
def move_between_stations(self, station_from_name, station_to_name, train_name, graph, mode = "not_scheduling"):
|
|
global trains
|
|
global scheduling_margin_gbl
|
|
global fast_clock_rate
|
|
global MoveTrain_index
|
|
global trains_dispatched
|
|
MoveTrain_index += 1
|
|
self.index = MoveTrain_index
|
|
strindex = str(self.index) + " " * 5 #make debugging easier to understand by indenting and prefixing by the train index
|
|
if self.logLevel > 0: print ""
|
|
if self.logLevel > 0: print ""
|
|
if self.logLevel > 0: print strindex + "&&&&&&&&&&&&&&&&& start move_between_stations &&&&&&&&&&&&&&&&&" , strindex
|
|
if self.logLevel > 0: print strindex + "*********************************************"
|
|
if self.logLevel > 0: print strindex + "move_between_stations"
|
|
if self.logLevel > 0: print strindex + "Moving from " + station_from_name + " to " + station_to_name
|
|
if self.logLevel > 0: print strindex + "*********************************************"
|
|
i = 0
|
|
if self.logLevel > 0: print strindex + "checking train in start block"
|
|
|
|
# print strindex + "move_between_stations a"
|
|
if self.logLevel > 0: print strindex + "train is in start block"
|
|
#need to look up the required transit in the graph
|
|
StateVertex_start = station_from_name
|
|
StateVertex_end = station_to_name
|
|
for e in graph.edgeSet():
|
|
if self.logLevel > 1: print (graph.getEdgeSource(e) + " --> " + graph.getEdgeTarget(e))
|
|
if self.logLevel > 0: print strindex + "calling shortest path", StateVertex_start, StateVertex_end
|
|
# List all vertices
|
|
if self.logLevel > 0:
|
|
for vertex in graph.vertexSet():
|
|
print("Vertex:", vertex)
|
|
|
|
paths = DijkstraShortestPath.findPathBetween(graph, StateVertex_start, StateVertex_end)
|
|
# print strindex + "move_between_stations b"
|
|
if paths == None:
|
|
if self.logLevel > 0: print strindex + "cannot find shortest path, paths found is empty"
|
|
# print strindex + "end of move between ", station_from_name, station_to_name
|
|
return
|
|
|
|
if self.logLevel > 1: print strindex + "graph", graph
|
|
if self.logLevel > 1: print strindex + "paths", paths
|
|
if self.logLevel > 1: print strindex + "returned from shortest path"
|
|
if self.logLevel > 0: print strindex + "in move_between_stations trains = ", trains, "train_name = ", train_name
|
|
|
|
if train_name in trains:
|
|
train = trains[train_name]
|
|
else:
|
|
if self.logLevel > 0: print strindex + "in case of key error: trains", trains
|
|
if self.logLevel > 0: print strindex + "******"
|
|
if self.logLevel > 0: print strindex + "train_name", train_name, "trains", trains
|
|
if self.logLevel > 0: print strindex + "************Not Moving Train************"
|
|
return
|
|
if self.logLevel > 1: print strindex + "train" , train, "train_name", train_name
|
|
penultimate_block_name = train["penultimate_block_name"]
|
|
if self.logLevel > 1: print strindex + "penultimate_block_name" , penultimate_block_name
|
|
previous_edge = train["edge"]
|
|
if self.logLevel > 2: print 'move_between_stations train["direction"]' , train["direction"]
|
|
previous_direction_from = train["direction"]
|
|
|
|
|
|
count_path = 0
|
|
# print strindex + "move_between_stations c"
|
|
if paths == None or paths == []:
|
|
if self.logLevel > 0: print strindex + "1Error cannot find shortest path. restart the system. " + \
|
|
"The stop dispatcher system routine does not work properly with multiple layout panels. Sorry"
|
|
return
|
|
|
|
# if we have a problem in one of the paths we set the following to False, and jump out of for statement
|
|
call_next_edge_in_paths = True
|
|
|
|
for e in paths:
|
|
if call_next_edge_in_paths == False:
|
|
break
|
|
|
|
# print strindex + "move_between_stations d"
|
|
# need to check whether:
|
|
# last block of previous edge and current first block
|
|
# are the same
|
|
|
|
# if the same the train must change direction. as we are going in and out the same path
|
|
#
|
|
|
|
if self.logLevel > 0: print strindex + "********************************"
|
|
|
|
previous_edge = train["edge"]
|
|
penultimate_block_name = train["penultimate_block_name"]
|
|
|
|
current_edge = e
|
|
neighbor_name = e.getItem("neighbor_name")
|
|
if self.logLevel > 0: print train
|
|
if self.logLevel > 0: print strindex + "neighbor_name = ", neighbor_name
|
|
if self.logLevel > 0: print strindex + "train penultimate_block_name" , penultimate_block_name
|
|
|
|
BlockManager = jmri.InstanceManager.getDefault(jmri.BlockManager)
|
|
|
|
previous_direction_from = train["direction"]
|
|
# print strindex + "previous direction from", previous_direction_from
|
|
|
|
# wait for the allocated time
|
|
speech_reqd = self.speech_required_flag()
|
|
# print strindex + "move_between_stations e"
|
|
# wait in station and announce the wait time (announcement only for debugging)
|
|
|
|
transit_direction = previous_direction_from
|
|
time_to_stop_in_station = self.get_time_to_stop_in_station(e, transit_direction)
|
|
t = time_to_stop_in_station / 1000
|
|
msg = "started waiting for " + str(int(t)) + " seconds"
|
|
if self.logLevel > 0: self.speak(msg)
|
|
self.waitMsec(int(time_to_stop_in_station))
|
|
msg = "finished waiting for " + str(int(t)) + " seconds"
|
|
if self.logLevel > 0: self.speak(msg)
|
|
|
|
iter = 0
|
|
result = False
|
|
# try to call dispatch until success (result of calling dispatch is True (success) or False (failure))
|
|
while result == False:
|
|
# in case the train moves since the last try of calling for the dispatch (and we have a failure)
|
|
# get the current location of the train at the beginning of the while loop
|
|
|
|
# if str(train_name) in trains_dispatched:
|
|
# print strindex + "train is dispatching trying again" + "trains_dispatched", trains_dispatched:
|
|
# self.waitMsec(500)
|
|
# continue
|
|
# else:
|
|
# print strindex + "train is not dispatching continuing"
|
|
train = trains[train_name]
|
|
previous_edge = train["edge"]
|
|
if self.logLevel > 0: print strindex + "previous_edge " + str(previous_edge)
|
|
penultimate_block_name = train["penultimate_block_name"]
|
|
|
|
previous_block = BlockManager.getBlock(previous_edge.getItem("penultimate_block_name"))
|
|
# print strindex + "previous_block", previous_block.getUserName()
|
|
current_block = BlockManager.getBlock(previous_edge.getItem("last_block_name"))
|
|
# print strindex + "current_block", current_block.getUserName()
|
|
next_block = BlockManager.getBlock(current_edge.getItem("second_block_name"))
|
|
# print strindex + "next_block", next_block.getUserName()
|
|
|
|
previous_direction_from = train["direction"]
|
|
transit_direction = previous_direction_from
|
|
# move_between_stations
|
|
if self.logLevel > 0: print strindex + "previous transit_direction ", transit_direction
|
|
if self.logLevel > 0: print strindex + "setting direction iterno", iter
|
|
[train["direction"], transit_instruction] = self.set_direction(train, previous_block, current_block, next_block, transit_direction, self.index) # get the new train_direction_from
|
|
transit_direction = train["direction"]
|
|
# need to store if we change direction in case we have to redo the command
|
|
if transit_direction != previous_direction_from:
|
|
stored_transit_instruction = "change"
|
|
else:
|
|
stored_transit_instruction = "no_change"
|
|
if self.logLevel > 0: print strindex + "new transit_direction " + transit_direction
|
|
|
|
if self.logLevel > 0: print strindex + "+++++++++++++++++++++++++++"
|
|
if self.logLevel > 0: print strindex + "calling self.move iterno", iter
|
|
result = self.move(e, transit_direction, transit_instruction, train_name, mode, self.index)
|
|
if self.logLevel > 0: print strindex + "called self.move iterno", iter, "result", result
|
|
|
|
# result is True (success) or False (failure)
|
|
# if result is false we will try again as we are in a loop
|
|
|
|
# if we are not scheduling, we will try once before allowing the operator to specify whether we are giving up
|
|
# if we are scheduling we try until the scheduling margin is reached
|
|
|
|
if self.logLevel > 0: print strindex + "returned from self.move, result = ", result
|
|
if result == False:
|
|
# we will repeat, sot put everything back to original state
|
|
if stored_transit_instruction == "change":
|
|
if self.logLevel > 0: print strindex + "reverting changed direction iterno", iter
|
|
if train["direction"] == "forward":
|
|
train["direction"] = "reverse"
|
|
else:
|
|
train["direction"] = "forward"
|
|
if self.logLevel > 0: print strindex + "mode", mode
|
|
if mode == "not_scheduling":
|
|
if iter >= 1: #allow one retry without prompting
|
|
msg = "Failure1 to dispatch train " + train_name + " retrying moving from " + station_from_name + " to " + station_to_name
|
|
title = ""
|
|
opt1 = "try again"
|
|
opt2 = "cancel"
|
|
reply = OptionDialog().customQuestionMessage2str(msg, title, opt1, opt2)
|
|
if opt1:
|
|
iter = 0
|
|
else:
|
|
result = True # break from while loop
|
|
else:
|
|
# print strindex + "--" + self.train_name + " calling doDispatch"
|
|
self.waitMsec(1000) # wait 1 sec
|
|
# wait for the scheduling margin (specified in fast minutes)
|
|
# convert scheduling margin to seconds
|
|
scheduling_margin_sec = int((float(scheduling_margin_gbl) / float(str(fast_clock_rate))) * 60.0) # fast minutes
|
|
# print strindex + "scheduling_margin_sec", scheduling_margin_sec
|
|
if iter > scheduling_margin_sec:
|
|
if self.logLevel > 0: print strindex + "waited", iter+1, "secs, could not schedule train and gave up"
|
|
result = True # break from while loop
|
|
# we do not want to call the next edge in the paths
|
|
call_next_edge_in_paths = False
|
|
else:
|
|
if self.logLevel > 0: print strindex + "waited", iter+1, "secs but could not schedule train", train
|
|
|
|
|
|
# end of while. repeat again if result is false and call dispatch again
|
|
if self.logLevel > 0: print strindex + "called self.move iterno", iter
|
|
if self.logLevel > 0: print strindex + "++++++++++++++++++++++++++++++++++"
|
|
|
|
# store the current edge for next move
|
|
#store current edge information in train
|
|
train["edge"] = e
|
|
train["penultimate_block_name"] = e.getItem("penultimate_block_name")
|
|
# count the paths in
|
|
count_path +=1
|
|
if self.logLevel > 0: print strindex + "transit finished, removing train from dispatch list" + str(trains_dispatched)
|
|
|
|
if str(train_name) in trains_dispatched:
|
|
# print "str(train_name) in trains_dispatched"
|
|
trains_dispatched.remove(str(train_name))
|
|
|
|
if self.logLevel > 0: print strindex + "removed from trains_dispatched", str(trains_dispatched)
|
|
if self.logLevel > 0: print strindex + "&&&&&&&&&&&&&&&&& end move_between_stations &&&&&&&&&&&&&&&&&", self.index
|
|
|
|
def set_direction(self, train, previous_block, current_block, next_block, previous_direction_from, index = 0):
|
|
# global train
|
|
strindex = str(index) + " " * 10 #make debugging easier to understand by indenting
|
|
if self.logLevel > 2: print "set_direction1: previous_direction_from", previous_direction_from
|
|
|
|
# We have two cases for the direction to be changed:
|
|
# 1) we have a back and forth situation where we can check that the previous_block == next_block
|
|
# 2) we reverse and go through a point. there will be no through path from the previous_block to the next next_block
|
|
#
|
|
# these two cases are not exclusive.
|
|
|
|
# print "set_direction"
|
|
transit_instruction = "same"
|
|
if self.logLevel > 0: print strindex + "previous_block", previous_block.getUserName(), "current", current_block.getUserName(), "next", next_block.getUserName()
|
|
if previous_block == next_block:
|
|
if self.logLevel > 0: print strindex + "previous_block == next_block", previous_block == next_block, "so changing direction"
|
|
transit_instruction = "change"
|
|
|
|
# check if current block is a turntable
|
|
for panel in jmri.util.JmriJFrame.getFrameList():
|
|
if isinstance(panel, jmri.jmrit.display.layoutEditor.LayoutEditor):
|
|
for turntable in panel.getLayoutTurntables():
|
|
if turntable.getLayoutBlock() is not None:
|
|
if (turntable.getLayoutBlock().getBlock() == current_block) and (current_block != next_block):
|
|
if self.logLevel > 0: print strindex + "current_block is a turntable, so changing direction"
|
|
transit_instruction = "change"
|
|
break
|
|
|
|
# check if current block is a traverser
|
|
for panel in jmri.util.JmriJFrame.getFrameList():
|
|
if isinstance(panel, jmri.jmrit.display.layoutEditor.LayoutEditor):
|
|
for traverser in panel.getLayoutTraversers():
|
|
if traverser.getLayoutBlock() is not None:
|
|
if (traverser.getLayoutBlock().getBlock() == current_block) and (current_block != next_block):
|
|
# Found the traverser object
|
|
entry_slot_index = -1
|
|
exit_slot_index = -1
|
|
slot_list = traverser.getSlotList()
|
|
for i in range(len(slot_list)):
|
|
slot = slot_list[i]
|
|
ts = slot.getConnect()
|
|
if ts is not None and ts.getLayoutBlock() is not None:
|
|
connected_block = ts.getLayoutBlock().getBlock()
|
|
if connected_block == previous_block: entry_slot_index = i
|
|
if connected_block == next_block: exit_slot_index = i
|
|
if entry_slot_index != -1 and exit_slot_index != -1 and ((entry_slot_index % 2) == (exit_slot_index % 2)):
|
|
if self.logLevel > 0: print strindex + "current_block is a traverser and slots are on the same side, so changing direction"
|
|
transit_instruction = "change"
|
|
break # Found the traverser, no need to check others
|
|
|
|
LayoutBlockManager=jmri.InstanceManager.getDefault(jmri.jmrit.display.layoutEditor.LayoutBlockManager)
|
|
current_layout_block = LayoutBlockManager.getLayoutBlock(current_block)
|
|
|
|
# don't need this as previous block == next block is sufficient
|
|
# if not current_layout_block.validThroughPath(previous_block, next_block):
|
|
# print ("current_layout_block.validThroughPath",
|
|
# current_layout_block.validThroughPath(previous_block, next_block), "so changing direction")
|
|
# transit_instruction = "change"
|
|
|
|
if transit_instruction == "change":
|
|
if previous_direction_from == "forward":
|
|
transit_direction = "reverse"
|
|
else:
|
|
transit_direction = "forward"
|
|
if self.logLevel > 2: print strindex + "set_direction1: transit_direction", transit_direction
|
|
else:
|
|
transit_direction = previous_direction_from
|
|
if self.logLevel > 2: print strindex + "set_direction1: transit_direction2", transit_direction
|
|
train["direction"] = transit_direction
|
|
# print "transit_direction", transit_direction
|
|
previous_direction_from = transit_direction
|
|
return [transit_direction, transit_instruction]
|
|
|
|
def check_train_in_start_block(self, train_to_move, blockName):
|
|
# print "check_train_in_start_block"
|
|
# print "checking " , train_to_move, " in " , blockName
|
|
block = blocks.getBlock(blockName)
|
|
if self.blockOccupied(block):
|
|
# print " block Occupied ", self.blockOccupied(block), " value ", block.getValue()
|
|
if block.getValue() == train_to_move:
|
|
return True
|
|
else:
|
|
startBlock = block.getUserName()
|
|
# print "trying to move from blockName" , blockName, "but not occupied by", "train_to_move", train_to_move
|
|
blockName = [block.getUserName() for block in blocks.getNamedBeanSet() if block.getValue() == train_to_move]
|
|
if blockName != []:
|
|
blockName = blockName[0]
|
|
# print "train", train_to_move, "actually in" , blockName
|
|
return False
|
|
else:
|
|
blockName = "train not in any block"
|
|
#as the block
|
|
block.setValue(train_to_move)
|
|
# print "train", train_to_move, "reset in" , blockName
|
|
return True
|
|
else:
|
|
# print "train_to_move", train_to_move, "not in" , blockName
|
|
blockName = [block for block in blocks.getNamedBeanSet() if block.getValue() == train_to_move]
|
|
if blockName != []:
|
|
blockName = blockName[0]
|
|
else:
|
|
blockName = "train not in any block"
|
|
# print "train_to_move", train_to_move, "in" , blockName
|
|
return False
|
|
|
|
def blockOccupied(self, block):
|
|
# print "blockOccupied"
|
|
if block.getState() == ACTIVE:
|
|
state = True
|
|
else:
|
|
state = False
|
|
return state
|
|
|
|
def get_time_to_stop_in_station(self, edge, direction):
|
|
|
|
if direction == "forward":
|
|
filename_fwd = self.get_filename(edge, "fwd")
|
|
trainInfo_fwd = jmri.jmrit.dispatcher.TrainInfoFile().readTrainInfo(filename_fwd)
|
|
if trainInfo_fwd is None:
|
|
OptionDialog().displayMessage("Route graph out of date. Regenerate Dispatcher System")
|
|
return 0
|
|
# print "type trainInfo_fwd", type (trainInfo_fwd)
|
|
station_wait_time = trainInfo_fwd.getWaitTime()
|
|
else:
|
|
filename_rvs = self.get_filename(edge, "rvs")
|
|
# print "filename_rvs", filename_rvs, "edge", edge
|
|
trainInfo_rvs = jmri.jmrit.dispatcher.TrainInfoFile().readTrainInfo(filename_rvs)
|
|
if trainInfo_rvs is None:
|
|
OptionDialog().displayMessage("Route graph out of date. Regenerate Dispatcher System")
|
|
return 0
|
|
# print "type trainInfo_rvs", type (trainInfo_rvs)
|
|
station_wait_time = trainInfo_rvs.getWaitTime()
|
|
if station_wait_time != None:
|
|
return math.floor(float(station_wait_time+0)) * 1000 # set in milli secs
|
|
else:
|
|
return 0
|
|
|
|
def is_integer(self, n):
|
|
try:
|
|
if n == None: return False
|
|
float(n)
|
|
except ValueError:
|
|
return False
|
|
else:
|
|
return float(n).is_integer()
|
|
|
|
def announce1(self, e, direction, instruction, train):
|
|
# print "announce1"
|
|
to_name = e.getTarget()
|
|
from_name = e.getSource()
|
|
speech_reqd = self.speech_required_flag()
|
|
self.announce( from_name, to_name, speech_reqd, direction, instruction)
|
|
|
|
def move(self, e, direction, instruction, train_name, mode="not_scheduling" , index = 0):
|
|
strindex = str(index) + " " * 10 # make debugging easier to understand by indenting
|
|
# print strindex +"move"
|
|
if self.logLevel > 0: print strindex +"++++++++++++++++++++++++"
|
|
if self.logLevel > 0: print strindex +"path" , e
|
|
if self.logLevel > 0: print strindex +"calling move: Target", e.getTarget(), "Source", e.getSource(),"Train", train_name
|
|
if self.logLevel > 0: print strindex +"++++++++++++++++++++++++"
|
|
to_name = e.getTarget()
|
|
from_name = e.getSource()
|
|
sensor_move_name = "MoveInProgress"+to_name.replace(" ","_")
|
|
|
|
self.set_sensor(sensor_move_name, "active")
|
|
speech_reqd = self.speech_required_flag()
|
|
#self.announce( from_name, to_name, speech_reqd, direction, instruction) # now done when train arrives in platfor instead of when leaving
|
|
if self.logLevel > 0: print strindex +"calling move", train, from_name, to_name
|
|
|
|
if mode == "not_scheduling":
|
|
self.waitMsec(1000) # wait for train to stop dispatching we don't want to start another train before it has stopped properly
|
|
if self.train_is_dispatching(train_name, index):
|
|
self.wait_till_train_stops_dispatching(train_name, index)
|
|
if self.logLevel > 0: print strindex + "waited till train stops dispatching, trying again with new position"
|
|
# print strindex + "train is dispatching, trying again with new position"
|
|
# self.waitMsec(500)
|
|
return False
|
|
else:
|
|
if self.logLevel > 0: print strindex + "train is not dispatching"
|
|
else:
|
|
if self.logLevel > 0: print "train is scheduling"
|
|
|
|
# if mode == "scheduling":
|
|
# waited_till_train_stops_dispatching = self.wait_till_train_stops_dispatching(train_name, index) #it might be already doing a dispatch
|
|
# if waited_till_train_stops_dispatching:
|
|
# # need to try again with new train position
|
|
# print strindex +"waited_till_train_stops_dispatching not calling dispatch"
|
|
# return False
|
|
|
|
if self.logLevel > 0: print strindex +"calling dispatch"
|
|
if self.logLevel > 0: print strindex + "trains_dispatched", trains_dispatched
|
|
|
|
result = self.call_dispatch(e, direction, train_name, mode, index)
|
|
if self.logLevel > 0: print strindex +"exit call_dispatch" , result
|
|
if self.logLevel > 0: print strindex + "trains_dispatched", trains_dispatched
|
|
self.set_sensor(sensor_move_name, "inactive")
|
|
if result == True:
|
|
# print strindex +"result from calling move is True!!", train, from_name, to_name
|
|
# Wait for the Active Trains List to not have the train we wish to start in it
|
|
self.wait_till_train_stops_dispatching(train_name, index)
|
|
self.set_sensor(sensor_move_name, "inactive")
|
|
self.report_train_state(train_name) # just for debugging
|
|
if self.logLevel > 0: print strindex +("+++++ sensor " + sensor_move_name + " inactive")
|
|
else:
|
|
# print strindex +"result from calling move is False!!", train, from_name, to_name
|
|
self.set_sensor(sensor_move_name, "inactive")
|
|
if self.logLevel > 0: print strindex +"****** finished moving train: called move *******"
|
|
return result
|
|
|
|
def report_train_state(self, train_name):
|
|
train = trains[train_name]
|
|
direction = train["direction"]
|
|
if self.logLevel > 1: print "train direction" , direction
|
|
|
|
|
|
def train_is_dispatching(self, train_name, index):
|
|
strindex = str(index) + " " * 10 #make debugging easier to understand by indenting
|
|
if self.logLevel > 0: print strindex + "checking if train is dispatching", train_name
|
|
DF = jmri.InstanceManager.getDefault(jmri.jmrit.dispatcher.DispatcherFrame)
|
|
java_active_trains_list = DF.getActiveTrainsList()
|
|
java_active_trains_Arraylist= java.util.ArrayList(java_active_trains_list)
|
|
active_train_names_list = [str(t.getTrainName()) for t in java_active_trains_Arraylist]
|
|
if train_name in active_train_names_list:
|
|
return True
|
|
else:
|
|
return False
|
|
|
|
def wait_till_train_stops_dispatching(self, train_name, index = 0):
|
|
strindex = str(index) + " " * 10 #make debugging easier to understand by indenting
|
|
# print strindex + "wait_till_train_stops_dispatching", train_name
|
|
DF = jmri.InstanceManager.getDefault(jmri.jmrit.dispatcher.DispatcherFrame)
|
|
java_active_trains_list = DF.getActiveTrainsList()
|
|
java_active_trains_Arraylist= java.util.ArrayList(java_active_trains_list)
|
|
active_train_names_list = [str(t.getTrainName()) for t in java_active_trains_Arraylist]
|
|
while train_name in active_train_names_list:
|
|
self.waitMsec(500)
|
|
# print strindex + train_name + "in active train list"
|
|
java_active_trains_list = DF.getActiveTrainsList()
|
|
java_active_trains_Arraylist= java.util.ArrayList(java_active_trains_list)
|
|
active_train_names_list = [str(t.getTrainName()) for t in java_active_trains_Arraylist]
|
|
if self.logLevel > 0: print (strindex + "+++++ train " + train_name + " stopped dispatching" )
|
|
return
|
|
|
|
def speech_required_flag(self):
|
|
# print "speech_required_flag"
|
|
self.sound_sensor = sensors.getSensor("soundSensor")
|
|
if self.sound_sensor is None:
|
|
OptionDialog().displayMessage("No sound Sensor set up")
|
|
return None
|
|
sound_state = self.sound_sensor.getKnownState()
|
|
if self.logLevel > 1: print sound_state,ACTIVE
|
|
if sound_state == ACTIVE:
|
|
sound_flag = True
|
|
else:
|
|
sound_flag = False
|
|
return sound_flag
|
|
|
|
def call_dispatch(self, e, direction, train, mode="not_scheduling", index = 0):
|
|
global scheduling_margin_gbl, fast_clock_rate
|
|
global check_action_route_flag
|
|
global check_route_flag
|
|
global trains_dispatched
|
|
|
|
strindex = str(index) + " " * 15 #make debugging easier to understand by indenting
|
|
if self.logLevel > 0: print strindex + "+++++++++++++++call_dispatch++++++++++++++++ mode:", train, mode
|
|
# for information only
|
|
if self.logLevel > 1: print strindex + " in dispatch"
|
|
to_name = e.getTarget()
|
|
from_name = e.getSource()
|
|
if self.logLevel > 1: print ("in call_dispatch: move from " + from_name + " to " + to_name)
|
|
|
|
# set traininfo filename
|
|
if direction == "forward":
|
|
filename = self.get_filename(e, "fwd")
|
|
else:
|
|
filename = self.get_filename(e, "rvs")
|
|
if self.logLevel > 1: print strindex + "filename = ", filename, "direction = " , direction
|
|
# print strindex + "call_dispatch a"
|
|
check_route_active_flag = sensors.getSensor("checkRouteSensor").getKnownState()
|
|
if check_route_active_flag == ACTIVE:
|
|
check_route_flag = True
|
|
else:
|
|
check_route_flag = False
|
|
if self.logLevel > 0: print strindex + "check_route_flag", check_route_flag
|
|
# initialise globals to False if not set
|
|
if 'check_action_route_flag' not in globals():
|
|
check_action_route_flag = False
|
|
|
|
# wait for blocks to be clear before allocating (if required)
|
|
if check_route_flag == True or check_action_route_flag == True: # can ask for route to be checked globally or in action
|
|
# print strindex + "call_dispatch b1"
|
|
# print strindex + "checking route is clear", from_name
|
|
self.wait_route_is_clear(filename, from_name, train)
|
|
t = trains[train] #train is train_name
|
|
t["allocating"] = True
|
|
|
|
if self.logLevel > 0: print self.train_name, "route", filename, "is clear"
|
|
|
|
if self.logLevel > 0: print strindex + "appending trains_dispatched", trains_dispatched
|
|
if str(train) not in trains_dispatched: #have to checl because added each transit of route
|
|
trains_dispatched.append(str(train))
|
|
if self.logLevel > 0: print strindex + "trains_dispatched", trains_dispatched
|
|
# run dispatch
|
|
if self.logLevel > 0: print strindex + "%%%%%%%%%calling doDispatch"
|
|
result = self.doDispatch(filename, "ROSTER", train, mode, index)
|
|
if self.logLevel > 0: print strindex + "%%%%%%%%%exiting doDispatch A"
|
|
if self.logLevel > 0: print strindex + "trains_dispatched", trains_dispatched
|
|
|
|
# # when scheduling the dispatch is normally not called until the previous dispatch is complete
|
|
# # we will keep this in for now even though better in calling routine
|
|
# # definitely cannot recall doDispatch from here in non-scheduling mode
|
|
#
|
|
# if mode != "not_scheduling and result == False": # i.e. if scheduling
|
|
# print strindex + "scheduling mode code"
|
|
# print strindex + "mode" , mode
|
|
# # keep repeating until the scheduling margin is reached
|
|
# iter = 0
|
|
# while result == False:
|
|
# # print strindex + "--" + self.train_name + " calling doDispatch"
|
|
# self.waitMsec(1000) # wait 1 sec
|
|
# # wait for the scheduling margin (specified in fast minutes)
|
|
# # convert scheduling margin to seconds
|
|
# scheduling_margin_sec = int((float(scheduling_margin_gbl) / float(str(fast_clock_rate))) * 60.0) # fast minutes
|
|
# # print strindex + "scheduling_margin_sec", scheduling_margin_sec
|
|
# if iter > scheduling_margin_sec:
|
|
# if self.logLevel > 0: print strindex + "waited", iter+1, "secs, could not schedule train and gave up"
|
|
# return result
|
|
# else:
|
|
# if self.logLevel > 0: print strindex + "waited", iter+1, "secs but could not schedule train", train
|
|
#
|
|
# result = self.doDispatch(filename, "ROSTER", train, mode, index)
|
|
# if self.logLevel > 0: print strindex + "exiting doDispatch B"
|
|
# iter += 1
|
|
|
|
#return result
|
|
if self.logLevel > 0: print strindex + "+++++++++++++exit call_dispatch+++++++++++++++++ result", result
|
|
if self.logLevel > 0: print strindex + "trains_dispatched", trains_dispatched
|
|
return result
|
|
|
|
def initialise_if_not_set(self, global_name, state):
|
|
if 'global_name' not in globals():
|
|
global_name = state
|
|
|
|
def get_filename(self, e, suffix):
|
|
|
|
# print "get_filename"
|
|
|
|
# suffix is "fwd" or "rvs"
|
|
# e is edge
|
|
|
|
from_station_name = g.g_express.getEdgeSource(e)
|
|
to_station_name = g.g_express.getEdgeTarget(e)
|
|
neighbor_name = e.getItem("neighbor_name")
|
|
index = e.getItem("index")
|
|
|
|
filename = "From " + str(from_station_name) + " To " + str(to_station_name) + " Via " + str(neighbor_name) + " " + str(index)
|
|
filename = filename.replace(" ", "_")
|
|
filename = filename + "_" + suffix + ".xml"
|
|
|
|
return filename
|
|
|
|
# Dispatch (<filename.xml>, [USER | ROSTER | OPERATIONS >,<dccAddress, RosterEntryName or Operations>
|
|
|
|
def doDispatch(self, traininfoFileName, type, train_name, mode = "not_scheduling", index = 0):
|
|
global trains_dispatched
|
|
strindex = str(index) + " " * 20 #make debugging easier to understand by indenting
|
|
|
|
if self.logLevel > 0: print strindex + "doDispatch"
|
|
if self.logLevel > 0: print strindex + "trains_dispatched", trains_dispatched
|
|
|
|
DF = jmri.InstanceManager.getDefault(jmri.jmrit.dispatcher.DispatcherFrame)
|
|
if self.logLevel > 1: print strindex + "traininfoFileName",traininfoFileName
|
|
if train_name in trains:
|
|
train = trains[train_name]
|
|
else:
|
|
if self.logLevel > 0: print strindex + "train", train_name , "cannot be dispatched", "trains", trains
|
|
return False
|
|
self.trainInfo = jmri.jmrit.dispatcher.TrainInfoFile().readTrainInfo(traininfoFileName)
|
|
self.modify_trainInfo(train_name) # sets the speed factor and other train dependent factors
|
|
transit_name = self.trainInfo.getTransitName()
|
|
self.transit_name = transit_name # allow calling routine to use transit_name
|
|
#print strindex + "traininfoFileName", traininfoFileName
|
|
jmri.jmrit.dispatcher.TrainInfoFile().writeTrainInfo(self.trainInfo, traininfoFileName)
|
|
# print strindex + "__" + train_name + " calling loadTrainFromTrainInfo"
|
|
# print strindex + "DF.dispatcherSystemSchedulingInOperation before", DF.dispatcherSystemSchedulingInOperation
|
|
DF.dispatcherSystemSchedulingInOperation = True # to inhibit error message when train started but not in station
|
|
# print strindex + "DF.dispatcherSystemSchedulingInOperation", DF.dispatcherSystemSchedulingInOperation
|
|
if mode != "not_scheduling": # == scheduling
|
|
# if self.logLevel > 0: print strindex + "__________________________Start__" + self.train_name + "__transit: " + transit_name
|
|
if self.logLevel > 0: print "__________________________Start__" + self.train_name + "__transit: " + transit_name
|
|
else:
|
|
if self.logLevel > 0: print strindex + "_Start__" + self.train_name + "__transit: " + transit_name
|
|
|
|
|
|
# run the train, setting the flag that the train is doing a dispatch
|
|
result = DF.loadTrainFromTrainInfo(self.trainInfo, type, train_name)
|
|
if self.logLevel > 0: print strindex + "loaded returning with code ", result
|
|
if self.logLevel > 0: print strindex + "trains_dispatched", trains_dispatched
|
|
if result == 0:
|
|
# print strindex + "--" + self.train_name + " called doDispatch; transit name: " + transit_name
|
|
self.set_whether_to_stop_at_sensor(DF)
|
|
train["allocating"] = False # this flag is used when checking to see whether path for dispatch is clear
|
|
if result == -1:
|
|
if self.logLevel > 0: print strindex + "did not run train ", train_name , "aborting: result from loading train:" , result
|
|
|
|
# did not work properly
|
|
|
|
# # delete the transit so can try loading the transit again
|
|
# self.trainInfo = jmri.jmrit.dispatcher.TrainInfoFile().readTrainInfo(traininfoFileName)
|
|
# transit_name = self.trainInfo.getTransitName()
|
|
# active_train_list = [active_train for active_train in DF.getActiveTrainsList() \
|
|
# if active_train.getTransitName() == transit_name]
|
|
# if active_train_list == []:
|
|
# active_train = None
|
|
# else:
|
|
# active_train = active_train_list[0]
|
|
# print strindex + "terminating active_train", active_train, "train", train_name, "active_train_list", active_train_list
|
|
# DF.terminateActiveTrain(active_train, True, False)
|
|
# if train_name in trains:
|
|
# trains.pop(train_name)
|
|
return False #No train allocated
|
|
else:
|
|
DF = None
|
|
if mode != "not_scheduling": # == scheduling
|
|
if self.logLevel > 0: print strindex + "__________________________End____" + self.train_name + "__transit: " + transit_name
|
|
else:
|
|
if self.logLevel > 0: print strindex + "_End____" + self.train_name + "__transit: " + transit_name
|
|
return True
|
|
|
|
def get_train_length(self, new_train_name):
|
|
|
|
# print "get_train_length"
|
|
|
|
EngineManager=jmri.InstanceManager.getDefault(jmri.jmrit.operations.rollingstock.engines.EngineManager)
|
|
engineRoad = "Set by Dispatcher System"
|
|
engineNumber = new_train_name
|
|
engine = EngineManager.newRS(engineRoad, engineNumber)
|
|
# get the current length of the engine
|
|
default = "10"
|
|
current_length = engine.getLength()
|
|
if current_length == "0":
|
|
current_length = default
|
|
return [engine, current_length]
|
|
|
|
def get_train_speed_factor(self, new_train_name):
|
|
|
|
# print "get_train_speed_factor"
|
|
EngineManager=jmri.InstanceManager.getDefault(jmri.jmrit.operations.rollingstock.engines.EngineManager)
|
|
engineRoad = "Set by Dispatcher System"
|
|
engineNumber = new_train_name
|
|
engine = EngineManager.newRS(engineRoad, engineNumber)
|
|
# get the current speed factor of the engine
|
|
default = "100" # percentage
|
|
comment = engine.getComment()
|
|
split_comment = []
|
|
if "speed factor" in comment:
|
|
split_comment = comment.split(" ")
|
|
index = split_comment.index("speed")
|
|
# print "len(split_comment)", len(split_comment), "index + 2", index + 2
|
|
if len(split_comment) > index + 2:
|
|
speed_factor = split_comment[index+2]
|
|
else:
|
|
speed_factor = default
|
|
else:
|
|
speed_factor = default
|
|
return [engine, speed_factor]
|
|
|
|
def get_stopping_length_fraction(self):
|
|
|
|
transit_name = self.trainInfo.getTransitName()
|
|
# this has _fwd or _rvs at end. Remove these to get edge
|
|
edge = transit_name.replace("_fwd","").replace("rvs", "")
|
|
# trainInfo_fwd = jmri.jmrit.dispatcher.TrainInfoFile().readTrainInfo(filename_fwd)
|
|
# filename_fwd = self.get_filename(edge, "fwd")
|
|
dm = DispatchMaster()
|
|
last_section = dm.last_section_of_transit(self.trainInfo)
|
|
length_of_last_section = float(dm.length_of_last_section(last_section))/10.0 # length in cm
|
|
overall_stopping_position = ResetButtonMaster().get_overall_stopping_distance()
|
|
[_, individual_stopping_position] = dm.get_stopping_position(edge)
|
|
# the stopping position is made up of one for a particular transit
|
|
# plus an overall one affecting all transits
|
|
total_stopping_position = individual_stopping_position + overall_stopping_position
|
|
stopping_length_fraction = 1.0-(float(total_stopping_position)/float(length_of_last_section))
|
|
return stopping_length_fraction
|
|
|
|
|
|
def modify_trainInfo(self, train_name):
|
|
|
|
# print "modify_trainInfo"
|
|
|
|
# setTrainLengthUnits to scalemetres
|
|
tlu = jmri.jmrit.dispatcher.ActiveTrain(None,None,0).TrainLengthUnits
|
|
# x = tlu.TRAINLENGTH_SCALEMETERS
|
|
# print "TRAINLENGTH_SCALEMETERS= ", x
|
|
self.trainInfo.setTrainLengthUnits(tlu.TRAINLENGTH_SCALEMETERS) #scale metres
|
|
|
|
# setMaxTrainLength (in scale metres)
|
|
[engine,current_length] = self.get_train_length(train_name) #get the engine name
|
|
self.trainInfo.setMaxTrainLengthScaleMeters(float(current_length))
|
|
|
|
# setSpeedFactor
|
|
# print "in modify_trainInfo1 "
|
|
[engine,current_speed_factor] = self.get_train_speed_factor(train_name)
|
|
# print "in modify_trainInfo2 ", current_speed_factor
|
|
speedFactor = float(current_speed_factor)/100.0
|
|
# print "in modify_trainInfo2 speedFactor", speedFactor
|
|
# print "in modify_trainInfo2 a"
|
|
if speedFactor >= 2 or speedFactor <=0:
|
|
speedFactor = 1
|
|
msg = "speedFactor set is out of range " + str(current_speed_factor) + "\nSpeed Factor set to 100% " + "for train " + train_name
|
|
OptionDialog().displayMessage(msg)
|
|
self.trainInfo.setSpeedFactor(float(speedFactor))
|
|
|
|
# set the stopbyspeedprofileadjust (stopping length)
|
|
stopbyspeedprofileadjust = self.get_stopping_length_fraction()
|
|
self.trainInfo.setStopBySpeedProfileAdjust(stopbyspeedprofileadjust)
|
|
|
|
# setMinReliableOperatingSpeed
|
|
percentage = 10.0
|
|
self.trainInfo.setMinReliableOperatingSpeed(percentage/100)
|
|
|
|
# set wait for block to be clear before running transit
|
|
transit_name = self.trainInfo.getTransitName()
|
|
folder = "restrictTransits"
|
|
filename = "restrictTransits.txt"
|
|
restricted_transits = DispatchMaster().read_list(folder,filename)
|
|
if restricted_transits[0] != "":
|
|
filtered_restricted_transits = [ t for t in restricted_transits if t[0] == transit_name]
|
|
if filtered_restricted_transits != []:
|
|
[transit_name1, transit_block_name] = filtered_restricted_transits
|
|
trainInfo_fwd.setBlockName(new_transit_block_name)
|
|
|
|
if self.logLevel > 0: print "self.forward_stopping_sensor_exists(self.trainInfo)",self.forward_stopping_sensor_exists(self.trainInfo)
|
|
# print "sensors.getSensor('stopAtStopSensor').getKnownState()", sensors.getSensor("stopAtStopSensor").getKnownState(), ACTIVE
|
|
|
|
def set_whether_to_stop_at_sensor(self, DF):
|
|
|
|
# print "set_whether_to_stop_at_sensor"
|
|
|
|
transit_name = self.trainInfo.getTransitName()
|
|
if self.logLevel > 0: print "transit_name", transit_name
|
|
active_train_list = [active_train for active_train in DF.getActiveTrainsList() \
|
|
if active_train.getTransitName() == transit_name]
|
|
if self.logLevel > 0: print "active_train_list", active_train_list
|
|
|
|
active_train = active_train_list[0]
|
|
if self.logLevel > 0: print "active_train", active_train
|
|
autoActiveTrain = active_train.getAutoActiveTrain()
|
|
if self.forward_stopping_sensor_exists(self.trainInfo):
|
|
if self.logLevel > 0: print "forward_stopping_sensor_exists"
|
|
# set default
|
|
if sensors.getSensor("stopAtStopSensor").getKnownState() == ACTIVE:
|
|
if self.logLevel > 0: print "stop at stop sensor active", sensors.getSensor("stopAtStopSensor").getKnownState(), ACTIVE
|
|
autoActiveTrain.set_useStopSensor(True)
|
|
else:
|
|
if self.logLevel > 0: print "stop at stop sensor inactive", sensors.getSensor("stopAtStopSensor").getKnownState(), INACTIVE
|
|
if self.logLevel > 0: print "before", self.trainInfo.getStopBySpeedProfile(), self.trainInfo.getUseSpeedProfile()
|
|
autoActiveTrain.set_useStopSensor(False)
|
|
# overwrite with set values
|
|
if self.stop_mode is None or self.stop_mode == "" or self.stop_mode == "Use Default":
|
|
if self.logLevel > 0: print "Use Defailt"
|
|
pass
|
|
elif self.stop_mode == "Use Stop Sensor":
|
|
autoActiveTrain.set_useStopSensor(True)
|
|
if self.logLevel > 0: print "set stop sensor True"
|
|
elif self.stop_mode == "Use Speed Profile":
|
|
autoActiveTrain.set_useStopSensor(False)
|
|
if self.logLevel > 0: print "set_useStopSensor False"
|
|
else:
|
|
print "ERROR incorrect value for stop mode"
|
|
else:
|
|
if self.logLevel > 0: print "forward_stopping_sensor does not exist"
|
|
|
|
def forward_stopping_sensor_exists(self, traininfo):
|
|
|
|
# print "forward_stopping_sensor_exists"
|
|
|
|
transit_name = traininfo.getTransitId()
|
|
transit = transits.getTransit(transit_name)
|
|
transit_section_list = transit.getTransitSectionList()
|
|
section_list = transit.getSectionListBySeq(transit.getMaxSequence())
|
|
section = section_list[0]
|
|
forward_stopping_sensor = section.getForwardStoppingSensor()
|
|
if forward_stopping_sensor != None:
|
|
return True
|
|
else:
|
|
return False
|
|
def set_sensor(self, sensorName, sensorState):
|
|
sensor = sensors.getSensor(sensorName)
|
|
if sensor is None:
|
|
self.displayMessage('{} - Sensor {} not found'.format(self.threadName, sensorName))
|
|
return
|
|
if sensorState == 'active':
|
|
newState = ACTIVE
|
|
elif sensorState == 'inactive':
|
|
if self.logLevel > 1: print "set_sensor ", sensorName, 'inactive'
|
|
newState = INACTIVE
|
|
else:
|
|
self.displayMessage('{} - Sensor state, {}, is not valid'.format(self.threadName, sensorState))
|
|
sensor.setKnownState(newState)
|
|
return
|
|
|
|
def wait_sensor(self, sensorName, sensorState):
|
|
|
|
# print "wait_sensor"
|
|
|
|
sensor = sensors.getSensor(sensorName)
|
|
if sensor is None:
|
|
self.displayMessage('{} - Sensor {} not found'.format(self.threadName, sensorName))
|
|
return
|
|
if sensorState == 'active':
|
|
self.waitSensorActive(sensor)
|
|
elif sensorState == 'inactive':
|
|
self.waitSensorInactive(sensor)
|
|
else:
|
|
self.displayMessage('{} - Sensor state, {}, is not valid'.format(self.threadName, sensorState))
|
|
|
|
## ***********************************************************************************
|
|
|
|
## sound routines
|
|
|
|
## ***********************************************************************************
|
|
|
|
def getOperatingSystem(self):
|
|
#detecting the operating system using `os.name` System property
|
|
os = java.lang.System.getProperty("os.name")
|
|
os = os.lower()
|
|
if "win" in os:
|
|
return "WINDOWS"
|
|
elif "nix" in os or "nux" in os or "aix" in os:
|
|
return "LINUX"
|
|
elif "mac" in os:
|
|
return "MAC"
|
|
return None
|
|
|
|
def speak(self, msg):
|
|
os = self.getOperatingSystem()
|
|
if os == "WINDOWS":
|
|
self.speak_windows(msg)
|
|
elif os == "LINUX":
|
|
self.speak_linux(msg)
|
|
elif os == "MAC":
|
|
self.speak_mac(msg)
|
|
|
|
def speak_windows(self,msg) :
|
|
try:
|
|
cmd1 = "Add-Type -AssemblyName System.Speech"
|
|
cmd2 = '$SpeechSynthesizer = New-Object -TypeName System.Speech.Synthesis.SpeechSynthesizer'
|
|
cmd3 = "$SpeechSynthesizer.Speak('" + msg + "')"
|
|
cmd = cmd1 + ";" + cmd2 + ";" + cmd3
|
|
os.system("powershell " + cmd )
|
|
except:
|
|
msg = "Announcements not working \n Only supported on windows versions with powershell and SpeechSynthesizer"
|
|
JOptionPane.showMessageDialog(None, msg, "Warning", JOptionPane.WARNING_MESSAGE)
|
|
|
|
def speak_mac(self, msg):
|
|
try:
|
|
java.lang.Runtime.getRuntime().exec("say {}".format(msg))
|
|
except:
|
|
msg = "Announcements not working \n say not working on your Mac"
|
|
JOptionPane.showMessageDialog(None, msg, "Warning", JOptionPane.WARNING_MESSAGE)
|
|
|
|
def speak_linux(self, msg):
|
|
try:
|
|
#os.system("""echo %s | spd-say -e -w -t male1""" % (msg,))
|
|
#os.system("""echo %s | spd-say -e -w -t female3""" % (msg,))
|
|
#os.system("""echo %s | spd-say -e -w -t child_male""" % (msg,))
|
|
os.system("""echo %s | spd-say -e -w -t child_female""" % (msg,)) #slightly slower
|
|
except:
|
|
msg = "Announcements not working \n spd-say not set up on your linux system"
|
|
JOptionPane.showMessageDialog(None, msg, "Warning", JOptionPane.WARNING_MESSAGE)
|
|
|
|
def announce(self, fromblockname, toblockname, speak_on, direction, instruction):
|
|
|
|
# print "announce"
|
|
|
|
from_station = self.get_station_name(fromblockname)
|
|
to_station = self.get_station_name(toblockname)
|
|
|
|
if speak_on == True:
|
|
if direction == "forward":
|
|
platform = " platform 1 "
|
|
else:
|
|
platform = " platform 2 "
|
|
self.speak("The train in" + platform + " is due to depart to " + to_station)
|
|
#self.speak("The train in "+ from_station + " is due to depart to " + to_station )
|
|
|
|
def get_station_name(self, block_name):
|
|
|
|
# print "get_station_name"
|
|
|
|
BlockManager = jmri.InstanceManager.getDefault(jmri.BlockManager)
|
|
block = BlockManager.getBlock(block_name)
|
|
comment = block.getComment()
|
|
# % is the delimeter for block name
|
|
delimeter = '"'
|
|
if delimeter in comment:
|
|
station_name = self.get_substring_between_delimeters(comment, delimeter)
|
|
else:
|
|
station_name = block_name
|
|
return station_name
|
|
|
|
|
|
|
|
def get_substring_between_delimeters(self, comment, delimeter):
|
|
start = delimeter
|
|
end = delimeter
|
|
s = comment
|
|
substring = s[s.find(start)+len(start):s.rfind(end)]
|
|
return substring
|
|
|
|
|
|
def bell(self, bell_on = "True"):
|
|
|
|
# print "bell"
|
|
|
|
if bell_on == "True":
|
|
snd = jmri.jmrit.Sound("resources/sounds/Bell.wav")
|
|
snd.play()
|
|
|
|
def do_not_start_trains_simultaneously(self):
|
|
|
|
# print "do_not_start_trains_simultaneously"
|
|
|
|
global time_last_train
|
|
time_now = int(round(time.time() * 1000))
|
|
time_train = math.max(time_now,time_last_train)
|
|
time_to_wait = time_train - time_now
|
|
time_last_train = time_train + 1000 #store the time this train will start
|
|
self.waitMsec(time_to_wait) #make this train wait for 1 sec after previous train
|
|
|
|
def wait_route_is_clear(self, traininfoFileName, startBlockName, train):
|
|
|
|
route_is_occupied = True # occupied
|
|
i = 0
|
|
while route_is_occupied : #require 1 occurrences of route not occupied
|
|
i = i+1
|
|
route_is_occupied = \
|
|
self.check_route_is_allocated_or_occupied(traininfoFileName, startBlockName)
|
|
if route_is_occupied:
|
|
if i == 1: print train, "waiting for route", traininfoFileName, "to be clear"
|
|
self.waitMsec(1000)
|
|
|
|
|
|
def check_route_is_allocated_or_occupied(self, traininfoFileName, startBlockName):
|
|
|
|
# print "check_route_is_allocated_or_occupied"
|
|
|
|
[transit_name, transit_id] = self.get_transit(traininfoFileName)
|
|
|
|
TransitManager = jmri.InstanceManager.getDefault(jmri.TransitManager)
|
|
transit = TransitManager.getTransit(transit_name)
|
|
if self.logLevel > 0: print "transit_name", transit_name, "transit_id", transit_id
|
|
block_list = [block for block in transit.getInternalBlocksList() if block.getUserName() != startBlockName]
|
|
if self.logLevel > 0: print "block_list", [block.getUserName() for block in block_list]
|
|
route_is_occupied = False
|
|
|
|
#add the block that must be clear for the transit to run
|
|
trainInfo = jmri.jmrit.dispatcher.TrainInfoFile().readTrainInfo(traininfoFileName)
|
|
transit_block_name = trainInfo.getBlockName()
|
|
if transit_block_name != "":
|
|
transit_block = blocks.getBlock(transit_block_name)
|
|
# print "appending", transit_block_name, transit_block
|
|
block_list.append(transit_block)
|
|
|
|
index = 0
|
|
for block in block_list:
|
|
index += 1
|
|
#getValue is set if the track is occupied
|
|
if block.getSensor().getKnownState() == ACTIVE: # check if block is occupied
|
|
route_is_occupied = True
|
|
if self.logLevel > 0: print block.getUserName() , "is not clear value =", block.getSensor().getKnownState(), index
|
|
break
|
|
else:
|
|
if self.logLevel > 0: print block.getUserName() , "is clear value =", block.getSensor().getKnownState(), index
|
|
# getExtraColor is set if the block is allocated
|
|
LayoutBlockManager=jmri.InstanceManager.getDefault(jmri.jmrit.display.layoutEditor.LayoutBlockManager)
|
|
layoutBlock = LayoutBlockManager.getLayoutBlock(block)
|
|
if layoutBlock.getUseExtraColor():
|
|
route_is_occupied = True
|
|
if self.logLevel > 0: print block.getUserName() , "is not clear (extracolor) value =", block.getSensor().getKnownState(), index
|
|
break
|
|
if self.logLevel > 0: print "route_is_occupied", route_is_occupied; print
|
|
|
|
# DF = jmri.InstanceManager.getDefault(jmri.jmrit.dispatcher.DispatcherFrame)
|
|
# java_active_trains_list = DF.getActiveTrainsList()
|
|
# java_active_trains_Arraylist= java.util.ArrayList(java_active_trains_list)
|
|
# active_train_names_list = [str(t.getTrainName()) for t in java_active_trains_Arraylist]
|
|
# if self.logLevel > 0: print "active_train_names_list", active_train_names_list
|
|
# for train_name in active_train_names_list:
|
|
# # print "trains", trains
|
|
# # print "train_name", train_name
|
|
# train = trains[train_name]
|
|
# if train["allocating"] == True:
|
|
# route_is_occupied = True # only allow one dispatch to be set up at a time else this routine does not work
|
|
# # we don't want to check that the route is clear, and then have an allocation take place immediately after
|
|
|
|
# print "route_is_occupied state is:", route_is_occupied
|
|
return route_is_occupied
|
|
|
|
def set_route_allocated(self, traininfoFileName, startBlockName):
|
|
|
|
# print "set_route_allocated"
|
|
|
|
[transit_name, transit_id] = self.get_transit(traininfoFileName)
|
|
TransitManager = jmri.InstanceManager.getDefault(jmri.TransitManager)
|
|
transit = TransitManager.getTransit(transit_name)
|
|
if self.logLevel > 0: print "transit_name", transit_name, "transit_id", transit_id
|
|
block_list = [block for block in transit.getInternalBlocksList() if block.getUserName() != startBlockName]
|
|
for block in block_list:
|
|
# getExtraColor is set if the block is allocated
|
|
LayoutBlockManager=jmri.InstanceManager.getDefault(jmri.jmrit.display.layoutEditor.LayoutBlockManager)
|
|
layoutBlock = LayoutBlockManager.getLayoutBlock(block)
|
|
layoutBlock.setUseExtraColor(True)
|
|
if self.train_name == "shunter": print " ",
|
|
if self.logLevel > 0: print "allocated route", traininfoFileName
|
|
|
|
def get_transit(self, filename):
|
|
|
|
# print "get_transit"
|
|
|
|
trainInfo = jmri.jmrit.dispatcher.TrainInfoFile().readTrainInfo(filename)
|
|
transit_name = trainInfo.getTransitName()
|
|
transit_id = trainInfo.getTransitId()
|
|
return [transit_name, transit_id]
|
|
|
|
|
|
|
|
class NewTrainMaster(jmri.jmrit.automat.AbstractAutomaton):
|
|
|
|
# responds to the newTrainSensor, and allocates trains available for dispatching
|
|
# we make the allocated flag global as we will use it in DispatchMaster when we dispatch a train
|
|
|
|
global trains_allocated
|
|
|
|
def init(self):
|
|
self.logLevel = 0
|
|
if self.logLevel > 0: print 'Create Stop Thread'
|
|
self.od = OptionDialog()
|
|
|
|
def setup(self):
|
|
global trains_allocated
|
|
#self.initialise_train()
|
|
newTrainSensor = "newTrainSensor"
|
|
self.new_train_sensor = sensors.getSensor(newTrainSensor)
|
|
if self.new_train_sensor is None:
|
|
return False
|
|
self.new_train_sensor.setKnownState(INACTIVE)
|
|
if 'trains_allocated' not in globals():
|
|
trains_allocated = []
|
|
self.od = OptionDialog()
|
|
return True
|
|
|
|
def handle(self):
|
|
|
|
global trains_allocated
|
|
|
|
#this repeats
|
|
# wait for a sensor requesting to check for new train
|
|
if self.logLevel > 0: print ("wait for a sensor requesting to check for new train")
|
|
|
|
self.waitSensorActive(self.new_train_sensor)
|
|
self.new_train_sensor.setKnownState(INACTIVE)
|
|
#display the allocated trains
|
|
title = "Setup trains"
|
|
msg = "setup one or more trains"
|
|
opt1 = "1 train"
|
|
opt2 = "several trains"
|
|
opt3 = "check/swap train direction"
|
|
opt4 = "modify existing trains"
|
|
#opt4 = "reset trains"
|
|
action = self.od.customQuestionMessage4str(msg, title, opt1, opt2, opt3, opt4)
|
|
if self.od.CLOSED_OPTION == True: #check of optionbox was closed prematurely
|
|
pass
|
|
elif action == "1 train":
|
|
# print "trains_allocated", trains_allocated
|
|
# msg = "choose"
|
|
# actions = ["setup 1 train","setup 2+ trains"]
|
|
# action = self.od.List(msg, actions)
|
|
# if action == "setup 1 train":
|
|
station_block_name, new_train_name = self.check_new_train_in_siding()
|
|
if self.logLevel > 0: print "station_block_name",station_block_name, "existing train name", new_train_name
|
|
if station_block_name != None:
|
|
# take actions for new train
|
|
# if new_train_name == None:
|
|
if True:
|
|
all_trains = self.get_all_roster_entries_with_speed_profile()
|
|
sections_to_choose = self.get_non_allocated_trains_sections()
|
|
if all_trains == []:
|
|
msg = "There are no engines with speed profiles, cannot operate without any"
|
|
JOptionPane.showMessageDialog(None,msg)
|
|
elif len(sections_to_choose)>1:
|
|
# msg = self.get_all_trains_msg()
|
|
# title = None
|
|
# opt1 = "Select section"
|
|
# s = self.od.customMessage(msg, title, opt1)
|
|
# if self.logLevel > 0: print "station_block_name",station_block_name, "s", s
|
|
# if self.od.CLOSED_OPTION == False:
|
|
|
|
msg = "Select section"
|
|
sections_to_choose = self.get_non_allocated_trains_sections()
|
|
new_section_name = self.od.List(msg, sections_to_choose)
|
|
if self.od.CLOSED_OPTION == False:
|
|
msg = "Select the train in " + new_section_name
|
|
trains_to_choose = self.get_non_allocated_trains()
|
|
if trains_to_choose == []:
|
|
s = OptionDialog().displayMessage("no more trains with speed profiles \nto select")
|
|
else:
|
|
new_train_name = self.od.List(msg, trains_to_choose)
|
|
if self.od.CLOSED_OPTION == False:
|
|
if new_train_name not in trains_allocated:
|
|
trains_allocated.append(new_train_name)
|
|
# print "trains allocated", trains_allocated
|
|
#print "*****", "new_train_name", new_train_name, "new_section_name", new_section_name
|
|
self.add_to_train_list_and_set_new_train_location(new_train_name, new_section_name)
|
|
if self.od.CLOSED_OPTION == False: #only do this if have not closed a frame in add_to_train_list_and_set_new_train_location
|
|
self.set_blockcontents(new_section_name, new_train_name)
|
|
self.set_length(new_train_name)
|
|
self.set_speed_factor(new_train_name)
|
|
else:
|
|
if self.logLevel > 0 : print "!!!!5"
|
|
trains_to_choose = self.get_non_allocated_trains()
|
|
title = "In " + station_block_name + " Select train roster"
|
|
list_items = trains_to_choose
|
|
new_train_name = self.od.List(title, list_items, preferred_size = "default")
|
|
if new_train_name not in trains_allocated:
|
|
trains_allocated.append(new_train_name)
|
|
self.add_to_train_list_and_set_new_train_location(new_train_name, station_block_name)
|
|
self.set_blockcontents(station_block_name, new_train_name)
|
|
self.set_length(new_train_name)
|
|
self.set_speed_factor(new_train_name)
|
|
else:
|
|
if self.logLevel > 0: print "about to show message no new train in siding"
|
|
msg = self.get_all_trains_msg()
|
|
msg += "\nPut a train in a section so it can be allocated!\n"
|
|
title = "All trains allocated"
|
|
opt1 = "Continue"
|
|
opt2 = "Delete the trains already set up and start again"
|
|
ans = self.od.customQuestionMessage2str(msg, title, opt1, opt2)
|
|
if self.od.CLOSED_OPTION == True:
|
|
pass
|
|
elif ans == opt2:
|
|
self.reset_allocation1()
|
|
elif action == "several trains":
|
|
self.hideGui()
|
|
createandshowGUI(self, action)
|
|
|
|
elif action == "modify existing trains":
|
|
self.hideGui()
|
|
createandshowGUI(self, action)
|
|
elif action == "check/swap train direction":
|
|
self.check_swap_train_direction()
|
|
return True
|
|
|
|
def check_swap_train_direction(self):
|
|
trains_to_choose = self.get_allocated_trains()
|
|
# print "trains_to_choose", trains_to_choose
|
|
if trains_to_choose == []:
|
|
s = OptionDialog().displayMessage("no allocated trains to select")
|
|
else:
|
|
msg = "Select the required train"
|
|
new_train_name = self.od.List(msg, trains_to_choose)
|
|
self.swap_train_direction1(new_train_name)
|
|
|
|
def swap_train_direction1(self, train_name):
|
|
train_block_array = \
|
|
[block.getUserName() for block in blocks.getNamedBeanSet() if block.getValue() == train_name]
|
|
if train_block_array == []:
|
|
OptionDialog().displayMessage(train_name + " is not allocated")
|
|
return
|
|
train_block = \
|
|
[block.getUserName() for block in blocks.getNamedBeanSet() if block.getValue() == train_name][0]
|
|
if train_block is not None:
|
|
self.check_train_direction(train_name, train_block)
|
|
|
|
def hideGui(self):
|
|
global CreateAndShowGUI_frame
|
|
if "CreateAndShowGUI_frame" in globals():
|
|
CreateAndShowGUI_frame.setVisible(False)
|
|
|
|
def check_train_direction(self, train_name, station_block_name):
|
|
global train
|
|
if train_name in trains:
|
|
train = trains[train_name]
|
|
direction = train["direction"]
|
|
penultimate_layout_block = self.get_penultimate_layout_block(station_block_name)
|
|
|
|
saved_state = penultimate_layout_block.getUseExtraColor()
|
|
in_siding = self.in_siding(station_block_name)
|
|
|
|
closed = False
|
|
while closed == False:
|
|
penultimate_layout_block.setUseExtraColor(True)
|
|
direction = train["direction"]
|
|
msg = "train travelling " + self.swap_direction(direction) + " towards highlighted block"
|
|
title = "swap directions of " + train_name
|
|
opt1 = "swap direction"
|
|
opt2 = "Close"
|
|
s = OptionDialog().customQuestionMessage2str(msg, title, opt1, opt2)
|
|
if s == JOptionPane.CLOSED_OPTION:
|
|
closed = True
|
|
if s == opt1:
|
|
self.swap_train_direction(train_name)
|
|
closed = False
|
|
if s == opt2:
|
|
closed = True
|
|
penultimate_layout_block.setUseExtraColor(saved_state)
|
|
|
|
def swap_train_direction(self, train_name):
|
|
global train
|
|
if train_name in trains:
|
|
train = trains[train_name]
|
|
direction = train["direction"]
|
|
train["direction"] = self.swap_direction(direction)
|
|
|
|
def swap_direction(self, direction):
|
|
if direction == "reverse":
|
|
direction = "forward"
|
|
else:
|
|
direction = "reverse"
|
|
return direction
|
|
|
|
|
|
def get_train_length(self, new_train_name):
|
|
EngineManager=jmri.InstanceManager.getDefault(jmri.jmrit.operations.rollingstock.engines.EngineManager)
|
|
engineRoad = "Set by Dispatcher System"
|
|
engineNumber = new_train_name
|
|
engine = EngineManager.newRS(engineRoad, engineNumber)
|
|
#get the current length of the engine
|
|
default = "10"
|
|
current_length = engine.getLength()
|
|
# print "current_length", current_length
|
|
# print "type", type(current_length) , "test", str(current_length) == "0"
|
|
if str(current_length) == "0" or current_length is None:
|
|
current_length = default # current length is in unicode
|
|
engine.setLength(current_length)
|
|
# print "current_length2", current_length
|
|
return [engine, current_length]
|
|
|
|
def set_length(self, new_train_name):
|
|
|
|
if new_train_name is None: return
|
|
|
|
title = "Set the length of the engine/train"
|
|
# msg = str(fred)
|
|
request = "Change"
|
|
while request == "Change":
|
|
[engine,current_length] = self.get_train_length(new_train_name)
|
|
if current_length == None: return
|
|
# print "current_length3", current_length
|
|
# current_length is an integer, and is set to a default of 10 scale metres
|
|
gauge = WarrantPreferences.getDefault().getLayoutScale()
|
|
length_in_cm_float = (float(current_length) / gauge) * 100.0
|
|
length_in_cm_str = str("{:.2f}".format(length_in_cm_float))
|
|
length_in_inches_float = (float(current_length) / gauge / 2.54) * 100.0
|
|
length_in_inches_str = str("{:.2f}".format(length_in_inches_float))
|
|
msg = "<html>length of " + new_train_name + " = " + str(current_length) + " scale metres" + \
|
|
"<br> gauge : " + "1:" + str(int(gauge)) + \
|
|
"<br> length in cm : " + length_in_cm_str + \
|
|
"<br> length in inches: " + length_in_inches_str
|
|
opt1 = "OK"
|
|
opt2 = "Change"
|
|
request = self.od.customQuestionMessage2str(msg,title,opt1, opt2)
|
|
if request == "Change":
|
|
#set the new length
|
|
msg = "input length of " + new_train_name + " in scale metres"
|
|
title = "length of " + new_train_name
|
|
default_value = current_length
|
|
new_length = self.od.input(msg, title, default_value)
|
|
engine.setLength(new_length)
|
|
|
|
def set_length0(self, new_train_name):
|
|
[engine,current_length] = self.get_train_length(new_train_name)
|
|
engine.setLength(current_length)
|
|
|
|
def get_train_speed_factor(self, new_train_name):
|
|
EngineManager=jmri.InstanceManager.getDefault(jmri.jmrit.operations.rollingstock.engines.EngineManager)
|
|
engineRoad = "Set by Dispatcher System"
|
|
engineNumber = new_train_name
|
|
engine = EngineManager.newRS(engineRoad, engineNumber)
|
|
# get the current speed factor of the engine
|
|
default = "100" # percentage
|
|
comment = engine.getComment()
|
|
split_comment = []
|
|
if "speed factor" in comment:
|
|
split_comment = comment.split(" ")
|
|
index = split_comment.index("speed")
|
|
# print "len(split_comment)", len(split_comment), "index + 2", index + 2
|
|
if len(split_comment) > index + 2:
|
|
speed_factor = split_comment[index+2]
|
|
else:
|
|
speed_factor = default
|
|
else:
|
|
speed_factor = default
|
|
return [engine, speed_factor]
|
|
|
|
def set_speed_factor(self, new_train_name):
|
|
[engine, current_speed_factor] = self.get_train_speed_factor(new_train_name)
|
|
# if current_length == "0":
|
|
# default = "10"
|
|
# current_speed_factor = default
|
|
# engine.setSpeedFactor(default)
|
|
#ask if want to change length
|
|
title = "Scale the speed of the engine/train"
|
|
msg = "speed factor of " + new_train_name + " = " + str(current_speed_factor) + "%"
|
|
opt1 = "OK"
|
|
opt2 = "Change"
|
|
request = self.od.customQuestionMessage2str(msg,title,opt1, opt2)
|
|
if request == "Change":
|
|
#set the new speed factor
|
|
msg = "input speed factor % of " + new_train_name
|
|
title = "speed factor of " + new_train_name
|
|
default_value = current_speed_factor
|
|
new_speed_factor= self.od.input(msg, title, default_value)
|
|
new_speed_factor = "speed factor " + new_speed_factor
|
|
engine.setComment(new_speed_factor)
|
|
|
|
def set_speed_factor0(self, new_train_name): # used in set several trains
|
|
[engine, current_speed_factor] = self.get_train_speed_factor(new_train_name)
|
|
new_speed_factor = "speed factor " + current_speed_factor
|
|
engine.setComment(new_speed_factor)
|
|
|
|
def get_allocated_trains_msg(self):
|
|
allocated_trains =[ str(train) + " in block " + str(trains[train]["edge"].getTarget()) for train in trains_allocated]
|
|
if allocated_trains ==[]:
|
|
msg = "There are no trains in blocks that are not allocated. \n"
|
|
else:
|
|
msg = "The allocated trains are: \n" +'\n'.join(allocated_trains)
|
|
return msg
|
|
|
|
def get_allocated_trains(self):
|
|
return trains_allocated
|
|
|
|
def get_non_allocated_trains(self):
|
|
all_trains = self.get_all_roster_entries_with_speed_profile()
|
|
non_allocated_trains = copy.copy(all_trains)
|
|
for train in trains_allocated:
|
|
if train in non_allocated_trains:
|
|
non_allocated_trains.remove(train)
|
|
return non_allocated_trains
|
|
|
|
def get_non_allocated_trains_msg(self):
|
|
trains_in_sections_allocated1 = self.trains_in_sections_allocated()
|
|
msg = "the non-allocated trains are in sections: \n\n" + "\n".join([" " + str(train[0]) for train in trains_in_sections_allocated1 if train[2] == "non-allocated"])
|
|
return msg
|
|
|
|
def get_all_sections(self):
|
|
return [section for section in sections.getNamedBeanSet()]
|
|
|
|
def get_all_blocks(self):
|
|
return [block for block in blocks.getNamedBeanSet()]
|
|
|
|
def get_sections_for_trains_in_table(self, trains_in_table):
|
|
return [str(train) for train in trains_in_table]
|
|
|
|
def get_non_allocated_trains_sections(self):
|
|
trains_in_sections_allocated1 = self.trains_in_sections_allocated()
|
|
# print "trains_in_sections_allocated1", trains_in_sections_allocated1
|
|
return [str(train[0]) for train in trains_in_sections_allocated1 if train[2] == "non-allocated"]
|
|
|
|
def get_allocated_trains_sections(self):
|
|
trains_in_sections_allocated1 = self.trains_in_sections_allocated()
|
|
return [str(train[0]) for train in trains_in_sections_allocated1 if train[2] == "allocated"]
|
|
|
|
def get_all_trains_msg(self):
|
|
return self.get_allocated_trains_msg() + "\n" + self.get_non_allocated_trains_msg()
|
|
|
|
def reset_allocation(self):
|
|
global trains_allocated
|
|
if trains_allocated == []:
|
|
if self.logLevel > 0: print ("a")
|
|
msg = "Nothing to reset"
|
|
OptionDialog().displayMessage(msg)
|
|
else:
|
|
if self.logLevel > 0: print ("b")
|
|
msg = "Select train to modify"
|
|
train_name_to_remove = modifiableJComboBox(trains_allocated,msg).return_val()
|
|
trains_allocated.remove(train_name_to_remove)
|
|
self.new_train_sensor.setKnownState(ACTIVE)
|
|
|
|
def reset_allocation1(self):
|
|
global trains_allocated
|
|
if trains_allocated == []:
|
|
if self.logLevel > 0: print ("a")
|
|
msg = "Nothing to reset"
|
|
OptionDialog().displayMessage(msg)
|
|
else:
|
|
if self.logLevel > 0: print ("b")
|
|
#set trains_allocated to []
|
|
for train_name_to_remove in trains_allocated:
|
|
msg = "Select train to modify"
|
|
#train_name_to_remove = modifiableJComboBox(trains_allocated,msg).return_val()
|
|
trains_allocated.remove(train_name_to_remove) #remove the train from trains_allocated
|
|
self.reset_train_in_blocks(train_name_to_remove) #remove the blockcontents text
|
|
if self.logLevel > 0: print "trains_allocated",trains_allocated
|
|
#self.new_train_sensor.setKnownState(ACTIVE)
|
|
|
|
def get_all_roster_entries_with_speed_profile(self):
|
|
roster_entries_with_speed_profile = []
|
|
r = jmri.jmrit.roster.Roster.getDefault()
|
|
for roster_entry in jmri.jmrit.roster.Roster.getAllEntries(r):
|
|
if self.logLevel > 0: print "roster_entry.getSpeedProfile()",roster_entry,roster_entry.getSpeedProfile()
|
|
if roster_entry.getSpeedProfile() != None:
|
|
roster_entries_with_speed_profile.append(roster_entry.getId())
|
|
if self.logLevel > 0: print "roster_entry.getId()",roster_entry.getId()
|
|
return roster_entries_with_speed_profile
|
|
|
|
def add_to_train_list_and_set_new_train_location(self, train_name, station_block_name):
|
|
|
|
# called by setup 1 train
|
|
|
|
# trains is a dictionary, with keys of the train_name
|
|
# each value is itself a dictionary with 3 items
|
|
# edge
|
|
# penultimate_block_name
|
|
# direction
|
|
global train
|
|
global trains_allocated
|
|
if train_name not in trains:
|
|
trains[train_name] = {}
|
|
train = trains[train_name]
|
|
train["train_name"] = train_name
|
|
else:
|
|
#train_name = self.get_train_name()
|
|
self.set_train_in_block(station_block_name, train_name)
|
|
|
|
# 2) set the last traversed edge to the edge going into the siding
|
|
edge = None
|
|
j = 0
|
|
#print "edge_before" , edge
|
|
#print "g.g_stopping.edgesOf(station_block_name)",g.g_stopping.edgesOf(station_block_name)
|
|
break1 = False
|
|
for e in g.g_stopping.edgeSet():
|
|
j+=1
|
|
LayoutBlockManager=jmri.InstanceManager.getDefault(jmri.jmrit.display.layoutEditor.LayoutBlockManager)
|
|
station_block = LayoutBlockManager.getLayoutBlock(station_block_name)
|
|
number_neighbors = station_block.getNumberOfNeighbours()
|
|
#print "station block number neighbors", number_neighbors
|
|
in_siding = (number_neighbors == 1)
|
|
#print "in_siding", in_siding
|
|
for i in range(station_block.getNumberOfNeighbours()):
|
|
neighbor_name = station_block.getNeighbourAtIndex(i).getDisplayName()
|
|
if e.getItem("penultimate_block_name") == neighbor_name and e.getItem("last_block_name") == station_block_name:
|
|
edge = e
|
|
break1 = True
|
|
if break1 == True:
|
|
break
|
|
#print "******************************++"
|
|
if edge == None:
|
|
print "Error the required block has not been found1. restart and try again. Sorry!"
|
|
return
|
|
train["edge"] = edge
|
|
train["penultimate_block_name"] = edge.getItem("penultimate_block_name")
|
|
|
|
# 3) set direction so can check direction of transit
|
|
|
|
penultimate_block_name = edge.getItem("penultimate_block_name")
|
|
penultimate_layout_block = LayoutBlockManager.getLayoutBlock(penultimate_block_name)
|
|
saved_state = penultimate_layout_block.getUseExtraColor()
|
|
if not in_siding:
|
|
# highlight the penultimate block
|
|
penultimate_layout_block.setUseExtraColor(True)
|
|
penultimate_layout_block.setUseExtraColor(True)
|
|
# print "set train direction"
|
|
[train_direction,result] = self.set_train_direction(station_block_name, in_siding)
|
|
# print "finished set train direction"
|
|
#check the condition set in set_train_direction
|
|
train["direction"] = train_direction
|
|
# print "train['direction']", train["direction"]
|
|
penultimate_layout_block.setUseExtraColor(saved_state)
|
|
# print "edge" , edge
|
|
if self.logLevel > 3: print "penultimate_block_name", penultimate_block_name
|
|
if self.logLevel > 4: print "train_direction", train_direction
|
|
# print
|
|
|
|
# 4) add to allocated train list
|
|
if str(train_name) not in trains_allocated:
|
|
trains_allocated.append(str(train_name))
|
|
if "allocating" not in train:
|
|
train["allocating"] = False
|
|
# print "done"
|
|
|
|
def add_to_train_list_and_set_new_train_location0(self, train_name, station_block_name,
|
|
train_direction, train_length, train_speed_factor):
|
|
# called by setup several trains
|
|
|
|
# trains is a dictionary, with keys of the train_name
|
|
# each value is itself a dictionary with 3 items
|
|
# edge
|
|
# penultimate_block_name
|
|
# direction
|
|
global train
|
|
global trains_allocated
|
|
if train_name not in trains:
|
|
trains[train_name] = {}
|
|
train = trains[train_name]
|
|
train["train_name"] = train_name
|
|
else:
|
|
#train_name = self.get_train_name()
|
|
train = trains[train_name]
|
|
train["train_name"] = train_name
|
|
self.set_train_in_block(station_block_name, train_name)
|
|
|
|
# 2) set the last traversed edge to the edge going into the siding
|
|
edge = None
|
|
j = 0
|
|
#print "edge_before" , edge
|
|
#print "g.g_stopping.edgesOf(station_block_name)",g.g_stopping.edgesOf(station_block_name)
|
|
break1 = False
|
|
#print "no edges", g.g_stopping.edgeSet()
|
|
for e in g.g_stopping.edgeSet():
|
|
j+=1
|
|
LayoutBlockManager=jmri.InstanceManager.getDefault(jmri.jmrit.display.layoutEditor.LayoutBlockManager)
|
|
station_block = LayoutBlockManager.getLayoutBlock(station_block_name)
|
|
number_neighbors = station_block.getNumberOfNeighbours()
|
|
#print "station block number neighbors", number_neighbors
|
|
in_siding = (number_neighbors == 1)
|
|
#print "in_siding", in_siding
|
|
for i in range(station_block.getNumberOfNeighbours()):
|
|
neighbor_name = station_block.getNeighbourAtIndex(i).getDisplayName()
|
|
# print "penultimate_block_name", e.getItem("penultimate_block_name")
|
|
# print "last_block_name", e.getItem("last_block_name")
|
|
print "***************"
|
|
if e.getItem("penultimate_block_name") == neighbor_name and e.getItem("last_block_name") == station_block_name:
|
|
edge = e
|
|
break1 = True
|
|
if break1 == True:
|
|
break
|
|
#print "******************************++"
|
|
if edge == None:
|
|
print "Error the required block has not been found2. restart and try again. Sorry!"
|
|
return
|
|
train["edge"] = edge
|
|
train["penultimate_block_name"] = edge.getItem("penultimate_block_name")
|
|
|
|
# 3) set direction so can check direction of transit
|
|
|
|
train["direction"] = train_direction
|
|
# print train_name, 'train["direction"]',train["direction"]
|
|
|
|
|
|
# 4) add to allocated train list
|
|
# if str(train_name) not in trains_allocated:
|
|
# trains_allocated.append(str(train_name))
|
|
|
|
[engine,current_length] = self.get_train_length(train_name) #get the engine name
|
|
engine.setLength(str(train_length)) # save the length provided in the parameter
|
|
|
|
#[engine,current_speed_factor] = self.get_train_speed_factor(train_name)
|
|
speed_factor_str = "speed factor " + train_speed_factor
|
|
engine.setComment(speed_factor_str)
|
|
|
|
train["allocating"] = False
|
|
|
|
def highlight_penultimate_block(self, station_block_name):
|
|
# print("highlight_penultimate_block")
|
|
# 2) set the last traversed edge to the edge going into the siding
|
|
edge = None
|
|
j = 0
|
|
#print "edge_before" , edge
|
|
#print "g.g_stopping.edgesOf(station_block_name)",g.g_stopping.edgesOf(station_block_name)
|
|
break1 = False
|
|
#print "no edges", g.g_stopping.edgeSet()
|
|
# for e in g.g_express.edgeSet():
|
|
# print "e" , e
|
|
for e in g.g_express.edgeSet():
|
|
j+=1
|
|
LayoutBlockManager=jmri.InstanceManager.getDefault(jmri.jmrit.display.layoutEditor.LayoutBlockManager)
|
|
station_block = LayoutBlockManager.getLayoutBlock(station_block_name)
|
|
number_neighbors = station_block.getNumberOfNeighbours()
|
|
#print "station block number neighbors", number_neighbors
|
|
in_siding = (number_neighbors == 1)
|
|
# print "in_siding", in_siding
|
|
for i in range(station_block.getNumberOfNeighbours()):
|
|
neighbor_name = station_block.getNeighbourAtIndex(i).getDisplayName()
|
|
print "neighbor_name", neighbor_name
|
|
print "station_block_name", station_block_name
|
|
# print "penultimate_block_name", e.getItem("penultimate_block_name")
|
|
# print "last_block_name", e.getItem("last_block_name")
|
|
print "***************"
|
|
if e.getItem("penultimate_block_name") == neighbor_name and e.getItem("last_block_name") == station_block_name:
|
|
edge = e
|
|
break1 = True
|
|
if break1 == True:
|
|
break
|
|
#print "******************************++"
|
|
if edge == None:
|
|
print "Error the required block has not been found3. restart and try again. Sorry!"
|
|
return ["Error", "Error", "Error"]
|
|
|
|
# 3) set direction so can check direction of transit
|
|
|
|
penultimate_block_name = edge.getItem("penultimate_block_name")
|
|
penultimate_layout_block = LayoutBlockManager.getLayoutBlock(penultimate_block_name)
|
|
saved_state = penultimate_layout_block.getUseExtraColor()
|
|
if not in_siding:
|
|
# highlight the penultimate block
|
|
penultimate_layout_block.setUseExtraColor(True)
|
|
penultimate_layout_block.setUseExtraColor(True)
|
|
[train_direction, result] = self.set_train_direction(station_block_name, in_siding)
|
|
penultimate_layout_block.setUseExtraColor(saved_state)
|
|
|
|
return [edge, train_direction, result]
|
|
|
|
def get_penultimate_layout_block(self, station_block_name):
|
|
# get the last traversed edge to the edge of the station_block
|
|
edge = None
|
|
j = 0
|
|
#print "edge_before" , edge
|
|
#print "g.g_stopping.edgesOf(station_block_name)",g.g_stopping.edgesOf(station_block_name)
|
|
break1 = False
|
|
#print "no edges", g.g_stopping.edgeSet()
|
|
for e in g.g_stopping.edgeSet():
|
|
j+=1
|
|
LayoutBlockManager=jmri.InstanceManager.getDefault(jmri.jmrit.display.layoutEditor.LayoutBlockManager)
|
|
station_block = LayoutBlockManager.getLayoutBlock(station_block_name)
|
|
number_neighbors = station_block.getNumberOfNeighbours()
|
|
#print "station block number neighbors", number_neighbors
|
|
in_siding = (number_neighbors == 1)
|
|
for i in range(station_block.getNumberOfNeighbours()):
|
|
neighbor_name = station_block.getNeighbourAtIndex(i).getDisplayName()
|
|
print "neighbor_name", neighbor_name
|
|
print "station_block_name", station_block_name
|
|
# print "penultimate_block_name", e.getItem("penultimate_block_name")
|
|
# print "last_block_name", e.getItem("last_block_name")
|
|
print "***************"
|
|
if e.getItem("penultimate_block_name") == neighbor_name and e.getItem("last_block_name") == station_block_name:
|
|
edge = e
|
|
break1 = True
|
|
if break1 == True:
|
|
break
|
|
if edge == None:
|
|
# print "Error the required block has not been found4. restart and try again. Sorry!"
|
|
return None
|
|
penultimate_block_name = edge.getItem("penultimate_block_name")
|
|
LayoutBlockManager=jmri.InstanceManager.getDefault(jmri.jmrit.display.layoutEditor.LayoutBlockManager)
|
|
penultimate_layout_block = LayoutBlockManager.getLayoutBlock(penultimate_block_name)
|
|
return penultimate_layout_block
|
|
|
|
def in_siding(self, station_block_name):
|
|
LayoutBlockManager=jmri.InstanceManager.getDefault(jmri.jmrit.display.layoutEditor.LayoutBlockManager)
|
|
station_block = LayoutBlockManager.getLayoutBlock(station_block_name)
|
|
number_neighbors = station_block.getNumberOfNeighbours()
|
|
#print "station block number neighbors", number_neighbors
|
|
in_siding = (number_neighbors == 1)
|
|
return in_siding
|
|
|
|
def set_train_direction(self, block_name, in_siding):
|
|
# in_siding = self.in_siding(block_name)
|
|
options = ["forward", "reverse"]
|
|
default = "forward"
|
|
self.od.CLOSED_OPTION = True
|
|
while self.od.CLOSED_OPTION == True:
|
|
msg = "In block: " + block_name + "\n" +'What way is train facing\ntowards highlighted block?'
|
|
title = "Set Train Facing Direction"
|
|
type = JOptionPane.QUESTION_MESSAGE
|
|
result = self.od.customQuestionMessage2str(msg, title, "forward", "reverse")
|
|
if self.od.CLOSED_OPTION == True:
|
|
OptionDialog().displayMessage("Sorry Can't Cancel at this point")
|
|
if result == "reverse":
|
|
train_direction = "forward"
|
|
else:
|
|
train_direction = "reverse"
|
|
|
|
# if in_siding:
|
|
# if result == "reverse":
|
|
# train_direction = "forward"
|
|
# else:
|
|
# train_direction = "reverse"
|
|
# else:
|
|
# if result == "forward":
|
|
# train_direction = "forward"
|
|
# else:
|
|
# train_direction = "reverse"
|
|
return [train_direction, result]
|
|
|
|
def set_train_in_block(self, block_name, train_name):
|
|
mem_val = train_name
|
|
self.set_blockcontents(block_name, mem_val)
|
|
|
|
def reset_train_in_blocks(self, train_name):
|
|
for block in blocks.getNamedBeanSet():
|
|
#print "block name", block.getUserName(), "block.getValue()" , block.getValue()
|
|
if block.getValue() == train_name:
|
|
#print "yes"
|
|
block.setValue("")
|
|
#print "block name yes", block.getUserName(), "block.getValue()" , block.getValue()
|
|
|
|
|
|
def trains_in_sections_allocated(self):
|
|
trains_in_sections_allocated = []
|
|
#trains_in_sections_nonallocated = []
|
|
for station_block_name in g.station_block_list:
|
|
block_value = self.get_blockcontents(station_block_name)
|
|
block_occupied_state = self.check_sensor_state_given_block_name(station_block_name)
|
|
# print "trains_allocated", trains_allocated
|
|
# print "block_value", block_value
|
|
if block_occupied_state == True:
|
|
if block_value not in trains_allocated:
|
|
# print "appending non_allocated as block_value not in trains allocated"
|
|
trains_in_sections_allocated.append([station_block_name, block_value, "non-allocated"])
|
|
elif (block_value != None and block_value != "" and block_value != "none"):
|
|
trains_in_sections_allocated.append([station_block_name, block_value, "allocated"])
|
|
else:
|
|
trains_in_sections_allocated.append([station_block_name, block_value, "other"])
|
|
# print "trains_in_sections_allocated", trains_in_sections_allocated
|
|
if self.logLevel > 0: print str(trains_in_sections_allocated)
|
|
return trains_in_sections_allocated
|
|
|
|
def occupied_blocks_allocated(self):
|
|
occupied_blocks = [block for [block, train, state] in self.trains_in_sections_allocated() if state == "allocated"]
|
|
return occupied_blocks
|
|
|
|
def occupied_blocks_not_allocated(self):
|
|
occupied_blocks = [block for [block, train, state] in self.trains_in_sections_allocated() if state == "non-allocated"]
|
|
return occupied_blocks
|
|
|
|
def blocks_allocated(self):
|
|
occupied_blocks = [block for [block, train, state] in self.trains_in_sections_allocated()]
|
|
return occupied_blocks
|
|
|
|
def train_blocks(self, train_list, in_list):
|
|
occupied_blocks = \
|
|
[station_block_name for station_block_name in g.station_block_list \
|
|
if self.check_sensor_state_given_block_name(station_block_name) == True]
|
|
|
|
# print "occupied_blocks", occupied_blocks
|
|
# print "train_list", train_list
|
|
self.get_blockcontents(station_block_name),
|
|
if in_list:
|
|
items_in_list = \
|
|
[[self.get_blockcontents(block_name), block_name, self.check_sensor_state_given_block_name(block_name)] \
|
|
for block_name in occupied_blocks if self.get_blockcontents(block_name) in train_list]
|
|
# [train_name , block_name, block_state] = items_in_list # for clarity
|
|
return items_in_list
|
|
else:
|
|
items_not_in_list = \
|
|
[[self.get_blockcontents(block_name), block_name, self.check_sensor_state_given_block_name(block_name)] \
|
|
for block_name in occupied_blocks if self.get_blockcontents(block_name) not in train_list]
|
|
# [train_name , block_name, block_state] = items_in_list # for clarity
|
|
return items_not_in_list
|
|
|
|
def train_blocks_in_list(self,train_list):
|
|
return self.train_blocks(train_list, True)
|
|
def train_blocks_not_in_list(self,train_list):
|
|
return self.train_blocks(train_list, False)
|
|
|
|
def check_new_train_in_siding(self):
|
|
|
|
# go through all station
|
|
global trains_allocated
|
|
|
|
for station_block_name in g.station_block_list:
|
|
|
|
#get a True if the block block_value has the train name in it
|
|
block_value = self.get_blockcontents(station_block_name)
|
|
if self.logLevel > 0: print " a trains_allocated:", trains_allocated, ": block_value", block_value
|
|
|
|
#get a True if the block is occupied
|
|
block_occupied_state = self.check_sensor_state_given_block_name(station_block_name)
|
|
|
|
if self.logLevel > 0: print ("station block name {} : block_value {}". format(station_block_name, str(block_value)))
|
|
|
|
#check if the block is occupied and has the required train in it
|
|
if (block_value == None or block_value == "" or block_value == "none") and block_occupied_state == True:
|
|
return [station_block_name, None]
|
|
elif block_occupied_state == True and (block_value != None and block_value != "" and block_value != "none"):
|
|
#check if there is already a thread for the train
|
|
#check if the train has already been allocated
|
|
#if self.new_train_thread_required(block_value):
|
|
if block_value not in trains_allocated:
|
|
return [station_block_name, block_value]
|
|
else:
|
|
if self.logLevel > 0: print "block_value in trains_allocated"
|
|
if self.logLevel > 0: print "b trains_allocated:", trains_allocated, ": block_value", block_value
|
|
pass
|
|
else:
|
|
pass
|
|
return [None, None]
|
|
|
|
def is_roster_entry(self, v):
|
|
return type(v) is jmri.jmrit.roster.RosterEntry
|
|
|
|
def train_thread_exists(self, train_name):
|
|
for thread in instanceList:
|
|
if thread is not None:
|
|
if thread.isRunning():
|
|
existing_train_name = thread.getName()
|
|
if existing_train_name == train_name:
|
|
return True
|
|
return False
|
|
|
|
def create_new_train_thread(self, train_name):
|
|
idx = len(instanceList)
|
|
instanceList.append(RunDispatch()) # Add a new instance
|
|
instanceList[idx].setName(train_name) # Set the instance name
|
|
#if instanceList[idx].setup(): # Compile the train actions
|
|
instanceList[idx].start() # Compile was successful
|
|
|
|
def get_blockcontents(self, block_name):
|
|
block = blocks.getBlock(block_name)
|
|
value = block.getValue()
|
|
return value
|
|
|
|
def set_blockcontents(self, block_name, value):
|
|
block = blocks.getBlock(block_name)
|
|
value = block.setValue(value)
|
|
|
|
def check_sensor_state_given_block_name(self, station_block_name):
|
|
#if self.logLevel > 0: print("station block name {}".format(station_block_name))
|
|
layoutBlock = layoutblocks.getLayoutBlock(station_block_name)
|
|
station_sensor = layoutBlock.getOccupancySensor()
|
|
if station_sensor is None:
|
|
OptionDialog().displayMessage(' Sensor in block {} not found'.format(station_block_name))
|
|
return
|
|
currentState = True if station_sensor.getKnownState() == ACTIVE else False
|
|
return currentState
|
|
|
|
class createandshowGUI(TableModelListener):
|
|
|
|
def __init__(self, super1, mode1):
|
|
|
|
global CreateAndShowGUI_frame
|
|
self.logLevel = 0
|
|
self.super = super1
|
|
|
|
#Create and set up the window.
|
|
self.mode = mode1 # "several trains" or "modify existing trains"
|
|
self.initialise_model(super1)
|
|
if self.mode == "modify existing trains":
|
|
CreateAndShowGUI_frame = JFrame("occupied blocks, allocated or not")
|
|
else:
|
|
CreateAndShowGUI_frame = JFrame("Set up trains. Any trains shown in blocks are showing on the track but not allocated. Save to allocate")
|
|
self.frame = CreateAndShowGUI_frame
|
|
self.frame.setPreferredSize(Dimension(800, 600));
|
|
self.frame.setVisible(True)
|
|
self.completeTablePanel1()
|
|
self.populate_action(None)
|
|
self.completeTablePanel()
|
|
self.cancel = False
|
|
|
|
def completeTablePanel(self):
|
|
self.tidy()
|
|
self.frame.pack()
|
|
self.frame.setVisible(True)
|
|
return
|
|
|
|
|
|
def completeTablePanel1(self):
|
|
self.topPanel = JPanel();
|
|
self.topPanel.setLayout(BoxLayout(self.topPanel, BoxLayout.X_AXIS))
|
|
self.self_table()
|
|
|
|
scrollPane = JScrollPane(self.table);
|
|
scrollPane.setPreferredSize(Dimension(800, 600));
|
|
self.topPanel.add(scrollPane);
|
|
|
|
self.buttonPane = JPanel();
|
|
self.buttonPane.setLayout(BoxLayout(self.buttonPane, BoxLayout.LINE_AXIS))
|
|
self.buttonPane.setBorder(BorderFactory.createEmptyBorder(0, 10, 10, 10))
|
|
# button_add = JButton("Add Row", actionPerformed = self.add_row_action)
|
|
# self.buttonPane.add(button_add);
|
|
# self.buttonPane.add(Box.createRigidArea(Dimension(10, 0)))
|
|
button_apply = JButton("Save", actionPerformed=self.save_action)
|
|
self.buttonPane.add(button_apply)
|
|
# self.buttonPane.add(Box.createHorizontalGlue())
|
|
self.buttonPane.add(Box.createRigidArea(Dimension(10, 0)))
|
|
button_cancel = JButton("Close", actionPerformed=self.cancel_action)
|
|
self.buttonPane.add(button_cancel)
|
|
self.buttonPane.add(Box.createHorizontalGlue())
|
|
button_populate = JButton("Populate", actionPerformed=self.populate_action)
|
|
self.buttonPane.add(button_populate)
|
|
# self.buttonPane.add(Box.createRigidArea(Dimension(10, 0)))
|
|
# button_tidy = JButton("Tidy", actionPerformed=self.tidy_action)
|
|
# self.buttonPane.add(button_tidy)
|
|
self.buttonPane.add(Box.createHorizontalGlue())
|
|
self.buttonPane.add(Box.createRigidArea(Dimension(10, 0)))
|
|
button_savetofile = JButton("Save To File", actionPerformed=self.savetofile_action)
|
|
self.buttonPane.add(button_savetofile)
|
|
# self.buttonPane.add(Box.createHorizontalGlue())
|
|
self.buttonPane.add(Box.createRigidArea(Dimension(10, 0)))
|
|
button_loadfromfile = JButton("Load From File", actionPerformed=self.loadfromfile_action)
|
|
self.buttonPane.add(button_loadfromfile)
|
|
# self.buttonPane.add(Box.createHorizontalGlue())
|
|
self.buttonPane.add(Box.createRigidArea(Dimension(10, 0)))
|
|
button_deletefromfile = JButton("Delete Saved Files", actionPerformed=self.deletesavedfile_action)
|
|
self.buttonPane.add(button_deletefromfile)
|
|
self.buttonPane.add(Box.createHorizontalGlue())
|
|
|
|
contentPane = self.frame.getContentPane()
|
|
contentPane.removeAll()
|
|
contentPane.add(self.topPanel, BorderLayout.CENTER)
|
|
contentPane.add(self.buttonPane, BorderLayout.PAGE_END)
|
|
|
|
def buttonPanel(self):
|
|
row1_1_button = JButton("Add Row", actionPerformed = self.add_row_action)
|
|
row1_2_button = JButton("Save", actionPerformed = self.save_action)
|
|
|
|
row1 = JPanel()
|
|
row1.setLayout(BoxLayout(row1, BoxLayout.X_AXIS))
|
|
|
|
row1.add(Box.createVerticalGlue())
|
|
row1.add(Box.createRigidArea(Dimension(20, 0)))
|
|
row1.add(row1_1_button)
|
|
row1.add(Box.createRigidArea(Dimension(10, 0)))
|
|
row1.add(row1_2_button)
|
|
|
|
layout = BorderLayout()
|
|
|
|
jPanel = JPanel()
|
|
jPanel.setLayout(layout);
|
|
jPanel.add(self.table,BorderLayout.NORTH)
|
|
jPanel.add(row1,BorderLayout.SOUTH)
|
|
|
|
#return jPanel
|
|
return topPanel
|
|
|
|
def initialise_model(self, super):
|
|
|
|
self.model = None
|
|
self.model = MyTableModel()
|
|
self.table = JTable(self.model)
|
|
self.model.addTableModelListener(MyModelListener(self, super))
|
|
|
|
def self_table(self):
|
|
|
|
self.table.setPreferredScrollableViewportSize(Dimension(800, 600));
|
|
#table.setFillsViewportHeight(True)
|
|
#self.table.getModel().addtableModelListener(self)
|
|
self.table.setFillsViewportHeight(True);
|
|
self.table.setRowHeight(30);
|
|
#table.setAutoResizeMode( JTable.AUTO_RESIZE_OFF );
|
|
# self.resizeColumnWidth(table)
|
|
|
|
#renderer = DefaultTableCellRenderer()
|
|
|
|
#renderer.setToolTipText("Click for combo box");
|
|
# set first 3 cols to combobox
|
|
# comboBox = [1,2,3]
|
|
# column = [1,2,3]
|
|
|
|
|
|
self.trainColumn = self.table.getColumnModel().getColumn(0)
|
|
self.trainColumn.setPreferredWidth(100)
|
|
self.combobox0 = JComboBox()
|
|
|
|
self.all_trains = self.super.get_all_roster_entries_with_speed_profile()
|
|
self.non_allocated_trains = self.super.get_non_allocated_trains()
|
|
self.allocated_trains = self.super.get_allocated_trains()
|
|
if self.mode == "several trains":
|
|
self.required_trains = self.non_allocated_trains
|
|
elif self.mode == "modify existing trains":
|
|
self.required_trains = self.allocated_trains
|
|
# print "self.non_allocated_trains", self.non_allocated_trains
|
|
# print "self.allocated_trains", self.allocated_trains
|
|
for train in self.required_trains:
|
|
self.combobox0.addItem(train)
|
|
# print "adding train", train
|
|
self.trainColumn.setCellEditor(DefaultCellEditor(self.combobox0));
|
|
renderer0 = ComboBoxCellRenderer()
|
|
self.trainColumn.setCellRenderer(renderer0)
|
|
self.all_sections = self.super.get_all_sections()
|
|
self.all_blocks = self.super.get_all_blocks()
|
|
|
|
self.sectionColumn = self.table.getColumnModel().getColumn(1);
|
|
self.sectionColumn.setPreferredWidth(100)
|
|
self.combobox1 = JComboBox()
|
|
if self.mode == "several trains":
|
|
self.sections_to_choose = self.super.get_non_allocated_trains_sections()
|
|
else:
|
|
self.sections_to_choose = self.super.get_allocated_trains_sections()
|
|
for section in self.sections_to_choose:
|
|
self.combobox1.addItem(section)
|
|
#self.set_train_selections(combobox0)
|
|
self.sectionColumn.setCellEditor(DefaultCellEditor(self.combobox1));
|
|
renderer1 = ComboBoxCellRenderer()
|
|
self.sectionColumn.setCellRenderer(renderer1);
|
|
jpane = JScrollPane(self.table)
|
|
panel = JPanel()
|
|
panel.add(jpane)
|
|
return self.table
|
|
|
|
def add_row_action(self, e):
|
|
model = e.getSource()
|
|
data = self.model.getValueAt(0, 0)
|
|
count = self.model.getRowCount()
|
|
colcount = self.model.getColumnCount()
|
|
self.model.add_row()
|
|
self.completeTablePanel()
|
|
|
|
def populate_action(self, event):
|
|
# print "populate_action"
|
|
column = 1 #block
|
|
all_blocks = [block.getUserName() for block in self.all_blocks]
|
|
blocks_in_table = [block for block in (self.model.getValueAt(r, column) for r in range(self.table.getRowCount())) if block in all_blocks]
|
|
|
|
if self.mode == "several trains":
|
|
not_allocated_blocks = self.super.occupied_blocks_not_allocated()
|
|
blocks_to_put_in_dropdown = [s for s in not_allocated_blocks]
|
|
self.populate(blocks_to_put_in_dropdown)
|
|
self.tidy()
|
|
else:
|
|
allocated_blocks = self.super.blocks_allocated()
|
|
# print "allocated_blocks", allocated_blocks
|
|
blocks_to_put_in_dropdown = [s for s in allocated_blocks]
|
|
# print "blocks to put in dropdown", blocks_to_put_in_dropdown
|
|
self.model.populate_existing(blocks_to_put_in_dropdown)
|
|
self.tidy()
|
|
|
|
# print "COMPLETING TABLE PANEL"
|
|
self.completeTablePanel()
|
|
|
|
def populate(self, blocks_to_put_in_dropdown):
|
|
|
|
for row in reversed(range(len(self.model.data))):
|
|
self.model.data.pop(row)
|
|
|
|
# append all blocks to put in dropdown
|
|
for block in blocks_to_put_in_dropdown:
|
|
# print "block", block
|
|
self.model.data.append(["", block, "click ->", False, 10, 100])
|
|
|
|
# delete rows with no blocks
|
|
for row in reversed(range(len(self.model.data))):
|
|
if self.model.data[row][1] == None or self.model.data[row][1] == "":
|
|
if len(self.model.data)>1:
|
|
self.model.data.pop(row)
|
|
self.completeTablePanel()
|
|
|
|
def remove_not_set_row(self):
|
|
# print "data", self.model.data
|
|
for row in reversed(range(len(self.model.data))):
|
|
# print "self.model.data[row][1]", self.model.data[row][1]
|
|
if self.model.data[row][1] == "":
|
|
self.model.data.pop(row)
|
|
|
|
def tidy_action(self,e):
|
|
self.tidy()
|
|
self.completeTablePanel()
|
|
|
|
def tidy(self):
|
|
self.remove_not_set_row()
|
|
size_of_one_row = 30
|
|
height = 130
|
|
for row in reversed(range(len(self.model.data))):
|
|
height += size_of_one_row
|
|
self.frame.setPreferredSize(Dimension(800, height));
|
|
|
|
def savetofile_action(self, event):
|
|
|
|
#Tidy
|
|
self.remove_not_set_row()
|
|
self.completeTablePanel()
|
|
|
|
if self.model.getRowCount() == 0:
|
|
return
|
|
|
|
dir = self.directory()
|
|
j = JFileChooser(dir);
|
|
j.setAcceptAllFileFilterUsed(False)
|
|
filter = FileNameExtensionFilter("text files txt", ["txt"])
|
|
j.addChoosableFileFilter(filter);
|
|
j.setDialogTitle("Select a .txt file");
|
|
|
|
ret = j.showSaveDialog(None);
|
|
if (ret == JFileChooser.APPROVE_OPTION) :
|
|
file = j.getSelectedFile()
|
|
if file == "" or file == None:
|
|
return
|
|
if FilenameUtils.getExtension(file.getName()).lower() == "txt" :
|
|
#filename is OK as-is
|
|
pass
|
|
else:
|
|
file = File(file.getParentFile(), FilenameUtils.getBaseName(file.getName())+".txt") # ALTERNATIVELY: remove the extension (if any) and replace it with ".xml"
|
|
|
|
else:
|
|
return
|
|
if self.logLevel > 0: print "savetofile action", file
|
|
my_list = []
|
|
[train, block, direction, length, speed_factor] = [0, 1, 2, 4, 5]
|
|
for row in range(len(self.model.data)):
|
|
train_name = str(self.model.data[row][train])
|
|
block_name = str(self.model.data[row][block])
|
|
train_direction = str(self.model.data[row][direction])
|
|
train_length = str(self.model.data[row][length])
|
|
train_speed_factor = str(self.model.data[row][speed_factor])
|
|
row_list = [train_name, block_name, train_direction,train_length,train_speed_factor]
|
|
if self.logLevel > 0: print "x", row
|
|
my_list.append(row_list)
|
|
if self.logLevel > 0: print "y", row
|
|
if self.logLevel > 0: print "A"
|
|
self.write_list(my_list,file)
|
|
|
|
|
|
def loadfromfile_action(self, event):
|
|
# load the file
|
|
dir = self.directory()
|
|
j = JFileChooser(dir)
|
|
j.setAcceptAllFileFilterUsed(False)
|
|
filter = FileNameExtensionFilter("text files txt", ["txt"])
|
|
j.setDialogTitle("Select a .txt file")
|
|
j.addChoosableFileFilter(filter)
|
|
|
|
# Automatically select the first file in the directory
|
|
files = j.getCurrentDirectory().listFiles()
|
|
j.setSelectedFile(files[0])
|
|
|
|
ret = j.showOpenDialog(None)
|
|
if (ret == JFileChooser.APPROVE_OPTION):
|
|
file = j.getSelectedFile()
|
|
if self.logLevel > 0: print "about to read list", file
|
|
my_list = self.read_list(file)
|
|
if self.logLevel > 0: print "my_list", my_list
|
|
for row in reversed(range(len(self.model.data))):
|
|
self.model.data.pop(row)
|
|
i = 0
|
|
[train, block, direction, length, speed_factor] = [0, 1, 2, 4, 5]
|
|
for row in my_list:
|
|
[train_val, block_val, direction_val, length_val, speed_factor_val] = row
|
|
self.model.add_row()
|
|
self.model.data[i][train] = train_val.replace('"','')
|
|
self.model.data[i][block] = block_val.replace('"','')
|
|
self.model.data[i][direction] = direction_val.replace('"','')
|
|
self.model.data[i][length] = length_val.replace('"','')
|
|
self.model.data[i][speed_factor] = speed_factor_val.replace('"','')
|
|
i += 1
|
|
|
|
self.completeTablePanel1()
|
|
self.completeTablePanel()
|
|
|
|
msg = "Deleting invalid rows"
|
|
result = OptionDialog().displayMessage(msg)
|
|
if result == JOptionPane.NO_OPTION:
|
|
return
|
|
|
|
# check the loaded contents
|
|
# 1) check that the trains are valid
|
|
# 2) check that the blocks are occupied by valid trains
|
|
# if either of the above are not valic we blank the entries
|
|
# 3) Tidy
|
|
|
|
# check the trains are valid
|
|
b = False
|
|
trains_to_put_in_dropdown = [t for t in self.non_allocated_trains]
|
|
for row in reversed(range(len(self.model.data))):
|
|
#if len(self.model.data) >1:
|
|
# print "row", row
|
|
if self.model.data[row][train] not in trains_to_put_in_dropdown:
|
|
self.model.data.pop(row)
|
|
|
|
not_allocated_blocks = self.super.occupied_blocks_not_allocated()
|
|
for row in reversed(range(len(self.model.data))):
|
|
if self.model.data[row][block] not in not_allocated_blocks:
|
|
self.model.data.pop(row)
|
|
self.completeTablePanel1()
|
|
self.completeTablePanel()
|
|
|
|
def deletesavedfile_action(self, event):
|
|
|
|
while True:
|
|
#Tidy
|
|
self.remove_not_set_row()
|
|
self.completeTablePanel()
|
|
|
|
if self.model.getRowCount() == 0:
|
|
return
|
|
|
|
dir = self.directory()
|
|
j = JFileChooser(dir);
|
|
j.setAcceptAllFileFilterUsed(False)
|
|
filter = FileNameExtensionFilter("text files txt", ["txt"])
|
|
j.addChoosableFileFilter(filter);
|
|
|
|
j.setDialogTitle("Delete not wanted files");
|
|
|
|
ret = j.showDialog(None, "Delete");
|
|
if ret == JFileChooser.APPROVE_OPTION:
|
|
file = j.getSelectedFile()
|
|
if file == "" or file == None:
|
|
return
|
|
if file.exists():
|
|
os.remove(file.getAbsolutePath())
|
|
# print("File " + file.getName() + " has been deleted successfully.")
|
|
else:
|
|
print("The selected file does not exist.")
|
|
else:
|
|
print("File selection cancelled.")
|
|
return
|
|
|
|
def cancel_action(self, event):
|
|
title = ""
|
|
msg = "Do you wish to exit without saving?"
|
|
opt1 = "Exit, don't save"
|
|
opt2 = "Exit and Save Results"
|
|
reply = OptionDialog().customQuestionMessage2str(msg, title, opt1, opt2)
|
|
if reply == opt1:
|
|
self.frame.dispatchEvent(WindowEvent(self.frame, WindowEvent.WINDOW_CLOSING))
|
|
else: #opt2
|
|
self.save_action(None)
|
|
|
|
|
|
def save_action(self, event):
|
|
[train, block, direction, length, speed_factor] = [0, 1, 2, 4, 5]
|
|
# print "save action"
|
|
for row in reversed(range(len(self.model.data))):
|
|
train_name = self.model.data[row][train]
|
|
block_name = self.model.data[row][block]
|
|
train_direction = self.model.data[row][direction]
|
|
train_length = self.model.data[row][length]
|
|
train_speed_factor = self.model.data[row][speed_factor]
|
|
|
|
result = train_direction
|
|
if result == "forward":
|
|
train_direction = "reverse"
|
|
else:
|
|
train_direction = "forward"
|
|
if self.logLevel > 3: print "train_name", train_name,"train_direction", train_direction
|
|
|
|
if train_name != "" and train_name != None and block_name != "" and block_name != None:
|
|
if train_name not in trains_allocated:
|
|
trains_allocated.append(train_name)
|
|
self.super.add_to_train_list_and_set_new_train_location0(train_name, block_name,
|
|
train_direction, train_length, train_speed_factor)
|
|
self.super.set_blockcontents(block_name, train_name)
|
|
self.super.set_length0(train_name)
|
|
self.super.set_speed_factor0(train_name)
|
|
|
|
self.model.data.pop(row)
|
|
|
|
# print "end save action"
|
|
self.completeTablePanel()
|
|
if self.model.getRowCount() == 0:
|
|
self.frame.dispatchEvent(WindowEvent(self.frame, WindowEvent.WINDOW_CLOSING))
|
|
def set_train_selections(self, combobox):
|
|
pass
|
|
def directory(self):
|
|
path = jmri.util.FileUtil.getUserFilesPath() + "dispatcher" + java.io.File.separator + "setup_trains"
|
|
if not os.path.exists(path):
|
|
os.makedirs(path)
|
|
return path + java.io.File.separator
|
|
def write_list(self, a_list, file):
|
|
# store list in binary file so 'wb' mode
|
|
#file = self.directory() + "blockDirections.txt"
|
|
if self.logLevel > 0: print "block_info" , a_list
|
|
if self.logLevel > 0: print "file" , file
|
|
file = str(file)
|
|
with open(file, 'wb') as fp:
|
|
pass
|
|
if self.logLevel > 0: print "V"
|
|
with open(file, 'wb') as fp:
|
|
if self.logLevel > 0: print "B"
|
|
for items in a_list:
|
|
if self.logLevel > 0: print "C", items
|
|
i = 0
|
|
for item in items:
|
|
if self.logLevel > 0: print "item", item
|
|
fp.write('"%s"' %item)
|
|
if i != 4: fp.write(",")
|
|
i+=1
|
|
fp.write('\n')
|
|
|
|
# Read list to memory
|
|
def read_list(self, file):
|
|
file = str(file)
|
|
if self.logLevel > 0: print "read list", file
|
|
# for reading also binary mode is important
|
|
#file = self.directory() + "blockDirections.txt"
|
|
n_list = []
|
|
# try:
|
|
with open(file, 'rb') as fp:
|
|
for line in fp:
|
|
if self.logLevel > 0: print "line" , line
|
|
x = line[:-1]
|
|
if self.logLevel > 0: print x
|
|
y = x.split(",")
|
|
#y = [item.replace('"','') for item in y]
|
|
if self.logLevel > 0: print "y" , y
|
|
n_list.append(y)
|
|
|
|
return n_list
|
|
|
|
class MyModelListener(TableModelListener):
|
|
|
|
def __init__(self, class_createandshowGUI, class_NewTrainMaster):
|
|
self.class_createandshowGUI = class_createandshowGUI
|
|
self.class_NewTrainMaster = class_NewTrainMaster
|
|
self.super = super
|
|
self.cancel = False
|
|
self.mode = class_createandshowGUI.mode
|
|
def tableChanged(self, e) :
|
|
global train_direction_gbl
|
|
global trains_allocated
|
|
row = e.getFirstRow()
|
|
column = e.getColumn()
|
|
model = e.getSource()
|
|
columnName = model.getColumnName(column)
|
|
data = model.getValueAt(row, column)
|
|
class_createandshowGUI = self.class_createandshowGUI
|
|
class_NewTrainMaster = self.class_NewTrainMaster
|
|
tablemodel = class_createandshowGUI.model
|
|
if column == 0: #trains
|
|
class_createandshowGUI.combobox0.removeAllItems()
|
|
#the non_allocated trains are stored in self.non_allocated_trains
|
|
# each time a cell is edited we regenerate the list if trains in the drop down
|
|
# we set to the non_allocated_trains less the ones marked ro be allocated in the table
|
|
|
|
trains_in_table = [train for train in (model.getValueAt(r, column) for r in range(class_createandshowGUI.table.getRowCount())) if train in class_createandshowGUI.all_trains]
|
|
# print "trains in table", trains_in_table
|
|
# starting with non_allocated_trains remove the ones in my_train_list
|
|
#trains_to_put_in_dropdown = [t for t in class_createandshowGUI.non_allocated_trains if t not in trains_in_table]
|
|
if self.mode == "several trains":
|
|
trains_to_put_in_dropdown = [t for t in class_createandshowGUI.non_allocated_trains]
|
|
else:
|
|
trains_to_put_in_dropdown = [t for t in class_createandshowGUI.allocated_trains]
|
|
# print "trains_to_put_in_dropdown", trains_to_put_in_dropdown
|
|
class_createandshowGUI.combobox0.removeAllItems()
|
|
#put the remaining trains in the combo dropdown
|
|
class_createandshowGUI.combobox0.addItem("")
|
|
[class_createandshowGUI.combobox0.addItem(train) for train in trains_to_put_in_dropdown]
|
|
class_createandshowGUI.trainColumn.setCellEditor(DefaultCellEditor(class_createandshowGUI.combobox0));
|
|
|
|
# populate the length of the engine
|
|
train_name = model.getValueAt(row, 0)
|
|
if train_name != "":
|
|
[engine, train_length] = class_NewTrainMaster.get_train_length(train_name)
|
|
model.setValueAt(train_length, row,4)
|
|
|
|
#populate the speed factor of the engine
|
|
train_name = model.getValueAt(row, 0)
|
|
if train_name != "":
|
|
[engine, train_speed_factor] = class_NewTrainMaster.get_train_speed_factor(train_name)
|
|
model.setValueAt(train_speed_factor, row,5)
|
|
# print "%%%%%%%%%%%%%%%%end col1 %%%%%%%%%%%%%%%%%%%%%%%%"
|
|
elif column == 1: # sections
|
|
class_createandshowGUI.combobox1.removeAllItems()
|
|
# print "%%%%%%%%%%%%%%%%start col2 %%%%%%%%%%%%%%%%%%%%%%%%"
|
|
# print "class_createandshowGUI.all_sections", class_createandshowGUI.all_sections
|
|
# print "range class_createandshowGUI.table.getRowCount()", range(class_createandshowGUI.table.getRowCount())
|
|
for r in range(class_createandshowGUI.table.getRowCount()):
|
|
# print "r",r,"column",column
|
|
# print "r", r, "(model.getValueAt(r, column)", (model.getValueAt(r, column))
|
|
pass
|
|
all_sections = [str(block.getUserName()) for block in class_createandshowGUI.all_sections]
|
|
all_blocks = [str(block.getUserName()) for block in class_createandshowGUI.all_blocks]
|
|
# print "all_sections", all_sections
|
|
trains_in_table = \
|
|
[train for train in (model.getValueAt(r, column) for r in range(class_createandshowGUI.table.getRowCount()))
|
|
if train in class_createandshowGUI.all_trains]
|
|
X = [str(model.getValueAt(r, column)) for r in range(class_createandshowGUI.table.getRowCount())]
|
|
# print "X", X
|
|
blocks_in_table = [block for block in X if block in all_blocks]
|
|
# print "sections in table", blocks_in_table
|
|
# starting with non_allocated_trains remove the ones in my_train_list
|
|
# print "sections to choose", class_createandshowGUI.sections_to_choose
|
|
# print "trains_in_table",trains_in_table
|
|
# print "sections True", class_createandshowGUI.train_blocks(trains_in_table, True)
|
|
# print "sections False", class_createandshowGUI.train_blocks(trains_in_table, False)
|
|
allocated_blocks = class_createandshowGUI.super.occupied_blocks_allocated()
|
|
not_allocated_blocks = class_createandshowGUI.super.occupied_blocks_not_allocated()
|
|
#blocks_to_put_in_dropdown = [s for s in not_allocated_blocks if s not in blocks_in_table]
|
|
blocks_to_put_in_dropdown = [s for s in not_allocated_blocks]
|
|
# print("blocks_to_put_in_dropdown", blocks_to_put_in_dropdown)
|
|
#put the remaining trains in the combo dropdown
|
|
class_createandshowGUI.combobox1.removeAllItems()
|
|
class_createandshowGUI.combobox1.addItem("")
|
|
[class_createandshowGUI.combobox1.addItem(section) for section in blocks_to_put_in_dropdown]
|
|
|
|
# [class_createandshowGUI.combobox1.addItem(section) for section in blocks_to_put_in_dropdown]
|
|
class_createandshowGUI.sectionColumn.setCellEditor(DefaultCellEditor(class_createandshowGUI.combobox1));
|
|
# print "%%%%%%%%%%%%%%%%end col2 %%%%%%%%%%%%%%%%%%%%%%%%"
|
|
elif column == 3: # show the direction on the layout to enable the facing direction to be chosen
|
|
# print "cancel on entry", self.cancel
|
|
if self.cancel == True:
|
|
self.cancel = False
|
|
# print "set cancel", self.cancel
|
|
return
|
|
station_block_name = model.getValueAt(row, 1)
|
|
# print "station_block_name", station_block_name
|
|
if station_block_name != None and station_block_name != "" and station_block_name != "None Available":
|
|
# print "here"
|
|
[edge, train_direction_gbl, result] = class_createandshowGUI.super.highlight_penultimate_block(station_block_name)
|
|
# print [edge, train_direction_gbl, result]
|
|
self.cancel = True
|
|
model.setValueAt(result, row, 2) #set the direction box to the result (forwards or reverse)
|
|
model.setValueAt(False, row, 3) #reset the check box (need the self.cancel code to stop retriggering of the event code)
|
|
else:
|
|
OptionDialog().displayMessage("must set Block first")
|
|
|
|
class ComboBoxCellRenderer (TableCellRenderer):
|
|
def getTableCellRendererComponent(self, jtable, value, isSelected, hasFocus, row, column):
|
|
combo = JComboBox()
|
|
combo.setSelectedItem(value)
|
|
return combo
|
|
|
|
def getTableCellRendererComponent(self, jtable, value, isSelected, hasFocus, row, column) :
|
|
panel = self.createPanel(value)
|
|
return panel
|
|
|
|
def createPanel(self, s) :
|
|
p = JPanel(BorderLayout())
|
|
p.add(JLabel(s, JLabel.LEFT), BorderLayout.WEST)
|
|
icon = UIManager.getIcon("Table.descendingSortIcon");
|
|
p.add(JLabel(icon, JLabel.RIGHT), BorderLayout.EAST);
|
|
p.setBorder(BorderFactory.createLineBorder(Color.blue));
|
|
return p;
|
|
|
|
class MyTableModel (DefaultTableModel):
|
|
|
|
columnNames = ["Train",
|
|
"Block",
|
|
"Set Direction",
|
|
"Direction Facing",
|
|
"Length (scale metres)",
|
|
"Speed Factor"]
|
|
|
|
def __init__(self):
|
|
self.data = []
|
|
self.add_row()
|
|
|
|
|
|
|
|
def add_row(self):
|
|
self.data.append(["", "", "click ->", False, 10, 100])
|
|
|
|
def populate_existing(self, blocks_to_put_in_dropdown):
|
|
# print "populate existing"
|
|
for row in reversed(range(len(self.data))):
|
|
self.data.pop(row)
|
|
items_to_put_in_dropdown = []
|
|
for block_name in blocks_to_put_in_dropdown:
|
|
train_name = NewTrainMaster().get_blockcontents(block_name)
|
|
# if train_name == "" or train_name is None:
|
|
# continue
|
|
if train_name == "" or train_name is None:
|
|
train_direction = "unassigned"
|
|
train_length = -1
|
|
current_speed_factor = -1
|
|
else:
|
|
# print "block_name", block_name, "train_name", train_name
|
|
[engine,current_length] = NewTrainMaster().get_train_length(train_name)
|
|
train_length = engine.getLength()
|
|
[engine, current_speed_factor] = NewTrainMaster().get_train_speed_factor(train_name)
|
|
# current_speed_factor_str = "speed factor " + current_speed_factor
|
|
current_speed_factor_str = engine.getComment()
|
|
train = trains[train_name]
|
|
result = train["direction"]
|
|
# print "train[direction] loading to put in dropdown", result
|
|
if result == "forward":
|
|
train_direction = "reverse"
|
|
else:
|
|
train_direction = "forward"
|
|
# print "train", train, train_direction
|
|
items_to_put_in_dropdown.append([train_name,block_name,train_direction, False, train_length, current_speed_factor ])
|
|
|
|
# print "items_to_put_in_dropdown", items_to_put_in_dropdown
|
|
for item in items_to_put_in_dropdown:
|
|
self.data.append(item)
|
|
|
|
# self.completeTablePanel()
|
|
pass
|
|
|
|
def getColumnCount(self) :
|
|
return len(self.columnNames)
|
|
|
|
|
|
def getRowCount(self) :
|
|
return len(self.data)
|
|
|
|
|
|
def getColumnName(self, col) :
|
|
return self.columnNames[col]
|
|
|
|
|
|
def getValueAt(self, row, col) :
|
|
return self.data[row][col]
|
|
|
|
def getColumnClass(self, c) :
|
|
if c <= 1:
|
|
return java.lang.Boolean.getClass(JComboBox)
|
|
return java.lang.Boolean.getClass(self.getValueAt(0,c))
|
|
|
|
|
|
#only include if table editable
|
|
def isCellEditable(self, row, col) :
|
|
# Note that the data/cell address is constant,
|
|
# no matter where the cell appears onscreen.
|
|
if col != 2:
|
|
return True
|
|
else:
|
|
return False
|
|
|
|
# only include if data can change.
|
|
def setValueAt(self, value, row, col) :
|
|
self.data[row][col] = value
|
|
self.fireTableCellUpdated(row, col)
|