1 module cif.basicschedule;
2 
3 import std.conv : to;
4 import std.datetime.date : Date, DayOfWeek;
5 import std.string : strip;
6 
7 import cif.types : TransactionType;
8 import cif.utils : daysRunning, twoToFourYear;
9 
10 struct BasicSchedule
11 {
12     TransactionType transactionType;
13     string trainUid;
14     Date start;
15     Date end;
16     DayOfWeek[] days;
17     char bankHolidayRunning;
18     char status;
19     string category;
20     string identity;
21     string headcode;
22     char courseIndicator;
23     string serviceCode;
24     char portionId;
25     string powerType;
26     string timingLoad;
27     int speed;
28     string operatingCharacteristics;
29     char seatingClass;
30     char sleepers;
31     char reservations;
32     char connectionIndicator;
33     string cateringCode;
34     string serviceBranding;
35     char stpIndicator;
36 
37     this(string record)
38     {
39         this.transactionType = to!TransactionType(record[2]);
40         this.trainUid = record[3 .. 9];
41         this.start = Date(twoToFourYear(to!int(record[9 .. 11])),
42                 to!int(record[11 .. 13]), to!int(record[13 .. 15]));
43         this.end = Date(twoToFourYear(to!int(record[15 .. 17])),
44                 to!int(record[17 .. 19]), to!int(record[19 .. 21]));
45         this.days = daysRunning(record[21 .. 28]);
46         this.bankHolidayRunning = record[28];
47         this.status = record[29];
48         this.category = record[30 .. 32];
49         this.identity = record[32 .. 36];
50         this.headcode = strip(record[36 .. 40]);
51         this.courseIndicator = record[40];
52         this.serviceCode = record[41 .. 49];
53         this.portionId = record[49];
54         this.powerType = record[50 .. 53];
55         this.timingLoad = strip(record[53 .. 57]);
56 
57         if (record[57] != ' ')
58         {
59             this.speed = to!int(record[57 .. 60]);
60         }
61 
62         this.operatingCharacteristics = record[60 .. 66];
63         this.seatingClass = record[66];
64         this.sleepers = record[67];
65         this.reservations = record[68];
66         this.connectionIndicator = record[69];
67         this.cateringCode = strip(record[70 .. 74]);
68         this.serviceBranding = strip(record[74 .. 78]);
69         this.stpIndicator = record[79];
70     }
71 
72     unittest
73     {
74         auto line = "BSNP642691712111805181111100 PXX1N865032122209000 EMU350 100      B S          P";
75         const BasicSchedule basicSchedule = BasicSchedule(line);
76 
77         assert(basicSchedule.transactionType == TransactionType.new_);
78         assert(basicSchedule.trainUid == "P64269");
79         assert(basicSchedule.start == Date(2017, 12, 11));
80         assert(basicSchedule.end == Date(2018, 5, 18));
81         assert(basicSchedule.days == [DayOfWeek.mon, DayOfWeek.tue,
82                 DayOfWeek.wed, DayOfWeek.thu, DayOfWeek.fri]);
83         assert(basicSchedule.bankHolidayRunning == ' ');
84         assert(basicSchedule.status == 'P');
85         assert(basicSchedule.category == "XX");
86         assert(basicSchedule.identity == "1N86");
87         assert(basicSchedule.headcode == "5032");
88         assert(basicSchedule.courseIndicator == '1');
89         assert(basicSchedule.serviceCode == "22209000");
90         assert(basicSchedule.portionId == ' ');
91         assert(basicSchedule.powerType == "EMU");
92         assert(basicSchedule.timingLoad == "350");
93         assert(basicSchedule.speed == 100);
94         assert(basicSchedule.operatingCharacteristics == "      ");
95         assert(basicSchedule.seatingClass == 'B');
96         assert(basicSchedule.sleepers == ' ');
97         assert(basicSchedule.reservations == 'S');
98         assert(basicSchedule.connectionIndicator == ' ');
99         assert(basicSchedule.cateringCode == "");
100         assert(basicSchedule.serviceBranding == "");
101         assert(basicSchedule.stpIndicator == 'P');
102     }
103 }
104 
105 struct BasicScheduleExtra
106 {
107     string tractionClass;
108     string uicClass;
109     string atocCode;
110     char applicableTimetableCode;
111     string reservationSystemId;
112     char dataSource;
113 
114     this(string record)
115     {
116         this.tractionClass = strip(record[2 .. 6]);
117         this.uicClass = strip(record[6 .. 11]);
118         this.atocCode = record[11 .. 13];
119         this.applicableTimetableCode = record[13];
120         this.reservationSystemId = record[14 .. 22];
121         this.dataSource = record[22];
122     }
123 
124     unittest
125     {
126         auto record = "BX         LMYLM503200                                                          ";
127         const BasicScheduleExtra extra = BasicScheduleExtra(record);
128 
129         assert(extra.tractionClass == "");
130         assert(extra.uicClass == "");
131         assert(extra.atocCode == "LM");
132         assert(extra.applicableTimetableCode == 'Y');
133         assert(extra.reservationSystemId == "LM503200");
134         assert(extra.dataSource == ' ');
135     }
136 }