-
Notifications
You must be signed in to change notification settings - Fork 30
/
RouteTime.c
221 lines (201 loc) · 7.7 KB
/
RouteTime.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "timeHM.h"
#include "flights.h"
#define MAX_NAME_LEN 128
#define MAX_LINE_LEN 256
extern int GlobalCountFlight;
extern int CountOfFreeFlight;
void stripNewLine(char* line) {
if(line[strlen(line)-1] == '\n') {
line[strlen(line)-1] = '\0';
}
}
void printCompleteRoute(char* route, timeHM_t* end, int cost) {
printf("Route %s will be completed by ",route);
printTime(end);
printf(" and costs $%d\n", cost);
}
/*
Given a file with routes and a flight system, parses the file and determine (and print) the earliest time each route can be completed.
Lines of bad form are skipped while new lines are ignored.
*/
void calcRouteTimes(flightSys_t* s, FILE* routes) {
char* newRoutePrefix = "ROUTE: ";
size_t prefixLen = strlen(newRoutePrefix);
char line[MAX_LINE_LEN];
timeHM_t now;
char route[MAX_LINE_LEN];
char timeBuf[MAX_LINE_LEN];
char airportBuf[MAX_LINE_LEN];
airport_t* curAirport = NULL;
int curCost = 0;
int totalCost = 0;
/*
This while loop parses the file line by line and calculate the route times as it goes.
If a new route line is found, the current route (if it exists) would be done and the result is printed.
A current route exists if curAirport is not null.
curAirport tells us where we are on the current route.
now tells us the current time (the earliest time we can reach the curAirport on the current route).
*/
while(fgets(line, MAX_LINE_LEN,routes)) {
stripNewLine(line);
if(!strlen(line)) continue; //ignore line if it's empty
else if(strncmp(line,newRoutePrefix,prefixLen) == 0) { //if beginning of line starts with "ROUTE: ", we are calculating for a new route
if(curAirport) printCompleteRoute(route,&now, totalCost); //if curAirport is not NULL, we are done with the previous route so print the result
curAirport = NULL;
totalCost = 0;
if(3!=sscanf(line+prefixLen,"%s %s %s",route,airportBuf,timeBuf) //parse rest of new route line into route name, airport name, and start time
|| !stringToTime(timeBuf,&now) //ensure time is valid
|| !(curAirport = getAirport(s,airportBuf))) { //ensure airport exists and sets curAirport to the starting airport
printf("Skipping line: %s\n",line);
continue;
}
} else if (curAirport) {
/*
This is the case when we are in the middle of calculating for a route,
and the line should just be next airport we have to get to.
Here, we use getNextFlight to determine the flight to take to the next airport.
If there are no possible flights, the route cannot be completed.
*/
airport_t* next = getAirport(s,line);
if(!next) {
printf("Skipping line: %s\n",line);
continue;
}
timeHM_t depart;
timeHM_t arrival;
if(!getNextFlight(curAirport,next,&now,&depart,&arrival,&curCost)) {
curAirport = NULL;
totalCost = 0;
printf("Route %s cannot be completed\n",route);
continue;
}
now = arrival;
curAirport = next;
totalCost += curCost;
}
}
if(curAirport) printCompleteRoute(route,&now,totalCost);
}
/*
Given a flight system and a file of airport names, each on a line,
add the airports to the flight system.
*/
void parseAirports(flightSys_t* s, FILE* airportFile) {
char name[MAX_NAME_LEN];
while(fgets(name, MAX_NAME_LEN, airportFile)) {
stripNewLine(name);
addAirport(s,name);
}
}
/*
Given a flight system with airports, and a file of schedules for those airports,
add flight times to the system.
*/
void parseSchedule(flightSys_t* s, FILE* schedule) {
char* newAirportPrefix = "AIRPORT: ";
size_t prefixLen = strlen(newAirportPrefix);
airport_t* curAirport = NULL;
/*
curAirport is the airport we are currently adding a schedule for.
In other words, it is the source airport.
The while loop parses the file line by line and sets a new curAirport when a line that starts with "STATION: " is found.
It'll also echo the schedule of the previous airport.
Otherwise, it treats the current line as a new entry in the schedule of the curAirport and calls addFlight.
*/
char line[MAX_LINE_LEN];
while(fgets(line, MAX_LINE_LEN, schedule)) {
if(!strcmp(line,"\n")) continue;
else if(strncmp(line,newAirportPrefix,prefixLen) == 0){
if(curAirport) printSchedule(curAirport); //done with previous schedule so print it
stripNewLine(line);
char* srcName = line+prefixLen;
curAirport = getAirport(s,srcName);
if(curAirport)
printf("Adding schedule for airport %s\n",srcName);
else
printf("Cannot find airport %s\n",srcName);
} else if (curAirport) {
char dstName[MAX_LINE_LEN];
char departureStr[MAX_LINE_LEN];
char arrivalStr[MAX_LINE_LEN];
char priceStr[MAX_LINE_LEN];
if(4!=sscanf(line,"%s %s %s $%s",dstName,departureStr,arrivalStr, priceStr)) { //parses the line as destination airport name, departure time, arrival time, and price
printf("Skipping line: %s\n",line);
continue;
}
airport_t* dst = getAirport(s,dstName);
if(dst==NULL) {
printf("Cannot find airport %s\n",dstName);
continue;
}
timeHM_t arrival;
timeHM_t departure;
int cost;
char* endptr;
cost = (int) strtol(priceStr,&endptr,10);
if(!stringToTime(arrivalStr, &arrival) || !stringToTime(departureStr, &departure) || *endptr) {
printf("Skipping line: %s\n",line);
continue;
}
addFlight(curAirport,dst,&departure,&arrival, cost);
}
}
if(curAirport) printSchedule(curAirport);
}
/*
Calls parseAirports, parseSchedules, and calcRouteTimes if the required files exists.
*/
void timeRoutes(char* airports, char* schedules, char* routes) {
FILE *airportFile, *scheduleFile, *routeFile;
char* read = "r";
airportFile = fopen(airports,read);
if(!airportFile) {
fprintf(stderr,"Cannot open file with list of airport names.");
exit(EXIT_FAILURE);
}
flightSys_t* s = createSystem();
if(s==NULL) {
printf("createSystem unimplemented\n");
return;
}
printf("***Parse and echo airports***\n");
parseAirports(s,airportFile);
fclose(airportFile);
printAirports(s);
scheduleFile = fopen(schedules,read);
if(!scheduleFile) {
fprintf(stderr,"Cannot open file with schedule.");
exit(EXIT_FAILURE);
}
printf("\n***Parse and echo schedules***\n");
parseSchedule(s,scheduleFile);
fclose(scheduleFile);
routeFile = fopen(routes,read);
if(!routeFile) {
fprintf(stderr,"Cannot open file with routes.");
exit(EXIT_FAILURE);
}
printf("\n***Parse and calculate route times***\n");
calcRouteTimes(s,routeFile);
fclose(routeFile);
deleteSystem(s);
}
int main(int argc, char* args[]) {
if(argc != 4) {
printf("Usage: <file of airport names> <file of schedules> <file of routes>\n");
printf("Given flight schedules and a route with a starting time, this program will determine when the route will be completed.\n");
printf("\t<file of airport names> should contain a list of airport names, one on each line.\n");
printf("\t<file of schedules> should contain a list of schedules. \n");
printf("\t\t\"AIRPORT: <airport name>\" marks the beginning of a schedule for that airport.\n");
printf("\t\tSubsequent lines contain the destination airport, departure time, and arrival time separated by spaces\n");
printf("\t<file of routes> should contain a list of routes. \n");
printf("\t\t\"ROUTE: <route name> <starting airport> <begin time>\" marks the beginning of a plan starting at the specified airport and time.\n");
printf("\t\tSubsequent lines contain the airports in the route, one on each line, in order\n");
return 0;
}
timeRoutes(args[1],args[2],args[3]);
return 0;
}