From 9ef313ad9f8bfab3a90eaaca134b10b338c5662a Mon Sep 17 00:00:00 2001 From: Mahmoud Bassem <82619789+Mahmoud-Bassem@users.noreply.github.com> Date: Sat, 4 May 2024 13:16:49 +0300 Subject: [PATCH 1/3] Added map update functionalities\n\n implement the update functions in account.cpp, added comparison operator in RoadProperties class --- data/data.txt | 10 +-- include/account.h | 27 +++--- include/map_helpers.h | 4 + src/account.cpp | 189 ++++++++++++++++++++++++++--------------- src/main.cpp | 101 +++++++++++++--------- src/map.cpp | 190 +++++++++++++++++++++--------------------- 6 files changed, 303 insertions(+), 218 deletions(-) diff --git a/data/data.txt b/data/data.txt index 4b50bf1..e237d32 100644 --- a/data/data.txt +++ b/data/data.txt @@ -1,6 +1,6 @@ 5 -Giza - Cairo Metro 30 Bus 60 Uber 230 -Giza - Dahab Bus 500 Microbus 345 -Cairo - BeniSuef Microbus 20 Bus 15 -Cairo - Asyut Train 250 Bus 450 -Dahab - BeniSuef Microbus 200 Bus 315 \ No newline at end of file +Asyut - Cairo Train 250 Bus 450 +BeniSuef - Cairo Microbus 20 Bus 15 +BeniSuef - Dahab Microbus 200 Bus 315 +Dahab - Giza Bus 500 Microbus 345 +Giza - Cairo Metro 30 Bus 60 Uber 230 \ No newline at end of file diff --git a/include/account.h b/include/account.h index 11daabf..eea26be 100644 --- a/include/account.h +++ b/include/account.h @@ -1,19 +1,21 @@ #pragma once +#include "map_helpers.h" #include + using namespace std; class Account { - private: +private: string userName; string password; bool validatePassword(string); - public: +public: Account(); - Account(string, string); // signup + Account(string, string); // signup bool greetUser(); bool signup(); bool login(); @@ -24,18 +26,21 @@ class Account { }; class User : Account { - public: +public: void traverseMap(); void checkState(); }; class Admin : Account { - public: - void addRoad(); - void updateRoad(); - void deleteRoad(); +public: + void addRoad(string &city1, string &city2, int cost, + transportations transportation); + void updateRoad(string &city1, string &city2, int cost, + transportations transportation, int new_cost, + transportations new_transportation); + void deleteRoad(Road road); // - void addCity(); - void updateCity(); - void deleteCity(); + void addCity(string &name); + void updateCity(string &name, string &new_name); + void deleteCity(string &name); }; \ No newline at end of file diff --git a/include/map_helpers.h b/include/map_helpers.h index 6267482..995c3e3 100644 --- a/include/map_helpers.h +++ b/include/map_helpers.h @@ -27,6 +27,10 @@ class RoadProperties { // RoadProperties(int, transportations); RoadProperties(const RoadProperties&); + + bool operator==(const RoadProperties &other) { + return other.cost == cost && other.transport == transport; + } }; class Road : Edge { diff --git a/src/account.cpp b/src/account.cpp index 030883d..0db615b 100644 --- a/src/account.cpp +++ b/src/account.cpp @@ -1,10 +1,11 @@ #include "../include/account.h" +#include "../include/map.h" +#include #include - Account::Account() { - userName = ""; - password = ""; + userName = ""; + password = ""; } Account::Account(string userName, string password) { @@ -13,68 +14,66 @@ Account::Account(string userName, string password) { } bool Account::validatePassword(string pass) { - if (pass.size() < 6) - return false; - // TOOD: Add more validation - return true; + if (pass.size() < 6) + return false; + // TOOD: Add more validation + return true; } bool Account::greetUser() { - int x = 9; - cout << "Hello, There...\n"; - cout << "What do you want to do?\n"; - while (x != 1 && x != 2) { - cout << "1.Login 2.signup\n"; - cin >> x; - if (x == 1) { - login(); - } - else if (x == 2) { - signup(); - } - else - cout << "Invalid option, Try again...\n"; - } - return true; + int x = 9; + cout << "Hello, There...\n"; + cout << "What do you want to do?\n"; + while (x != 1 && x != 2) { + cout << "1.Login 2.signup\n"; + cin >> x; + if (x == 1) { + login(); + } else if (x == 2) { + signup(); + } else + cout << "Invalid option, Try again...\n"; + } + return true; } bool Account::signup() { - string userName, password = "77"; - cout << "Enter your wanted username:\n"; - cin >> userName; - cout << '\n'; - cout << "Enter your wanted password:\n"; - cin >> password; - while (!validatePassword(password)) { - cout << "Please enter a valid password, your password must be at least 6 characters long\n"; - cin >> password; - } - cout << "Signup Successful!!\n"; - this->setName(userName); - this->setPassword(password); - login(); - return true; + string userName, password = "77"; + cout << "Enter your wanted username:\n"; + cin >> userName; + cout << '\n'; + cout << "Enter your wanted password:\n"; + cin >> password; + while (!validatePassword(password)) { + cout << "Please enter a valid password, your password must be at least " + "6 characters long\n"; + cin >> password; + } + cout << "Signup Successful!!\n"; + this->setName(userName); + this->setPassword(password); + login(); + return true; } bool Account::login() { - string userName, password; - bool done = false; - while (!done) { - cout << "Enter your username:\n"; - cin >> userName; - cout << "Enter your password:\n"; - cin >> password; - // TODO: add searching in users data - cout << this->getName() << " " << this->getPassword() << '\n'; - if (userName == this->getName() && password == this->getPassword()) { - cout << "Login Successful!!\n"; - done = true; - } - else { - cout << "Invalid data, Try again...\n"; - } - } - return true; + string userName, password; + bool done = false; + while (!done) { + cout << "Enter your username:\n"; + cin >> userName; + cout << "Enter your password:\n"; + cin >> password; + // TODO: add searching in users data + cout << this->getName() << " " << this->getPassword() << '\n'; + if (userName == this->getName() && password == this->getPassword()) { + cout << "Login Successful!!\n"; + done = true; + } else { + cout << "Invalid data, Try again...\n"; + } + } + return true; } string Account::getName() { return userName; } @@ -84,22 +83,80 @@ void Account::setName(string name) { userName = name; } void Account::setPassword(string password) { this->password = password; } void User::traverseMap() { - int option = -1; - cout << "How do you want to traverse?\n"; - cout << "1.BFS 2.DFS"; - cin >> option; + int option = -1; + cout << "How do you want to traverse?\n"; + cout << "1.BFS 2.DFS"; + cin >> option; } void User::checkState() {} -void Admin::addCity() {} +void Admin::addCity(string &name) { + // add it as a key + auto &adjList = Map::adjList; + adjList[name] = {}; +} + +void Admin::updateCity(string &name, string &new_name) { // NOTE: if city doesn't exist, the new city will just be added + + // find it, update name, and update name in all connections + auto &adjList = Map::adjList; -void Admin::updateCity() {} + for (auto [city, connections] : adjList[name]) { // erase all connections + auto it = adjList[city].find(name); + assert(it != adjList[city].end()); + adjList[city].erase(it); + + adjList[city].emplace(new_name, connections); + } + + auto temp = adjList[name]; + adjList.erase(adjList.find(name)); // erase key + adjList.emplace(new_name, temp); +} -void Admin::deleteCity() {} +void Admin::deleteCity(string &name) { // WARNING: city doesn't exist -> runtime error! + // delete key, delete connections -void Admin::addRoad() {} + auto &adjList = Map::adjList; -void Admin::updateRoad() {} + for (auto [city, connections] : adjList[name]) { // erase all connections + auto it = adjList[city].find(name); + assert(it != adjList[city].end()); + adjList[city].erase(it); + } + + adjList.erase(adjList.find(name)); // erase key +} + +void Admin::addRoad(string &city1, string &city2, int cost, + transportations transportation) { + // add it to connections + auto &adjList = Map::adjList; + + adjList[city1][city2].addRoad(RoadProperties(cost, transportation)); + adjList[city2][city1].addRoad(RoadProperties(cost, transportation)); +} + +void Admin::updateRoad(string &city1, string &city2, int cost, transportations transportation, int new_cost, + transportations new_transportation) { + // change props + deleteRoad(Road(city1, city2, RoadProperties(cost, transportation))); + addRoad(city1, city2, new_cost, new_transportation); +} -void Admin::deleteRoad() {} \ No newline at end of file +void Admin::deleteRoad(Road road) { // WARNING: road doesn't exist -> runtimer error! + + // delete connection + auto &adjList = Map::adjList; + auto city1 = road.city1Name; + auto city2 = road.city2Name; + + adjList[city1][city2].roads.remove(road.props); + adjList[city2][city1].roads.remove(road.props); + + if (adjList[city1][city2].roads.empty()) { + adjList[city1].erase(city2); + adjList[city2].erase(city1); + } +} \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index fc6aca5..d4a334d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,8 +1,9 @@ #include +#include "../include/account.h" #include "../include/data_manager.h" #include "../include/map.h" -#include "../include/account.h" + // Set Global Variables string DATA_PATH = "../data/data.txt"; @@ -19,48 +20,66 @@ int main(int argc, char **argv) { DataManager dataManager = DataManager(); dataManager.readData(DATA_PATH); Account account; - // Greet User - bool greetingState = account.greetUser(); - if (!greetingState) return 0; - // cast to user or admin according to data - bool isAdmin = false; - if (account.getName() == ADMIN_NAME && account.getPassword() == ADMIN_PASSWORD) - isAdmin = true; - // - if (isAdmin) { - Admin* user = (Admin*)&account; - cout << "What do you want to do?\n"; - cout << "1.Add City 2.Update City 3.Delete City"; - // TODO: add handling logic - } - else { - User* user = (User*)&account; - int choice=-1; - cout << "What do you want to do?\n"; - while (choice != 1 && choice != 2) { - cout << "1.Traverse Map 2.Check Map State 3.Close app\n"; - cin >> choice; - if (choice == 1) { - choice = -1; - user->traverseMap(); - Map::bfs("Cairo","Dahab"); - } + // // Greet User + // bool greetingState = account.greetUser(); + // if (!greetingState) return 0; + // // cast to user or admin according to data + // bool isAdmin = false; + // if (account.getName() == ADMIN_NAME && account.getPassword() == + // ADMIN_PASSWORD) + // isAdmin = true; + // // + // if (isAdmin) { + // Admin* user = (Admin*)&account; + // cout << "What do you want to do?\n"; + // cout << "1.Add City 2.Update City 3.Delete City"; + // // TODO: add handling logic + // } + // else { + // User* user = (User*)&account; + // int choice=-1; + // cout << "What do you want to do?\n"; + // while (choice != 1 && choice != 2) { + // cout << "1.Traverse Map 2.Check Map State 3.Close + // app\n"; cin >> choice; if (choice == 1) { choice = -1; user->traverseMap(); + // Map::bfs("Cairo","Dahab"); + // } - else if (choice == 2) { - choice = -1; - user->checkState(); - } - else if (choice == 3) - break; - else - cout << "Invalid Option, Try again...\n"; - } - cout << "See ya later...\n"; - } + // else if (choice == 2) { + // choice = -1; + // user->checkState(); + // } + // else if (choice == 3) + // break; + // else + // cout << "Invalid Option, Try again...\n"; + // } + // cout << "See ya later...\n"; + // } // - cout<< Map::Dijkstra("Cairo","Dahab"); - //dataManager.printAdjList(); - // shutdown + // cout<< Map::Dijkstra("Cairo","Dahab"); + dataManager.printAdjList(); + Admin *user = (Admin *)&account; + string name1 = "ccccc"; + user->addCity(name1); + string name2 = "bbbbb"; + user->addCity(name2); + + dataManager.printAdjList(); + cout << "\n\n\n\n\n"; + + user->addRoad(name1, name2, 50, BUS); + + dataManager.printAdjList(); + cout << "\n\n\n\n\n"; + +// user->deleteCity(name1); +// user->deleteCity(name2); + user->deleteRoad(Road(name1, name2, RoadProperties(50, BUS))); + + dataManager.printAdjList(); + // user->deleteRoad() + // shutdown dataManager.saveData(DATA_PATH); return 0; } \ No newline at end of file diff --git a/src/map.cpp b/src/map.cpp index 891d001..62dde81 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -1,114 +1,114 @@ #include "../include/map.h" -#include -#include -#include -#include +#include #include #include -#include +#include +#include +#include +#include + using namespace std; // Map // i dont know where to put the visited array -void Map::bfs(string start,string destination) { - mapvisited; - mapparent; - visited[start]=true; - queueq; - q.push(start); - parent[start]="-1"; - parent[destination]="-1";// in case there is no way from start to destination - while(!q.empty()){ - string this_city_name; - this_city_name=q.front(); - q.pop(); - for(auto to : adjList[this_city_name]){ - if(!visited[to.first]){ - visited[to.first]=true; - q.push(to.first); - parent[to.first]=this_city_name; - } - } - } - stack path; - for(string child = destination;child!="-1";child=parent[child]){ - path.push(child); +void Map::bfs(string start, string destination) { + map visited; + map parent; + visited[start] = true; + queue q; + q.push(start); + parent[start] = "-1"; + parent[destination] = "-1"; // in case there is no way from start to destination + while (!q.empty()) { + string this_city_name; + this_city_name = q.front(); + q.pop(); + for (auto to : adjList[this_city_name]) { + if (!visited[to.first]) { + visited[to.first] = true; + q.push(to.first); + parent[to.first] = this_city_name; + } } - if(parent[destination]=="-1"){ - cout << "There is no way to get from " << start << " to " << destination << endl; - return; - } - string transportNames[]={"Bus","Microbus","Train","Metro","Uber"}; - string cityfrom=path.top(); + } + stack path; + for (string child = destination; child != "-1"; child = parent[child]) { + path.push(child); + } + if (parent[destination] == "-1") { + cout << "There is no way to get from " << start << " to " << destination + << endl; + return; + } + string transportNames[] = {"Bus", "Microbus", "Train", "Metro", "Uber"}; + string cityfrom = path.top(); + path.pop(); + while (!path.empty()) { + string cityto = path.top(); path.pop(); - while(!path.empty()){ - string cityto = path.top(); - path.pop(); - cout << " From "<< cityfrom << " to " << cityto << " you can take: " << endl; - for(auto roads : adjList[cityfrom][cityto].roads){ - cout << transportNames[roads.transport] << " for " << roads.cost << " pounds " << endl; - } - if(!path.empty()) - cout << "then\n"; - cityfrom=cityto; + cout << " From " << cityfrom << " to " << cityto + << " you can take: " << endl; + for (auto roads : adjList[cityfrom][cityto].roads) { + cout << transportNames[roads.transport] << " for " << roads.cost + << " pounds " << endl; } + if (!path.empty()) + cout << "then\n"; + cityfrom = cityto; + } } -int Map::compute_hash(string s) -{ - long long ret=0, pw = 1; - int i = 1; - const int mod = 1e3, p =31; - for (auto c : s) - { - if(c>='a' && c<='z'){ - ret = ( (ret%mod ) + ( (pw%mod )* (c - 'a' + 1)%mod )%mod )%mod; - pw = ((pw*mod)*(p%mod))%mod; - }else{ - ret = ( (ret%mod ) + ( (pw%mod )* (c - 'A' + 1)%mod )%mod )%mod; - pw = ((pw*mod)*(p%mod))%mod; - } +int Map::compute_hash(string s) { + long long ret = 0, pw = 1; + int i = 1; + const int mod = 1e3, p = 31; + for (auto c : s) { + if (c >= 'a' && c <= 'z') { + ret = ((ret % mod) + ((pw % mod) * (c - 'a' + 1) % mod) % mod) % mod; + pw = ((pw * mod) * (p % mod)) % mod; + } else { + ret = ((ret % mod) + ((pw % mod) * (c - 'A' + 1) % mod) % mod) % mod; + pw = ((pw * mod) * (p % mod)) % mod; } - return ret; + } + return ret; } -long long Map::Dijkstra(string node,string distination){ - cout<< "ya rab\n"; -priority_queue >pq; // < -cost , city > -map > par; -long long dis[int(1e3)]; // [hash(city)] -memset(dis,0x3fffff,sizeof dis); -pq.push({0,node}); -dis[compute_hash(node)] = 0; -while(!pq.empty()){ - long long cost;string city ; - tie(cost,city) =pq.top(); - cost *=-1; - pq.pop(); - for(auto to : adjList[city]){ - - int hash = compute_hash(to.first); - long long mn = (dis[hash] == -1 ? 100000 : dis[hash] ); - transportations t; - for(auto r : to.second.roads){ - if(cost + r.cost < mn ){ - mn = cost + r.cost; - t = r.transport; - } - } - if(dis[hash] == -1 || mn < dis[hash]){ - dis[hash] = mn; - pq.push({-mn , to.first}); - par[to.first] = {city,t}; - } +long long Map::Dijkstra(string node, string distination) { + cout << "ya rab\n"; + priority_queue> pq; // < -cost , city > + map> par; + long long dis[int(1e3)]; // [hash(city)] + memset(dis, 0x3fffff, sizeof dis); + pq.push({0, node}); + dis[compute_hash(node)] = 0; + while (!pq.empty()) { + long long cost; + string city; + tie(cost, city) = pq.top(); + cost *= -1; + pq.pop(); + for (auto to : adjList[city]) { + int hash = compute_hash(to.first); + long long mn = (dis[hash] == -1 ? 100000 : dis[hash]); + transportations t; + for (auto r : to.second.roads) { + if (cost + r.cost < mn) { + mn = cost + r.cost; + t = r.transport; + } + } + if (dis[hash] == -1 || mn < dis[hash]) { + dis[hash] = mn; + pq.push({-mn, to.first}); + par[to.first] = {city, t}; + } } - } - return dis[compute_hash(distination)]; + } + return dis[compute_hash(distination)]; } -int Map::getNumberOfEdges() -{ +int Map::getNumberOfEdges() { int cnt = 0; - for(auto i:Map::adjList) - { + for (auto i : Map::adjList) { cnt += i.second.size(); } - return cnt/2; + return cnt / 2; } \ No newline at end of file From 5b8d5cc85f887dc918311d1f6885ef70fca027fb Mon Sep 17 00:00:00 2001 From: Abdallah Ibrahim IsmaiI <64263339+Apolo151@users.noreply.github.com> Date: Sat, 4 May 2024 16:06:42 +0300 Subject: [PATCH 2/3] Update CMakeLists.txt Set standard to c++17 --- CMakeLists.txt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index ba2588b..bb20037 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,4 +2,9 @@ cmake_minimum_required(VERSION 3.5) project(guide_me) file(GLOB HEADERS "include/*.h") file(GLOB SOURCES "src/*.cpp") + +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_CXX_EXTENSIONS OFF) + add_executable(main ${SOURCES} ${HEADERS}) From 86bb12776eea4a4e135bbe65e2acd4fa483c739f Mon Sep 17 00:00:00 2001 From: Abdallah Ibrahim IsmaiI <64263339+Apolo151@users.noreply.github.com> Date: Sat, 4 May 2024 16:19:01 +0300 Subject: [PATCH 3/3] Update map_helpers.h update equality operator to be `const` --- include/map_helpers.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/map_helpers.h b/include/map_helpers.h index 995c3e3..6195619 100644 --- a/include/map_helpers.h +++ b/include/map_helpers.h @@ -28,7 +28,7 @@ class RoadProperties { RoadProperties(int, transportations); RoadProperties(const RoadProperties&); - bool operator==(const RoadProperties &other) { + bool operator==(const RoadProperties &other) const { return other.cost == cost && other.transport == transport; } }; @@ -54,4 +54,4 @@ class Route { Route(const Route&); // void addRoad(RoadProperties); -}; \ No newline at end of file +};