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.rollingstock.cars.CarManager; 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 cars of a given type 095 int numberOfCars = InstanceManager.getDefault(CarManager.class).getByTypeList(getTypeName()).size(); 096 int adjustment = 100 + numberOfCars; 097 _calculatedRandom = adjustment * Math.random(); 098 try { 099 int value = Integer.parseInt(getRandom()); 100 log.debug("Selected random {}, created random {}", getRandom(), _calculatedRandom); 101 if (_calculatedRandom <= value) { 102 return true; 103 } 104 } catch (NumberFormatException e) { 105 log.error("Schedule item ({}) random value ({}) isn't a number", getId(), getRandom()); 106 } 107 return false; 108 } 109 110 double _calculatedRandom; 111 112 public double getCalculatedRandom() { 113 return _calculatedRandom; 114 } 115 116 public String getSetoutTrainScheduleId() { 117 return _setoutTrainScheduleId; 118 } 119 120 public String getSetoutTrainScheduleName() { 121 String name = ""; 122 TrainSchedule sch = InstanceManager.getDefault(TrainScheduleManager.class) 123 .getScheduleById(getSetoutTrainScheduleId()); 124 if (sch != null) { 125 name = sch.getName(); 126 } 127 return name; 128 } 129 130 public void setSetoutTrainScheduleId(String id) { 131 String old = _setoutTrainScheduleId; 132 _setoutTrainScheduleId = id; 133 firePropertyChange(TRAIN_SCHEDULE_CHANGED_PROPERTY, old, id); 134 } 135 136 public String getPickupTrainScheduleId() { 137 return _pickupTrainScheduleId; 138 } 139 140 public String getPickupTrainScheduleName() { 141 String name = ""; 142 TrainSchedule sch = InstanceManager.getDefault(TrainScheduleManager.class) 143 .getScheduleById(getPickupTrainScheduleId()); 144 if (sch != null) { 145 name = sch.getName(); 146 } 147 return name; 148 } 149 150 public void setPickupTrainScheduleId(String id) { 151 String old = _pickupTrainScheduleId; 152 _pickupTrainScheduleId = id; 153 firePropertyChange(TRAIN_SCHEDULE_CHANGED_PROPERTY, old, id); 154 } 155 156 public String getRoadName() { 157 return _road; 158 } 159 160 /** 161 * Sets the requested car road name. 162 * 163 * @param road The car road requested. 164 */ 165 public void setRoadName(String road) { 166 String old = _road; 167 _road = road; 168 firePropertyChange(ROAD_CHANGED_PROPERTY, old, road); 169 } 170 171 /** 172 * Sets the car load requested. 173 * 174 * @param load The load name requested. 175 */ 176 public void setReceiveLoadName(String load) { 177 String old = _load; 178 _load = load; 179 firePropertyChange(LOAD_CHANGED_PROPERTY, old, load); 180 } 181 182 public String getReceiveLoadName() { 183 return _load; 184 } 185 186 /** 187 * Sets the car load that will ship. 188 * 189 * @param load The car load shipped. 190 */ 191 public void setShipLoadName(String load) { 192 String old = _ship; 193 _ship = load; 194 firePropertyChange(LOAD_CHANGED_PROPERTY, old, load); 195 } 196 197 public String getShipLoadName() { 198 return _ship; 199 } 200 201 public int getSequenceId() { 202 return _sequenceId; 203 } 204 205 public void setSequenceId(int sequence) { 206 // property change not needed 207 _sequenceId = sequence; 208 } 209 210 /** 211 * How many times a car type needs to use the schedule item before going to 212 * the next item in the schedule. Used in sequential mode. Default is one. 213 * 214 * @return the number of times a car type needs to use the schedule item 215 */ 216 public int getCount() { 217 return _count; 218 } 219 220 public void setCount(int count) { 221 int old = _count; 222 _count = count; 223 firePropertyChange(COUNT_CHANGED_PROPERTY, old, count); 224 } 225 226 public int getWait() { 227 return _wait; 228 } 229 230 public void setWait(int wait) { 231 int old = _wait; 232 _wait = wait; 233 firePropertyChange(WAIT_CHANGED_PROPERTY, old, wait); 234 } 235 236 public int getHits() { 237 return _hits; 238 } 239 240 public void setHits(int hit) { 241 int old = _hits; 242 _hits = hit; 243 firePropertyChange(HITS_CHANGED_PROPERTY, old, hit); 244 } 245 246 public Location getDestination() { 247 return _destination; 248 } 249 250 public void setDestination(Location destination) { 251 Location old = _destination; 252 _destination = destination; 253 firePropertyChange(DESTINATION_CHANGED_PROPERTY, old, destination); 254 } 255 256 public String getDestinationName() { 257 if (_destination != null) { 258 return _destination.getName(); 259 } 260 return NONE; 261 } 262 263 public String getDestinationId() { 264 if (_destination != null) { 265 return _destination.getId(); 266 } 267 return NONE; 268 } 269 270 public Track getDestinationTrack() { 271 return _trackDestination; 272 } 273 274 public void setDestinationTrack(Track track) { 275 Track old = _trackDestination; 276 _trackDestination = track; 277 firePropertyChange(DESTINATION_TRACK_CHANGED_PROPERTY, old, track); 278 } 279 280 public String getDestinationTrackName() { 281 if (_trackDestination != null) { 282 return _trackDestination.getName(); 283 } 284 return NONE; 285 } 286 287 public String getDestinationTrackId() { 288 if (_trackDestination != null) { 289 return _trackDestination.getId(); 290 } 291 return NONE; 292 } 293 294 public void setComment(String comment) { 295 _comment = comment; 296 } 297 298 public String getComment() { 299 return _comment; 300 } 301 302 public void copyScheduleItem(ScheduleItem si) { 303 setComment(si.getComment()); 304 setCount(si.getCount()); 305 setDestination(si.getDestination()); 306 setDestinationTrack(si.getDestinationTrack()); 307 setPickupTrainScheduleId(si.getPickupTrainScheduleId()); 308 setRandom(si.getRandom()); 309 setReceiveLoadName(si.getReceiveLoadName()); 310 setRoadName(si.getRoadName()); 311 setSetoutTrainScheduleId(si.getSetoutTrainScheduleId()); 312 setShipLoadName(si.getShipLoadName()); 313 setWait(si.getWait()); 314 } 315 316 public void dispose() { 317 firePropertyChange(DISPOSE, null, DISPOSE); 318 } 319 320 /** 321 * Construct this Entry from XML. This member has to remain synchronized 322 * with the detailed DTD in operations-config.xml 323 * 324 * @param e Consist XML element 325 */ 326 public ScheduleItem(org.jdom2.Element e) { 327 org.jdom2.Attribute a; 328 if ((a = e.getAttribute(Xml.ID)) != null) { 329 _id = a.getValue(); 330 } else { 331 log.warn("no id attribute in Schedule Item element when reading operations"); 332 } 333 if ((a = e.getAttribute(Xml.SEQUENCE_ID)) != null) { 334 _sequenceId = Integer.parseInt(a.getValue()); 335 } 336 if ((a = e.getAttribute(Xml.RANDOM)) != null) { 337 _random = a.getValue(); 338 } 339 if ((a = e.getAttribute(Xml.TRAIN_SCHEDULE_ID)) != null) { 340 _setoutTrainScheduleId = a.getValue(); 341 } 342 if ((a = e.getAttribute(Xml.PICKUP_TRAIN_SCHEDULE_ID)) != null) { 343 _pickupTrainScheduleId = a.getValue(); 344 } 345 if ((a = e.getAttribute(Xml.COUNT)) != null) { 346 _count = Integer.parseInt(a.getValue()); 347 } 348 if ((a = e.getAttribute(Xml.WAIT)) != null) { 349 _wait = Integer.parseInt(a.getValue()); 350 } 351 if ((a = e.getAttribute(Xml.TYPE)) != null) { 352 _type = a.getValue(); 353 } 354 if ((a = e.getAttribute(Xml.ROAD)) != null) { 355 _road = a.getValue(); 356 } 357 if ((a = e.getAttribute(Xml.LOAD)) != null) { 358 _load = a.getValue(); 359 } 360 if ((a = e.getAttribute(Xml.SHIP)) != null) { 361 _ship = a.getValue(); 362 } 363 if ((a = e.getAttribute(Xml.DESTINATION_ID)) != null) { 364 _destination = InstanceManager.getDefault(LocationManager.class).getLocationById(a.getValue()); 365 } 366 if ((a = e.getAttribute(Xml.DEST_TRACK_ID)) != null && _destination != null) { 367 _trackDestination = _destination.getTrackById(a.getValue()); 368 } 369 if ((a = e.getAttribute(Xml.COMMENT)) != null) { 370 _comment = a.getValue(); 371 } 372 if ((a = e.getAttribute(Xml.HITS)) != null) { 373 _hits = Integer.parseInt(a.getValue()); 374 } 375 } 376 377 /** 378 * Create an XML element to represent this Entry. This member has to remain 379 * synchronized with the detailed DTD in operations-config.xml. 380 * 381 * @return Contents in a JDOM Element 382 */ 383 public org.jdom2.Element store() { 384 org.jdom2.Element e = new org.jdom2.Element(Xml.ITEM); 385 e.setAttribute(Xml.ID, getId()); 386 e.setAttribute(Xml.SEQUENCE_ID, Integer.toString(getSequenceId())); 387 e.setAttribute(Xml.RANDOM, getRandom()); 388 e.setAttribute(Xml.TRAIN_SCHEDULE_ID, getSetoutTrainScheduleId()); 389 e.setAttribute(Xml.PICKUP_TRAIN_SCHEDULE_ID, getPickupTrainScheduleId()); 390 e.setAttribute(Xml.COUNT, Integer.toString(getCount())); 391 e.setAttribute(Xml.WAIT, Integer.toString(getWait())); 392 e.setAttribute(Xml.TYPE, getTypeName()); 393 e.setAttribute(Xml.ROAD, getRoadName()); 394 e.setAttribute(Xml.LOAD, getReceiveLoadName()); 395 e.setAttribute(Xml.SHIP, getShipLoadName()); 396 if (!getDestinationId().equals(NONE)) { 397 e.setAttribute(Xml.DESTINATION_ID, getDestinationId()); 398 } 399 if (!getDestinationTrackId().equals(NONE)) { 400 e.setAttribute(Xml.DEST_TRACK_ID, getDestinationTrackId()); 401 } 402 e.setAttribute(Xml.COMMENT, getComment()); 403 e.setAttribute(Xml.HITS, Integer.toString(getHits())); 404 return e; 405 } 406 407 private static final Logger log = LoggerFactory.getLogger(ScheduleItem.class); 408 409}