Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

🤷🤷🤷 #30

Open
wants to merge 18 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 11 additions & 5 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,14 @@ 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
Content.h
Content.cpp
ContentRelation.h
ContentRelation.cpp
Logger.cpp
Logger.h
main.cpp
User.cpp
User.h)
28 changes: 28 additions & 0 deletions Content.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#include "Content.h"

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;
}
25 changes: 25 additions & 0 deletions Content.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#pragma once

#include <iostream>
#include <vector>
#include "ContentRelation.h"

enum ContentType {
QUESTION,
ANSWER
};

class Content {
public:
std::string body;
ContentType type;
int visits;
std::vector<ContentRelation*> relations;

public:
Content(std::string &body, ContentType type);
~Content();
void add_relation(ContentRelationType type, Content &destination);
void edit_content(std::string &body);
void print_answers();
};
25 changes: 25 additions & 0 deletions ContentRelation.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#include "ContentRelation.h"
#include "Content.h"

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);
}
}
}
22 changes: 22 additions & 0 deletions ContentRelation.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#pragma once

#include <iostream>
#include<vector>

enum ContentRelationType {
DUPLICATE_OF,
ANSWER_TO
};

class Content;

class ContentRelation {
public:
ContentRelation(Content* destination, Content* source, ContentRelationType type);
~ContentRelation();

public:
Content* destination;
Content* source ;
ContentRelationType type;
};
28 changes: 24 additions & 4 deletions Exceptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ class UsernameAlreadyExistsException : public std::exception {

private:
const std::string message = "Error: username already exists";

};

class EmailAlreadyExistsException : public std::exception {
Expand All @@ -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 {
Expand All @@ -42,5 +63,4 @@ class DeleteAdminException : public std::exception {

private:
const std::string message = "Error: can't delete admin account!";

};
45 changes: 45 additions & 0 deletions Logger.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
#include "Logger.h"
#include "User.h"
#include <iostream>
#include <fstream>
#include <vector>
#include <ctime>

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;
}

void Logger::log(User& user) {
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;
this->logs.push_back(user.toString() + " | " + date_time);
}

void Logger::printLogs() {
for(auto &log : logs) {
std::cout << log << std::endl;
}
}

std::vector<std::string>& Logger::getLogs() {
return this->logs;
}
22 changes: 22 additions & 0 deletions Logger.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#pragma once

#include <vector>
#include <string>
#include "User.h"

#define _Log(x) Logger::getInstance().log((x))


class Logger {
public:
static Logger& getInstance();
public:
void printLogs();
void log(User& user);
std::vector<std::string>& getLogs ();
private:
Logger();
std::vector<std::string> logs;
private:
int log_num;
};
75 changes: 70 additions & 5 deletions User.cpp
Original file line number Diff line number Diff line change
@@ -1,14 +1,20 @@
#include <utility>

//
// Created by spsina on 11/8/18.
//

#include <sstream>
#include "User.h"
#include "Exceptions.h"
#include <iostream>
#include <regex>

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> User::users;
string User::salt;
Expand Down Expand Up @@ -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];
}
Expand All @@ -80,4 +94,55 @@ 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;
}

string User::toString() {
return email + " | " + username;
}

std::ostream& operator<<(std::ostream &os, User &user) {
os << user.toString();
return os;
}

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;
}
}
}
}

void User::print_content(int num) {
num %= contents.size();
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) {
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);
}
19 changes: 18 additions & 1 deletion User.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@

#include <iostream>
#include "AbstractUser.h"
#include "Content.h"

class User : public AbstractUser {
public:
User(string username, string password, string email, UserType type);

static void init(const string &salt);

public:
Expand All @@ -21,6 +21,23 @@ class User : public AbstractUser {
static User& login(string username, string password);
static User& signup(string username, string password, string email);

public:
bool is_admin();

public:
string toString();
friend std::ostream& operator<<(std::ostream& os, User& user);

public:
vector<Content> contents;
void create(std::string &body, ContentType type);

public:
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;
static vector<User> users;
Expand Down
Loading