use of jmri.jmrit.operations.routes.RouteLocation in project JMRI by JMRI.
the class OperationsSetupPanel method checkRoutes.
// if max train length has changed, check routes
private void checkRoutes() {
int maxLength = Integer.parseInt(maxLengthTextField.getText());
if (maxLength > Setup.getMaxTrainLength()) {
JOptionPane.showMessageDialog(this, Bundle.getMessage("RouteLengthNotModified"), MessageFormat.format(Bundle.getMessage("MaxTrainLengthIncreased"), new Object[] { maxLength, Setup.getLengthUnit().toLowerCase() }), JOptionPane.INFORMATION_MESSAGE);
}
if (maxLength < Setup.getMaxTrainLength()) {
StringBuilder sb = new StringBuilder();
List<Route> routes = RouteManager.instance().getRoutesByNameList();
int count = 0;
for (Route route : routes) {
for (RouteLocation rl : route.getLocationsBySequenceList()) {
if (rl.getMaxTrainLength() > maxLength) {
String s = MessageFormat.format(Bundle.getMessage("RouteMaxLengthExceeds"), new Object[] { route.getName(), rl.getName(), rl.getMaxTrainLength(), maxLength });
log.info(s);
sb.append(s).append(NEW_LINE);
count++;
break;
}
}
// maximum of 20 route warnings
if (count > 20) {
sb.append(Bundle.getMessage("More")).append(NEW_LINE);
break;
}
}
if (sb.length() > 0) {
JOptionPane.showMessageDialog(this, sb.toString(), Bundle.getMessage("YouNeedToAdjustRoutes"), JOptionPane.WARNING_MESSAGE);
if (JOptionPane.showConfirmDialog(null, MessageFormat.format(Bundle.getMessage("ChangeMaximumTrainDepartureLength"), new Object[] { maxLength }), Bundle.getMessage("ModifyAllRoutes"), JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION) {
routes.stream().forEach((route) -> {
route.getLocationsBySequenceList().stream().filter((rl) -> (rl.getMaxTrainLength() > maxLength)).map((rl) -> {
log.debug("Setting route ({}) routeLocation ({}) max traim length to {}", route.getName(), rl.getName(), // NOI18N
maxLength);
return rl;
}).forEach((rl) -> {
rl.setMaxTrainLength(maxLength);
});
});
// save the route changes
RouteManagerXml.instance().writeOperationsFile();
}
}
}
}
use of jmri.jmrit.operations.routes.RouteLocation in project JMRI by JMRI.
the class TrainBuilder method build.
private void build() throws BuildFailedException {
log.debug("Building train ({})", _train.getName());
_train.setStatusCode(Train.CODE_BUILDING);
_train.setBuilt(false);
_train.setLeadEngine(null);
// create build report file
File file = TrainManagerXml.instance().createTrainBuildReportFile(_train.getName());
try {
_buildReport = new PrintWriter(new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file), "UTF-8")), // NOI18N
true);
} catch (IOException e) {
log.error("Can not open build report file: " + file.getName());
return;
}
Date startTime = new Date();
addLine(_buildReport, ONE, MessageFormat.format(Bundle.getMessage("BuildReportMsg"), new Object[] { _train.getName(), startTime }));
addLine(_buildReport, ONE, MessageFormat.format(Bundle.getMessage("BuildReportVersion"), new Object[] { Version.name() }));
// show the various build detail levels
addLine(_buildReport, THREE, Bundle.getMessage("buildReportLevelThree"));
addLine(_buildReport, FIVE, Bundle.getMessage("buildReportLevelFive"));
addLine(_buildReport, SEVEN, Bundle.getMessage("buildReportLevelSeven"));
if (Setup.getRouterBuildReportLevel().equals(Setup.BUILD_REPORT_DETAILED)) {
addLine(_buildReport, SEVEN, Bundle.getMessage("buildRouterReportLevelDetailed"));
} else if (Setup.getRouterBuildReportLevel().equals(Setup.BUILD_REPORT_VERY_DETAILED)) {
addLine(_buildReport, SEVEN, Bundle.getMessage("buildRouterReportLevelVeryDetailed"));
}
if (!Setup.getComment().trim().isEmpty()) {
addLine(_buildReport, ONE, BLANK_LINE);
addLine(_buildReport, ONE, Setup.getComment());
}
addLine(_buildReport, ONE, BLANK_LINE);
if (_train.getRoute() == null) {
throw new BuildFailedException(MessageFormat.format(Bundle.getMessage("buildErrorRoute"), new Object[] { _train.getName() }));
}
// get the train's route
_routeList = _train.getRoute().getLocationsBySequenceList();
if (_routeList.size() < 1) {
throw new BuildFailedException(MessageFormat.format(Bundle.getMessage("buildErrorNeedRoute"), new Object[] { _train.getName() }));
}
// train departs
_departLocation = locationManager.getLocationByName(_train.getTrainDepartsName());
if (_departLocation == null) {
throw new BuildFailedException(MessageFormat.format(Bundle.getMessage("buildErrorNeedDepLoc"), new Object[] { _train.getName() }));
}
// train terminates
_terminateLocation = locationManager.getLocationByName(_train.getTrainTerminatesName());
if (_terminateLocation == null) {
throw new BuildFailedException(MessageFormat.format(Bundle.getMessage("buildErrorNeedTermLoc"), new Object[] { _train.getName() }));
}
// show train build options in detailed mode
addLine(_buildReport, FIVE, Bundle.getMessage("MenuItemBuildOptions") + ":");
if (Setup.isBuildAggressive()) {
addLine(_buildReport, FIVE, Bundle.getMessage("BuildModeAggressive"));
addLine(_buildReport, FIVE, MessageFormat.format(Bundle.getMessage("BuildNumberPasses"), new Object[] { Setup.getNumberPasses() }));
if (Setup.isStagingTrackImmediatelyAvail() && _departLocation.isStaging()) {
addLine(_buildReport, FIVE, Bundle.getMessage("BuildStagingTrackAvail"));
}
} else {
addLine(_buildReport, FIVE, Bundle.getMessage("BuildModeNormal"));
}
if (Setup.isTrainIntoStagingCheckEnabled() && _terminateLocation.isStaging()) {
addLine(_buildReport, FIVE, Bundle.getMessage("buildOptionRestrictStaging"));
}
// warn if car routing is disabled
if (!Setup.isCarRoutingEnabled()) {
addLine(_buildReport, FIVE, Bundle.getMessage("RoutingDisabled"));
} else {
if (Setup.isCarRoutingViaYardsEnabled()) {
addLine(_buildReport, FIVE, Bundle.getMessage("RoutingViaYardsEnabled"));
}
if (Setup.isCarRoutingViaStagingEnabled()) {
addLine(_buildReport, FIVE, Bundle.getMessage("RoutingViaStagingEnabled"));
}
if (Setup.isOnlyActiveTrainsEnabled()) {
addLine(_buildReport, FIVE, Bundle.getMessage("OnlySelectedTrains"));
// list the selected trains
for (Train train : TrainManager.instance().getTrainsByNameList()) {
if (train.isBuildEnabled()) {
addLine(_buildReport, SEVEN, MessageFormat.format(Bundle.getMessage("buildTrainNameAndDesc"), new Object[] { train.getName(), train.getDescription() }));
}
}
if (!_train.isBuildEnabled()) {
addLine(_buildReport, FIVE, MessageFormat.format(Bundle.getMessage("buildTrainNotSelected"), new Object[] { _train.getName() }));
}
}
if (Setup.isCheckCarDestinationEnabled()) {
addLine(_buildReport, FIVE, Bundle.getMessage("CheckCarDestination"));
}
}
if (_train.isBuildTrainNormalEnabled()) {
addLine(_buildReport, FIVE, Bundle.getMessage("NormalModeWhenBuilding"));
}
if (_train.isSendCarsToTerminalEnabled()) {
addLine(_buildReport, FIVE, MessageFormat.format(Bundle.getMessage("SendToTerminal"), new Object[] { _terminateLocation.getName() }));
}
if ((_train.isAllowReturnToStagingEnabled() || Setup.isAllowReturnToStagingEnabled()) && _departLocation.isStaging() && _departLocation == _terminateLocation) {
addLine(_buildReport, FIVE, Bundle.getMessage("AllowCarsToReturn"));
}
if (_train.isAllowLocalMovesEnabled()) {
addLine(_buildReport, FIVE, Bundle.getMessage("AllowLocalMoves"));
}
if (_train.isAllowThroughCarsEnabled()) {
addLine(_buildReport, FIVE, Bundle.getMessage("AllowThroughCars"));
}
if (_train.isServiceAllCarsWithFinalDestinationsEnabled()) {
addLine(_buildReport, FIVE, Bundle.getMessage("ServiceAllCars"));
}
if (_train.isSendCarsWithCustomLoadsToStagingEnabled()) {
addLine(_buildReport, FIVE, Bundle.getMessage("SendCustomToStaging"));
}
if (_train.isBuildConsistEnabled()) {
addLine(_buildReport, FIVE, Bundle.getMessage("BuildConsist"));
addLine(_buildReport, FIVE, MessageFormat.format(Bundle.getMessage("BuildConsistHPT"), new Object[] { Setup.getHorsePowerPerTon() }));
}
// add line
addLine(_buildReport, ONE, BLANK_LINE);
// TODO: DAB control minimal build by each train
if (_train.getTrainDepartsRouteLocation().getMaxCarMoves() > _departLocation.getNumberRS() && Control.fullTrainOnly) {
throw new BuildFailedException(MessageFormat.format(Bundle.getMessage("buildErrorCars"), new Object[] { Integer.toString(_departLocation.getNumberRS()), _train.getTrainDepartsName(), _train.getName() }));
}
addLine(_buildReport, THREE, MessageFormat.format(Bundle.getMessage("buildTrainRoute"), new Object[] { _train.getName(), _train.getRoute().getName() }));
// get the number of requested car moves for this train
int requested = 0;
for (RouteLocation rl : _routeList) {
// check to see if there's a location for each stop in the route
// this checks for a deleted location
Location location = locationManager.getLocationByName(rl.getName());
if (location == null || rl.getLocation() == null) {
throw new BuildFailedException(MessageFormat.format(Bundle.getMessage("buildErrorLocMissing"), new Object[] { _train.getRoute().getName() }));
}
// train doesn't drop or pick up cars from staging locations found in middle of a route
if (location.isStaging() && rl != _train.getTrainDepartsRouteLocation() && rl != _train.getTrainTerminatesRouteLocation()) {
addLine(_buildReport, ONE, MessageFormat.format(Bundle.getMessage("buildLocStaging"), new Object[] { rl.getName() }));
// don't allow car moves for this location
rl.setCarMoves(rl.getMaxCarMoves());
// if a location is skipped, no car drops or pick ups
} else if (_train.skipsLocation(rl.getId())) {
addLine(_buildReport, THREE, MessageFormat.format(Bundle.getMessage("buildLocSkippedMaxTrain"), new Object[] { rl.getName(), _train.getName(), rl.getMaxTrainLength(), Setup.getLengthUnit().toLowerCase() }));
// don't allow car moves for this location
rl.setCarMoves(rl.getMaxCarMoves());
} else if (!rl.isDropAllowed() && !rl.isPickUpAllowed()) {
addLine(_buildReport, THREE, MessageFormat.format(Bundle.getMessage("buildLocNoDropsOrPickups"), new Object[] { rl.getName(), rl.getMaxTrainLength(), Setup.getLengthUnit().toLowerCase() }));
// don't allow car moves for this location
rl.setCarMoves(rl.getMaxCarMoves());
} else {
// we're going to use this location, so initialize the location
// clear the number of moves
rl.setCarMoves(0);
// add up the total number of car moves requested
requested += rl.getMaxCarMoves();
// show the type of moves allowed at this location
if (location.isStaging() && rl.isPickUpAllowed() && rl == _train.getTrainDepartsRouteLocation()) {
addLine(_buildReport, THREE, MessageFormat.format(Bundle.getMessage("buildStagingDeparts"), new Object[] { rl.getName(), rl.getMaxCarMoves(), rl.getMaxTrainLength(), Setup.getLengthUnit().toLowerCase() }));
} else if (location.isStaging() && rl.isDropAllowed() && rl == _train.getTrainTerminatesRouteLocation()) {
addLine(_buildReport, THREE, MessageFormat.format(Bundle.getMessage("buildStagingTerminates"), new Object[] { rl.getName(), rl.getMaxCarMoves() }));
} else if (rl == _train.getTrainTerminatesRouteLocation() && rl.isDropAllowed() && rl.isPickUpAllowed()) {
addLine(_buildReport, THREE, MessageFormat.format(Bundle.getMessage("buildLocTerminatesMoves"), new Object[] { rl.getName(), rl.getMaxCarMoves() }));
} else if (rl.isDropAllowed() && rl.isPickUpAllowed()) {
addLine(_buildReport, THREE, MessageFormat.format(Bundle.getMessage("buildLocRequestMoves"), new Object[] { rl.getName(), rl.getMaxCarMoves(), rl.getMaxTrainLength(), Setup.getLengthUnit().toLowerCase() }));
} else if (!rl.isDropAllowed()) {
addLine(_buildReport, THREE, MessageFormat.format(Bundle.getMessage("buildLocRequestPickups"), new Object[] { rl.getName(), rl.getMaxCarMoves(), rl.getMaxTrainLength(), Setup.getLengthUnit().toLowerCase() }));
} else if (rl == _train.getTrainTerminatesRouteLocation()) {
addLine(_buildReport, THREE, MessageFormat.format(Bundle.getMessage("buildLocTerminates"), new Object[] { rl.getName(), rl.getMaxCarMoves() }));
} else {
addLine(_buildReport, THREE, MessageFormat.format(Bundle.getMessage("buildLocRequestDrops"), new Object[] { rl.getName(), rl.getMaxCarMoves(), rl.getMaxTrainLength(), Setup.getLengthUnit().toLowerCase() }));
}
}
// clear the total train weight
rl.setTrainWeight(0);
// and length
rl.setTrainLength(0);
}
// check for random controls
for (RouteLocation rl : _routeList) {
if (rl.getRandomControl().equals(RouteLocation.DISABLED)) {
continue;
}
if (rl.getCarMoves() == 0 && rl.getMaxCarMoves() > 0) {
log.debug("Location ({}) has random control value {} and maximum moves {}", rl.getName(), rl.getRandomControl(), rl.getMaxCarMoves());
try {
int value = Integer.parseInt(rl.getRandomControl());
// now adjust the number of available moves for this location
double random = Math.random();
log.debug("random {}", random);
int moves = (int) (random * ((rl.getMaxCarMoves() * value / 100) + 1));
log.debug("Reducing number of moves for location ({}) by {}", rl.getName(), moves);
rl.setCarMoves(moves);
requested = requested - moves;
addLine(_buildReport, FIVE, MessageFormat.format(Bundle.getMessage("buildRouteRandomControl"), new Object[] { rl.getName(), rl.getId(), rl.getRandomControl(), rl.getMaxCarMoves(), rl.getMaxCarMoves() - moves }));
} catch (NumberFormatException e) {
throw new BuildFailedException(MessageFormat.format(Bundle.getMessage("buildErrorRandomControl"), new Object[] { _train.getRoute().getName(), rl.getName(), rl.getRandomControl() }));
}
}
}
// number of car moves
int numMoves = requested;
if (!_train.isLocalSwitcher()) {
// only need half as many cars to meet requests
requested = requested / 2;
}
addLine(_buildReport, ONE, MessageFormat.format(Bundle.getMessage("buildRouteRequest"), new Object[] { _train.getRoute().getName(), Integer.toString(requested), Integer.toString(numMoves) }));
// save number of car requested
_train.setNumberCarsRequested(requested);
// is this train a switcher?
if (_train.isLocalSwitcher()) {
// add line when in detailed report mode
addLine(_buildReport, THREE, BLANK_LINE);
addLine(_buildReport, THREE, MessageFormat.format(Bundle.getMessage("buildTrainIsSwitcher"), new Object[] { _train.getName(), TrainCommon.splitString(_train.getTrainDepartsName()) }));
}
// get engine requirements for this train
if (_train.getNumberEngines().equals(Train.AUTO)) {
_reqNumEngines = getAutoEngines();
} else if (_train.getNumberEngines().equals(Train.AUTO_HPT)) {
// get one loco for now, check HP requirements after train is built
_reqNumEngines = 1;
} else {
_reqNumEngines = Integer.parseInt(_train.getNumberEngines());
}
showTrainRequirements();
// show road names that this train will service
if (!_train.getRoadOption().equals(Train.ALL_ROADS)) {
addLine(_buildReport, FIVE, MessageFormat.format(Bundle.getMessage("buildTrainRoads"), new Object[] { _train.getName(), _train.getRoadOption(), formatStringToCommaSeparated(_train.getRoadNames()) }));
}
// show owner names that this train will service
if (!_train.getOwnerOption().equals(Train.ALL_OWNERS)) {
addLine(_buildReport, FIVE, MessageFormat.format(Bundle.getMessage("buildTrainOwners"), new Object[] { _train.getName(), _train.getOwnerOption(), formatStringToCommaSeparated(_train.getOwnerNames()) }));
}
// show built date serviced
if (!_train.getBuiltStartYear().equals(Train.NONE)) {
addLine(_buildReport, FIVE, MessageFormat.format(Bundle.getMessage("buildTrainBuiltAfter"), new Object[] { _train.getName(), _train.getBuiltStartYear() }));
}
if (!_train.getBuiltEndYear().equals(Train.NONE)) {
addLine(_buildReport, FIVE, MessageFormat.format(Bundle.getMessage("buildTrainBuiltBefore"), new Object[] { _train.getName(), _train.getBuiltEndYear() }));
}
// show engine types that this train will service
if (_reqNumEngines > 0) {
addLine(_buildReport, FIVE, MessageFormat.format(Bundle.getMessage("buildTrainServicesEngineTypes"), new Object[] { _train.getName() }));
addLine(_buildReport, FIVE, formatStringToCommaSeparated(_train.getLocoTypeNames()));
}
// allow up to two engine and caboose swaps in the train's route
RouteLocation engineTerminatesFirstLeg = _train.getTrainTerminatesRouteLocation();
RouteLocation cabooseOrFredTerminatesFirstLeg = _train.getTrainTerminatesRouteLocation();
RouteLocation engineTerminatesSecondLeg = _train.getTrainTerminatesRouteLocation();
RouteLocation cabooseOrFredTerminatesSecondLeg = _train.getTrainTerminatesRouteLocation();
// Adjust where the locos will terminate
if ((_train.getSecondLegOptions() & Train.CHANGE_ENGINES) == Train.CHANGE_ENGINES && _train.getSecondLegStartLocation() != null) {
engineTerminatesFirstLeg = _train.getSecondLegStartLocation();
}
if ((_train.getThirdLegOptions() & Train.CHANGE_ENGINES) == Train.CHANGE_ENGINES && _train.getThirdLegStartLocation() != null) {
engineTerminatesSecondLeg = _train.getThirdLegStartLocation();
// No engine or caboose change at first leg?
if ((_train.getSecondLegOptions() & Train.CHANGE_ENGINES) != Train.CHANGE_ENGINES) {
engineTerminatesFirstLeg = _train.getThirdLegStartLocation();
}
}
// make any caboose changes
if ((_train.getSecondLegOptions() & Train.REMOVE_CABOOSE) == Train.REMOVE_CABOOSE || (_train.getSecondLegOptions() & Train.ADD_CABOOSE) == Train.ADD_CABOOSE) {
cabooseOrFredTerminatesFirstLeg = _train.getSecondLegStartLocation();
} else if ((_train.getThirdLegOptions() & Train.REMOVE_CABOOSE) == Train.REMOVE_CABOOSE || (_train.getThirdLegOptions() & Train.ADD_CABOOSE) == Train.ADD_CABOOSE) {
cabooseOrFredTerminatesFirstLeg = _train.getThirdLegStartLocation();
}
if ((_train.getThirdLegOptions() & Train.REMOVE_CABOOSE) == Train.REMOVE_CABOOSE || (_train.getThirdLegOptions() & Train.ADD_CABOOSE) == Train.ADD_CABOOSE) {
cabooseOrFredTerminatesSecondLeg = _train.getThirdLegStartLocation();
}
// does train terminate into staging?
_terminateStageTrack = null;
List<Track> stagingTracksTerminate = _terminateLocation.getTrackByMovesList(Track.STAGING);
if (stagingTracksTerminate.size() > 0) {
// add line when in normal report mode
addLine(_buildReport, THREE, BLANK_LINE);
addLine(_buildReport, ONE, MessageFormat.format(Bundle.getMessage("buildTerminateStaging"), new Object[] { _terminateLocation.getName(), Integer.toString(stagingTracksTerminate.size()) }));
if (stagingTracksTerminate.size() > 1 && Setup.isPromptToStagingEnabled()) {
_terminateStageTrack = PromptToStagingDialog();
// reset build time
startTime = new Date();
} else {
// is this train returning to the same staging in aggressive mode?
if (_departLocation == _terminateLocation && Setup.isBuildAggressive() && Setup.isStagingTrackImmediatelyAvail()) {
addLine(_buildReport, ONE, MessageFormat.format(Bundle.getMessage("buildStagingReturn"), new Object[] { _terminateLocation.getName() }));
} else {
for (Track track : stagingTracksTerminate) {
_terminateStageTrack = track;
if (checkTerminateStagingTrack(_terminateStageTrack)) {
addLine(_buildReport, ONE, MessageFormat.format(Bundle.getMessage("buildStagingAvail"), new Object[] { _terminateStageTrack.getName(), _terminateLocation.getName() }));
break;
}
_terminateStageTrack = null;
}
}
}
if (_terminateStageTrack == null) {
// is this train returning to the same staging in aggressive mode?
if (_departLocation == _terminateLocation && Setup.isBuildAggressive() && Setup.isStagingTrackImmediatelyAvail()) {
log.debug("Train is returning to same track in staging");
} else {
addLine(_buildReport, ONE, Bundle.getMessage("buildErrorStagingFullNote"));
throw new BuildFailedException(MessageFormat.format(Bundle.getMessage("buildErrorStagingFull"), new Object[] { _terminateLocation.getName() }));
}
}
}
// get list of engines for this route
_engineList = engineManager.getAvailableTrainList(_train);
// determine if train is departing staging
_departStageTrack = null;
List<Track> stagingTracks = _departLocation.getTrackByMovesList(Track.STAGING);
if (stagingTracks.size() > 0) {
// add line when in normal report mode
addLine(_buildReport, THREE, BLANK_LINE);
addLine(_buildReport, ONE, MessageFormat.format(Bundle.getMessage("buildDepartStaging"), new Object[] { _departLocation.getName(), Integer.toString(stagingTracks.size()) }));
if (stagingTracks.size() > 1 && Setup.isPromptFromStagingEnabled()) {
_departStageTrack = PromptFromStagingDialog();
// restart build timer
startTime = new Date();
if (_departStageTrack == null) {
showTrainRequirements();
throw new BuildFailedException(MessageFormat.format(Bundle.getMessage("buildErrorStagingEmpty"), new Object[] { _departLocation.getName() }));
}
// load engines for this train
if (!getEngines(_reqNumEngines, _train.getEngineModel(), _train.getEngineRoad(), _train.getTrainDepartsRouteLocation(), engineTerminatesFirstLeg)) {
throw new BuildFailedException(MessageFormat.format(Bundle.getMessage("buildErrorEngines"), new Object[] { _reqNumEngines, _train.getTrainDepartsName(), engineTerminatesFirstLeg.getName() }));
}
} else {
for (Track track : stagingTracks) {
addLine(_buildReport, THREE, MessageFormat.format(Bundle.getMessage("buildStagingHas"), new Object[] { track.getName(), Integer.toString(track.getNumberEngines()), Integer.toString(track.getNumberCars()) }));
// is the departure track available?
if (!checkDepartureStagingTrack(track)) {
addLine(_buildReport, SEVEN, MessageFormat.format(Bundle.getMessage("buildStagingTrackRestriction"), new Object[] { track.getName(), _train.getName() }));
continue;
}
_departStageTrack = track;
// try each departure track for the required engines
if (getEngines(_reqNumEngines, _train.getEngineModel(), _train.getEngineRoad(), _train.getTrainDepartsRouteLocation(), engineTerminatesFirstLeg)) {
addLine(_buildReport, SEVEN, Bundle.getMessage("buildDoneAssignEnginesStaging"));
// done!
break;
}
_departStageTrack = null;
}
}
if (_departStageTrack == null) {
showTrainRequirements();
throw new BuildFailedException(MessageFormat.format(Bundle.getMessage("buildErrorStagingEmpty"), new Object[] { _departLocation.getName() }));
// departing staging and returning to same track?
} else if (_terminateStageTrack == null && _departLocation == _terminateLocation && Setup.isBuildAggressive() && Setup.isStagingTrackImmediatelyAvail()) {
// use the same track
_terminateStageTrack = _departStageTrack;
}
} else {
// no staging tracks at this location, load engines for this train
if (_reqNumEngines > 0) {
// add line when in detailed report mode
addLine(_buildReport, FIVE, BLANK_LINE);
}
if (!getEngines(_reqNumEngines, _train.getEngineModel(), _train.getEngineRoad(), _train.getTrainDepartsRouteLocation(), engineTerminatesFirstLeg)) {
throw new BuildFailedException(MessageFormat.format(Bundle.getMessage("buildErrorEngines"), new Object[] { _reqNumEngines, _train.getTrainDepartsName(), engineTerminatesFirstLeg.getName() }));
}
}
// Save termination and departure tracks
_train.setTerminationTrack(_terminateStageTrack);
_train.setDepartureTrack(_departStageTrack);
// First engine change in route?
Engine secondLeadEngine = null;
if ((_train.getSecondLegOptions() & Train.CHANGE_ENGINES) == Train.CHANGE_ENGINES) {
addLine(_buildReport, THREE, BLANK_LINE);
addLine(_buildReport, THREE, MessageFormat.format(Bundle.getMessage("buildTrainEngineChange"), new Object[] { _train.getSecondLegStartLocationName(), _train.getSecondLegNumberEngines(), _train.getSecondLegEngineModel(), _train.getSecondLegEngineRoad() }));
if (getEngines(Integer.parseInt(_train.getSecondLegNumberEngines()), _train.getSecondLegEngineModel(), _train.getSecondLegEngineRoad(), _train.getSecondLegStartLocation(), engineTerminatesSecondLeg)) {
secondLeadEngine = _leadEngine;
} else {
throw new BuildFailedException(MessageFormat.format(Bundle.getMessage("buildErrorEngines"), new Object[] { Integer.parseInt(_train.getSecondLegNumberEngines()), _train.getSecondLegStartLocation(), engineTerminatesSecondLeg }));
}
}
// Second engine change in route?
Engine thirdLeadEngine = null;
if ((_train.getThirdLegOptions() & Train.CHANGE_ENGINES) == Train.CHANGE_ENGINES) {
addLine(_buildReport, THREE, BLANK_LINE);
addLine(_buildReport, THREE, MessageFormat.format(Bundle.getMessage("buildTrainEngineChange"), new Object[] { _train.getThirdLegStartLocationName(), _train.getThirdLegNumberEngines(), _train.getThirdLegEngineModel(), _train.getThirdLegEngineRoad() }));
if (getEngines(Integer.parseInt(_train.getThirdLegNumberEngines()), _train.getThirdLegEngineModel(), _train.getThirdLegEngineRoad(), _train.getThirdLegStartLocation(), _train.getTrainTerminatesRouteLocation())) {
thirdLeadEngine = _leadEngine;
} else {
throw new BuildFailedException(MessageFormat.format(Bundle.getMessage("buildErrorEngines"), new Object[] { Integer.parseInt(_train.getThirdLegNumberEngines()), _train.getThirdLegStartLocation(), _train.getTrainTerminatesRouteLocation() }));
}
}
if (_reqNumEngines > 0 && (!_train.isBuildConsistEnabled() || Setup.getHorsePowerPerTon() == 0)) {
addLine(_buildReport, SEVEN, MessageFormat.format(Bundle.getMessage("buildDoneAssingEnginesTrain"), new Object[] { _train.getName() }));
}
// show car types and loads that this train will service
// add line when in detailed report mode
addLine(_buildReport, FIVE, BLANK_LINE);
addLine(_buildReport, FIVE, MessageFormat.format(Bundle.getMessage("buildTrainServicesCarTypes"), new Object[] { _train.getName() }));
addLine(_buildReport, FIVE, formatStringToCommaSeparated(_train.getCarTypeNames()));
// show load names that this train will service
if (!_train.getLoadOption().equals(Train.ALL_LOADS)) {
addLine(_buildReport, FIVE, MessageFormat.format(Bundle.getMessage("buildTrainLoads"), new Object[] { _train.getName(), _train.getLoadOption(), formatStringToCommaSeparated(_train.getLoadNames()) }));
}
// get list of cars for this route
_carList = carManager.getAvailableTrainList(_train);
// TODO: DAB this needs to be controlled by each train
if (requested > _carList.size() && Control.fullTrainOnly) {
throw new BuildFailedException(MessageFormat.format(Bundle.getMessage("buildErrorNumReq"), new Object[] { Integer.toString(requested), _train.getName(), Integer.toString(_carList.size()) }));
}
// remove unwanted cars and list available cars by location
removeAndListCars();
// second caboose change?
if ((_train.getThirdLegOptions() & Train.ADD_CABOOSE) == Train.ADD_CABOOSE && _train.getThirdLegStartLocation() != null && _train.getTrainTerminatesRouteLocation() != null) {
getCaboose(_train.getThirdLegCabooseRoad(), thirdLeadEngine, _train.getThirdLegStartLocation(), _train.getTrainTerminatesRouteLocation(), true);
}
// first caboose change?
if ((_train.getSecondLegOptions() & Train.ADD_CABOOSE) == Train.ADD_CABOOSE && _train.getSecondLegStartLocation() != null && cabooseOrFredTerminatesSecondLeg != null) {
getCaboose(_train.getSecondLegCabooseRoad(), secondLeadEngine, _train.getSecondLegStartLocation(), cabooseOrFredTerminatesSecondLeg, true);
}
// get caboose or car with FRED if needed for train
getCaboose(_train.getCabooseRoad(), _train.getLeadEngine(), _train.getTrainDepartsRouteLocation(), cabooseOrFredTerminatesFirstLeg, (_train.getRequirements() & Train.CABOOSE) == Train.CABOOSE);
getCarWithFred(_train.getCabooseRoad(), _train.getTrainDepartsRouteLocation(), cabooseOrFredTerminatesFirstLeg);
// done assigning cabooses and cars with FRED, remove the rest, and save final destination
removeCaboosesAndCarsWithFredAndSaveFinalDestination();
// block cars from staging
blockCarsFromStaging();
// now find destinations for cars
// add line when in normal report mode
addLine(_buildReport, THREE, BLANK_LINE);
addLine(_buildReport, THREE, MessageFormat.format(Bundle.getMessage("buildTrain"), new Object[] { requested, _train.getName(), _carList.size() }));
if (Setup.isBuildAggressive() && !_train.isBuildTrainNormalEnabled()) {
// perform a multiple pass build for this train, default is two passes
int passes = 0;
boolean firstPass = true;
while (passes++ < Setup.getNumberPasses()) {
placeCars(100 * passes / Setup.getNumberPasses(), firstPass);
firstPass = false;
}
} else {
placeCars(100, false);
}
_train.setCurrentLocation(_train.getTrainDepartsRouteLocation());
if (_numberCars < requested) {
_train.setStatusCode(Train.CODE_PARTIAL_BUILT);
addLine(_buildReport, ONE, Train.PARTIAL_BUILT + " " + _train.getNumberCarsWorked() + "/" + _train.getNumberCarsRequested() + " " + Bundle.getMessage("cars"));
} else {
_train.setStatusCode(Train.CODE_BUILT);
addLine(_buildReport, ONE, Train.BUILT + " " + _train.getNumberCarsWorked() + " " + Bundle.getMessage("cars"));
}
// check that engine assigned to the train has the appropriate HP
checkEngineHP();
// check to see if additional engines are needed for this train
checkNumnberOfEnginesNeeded();
// any cars not able to route?
if (_notRoutable.size() > 0) {
addLine(_buildReport, ONE, BLANK_LINE);
addLine(_buildReport, ONE, Bundle.getMessage("buildCarsNotRoutable"));
for (Car car : _notRoutable) {
addLine(_buildReport, ONE, MessageFormat.format(Bundle.getMessage("buildCarNotRoutable"), new Object[] { car.toString(), car.getLocationName(), car.getTrackName(), car.getFinalDestinationName(), car.getFinalDestinationTrackName() }));
}
addLine(_buildReport, ONE, BLANK_LINE);
}
addLine(_buildReport, FIVE, MessageFormat.format(Bundle.getMessage("buildTime"), new Object[] { _train.getName(), new Date().getTime() - startTime.getTime() }));
_buildReport.flush();
_buildReport.close();
// now make manifest
new TrainManifest(_train);
try {
new JsonManifest(_train).build();
} catch (IOException ex) {
log.error("Unable to create JSON manifest: {}", ex.getLocalizedMessage());
throw new BuildFailedException(ex);
}
if (Setup.isGenerateCsvManifestEnabled()) {
new TrainCsvManifest(_train);
}
_train.setBuilt(true);
// notify that locations have been modified by this train's build
for (Location location : _modifiedLocations) {
location.setStatus(Location.MODIFIED);
}
// now create and place train icon
_train.moveTrainIcon(_train.getTrainDepartsRouteLocation());
log.debug("Done building train ({})", _train.getName());
}
use of jmri.jmrit.operations.routes.RouteLocation in project JMRI by JMRI.
the class TrainBuilder method removeAndListCars.
/**
* Remove unwanted cars from the car list. Remove cars that don't have a
* track assignment, and check that the car can be serviced by this train.
* Lists all cars available to train by location.
*/
private void removeAndListCars() throws BuildFailedException {
// add line when in very detailed report mode
addLine(_buildReport, SEVEN, BLANK_LINE);
addLine(_buildReport, SEVEN, Bundle.getMessage("buildRemoveCars"));
boolean showCar = true;
int carListSize = _carList.size();
for (_carIndex = 0; _carIndex < _carList.size(); _carIndex++) {
Car car = _carList.get(_carIndex);
// only show the first 100 cars removed
if (showCar && carListSize - _carList.size() == DISPLAY_CAR_LIMIT_100) {
showCar = false;
addLine(_buildReport, FIVE, MessageFormat.format(Bundle.getMessage("buildOnlyFirstXXXCars"), new Object[] { DISPLAY_CAR_LIMIT_100, Bundle.getMessage("Type") }));
}
// remove cars that don't have a track assignment
if (car.getTrack() == null) {
addLine(_buildReport, ONE, MessageFormat.format(Bundle.getMessage("buildErrorRsNoLoc"), new Object[] { car.toString(), car.getLocationName() }));
_carList.remove(car);
_carIndex--;
continue;
}
// remove cars that have been reported as missing
if (car.isLocationUnknown()) {
addLine(_buildReport, SEVEN, MessageFormat.format(Bundle.getMessage("buildExcludeCarLocUnknown"), new Object[] { car.toString(), car.getLocationName(), car.getTrackName() }));
if (car.getTrack().equals(_departStageTrack)) {
throw new BuildFailedException(MessageFormat.format(Bundle.getMessage("buildErrorLocationUnknown"), new Object[] { car.getLocationName(), car.getTrackName(), car.toString() }));
}
_carList.remove(car);
_carIndex--;
continue;
}
// remove cars that are out of service
if (car.isOutOfService()) {
addLine(_buildReport, SEVEN, MessageFormat.format(Bundle.getMessage("buildExcludeCarOutOfService"), new Object[] { car.toString(), car.getLocationName(), car.getTrackName() }));
if (car.getTrack().equals(_departStageTrack)) {
throw new BuildFailedException(MessageFormat.format(Bundle.getMessage("buildErrorLocationOutOfService"), new Object[] { car.getLocationName(), car.getTrackName(), car.toString() }));
}
_carList.remove(car);
_carIndex--;
continue;
}
// remove cars with FRED that have a destination that isn't the terminal
if (car.hasFred() && car.getDestination() != null && car.getDestination() != _terminateLocation) {
addLine(_buildReport, FIVE, MessageFormat.format(Bundle.getMessage("buildExcludeCarWrongDest"), new Object[] { car.toString(), car.getTypeName(), car.getDestinationName() }));
_carList.remove(car);
_carIndex--;
continue;
}
// remove cabooses that have a destination that isn't the terminal, no caboose changes in the train's route
if (car.isCaboose() && car.getDestination() != null && car.getDestination() != _terminateLocation && _train.getSecondLegOptions() == Train.NO_CABOOSE_OR_FRED && _train.getThirdLegOptions() == Train.NO_CABOOSE_OR_FRED) {
addLine(_buildReport, FIVE, MessageFormat.format(Bundle.getMessage("buildExcludeCarWrongDest"), new Object[] { car.toString(), car.getTypeName(), car.getDestinationName() }));
_carList.remove(car);
_carIndex--;
continue;
}
// is car at interchange?
if (car.getTrack().getTrackType().equals(Track.INTERCHANGE)) {
// don't service a car at interchange and has been dropped off by this train
if (car.getTrack().getPickupOption().equals(Track.ANY) && car.getLastRouteId().equals(_train.getRoute().getId())) {
addLine(_buildReport, SEVEN, MessageFormat.format(Bundle.getMessage("buildExcludeCarDropByTrain"), new Object[] { car.toString(), _train.getRoute().getName(), car.getLocationName(), car.getTrackName() }));
_carList.remove(car);
_carIndex--;
continue;
}
}
if (car.getTrack().getTrackType().equals(Track.INTERCHANGE) || car.getTrack().getTrackType().equals(Track.SPUR)) {
if (car.getTrack().getPickupOption().equals(Track.TRAINS) || car.getTrack().getPickupOption().equals(Track.EXCLUDE_TRAINS)) {
if (car.getTrack().acceptsPickupTrain(_train)) {
log.debug("Car ({}) can be picked up by this train", car.toString());
} else {
addLine(_buildReport, SEVEN, MessageFormat.format(Bundle.getMessage("buildExcludeCarByTrain"), new Object[] { car.toString(), car.getTrack().getTrackTypeName(), car.getLocationName(), car.getTrackName() }));
_carList.remove(car);
_carIndex--;
continue;
}
} else if (car.getTrack().getPickupOption().equals(Track.ROUTES) || car.getTrack().getPickupOption().equals(Track.EXCLUDE_ROUTES)) {
if (car.getTrack().acceptsPickupRoute(_train.getRoute())) {
log.debug("Car ({}) can be picked up by this route", car.toString());
} else {
addLine(_buildReport, SEVEN, MessageFormat.format(Bundle.getMessage("buildExcludeCarByRoute"), new Object[] { car.toString(), car.getTrack().getTrackTypeName(), car.getLocationName(), car.getTrackName() }));
_carList.remove(car);
_carIndex--;
continue;
}
}
}
// checked in the routine checkDepartureStagingTrack().
if (_departStageTrack == null || car.getTrack() != _departStageTrack) {
if (!_train.acceptsRoadName(car.getRoadName())) {
addLine(_buildReport, SEVEN, MessageFormat.format(Bundle.getMessage("buildExcludeCarWrongRoad"), new Object[] { car.toString(), car.getTypeName(), car.getRoadName() }));
_carList.remove(car);
_carIndex--;
continue;
}
if (!_train.acceptsTypeName(car.getTypeName())) {
if (showCar) {
addLine(_buildReport, SEVEN, MessageFormat.format(Bundle.getMessage("buildExcludeCarWrongType"), new Object[] { car.toString(), car.getTypeName() }));
}
_carList.remove(car);
_carIndex--;
continue;
}
if (!car.isCaboose() && !car.isPassenger() && !_train.acceptsLoad(car.getLoadName(), car.getTypeName())) {
addLine(_buildReport, SEVEN, MessageFormat.format(Bundle.getMessage("buildExcludeCarLoadAtLoc"), new Object[] { car.toString(), car.getTypeName(), car.getLoadName() }));
_carList.remove(car);
_carIndex--;
continue;
}
if (!_train.acceptsOwnerName(car.getOwner())) {
addLine(_buildReport, SEVEN, MessageFormat.format(Bundle.getMessage("buildExcludeCarOwnerAtLoc"), new Object[] { car.toString(), car.getOwner(), (car.getLocationName() + ", " + car.getTrackName()) }));
_carList.remove(car);
_carIndex--;
continue;
}
if (!_train.acceptsBuiltDate(car.getBuilt())) {
addLine(_buildReport, SEVEN, MessageFormat.format(Bundle.getMessage("buildExcludeCarBuiltAtLoc"), new Object[] { car.toString(), car.getBuilt(), (car.getLocationName() + ", " + car.getTrackName()) }));
_carList.remove(car);
_carIndex--;
continue;
}
// remove cars with FRED if not needed by train
if (car.hasFred() && (_train.getRequirements() & Train.FRED) == 0) {
addLine(_buildReport, SEVEN, MessageFormat.format(Bundle.getMessage("buildExcludeCarWithFredAtLoc"), new Object[] { car.toString(), car.getTypeName(), (car.getLocationName() + ", " + car.getTrackName()) }));
// remove this car from the list
_carList.remove(car);
_carIndex--;
continue;
}
// does car have a wait count?
if (car.getWait() > 0 && _train.services(car)) {
addLine(_buildReport, SEVEN, MessageFormat.format(Bundle.getMessage("buildExcludeCarWait"), new Object[] { car.toString(), car.getTypeName(), car.getLocationName(), car.getTrackName(), car.getWait() }));
// decrement wait count
car.setWait(car.getWait() - 1);
// a car's load changes when the wait count reaches 0
String oldLoad = car.getLoadName();
if (car.getTrack().getTrackType().equals(Track.SPUR)) {
// has the wait count reached 0?
car.updateLoad();
}
String newLoad = car.getLoadName();
if (!oldLoad.equals(newLoad)) {
addLine(_buildReport, SEVEN, MessageFormat.format(Bundle.getMessage("buildCarLoadChangedWait"), new Object[] { car.toString(), car.getTypeName(), oldLoad, newLoad }));
}
_carList.remove(car);
_carIndex--;
continue;
}
if (!car.getPickupScheduleId().equals(Car.NONE)) {
if (TrainManager.instance().getTrainScheduleActiveId().equals(TrainSchedule.ANY) || car.getPickupScheduleId().equals(TrainManager.instance().getTrainScheduleActiveId())) {
car.setPickupScheduleId(Car.NONE);
} else {
TrainSchedule sch = TrainScheduleManager.instance().getScheduleById(car.getPickupScheduleId());
if (sch != null) {
addLine(_buildReport, SEVEN, MessageFormat.format(Bundle.getMessage("buildExcludeCarSchedule"), new Object[] { car.toString(), car.getTypeName(), car.getLocationName(), car.getTrackName(), sch.getName() }));
_carList.remove(car);
_carIndex--;
continue;
}
}
}
}
}
// adjust car list to only have cars from one staging track
if (_departStageTrack != null) {
int numCarsFromStaging = 0;
_numOfBlocks = new Hashtable<String, Integer>();
// add line when in very detailed report mode
addLine(_buildReport, SEVEN, BLANK_LINE);
addLine(_buildReport, SEVEN, Bundle.getMessage("buildRemoveCarsStaging"));
for (_carIndex = 0; _carIndex < _carList.size(); _carIndex++) {
Car car = _carList.get(_carIndex);
if (car.getLocationName().equals(_departLocation.getName())) {
if (car.getTrackName().equals(_departStageTrack.getName())) {
numCarsFromStaging++;
// don't block cabooses, cars with FRED, or passenger. Only block lead cars in kernel
if (!car.isCaboose() && !car.hasFred() && !car.isPassenger() && (car.getKernel() == null || car.getKernel().isLead(car))) {
log.debug("Car {} last location id: {}", car.toString(), car.getLastLocationId());
Integer number = 1;
if (_numOfBlocks.containsKey(car.getLastLocationId())) {
number = _numOfBlocks.get(car.getLastLocationId()) + 1;
_numOfBlocks.remove(car.getLastLocationId());
}
_numOfBlocks.put(car.getLastLocationId(), number);
}
} else {
addLine(_buildReport, SEVEN, MessageFormat.format(Bundle.getMessage("buildExcludeCarAtLoc"), new Object[] { car.toString(), (car.getLocationName() + ", " + car.getTrackName()) }));
_carList.remove(car);
_carIndex--;
}
}
}
// show how many cars are departing from staging
// add line when in detailed report mode
addLine(_buildReport, FIVE, BLANK_LINE);
addLine(_buildReport, FIVE, MessageFormat.format(Bundle.getMessage("buildDepartingStagingCars"), new Object[] { _departStageTrack.getLocation().getName(), _departStageTrack.getName(), numCarsFromStaging }));
// and list them
for (Car car : _carList) {
if (car.getTrack() == _departStageTrack) {
addLine(_buildReport, SEVEN, MessageFormat.format(Bundle.getMessage("buildStagingCarAtLoc"), new Object[] { car.toString(), car.getTypeName(), car.getLoadName() }));
}
}
// error if all of the cars from staging aren't available
if (numCarsFromStaging != _departStageTrack.getNumberCars()) {
throw new BuildFailedException(MessageFormat.format(Bundle.getMessage("buildErrorNotAllCars"), new Object[] { _departStageTrack.getName(), Integer.toString(_departStageTrack.getNumberCars() - numCarsFromStaging) }));
}
log.debug("Staging departure track ({}) has {} cars and {} blocks", _departStageTrack.getName(), numCarsFromStaging, // NOI18N
_numOfBlocks.size());
}
// show how many cars were found
// add line when in detailed report mode
addLine(_buildReport, FIVE, BLANK_LINE);
addLine(_buildReport, ONE, MessageFormat.format(Bundle.getMessage("buildFoundCars"), new Object[] { Integer.toString(_carList.size()), _train.getName() }));
// only show cars once using the train's route
List<String> locationNames = new ArrayList<String>();
for (RouteLocation rl : _train.getRoute().getLocationsBySequenceList()) {
if (locationNames.contains(rl.getName())) {
continue;
}
locationNames.add(rl.getName());
if (rl.getLocation().isStaging()) {
addLine(_buildReport, SEVEN, MessageFormat.format(Bundle.getMessage("buildCarsInStaging"), new Object[] { rl.getName() }));
} else {
addLine(_buildReport, SEVEN, MessageFormat.format(Bundle.getMessage("buildCarsAtLocation"), new Object[] { rl.getName() }));
}
// now go through the car list and remove non-lead cars in kernels, destinations that aren't part of this
// route
int carCount = 0;
for (_carIndex = 0; _carIndex < _carList.size(); _carIndex++) {
Car car = _carList.get(_carIndex);
if (!car.getLocationName().equals(rl.getName())) {
continue;
}
// only print out the first DISPLAY_CAR_LIMIT cars for each location
if (carCount < DISPLAY_CAR_LIMIT_50) {
if (car.getLoadPriority().equals(CarLoad.PRIORITY_LOW)) {
addLine(_buildReport, SEVEN, MessageFormat.format(Bundle.getMessage("buildCarAtLocWithMoves"), new Object[] { car.toString(), car.getTypeName(), (car.getLocationName() + ", " + car.getTrackName()), car.getMoves() }));
} else {
addLine(_buildReport, SEVEN, MessageFormat.format(Bundle.getMessage("buildCarAtLocWithMovesPriority"), new Object[] { car.toString(), car.getTypeName(), (car.getLocationName() + ", " + car.getTrackName()), car.getMoves(), car.getLoadPriority() }));
}
}
if (carCount == DISPLAY_CAR_LIMIT_50) {
addLine(_buildReport, SEVEN, MessageFormat.format(Bundle.getMessage("buildOnlyFirstXXXCars"), new Object[] { carCount, rl.getName() }));
}
carCount++;
// use only the lead car in a kernel for building trains
if (car.getKernel() != null) {
if (car.getKernel().isLead(car)) {
addLine(_buildReport, SEVEN, MessageFormat.format(Bundle.getMessage("buildCarLeadKernel"), new Object[] { car.toString(), car.getKernelName(), car.getKernel().getSize(), car.getKernel().getTotalLength(), Setup.getLengthUnit().toLowerCase() }));
} else {
addLine(_buildReport, SEVEN, MessageFormat.format(Bundle.getMessage("buildCarPartOfKernel"), new Object[] { car.toString(), car.getKernelName(), car.getKernel().getSize(), car.getKernel().getTotalLength(), Setup.getLengthUnit().toLowerCase() }));
}
checkKernel(car);
if (!car.getKernel().isLead(car)) {
// remove this car from the list
_carList.remove(car);
_carIndex--;
continue;
}
}
if (_train.equals(car.getTrain())) {
addLine(_buildReport, FIVE, MessageFormat.format(Bundle.getMessage("buildCarAlreadyAssigned"), new Object[] { car.toString() }));
}
// does car have a destination that is part of this train's route?
if (car.getDestination() != null) {
addLine(_buildReport, SEVEN, MessageFormat.format(Bundle.getMessage("buildCarHasAssignedDest"), new Object[] { car.toString(), (car.getDestinationName() + ", " + car.getDestinationTrackName()) }));
RouteLocation rld = _train.getRoute().getLastLocationByName(car.getDestinationName());
if (rld == null) {
addLine(_buildReport, SEVEN, MessageFormat.format(Bundle.getMessage("buildExcludeCarDestNotPartRoute"), new Object[] { car.toString(), car.getDestinationName(), _train.getRoute().getName() }));
// build failure if car departing staging
if (car.getLocation().equals(_departLocation) && _departStageTrack != null) {
// routine.
throw new BuildFailedException(MessageFormat.format(Bundle.getMessage("buildErrorCarNotPartRoute"), new Object[] { car.toString() }));
}
// remove this car from the list
_carList.remove(car);
_carIndex--;
}
}
}
// add line when in detailed report mode
addLine(_buildReport, SEVEN, BLANK_LINE);
}
return;
}
use of jmri.jmrit.operations.routes.RouteLocation in project JMRI by JMRI.
the class TrainCommon method blockCarsByTrack.
/**
* Block cars by track, then pick up and set out for each location in a
* train's route. This routine is used for the "Standard" format.
*
* @param file Manifest or switch list File
* @param train The train being printed.
* @param carList List of cars for this train
* @param routeList The train's list of RouteLocations
* @param rl The RouteLocation being printed
* @param printHeader True if new location.
* @param isManifest True if manifest, false if switch list.
*/
protected void blockCarsByTrack(PrintWriter file, Train train, List<Car> carList, List<RouteLocation> routeList, RouteLocation rl, boolean printHeader, boolean isManifest) {
if (printHeader) {
printPickupHeader = true;
printSetoutHeader = true;
printLocalMoveHeader = true;
}
List<Track> tracks = rl.getLocation().getTrackByNameList(null);
List<String> trackNames = new ArrayList<String>();
// list utility cars by quantity
clearUtilityCarTypes();
boolean isOnlyPassenger = train.isOnlyPassengerCars();
for (Track track : tracks) {
if (trackNames.contains(splitString(track.getName()))) {
continue;
}
// use a track name once
trackNames.add(splitString(track.getName()));
// block pick up cars by destination
// except for passenger cars
// begin blocking at rl
boolean found = false;
for (RouteLocation rld : routeList) {
if (rld != rl && !found) {
continue;
}
found = true;
for (Car car : carList) {
if (Setup.isSortByTrackNameEnabled() && !splitString(track.getName()).equals(splitString(car.getTrackName()))) {
continue;
}
// passenger trains are already blocked in the car list
if (car.getRouteLocation() == rl && car.getTrack() != null && ((car.getRouteDestination() == rld && !car.isCaboose() && !car.hasFred()) || (rld == routeList.get(routeList.size() - 1) && (car.isCaboose() || car.hasFred())) || (car.isPassenger() && isOnlyPassenger))) {
// determine if header is to be printed
if (printPickupHeader && !isLocalMove(car)) {
printPickupCarHeader(file, isManifest, !IS_TWO_COLUMN_TRACK);
printPickupHeader = false;
// check to see if the other headers are needed. If they are identical, not needed
if (getPickupCarHeader(isManifest, !IS_TWO_COLUMN_TRACK).equals(getDropCarHeader(isManifest, !IS_TWO_COLUMN_TRACK))) {
printSetoutHeader = false;
}
if (getPickupCarHeader(isManifest, !IS_TWO_COLUMN_TRACK).equals(getLocalMoveHeader(isManifest))) {
printLocalMoveHeader = false;
}
}
if (car.isUtility()) {
pickupUtilityCars(file, carList, car, isManifest);
} else // use truncated format if there's a switch list
if (isManifest && Setup.isTruncateManifestEnabled() && rl.getLocation().isSwitchListEnabled()) {
pickUpCarTruncated(file, car, isManifest);
} else {
pickUpCar(file, car, isManifest);
}
pickupCars = true;
cars++;
if (car.getLoadType().equals(CarLoad.LOAD_TYPE_EMPTY)) {
emptyCars++;
}
}
}
if (isOnlyPassenger) {
break;
}
}
// now do set outs and local moves
for (Car car : carList) {
if (Setup.isSortByTrackNameEnabled() && car.getRouteLocation() != null && car.getRouteDestination() == rl) {
// sorting by car's track name fails if there are "similar" location names.
if (!splitString(track.getName()).equals(splitString(car.getDestinationTrackName()))) {
continue;
}
}
if (car.getRouteDestination() == rl && car.getDestinationTrack() != null) {
if (printSetoutHeader && !isLocalMove(car)) {
printDropCarHeader(file, isManifest, !IS_TWO_COLUMN_TRACK);
printSetoutHeader = false;
// check to see if the other headers are needed. If they are identical, not needed
if (getPickupCarHeader(isManifest, !IS_TWO_COLUMN_TRACK).equals(getDropCarHeader(isManifest, !IS_TWO_COLUMN_TRACK))) {
printPickupHeader = false;
}
if (getDropCarHeader(isManifest, !IS_TWO_COLUMN_TRACK).equals(getLocalMoveHeader(isManifest))) {
printLocalMoveHeader = false;
}
}
if (printLocalMoveHeader && isLocalMove(car)) {
printLocalCarMoveHeader(file, isManifest);
printLocalMoveHeader = false;
// check to see if the other headers are needed. If they are identical, not needed
if (getPickupCarHeader(isManifest, !IS_TWO_COLUMN_TRACK).equals(getLocalMoveHeader(isManifest))) {
printPickupHeader = false;
}
if (getDropCarHeader(isManifest, !IS_TWO_COLUMN_TRACK).equals(getLocalMoveHeader(isManifest))) {
printSetoutHeader = false;
}
}
if (car.isUtility()) {
setoutUtilityCars(file, carList, car, isManifest);
} else // use truncated format if there's a switch list
if (isManifest && Setup.isTruncateManifestEnabled() && rl.getLocation().isSwitchListEnabled() && !train.isLocalSwitcher()) {
truncatedDropCar(file, car, isManifest);
} else {
dropCar(file, car, isManifest);
}
dropCars = true;
cars--;
if (CarLoads.instance().getLoadType(car.getTypeName(), car.getLoadName()).equals(CarLoad.LOAD_TYPE_EMPTY)) {
emptyCars--;
}
}
}
if (!Setup.isSortByTrackNameEnabled()) {
// done
break;
}
}
}
use of jmri.jmrit.operations.routes.RouteLocation in project JMRI by JMRI.
the class TrainBuilder method getAutoEngines.
/**
* Returns the number of engines needed for this train, minimum 1, maximum
* user specified in setup. Based on maximum allowable train length and
* grade between locations, and the maximum cars that the train can have at
* the maximum train length. One engine per sixteen 40' cars for 1% grade.
* TODO Currently ignores the cars weight and engine horsepower
*
* @return The number of engines needed
*/
private int getAutoEngines() {
double numberEngines = 1;
int moves = 0;
for (RouteLocation rl : _routeList) {
moves += rl.getMaxCarMoves();
// number of 40' cars per engine 1% grade
double carDivisor = 16;
// change engine requirements based on grade
if (rl.getGrade() > 1) {
double grade = rl.getGrade();
carDivisor = carDivisor / grade;
}
log.debug("Maximum train length {} for location ({})", rl.getMaxTrainLength(), rl.getName());
if (rl.getMaxTrainLength() / (carDivisor * 40) > numberEngines) {
numberEngines = rl.getMaxTrainLength() / (carDivisor * (40 + Car.COUPLER));
// round up to next whole integer
numberEngines = Math.ceil(numberEngines);
if (numberEngines > moves / carDivisor) {
numberEngines = Math.ceil(moves / carDivisor);
}
if (numberEngines < 1) {
numberEngines = 1;
}
}
}
int nE = (int) numberEngines;
addLine(_buildReport, ONE, MessageFormat.format(Bundle.getMessage("buildAutoBuildMsg"), new Object[] { Integer.toString(nE) }));
if (nE > Setup.getMaxNumberEngines()) {
addLine(_buildReport, THREE, MessageFormat.format(Bundle.getMessage("buildMaximumNumberEngines"), new Object[] { Setup.getMaxNumberEngines() }));
nE = Setup.getMaxNumberEngines();
}
return nE;
}
Aggregations