Files
JIMRI/jython/operations/OperationsAssignUnitsToFlatcars.py
T
2026-06-17 14:00:51 +02:00

175 lines
10 KiB
Python

# Sample script to assign containers and trailers to flat cars.
#
#
# Author: Daniel Boudreau, copyright 2015
# Part of the JMRI distribution
#
# To use this script you must provide the type names for containers and trailers, and the type names for the flatcars to use.
# You must also enter the train name that will service them. The train should not service the flatcars, this script will
# do the flatcar assignments based on the container or trailer destinations. Run this script after the train is built. The containers
# and trailers must resside on the same track as the flatcars.
#
# When there isn't enough flatcars for the containers or trailers, the script will produce a warning message and remove them
# from the train.
#
# Some minor issues with this script:
# It will never assign two 20 foot containers and one 40 foot container to the same flatcar. It can do one of each.
# It doesn't consider the best allocation of flatcars, it can assign a single trailer to a flatcar that can hold two trailers,
# even of there's a flatcar available that can only hold one trailer.
#
import jmri
import javax.swing.JOptionPane;
class AssignTrailersToCars(jmri.jmrit.automat.AbstractAutomaton):
def init(self):
# train (use train name)
self.trainName = "85"
# the flatcar load name
self.loadNameTrailers = "Trailers"
self.loadNameContainers = "Containers"
# flatcar names and the number of container that can be carried
self.container20 = [["Flatcar-COFC", 4]]
self.container40 = [["Flatcar-COFC", 2]]
# flatcar names and the number of trailers that can be carried. This defines the order in which flatcars are allocated.
self.trailerPup = [["Flatcar-TOFC-(X)", 3], ["Flatcar-TOFC", 2], ["Flatcar-TOFC-(S)", 1], ["Flatcar-COFC", 2]]
self.trailer = [["Flatcar-TOFC", 2], ["Flatcar-TOFC-(S)", 1], ["Flatcar-TOFC-(X)", 2], ["Flatcar-COFC", 2]]
# Try to place reefer on single flatcars first, as an example of how to change the order flatcars are allocated
self.trailerReefer = [["Flatcar-TOFC-(S)", 1], ["Flatcar-TOFC", 2], ["Flatcar-TOFC-(X)", 2], ["Flatcar-COFC", 2]]
# containers and trailers, which flatcars can carry them, flatcar load name
self.units = [["Container-20", self.container20, self.loadNameContainers], ["Container-40", self.container40, self.loadNameContainers],
["Trailer-Pup", self.trailerPup, self.loadNameTrailers], ["Trailer-UPS", self.trailer, self.loadNameTrailers],
["Trailer-USMail", self.trailer, self.loadNameTrailers], ["Trailer-Reefer", self.trailerReefer, self.loadNameTrailers],
["Trailer", self.trailer, self.loadNameTrailers]]
# used when creating kernel names
self.regex = "_$_"
print ('Assigning flatcars to train ({})'.format(self.trainName))
return
def handle(self):
# first some checking
# determine if trailer, container, and flatcar names exist
carTypes = jmri.InstanceManager.getDefault(jmri.jmrit.operations.rollingstock.cars.CarTypes)
for unitArray in self.units:
unitName = unitArray[0]
if (carTypes.containsName(unitName) == False):
print ('Error car type ({}) not found'.format(unitName))
return False
flatcarOptions = unitArray[1]
flatcarLoadName = unitArray[2]
for flatcarOption in flatcarOptions:
number = flatcarOption[1]
flatcarName = flatcarOption[0]
if (carTypes.containsName(flatcarName) == False):
print ('Error flatcar ({}) for ({}) not found'.format(flatcarName, unitName))
return False
print ('{} ({}) can be carried by flatcar ({}) load name ({})'.format(number, unitName, flatcarName, flatcarLoadName))
# get the train manager
trainManager = jmri.InstanceManager.getDefault(jmri.jmrit.operations.trains.TrainManager)
# determine if train exists and is built
train = trainManager.getTrainByName(self.trainName)
if train == None:
print ('Error Train ({}) not found'.format(self.trainName))
return False
if not train.isBuilt():
print ('Error Train ({}) not built'.format(self.trainName))
return False
# get the car manager
carManager = jmri.InstanceManager.getDefault(jmri.jmrit.operations.rollingstock.cars.CarManager)
# get the kernel manager
kernelManager = jmri.InstanceManager.getDefault(jmri.jmrit.operations.rollingstock.cars.KernelManager)
# get a list of cars from the manager
carList = carManager.getByTrainDestinationList(train)
flatcarList = carManager.getAvailableTrainList(train)
print ('{} cars assigned to train ({})'.format(carList.size(), self.trainName))
for unitArray in self.units:
unitName = unitArray[0]
flatcarOptions = unitArray[1]
flatcarLoadName = unitArray[2]
print ('Searching for ({}):'.format(unitName))
for unit in carList:
if unit.getTypeName() == unitName:
print (' Loading ({}) ({}) destination ({}, {}) final destination ({}, {})'.format(unit.toString(), unitName, unit.getDestinationName(), unit.getDestinationTrackName(), unit.getFinalDestinationName(), unit.getFinalDestinationTrackName()))
if not unit.getKernel() == None:
print (' ({}) assigned to kernel ({})'.format(unit.toString(), unit.getKernelName()))
continue
else:
print (' ({}) isn''t assigned to a kernel'.format(unit.toString()))
for flatcarOption in flatcarOptions:
flatcarName = flatcarOption[0]
number = flatcarOption[1]
for flatcar in flatcarList:
if flatcar.getTypeName() == flatcarName and flatcar.getTrack() == unit.getTrack():
print (' Found flatcar ({}) type ({})'.format(flatcar.toString(), flatcarName))
if flatcar.getKernel() == None:
# create new kernel using train name and unit's id
kernel = kernelManager.newKernel(self.trainName + self.regex + unit.toString())
print (' Add ({}) and flatcar ({}) to kernel ({})'.format(unit.toString(), flatcar.toString(), kernel.getName()))
unit.setKernel(kernel)
flatcar.setKernel(kernel)
# show flatcar first in the manifest or switch list, then the units being carried
flatcar.setBlocking(0)
unit.setBlocking(1)
# now add flatcar to train
# force flatcar to destination
flatcar.setDestination(unit.getDestination(), unit.getDestinationTrack(), True)
flatcar.setFinalDestination(unit.getFinalDestination())
flatcar.setFinalDestinationTrack(unit.getFinalDestinationTrack())
flatcar.setRouteLocation(unit.getRouteLocation())
flatcar.setRouteDestination(unit.getRouteDestination())
flatcar.setLoadName(flatcarLoadName)
flatcar.setTrain(train)
train.setModified(True)
break
elif flatcar.getKernel().getSize() <= number:
kernel = flatcar.getKernel()
# determine if kernel is going to the same destination as this unit
if not unit.getDestination() == flatcar.getDestination() or not unit.getDestinationTrack() == flatcar.getDestinationTrack():
print (' Can''t use flatcar ({}) destination ({}, {})'.format(flatcar.toString(), flatcar.getDestinationName(), flatcar.getDestinationTrackName()))
continue
if not unit.getFinalDestination() == flatcar.getFinalDestination() or not unit.getFinalDestinationTrack() == flatcar.getFinalDestinationTrack():
print (' Can''t use flatcar ({}) final destination ({}, {})'.format())
continue
if not flatcarLoadName == flatcar.getLoadName():
print (' Can''t use flatcar ({}) load name ({})'.format(flatcar.toString(), flatcar.getLoadName()))
continue
print (' Add ({}) to kernel ({})'.format(unit.toString(), kernel.getName()))
unit.setKernel(kernel)
unit.setBlocking(kernel.getSize())
train.setModified(True)
break
else:
print (' Flatcar ({}) full'.format(flatcar.toString()))
else:
continue
break
if unit.getKernel() == None:
title = "Warning couldn't find enough flatcars for train (" + self.trainName + ")"
message = "Warning (" + unit.toString() + ") type (" + unit.getTypeName() + ") at (" + unit.getLocationName() + ") not assigned to a flatcar, train (" + self.trainName + ")"
print (message)
javax.swing.JOptionPane.showMessageDialog(None, message, title, javax.swing.JOptionPane.WARNING_MESSAGE)
# remove trailer from train
unit.setRouteLocation(None)
unit.setRouteDestination(None)
unit.setTrain(None)
train.setModified(True)
return False # all done, don't repeat again
AssignTrailersToCars().start() # create one of these, and start it running