-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathBusScheduler.cpp
More file actions
151 lines (136 loc) · 5.62 KB
/
BusScheduler.cpp
File metadata and controls
151 lines (136 loc) · 5.62 KB
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
#include "BusScheduler.h"
#include "common.h"
#include "DataLoader.h"
#include <iostream>
#include <map>
#include <vector>
#include <iomanip>
#include <stdexcept>
BusScheduler::BusScheduler(RouteGraph *graph)
{
// Store a pointer to the graph to get travel times
this->routeGraph = graph;
}
// Adds a single scheduled bus departure to the system.
void BusScheduler::addScheduledBus(string busNum, string startStop, int depTime)
{
string normStop = normalizeString(startStop);
// Add to the priority queue for that specific stop
allSchedules[normStop].push({busNum, normStop, depTime});
}
// Takes an "optimal" path (from RouteGraph) and a user's start time,
// and calculates the "actual" journey, including wait times and fare.
JourneyPlan BusScheduler::findJourney(RoutePlan &plan, int userStartTime)
{
JourneyPlan journey;
int currentTime = userStartTime; // acts as the clock
journey.totalFare = 0.0;
// Go through the optimal path step-by-step
for (const auto &step : plan.steps)
{
// 1. Find the next bus for this leg
ScheduledBus nextBus = findNextAvailableBus(step.busNumber, step.startStop, currentTime);
// 2. Check if a bus was found
if (nextBus.departureTime == -1)
{
cout << "\nError: No available bus found for the leg: "
<< step.startStop << " to " << step.endStop
<< " (Bus " << step.busNumber << ") at or after "
<< minutesToTime(currentTime) << "." << endl;
journey.finalArrivalTime = -1; // Mark journey as invalid
return journey;
}
// 3. A bus was found! Update our journey
JourneyStep journeyStep;
journeyStep.startStop = step.startStop;
journeyStep.endStop = step.endStop;
journeyStep.busNumber = step.busNumber;
journeyStep.departureTime = nextBus.departureTime;
journeyStep.arrivalTime = nextBus.departureTime + step.time;
journeyStep.waitTime = nextBus.departureTime - currentTime;
journeyStep.travelTime = step.time;
journey.steps.push_back(journeyStep);
// 4. Update our "clock" for the next leg
currentTime = journeyStep.arrivalTime;
// 5. Update total times
journey.totalTravelTime += step.time;
journey.totalWaitTime += journeyStep.waitTime;
// 6. Calculate Fare
try
{
// Get the normalized bus number (e.g., "21g")
string normBus = normalizeString(step.busNumber);
// Get the fare rate from the static map
double rate = DataLoader::busFareRates.at(normBus);
double stepFare = journeyStep.travelTime * rate;
journey.totalFare += stepFare;
}
catch (const out_of_range &e)
{
cout << "Warning: No fare rate found for bus " << step.busNumber
<< ". Using default rate of 1.5." << endl;
journey.totalFare += (journeyStep.travelTime * 1.5); // Default rate
}
}
journey.finalArrivalTime = currentTime;
return journey;
}
// Prints a formatted journey plan to the console, including fare.
void BusScheduler::printJourneyPlan(JourneyPlan &plan)
{
if (plan.finalArrivalTime == -1)
{
// findJourney function prints the error
return;
}
cout << fixed << setprecision(2);
cout << "\n--- Your Journey Plan ---" << endl;
for (const auto &step : plan.steps)
{
cout << "\n [STEP]: " << step.startStop << " to " << step.endStop << endl;
cout << " > Take Bus: " << step.busNumber << endl;
if (step.waitTime > 0)
{
cout << " > Wait Time: " << step.waitTime << " minutes" << endl;
}
cout << " > Depart at: " << minutesToTime(step.departureTime) << endl;
cout << " > Arrive at: " << minutesToTime(step.arrivalTime) << endl;
cout << " (Travel time for this leg: " << step.travelTime << " min)" << endl;
}
cout << "\n--- Summary ---" << endl;
cout << "Final Destination Reached at: " << minutesToTime(plan.finalArrivalTime) << endl;
cout << "Total Time on Bus: " << plan.totalTravelTime << " minutes" << endl;
cout << "Total Time Waiting: " << plan.totalWaitTime << " minutes" << endl;
cout << "Total Journey Time: " << (plan.totalTravelTime + plan.totalWaitTime) << " minutes" << endl;
cout << "Estimated Total Fare: Rs. " << plan.totalFare << endl;
cout << "-------------------------" << endl;
cout.unsetf(ios_base::floatfield);
}
// Finds the earliest bus for a specific route leg that departs
ScheduledBus BusScheduler::findNextAvailableBus(string busNum, string stop, int afterTime)
{
string normStop = normalizeString(stop);
string normBus = normalizeString(busNum);
// 1. Check if this stop exists in our schedule map
if (allSchedules.find(normStop) == allSchedules.end())
{
return {"", "", -1}; // No buses ever from this stop
}
// 2. Get the priority queue for this stop
// make a copy so we can search without removing buses from the real schedule
priority_queue<ScheduledBus, vector<ScheduledBus>, greater<ScheduledBus>> tempQueue = allSchedules[normStop];
// 3. Search the queue
while (!tempQueue.empty())
{
ScheduledBus bus = tempQueue.top();
tempQueue.pop(); // Check the next bus
// Check 1: Does the bus number match?
// Check 2: Does it depart at or after the time we need?
if (normalizeString(bus.busNumber) == normBus && bus.departureTime >= afterTime)
{
return bus; // best bus found.
}
}
// 4. No bus found
return {"", "", -1};
}