populating train schedule

Populating the train schedule and directions

Once the Station list has been fed into the database, along with the associated properties (next and previous), the Trains can be added to the database as well. The Timing objects for each station can be created automatically once a train has been added. The concept of up/down as directions amongst trains is a trivial, but useful one.

While adding the train, it's timing, train_no, initial station and destination will be the inputs. The ID will be assigned automatically by the system since we have no need to set it explicitly.

post_save for Train:
  if train.initial_station.id > train.destination.id:
  # direction is UP lonavala to pune
    add_up_train(train)
  else:
  # direction is DOWN: pune to lonavala
    add_down_train(train)

  add_up_train:
    station_list = [
      stations where 
      id<=train.initial_station.id 
      and id>=train.destination ]
    ( order in descending order )
    time = train.time 
    # start time
    for station in station_list:
      timing.train = train
      timing.station = station
      timing.time = time
     time = time + station.time_to_next

  add_down_train:
    station_list = [ 
      stations where id<=train.destination
      and id>=train.initial_station ]
      ( order in ascending order )
      time = train.time # start time
      for station in station_list:
        timing = Timing()
        timing.train = train
        timing.station = station
        timing.time = time
        timing.save()
        time = time + station.time_to_prev

This will populate the train timings based on the train (up/down). It can be further refactored using abstraction for getting the station list and calculating the time between stops. For example, lambdas can be used and passed to a generic add_train function:

add_train(train):
  if train.initial_station.id > train.destination.id:
  # UP
    top = train.initial_station.id
    bottom = train.destination.id
    ordering = descending
    stop = lambda station: station.time_to_next
  else:
  # DOWN
    top = train.destination.id
    bottom = train.initial_station.id
    ordering = ascending
    stop = lambda station: station.time_to_prev
    station_list = [
      stations where id<=top
      and id>=bottom ]
      ( order by ordering )
    time = train.time
    for station in station_list:
        timing.train = train
        timing.station = station
        timing.time = time
        timing.save()
        time = time + stop(station)

This results in roughly the same code, but saves duplication where unnecessary. If the train is being modified, then instead of modifying all the timings, it is easier to delete them all and repopulate the timing table with the new entries.

add_train(train):
  if train in [ 
    select train in timings ]
  ( group by train )
  # train already has timings, so let's remove them first
  delete all timings
    where train=train
  # ... rest of the code remains the same