001package jmri.jmrit.operations.locations.schedules; 002 003import org.slf4j.Logger; 004import org.slf4j.LoggerFactory; 005 006import jmri.InstanceManager; 007import jmri.beans.PropertyChangeSupport; 008import jmri.jmrit.operations.locations.*; 009import jmri.jmrit.operations.setup.Setup; 010import jmri.jmrit.operations.trains.schedules.TrainSchedule; 011import jmri.jmrit.operations.trains.schedules.TrainScheduleManager; 012 013/** 014 * Represents one schedule item of a schedule 015 * 016 * @author Daniel Boudreau Copyright (C) 2009, 2010, 2013, 2014 017 */ 018public class ScheduleItem extends PropertyChangeSupport { 019 020 public static final String NONE = ""; // NOI18N 021 022 protected String _id = NONE; 023 protected int _sequenceId = 0; // used to determine order in schedule 024 protected String _random = NONE; // used to determine if random set out is needed 025 protected String _setoutTrainScheduleId = NONE; // which day of the week to deliver car 026 protected String _type = NONE; // the type of car 027 protected String _road = NONE; // the car road 028 protected String _load = NONE; // the car load requested 029 protected String _ship = NONE; // the car load shipped 030 protected Location _destination = null; // car destination after load 031 protected Track _trackDestination = null;// car destination track after load 032 protected String _pickupTrainScheduleId = NONE; // which day of the week to pickup car 033 protected int _count = 1; // the number of times this type of car must be dropped 034 protected int _wait = 0; // how many trains this car must wait before being picked up 035 protected int _hits = 0; // how many times this schedule item has been used 036 protected String _comment = NONE; 037 038 public static final String TRAIN_SCHEDULE_CHANGED_PROPERTY = "trainScheduleId"; // NOI18N 039 public static final String COUNT_CHANGED_PROPERTY = "scheduleItemCount"; // NOI18N 040 public static final String TYPE_CHANGED_PROPERTY = "scheduleItemType"; // NOI18N 041 public static final String ROAD_CHANGED_PROPERTY = "scheduleItemRoad"; // NOI18N 042 public static final String LOAD_CHANGED_PROPERTY = "scheduleItemLoad"; // NOI18N 043 public static final String DESTINATION_CHANGED_PROPERTY = "scheduleItemDestination"; // NOI18N 044 public static final String DESTINATION_TRACK_CHANGED_PROPERTY = "scheduleItemDestinationTrack"; // NOI18N 045 public static final String WAIT_CHANGED_PROPERTY = "scheduleItemWait"; // NOI18N 046 public static final String HITS_CHANGED_PROPERTY = "scheduleItemHits"; // NOI18N 047 public static final String DISPOSE = "scheduleItemDispose"; // NOI18N 048 049 /** 050 * @param id ScheduleItem string id 051 * @param type car type for schedule 052 */ 053 public ScheduleItem(String id, String type) { 054 log.debug("New schedule item, car type ({}) id: {}", type, id); 055 _type = type; 056 _id = id; 057 } 058 059 public String getId() { 060 return _id; 061 } 062 063 public String getTypeName() { 064 return _type; 065 } 066 067 /** 068 * Sets the type of car requested. 069 * 070 * @param type The car type requested. 071 */ 072 public void setTypeName(String type) { 073 String old = _type; 074 _type = type; 075 firePropertyChange(TYPE_CHANGED_PROPERTY, old, type); 076 } 077 078 public String getRandom() { 079 return _random; 080 } 081 082 public void setRandom(String value) { 083 String old = _random; 084 _random = value; 085 firePropertyChange("scheduleItemRandomValueChanged", old, value); // NOI18N 086 } 087 088 /** 089 * Method determines by random if a car is accepted by a scheduleItem 090 * 091 * @return true if car is accepted by the scheduleItem 092 */ 093 public boolean doRandom() { 094 // make an adjustment based on the number of passes 095 int passes = 1; 096 if (Setup.isBuildAggressive()) { 097 passes = Setup.getNumberPasses(); 098 } 099 _calculatedRandom = 100 * passes * Math.random(); 100 try { 101 int value = Integer.parseInt(getRandom()); 102 log.debug("Selected random {}, created random {}", getRandom(), _calculatedRandom); 103 if (_calculatedRandom <= value) { 104 return true; 105 } 106 } catch (NumberFormatException e) { 107 log.error("Schedule item ({}) random value ({}) isn't a number", getId(), getRandom()); 108 } 109 return false; 110 } 111 112 double _calculatedRandom; 113 114 public double getCalculatedRandom() { 115 return _calculatedRandom; 116 } 117 118 public String getSetoutTrainScheduleId() { 119 return _setoutTrainScheduleId; 120 } 121 122 public String getSetoutTrainScheduleName() { 123 String name = ""; 124 TrainSchedule sch = InstanceManager.getDefault(TrainScheduleManager.class) 125 .getScheduleById(getSetoutTrainScheduleId()); 126 if (sch != null) { 127 name = sch.getName(); 128 } 129 return name; 130 } 131 132 public void setSetoutTrainScheduleId(String id) { 133 String old = _setoutTrainScheduleId; 134 _setoutTrainScheduleId = id; 135 firePropertyChange(TRAIN_SCHEDULE_CHANGED_PROPERTY, old, id); 136 } 137 138 public String getPickupTrainScheduleId() { 139 return _pickupTrainScheduleId; 140 } 141 142 public String getPickupTrainScheduleName() { 143 String name = ""; 144 TrainSchedule sch = InstanceManager.getDefault(TrainScheduleManager.class) 145 .getScheduleById(getPickupTrainScheduleId()); 146 if (sch != null) { 147 name = sch.getName(); 148 } 149 return name; 150 } 151 152 public void setPickupTrainScheduleId(String id) { 153 String old = _pickupTrainScheduleId; 154 _pickupTrainScheduleId = id; 155 firePropertyChange(TRAIN_SCHEDULE_CHANGED_PROPERTY, old, id); 156 } 157 158 public String getRoadName() { 159 return _road; 160 } 161 162 /** 163 * Sets the requested car road name. 164 * 165 * @param road The car road requested. 166 */ 167 public void setRoadName(String road) { 168 String old = _road; 169 _road = road; 170 firePropertyChange(ROAD_CHANGED_PROPERTY, old, road); 171 } 172 173 /** 174 * Sets the car load requested. 175 * 176 * @param load The load name requested. 177 */ 178 public void setReceiveLoadName(String load) { 179 String old = _load; 180 _load = load; 181 firePropertyChange(LOAD_CHANGED_PROPERTY, old, load); 182 } 183 184 public String getReceiveLoadName() { 185 return _load; 186 } 187 188 /** 189 * Sets the car load that will ship. 190 * 191 * @param load The car load shipped. 192 */ 193 public void setShipLoadName(String load) { 194 String old = _ship; 195 _ship = load; 196 firePropertyChange(LOAD_CHANGED_PROPERTY, old, load); 197 } 198 199 public String getShipLoadName() { 200 return _ship; 201 } 202 203 public int getSequenceId() { 204 return _sequenceId; 205 } 206 207 public void setSequenceId(int sequence) { 208 // property change not needed 209 _sequenceId = sequence; 210 } 211 212 /** 213 * How many times a car type needs to use the schedule item before going to 214 * the next item in the schedule. Used in sequential mode. Default is one. 215 * 216 * @return the number of times a car type needs to use the schedule item 217 */ 218 public int getCount() { 219 return _count; 220 } 221 222 public void setCount(int count) { 223 int old = _count; 224 _count = count; 225 firePropertyChange(COUNT_CHANGED_PROPERTY, old, count); 226 } 227 228 public int getWait() { 229 return _wait; 230 } 231 232 public void setWait(int wait) { 233 int old = _wait; 234 _wait = wait; 235 firePropertyChange(WAIT_CHANGED_PROPERTY, old, wait); 236 } 237 238 public int getHits() { 239 return _hits; 240 } 241 242 public void setHits(int hit) { 243 int old = _hits; 244 _hits = hit; 245 firePropertyChange(HITS_CHANGED_PROPERTY, old, hit); 246 } 247 248 public Location getDestination() { 249 return _destination; 250 } 251 252 public void setDestination(Location destination) { 253 Location old = _destination; 254 _destination = destination; 255 firePropertyChange(DESTINATION_CHANGED_PROPERTY, old, destination); 256 } 257 258 public String getDestinationName() { 259 if (_destination != null) { 260 return _destination.getName(); 261 } 262 return NONE; 263 } 264 265 public String getDestinationId() { 266 if (_destination != null) { 267 return _destination.getId(); 268 } 269 return NONE; 270 } 271 272 public Track getDestinationTrack() { 273 return _trackDestination; 274 } 275 276 public void setDestinationTrack(Track track) { 277 Track old = _trackDestination; 278 _trackDestination = track; 279 firePropertyChange(DESTINATION_TRACK_CHANGED_PROPERTY, old, track); 280 } 281 282 public String getDestinationTrackName() { 283 if (_trackDestination != null) { 284 return _trackDestination.getName(); 285 } 286 return NONE; 287 } 288 289 public String getDestinationTrackId() { 290 if (_trackDestination != null) { 291 return _trackDestination.getId(); 292 } 293 return NONE; 294 } 295 296 public void setComment(String comment) { 297 _comment = comment; 298 } 299 300 public String getComment() { 301 return _comment; 302 } 303 304 public void copyScheduleItem(ScheduleItem si) { 305 setComment(si.getComment()); 306 setCount(si.getCount()); 307 setDestination(si.getDestination()); 308 setDestinationTrack(si.getDestinationTrack()); 309 setPickupTrainScheduleId(si.getPickupTrainScheduleId()); 310 setRandom(si.getRandom()); 311 setReceiveLoadName(si.getReceiveLoadName()); 312 setRoadName(si.getRoadName()); 313 setSetoutTrainScheduleId(si.getSetoutTrainScheduleId()); 314 setShipLoadName(si.getShipLoadName()); 315 setWait(si.getWait()); 316 } 317 318 public void dispose() { 319 firePropertyChange(DISPOSE, null, DISPOSE); 320 } 321 322 /** 323 * Construct this Entry from XML. This member has to remain synchronized 324 * with the detailed DTD in operations-config.xml 325 * 326 * @param e Consist XML element 327 */ 328 public ScheduleItem(org.jdom2.Element e) { 329 org.jdom2.Attribute a; 330 if ((a = e.getAttribute(Xml.ID)) != null) { 331 _id = a.getValue(); 332 } else { 333 log.warn("no id attribute in Schedule Item element when reading operations"); 334 } 335 if ((a = e.getAttribute(Xml.SEQUENCE_ID)) != null) { 336 _sequenceId = Integer.parseInt(a.getValue()); 337 } 338 if ((a = e.getAttribute(Xml.RANDOM)) != null) { 339 _random = a.getValue(); 340 } 341 if ((a = e.getAttribute(Xml.TRAIN_SCHEDULE_ID)) != null) { 342 _setoutTrainScheduleId = a.getValue(); 343 } 344 if ((a = e.getAttribute(Xml.PICKUP_TRAIN_SCHEDULE_ID)) != null) { 345 _pickupTrainScheduleId = a.getValue(); 346 } 347 if ((a = e.getAttribute(Xml.COUNT)) != null) { 348 _count = Integer.parseInt(a.getValue()); 349 } 350 if ((a = e.getAttribute(Xml.WAIT)) != null) { 351 _wait = Integer.parseInt(a.getValue()); 352 } 353 if ((a = e.getAttribute(Xml.TYPE)) != null) { 354 _type = a.getValue(); 355 } 356 if ((a = e.getAttribute(Xml.ROAD)) != null) { 357 _road = a.getValue(); 358 } 359 if ((a = e.getAttribute(Xml.LOAD)) != null) { 360 _load = a.getValue(); 361 } 362 if ((a = e.getAttribute(Xml.SHIP)) != null) { 363 _ship = a.getValue(); 364 } 365 if ((a = e.getAttribute(Xml.DESTINATION_ID)) != null) { 366 _destination = InstanceManager.getDefault(LocationManager.class).getLocationById(a.getValue()); 367 } 368 if ((a = e.getAttribute(Xml.DEST_TRACK_ID)) != null && _destination != null) { 369 _trackDestination = _destination.getTrackById(a.getValue()); 370 } 371 if ((a = e.getAttribute(Xml.COMMENT)) != null) { 372 _comment = a.getValue(); 373 } 374 if ((a = e.getAttribute(Xml.HITS)) != null) { 375 _hits = Integer.parseInt(a.getValue()); 376 } 377 } 378 379 /** 380 * Create an XML element to represent this Entry. This member has to remain 381 * synchronized with the detailed DTD in operations-config.xml. 382 * 383 * @return Contents in a JDOM Element 384 */ 385 public org.jdom2.Element store() { 386 org.jdom2.Element e = new org.jdom2.Element(Xml.ITEM); 387 e.setAttribute(Xml.ID, getId()); 388 e.setAttribute(Xml.SEQUENCE_ID, Integer.toString(getSequenceId())); 389 e.setAttribute(Xml.RANDOM, getRandom()); 390 e.setAttribute(Xml.TRAIN_SCHEDULE_ID, getSetoutTrainScheduleId()); 391 e.setAttribute(Xml.PICKUP_TRAIN_SCHEDULE_ID, getPickupTrainScheduleId()); 392 e.setAttribute(Xml.COUNT, Integer.toString(getCount())); 393 e.setAttribute(Xml.WAIT, Integer.toString(getWait())); 394 e.setAttribute(Xml.TYPE, getTypeName()); 395 e.setAttribute(Xml.ROAD, getRoadName()); 396 e.setAttribute(Xml.LOAD, getReceiveLoadName()); 397 e.setAttribute(Xml.SHIP, getShipLoadName()); 398 if (!getDestinationId().equals(NONE)) { 399 e.setAttribute(Xml.DESTINATION_ID, getDestinationId()); 400 } 401 if (!getDestinationTrackId().equals(NONE)) { 402 e.setAttribute(Xml.DEST_TRACK_ID, getDestinationTrackId()); 403 } 404 e.setAttribute(Xml.COMMENT, getComment()); 405 e.setAttribute(Xml.HITS, Integer.toString(getHits())); 406 return e; 407 } 408 409 private static final Logger log = LoggerFactory.getLogger(ScheduleItem.class); 410 411}