Search in sources :

Example 61 with RouteLocation

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();
            }
        }
    }
}
Also used : JTextField(javax.swing.JTextField) RouteLocation(jmri.jmrit.operations.routes.RouteLocation) LoggerFactory(org.slf4j.LoggerFactory) MessageFormat(java.text.MessageFormat) UnexpectedExceptionContext(jmri.jmrit.operations.UnexpectedExceptionContext) CarTypes(jmri.jmrit.operations.rollingstock.cars.CarTypes) RouteManagerXml(jmri.jmrit.operations.routes.RouteManagerXml) Route(jmri.jmrit.operations.routes.Route) JComboBox(javax.swing.JComboBox) LocoIcon(jmri.jmrit.display.LocoIcon) BoxLayout(javax.swing.BoxLayout) JButton(javax.swing.JButton) RouteManager(jmri.jmrit.operations.routes.RouteManager) Logger(org.slf4j.Logger) ButtonGroup(javax.swing.ButtonGroup) ExceptionDisplayFrame(jmri.jmrit.operations.ExceptionDisplayFrame) BorderFactory(javax.swing.BorderFactory) OperationsXml(jmri.jmrit.operations.OperationsXml) JOptionPane(javax.swing.JOptionPane) JRadioButton(javax.swing.JRadioButton) JScrollPane(javax.swing.JScrollPane) Dimension(java.awt.Dimension) List(java.util.List) WebServerPreferences(jmri.web.server.WebServerPreferences) PropertyChangeListener(java.beans.PropertyChangeListener) JLabel(javax.swing.JLabel) JCheckBox(javax.swing.JCheckBox) JTextArea(javax.swing.JTextArea) GridBagLayout(java.awt.GridBagLayout) SuppressFBWarnings(edu.umd.cs.findbugs.annotations.SuppressFBWarnings) JPanel(javax.swing.JPanel) RouteLocation(jmri.jmrit.operations.routes.RouteLocation) Route(jmri.jmrit.operations.routes.Route)

Example 62 with RouteLocation

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());
}
Also used : IOException(java.io.IOException) RouteLocation(jmri.jmrit.operations.routes.RouteLocation) Date(java.util.Date) BufferedWriter(java.io.BufferedWriter) Car(jmri.jmrit.operations.rollingstock.cars.Car) FileOutputStream(java.io.FileOutputStream) OutputStreamWriter(java.io.OutputStreamWriter) File(java.io.File) Track(jmri.jmrit.operations.locations.Track) Engine(jmri.jmrit.operations.rollingstock.engines.Engine) PrintWriter(java.io.PrintWriter) RouteLocation(jmri.jmrit.operations.routes.RouteLocation) Location(jmri.jmrit.operations.locations.Location)

Example 63 with RouteLocation

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;
}
Also used : Car(jmri.jmrit.operations.rollingstock.cars.Car) TrainSchedule(jmri.jmrit.operations.trains.timetable.TrainSchedule) ArrayList(java.util.ArrayList) RouteLocation(jmri.jmrit.operations.routes.RouteLocation)

Example 64 with RouteLocation

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;
        }
    }
}
Also used : Car(jmri.jmrit.operations.rollingstock.cars.Car) ArrayList(java.util.ArrayList) RouteLocation(jmri.jmrit.operations.routes.RouteLocation) Track(jmri.jmrit.operations.locations.Track)

Example 65 with RouteLocation

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;
}
Also used : RouteLocation(jmri.jmrit.operations.routes.RouteLocation)

Aggregations

RouteLocation (jmri.jmrit.operations.routes.RouteLocation)118 Route (jmri.jmrit.operations.routes.Route)64 Location (jmri.jmrit.operations.locations.Location)55 Track (jmri.jmrit.operations.locations.Track)52 Car (jmri.jmrit.operations.rollingstock.cars.Car)48 Engine (jmri.jmrit.operations.rollingstock.engines.Engine)33 LocationManager (jmri.jmrit.operations.locations.LocationManager)21 RouteManager (jmri.jmrit.operations.routes.RouteManager)20 Consist (jmri.jmrit.operations.rollingstock.engines.Consist)17 Train (jmri.jmrit.operations.trains.Train)16 CarManager (jmri.jmrit.operations.rollingstock.cars.CarManager)13 ArrayList (java.util.ArrayList)12 CarTypes (jmri.jmrit.operations.rollingstock.cars.CarTypes)12 EngineManager (jmri.jmrit.operations.rollingstock.engines.EngineManager)12 RollingStock (jmri.jmrit.operations.rollingstock.RollingStock)11 EngineTypes (jmri.jmrit.operations.rollingstock.engines.EngineTypes)8 SuppressFBWarnings (edu.umd.cs.findbugs.annotations.SuppressFBWarnings)6 IOException (java.io.IOException)6 TrainManager (jmri.jmrit.operations.trains.TrainManager)6 JCheckBox (javax.swing.JCheckBox)5