From 02bd0209848ec0778cfd3673c7d2323f503e77c8 Mon Sep 17 00:00:00 2001 From: Hassan Date: Wed, 21 Nov 2018 10:53:02 +0330 Subject: [PATCH 01/18] Add Logger to project --- CMakeLists.txt | 12 +++++++----- Logger.cpp | 24 ++++++++++++++++++++++++ Logger.h | 19 +++++++++++++++++++ main.cpp | 1 + 4 files changed, 51 insertions(+), 5 deletions(-) create mode 100644 Logger.cpp create mode 100644 Logger.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 5fd9156..03979cb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,8 +6,10 @@ set(CMAKE_CXX_STANDARD 14) include_directories(.) add_executable(stackoverflow_in_cpp - AbstractUser.h - Exceptions.h - main.cpp - User.cpp - User.h) + AbstractUser.h + Exceptions.h + Logger.cpp + Logger.h + main.cpp + User.cpp + User.h) diff --git a/Logger.cpp b/Logger.cpp new file mode 100644 index 0000000..bb29eb1 --- /dev/null +++ b/Logger.cpp @@ -0,0 +1,24 @@ +#include "Logger.h" +#include +#include + +Logger::Logger() {} + +Logger& Logger::getInstance() { + static Logger lg; + return lg; +} + +void Logger::log(std::string lg) { + this->logs.push_back(lg); +} + +void Logger::printLogs() { + for(auto &log : logs) { + std::cout << log << std::endl; + } +} + +std::vector& Logger::getLogs() { + return this->logs; +} diff --git a/Logger.h b/Logger.h new file mode 100644 index 0000000..6d328ec --- /dev/null +++ b/Logger.h @@ -0,0 +1,19 @@ +#pragma once + +#include +#include + +#define _Log(x) Logger::getInstance().log((x)) + + +class Logger { +public: + static Logger& getInstance(); +public: + void printLogs(); + void log(std::string lg); + std::vector& getLogs (); +private: + Logger(); + std::vector logs; +}; diff --git a/main.cpp b/main.cpp index 01eac03..89b6f67 100755 --- a/main.cpp +++ b/main.cpp @@ -3,6 +3,7 @@ #include "AbstractUser.h" #include "Exceptions.h" #include "User.h" +#include "Logger.h" #ifdef _WIN32 #define CLEAR "cls" From edabf9f8d83b1e7403e296d4577ae30a834c33a3 Mon Sep 17 00:00:00 2001 From: Hassan Date: Thu, 22 Nov 2018 00:23:02 +0330 Subject: [PATCH 02/18] Handle Logger --- Logger.cpp | 10 ++++++++-- Logger.h | 2 +- main.cpp | 12 ++++++++---- 3 files changed, 17 insertions(+), 7 deletions(-) diff --git a/Logger.cpp b/Logger.cpp index bb29eb1..1c0956a 100644 --- a/Logger.cpp +++ b/Logger.cpp @@ -1,6 +1,8 @@ #include "Logger.h" #include +#include #include +#include Logger::Logger() {} @@ -9,8 +11,12 @@ Logger& Logger::getInstance() { return lg; } -void Logger::log(std::string lg) { - this->logs.push_back(lg); +void Logger::log(const std::string& lg) { + std::ofstream file("Log.txt", std::ios::app); + time_t now = time(0); + std::string date_time(ctime(&now)); + file << "┌─[" << date_time << "└─[" << lg << std::endl; + this->logs.push_back("┌─[" + date_time + "└─[" + lg); } void Logger::printLogs() { diff --git a/Logger.h b/Logger.h index 6d328ec..421a740 100644 --- a/Logger.h +++ b/Logger.h @@ -11,7 +11,7 @@ class Logger { static Logger& getInstance(); public: void printLogs(); - void log(std::string lg); + void log(const std::string& lg); std::vector& getLogs (); private: Logger(); diff --git a/main.cpp b/main.cpp index 89b6f67..9ed6289 100755 --- a/main.cpp +++ b/main.cpp @@ -29,9 +29,10 @@ int main() { char choice; while(menuState != MenuState::END) { system(CLEAR); - if (!last_message.empty()) + if (not last_message.empty()) { cout << last_message << endl; - last_message = ""; + last_message = ""; + } switch (menuState) { case MenuState::START: { cout << "1. login\n2. signup\ne. exit\n"; @@ -44,8 +45,9 @@ int main() { cin >> username; cout << "Enter Password: "; cin >> password; - loggedInUser = &User::login(username,password); + loggedInUser = &User::login(username, password); menuState = MenuState::LOGGED_IN; + _Log("Logged in: " + username); } catch (WrongUsernameOrPasswordException &e) { last_message = e.what(); } @@ -63,6 +65,7 @@ int main() { loggedInUser = &User::signup(username, password, email); menuState = MenuState::LOGGED_IN; last_message = "User signed up!\n"; + _Log("Signed up: " + username); } catch (UsernameAlreadyExistsException &e) { last_message = e.what(); break; @@ -91,6 +94,7 @@ int main() { try { loggedInUser->deleteAccount(); cout << "Account successfully deleted\n"; + _Log("User has been deleted: " + loggedInUser->username); loggedInUser = nullptr; menuState = MenuState::START; } @@ -100,9 +104,9 @@ int main() { break; } case 'l': { // logout + _Log("Logged out: " + loggedInUser->username); loggedInUser = nullptr; menuState = MenuState::START; - last_message = "GOOD BYE\n"; break; } case 'e': { // exit From a1e5998b80047188652e0b5a425e8fce10f14d5b Mon Sep 17 00:00:00 2001 From: Hassan Date: Thu, 22 Nov 2018 01:01:18 +0330 Subject: [PATCH 03/18] Add 'show logs' to admin panel --- User.cpp | 4 ++++ User.h | 3 +++ main.cpp | 25 ++++++++++++++++++++----- 3 files changed, 27 insertions(+), 5 deletions(-) diff --git a/User.cpp b/User.cpp index 7aa9f46..c136dd4 100644 --- a/User.cpp +++ b/User.cpp @@ -80,4 +80,8 @@ void User::init(const string &salt) { User::salt = salt; users.reserve(20); users.emplace_back("admin", "admin", "admin@stackoverflow.com", UserType::ADMIN); +} + +bool User::is_admin() { + return this->type == UserType::ADMIN; } \ No newline at end of file diff --git a/User.h b/User.h index 6b239d9..04f7042 100644 --- a/User.h +++ b/User.h @@ -21,6 +21,9 @@ class User : public AbstractUser { static User& login(string username, string password); static User& signup(string username, string password, string email); +public: + bool is_admin(); + private: static string salt; static vector users; diff --git a/main.cpp b/main.cpp index 9ed6289..58122dd 100755 --- a/main.cpp +++ b/main.cpp @@ -25,10 +25,12 @@ int main() { User * loggedInUser = nullptr; MenuState menuState = MenuState::START; string last_message; - + bool show_logs = false; char choice; while(menuState != MenuState::END) { - system(CLEAR); + if(not show_logs) + system(CLEAR); + show_logs = false; if (not last_message.empty()) { cout << last_message << endl; last_message = ""; @@ -87,14 +89,17 @@ int main() { break; } case MenuState::LOGGED_IN: { - cout << "d.delete account\nl. logout\ne. exit\n"; + if(loggedInUser->is_admin()) + cout << "d. delete account\ns. show logs\nl. logout\ne. exit\n"; + else + cout << "d. delete account\nl. logout\ne. exit\n"; cin >> choice; switch (choice) { - case 'd': { + case 'd': { // delete account try { loggedInUser->deleteAccount(); cout << "Account successfully deleted\n"; - _Log("User has been deleted: " + loggedInUser->username); + _Log("deleted: " + loggedInUser->username); loggedInUser = nullptr; menuState = MenuState::START; } @@ -103,6 +108,16 @@ int main() { } break; } + case 's': { // show logs + if(loggedInUser->is_admin()) { + system(CLEAR); + Logger::getInstance().printLogs(); + show_logs = true; + } + else + last_message = "Unknown Input\n"; + break; + } case 'l': { // logout _Log("Logged out: " + loggedInUser->username); loggedInUser = nullptr; From b964d62a07e6cec2f2a638c622edc2937c029364 Mon Sep 17 00:00:00 2001 From: mahdi hosseiny farzad Date: Thu, 22 Nov 2018 18:11:36 +0330 Subject: [PATCH 04/18] overload operator<< | handle logger in main | add one TODO to do in the future! --- Logger.cpp | 9 +++++---- Logger.h | 3 ++- User.cpp | 9 +++++++++ User.h | 3 +++ main.cpp | 5 +---- 5 files changed, 20 insertions(+), 9 deletions(-) diff --git a/Logger.cpp b/Logger.cpp index 1c0956a..6e2a33d 100644 --- a/Logger.cpp +++ b/Logger.cpp @@ -1,4 +1,5 @@ #include "Logger.h" +#include "User.h" #include #include #include @@ -11,12 +12,12 @@ Logger& Logger::getInstance() { return lg; } -void Logger::log(const std::string& lg) { - std::ofstream file("Log.txt", std::ios::app); +void Logger::log(User& user) { + std::ofstream log_file("log.x.txt", std::ios::app); time_t now = time(0); std::string date_time(ctime(&now)); - file << "┌─[" << date_time << "└─[" << lg << std::endl; - this->logs.push_back("┌─[" + date_time + "└─[" + lg); + log_file << user << " " << date_time; + this->logs.push_back(date_time); //TODO: fix it!! } void Logger::printLogs() { diff --git a/Logger.h b/Logger.h index 421a740..cf764ae 100644 --- a/Logger.h +++ b/Logger.h @@ -2,6 +2,7 @@ #include #include +#include "User.h" #define _Log(x) Logger::getInstance().log((x)) @@ -11,7 +12,7 @@ class Logger { static Logger& getInstance(); public: void printLogs(); - void log(const std::string& lg); + void log(User& user); std::vector& getLogs (); private: Logger(); diff --git a/User.cpp b/User.cpp index c136dd4..1b0a8b7 100644 --- a/User.cpp +++ b/User.cpp @@ -84,4 +84,13 @@ void User::init(const string &salt) { bool User::is_admin() { return this->type == UserType::ADMIN; +} + +string User::toString() { + return email + " " + username; +} + +std::ostream& operator<<(std::ostream &os, User &user) { + os << user.toString(); + return os; } \ No newline at end of file diff --git a/User.h b/User.h index 04f7042..847346c 100644 --- a/User.h +++ b/User.h @@ -24,6 +24,9 @@ class User : public AbstractUser { public: bool is_admin(); +public: + string toString(); + friend std::ostream& operator<<(std::ostream& os, User& user); private: static string salt; static vector users; diff --git a/main.cpp b/main.cpp index 58122dd..5d6ab45 100755 --- a/main.cpp +++ b/main.cpp @@ -49,7 +49,7 @@ int main() { cin >> password; loggedInUser = &User::login(username, password); menuState = MenuState::LOGGED_IN; - _Log("Logged in: " + username); + _Log(*loggedInUser); } catch (WrongUsernameOrPasswordException &e) { last_message = e.what(); } @@ -67,7 +67,6 @@ int main() { loggedInUser = &User::signup(username, password, email); menuState = MenuState::LOGGED_IN; last_message = "User signed up!\n"; - _Log("Signed up: " + username); } catch (UsernameAlreadyExistsException &e) { last_message = e.what(); break; @@ -99,7 +98,6 @@ int main() { try { loggedInUser->deleteAccount(); cout << "Account successfully deleted\n"; - _Log("deleted: " + loggedInUser->username); loggedInUser = nullptr; menuState = MenuState::START; } @@ -119,7 +117,6 @@ int main() { break; } case 'l': { // logout - _Log("Logged out: " + loggedInUser->username); loggedInUser = nullptr; menuState = MenuState::START; break; From e2a09091ba3333aa49aad737fcb4f0c1d013b272 Mon Sep 17 00:00:00 2001 From: Hassan Date: Fri, 23 Nov 2018 16:40:10 +0330 Subject: [PATCH 05/18] Fix push back logs to vector --- Logger.cpp | 4 ++-- User.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Logger.cpp b/Logger.cpp index 6e2a33d..3778be1 100644 --- a/Logger.cpp +++ b/Logger.cpp @@ -16,8 +16,8 @@ void Logger::log(User& user) { std::ofstream log_file("log.x.txt", std::ios::app); time_t now = time(0); std::string date_time(ctime(&now)); - log_file << user << " " << date_time; - this->logs.push_back(date_time); //TODO: fix it!! + log_file << user << " | " << date_time; + this->logs.push_back(user.toString() + " | " + date_time); } void Logger::printLogs() { diff --git a/User.cpp b/User.cpp index 1b0a8b7..dcd4bc4 100644 --- a/User.cpp +++ b/User.cpp @@ -87,7 +87,7 @@ bool User::is_admin() { } string User::toString() { - return email + " " + username; + return email + " | " + username; } std::ostream& operator<<(std::ostream &os, User &user) { From be5e17cc01d714fdf20532d3b437d145ef277eb9 Mon Sep 17 00:00:00 2001 From: Hassan Date: Fri, 23 Nov 2018 17:58:02 +0330 Subject: [PATCH 06/18] Fix log files number --- Logger.cpp | 3 ++- main.cpp | 17 +++++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/Logger.cpp b/Logger.cpp index 3778be1..80731c9 100644 --- a/Logger.cpp +++ b/Logger.cpp @@ -11,9 +11,10 @@ Logger& Logger::getInstance() { static Logger lg; return lg; } +extern int log_num; void Logger::log(User& user) { - std::ofstream log_file("log.x.txt", std::ios::app); + std::ofstream log_file("log." + std::to_string(log_num) + ".txt", std::ios::app); time_t now = time(0); std::string date_time(ctime(&now)); log_file << user << " | " << date_time; diff --git a/main.cpp b/main.cpp index 5d6ab45..b5168ff 100755 --- a/main.cpp +++ b/main.cpp @@ -1,4 +1,5 @@ #include +#include #include #include "AbstractUser.h" #include "Exceptions.h" @@ -13,6 +14,21 @@ using namespace std; +int log_num; + +int find_log_num() { + ifstream file; + int num = 1; + while(true) { + file.open("log." + to_string(num) + ".txt"); + if(file.is_open()) { + file.close(); + num++; + continue; + } + return num; + } +} enum MenuState { START, @@ -21,6 +37,7 @@ enum MenuState { }; int main() { + log_num = find_log_num(); User::init("SECRET_KEY"); User * loggedInUser = nullptr; MenuState menuState = MenuState::START; From fe05f78f19618d66277b2701d26fceafc58ce8ec Mon Sep 17 00:00:00 2001 From: Hassan Date: Fri, 23 Nov 2018 18:34:42 +0330 Subject: [PATCH 07/18] Transfer log number to Logger --- Logger.cpp | 19 ++++++++++++++++--- Logger.h | 2 ++ main.cpp | 17 +---------------- 3 files changed, 19 insertions(+), 19 deletions(-) diff --git a/Logger.cpp b/Logger.cpp index 80731c9..c23e90c 100644 --- a/Logger.cpp +++ b/Logger.cpp @@ -5,16 +5,29 @@ #include #include -Logger::Logger() {} +Logger::Logger() { + std::ifstream file; + int num = 1; + while(true) { + file.open("log." + to_string(num) + ".txt"); + if(file.is_open()) { + file.close(); + num++; + continue; + } + log_num = num; + std::ofstream log_file("log." + std::to_string(log_num) + ".txt"); + break; + } +} Logger& Logger::getInstance() { static Logger lg; return lg; } -extern int log_num; void Logger::log(User& user) { - std::ofstream log_file("log." + std::to_string(log_num) + ".txt", std::ios::app); + std::ofstream log_file("log." + std::to_string(Logger::getInstance().log_num) + ".txt", std::ios::app); time_t now = time(0); std::string date_time(ctime(&now)); log_file << user << " | " << date_time; diff --git a/Logger.h b/Logger.h index cf764ae..1e0f446 100644 --- a/Logger.h +++ b/Logger.h @@ -17,4 +17,6 @@ class Logger { private: Logger(); std::vector logs; +private: + int log_num; }; diff --git a/main.cpp b/main.cpp index b5168ff..5e4a936 100755 --- a/main.cpp +++ b/main.cpp @@ -14,21 +14,6 @@ using namespace std; -int log_num; - -int find_log_num() { - ifstream file; - int num = 1; - while(true) { - file.open("log." + to_string(num) + ".txt"); - if(file.is_open()) { - file.close(); - num++; - continue; - } - return num; - } -} enum MenuState { START, @@ -37,7 +22,7 @@ enum MenuState { }; int main() { - log_num = find_log_num(); + Logger::getInstance(); User::init("SECRET_KEY"); User * loggedInUser = nullptr; MenuState menuState = MenuState::START; From 1f18e90fac73bf5dc7da1848facba644cfef15de Mon Sep 17 00:00:00 2001 From: Hassan Date: Sat, 24 Nov 2018 00:46:56 +0330 Subject: [PATCH 08/18] Add username and email validation checking | Add InvalidUsernameException and InvalidEmailException --- Exceptions.h | 28 ++++++++++++++++++++++++---- User.cpp | 24 +++++++++++++++++++----- main.cpp | 6 +----- 3 files changed, 44 insertions(+), 14 deletions(-) diff --git a/Exceptions.h b/Exceptions.h index f304c0b..8bce64f 100644 --- a/Exceptions.h +++ b/Exceptions.h @@ -11,7 +11,6 @@ class UsernameAlreadyExistsException : public std::exception { private: const std::string message = "Error: username already exists"; - }; class EmailAlreadyExistsException : public std::exception { @@ -22,16 +21,38 @@ class EmailAlreadyExistsException : public std::exception { private: const std::string message = "Error: email already exists"; +}; +class InvalidUsernameException : public std::exception { +public: + const char *what() const throw() { + return message.c_str(); + } + +private: + const std::string message = "Error: invalid username\n" + "You can use a-z, 0-9 and underscores\n" + "Username must be at least 5 and at most 32 characters"; }; -class WrongUsernameOrPasswordException : public std::exception { +class InvalidEmailException : public std::exception { +public: + const char *what() const throw() { + return message.c_str(); + } + private: - const std::string message = "Error: wrong username or password!"; + const std::string message = "Error: invalid email address"; +}; + +class WrongUsernameOrPasswordException : public std::exception { public: const char *what() const throw() { return message.c_str(); } + +private: + const std::string message = "Error: wrong username or password!"; }; class DeleteAdminException : public std::exception { @@ -42,5 +63,4 @@ class DeleteAdminException : public std::exception { private: const std::string message = "Error: can't delete admin account!"; - }; diff --git a/User.cpp b/User.cpp index dcd4bc4..da9c6b8 100644 --- a/User.cpp +++ b/User.cpp @@ -1,14 +1,20 @@ #include -// -// Created by spsina on 11/8/18. -// - #include #include "User.h" #include "Exceptions.h" #include +#include + +bool is_username_valid(const string& username) { + const std::regex pattern("\\w{5,32}"); + return std::regex_match(username, pattern); +} +bool is_email_valid(const string& email) { + const std::regex pattern("(\\w+)(\\.|_)?(\\w*)@(\\w+)(\\.(\\w+))+"); + return std::regex_match(email, pattern); +} vector User::users; string User::salt; @@ -71,7 +77,15 @@ User& User::signup(string username, string password, string email){ throw EmailAlreadyExistsException(); } } - //Create user + // Check username validatin + if(not is_username_valid(username)) + throw InvalidUsernameException(); + + // Check email validatin + if(not is_email_valid(email)) + throw InvalidEmailException(); + + // Create user users.emplace_back(username, password, email, UserType::MEMBER); return users[users.size() - 1]; } diff --git a/main.cpp b/main.cpp index 5e4a936..f79fc10 100755 --- a/main.cpp +++ b/main.cpp @@ -69,11 +69,7 @@ int main() { loggedInUser = &User::signup(username, password, email); menuState = MenuState::LOGGED_IN; last_message = "User signed up!\n"; - } catch (UsernameAlreadyExistsException &e) { - last_message = e.what(); - break; - - } catch (EmailAlreadyExistsException &e) { + } catch (exception &e) { last_message = e.what(); } break; From 566fcff726ba51e584a9f8f04c3681f544f81a49 Mon Sep 17 00:00:00 2001 From: mahdi hosseiny farzad Date: Sat, 24 Nov 2018 15:26:03 +0330 Subject: [PATCH 09/18] Define Content and ContentRelation header files --- Content.h | 18 ++++++++++++++++++ ContentRelation.h | 15 +++++++++++++++ User.h | 5 ++++- 3 files changed, 37 insertions(+), 1 deletion(-) create mode 100644 Content.h create mode 100644 ContentRelation.h diff --git a/Content.h b/Content.h new file mode 100644 index 0000000..942f3b8 --- /dev/null +++ b/Content.h @@ -0,0 +1,18 @@ +#pragma once + +#include +#include +#include "ContentRelation.h" + +enum ContentType { + QUESTION, + ANSWER +}; + +class Content { +public: + std::string body; + ContentType type; + int visits; + std::vector relations; +}; \ No newline at end of file diff --git a/ContentRelation.h b/ContentRelation.h new file mode 100644 index 0000000..eee27a5 --- /dev/null +++ b/ContentRelation.h @@ -0,0 +1,15 @@ +#pragma once + +#include +#include "Content.h" + +enum ContentRelationType { + DUPLICATE_OF, + ANSWER_TO +}; + +class ContentRelation { +public: + Content destination; + ContentRelationType type; +}; \ No newline at end of file diff --git a/User.h b/User.h index 847346c..fee4f1f 100644 --- a/User.h +++ b/User.h @@ -6,7 +6,6 @@ class User : public AbstractUser { public: User(string username, string password, string email, UserType type); - static void init(const string &salt); public: @@ -27,6 +26,10 @@ class User : public AbstractUser { public: string toString(); friend std::ostream& operator<<(std::ostream& os, User& user); + +public: + vector contents; + private: static string salt; static vector users; From b0fba9e872cd2368a4587805375cc1f0a4fda802 Mon Sep 17 00:00:00 2001 From: Hassan Date: Sat, 24 Nov 2018 17:03:09 +0330 Subject: [PATCH 10/18] Solve the circular inclusion problem --- CMakeLists.txt | 2 ++ ContentRelation.h | 5 +++-- User.h | 1 + 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 03979cb..741d932 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -8,6 +8,8 @@ include_directories(.) add_executable(stackoverflow_in_cpp AbstractUser.h Exceptions.h + Content.h + ContentRelation.h Logger.cpp Logger.h main.cpp diff --git a/ContentRelation.h b/ContentRelation.h index eee27a5..84e642e 100644 --- a/ContentRelation.h +++ b/ContentRelation.h @@ -1,15 +1,16 @@ #pragma once #include -#include "Content.h" enum ContentRelationType { DUPLICATE_OF, ANSWER_TO }; +class Content; + class ContentRelation { public: - Content destination; + Content* destination; ContentRelationType type; }; \ No newline at end of file diff --git a/User.h b/User.h index fee4f1f..e4afcf0 100644 --- a/User.h +++ b/User.h @@ -2,6 +2,7 @@ #include #include "AbstractUser.h" +#include "Content.h" class User : public AbstractUser { public: From b1858b380eb80b55f4601570b5f6e56f8beec6df Mon Sep 17 00:00:00 2001 From: Hassan Date: Sun, 25 Nov 2018 22:03:24 +0330 Subject: [PATCH 11/18] Change Content and ContentRelation default constructors --- CMakeLists.txt | 2 ++ Content.cpp | 3 +++ Content.h | 7 +++++-- ContentRelation.cpp | 4 ++++ ContentRelation.h | 5 ++++- 5 files changed, 18 insertions(+), 3 deletions(-) create mode 100644 Content.cpp create mode 100644 ContentRelation.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 741d932..20b19cc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -9,7 +9,9 @@ add_executable(stackoverflow_in_cpp AbstractUser.h Exceptions.h Content.h + Content.cpp ContentRelation.h + ContentRelation.cpp Logger.cpp Logger.h main.cpp diff --git a/Content.cpp b/Content.cpp new file mode 100644 index 0000000..73eaef7 --- /dev/null +++ b/Content.cpp @@ -0,0 +1,3 @@ +#include "Content.h" + +Content::Content(ContentType &type, std::string &body): visits(0), type(type), body(body) {} diff --git a/Content.h b/Content.h index 942f3b8..b524989 100644 --- a/Content.h +++ b/Content.h @@ -12,7 +12,10 @@ enum ContentType { class Content { public: std::string body; + std::vector relations; ContentType type; int visits; - std::vector relations; -}; \ No newline at end of file + +public: + Content(ContentType &type, std::string &body); +}; diff --git a/ContentRelation.cpp b/ContentRelation.cpp new file mode 100644 index 0000000..66616bc --- /dev/null +++ b/ContentRelation.cpp @@ -0,0 +1,4 @@ +#include "ContentRelation.h" + +ContentRelation::ContentRelation(ContentRelationType &type, Content *destination): + type(type), destination(destination) {} diff --git a/ContentRelation.h b/ContentRelation.h index 84e642e..b7da4f8 100644 --- a/ContentRelation.h +++ b/ContentRelation.h @@ -13,4 +13,7 @@ class ContentRelation { public: Content* destination; ContentRelationType type; -}; \ No newline at end of file + +public: + ContentRelation(ContentRelationType &type, Content* destination); +}; From 1565eef2665364559d678c11a20595cceca10bde Mon Sep 17 00:00:00 2001 From: Hassan Date: Fri, 30 Nov 2018 21:17:24 +0330 Subject: [PATCH 12/18] Add add_relation & edit_content & print_answers to Content --- Content.cpp | 27 ++++++++++++++++++++++++++- Content.h | 8 ++++++-- ContentRelation.cpp | 25 +++++++++++++++++++++++-- ContentRelation.h | 9 ++++++--- User.cpp | 6 +++++- User.h | 1 + 6 files changed, 67 insertions(+), 9 deletions(-) diff --git a/Content.cpp b/Content.cpp index 73eaef7..37308c6 100644 --- a/Content.cpp +++ b/Content.cpp @@ -1,3 +1,28 @@ #include "Content.h" -Content::Content(ContentType &type, std::string &body): visits(0), type(type), body(body) {} +Content::Content(std::string &body, ContentType &type): visits(0), type(type), body(body) {} + +Content::~Content() { + for(int i = 0; i < relations.size(); i++) + delete relations[0]; +} + +void Content::add_relation(ContentRelationType &type, Content &destination) { + auto relation_ptr = new ContentRelation(&destination, this, type); + relations.push_back(relation_ptr); + destination.relations.push_back(relation_ptr); +} + +void Content::edit_content(std::string &body) { + this->body = body; +} + +void Content::print_answers() { + int answer_number = 1; + for(int i = 0; i < relations.size(); i++) { + if(relations[i]->type == ANSWER_TO) { + std::cout << answer_number++ << ". " << relations[i]->source->body << std::endl; + } + } + std::cout << std::endl; +} diff --git a/Content.h b/Content.h index b524989..d01445f 100644 --- a/Content.h +++ b/Content.h @@ -12,10 +12,14 @@ enum ContentType { class Content { public: std::string body; - std::vector relations; ContentType type; int visits; + std::vector relations; public: - Content(ContentType &type, std::string &body); + Content(std::string &body, ContentType &type); + ~Content(); + void add_relation(ContentRelationType &type, Content &destination); + void edit_content(std::string &body); + void print_answers(); }; diff --git a/ContentRelation.cpp b/ContentRelation.cpp index 66616bc..60ab2fc 100644 --- a/ContentRelation.cpp +++ b/ContentRelation.cpp @@ -1,4 +1,25 @@ #include "ContentRelation.h" +#include "Content.h" -ContentRelation::ContentRelation(ContentRelationType &type, Content *destination): - type(type), destination(destination) {} +ContentRelation::ContentRelation(Content *destination, Content *source, ContentRelationType type): + destination(destination), + source(source), + type(type) {} + +ContentRelation::~ContentRelation() { + auto relations = &(this->destination->relations); + + for(auto it = relations->begin(); it < relations->end(); it++) { + if(*it == this) { + relations->erase(it); + } + } + + relations = &(this->source->relations); + + for (auto it = relations->begin(); it < relations->end(); it++) { + if (*it == this) { + relations->erase(it); + } + } +} diff --git a/ContentRelation.h b/ContentRelation.h index b7da4f8..c0f1cb2 100644 --- a/ContentRelation.h +++ b/ContentRelation.h @@ -1,6 +1,7 @@ #pragma once #include +#include enum ContentRelationType { DUPLICATE_OF, @@ -11,9 +12,11 @@ class Content; class ContentRelation { public: - Content* destination; - ContentRelationType type; + ContentRelation(Content* destination, Content* source, ContentRelationType type); + ~ContentRelation(); public: - ContentRelation(ContentRelationType &type, Content* destination); + Content* destination; + Content* source ; + ContentRelationType type; }; diff --git a/User.cpp b/User.cpp index da9c6b8..831eb80 100644 --- a/User.cpp +++ b/User.cpp @@ -107,4 +107,8 @@ string User::toString() { std::ostream& operator<<(std::ostream &os, User &user) { os << user.toString(); return os; -} \ No newline at end of file +} + +void User::create(std::string &body, ContentType &type) { + contents.emplace_back( body, type); +} diff --git a/User.h b/User.h index e4afcf0..5cddbba 100644 --- a/User.h +++ b/User.h @@ -30,6 +30,7 @@ class User : public AbstractUser { public: vector contents; + void create(std::string &body, ContentType &type); private: static string salt; From fe711cda812e70db9f01eebb4b47a514da9592ae Mon Sep 17 00:00:00 2001 From: Hassan Date: Fri, 30 Nov 2018 22:01:37 +0330 Subject: [PATCH 13/18] Add 'add questin' in menu --- Content.cpp | 4 ++-- Content.h | 4 ++-- User.cpp | 2 +- User.h | 2 +- main.cpp | 22 +++++++++++++++++++--- 5 files changed, 25 insertions(+), 9 deletions(-) diff --git a/Content.cpp b/Content.cpp index 37308c6..d12ae40 100644 --- a/Content.cpp +++ b/Content.cpp @@ -1,13 +1,13 @@ #include "Content.h" -Content::Content(std::string &body, ContentType &type): visits(0), type(type), body(body) {} +Content::Content(std::string &body, ContentType type): visits(0), type(type), body(body) {} Content::~Content() { for(int i = 0; i < relations.size(); i++) delete relations[0]; } -void Content::add_relation(ContentRelationType &type, Content &destination) { +void Content::add_relation(ContentRelationType type, Content &destination) { auto relation_ptr = new ContentRelation(&destination, this, type); relations.push_back(relation_ptr); destination.relations.push_back(relation_ptr); diff --git a/Content.h b/Content.h index d01445f..0681543 100644 --- a/Content.h +++ b/Content.h @@ -17,9 +17,9 @@ class Content { std::vector relations; public: - Content(std::string &body, ContentType &type); + Content(std::string &body, ContentType type); ~Content(); - void add_relation(ContentRelationType &type, Content &destination); + void add_relation(ContentRelationType type, Content &destination); void edit_content(std::string &body); void print_answers(); }; diff --git a/User.cpp b/User.cpp index 831eb80..7bcd3a2 100644 --- a/User.cpp +++ b/User.cpp @@ -109,6 +109,6 @@ std::ostream& operator<<(std::ostream &os, User &user) { return os; } -void User::create(std::string &body, ContentType &type) { +void User::create(std::string &body, ContentType type) { contents.emplace_back( body, type); } diff --git a/User.h b/User.h index 5cddbba..cb2aa5f 100644 --- a/User.h +++ b/User.h @@ -30,7 +30,7 @@ class User : public AbstractUser { public: vector contents; - void create(std::string &body, ContentType &type); + void create(std::string &body, ContentType type); private: static string salt; diff --git a/main.cpp b/main.cpp index f79fc10..91b4772 100755 --- a/main.cpp +++ b/main.cpp @@ -5,6 +5,7 @@ #include "Exceptions.h" #include "User.h" #include "Logger.h" +#include "Content.h" #ifdef _WIN32 #define CLEAR "cls" @@ -18,6 +19,7 @@ using namespace std; enum MenuState { START, LOGGED_IN, + QUESTIONS, END }; @@ -87,11 +89,22 @@ int main() { } case MenuState::LOGGED_IN: { if(loggedInUser->is_admin()) - cout << "d. delete account\ns. show logs\nl. logout\ne. exit\n"; - else - cout << "d. delete account\nl. logout\ne. exit\n"; + cout << "s. show logs\n"; + cout << "a. add question\nq. all questions\nd. delete account\nl. logout\ne. exit\n"; cin >> choice; switch (choice) { + case 'a': { // add question + cout << "Enter your question: "; + string question; + cin >> question; + //getline(cin, question); + loggedInUser->create(question, ContentType::QUESTION); + break; + } + case 'q': { // all questions + menuState = MenuState::QUESTIONS; + break; + } case 'd': { // delete account try { loggedInUser->deleteAccount(); @@ -130,6 +143,9 @@ int main() { } } + case MenuState::QUESTIONS: { + //TODO: questions menu + } } } system(CLEAR); From 5ceff723144991e985be5046504e38975e7c6fe6 Mon Sep 17 00:00:00 2001 From: Hassan Date: Sat, 1 Dec 2018 14:12:55 +0330 Subject: [PATCH 14/18] Add print_questions to User | Use getline for getting questions --- User.cpp | 10 ++++++++++ User.h | 3 +++ main.cpp | 9 ++++++--- 3 files changed, 19 insertions(+), 3 deletions(-) diff --git a/User.cpp b/User.cpp index 7bcd3a2..140ad47 100644 --- a/User.cpp +++ b/User.cpp @@ -112,3 +112,13 @@ std::ostream& operator<<(std::ostream &os, User &user) { void User::create(std::string &body, ContentType type) { contents.emplace_back( body, type); } + +void User::print_questions() { + for(const auto &user : users) { + for(const auto &content : user.contents) { + if(content.type == ContentType::QUESTION) { + std::cout << user.username << ": " << content.body << std::endl << std::endl; + } + } + } +} diff --git a/User.h b/User.h index cb2aa5f..5cfc37c 100644 --- a/User.h +++ b/User.h @@ -32,6 +32,9 @@ class User : public AbstractUser { vector contents; void create(std::string &body, ContentType type); +public: + static void print_questions(); + private: static string salt; static vector users; diff --git a/main.cpp b/main.cpp index 91b4772..f283715 100755 --- a/main.cpp +++ b/main.cpp @@ -96,8 +96,8 @@ int main() { case 'a': { // add question cout << "Enter your question: "; string question; - cin >> question; - //getline(cin, question); + cin.ignore(1); + getline(cin, question); loggedInUser->create(question, ContentType::QUESTION); break; } @@ -142,9 +142,12 @@ int main() { } } + break; } case MenuState::QUESTIONS: { - //TODO: questions menu + loggedInUser->print_questions(); + menuState = MenuState::LOGGED_IN; + break; } } } From efadfa56b9cf73679221e93bd6beef5e42354f4b Mon Sep 17 00:00:00 2001 From: Hassan Date: Sat, 1 Dec 2018 16:08:55 +0330 Subject: [PATCH 15/18] Improve QUESTIONS menu --- User.cpp | 5 +++++ User.h | 1 + main.cpp | 25 +++++++++++++++++++++++-- 3 files changed, 29 insertions(+), 2 deletions(-) diff --git a/User.cpp b/User.cpp index 140ad47..07c8ca3 100644 --- a/User.cpp +++ b/User.cpp @@ -122,3 +122,8 @@ void User::print_questions() { } } } + +void User::print_content(int num) { + num %= contents.size(); + cout << "Question " << num+1 << ": " << contents[num].body << endl << endl; +} diff --git a/User.h b/User.h index 5cfc37c..978dbf6 100644 --- a/User.h +++ b/User.h @@ -34,6 +34,7 @@ class User : public AbstractUser { public: static void print_questions(); + void print_content(int num); private: static string salt; diff --git a/main.cpp b/main.cpp index f283715..8059d3a 100755 --- a/main.cpp +++ b/main.cpp @@ -31,6 +31,7 @@ int main() { string last_message; bool show_logs = false; char choice; + int content_num = 0; while(menuState != MenuState::END) { if(not show_logs) system(CLEAR); @@ -102,6 +103,7 @@ int main() { break; } case 'q': { // all questions + content_num = 0; menuState = MenuState::QUESTIONS; break; } @@ -145,8 +147,27 @@ int main() { break; } case MenuState::QUESTIONS: { - loggedInUser->print_questions(); - menuState = MenuState::LOGGED_IN; + loggedInUser->print_content(content_num); + cout << "p. previous question\nn. next question\nb. back to main menu\n"; + cin >> choice; + switch (choice) { + case 'p': { // previous question + content_num--; + break; + } + case 'n': { // next question + content_num++; + break; + } + case 'b': { // back to main menu + menuState = MenuState::LOGGED_IN; + break; + } + default: { // unknown input + last_message = "Unknown Input\n"; + break; + } + } break; } } From ce58852f696553947c45a4103e882c25f8025c9d Mon Sep 17 00:00:00 2001 From: Hassan Date: Sat, 1 Dec 2018 17:24:18 +0330 Subject: [PATCH 16/18] Add 'edit question' to menu --- User.cpp | 5 +++++ User.h | 1 + main.cpp | 10 +++++++++- 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/User.cpp b/User.cpp index 07c8ca3..5233dfd 100644 --- a/User.cpp +++ b/User.cpp @@ -127,3 +127,8 @@ void User::print_content(int num) { num %= contents.size(); cout << "Question " << num+1 << ": " << contents[num].body << endl << endl; } + +void User::edit_content(int num, string &body) { + num %= contents.size(); + contents[num].body = body; +} diff --git a/User.h b/User.h index 978dbf6..649ee0e 100644 --- a/User.h +++ b/User.h @@ -35,6 +35,7 @@ class User : public AbstractUser { public: static void print_questions(); void print_content(int num); + void edit_content(int num, string& body); private: static string salt; diff --git a/main.cpp b/main.cpp index 8059d3a..abf8054 100755 --- a/main.cpp +++ b/main.cpp @@ -148,7 +148,7 @@ int main() { } case MenuState::QUESTIONS: { loggedInUser->print_content(content_num); - cout << "p. previous question\nn. next question\nb. back to main menu\n"; + cout << "p. previous question\nn. next question\ne. edit question\nb. back to main menu\n"; cin >> choice; switch (choice) { case 'p': { // previous question @@ -159,6 +159,14 @@ int main() { content_num++; break; } + case 'e': { // edit question + cout << "Enter your question: "; + string question; + cin.ignore(1); + getline(cin, question); + loggedInUser->edit_content(content_num, question); + break; + } case 'b': { // back to main menu menuState = MenuState::LOGGED_IN; break; From b96308765a8d27a7d0e2a5a42b1994dcf65880e1 Mon Sep 17 00:00:00 2001 From: Hassan Date: Sat, 1 Dec 2018 17:41:00 +0330 Subject: [PATCH 17/18] Show answers of a questions --- User.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/User.cpp b/User.cpp index 5233dfd..393b1b1 100644 --- a/User.cpp +++ b/User.cpp @@ -110,7 +110,7 @@ std::ostream& operator<<(std::ostream &os, User &user) { } void User::create(std::string &body, ContentType type) { - contents.emplace_back( body, type); + contents.emplace_back(body, type); } void User::print_questions() { @@ -125,7 +125,14 @@ void User::print_questions() { void User::print_content(int num) { num %= contents.size(); - cout << "Question " << num+1 << ": " << contents[num].body << endl << endl; + std::cout << "Question " << num+1 << ": " << contents[num].body << std::endl + << "_______________________________" << std::endl + << "Answers:" << std::endl; + for(const auto &relation : contents[num].relations) { + if(relation->type == ContentRelationType::ANSWER_TO) + std::cout << relation->destination->body << std::endl; + } + std::cout << "_______________________________" << std::endl; } void User::edit_content(int num, string &body) { From c018d355a774fd487fd3aedda1601a7a432c264c Mon Sep 17 00:00:00 2001 From: Hassan Date: Sat, 1 Dec 2018 17:56:43 +0330 Subject: [PATCH 18/18] Add 'delete question' to menu --- User.cpp | 7 +++++++ User.h | 1 + main.cpp | 6 +++++- 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/User.cpp b/User.cpp index 393b1b1..88d12a0 100644 --- a/User.cpp +++ b/User.cpp @@ -139,3 +139,10 @@ void User::edit_content(int num, string &body) { num %= contents.size(); contents[num].body = body; } + +void User::delete_content(int num) { + num %= contents.size(); + auto it = contents.begin(); + it += num; + contents.erase(it); +} \ No newline at end of file diff --git a/User.h b/User.h index 649ee0e..276fafe 100644 --- a/User.h +++ b/User.h @@ -36,6 +36,7 @@ class User : public AbstractUser { static void print_questions(); void print_content(int num); void edit_content(int num, string& body); + void delete_content(int num); private: static string salt; diff --git a/main.cpp b/main.cpp index abf8054..9f557d6 100755 --- a/main.cpp +++ b/main.cpp @@ -148,7 +148,7 @@ int main() { } case MenuState::QUESTIONS: { loggedInUser->print_content(content_num); - cout << "p. previous question\nn. next question\ne. edit question\nb. back to main menu\n"; + cout << "p. previous question\nn. next question\ne. edit question\nd. delete question\nb. back to main menu\n"; cin >> choice; switch (choice) { case 'p': { // previous question @@ -167,6 +167,10 @@ int main() { loggedInUser->edit_content(content_num, question); break; } + case 'd': { // delete question + loggedInUser->delete_content(content_num); + break; + } case 'b': { // back to main menu menuState = MenuState::LOGGED_IN; break;