001package jmri.jmrit.operations.locations.tools; 002 003import java.awt.*; 004import java.io.IOException; 005import java.text.MessageFormat; 006import java.util.List; 007 008import javax.swing.*; 009 010import jmri.InstanceManager; 011import jmri.jmrit.operations.OperationsFrame; 012import jmri.jmrit.operations.locations.*; 013import jmri.jmrit.operations.locations.schedules.*; 014import jmri.jmrit.operations.rollingstock.cars.*; 015import jmri.jmrit.operations.rollingstock.engines.EngineTypes; 016import jmri.jmrit.operations.routes.Route; 017import jmri.jmrit.operations.routes.RouteManager; 018import jmri.jmrit.operations.setup.Control; 019import jmri.jmrit.operations.setup.Setup; 020import jmri.jmrit.operations.trains.Train; 021import jmri.jmrit.operations.trains.TrainManager; 022import jmri.jmrit.operations.trains.trainbuilder.TrainCommon; 023import jmri.util.davidflanagan.HardcopyWriter; 024 025import org.slf4j.Logger; 026import org.slf4j.LoggerFactory; 027 028/** 029 * Frame to print a summary of the Location Roster contents 030 * <p> 031 * This uses the older style printing, for compatibility with Java 1.1.8 in 032 * Macintosh MRJ 033 * 034 * @author Bob Jacobsen Copyright (C) 2003 035 * @author Dennis Miller Copyright (C) 2005 036 * @author Daniel Boudreau Copyright (C) 2008, 2011, 2012, 2014, 2022, 2023, 2026 037 */ 038public class PrintLocationsFrame extends OperationsFrame { 039 040 protected static final String FORM_FEED = "\f"; // NOI18N 041 protected static final String TAB = "\t"; // NOI18N 042 protected static final int TAB_LENGTH = 10; 043 protected static final String SPACES_2 = " "; 044 protected static final String SPACES_3 = " "; 045 protected static final String SPACES_4 = " "; 046 047 protected static final int MAX_NAME_LENGTH = Control.max_len_string_location_name; 048 049 JCheckBox printLocations = new JCheckBox(Bundle.getMessage("PrintLocations")); 050 JCheckBox printSchedules = new JCheckBox(Bundle.getMessage("PrintSchedules")); 051 JCheckBox printComments = new JCheckBox(Bundle.getMessage("PrintComments")); 052 JCheckBox printDetails = new JCheckBox(Bundle.getMessage("PrintDetails")); 053 JCheckBox printAnalysis = new JCheckBox(Bundle.getMessage("PrintAnalysis")); 054 JCheckBox printErrorAnalysis = new JCheckBox(Bundle.getMessage("PrintErrorAnalysis")); 055 056 JButton okayButton = new JButton(Bundle.getMessage("ButtonOK")); 057 058 LocationManager lmanager = InstanceManager.getDefault(LocationManager.class); 059 CarTypes cts = InstanceManager.getDefault(CarTypes.class); 060 CarLoads cls = InstanceManager.getDefault(CarLoads.class); 061 CarRoads crs = InstanceManager.getDefault(CarRoads.class); 062 063 boolean _isPreview; 064 Location _location; 065 066 private int charactersPerLine = 70; 067 068 HardcopyWriter writer; 069 070 public PrintLocationsFrame(boolean isPreview, Location location) { 071 super(); 072 _isPreview = isPreview; 073 _location = location; 074 075 // create panel 076 JPanel pPanel = new JPanel(); 077 pPanel.setLayout(new GridBagLayout()); 078 pPanel.setBorder(BorderFactory.createTitledBorder(Bundle.getMessage("PrintOptions"))); 079 addItemLeft(pPanel, printLocations, 0, 0); 080 addItemLeft(pPanel, printSchedules, 0, 3); 081 addItemLeft(pPanel, printComments, 0, 5); 082 addItemLeft(pPanel, printDetails, 0, 7); 083 addItemLeft(pPanel, printAnalysis, 0, 9); 084 addItemLeft(pPanel, printErrorAnalysis, 0, 11); 085 086 // set defaults 087 printLocations.setSelected(true); 088 printSchedules.setSelected(false); 089 printComments.setSelected(false); 090 printDetails.setSelected(false); 091 printAnalysis.setSelected(false); 092 printErrorAnalysis.setSelected(false); 093 094 // add tool tips 095 JPanel pButtons = new JPanel(); 096 pButtons.setLayout(new GridBagLayout()); 097 pButtons.add(okayButton); 098 addButtonAction(okayButton); 099 100 getContentPane().setLayout(new BoxLayout(getContentPane(), BoxLayout.Y_AXIS)); 101 getContentPane().add(pPanel); 102 getContentPane().add(pButtons); 103 setPreferredSize(null); 104 if (_isPreview) { 105 setTitle(Bundle.getMessage("MenuItemPreview")); 106 } else { 107 setTitle(Bundle.getMessage("MenuItemPrint")); 108 } 109 initMinimumSize(new Dimension(Control.panelWidth300, Control.panelHeight250)); 110 } 111 112 @Override 113 public void buttonActionPerformed(java.awt.event.ActionEvent ae) { 114 setVisible(false); 115 printLocations(); 116 } 117 118 private void printLocations() { 119 // prevent NPE on close 120 if (!printLocations.isSelected() && 121 !printSchedules.isSelected() && 122 !printComments.isSelected() && 123 !printDetails.isSelected() && 124 !printAnalysis.isSelected() && 125 !printErrorAnalysis.isSelected()) { 126 return; 127 } 128 // obtain a HardcopyWriter 129 String title = Bundle.getMessage("TitleLocationsTable"); 130 if (_location != null) { 131 title = _location.getName(); 132 } 133 try (HardcopyWriter writer = 134 new HardcopyWriter(new Frame(), title, null, null, Control.reportFontSize, .5 * 72, .5 * 72, .5 * 72, 135 .5 * 72, _isPreview, "", false, true, null, null)) { 136 137 this.writer = writer; 138 139 charactersPerLine = writer.getCharactersPerLine(); 140 141 // print locations? 142 if (printLocations.isSelected()) { 143 printLocationsSelected(); 144 } 145 // print schedules? 146 if (printSchedules.isSelected()) { 147 printSchedulesSelected(); 148 } 149 if (printComments.isSelected()) { 150 printCommentsSelected(); 151 } 152 // print detailed report? 153 if (printDetails.isSelected()) { 154 printDetailsSelected(); 155 } 156 // print analysis? 157 if (printAnalysis.isSelected()) { 158 printAnalysisSelected(); 159 } 160 if (printErrorAnalysis.isSelected()) { 161 printErrorAnalysisSelected(); 162 } 163 } catch (HardcopyWriter.PrintCanceledException ex) { 164 log.debug("Print canceled"); 165 } catch (IOException we) { 166 log.error("Error printing PrintLocationAction: {}", we.getLocalizedMessage()); 167 } 168 } 169 170 // Loop through the Roster, printing as needed 171 private void printLocationsSelected() throws IOException { 172 List<Location> locations = lmanager.getLocationsByNameList(); 173 int totalLength = 0; 174 int usedLength = 0; 175 int numberRS = 0; 176 int numberCars = 0; 177 int numberEngines = 0; 178 // header 179 String s = Bundle.getMessage("Location") + 180 TAB + 181 TAB + 182 TAB + 183 Bundle.getMessage("Length") + 184 " " + 185 Bundle.getMessage("Used") + 186 TAB + 187 Bundle.getMessage("RS") + 188 TAB + 189 Bundle.getMessage("Cars") + 190 TAB + 191 Bundle.getMessage("Engines") + 192 TAB + 193 padAndTruncate(Bundle.getMessage("Pickups"), 7) + 194 " " + 195 Bundle.getMessage("Drop") + 196 NEW_LINE; 197 writer.write(s); 198 199 for (Location location : locations) { 200 if (_location != null && location != _location) { 201 continue; 202 } 203 // location name, track length, used, number of RS, scheduled pick 204 // ups and drops 205 s = padAndTruncate(location.getName(), MAX_NAME_LENGTH) + 206 TAB + 207 " " + 208 Integer.toString(location.getLength()) + 209 TAB + 210 Integer.toString(location.getUsedLength()) + 211 TAB + 212 Integer.toString(location.getNumberRS()) + 213 TAB + 214 Integer.toString(location.getNumberCars()) + 215 TAB + 216 Integer.toString(location.getNumberEngines()) + 217 TAB + 218 Integer.toString(location.getPickupRS()) + 219 TAB + 220 Integer.toString(location.getDropRS()) + 221 NEW_LINE; 222 writer.write(s); 223 224 if (location.getDivision() != null) { 225 writer.write(SPACES_3 + Bundle.getMessage("Division") + ": " + location.getDivisionName() + NEW_LINE); 226 } 227 228 totalLength += location.getLength(); 229 usedLength += location.getUsedLength(); 230 numberRS += location.getNumberRS(); 231 232 List<Track> yards = location.getTracksByNameList(Track.YARD); 233 if (yards.size() > 0) { 234 // header 235 writer.write(SPACES_3 + Bundle.getMessage("YardName") + NEW_LINE); 236 for (Track yard : yards) { 237 writer.write(getTrackString(yard)); 238 numberCars += yard.getNumberCars(); 239 numberEngines += yard.getNumberEngines(); 240 } 241 } 242 243 List<Track> spurs = location.getTracksByNameList(Track.SPUR); 244 if (spurs.size() > 0) { 245 // header 246 writer.write(SPACES_3 + Bundle.getMessage("SpurName") + NEW_LINE); 247 for (Track spur : spurs) { 248 writer.write(getTrackString(spur)); 249 numberCars += spur.getNumberCars(); 250 numberEngines += spur.getNumberEngines(); 251 } 252 } 253 254 List<Track> interchanges = location.getTracksByNameList(Track.INTERCHANGE); 255 if (interchanges.size() > 0) { 256 // header 257 writer.write(SPACES_3 + Bundle.getMessage("InterchangeName") + NEW_LINE); 258 for (Track interchange : interchanges) { 259 writer.write(getTrackString(interchange)); 260 numberCars += interchange.getNumberCars(); 261 numberEngines += interchange.getNumberEngines(); 262 } 263 } 264 265 List<Track> stagingTracks = location.getTracksByNameList(Track.STAGING); 266 if (stagingTracks.size() > 0) { 267 // header 268 writer.write(SPACES_3 + Bundle.getMessage("StagingName") + NEW_LINE); 269 for (Track staging : stagingTracks) { 270 writer.write(getTrackString(staging)); 271 numberCars += staging.getNumberCars(); 272 numberEngines += staging.getNumberEngines(); 273 } 274 } 275 writer.write(NEW_LINE); 276 } 277 278 // summary 279 s = MessageFormat 280 .format(Bundle.getMessage("TotalLengthMsg"), 281 new Object[]{Integer.toString(totalLength), Integer.toString(usedLength), 282 totalLength > 0 ? Integer.toString(usedLength * 100 / totalLength) : 0}) + 283 NEW_LINE; 284 writer.write(s); 285 s = MessageFormat 286 .format(Bundle.getMessage("TotalRollingMsg"), 287 new Object[]{Integer.toString(numberRS), Integer.toString(numberCars), 288 Integer.toString(numberEngines)}) + 289 NEW_LINE; 290 writer.write(s); 291 // are there trains en route, then some cars and engines not counted! 292 if (numberRS != numberCars + numberEngines) { 293 s = Bundle.getMessage("NoteRSMsg", Integer.toString(numberRS - (numberCars + numberEngines))) + NEW_LINE; 294 writer.write(s); 295 } 296 if (printSchedules.isSelected() || 297 printComments.isSelected() || 298 printDetails.isSelected() || 299 printAnalysis.isSelected() || 300 printErrorAnalysis.isSelected()) { 301 writer.write(FORM_FEED); 302 } 303 } 304 305 private void printSchedulesSelected() throws IOException { 306 List<Location> locations = lmanager.getLocationsByNameList(); 307 String s = padAndTruncate(Bundle.getMessage("Schedules"), MAX_NAME_LENGTH) + 308 " " + 309 Bundle.getMessage("Location") + 310 " - " + 311 Bundle.getMessage("SpurName") + 312 NEW_LINE; 313 writer.write(s); 314 List<Schedule> schedules = InstanceManager.getDefault(ScheduleManager.class).getSchedulesByNameList(); 315 for (Schedule schedule : schedules) { 316 for (Location location : locations) { 317 if (_location != null && location != _location) { 318 continue; 319 } 320 List<Track> spurs = location.getTracksByNameList(Track.SPUR); 321 for (Track spur : spurs) { 322 if (spur.getScheduleId().equals(schedule.getId())) { 323 // pad out schedule name 324 s = padAndTruncate(schedule.getName(), 325 MAX_NAME_LENGTH) + " " + location.getName() + " - " + spur.getName(); 326 String status = spur.checkScheduleValid(); 327 if (!status.equals(Schedule.SCHEDULE_OKAY)) { 328 StringBuffer buf = new StringBuffer(s); 329 for (int m = s.length(); m < 63; m++) { 330 buf.append(" "); 331 } 332 s = buf.toString(); 333 if (s.length() > 63) { 334 s = s.substring(0, 63); 335 } 336 s = s + TAB + status; 337 } 338 s = s + NEW_LINE; 339 writer.write(s); 340 if (!schedule.getComment().isBlank()) { 341 s = padAndTruncate("", MAX_NAME_LENGTH) + SPACES_3 + schedule.getComment() + NEW_LINE; 342 writer.write(s); 343 } 344 // show the schedule's mode 345 s = padAndTruncate("", MAX_NAME_LENGTH) + 346 SPACES_3 + 347 Bundle.getMessage("ScheduleMode") + 348 ": " + 349 spur.getScheduleModeName() + 350 NEW_LINE; 351 writer.write(s); 352 // show alternate track if there's one 353 if (spur.getAlternateTrack() != null) { 354 s = padAndTruncate("", MAX_NAME_LENGTH) + 355 SPACES_3 + 356 Bundle.getMessage("AlternateTrackName", spur.getAlternateTrack().getName()) + 357 NEW_LINE; 358 writer.write(s); 359 } 360 // show custom loads from staging if not 100% 361 if (spur.getReservationFactor() != 100) { 362 s = padAndTruncate("", MAX_NAME_LENGTH) + 363 SPACES_3 + 364 Bundle.getMessage("PercentageStaging", 365 spur.getReservationFactor()) + 366 NEW_LINE; 367 writer.write(s); 368 } 369 } 370 } 371 } 372 } 373 // now show the contents of each schedule 374 for (Schedule schedule : schedules) { 375 writer.write(FORM_FEED); 376 s = schedule.getName() + NEW_LINE; 377 writer.write(s); 378 379 // set the minimum field lengths 380 int loadNameLength = cls.getMaxNameLength() + 1; 381 if (loadNameLength < Bundle.getMessage("Receive").length() + 1) { 382 loadNameLength = Bundle.getMessage("Receive").length() + 1; 383 } 384 int locationNameLength = lmanager.getMaxLocationNameLength() + 1; 385 if (locationNameLength < Bundle.getMessage("Destination").length() + 1) { 386 locationNameLength = Bundle.getMessage("Destination").length() + 1; 387 } 388 389 for (ScheduleItem si : schedule.getItemsBySequenceList()) { 390 s = padAndTruncate(Bundle.getMessage("Type"), cts.getMaxNameLength() + 1) + 391 padAndTruncate(Bundle.getMessage("Receive"), loadNameLength) + 392 padAndTruncate(Bundle.getMessage("Ship"), loadNameLength) + 393 padAndTruncate(Bundle.getMessage("Destination"), locationNameLength) + 394 Bundle.getMessage("Track") + 395 NEW_LINE; 396 writer.write(s); 397 s = padAndTruncate(si.getTypeName(), cts.getMaxNameLength() + 1) + 398 padAndTruncate(si.getReceiveLoadName(), loadNameLength) + 399 padAndTruncate(si.getShipLoadName(), loadNameLength) + 400 padAndTruncate(si.getDestinationName(), locationNameLength) + 401 si.getDestinationTrackName() + 402 NEW_LINE; 403 writer.write(s); 404 405 s = padAndTruncate("", cts.getMaxNameLength() + 1) + 406 padAndTruncate(Bundle.getMessage("Random"), Bundle.getMessage("Random").length() + 1) + 407 padAndTruncate(Bundle.getMessage("Delivery"), Bundle.getMessage("Delivery").length() + 1) + 408 padAndTruncate(Bundle.getMessage("Road"), crs.getMaxNameLength() + 1) + 409 padAndTruncate(Bundle.getMessage("Pickup"), Bundle.getMessage("Delivery").length() + 1) + 410 Bundle.getMessage("Wait") + 411 NEW_LINE; 412 writer.write(s); 413 414 s = padAndTruncate("", cts.getMaxNameLength() + 1) + 415 padAndTruncate(si.getRandom(), Bundle.getMessage("Random").length() + 1) + 416 padAndTruncate(si.getSetoutTrainScheduleName(), Bundle.getMessage("Delivery").length() + 1) + 417 padAndTruncate(si.getRoadName(), crs.getMaxNameLength() + 1) + 418 padAndTruncate(si.getPickupTrainScheduleName(), Bundle.getMessage("Delivery").length() + 1) + 419 si.getWait() + 420 NEW_LINE; 421 writer.write(s); 422 } 423 } 424 if (printComments.isSelected() || 425 printDetails.isSelected() || 426 printAnalysis.isSelected() || 427 printErrorAnalysis.isSelected()) { 428 writer.write(FORM_FEED); 429 } 430 } 431 432 private void printCommentsSelected() throws IOException { 433 String s = Bundle.getMessage("PrintComments") + NEW_LINE + NEW_LINE; 434 writer.write(s); 435 List<Location> locations = lmanager.getLocationsByNameList(); 436 for (Location location : locations) { 437 if (_location != null && location != _location) { 438 continue; 439 } 440 s = location.getName() + NEW_LINE; 441 writer.write(s); 442 s = SPACES_3 + location.getComment() + NEW_LINE; 443 writer.write(s); 444 for (Track track : location.getTracksByNameList(null)) { 445 if (!track.getComment().equals(Track.NONE) || 446 !track.getCommentBoth().equals(Track.NONE) || 447 !track.getCommentPickup().equals(Track.NONE) || 448 !track.getCommentSetout().equals(Track.NONE)) { 449 s = SPACES_2 + track.getName() + NEW_LINE; 450 writer.write(s); 451 if (!track.getComment().equals(Track.NONE)) { 452 s = SPACES_4 + track.getComment() + NEW_LINE; 453 writer.write(s); 454 } 455 if (!track.getCommentBoth().equals(Track.NONE)) { 456 s = SPACES_3 + Bundle.getMessage("CommentBoth") + ":" + NEW_LINE; 457 writer.write(s); 458 s = SPACES_4 + track.getCommentBoth() + NEW_LINE; 459 writer.write(s); 460 } 461 if (!track.getCommentPickup().equals(Track.NONE)) { 462 s = SPACES_3 + Bundle.getMessage("CommentPickup") + ":" + NEW_LINE; 463 writer.write(s); 464 s = SPACES_4 + track.getCommentPickup() + NEW_LINE; 465 writer.write(s); 466 } 467 if (!track.getCommentSetout().equals(Track.NONE)) { 468 s = SPACES_3 + Bundle.getMessage("CommentSetout") + ":" + NEW_LINE; 469 writer.write(s); 470 s = SPACES_4 + track.getCommentSetout() + NEW_LINE; 471 writer.write(s); 472 } 473 } 474 } 475 } 476 if (printDetails.isSelected() || printAnalysis.isSelected() || printErrorAnalysis.isSelected()) { 477 writer.write(FORM_FEED); 478 } 479 } 480 481 private void printDetailsSelected() throws IOException { 482 List<Location> locations = lmanager.getLocationsByNameList(); 483 String s = Bundle.getMessage("DetailedReport") + NEW_LINE; 484 writer.write(s); 485 for (Location location : locations) { 486 if (_location != null && location != _location) { 487 continue; 488 } 489 String name = location.getName(); 490 // services train direction 491 int dir = location.getTrainDirections(); 492 s = NEW_LINE + name + getDirection(dir); 493 writer.write(s); 494 495 // division 496 if (location.getDivision() != null) { 497 s = SPACES_3 + Bundle.getMessage("Division") + ": " + location.getDivisionName() + NEW_LINE; 498 writer.write(s); 499 } 500 501 // services car and engine types 502 s = getLocationTypes(location); 503 writer.write(s); 504 505 List<Track> spurs = location.getTracksByNameList(Track.SPUR); 506 if (spurs.size() > 0) { 507 s = SPACES_3 + Bundle.getMessage("SpurName") + NEW_LINE; 508 writer.write(s); 509 printTrackInfo(location, spurs); 510 } 511 512 List<Track> yards = location.getTracksByNameList(Track.YARD); 513 if (yards.size() > 0) { 514 s = SPACES_3 + Bundle.getMessage("YardName") + NEW_LINE; 515 writer.write(s); 516 printTrackInfo(location, yards); 517 } 518 519 List<Track> interchanges = location.getTracksByNameList(Track.INTERCHANGE); 520 if (interchanges.size() > 0) { 521 s = SPACES_3 + Bundle.getMessage("InterchangeName") + NEW_LINE; 522 writer.write(s); 523 printTrackInfo(location, interchanges); 524 } 525 526 List<Track> staging = location.getTracksByNameList(Track.STAGING); 527 if (staging.size() > 0) { 528 s = SPACES_3 + Bundle.getMessage("StagingName") + NEW_LINE; 529 writer.write(s); 530 printTrackInfo(location, staging); 531 } 532 } 533 if (printAnalysis.isSelected() || printErrorAnalysis.isSelected()) { 534 writer.write(FORM_FEED); 535 } 536 } 537 538 private final boolean showStaging = true; 539 540 private void printAnalysisSelected() throws IOException { 541 CarManager carManager = InstanceManager.getDefault(CarManager.class); 542 List<Location> locations = lmanager.getLocationsByNameList(); 543 List<Car> cars = carManager.getByLocationList(); 544 String[] carTypes = cts.getNames(); 545 546 String s = Bundle.getMessage("TrackAnalysis") + NEW_LINE; 547 writer.write(s); 548 549 // print the car type being analyzed 550 for (String type : carTypes) { 551 // get the total length for a given car type 552 int numberOfCars = 0; 553 int totalTrackLength = 0; 554 for (Car car : cars) { 555 if (car.getTypeName().equals(type) && car.getLocation() != null) { 556 numberOfCars++; 557 totalTrackLength += car.getTotalLength(); 558 } 559 } 560 writer.write(Bundle.getMessage("NumberTypeLength", 561 numberOfCars, type, totalTrackLength, Setup.getLengthUnit().toLowerCase()) + 562 NEW_LINE); 563 // don't bother reporting when the number of cars for a given type 564 // is zero. Round up percentage used by a car type. 565 if (numberOfCars > 0) { 566 // spurs 567 writer.write(SPACES_3 + 568 Bundle.getMessage("SpurTrackThatAccept", type) + 569 NEW_LINE); 570 int trackLength = getTrackLengthAcceptType(locations, type, Track.SPUR); 571 if (trackLength > 0) { 572 writer.write(SPACES_3 + 573 Bundle.getMessage("TotalLengthSpur", type, trackLength, Setup.getLengthUnit().toLowerCase(), 574 Math.ceil((double) 100 * totalTrackLength / trackLength)) + 575 NEW_LINE); 576 } else { 577 writer.write(SPACES_3 + Bundle.getMessage("None") + NEW_LINE); 578 } 579 // yards 580 writer.write(SPACES_3 + 581 Bundle.getMessage("YardTrackThatAccept", type) + 582 NEW_LINE); 583 trackLength = getTrackLengthAcceptType(locations, type, Track.YARD); 584 if (trackLength > 0) { 585 writer.write(SPACES_3 + 586 Bundle.getMessage("TotalLengthYard", type, trackLength, Setup.getLengthUnit().toLowerCase(), 587 Math.ceil((double) 100 * totalTrackLength / trackLength)) + 588 NEW_LINE); 589 } else { 590 writer.write(SPACES_3 + Bundle.getMessage("None") + NEW_LINE); 591 } 592 // interchanges 593 writer.write(SPACES_3 + 594 Bundle.getMessage("InterchangesThatAccept", type) + 595 NEW_LINE); 596 trackLength = getTrackLengthAcceptType(locations, type, Track.INTERCHANGE); 597 if (trackLength > 0) { 598 writer.write(SPACES_3 + 599 Bundle.getMessage("TotalLengthInterchange", 600 type, trackLength, Setup.getLengthUnit().toLowerCase(), 601 Math.ceil((double) 100 * totalTrackLength / trackLength)) + 602 NEW_LINE); 603 } else { 604 writer.write(SPACES_3 + Bundle.getMessage("None") + NEW_LINE); 605 } 606 // staging 607 if (showStaging) { 608 writer.write(SPACES_3 + 609 Bundle.getMessage("StageTrackThatAccept", type) + 610 NEW_LINE); 611 trackLength = getTrackLengthAcceptType(locations, type, Track.STAGING); 612 if (trackLength > 0) { 613 writer.write(SPACES_3 + 614 Bundle.getMessage("TotalLengthStage", 615 type, trackLength, Setup.getLengthUnit().toLowerCase(), 616 Math.ceil((double) 100 * totalTrackLength / trackLength)) + 617 NEW_LINE); 618 } else { 619 writer.write(SPACES_3 + Bundle.getMessage("None") + NEW_LINE); 620 } 621 } 622 } 623 } 624 if (printErrorAnalysis.isSelected()) { 625 writer.write(FORM_FEED); 626 } 627 } 628 629 private void printErrorAnalysisSelected() throws IOException { 630 writer.write(Bundle.getMessage("TrackErrorAnalysis") + NEW_LINE); 631 boolean foundError = false; 632 for (Location location : lmanager.getLocationsByNameList()) { 633 if (_location != null && location != _location) { 634 continue; 635 } 636 writer.write(location.getName() + NEW_LINE); 637 for (Track track : location.getTracksByNameList(null)) { 638 if (!track.checkPickups().equals(Track.PICKUP_OKAY)) { 639 writer.write(TAB + track.checkPickups() + NEW_LINE); 640 foundError = true; 641 } 642 } 643 } 644 if (!foundError) { 645 writer.write(Bundle.getMessage("NoErrors")); 646 } 647 } 648 649 private int getTrackLengthAcceptType(List<Location> locations, String carType, 650 String trackType) 651 throws IOException { 652 int trackLength = 0; 653 for (Location location : locations) { 654 if (_location != null && location != _location) { 655 continue; 656 } 657 List<Track> tracks = location.getTracksByNameList(trackType); 658 for (Track track : tracks) { 659 if (track.isTypeNameAccepted(carType)) { 660 trackLength = trackLength + track.getLength(); 661 writer.write(SPACES_3 + 662 SPACES_3 + 663 Bundle.getMessage("LocationTrackLength", 664 location.getName(), track.getName(), track.getLength(), 665 Setup.getLengthUnit().toLowerCase()) + 666 NEW_LINE); 667 } 668 } 669 } 670 return trackLength; 671 } 672 673 private String getTrackString(Track track) { 674 String s = TAB + 675 padAndTruncate(track.getName(), Control.max_len_string_track_name) + 676 " " + 677 Integer.toString(track.getLength()) + 678 TAB + 679 Integer.toString(track.getUsedLength()) + 680 TAB + 681 Integer.toString(track.getNumberRS()) + 682 TAB + 683 Integer.toString(track.getNumberCars()) + 684 TAB + 685 Integer.toString(track.getNumberEngines()) + 686 TAB + 687 Integer.toString(track.getPickupRS()) + 688 TAB + 689 Integer.toString(track.getDropRS()) + 690 NEW_LINE; 691 return s; 692 } 693 694 private String getDirection(int dir) { 695 if ((Setup.getTrainDirection() & dir) == 0) { 696 return " " + Bundle.getMessage("LocalOnly") + NEW_LINE; 697 } 698 StringBuffer direction = new StringBuffer(" " + Bundle.getMessage("ServicedByTrain") + " "); 699 if ((Setup.getTrainDirection() & dir & Location.NORTH) == Location.NORTH) { 700 direction.append(Bundle.getMessage("North") + " "); 701 } 702 if ((Setup.getTrainDirection() & dir & Location.SOUTH) == Location.SOUTH) { 703 direction.append(Bundle.getMessage("South") + " "); 704 } 705 if ((Setup.getTrainDirection() & dir & Location.EAST) == Location.EAST) { 706 direction.append(Bundle.getMessage("East") + " "); 707 } 708 if ((Setup.getTrainDirection() & dir & Location.WEST) == Location.WEST) { 709 direction.append(Bundle.getMessage("West") + " "); 710 } 711 direction.append(NEW_LINE); 712 return direction.toString(); 713 } 714 715 private void printTrackInfo(Location location, List<Track> tracks) { 716 for (Track track : tracks) { 717 try { 718 String s = TAB + 719 track.getName() + 720 getDirection(location.getTrainDirections() & track.getTrainDirections()); 721 writer.write(s); 722 printIsAlternate(track); 723 writer.write(getTrackCarTypes(track)); 724 writer.write(getTrackEngineTypes(track)); 725 writer.write(getTrackRoads(track)); 726 writer.write(getTrackLoads(track)); 727 writer.write(getTrackShipLoads(track)); 728 writer.write(getCarOrder(track)); 729 writer.write(getSetOutTrains(track)); 730 writer.write(getPickUpTrains(track)); 731 writer.write(getDestinations(track)); 732 writer.write(getTrackInfo(track)); 733 writer.write(getSpurInfo(track)); 734 writer.write(getSchedule(track)); 735 writer.write(getStagingInfo(track)); 736 printIsQuickService(track); 737 writer.write(NEW_LINE); 738 } catch (IOException we) { 739 log.error("Error printing PrintLocationAction: {}", we.getLocalizedMessage()); 740 } 741 } 742 } 743 744 private String getLocationTypes(Location location) { 745 StringBuffer buf = new StringBuffer(TAB + TAB + Bundle.getMessage("TypesServiced") + NEW_LINE + TAB + TAB); 746 int charCount = 0; 747 int typeCount = 0; 748 749 for (String type : cts.getNames()) { 750 if (location.acceptsTypeName(type)) { 751 typeCount++; 752 charCount += type.length() + 2; 753 if (charCount > charactersPerLine - 2 * TAB_LENGTH) { 754 buf.append(NEW_LINE + TAB + TAB); 755 charCount = type.length() + 2; 756 } 757 buf.append(type + ", "); 758 } 759 } 760 761 for (String type : InstanceManager.getDefault(EngineTypes.class).getNames()) { 762 if (location.acceptsTypeName(type)) { 763 typeCount++; 764 charCount += type.length() + 2; 765 if (charCount > charactersPerLine - 2 * TAB_LENGTH) { 766 buf.append(NEW_LINE + TAB + TAB); 767 charCount = type.length() + 2; 768 } 769 buf.append(type + ", "); 770 } 771 } 772 if (buf.length() > 2) { 773 buf.setLength(buf.length() - 2); // remove trailing separators 774 } 775 // does this location accept all types? 776 if (typeCount == cts.getNames().length + InstanceManager.getDefault(EngineTypes.class).getNames().length) { 777 buf = new StringBuffer(TAB + TAB + Bundle.getMessage("LocationAcceptsAllTypes")); 778 } 779 buf.append(NEW_LINE); 780 return buf.toString(); 781 } 782 783 private String getTrackCarTypes(Track track) { 784 StringBuffer buf = 785 new StringBuffer(TAB + TAB + Bundle.getMessage("CarTypesServicedTrack") + NEW_LINE + TAB + TAB); 786 int charCount = 0; 787 int typeCount = 0; 788 789 for (String type : cts.getNames()) { 790 if (track.isTypeNameAccepted(type)) { 791 typeCount++; 792 charCount += type.length() + 2; 793 if (charCount > charactersPerLine - 2 * TAB_LENGTH) { 794 buf.append(NEW_LINE + TAB + TAB); 795 charCount = type.length() + 2; 796 } 797 buf.append(type + ", "); 798 } 799 } 800 if (buf.length() > 2) { 801 buf.setLength(buf.length() - 2); // remove trailing separators 802 } 803 // does this track accept all types? 804 if (typeCount == cts.getNames().length) { 805 buf = new StringBuffer(TAB + TAB + Bundle.getMessage("TrackAcceptsAllCarTypes")); 806 } 807 buf.append(NEW_LINE); 808 return buf.toString(); 809 } 810 811 private String getTrackEngineTypes(Track track) { 812 StringBuffer buf = 813 new StringBuffer(TAB + TAB + Bundle.getMessage("EngineTypesServicedTrack") + NEW_LINE + TAB + TAB); 814 int charCount = 0; 815 int typeCount = 0; 816 817 for (String type : InstanceManager.getDefault(EngineTypes.class).getNames()) { 818 if (track.isTypeNameAccepted(type)) { 819 typeCount++; 820 charCount += type.length() + 2; 821 if (charCount > charactersPerLine - 2 * TAB_LENGTH) { 822 buf.append(NEW_LINE + TAB + TAB); 823 charCount = type.length() + 2; 824 } 825 buf.append(type + ", "); 826 } 827 } 828 if (buf.length() > 2) { 829 buf.setLength(buf.length() - 2); // remove trailing separators 830 } 831 // does this track accept all types? 832 if (typeCount == InstanceManager.getDefault(EngineTypes.class).getNames().length) { 833 buf = new StringBuffer(TAB + TAB + Bundle.getMessage("TrackAcceptsAllEngTypes")); 834 } 835 buf.append(NEW_LINE); 836 return buf.toString(); 837 } 838 839 private String getTrackRoads(Track track) { 840 if (track.getRoadOption().equals(Track.ALL_ROADS)) { 841 return TAB + TAB + Bundle.getMessage("AcceptsAllRoads") + NEW_LINE; 842 } 843 844 String op = Bundle.getMessage("RoadsServicedTrack"); 845 if (track.getRoadOption().equals(Track.EXCLUDE_ROADS)) { 846 op = Bundle.getMessage("ExcludeRoadsTrack"); 847 } 848 849 StringBuffer buf = new StringBuffer(TAB + TAB + op + NEW_LINE + TAB + TAB); 850 int charCount = 0; 851 852 for (String road : track.getRoadNames()) { 853 charCount += road.length() + 2; 854 if (charCount > charactersPerLine - 2 * TAB_LENGTH) { 855 buf.append(NEW_LINE + TAB + TAB); 856 charCount = road.length() + 2; 857 } 858 buf.append(road + ", "); 859 } 860 if (buf.length() > 2) { 861 buf.setLength(buf.length() - 2); // remove trailing separators 862 } 863 buf.append(NEW_LINE); 864 return buf.toString(); 865 } 866 867 private String getTrackLoads(Track track) { 868 if (track.getLoadOption().equals(Track.ALL_LOADS)) { 869 return TAB + TAB + Bundle.getMessage("AcceptsAllLoads") + NEW_LINE; 870 } 871 872 String op = Bundle.getMessage("LoadsServicedTrack"); 873 if (track.getLoadOption().equals(Track.EXCLUDE_LOADS)) { 874 op = Bundle.getMessage("ExcludeLoadsTrack"); 875 } 876 877 StringBuffer buf = new StringBuffer(TAB + TAB + op + NEW_LINE + TAB + TAB); 878 int charCount = 0; 879 880 for (String load : track.getLoadNames()) { 881 charCount += load.length() + 2; 882 if (charCount > charactersPerLine - 2 * TAB_LENGTH) { 883 buf.append(NEW_LINE + TAB + TAB); 884 charCount = load.length() + 2; 885 } 886 buf.append(load + ", "); 887 } 888 if (buf.length() > 2) { 889 buf.setLength(buf.length() - 2); // remove trailing separators 890 } 891 buf.append(NEW_LINE); 892 return buf.toString(); 893 } 894 895 private String getTrackShipLoads(Track track) { 896 // only staging has the ship load control 897 if (!track.isStaging()) { 898 return ""; 899 } 900 if (track.getShipLoadOption().equals(Track.ALL_LOADS)) { 901 return TAB + TAB + Bundle.getMessage("ShipsAllLoads") + NEW_LINE; 902 } 903 String op = Bundle.getMessage("LoadsShippedTrack"); 904 if (track.getShipLoadOption().equals(Track.EXCLUDE_LOADS)) { 905 op = Bundle.getMessage("ExcludeLoadsShippedTrack"); 906 } 907 908 StringBuffer buf = new StringBuffer(TAB + TAB + op + NEW_LINE + TAB + TAB); 909 int charCount = 0; 910 911 for (String load : track.getShipLoadNames()) { 912 charCount += load.length() + 2; 913 if (charCount > charactersPerLine - 2 * TAB_LENGTH) { 914 buf.append(NEW_LINE + TAB + TAB); 915 charCount = load.length() + 2; 916 } 917 buf.append(load + ", "); 918 } 919 if (buf.length() > 2) { 920 buf.setLength(buf.length() - 2); // remove trailing separators 921 } 922 buf.append(NEW_LINE); 923 return buf.toString(); 924 } 925 926 private String getCarOrder(Track track) { 927 // only yards and interchanges have the car order option 928 if (track.isSpur() || track.isStaging() || track.getServiceOrder().equals(Track.NORMAL)) { 929 return ""; 930 } 931 if (track.getServiceOrder().equals(Track.FIFO)) { 932 return TAB + TAB + Bundle.getMessage("TrackPickUpOrderFIFO") + NEW_LINE; 933 } 934 return TAB + TAB + Bundle.getMessage("TrackPickUpOrderLIFO") + NEW_LINE; 935 } 936 937 private String getSetOutTrains(Track track) { 938 if (track.getDropOption().equals(Track.ANY)) { 939 return TAB + TAB + Bundle.getMessage("SetOutAllTrains") + NEW_LINE; 940 } 941 StringBuffer buf; 942 int charCount = 0; 943 String[] ids = track.getDropIds(); 944 if (track.getDropOption().equals(Track.TRAINS) || track.getDropOption().equals(Track.EXCLUDE_TRAINS)) { 945 String trainType = Bundle.getMessage("TrainsSetOutTrack"); 946 if (track.getDropOption().equals(Track.EXCLUDE_TRAINS)) { 947 trainType = Bundle.getMessage("ExcludeTrainsSetOutTrack"); 948 } 949 buf = new StringBuffer(TAB + TAB + trainType + NEW_LINE + TAB + TAB); 950 for (String id : ids) { 951 Train train = InstanceManager.getDefault(TrainManager.class).getTrainById(id); 952 if (train == null) { 953 log.info("Could not find a train for id: {} track ({})", id, track.getName()); 954 continue; 955 } 956 charCount += train.getName().length() + 2; 957 if (charCount > charactersPerLine - 2 * TAB_LENGTH) { 958 buf.append(NEW_LINE + TAB + TAB); 959 charCount = train.getName().length() + 2; 960 } 961 buf.append(train.getName() + ", "); 962 } 963 } else { 964 String routeType = Bundle.getMessage("RoutesSetOutTrack"); 965 if (track.getDropOption().equals(Track.EXCLUDE_ROUTES)) { 966 routeType = Bundle.getMessage("ExcludeRoutesSetOutTrack"); 967 } 968 buf = new StringBuffer(TAB + TAB + routeType + NEW_LINE + TAB + TAB); 969 for (String id : ids) { 970 Route route = InstanceManager.getDefault(RouteManager.class).getRouteById(id); 971 if (route == null) { 972 log.info("Could not find a route for id: {} location ({}) track ({})", id, 973 track.getLocation().getName(), track.getName()); // NOI18N 974 continue; 975 } 976 charCount += route.getName().length() + 2; 977 if (charCount > charactersPerLine - 2 * TAB_LENGTH) { 978 buf.append(NEW_LINE + TAB + TAB); 979 charCount = route.getName().length() + 2; 980 } 981 buf.append(route.getName() + ", "); 982 } 983 } 984 if (buf.length() > 2) { 985 buf.setLength(buf.length() - 2); // remove trailing separators 986 } 987 buf.append(NEW_LINE); 988 return buf.toString(); 989 } 990 991 private String getPickUpTrains(Track track) { 992 if (track.getPickupOption().equals(Track.ANY)) { 993 return TAB + TAB + Bundle.getMessage("PickUpAllTrains") + NEW_LINE; 994 } 995 StringBuffer buf; 996 int charCount = 0; 997 String[] ids = track.getPickupIds(); 998 if (track.getPickupOption().equals(Track.TRAINS) || track.getPickupOption().equals(Track.EXCLUDE_TRAINS)) { 999 String trainType = Bundle.getMessage("TrainsPickUpTrack"); 1000 if (track.getPickupOption().equals(Track.EXCLUDE_TRAINS)) { 1001 trainType = Bundle.getMessage("ExcludeTrainsPickUpTrack"); 1002 } 1003 buf = new StringBuffer(TAB + TAB + trainType + NEW_LINE + TAB + TAB); 1004 for (String id : ids) { 1005 Train train = InstanceManager.getDefault(TrainManager.class).getTrainById(id); 1006 if (train == null) { 1007 log.info("Could not find a train for id: {} track ({})", id, track.getName()); 1008 continue; 1009 } 1010 charCount += train.getName().length() + 2; 1011 if (charCount > charactersPerLine - 2 * TAB_LENGTH) { 1012 buf.append(NEW_LINE + TAB + TAB); 1013 charCount = train.getName().length() + 2; 1014 } 1015 buf.append(train.getName() + ", "); 1016 } 1017 } else { 1018 String routeType = Bundle.getMessage("RoutesPickUpTrack"); 1019 if (track.getPickupOption().equals(Track.EXCLUDE_ROUTES)) { 1020 routeType = Bundle.getMessage("ExcludeRoutesPickUpTrack"); 1021 } 1022 buf = new StringBuffer(TAB + TAB + routeType + NEW_LINE + TAB + TAB); 1023 for (String id : ids) { 1024 Route route = InstanceManager.getDefault(RouteManager.class).getRouteById(id); 1025 if (route == null) { 1026 log.info("Could not find a route for id: {} location ({}) track ({})", id, 1027 track.getLocation().getName(), track.getName()); // NOI18N 1028 continue; 1029 } 1030 charCount += route.getName().length() + 2; 1031 if (charCount > charactersPerLine - 2 * TAB_LENGTH) { 1032 buf.append(NEW_LINE + TAB + TAB); 1033 charCount = route.getName().length() + 2; 1034 } 1035 buf.append(route.getName() + ", "); 1036 } 1037 } 1038 if (buf.length() > 2) { 1039 buf.setLength(buf.length() - 2); // remove trailing separators 1040 } 1041 buf.append(NEW_LINE); 1042 return buf.toString(); 1043 } 1044 1045 private String getDestinations(Track track) { 1046 StringBuffer buf = new StringBuffer(); 1047 if (track.isOnlyCarsWithFinalDestinationEnabled()) { 1048 buf.append(TAB + TAB + Bundle.getMessage("OnlyCarsWithFD")); 1049 buf.append(NEW_LINE); 1050 } 1051 if (track.getDestinationOption().equals(Track.ALL_DESTINATIONS)) { 1052 return buf.toString(); 1053 } 1054 String op = Bundle.getMessage( 1055 "AcceptOnly") + " " + track.getDestinationListSize() + " " + Bundle.getMessage("Destinations") + ":"; 1056 if (track.getDestinationOption().equals(Track.EXCLUDE_DESTINATIONS)) { 1057 op = Bundle.getMessage("Exclude") + 1058 " " + 1059 (lmanager.getNumberOfLocations() - track.getDestinationListSize()) + 1060 " " + 1061 Bundle.getMessage("Destinations") + 1062 ":"; 1063 } 1064 buf.append(TAB + TAB + op + NEW_LINE + TAB + TAB); 1065 String[] destIds = track.getDestinationIds(); 1066 int charCount = 0; 1067 for (String id : destIds) { 1068 Location location = lmanager.getLocationById(id); 1069 if (location == null) { 1070 continue; 1071 } 1072 charCount += location.getName().length() + 2; 1073 if (charCount > charactersPerLine - 2 * TAB_LENGTH) { 1074 buf.append(NEW_LINE + TAB + TAB); 1075 charCount = location.getName().length() + 2; 1076 } 1077 buf.append(location.getName() + ", "); 1078 } 1079 if (buf.length() > 2) { 1080 buf.setLength(buf.length() - 2); // remove trailing separators 1081 } 1082 buf.append(NEW_LINE); 1083 return buf.toString(); 1084 } 1085 1086 private String getTrackInfo(Track track) { 1087 if (track.getPool() != null) { 1088 StringBuffer buf = 1089 new StringBuffer(TAB + TAB + Bundle.getMessage("Pool") + ": " + track.getPoolName() + NEW_LINE); 1090 return buf.toString(); 1091 } 1092 return ""; 1093 } 1094 1095 private String getSchedule(Track track) { 1096 // only spurs have schedules 1097 if (!track.isSpur() || track.getSchedule() == null) { 1098 return ""; 1099 } 1100 StringBuffer buf = new StringBuffer(TAB + 1101 TAB + 1102 Bundle.getMessage("TrackScheduleName", track.getScheduleName()) + 1103 NEW_LINE); 1104 if (track.getAlternateTrack() != null) { 1105 buf.append(TAB + 1106 TAB + 1107 Bundle.getMessage("AlternateTrackName", 1108 track.getAlternateTrack().getName()) + 1109 NEW_LINE); 1110 } 1111 if (track.getReservationFactor() != 100) { 1112 buf.append(TAB + 1113 TAB + 1114 Bundle.getMessage("PercentageStaging", 1115 track.getReservationFactor()) + 1116 NEW_LINE); 1117 } 1118 return buf.toString(); 1119 } 1120 1121 private void printIsAlternate(Track track) throws IOException { 1122 if (track.isAlternate()) { 1123 writer.write(TAB + TAB + Bundle.getMessage("AlternateTrack") + NEW_LINE); 1124 } 1125 } 1126 1127 private void printIsQuickService(Track track) throws IOException { 1128 if (track.isQuickServiceEnabled()) { 1129 writer.write(TAB + TAB + Bundle.getMessage("QuickService") + NEW_LINE); 1130 } 1131 } 1132 1133 private String getSpurInfo(Track track) { 1134 if (!track.isSpur()) { 1135 return ""; 1136 } 1137 1138 StringBuffer buf = new StringBuffer(); 1139 1140 if (track.isHoldCarsWithCustomLoadsEnabled()) { 1141 buf.append(TAB + TAB + Bundle.getMessage("HoldCarsWithCustomLoads") + NEW_LINE); 1142 } 1143 if (track.isDisableLoadChangeEnabled()) { 1144 buf.append(TAB + TAB + Bundle.getMessage("DisableLoadChange") + NEW_LINE); 1145 } 1146 return buf.toString(); 1147 } 1148 1149 private String getStagingInfo(Track track) { 1150 if (!track.isStaging()) { 1151 return ""; 1152 } 1153 1154 StringBuffer buf = new StringBuffer(); 1155 1156 if (track.isLoadSwapEnabled() || track.isLoadEmptyEnabled()) { 1157 buf.append(TAB + SPACES_3 + Bundle.getMessage("OptionalLoads") + NEW_LINE); 1158 if (track.isLoadSwapEnabled()) { 1159 buf.append(TAB + TAB + Bundle.getMessage("SwapCarLoads") + NEW_LINE); 1160 } 1161 if (track.isLoadEmptyEnabled()) { 1162 buf.append(TAB + TAB + Bundle.getMessage("EmptyDefaultCarLoads") + NEW_LINE); 1163 } 1164 } 1165 1166 if (track.isRemoveCustomLoadsEnabled() || 1167 track.isAddCustomLoadsEnabled() || 1168 track.isAddCustomLoadsAnySpurEnabled() || 1169 track.isAddCustomLoadsAnyStagingTrackEnabled()) { 1170 buf.append(TAB + SPACES_3 + Bundle.getMessage("OptionalCustomLoads") + NEW_LINE); 1171 if (track.isRemoveCustomLoadsEnabled()) { 1172 buf.append(TAB + TAB + Bundle.getMessage("EmptyCarLoads") + NEW_LINE); 1173 } 1174 if (track.isAddCustomLoadsEnabled()) { 1175 buf.append(TAB + TAB + Bundle.getMessage("LoadCarLoads") + NEW_LINE); 1176 } 1177 if (track.isAddCustomLoadsAnySpurEnabled()) { 1178 buf.append(TAB + TAB + Bundle.getMessage("LoadAnyCarLoads") + NEW_LINE); 1179 } 1180 if (track.isAddCustomLoadsAnyStagingTrackEnabled()) { 1181 buf.append(TAB + TAB + Bundle.getMessage("LoadsStaging") + NEW_LINE); 1182 } 1183 } 1184 1185 if (track.isBlockCarsEnabled()) { 1186 buf.append(TAB + SPACES_3 + Bundle.getMessage("OptionalBlocking") + NEW_LINE); 1187 buf.append(TAB + TAB + Bundle.getMessage("BlockCars") + NEW_LINE); 1188 } 1189 return buf.toString(); 1190 } 1191 1192 private String padAndTruncate(String s, int length) { 1193 return TrainCommon.padAndTruncate(s, length); 1194 } 1195 1196 private static final Logger log = LoggerFactory.getLogger(PrintLocationsFrame.class); 1197}