Trains

Active timetable for London to Liverpool trains

Introduction

This novel, effective program reports on the scheduled progress of currently running weekday trains from London Euston to Liverpool Lime Street. Peter uses string manipulation extensively for reading the timetable and in time conversion functions. (There are inbuilt date and time conversion routines such as DecodeTime which you could consider as alternatives to string manipulation if you are planning to write code to process times).

This program uses the CRT unit and will run in Lazarus. In order to run it in Delphi, you will need to download and include CRT files as described in the last section of our Graphics tutorial.

A typical screenshot from the running program is shown below.

Screenshot showing details for two trains on route from Euston to Liverpool Lime Street

The Program

program Trains;
{
    Copyright (c) 2010 Peter Hearnshaw
    
    Licensed under the Apache License, Version 2.0 (the "License"); you may not 
    use this file except in compliance with the License, as described at
    http://www.apache.org/licenses/ and http://www.pp4s.co.uk/licenses/
}
uses
  sysUtils, Crt;
var
  tt : array [1..18, 1..10] of string = (
  ('0527', '0545', '0610', '', '0703', '', '', '0724', '0742', '0801'),
  ('0707', '', '', '', '0823', '', '', '', '0855', '0915'),
  ('0807', '', '', '', '0923', '', '', '', '0955', '1015'),
  ('0907', '', '', '', '1023', '', '', '', '1055', '1115'),
  ('1007', '', '', '', '1123', '', '', '', '1155', '1215'),
  ('1107', '', '', '', '1223', '', '', '', '1255', '1315'),
  ('1207', '', '', '', '1323', '', '', '', '1355', '1415'),
  ('1307', '', '', '', '1423', '', '', '', '1455', '1515'),
  ('1407', '', '', '', '1523', '', '', '', '1555', '1615'),
  ('1507', '', '', '', '1623', '', '', '', '1655', '1715'),
  ('1607', '', '', '', '1723', '', '', '', '1755', '1815'),
  ('1707', '', '', '', '1825', '', '', '1845', '1902', '1923'),
  ('1733', '', '', '1823', '1856', '', '', '1917', '1934', '1952'),
  ('1807', '', '', '', '1924', '', '', '1944', '2001', '2021'),
  ('1833', '', '', '1923', '1956', '', '', '2017', '2034', '2053'),
  ('1907', '', '', '', '2027', '', '', '', '2101', '2121'),
  ('2007', '', '', '', '2127', '', '', '', '2159', '2221'),
  ('2107', '', '2138', '', '', '', '', '2248', '2307', '2331'));

  stationNames : array [1..10] of string = ('London Euston','Watford Junction','Milton Keynes Central',
          'Rugby','Stafford','Stoke on Trent','Macclesfield','Crewe','Runcorn','Liverpool Lime Street');

  i, ii, TThours, TTminutes, RTseconds, OThrs, OTmins, OTsecs, prevStation, nextStation : integer;
  RTtimenow : TDateTime;
  RTStrtime, RThrsStr, RTminsStr, RTsecsStr, progressStr : string;

function timeConvert (TTtime : string) : integer;
begin
  //converts hhmm into seconds since 12 midnight
  TThours := strtoint(LeftStr(TTtime, 2));
  TTminutes := strtoint(RightStr(TTtime, 2));
  TThours := TThours * 60;
  result := (TThours+TTminutes)*60;
end;

function timeReverseConvert (OTlongSecs : integer) : string;
begin
  //converts seconds since 12 midnight into hours, minutes and seconds
  OThrs := OTlongSecs div 3600;
  OTlongSecs := OTlongSecs mod 3600;
  OTmins := OTlongSecs div 60;
  OTlongSecs := OTlongSecs mod 60;
  OTsecs := OTlongSecs;
  result := inttostr(OThrs) + ' hours ' + inttostr(OTmins) + ' minutes ' + inttostr(OTsecs) + ' seconds';
end;

begin
  repeat
    sleep (1000);
    clrscr;
    writeln('This program will get the current time and look at the timetable and find');
    writeln('trains which are currently running. This timetable is for Virgin trains from');
    writeln('London Euston to Liverpool Lime Street on Mon-Fri only.');
    writeln('');
    //FINDING THE CURRENT TIME
    RTtimenow:= Now;
    RTStrtime := StringReplace(timetostr(RTtimenow), ':', '',[rfReplaceAll, rfIgnoreCase]);
    RThrsStr := LeftStr (RTStrtime, 2);
    delete (RTStrTime, 1,2);
    RTminsStr := LeftStr (RTStrtime, 2);
    delete (RTStrTime, 1,2);
    RTsecsStr := LeftStr (RTStrtime, 2);
    RTseconds := strtoint(RThrsStr)*60*60 + strtoint(RTminsStr)*60 + strtoint(RTsecsStr);
    //RTseconds IS NOW THE REAL TIME IN SECONDS

    //Go through each train
    for i :=1 to 18 do
      begin
        if(timeConvert(tt[i][10])>RTseconds) and (timeConvert(tt[i][1])<RTseconds)then
          begin
            writeln('Train Departed: Euston Junction at       ',tt[i][1]);
            writeln('       Arrival: Liverpool Lime Street at ',tt[i][10]);
            writeln('       Duration: ',timeReverseConvert(timeConvert(tt[i][10])-timeConvert(tt[i][1])));
            writeln('       Journey Time Left: ', timeReverseConvert(timeConvert(tt[i][10])-RTseconds));
            progressStr := floattostr(( 1- (timeConvert(tt[i][10])-RTseconds) / (timeConvert(tt[i][10])-timeConvert(tt[i][1])) )*100);
            delete (progressStr, 7,10);//shortens the number of decimal places
            writeln('       Progress of Journey: ', progressStr, '%');
            for ii:=1 to 10 do
              begin
                if(tt[i][ii] <> '') then
                  begin
                    if(timeConvert(tt[i][ii])<RTseconds)then //if the train has already passed through station number ii
                      begin
                        prevStation := ii;
                      end;

                  end;
               end;
            nextStation := 0;
            ii := prevStation;
            while nextStation = 0 do
              begin
                inc(ii);
                if(tt[i][ii] <> '') then
                  begin
                    nextStation := ii;
                  end;
                end;
            writeln('       Previous Station: ', stationNames[prevStation]);
            writeln('       Next Station: ', stationNames[nextStation], ' due in ', timeReverseConvert(timeConvert(tt[i][nextStation])-RTseconds));
            for ii:=1 to 10 do
              begin
                if(tt[i][ii] <> '') then
                  begin
                    if((timeConvert(tt[i][ii])<RTseconds+10) and (timeConvert(tt[i][ii])>RTseconds))then
                      begin
                        writeln();
                        writeln('       TRAIN STOPPING. NOW ARRIVING AT ', uppercase(stationNames[nextStation]));
                        writeln();
                      end;
                  end;
              end;
            writeln();
          end;
      end;
  until 1=2;
end.

Remarks

Can you think of a program like this that you could write?

Programming - a skill for life!

Fourteen programs (with five web versions) including 3D-Driving, GASP and Knowledge by Peter Hearnshaw