Repository navigation
Expand file tree
/
Copy pathStationMapper.cpp
More file actions
186 lines (162 loc) · 7.75 KB
/
Copy pathStationMapper.cpp
File metadata and controls
186 lines (162 loc) · 7.75 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
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
#include "StationMapper.hpp"
#include "Generic_connection_parser.hpp"
#include "Generic_station_parser.hpp"
#include "Generic_mapper.hpp"
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include <vector>
#include <limits>
#include <queue>
#include <cstring>
#include<algorithm>
#include <set>
using namespace std ;
void StationMapper::read_stations(const std::string& _filename) {
std::string line, word; // Strings to hold the current line and word.
std::ifstream file(_filename); // Open the file with the provided filename.
std::vector<std::string> row; // A vector to hold each word in a line.
int line_nbr = 0; // Line number tracker to skip the header line.
// Check if the file is successfully opened.
if (file.is_open()) {
// Read the file line by line.
while (getline(file, line)) {
row.clear(); // Clear the row vector for new line.
std::stringstream str(line); // Create a stringstream from the line.
// Split the line into words based on the comma delimiter.
while (getline(str, word, ',')) {
row.push_back(word); // Add each word to the row vector.
}
// Skip the first line assuming it's a header.
if (line_nbr != 0) {
try {
// Convert the second element (expected to be station ID) to integer
// and use it as the key to insert the station data into the map.
stations_hashmap[std::stoi(row[1])] = travel::Station{row[0], row[1], row[2], row[3]};
} catch (const std::invalid_argument& e) {
// Handle the exception if the conversion to integer fails.
std::cerr << "Invalid data in CSV: " << e.what() << std::endl;
}
}
line_nbr++; // Increment line number.
}
std::cout << "Reading Stations - Done" << std::endl;
} else {
// Throw an exception if the file could not be opened.
throw std::runtime_error("Error: Unable to open the CSV file.");
}
}
void StationMapper::read_connections(const std::string& _filename) {
std::string line, word ;
std::fstream file(_filename, ios::in); // Open the file for input.
std::vector<std::string> row;
int line_nbr = 0; // Line number tracker to skip the header.
// Check if the file is successfully opened.
if (file.is_open()) {
int tmp, same = 0;
std::unordered_map<uint64_t, uint64_t> umap; // Temporary map to store connections for a station.
std::set<uint64_t> seenStations;
// Read the file line by line.
while (getline(file, line)) {
row.clear(); // Clear the row vector for the new line.
std::stringstream str(line); // Create a stringstream from the line.
// Split the line into words based on the comma delimiter.
while (getline(str, word, ',')) { // like split on , in python
row.push_back(word); // Add each word to the row vector.
}
// Skip the first line assuming it's a header.
if (line_nbr != 0) {
uint64_t current_station = std::stoi(row[0]);
if (seenStations.find(current_station) == seenStations.end()) {
// If we're reading data for a new station, clear the temporary map.
umap.clear();
// Add the new station and its connections.
seenStations.insert(current_station);
}
// If we're still reading data for the same station, just add the new connection.
uint64_t connected_station = std::stoi(row[1]);
uint64_t connection_time = std::stoi(row[2]);
umap[connected_station] = connection_time;
// Always update or add the umap to the main connections hashmap
if (current_station != connected_station) {
connections_hashmap[current_station] = umap;
}}
line_nbr++; // Increment line number.
}
std::cout << "Reading Connections - Done" << std::endl;
} else {
// If the file couldn't be opened, throw a custom Error.
std::cerr<< "401, Error 401: Opening the CSV file is not possible" << std::endl;
}
}
void StationMapper::display_connections() {
std::cout << "\nAll Connection Elements:\n";
// Use a range-based for loop for better readability.
for (const auto& pair : connections_hashmap) {
std::cout << pair.first << " : ";
for (const auto& inner_pair : pair.second) {
std::cout << inner_pair.first << " (" << inner_pair.second << " sec) ";
}
std::cout << std::endl;
}
}
void StationMapper::display_stations() {
std::cout << "\nAll Station Elements:\n";
// Using a range-based for loop for iterating over stations_hashmap
for (const auto& pair : stations_hashmap) {
// Assuming 'Station' has members 'name', 'line_id', 'address', and 'line_name'.
// Access these members and print out the details.
const auto& station_id = pair.first;
const auto& station = pair.second;
std::cout << "Station ID: " << station_id
<< ", Name: " << station.name
<< ", Line ID: " << station.line_id
<< ", Address: " << station.address
<< ", Line Name: " << station.line_name
<< std::endl;
} }
std::vector<std::pair<uint64_t, uint64_t>> StationMapper::compute_travel(uint64_t start, uint64_t end) {
std::unordered_map<uint64_t, uint64_t> distances;
// This map keeps track of the path (how we reached each station).
std::unordered_map<uint64_t, uint64_t> previous;
// Initialize distances to maximum possible (infinite).
for (const auto& connection : connections_hashmap) {
distances[connection.first] = std::numeric_limits<uint64_t>::max();
}
distances[start] = 0; // Distance to start is zero.
// Priority queue to process nodes/stations, sorted by distance.
auto cmp = [&distances](uint64_t left, uint64_t right) { return distances[left] > distances[right]; };
std::priority_queue<uint64_t, std::vector<uint64_t>, decltype(cmp)> queue(cmp);
// Start with the start station.
queue.push(start);
while (!queue.empty()) {
uint64_t current = queue.top();
queue.pop();
// If we reached the end station, break out of the loop.
if (current == end) {
break;
}
// Process each connection from the current station.
for (const auto& neighbor : connections_hashmap[current]) {
uint64_t next = neighbor.first;
uint64_t time = neighbor.second;
// Calculate the distance to this neighbor via the current station.
uint64_t new_distance = distances[current] + time;
// If the calculated distance is less than the known distance, update and continue.
if (new_distance < distances[next]) {
distances[next] = new_distance;
previous[next] = current; // Record the path.
queue.push(next);
}
}
}
// Reconstruct the path from end to start using the previous map.
std::vector<std::pair<uint64_t, uint64_t>> path;
for (uint64_t at = end; at != start; at = previous[at]) {
path.push_back({at, distances[at]});
}
path.push_back({start, distances[start]});
std::reverse(path.begin(), path.end());
return path;
}