From 2dd63d53cebf699b74cfd7768ce1dc5520e366bc Mon Sep 17 00:00:00 2001 From: Process-ing Date: Wed, 27 Dec 2023 17:31:09 +0000 Subject: [PATCH 1/4] Implement getBestFlightPath --- include/Dataset.h | 4 +++ include/Flight.h | 4 +-- include/Graph.h | 13 ++++++++++ src/Dataset.cpp | 66 ++++++++++++++++++++++++++++++++++++++++++++++- src/Flight.cpp | 18 ++----------- test/tests.cpp | 15 +++++++++++ 6 files changed, 100 insertions(+), 20 deletions(-) diff --git a/include/Dataset.h b/include/Dataset.h index d5bbd42..dcefe37 100644 --- a/include/Dataset.h +++ b/include/Dataset.h @@ -36,6 +36,8 @@ class Dataset { AirportRef getAirport(const std::string& code) const; AirlineRef getAirline(const std::string& code) const; + std::vector getBestFlightPath(const AirportRef &src, const AirportRef &dest, double& distance) const; + private: CountrySet countrySet_; CitySet citySet_; @@ -44,6 +46,8 @@ class Dataset { CityRef getOrInsertCity(const std::string& name, const std::string& country); CountryRef getOrInsertCountry(const std::string& name); + + static double calculateDistance(double lat1, double lon1, double lat2, double lon2); }; diff --git a/include/Flight.h b/include/Flight.h index 2754bad..1edc628 100644 --- a/include/Flight.h +++ b/include/Flight.h @@ -16,7 +16,7 @@ class AirportInfo; class FlightInfo { public: - explicit FlightInfo(AirlineRef airline, const AirportInfo& src, const AirportInfo& dest); + explicit FlightInfo(AirlineRef airline, double distance); const AirlineRef &getAirline() const; double getDistance() const; @@ -24,8 +24,6 @@ class FlightInfo { private: AirlineRef airline_; double distance_; - - static double calculateDistance(const AirportInfo& src, const AirportInfo& dest); }; typedef Edge Flight; diff --git a/include/Graph.h b/include/Graph.h index 865033e..5e2f436 100644 --- a/include/Graph.h +++ b/include/Graph.h @@ -44,6 +44,8 @@ class Vertex { void setNum(int num); int getLow() const; void setLow(int low); + VertexRef getParent(); + void setParent(VertexRef parent); const std::vector> &getAdj() const; void addEdge(VertexRef dest, const EdgeInfo &info); @@ -55,6 +57,7 @@ class Vertex { int indegree_; int num_; int low_; + VertexRef parent_; }; @@ -168,6 +171,16 @@ void Vertex::setLow(int low) { low_ = low; } +template +VertexRef Vertex::getParent() { + return parent_; +} + +template +void Vertex::setParent(VertexRef parent) { + parent_ = parent; +} + template const std::vector> &Vertex::getAdj() const { return adj_; diff --git a/src/Dataset.cpp b/src/Dataset.cpp index 624ec0d..df403ed 100644 --- a/src/Dataset.cpp +++ b/src/Dataset.cpp @@ -1,6 +1,8 @@ #include #include #include +#include +#include #include "Dataset.h" using namespace std; @@ -80,7 +82,9 @@ void Dataset::readFlights() { AirportInfo sourceAirport = getAirport(source).lock()->getInfo(); AirportInfo targetAirport = getAirport(target).lock()->getInfo(); AirlineRef airline = getAirline(airlineCode); - FlightInfo flightInfo(airline, sourceAirport, targetAirport); + double distance = calculateDistance(sourceAirport.getLatitude(), sourceAirport.getLongitude(), + targetAirport.getLatitude(), targetAirport.getLongitude()); + FlightInfo flightInfo(airline, distance); network_.addEdge(sourceAirport, targetAirport, flightInfo); } } @@ -142,3 +146,63 @@ const CitySet &Dataset::getCities() const { const AirportSet &Dataset::getAirports() const { return network_.getVertexSet(); } + +std::vector Dataset::getBestFlightPath(const AirportRef& src, const AirportRef& dest, double &distance) const { + for (AirportRef airport: network_.getVertexSet()) { + airport.lock()->setVisited(false); + airport.lock()->setParent(AirportRef()); + } + queue airportQueue; + airportQueue.push(src); + src.lock()->setVisited(true); + while (!airportQueue.empty()) { + AirportRef parent = airportQueue.front(); + airportQueue.pop(); + if (parent.lock()->getInfo().getCode() == dest.lock()->getInfo().getCode()) + break; + + for (const Flight& flight: parent.lock()->getAdj()) { + AirportRef child = flight.getDest(); + if (!child.lock()->isVisited()) { + airportQueue.push(child); + child.lock()->setVisited(true); + child.lock()->setParent(parent); + } + } + } + + if (!dest.lock()->isVisited()) + return {}; + + vector airports; + airports.push_back(dest); + AirportRef curr = dest; + distance = 0; + while (curr.lock()->getInfo().getCode() != src.lock()->getInfo().getCode()) { + AirportRef next = curr.lock()->getParent(); + distance += calculateDistance( + curr.lock()->getInfo().getLatitude(), + curr.lock()->getInfo().getLongitude(), + next.lock()->getInfo().getLatitude(), + next.lock()->getInfo().getLongitude() + ); + curr = next; + airports.push_back(curr); + } + reverse(airports.begin(), airports.end()); + return airports; +} + +double hav(double x) { + double sinVal = sin(x / 2); + return sinVal * sinVal; +} + +double Dataset::calculateDistance(double lat1, double lon1, double lat2, double lon2) { + static const double EARTH_DIAMETER = 12742.0; + static const double DEG_TO_RAD_FACTOR = M_PI / 180.0; + double latRad1 = lat1 * DEG_TO_RAD_FACTOR, lonRad1 = lon1 * DEG_TO_RAD_FACTOR, + latRad2 = lat2 * DEG_TO_RAD_FACTOR, lonRad2 = lon2 * DEG_TO_RAD_FACTOR; + + return EARTH_DIAMETER * asin(hav(latRad2 - latRad1) + cos(latRad1) * cos(latRad2) * hav(lonRad2 - lonRad1)); +} diff --git a/src/Flight.cpp b/src/Flight.cpp index 6d85ad4..666037a 100644 --- a/src/Flight.cpp +++ b/src/Flight.cpp @@ -2,8 +2,8 @@ #include #include "Flight.h" -FlightInfo::FlightInfo(AirlineRef airline, const AirportInfo& src, const AirportInfo& dest) - : airline_(std::move(airline)), distance_(calculateDistance(src, dest)) {} +FlightInfo::FlightInfo(AirlineRef airline, double distance) + : airline_(std::move(airline)), distance_(distance) {} const AirlineRef &FlightInfo::getAirline() const { return airline_; @@ -12,17 +12,3 @@ const AirlineRef &FlightInfo::getAirline() const { double FlightInfo::getDistance() const { return distance_; } - -double hav(double x) { - double sinVal = sin(x / 2); - return sinVal * sinVal; -} - -double FlightInfo::calculateDistance(const AirportInfo &src, const AirportInfo &dest) { - static const double EARTH_DIAMETER = 12742.0; - static const double DEG_TO_RAD_FACTOR = M_PI / 180.0; - double lat1 = src.getLatitude() * DEG_TO_RAD_FACTOR, lat2 = dest.getLatitude() * DEG_TO_RAD_FACTOR, - lon1 = src.getLongitude() * DEG_TO_RAD_FACTOR, lon2 = dest.getLongitude() * DEG_TO_RAD_FACTOR; - - return EARTH_DIAMETER * asin(hav(lat2 - lat1) + cos(lat1) * cos(lat2) * hav(lon2 - lon1)); -} diff --git a/test/tests.cpp b/test/tests.cpp index 5ee1dac..4829740 100644 --- a/test/tests.cpp +++ b/test/tests.cpp @@ -65,3 +65,18 @@ TEST(FileParseTestSuite, ReadFilesTest) { EXPECT_EQ("LAS", SCKAirport.lock()->getAdj()[0].getDest().lock()->getInfo().getCode()); EXPECT_EQ(1, SCKAirport.lock()->getIndegree()); } + +TEST(BestFlightTestSuite, GetBestFlightPathTest) { + Dataset dataset; + dataset.readFiles(); + + AirportRef JFK = dataset.getAirport("JFK"); + AirportRef CDG = dataset.getAirport("CDG"); + ASSERT_FALSE(JFK.expired()); + ASSERT_FALSE(CDG.expired()); + double distance; + vector airports = dataset.getBestFlightPath(JFK, CDG, distance); + ASSERT_EQ(2, airports.size()); + EXPECT_EQ(JFK.lock(), airports[0].lock()); + EXPECT_EQ(CDG.lock(), airports[1].lock()); +} From 48fe3c0f4ddeddfd641af56a999aa723ab52be06 Mon Sep 17 00:00:00 2001 From: Process-ing Date: Thu, 28 Dec 2023 10:16:18 +0000 Subject: [PATCH 2/4] Display best flights --- include/Program.h | 2 + src/Flight.cpp | 1 - src/Program.cpp | 101 +++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 102 insertions(+), 2 deletions(-) diff --git a/include/Program.h b/include/Program.h index 3094758..cf84ae1 100644 --- a/include/Program.h +++ b/include/Program.h @@ -19,6 +19,8 @@ class Program { Dataset dataset_; void displayMainMenu(); + void chooseBestFlight(); + static void displayBestFlight(const std::vector &airports, double distance); static int receiveOption(int max); CountryRef receiveCountry() const; diff --git a/src/Flight.cpp b/src/Flight.cpp index 666037a..4b98d6a 100644 --- a/src/Flight.cpp +++ b/src/Flight.cpp @@ -1,4 +1,3 @@ -#include #include #include "Flight.h" diff --git a/src/Program.cpp b/src/Program.cpp index 4b8dd8d..7c02e45 100644 --- a/src/Program.cpp +++ b/src/Program.cpp @@ -1,5 +1,7 @@ #include #include +#include +#include #include "Program.h" using namespace std; @@ -43,13 +45,106 @@ void Program::displayMainMenu() { "\n"; switch (receiveOption(NUM_OPTIONS)) { - case Option::EXIT: + case BEST_FLIGHT: + chooseBestFlight(); + break; + case EXIT: leave(); return; } } } +void Program::chooseBestFlight() { + const static int NUM_OPTIONS = 2; + enum Option { + AIRPORT_CODE = 1, + AIRPORT_NAME = 2, + }; + + clearScreen(); + cout << "\n" + " ┌─ Choose source ─────────────────────────────────────────────────────────────┐\n" + " │ │\n" + " │ Options: │\n" + " │ [1] Airport code │\n" + " │ [2] Airport name │\n" + " │ │\n" + " └─────────────────────────────────────────────────────────────────────────────┘\n" + "\n"; + AirportRef src; + switch (receiveOption(NUM_OPTIONS)) { + case AIRPORT_CODE: + src = receiveAirportByCode(); + break; + case AIRPORT_NAME: + src = receiveAirportByName(); + break; + } + if (src.expired()) + return; + + clearScreen(); + cout << "\n" + " ┌─ Choose destination ────────────────────────────────────────────────────────┐\n" + " │ │\n" + " │ Options: │\n" + " │ [1] Airport code │\n" + " │ [2] Airport name │\n" + " │ │\n" + " └─────────────────────────────────────────────────────────────────────────────┘\n" + "\n"; + AirportRef dest; + switch (receiveOption(NUM_OPTIONS)) { + case AIRPORT_CODE: + dest = receiveAirportByCode(); + break; + case AIRPORT_NAME: + dest = receiveAirportByName(); + break; + } + if (dest.expired()) + return; + + double distance; + vector airports = dataset_.getBestFlightPath(src, dest, distance); + displayBestFlight(airports, distance); +} + +string getAirportInfoString(const Airport& airport) { + return "Code: " + airport.getInfo().getCode() + ", Name: " + airport.getInfo().getName(); +} + +void Program::displayBestFlight(const std::vector &airports, double distance) { + if (airports.empty()) { + cout << "\nNo flight paths were found. "; + waitForEnter(); + return; + } + + int totalFlights = (int)airports.size() - 1; + + clearScreen(); + cout << "\n" + " ┌─ Best flight ───────────────────────────────────────────────────────────────┐\n" + " │ │\n" + " │ Total flights: " << left << setw(60) << totalFlights << "│\n" + " │ Total travel distance: " << setw(52) << to_string(distance) + " Km" << "│\n" + " │ │\n" + " │ Travel airports: │\n"; + + for (int i = 0; i < airports.size(); i++) { + const AirportRef &airport = airports[i]; + cout << " │ " << left << setw(71) + << to_string(i + 1) + ". " + getAirportInfoString(*airport.lock()) << "│\n"; + } + + cout << " │ │\n" + " └─────────────────────────────────────────────────────────────────────────────┘\n" + "\n"; + waitForEnter(); +} + void Program::clearScreen() { system("clear || cls"); } @@ -79,6 +174,7 @@ void Program::leave() { CountryRef Program::receiveCountry() const { string name; cout << "Please enter the country's name: "; + cin.ignore(numeric_limits::max(), '\n'); getline(cin, name); CountryRef country = dataset_.getCountry(name); if (country.expired()) { @@ -94,6 +190,7 @@ CityRef Program::receiveCity() const { if (country.expired()) return {}; cout << "Please enter the city's name: "; + cin.ignore(numeric_limits::max(), '\n'); getline(cin, name); CityRef city = dataset_.getCity(name, country.lock()->getName()); if (country.expired()) { @@ -118,6 +215,7 @@ AirlineRef Program::receiveAirlineByCode() const { AirlineRef Program::receiveAirlineByName() const { string name; cout << "Please enter the airline's name: "; + cin.ignore(numeric_limits::max(), '\n'); getline(cin, name); for (const AirlineRef &airline: dataset_.getAirlines()) { if (airline.lock()->getName() == name) @@ -143,6 +241,7 @@ AirportRef Program::receiveAirportByCode() const { AirportRef Program::receiveAirportByName() const { string name; cout << "Please enter the airport's name: "; + cin.ignore(numeric_limits::max(), '\n'); getline(cin, name); for (AirportRef airport: dataset_.getAirports()) { if (airport.lock()->getInfo().getName() == name) From 4bebe9ef2cdc900bcf9027786faeb1badf5892bc Mon Sep 17 00:00:00 2001 From: Process-ing Date: Thu, 28 Dec 2023 11:23:00 +0000 Subject: [PATCH 3/4] Change best flight search to handle multiple sources and destinations --- CMakeLists.txt | 4 ++ include/Dataset.h | 4 +- include/FlightPath.h | 26 +++++++++ include/Program.h | 2 +- src/Dataset.cpp | 37 ++++++++++--- src/FlightPath.cpp | 26 +++++++++ src/Program.cpp | 122 +++++++++++++++++++++++++++++++------------ test/tests.cpp | 12 +++-- 8 files changed, 186 insertions(+), 47 deletions(-) create mode 100644 include/FlightPath.h create mode 100644 src/FlightPath.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 2e1b75f..0b9e235 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -24,6 +24,8 @@ add_executable(feup_aed2 main.cpp include/Flight.h src/Program.cpp include/Program.h + src/FlightPath.cpp + include/FlightPath.h ) add_subdirectory(docs) @@ -47,6 +49,8 @@ add_executable(tests test/tests.cpp include/Flight.h src/Program.cpp include/Program.h + src/FlightPath.cpp + include/FlightPath.h ) target_link_libraries( tests diff --git a/include/Dataset.h b/include/Dataset.h index dcefe37..645fad0 100644 --- a/include/Dataset.h +++ b/include/Dataset.h @@ -8,6 +8,7 @@ #include #include "City.h" +#include "FlightPath.h" typedef Graph Network; typedef VertexSet AirportSet; @@ -36,7 +37,8 @@ class Dataset { AirportRef getAirport(const std::string& code) const; AirlineRef getAirline(const std::string& code) const; - std::vector getBestFlightPath(const AirportRef &src, const AirportRef &dest, double& distance) const; + FlightPath getBestFlightPath(const AirportRef &src, const AirportRef &dest) const; + std::vector getBestFlightPaths(const std::vector &srcs, const std::vector &dests) const; private: CountrySet countrySet_; diff --git a/include/FlightPath.h b/include/FlightPath.h new file mode 100644 index 0000000..6329b35 --- /dev/null +++ b/include/FlightPath.h @@ -0,0 +1,26 @@ +#ifndef FEUP_AED2_FLIGHTPATH_H +#define FEUP_AED2_FLIGHTPATH_H + + +#include +#include "Airport.h" + +class FlightPath { + public: + FlightPath(); + + FlightPath(const std::vector &airports, double distance); + + const std::vector &getAirports() const; + std::vector &getAirports(); + double getDistance() const; + void setDistance(double distance); + int getFlights() const; + +private: + std::vector airports_; + double distance_; +}; + + +#endif //FEUP_AED2_FLIGHTPATH_H diff --git a/include/Program.h b/include/Program.h index cf84ae1..d7569b6 100644 --- a/include/Program.h +++ b/include/Program.h @@ -20,7 +20,7 @@ class Program { void displayMainMenu(); void chooseBestFlight(); - static void displayBestFlight(const std::vector &airports, double distance); + static void displayBestFlight(const std::vector &paths); static int receiveOption(int max); CountryRef receiveCountry() const; diff --git a/src/Dataset.cpp b/src/Dataset.cpp index df403ed..4cf2ee1 100644 --- a/src/Dataset.cpp +++ b/src/Dataset.cpp @@ -147,7 +147,7 @@ const AirportSet &Dataset::getAirports() const { return network_.getVertexSet(); } -std::vector Dataset::getBestFlightPath(const AirportRef& src, const AirportRef& dest, double &distance) const { +FlightPath Dataset::getBestFlightPath(const AirportRef &src, const AirportRef &dest) const { for (AirportRef airport: network_.getVertexSet()) { airport.lock()->setVisited(false); airport.lock()->setParent(AirportRef()); @@ -174,10 +174,10 @@ std::vector Dataset::getBestFlightPath(const AirportRef& src, const if (!dest.lock()->isVisited()) return {}; - vector airports; - airports.push_back(dest); + FlightPath path; + double distance = 0.0; + path.getAirports().push_back(dest); AirportRef curr = dest; - distance = 0; while (curr.lock()->getInfo().getCode() != src.lock()->getInfo().getCode()) { AirportRef next = curr.lock()->getParent(); distance += calculateDistance( @@ -187,10 +187,33 @@ std::vector Dataset::getBestFlightPath(const AirportRef& src, const next.lock()->getInfo().getLongitude() ); curr = next; - airports.push_back(curr); + path.getAirports().push_back(curr); } - reverse(airports.begin(), airports.end()); - return airports; + reverse(path.getAirports().begin(), path.getAirports().end()); + path.setDistance(distance); + return path; +} + +vector Dataset::getBestFlightPaths(const vector &srcs, const vector &dests) const { + int minFlights = numeric_limits::max(); + vector paths; + + for (const AirportRef &src: srcs) { + for (const AirportRef &dest: dests) { + FlightPath path = getBestFlightPath(src, dest); + int flights = path.getFlights(); + + if (flights < minFlights) { + paths.clear(); + paths.push_back(path); + minFlights = flights; + } else if (flights == minFlights) { + paths.push_back(path); + } + } + } + + return paths; } double hav(double x) { diff --git a/src/FlightPath.cpp b/src/FlightPath.cpp new file mode 100644 index 0000000..e29bd26 --- /dev/null +++ b/src/FlightPath.cpp @@ -0,0 +1,26 @@ +#include "FlightPath.h" + +FlightPath::FlightPath(): airports_(), distance_(0.0) {} + +FlightPath::FlightPath(const std::vector &airports, double distance) + : airports_(airports), distance_(distance) {} + +const std::vector &FlightPath::getAirports() const { + return airports_; +} + +std::vector &FlightPath::getAirports() { + return airports_; +} + +double FlightPath::getDistance() const { + return distance_; +} + +void FlightPath::setDistance(double distance) { + distance_ = distance; +} + +int FlightPath::getFlights() const { + return (int)airports_.size() - 1; +} diff --git a/src/Program.cpp b/src/Program.cpp index 7c02e45..94677dd 100644 --- a/src/Program.cpp +++ b/src/Program.cpp @@ -72,17 +72,19 @@ void Program::chooseBestFlight() { " │ │\n" " └─────────────────────────────────────────────────────────────────────────────┘\n" "\n"; - AirportRef src; + vector srcs; switch (receiveOption(NUM_OPTIONS)) { case AIRPORT_CODE: - src = receiveAirportByCode(); + srcs = { receiveAirportByCode() }; + if (srcs[0].expired()) + return; break; case AIRPORT_NAME: - src = receiveAirportByName(); + srcs = { receiveAirportByName() }; + if (srcs[0].expired()) + return; break; } - if (src.expired()) - return; clearScreen(); cout << "\n" @@ -94,55 +96,109 @@ void Program::chooseBestFlight() { " │ │\n" " └─────────────────────────────────────────────────────────────────────────────┘\n" "\n"; - AirportRef dest; + vector dests; switch (receiveOption(NUM_OPTIONS)) { case AIRPORT_CODE: - dest = receiveAirportByCode(); + dests = { receiveAirportByCode() }; + if (dests[0].expired()) + return; break; case AIRPORT_NAME: - dest = receiveAirportByName(); + dests = { receiveAirportByName() }; + if (dests[0].expired()) + return; break; } - if (dest.expired()) - return; - double distance; - vector airports = dataset_.getBestFlightPath(src, dest, distance); - displayBestFlight(airports, distance); + vector paths = dataset_.getBestFlightPaths(srcs, dests); + displayBestFlight(paths); } string getAirportInfoString(const Airport& airport) { return "Code: " + airport.getInfo().getCode() + ", Name: " + airport.getInfo().getName(); } -void Program::displayBestFlight(const std::vector &airports, double distance) { - if (airports.empty()) { +void Program::displayBestFlight(const vector &paths) { + enum Option { + NEXT_PAGE = 1, + PREVIOUS_PAGE = 2, + GO_BACK = 3, + }; + + if (paths.empty()) { cout << "\nNo flight paths were found. "; waitForEnter(); return; } - int totalFlights = (int)airports.size() - 1; + int pathIndex = 0; + while (true) { + const FlightPath& path = paths[pathIndex]; + clearScreen(); + cout << "\n" + " ┌─ Best flight paths ─────────────────────────────────────────────────────────┐\n" + " │ │\n" + " │ Total flights: " << left << setw(60) << path.getFlights() << "│\n" + " │ Total travel distance: " << setw(52) << to_string(path.getDistance()) + " Km" << "│\n" + " │ │\n" + " │ Travel airports: │\n"; - clearScreen(); - cout << "\n" - " ┌─ Best flight ───────────────────────────────────────────────────────────────┐\n" - " │ │\n" - " │ Total flights: " << left << setw(60) << totalFlights << "│\n" - " │ Total travel distance: " << setw(52) << to_string(distance) + " Km" << "│\n" - " │ │\n" - " │ Travel airports: │\n"; + for (int i = 0; i < path.getAirports().size(); i++) { + const AirportRef &airport = path.getAirports()[i]; + cout << " │ " << left << setw(71) + << to_string(i + 1) + ". " + getAirportInfoString(*airport.lock()) << "│\n"; + } - for (int i = 0; i < airports.size(); i++) { - const AirportRef &airport = airports[i]; - cout << " │ " << left << setw(71) - << to_string(i + 1) + ". " + getAirportInfoString(*airport.lock()) << "│\n"; - } + cout << " │ │\n" + " │ Flight path " << left << setw(63) << to_string(pathIndex + 1) + " of " + to_string(paths.size()) << "│\n"; + if (pathIndex < paths.size() - 1) + cout << " │ [1] Next page │\n"; + if (pathIndex > 0) + cout << " │ [2] Previous page │\n"; - cout << " │ │\n" - " └─────────────────────────────────────────────────────────────────────────────┘\n" - "\n"; - waitForEnter(); + cout << " │ [3] Go back │\n" + " │ │\n" + " └─────────────────────────────────────────────────────────────────────────────┘\n" + "\n"; + + int option; + cout << "Please choose an option: "; + bool valid_option = false; + while (true) { + if (!(cin >> option)) { + cin.clear(); + cin.ignore(numeric_limits::max(), '\n'); + cout << "Invalid option. Please choose another option: "; + continue; + } + + switch (option) { + case NEXT_PAGE: + if (pathIndex < paths.size() - 1) { + pathIndex++; + valid_option = true; + } else { + valid_option = false; + } + break; + case PREVIOUS_PAGE: + if (pathIndex > 0) { + pathIndex--; + valid_option = true; + } else { + valid_option = false; + } + break; + case GO_BACK: + return; + default: + break; + } + if (valid_option) + break; + cout << "Invalid option. Please choose another option: "; + } + } } void Program::clearScreen() { diff --git a/test/tests.cpp b/test/tests.cpp index 4829740..471aa0b 100644 --- a/test/tests.cpp +++ b/test/tests.cpp @@ -74,9 +74,11 @@ TEST(BestFlightTestSuite, GetBestFlightPathTest) { AirportRef CDG = dataset.getAirport("CDG"); ASSERT_FALSE(JFK.expired()); ASSERT_FALSE(CDG.expired()); - double distance; - vector airports = dataset.getBestFlightPath(JFK, CDG, distance); - ASSERT_EQ(2, airports.size()); - EXPECT_EQ(JFK.lock(), airports[0].lock()); - EXPECT_EQ(CDG.lock(), airports[1].lock()); + vector paths = dataset.getBestFlightPaths({ JFK }, { CDG }); + ASSERT_EQ(1, paths.size()); + FlightPath path = paths[0]; + + ASSERT_EQ(2, path.getAirports().size()); + EXPECT_EQ(JFK.lock(), path.getAirports()[0].lock()); + EXPECT_EQ(CDG.lock(), path.getAirports()[1].lock()); } From d71219602f8edd1eca70a079cc0ade9849ff821f Mon Sep 17 00:00:00 2001 From: Process-ing Date: Thu, 28 Dec 2023 11:31:55 +0000 Subject: [PATCH 4/4] Refactor airport choosing --- include/Program.h | 1 + src/Program.cpp | 54 +++++++++++++++++++++++------------------------ 2 files changed, 27 insertions(+), 28 deletions(-) diff --git a/include/Program.h b/include/Program.h index d7569b6..f997424 100644 --- a/include/Program.h +++ b/include/Program.h @@ -20,6 +20,7 @@ class Program { void displayMainMenu(); void chooseBestFlight(); + std::vector chooseAirportsForBestFlight(); static void displayBestFlight(const std::vector &paths); static int receiveOption(int max); diff --git a/src/Program.cpp b/src/Program.cpp index 94677dd..bd1b06b 100644 --- a/src/Program.cpp +++ b/src/Program.cpp @@ -56,12 +56,6 @@ void Program::displayMainMenu() { } void Program::chooseBestFlight() { - const static int NUM_OPTIONS = 2; - enum Option { - AIRPORT_CODE = 1, - AIRPORT_NAME = 2, - }; - clearScreen(); cout << "\n" " ┌─ Choose source ─────────────────────────────────────────────────────────────┐\n" @@ -72,19 +66,9 @@ void Program::chooseBestFlight() { " │ │\n" " └─────────────────────────────────────────────────────────────────────────────┘\n" "\n"; - vector srcs; - switch (receiveOption(NUM_OPTIONS)) { - case AIRPORT_CODE: - srcs = { receiveAirportByCode() }; - if (srcs[0].expired()) - return; - break; - case AIRPORT_NAME: - srcs = { receiveAirportByName() }; - if (srcs[0].expired()) - return; - break; - } + vector srcs = chooseAirportsForBestFlight(); + if (srcs.empty()) + return; clearScreen(); cout << "\n" @@ -96,22 +80,36 @@ void Program::chooseBestFlight() { " │ │\n" " └─────────────────────────────────────────────────────────────────────────────┘\n" "\n"; - vector dests; + vector dests = chooseAirportsForBestFlight(); + if (dests.empty()) + return; + + vector paths = dataset_.getBestFlightPaths(srcs, dests); + displayBestFlight(paths); +} + +vector Program::chooseAirportsForBestFlight() { + const static int NUM_OPTIONS = 2; + enum Option { + AIRPORT_CODE = 1, + AIRPORT_NAME = 2, + }; + + vector airports; switch (receiveOption(NUM_OPTIONS)) { case AIRPORT_CODE: - dests = { receiveAirportByCode() }; - if (dests[0].expired()) - return; + airports = { receiveAirportByCode() }; + if (airports[0].expired()) + return {}; break; case AIRPORT_NAME: - dests = { receiveAirportByName() }; - if (dests[0].expired()) - return; + airports = { receiveAirportByName() }; + if (airports[0].expired()) + return {}; break; } - vector paths = dataset_.getBestFlightPaths(srcs, dests); - displayBestFlight(paths); + return airports; } string getAirportInfoString(const Airport& airport) {