-
-
Save elja/8aa80fe557f6210ae0f396065ff08f52 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <iostream> | |
#include <iomanip> | |
#include <stdexcept> | |
#include <vector> | |
#include <cstdlib> | |
#include <sstream> | |
#include <cstring> | |
#include <algorithm> | |
using namespace std; | |
#include "sqltools.h" | |
#include "repository_object.h" | |
#include "repository.h" | |
// ---------------- MODELS -------------------- // | |
class User : public RepositoryObject { | |
public: | |
enum Role { admin, user }; | |
static const char* roleTitles[]; | |
string login; | |
string password; | |
Role role; | |
public: | |
User() : RepositoryObject() { | |
} | |
User(const string login, const string password, const Role role) : RepositoryObject() { | |
this->login = login; | |
this->password = password; | |
this->role = role; | |
} | |
const char* roleTitle() { | |
return User::roleTitles[role]; | |
} | |
static Role getRoleByTitle(const string title) { | |
return User::getRoleByTitle(title.c_str()); | |
} | |
static Role getRoleByTitle(const char* title) { | |
if (strcmp(title, "admin") == 0) { | |
return Role::admin; | |
} | |
if (strcmp(title, "user") == 0) { | |
return Role::user; | |
} | |
return (Role)-1; | |
} | |
virtual bool isValid() { | |
if (login.length() && password.length() && (role == user || role == admin)) { | |
return true; | |
} | |
return false; | |
} | |
protected: | |
virtual RepositoryObject* setAttribute(const char *attrName, const char *attrValue) { | |
if (strcmp(attrName, "login") == 0) { | |
this->login = attrValue; | |
} | |
else if (strcmp(attrName, "password") == 0) { | |
this->password = attrValue; | |
} | |
else if (strcmp(attrName, "role") == 0) { | |
this->role = (Role)_atoi64(attrValue); | |
} | |
return RepositoryObject::setAttribute(attrName, attrValue); | |
} | |
}; | |
class Patient : public RepositoryObject { | |
public: | |
enum Sex { male, female }; | |
static const char* sexTitles[]; | |
string firstName; | |
string lastName; | |
string city; | |
string diagnosis; | |
int age; | |
Sex sex; | |
public: | |
Patient() : RepositoryObject() { | |
} | |
Patient(const string firstName, const string lastName, const int age, Sex sex, const string city, const string diagnosis) : RepositoryObject() { | |
this->firstName = firstName; | |
this->lastName = lastName; | |
this->age = age; | |
this->sex = sex; | |
this->city = city; | |
this->diagnosis = diagnosis; | |
} | |
const char* sexTitle() { | |
return sexTitles[sex]; | |
} | |
static Sex getSexByTitle(const string title) { | |
return Patient::getSexByTitle(title.c_str()); | |
} | |
static Sex getSexByTitle(const char* title) { | |
if (strcmp(title, "male") == 0) { | |
return Sex::male; | |
} | |
if (strcmp(title, "female") == 0) { | |
return Sex::female; | |
} | |
return (Sex)-1; | |
} | |
bool isValid() { | |
if (firstName.length() && lastName.length() && city.length() && diagnosis.length() && age > 0 && (sex == male || sex == female)) | |
return true; | |
return false; | |
} | |
protected: | |
RepositoryObject* setAttribute(const char *attrName, const char *attrValue) { | |
if (strcmp(attrName, "lastName") == 0) { | |
this->lastName = attrValue; | |
} | |
else if (strcmp(attrName, "firstName") == 0) { | |
this->firstName = attrValue; | |
} | |
else if (strcmp(attrName, "age") == 0) { | |
this->age = strtoul(attrValue, NULL, 0); | |
} | |
else if (strcmp(attrName,"sex") == 0) { | |
this->sex = (Sex)strtoul(attrValue, NULL, 0); | |
} | |
else if (strcmp(attrName, "city") == 0) { | |
this->city = attrValue; | |
} | |
else if (strcmp(attrName, "diagnosis") == 0) { | |
this->diagnosis = attrValue; | |
} | |
return RepositoryObject::setAttribute(attrName, attrValue); | |
} | |
}; | |
// ------------ STATIC INITIALIZATION -------- // | |
const char* User::roleTitles[] = { "admin", "user" }; | |
const char* Patient::sexTitles[] = { "male", "female" }; | |
// ------------- REPOSITORIES --------------- // | |
class UserRepository : public Repository { | |
public: | |
UserRepository(SQLManager *db) : Repository(db) { | |
_createSchema(); | |
} | |
User* getByLoginAndPassowrd(const string login, const string password) { | |
string queryStr = "SELECT * FROM " + _getTableName() + " WHERE login = ? AND password = ?;"; | |
SQLQuery *query = dbManager->prepareQuery(queryStr.c_str()); | |
query->setTextParam(1, login); | |
query->setTextParam(2, password); | |
vector<RepositoryObject*> objects = fillInObjects(dbManager->selectQuery(query)); | |
return objects.size() == 1 ? (User*)objects[0] : nullptr; | |
} | |
protected: | |
virtual RepositoryObject* _initNewRecord() { | |
return new User(); | |
} | |
virtual string _getTableName() { | |
return "users"; | |
} | |
virtual vector<string> _getColumnNames() { | |
return { "id", "login", "password", "role" }; | |
} | |
//реализация метода вставки нового пользователя у класса хранилища пользователя | |
//принимает в себя объект с аттрибудами | |
virtual bool _insertRecord(RepositoryObject *object) { | |
//тут уже полиморфизм не прокатит, нам нужно работать с конкретными аттрибутами класса, поэтому преобразовываем базовый класс в его непосредственную реализацию | |
User *user = (User*)object; | |
//формирем запрос вставки, как и прежде вопросики это параметры (можно было сделать также через + как с _getTableName, просто так безопаснее) | |
SQLQuery *query = dbManager->prepareQuery("INSERT INTO " + _getTableName() + " (login, password, role) VALUES (?, ?, ?);"); | |
query->setTextParam(1, user->login); //сетаем на первый вопросик логине | |
query->setTextParam(2, user->password); //на второй пассворс | |
query->setIntParam(3, user->role); //на третий роль, т.е. роль типа enum, а enum это грубо говоря хранится как цифра, то использем метод для установки числового параметра | |
// вызываем библиотечную функцию которая исполняет SQL в базе данных, возращает true если всё ок, если не прокатило то false. | |
return _insertSQL(object, query); | |
} | |
// тож самое что и выше, только другой запрос - на обновление | |
virtual bool _updateRecord(RepositoryObject *object) { | |
User *user = (User*)object; | |
SQLQuery *query = dbManager->prepareQuery("UPDATE " + _getTableName() + " SET login=?, password=?, role=? WHERE id=?;"); | |
query->setTextParam(1, user->login); | |
query->setTextParam(2, user->password); | |
query->setIntParam(3, user->role); | |
query->setIntParam(4, user->getID()); | |
return _execSQL(query); | |
}; | |
virtual void _createSchema() { | |
string tableSchemaQuery = | |
"CREATE TABLE IF NOT EXISTS " + _getTableName() + " (\ | |
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, \ | |
login VARCHAR(255) UNIQUE NOT NULL, \ | |
password VARCHAR(255) NOT NULL, \ | |
role INTEGER NOT NULL \ | |
);"; | |
return _createSQLSchema(tableSchemaQuery); | |
} | |
}; | |
class PatientRepository : public Repository { | |
public: | |
PatientRepository(SQLManager *db) : Repository(db) { | |
_createSchema(); | |
} | |
vector<RepositoryObject*> getAllSortedBy(string attrName) { | |
SQLQuery *query = dbManager->prepareQuery("SELECT * FROM " + _getTableName() + " ORDER BY " + attrName + " COLLATE NOCASE;"); | |
return fillInObjects(dbManager->selectQuery(query)); | |
} | |
//метод хранилища пациентов для поиска по диагнозу и возрасту, принимает строку диагноза и цифру возраста | |
vector<RepositoryObject*> getAllWhereDiagnosisAndAge(string diagnosis, int age) { | |
//формируем строку запроса в базу данных - это SQL код | |
//dbManager это наш самопальный библиотечный класс, помогает работать с SQL и базой данный SQLITE3 | |
//На выходе это *query должен содержать строку запроса и всякую вспомогательную и не интересную нам ерунду для SQLITE3 | |
//Запрос будет выглядеть типа так SELECT * FROM patients WHERE diagnosis = 'анемия' AND age > 21 | |
//Где стоят вопросики в строке это места для параметров, что бы их установить используется индекс их позиций | |
//Для первого вопросика индекс - 1, для второго - 2, для третьего - 3 и так далее | |
SQLQuery *query = dbManager->prepareQuery("SELECT * FROM " + _getTableName() + " WHERE diagnosis = ? AND age > ?;"); | |
//Устанавливаем значение параметра 1, т.к. он у нас текстовый используем setTextParam | |
//Этот вызов грубо говоря должен внутри запроса вместо diagnosis = ? сделать diagnosis = 'анемия' | |
//Короче подставить вместо ? значение из переменной diagnosis | |
query->setTextParam(1, diagnosis); | |
//тож самое но для числового возраста | |
query->setIntParam(2, age); | |
//выполняем получившийся запрос в базу данных, получаем данные из базы и вызываем/отправляем эти данные в метод fillInObjects | |
//дальше описание смотри в методе fillInObjects - он описан в другом файле -repository.h | |
return fillInObjects(dbManager->selectQuery(query)); | |
} | |
vector<RepositoryObject*> getAllWhereCityNot(string city) { | |
SQLQuery *query = dbManager->prepareQuery("SELECT * FROM " + _getTableName() + " WHERE city != ? COLLATE NOCASE;"); | |
query->setTextParam(1, city); | |
return fillInObjects(dbManager->selectQuery(query)); | |
} | |
protected: | |
virtual RepositoryObject* _initNewRecord() { | |
return new Patient(); | |
} | |
virtual string _getTableName() { | |
return "patients"; | |
} | |
virtual vector<string> _getColumnNames() { | |
return { "id", "firstName", "lastName", "age", "sex", "city", "diagnosis" }; | |
} | |
virtual bool _insertRecord(RepositoryObject *object) { | |
SQLQuery *query = dbManager->prepareQuery("INSERT INTO " + _getTableName() + " (firstName, lastName, age, sex, city, diagnosis) VALUES (?, ?, ?, ?, ?, ?);"); | |
Patient *patient = (Patient*)object; | |
query->setTextParam(1, patient->firstName); | |
query->setTextParam(2, patient->lastName); | |
query->setIntParam(3, patient->age); | |
query->setIntParam(4, patient->sex); | |
query->setTextParam(5, patient->city); | |
query->setTextParam(6, patient->diagnosis); | |
return _insertSQL(object, query); | |
} | |
virtual bool _updateRecord(RepositoryObject *object) { | |
Patient *patient = (Patient*)object; | |
SQLQuery *query = dbManager->prepareQuery("UPDATE " + _getTableName() + " SET firstName=?, lastName=?, age=?, sex=?, city=?, diagnosis=? WHERE id=?;"); | |
query->setTextParam(1, patient->firstName); | |
query->setTextParam(2, patient->lastName); | |
query->setIntParam(3, patient->age); | |
query->setIntParam(4, patient->sex); | |
query->setTextParam(5, patient->city); | |
query->setTextParam(6, patient->diagnosis); | |
query->setIntParam(7, patient->getID()); | |
return _execSQL(query); | |
}; | |
virtual void _createSchema() { | |
string tableSchemaQuery = | |
"CREATE TABLE IF NOT EXISTS " + _getTableName() + " (\ | |
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, \ | |
firstName VARCHAR(255) NOT NULL, \ | |
lastName VARCHAR(255) NOT NULL, \ | |
age INTEGER NOT NULL DEFAULT 0, \ | |
sex VARCHAR(10) NOT NULL, \ | |
city VARCHAR(50) NOT NULL, \ | |
diagnosis VARCHAR(255) NOT NULL \ | |
);"; | |
return _createSQLSchema(tableSchemaQuery); | |
} | |
}; | |
class TableView { | |
protected: | |
vector<int> _colsWidth; | |
static void consoleClear() { | |
system("cls"); | |
} | |
virtual void displayRow(RepositoryObject* object) = 0; | |
virtual void displayHeader() = 0; | |
template<typename T> void displayCell(int index, T t) { | |
cout << "|" << setw(_colsWidth[index]) << t; | |
} | |
void displayEndRow() { | |
cout << "|" << endl; | |
} | |
void displayLast() { | |
stringstream buff; | |
buff << "|"; | |
for(int i = 0; i < _colsWidth.size(); i++) { | |
buff << string(_colsWidth[i], '-'); | |
if (i + 1 != _colsWidth.size()) | |
buff << '-'; | |
} | |
buff << "|"; | |
cout << buff.str() << endl; | |
} | |
void log(string logText) { | |
cout << endl << endl << logText << endl; | |
} | |
public: | |
TableView(const vector<int> colsWidth) { | |
_colsWidth = colsWidth; | |
} | |
~TableView() { | |
} | |
virtual RepositoryObject* findById(Repository *repos) = 0; | |
virtual bool add(Repository *repos) = 0; | |
virtual bool remove(Repository *repos) = 0; | |
virtual bool update(Repository *repos) = 0; | |
void display(vector<RepositoryObject*> objects, bool clear = true) { | |
if (clear) { | |
TableView::consoleClear(); | |
} | |
displayHeader(); | |
displayLast(); | |
if (objects.size() > 0) { | |
for(int i = 0; i < objects.size(); i++) { | |
displayRow(objects[i]); | |
} | |
} | |
displayLast(); | |
} | |
}; | |
class UsersView : public TableView { | |
private: | |
virtual void displayRow(RepositoryObject* object) { | |
User *user = (User*)object; | |
int colIndex = 0; | |
displayCell(colIndex++, user->getID()); | |
displayCell(colIndex++, user->login); | |
displayCell(colIndex++, user->password); | |
displayCell(colIndex++, user->roleTitle()); | |
displayEndRow(); | |
}; | |
virtual void displayHeader() { | |
int colIndex = 0; | |
displayCell(colIndex++, "ID"); | |
displayCell(colIndex++, "Login"); | |
displayCell(colIndex++, "Password"); | |
displayCell(colIndex++, "Role"); | |
displayEndRow(); | |
}; | |
public: | |
UsersView() : TableView({3, 20, 20, 5}) { | |
} | |
virtual RepositoryObject* findById(Repository* repos) { | |
RepositoryObject *user = nullptr; | |
string userID; | |
cout << endl << "User ID: "; | |
getline(cin, userID); | |
if (userID.length()){ | |
row_id id = _atoi64(userID.c_str()); | |
user = repos->getById(id); | |
} | |
return user; | |
} | |
//добавление нового пользователя | |
//что бы лучше понимать в голове просто представить себе 3 типа классов | |
//1) класс данных который хранится - обычно их называют Model | |
//2) класс хранилища (Repasitory) он реализует все методы о том как сохранить, удалить, выбрать Model | |
//3) класс отображения (View) - он занимается взаимодействием с пользователем | |
// сейчас мы в классе типа View | |
//метод добавления нового пользователя, принимает в себя хранилище пользователей что бы потом в него сохранить | |
virtual bool add(Repository *repos) { | |
//подготавливаем переменные | |
User *user = nullptr; | |
string login, password, role; | |
//говорим что мы счя делаем | |
log("Add new user: "); | |
cout << "Login: "; | |
getline(cin, login); //все как обычно говорим что ввести и вводим | |
cout << "Password: "; | |
getline(cin, password); | |
cout << "Role (admin, user): "; | |
getline(cin, role); | |
// проверям все ли мы ввели, все ли строки не пустые | |
if (login.length() && password.length() && role.length()) { | |
//пытаемся найти роль по её имени, роли у нас хранятся как enum | |
//enum это такой тип данных который используется для перечисления какиех-то константных штук | |
//грубо говоря метод ниже просто преобразовывает строку 'admin' в типа данных enum со значением admin | |
User::Role userRole = User::getRoleByTitle(role); | |
//создаем нового пользователя с логин пароль роль которые мы ввели | |
user = new User(login, password, userRole); | |
} | |
//если мы ничего не введем то и условие выше не выполнится, а следовательно и пользователя не будет создано, | |
//поэтому проверям, смогли ли мы инициализировать нового пользователя | |
if (user) { | |
//смогли инициализировать, теперь пробуем сохранить (записать) в хранилище | |
//если метод save вернет true то смогли записать, если фолс, то не смогли | |
//дальше смотри метод save в repository.h | |
if (repos->save(user)) { | |
log("User successfully saved"); | |
return true; | |
} | |
else { | |
log("User couldn't be saved"); | |
} | |
} | |
else { | |
//не смогли, говорим об этом | |
log("Please check your input"); | |
} | |
return false; | |
} | |
virtual bool remove(Repository *repos) { | |
RepositoryObject *user = nullptr; | |
log("Remove user: "); | |
if (user = findById(repos)) { | |
log("User found! Deleting..."); | |
if (repos->remove(user)) { | |
log("User successfully deleted"); | |
return true; | |
} | |
else { | |
log("Can't delete user"); | |
} | |
} | |
else { | |
log("User not found!"); | |
} | |
return false; | |
} | |
virtual bool update(Repository *repos) { | |
User *user = nullptr; | |
string login, password, role; | |
log("Update user: "); | |
if (user = (User*)findById(repos)) { | |
log("User found!"); | |
cout << "Login: "; | |
getline(cin, login); | |
cout << "Password: "; | |
getline(cin, password); | |
cout << "Role (admin, user): "; | |
getline(cin, role); | |
if (login.length()) { | |
user->login = login; | |
} | |
if (password.length()) { | |
user->password = password; | |
} | |
if (role.length()) { | |
User::Role userRole = User::getRoleByTitle(role); | |
user->role = userRole; | |
} | |
if (repos->save(user)) { | |
log("User successfully updated"); | |
return true; | |
} | |
else { | |
log("Can't update user"); | |
} | |
} | |
else { | |
log("User not found!"); | |
} | |
return false; | |
} | |
}; | |
class PatientsView : public TableView { | |
private: | |
virtual void displayRow(RepositoryObject* object) { | |
Patient *patient = (Patient*)object; | |
int colIndex = 0; | |
displayCell(colIndex++, patient->getID()); | |
displayCell(colIndex++, patient->firstName); | |
displayCell(colIndex++, patient->lastName); | |
displayCell(colIndex++, patient->age); | |
displayCell(colIndex++, patient->sexTitle()); | |
displayCell(colIndex++, patient->city); | |
displayCell(colIndex++, patient->diagnosis); | |
displayEndRow(); | |
}; | |
virtual void displayHeader() { | |
int colIndex = 0; | |
displayCell(colIndex++, "ID"); | |
displayCell(colIndex++, "First Name"); | |
displayCell(colIndex++, "Last Name"); | |
displayCell(colIndex++, "Age"); | |
displayCell(colIndex++, "Sex"); | |
displayCell(colIndex++, "City"); | |
displayCell(colIndex++, "Diagnosis"); | |
displayEndRow(); | |
}; | |
public: | |
PatientsView() : TableView({ 3, 13, 13, 3, 6, 15, 15 }) { | |
} | |
virtual RepositoryObject* findById(Repository* repos) { | |
RepositoryObject *patient = nullptr; | |
string patientID; | |
cout << endl << "Patient ID: "; | |
getline(cin, patientID); | |
if (patientID.length()){ | |
row_id id = _atoi64(patientID.c_str()); | |
patient = repos->getById(id); | |
} | |
return patient; | |
} | |
virtual bool add(Repository *repos) { | |
Patient *patient = nullptr; | |
string firstName, lastName, city, sex, diagnosis, age; | |
log("Add new patient: "); | |
cout << "First Name: "; | |
getline(cin, firstName); | |
cout << "Last Name: "; | |
getline(cin, lastName); | |
cout << "City: "; | |
getline(cin, city); | |
cout << "Sex (male, female): "; | |
getline(cin, sex); | |
cout << "Age: "; | |
getline(cin, age); | |
cout << "Diagnosis: "; | |
getline(cin, diagnosis); | |
if (firstName.length() && lastName.length() && city.length() && sex.length() && age.length() && diagnosis.length()) { | |
Patient::Sex userSex = Patient::getSexByTitle(sex); | |
patient = new Patient(firstName, lastName, atoi(age.c_str()), userSex, city, diagnosis); | |
} | |
if (patient) { | |
if (repos->save(patient)) { | |
log("Patient successfully saved"); | |
return true; | |
} | |
else { | |
log("Patient couldn't be saved"); | |
} | |
} | |
else { | |
log("Please check your input"); | |
} | |
return false; | |
} | |
virtual bool update(Repository *repos) { | |
Patient *patient = nullptr; | |
string firstName, lastName, city, sex, diagnosis, age; | |
log("Update patient: "); | |
if (patient = (Patient*)findById(repos)) { | |
log("Patient found!"); | |
cout << "First Name: "; | |
getline(cin, firstName); | |
cout << "Last Name: "; | |
getline(cin, lastName); | |
cout << "City: "; | |
getline(cin, city); | |
cout << "Sex (male, female): "; | |
getline(cin, sex); | |
cout << "Age: "; | |
getline(cin, age); | |
cout << "Diagnosis: "; | |
getline(cin, diagnosis); | |
if (firstName.length()) { | |
patient->firstName = firstName; | |
} | |
if (lastName.length()) { | |
patient->lastName = lastName; | |
} | |
if (city.length()) { | |
patient->city = city; | |
} | |
if (sex.length()) { | |
Patient::Sex patientSex = Patient::getSexByTitle(sex); | |
patient->sex = patientSex; | |
} | |
if (age.length()) { | |
patient->age = atoi(age.c_str()); | |
} | |
if (diagnosis.length()) { | |
patient->diagnosis = diagnosis; | |
} | |
if (repos->save(patient)) { | |
log("Patient successfully updated"); | |
return true; | |
} | |
else { | |
log("Can't update Patient"); | |
} | |
} | |
else { | |
log("Patient not found!"); | |
} | |
return false; | |
} | |
virtual bool remove(Repository *repos) { | |
RepositoryObject *patient = nullptr; | |
log("Remove patient: "); | |
if (patient = findById(repos)) { | |
log("Patient found! Deleting..."); | |
if (repos->remove(patient)) { | |
log("Patient successfully deleted"); | |
return true; | |
} | |
else { | |
log("Can't delete patient"); | |
} | |
} | |
else { | |
log("Patient not found!"); | |
} | |
return false; | |
} | |
}; | |
class LoginManager { | |
private: | |
UserRepository *_repos; | |
unsigned int _attempts; | |
public: | |
LoginManager(UserRepository *repos, unsigned int attempts = 3) { | |
this->_repos = repos; | |
this->_attempts = attempts; | |
} | |
User* authorize() { | |
string login, password; | |
unsigned int maxLoginAttempts = _attempts; | |
do { | |
cout << endl << endl << "Please authorize!" << endl; | |
cout << endl << "Login: "; | |
getline(cin, login); | |
cout << "Password: "; | |
getline(cin, password); | |
if (login.length() && password.length()) { | |
if (User *user = _repos->getByLoginAndPassowrd(login, password)) { | |
return user; | |
} | |
else { | |
cout << endl << "User not found..."; | |
} | |
} | |
} while(maxLoginAttempts--); | |
return nullptr; | |
} | |
}; | |
class ProgramMenu { | |
private: | |
User *_currentUser; | |
unsigned int _state = 0; | |
int _userChoice() { | |
string userInput; | |
do { | |
cout << endl << "Your choice: "; | |
getline(cin, userInput); | |
} while(!userInput.length()); | |
try { | |
return stoi(userInput); | |
} | |
catch(const invalid_argument& ex) { | |
return -1; | |
} | |
} | |
bool _isUserAdmin() { | |
return _currentUser->role == User::admin; | |
} | |
public: | |
ProgramMenu(User *user) { | |
this->_currentUser = user; | |
} | |
int back(int state = 0) { | |
_state = state; | |
return step(); | |
} | |
int step() { | |
switch(_state) { | |
case 0: | |
return showStartMenu(); | |
case 1: | |
return showUsersManagement(); | |
case 2: | |
return showPatiaentsManagement(); | |
case 3: | |
return showPatiaentsListing(); | |
case 4: | |
return showSortMenu(); | |
default: | |
return -1; | |
} | |
} | |
int showStartMenu() { | |
_state = 0; | |
if (_isUserAdmin()) { | |
return showAdminMenu(); | |
} | |
else { | |
return showUserMenu(); | |
} | |
} | |
int showAdminMenu() { | |
cout << endl; | |
cout << "1. Users Management" << endl; | |
cout << "2. Patients Management" << endl; | |
cout << "3. Exit" << endl; | |
do { | |
int choice = _userChoice(); | |
switch(choice) { | |
case 1: | |
return showUsersManagement(); | |
case 2: | |
return showPatiaentsManagement(); | |
case 3: | |
return -1; | |
} | |
} while(true); | |
} | |
int showUserMenu() { | |
return showPatiaentsListing(); | |
} | |
int showUsersManagement() { | |
_state = 1; | |
cout << endl; | |
cout << "1. Show All Users" << endl; | |
cout << "2. Add User" << endl; | |
cout << "3. Update User" << endl; | |
cout << "4. Delete User" << endl; | |
cout << "5. Back" << endl; | |
do { | |
int choice = _userChoice(); | |
switch(choice) { | |
case 1: | |
return 11; | |
case 2: | |
return 12; | |
case 3: | |
return 13; | |
case 4: | |
return 14; | |
case 5: | |
return back(); | |
} | |
} while(true); | |
} | |
int showPatiaentsManagement() { | |
_state = 2; | |
cout << endl; | |
cout << "1. Patients Listing (Show All, Sort, Search)" << endl; | |
cout << "2. Add Patient" << endl; | |
cout << "3. Update Patient" << endl; | |
cout << "4. Delete Patient" << endl; | |
cout << "5. Back" << endl; | |
do { | |
int choice = _userChoice(); | |
switch(choice) { | |
case 1: | |
return showPatiaentsListing(); | |
case 2: | |
return 22; | |
case 3: | |
return 23; | |
case 4: | |
return 24; | |
case 5: | |
return back(); | |
} | |
} while(true); | |
} | |
int showPatiaentsListing() { | |
_state = 3; | |
cout << endl; | |
cout << "1. Show All Patients" << endl; | |
cout << "2. Show All Where city is not in {city}" << endl; | |
cout << "3. Show All Where diagnosis is {diagnosis} and age older than {age}" << endl; | |
cout << "4. Sort Menu" << endl; | |
if (_isUserAdmin()) { | |
cout << "5. Back" << endl; | |
} | |
else { | |
cout << "5. Exit" << endl; | |
} | |
do { | |
int choice = _userChoice(); | |
switch(choice) { | |
case 1: | |
return 31; | |
case 2: | |
return 32; | |
case 3: | |
return 33; | |
case 4: | |
return showSortMenu(); | |
case 5: | |
if (_isUserAdmin()) { | |
return back(2); | |
} | |
else { | |
return -1; | |
} | |
} | |
} while(true); | |
} | |
int showSortMenu() { | |
_state = 4; | |
cout << endl; | |
cout << "1. Sort By First Name" << endl; | |
cout << "2. Sort By Last Name" << endl; | |
cout << "3. Sort By Age" << endl; | |
cout << "4. Sort By City" << endl; | |
cout << "5. Back" << endl; | |
do { | |
int choice = _userChoice(); | |
switch(choice) { | |
case 1: | |
return 41; | |
case 2: | |
return 42; | |
case 3: | |
return 43; | |
case 4: | |
return 44; | |
case 5: | |
return back(3); | |
} | |
} while(true); | |
} | |
}; | |
void seedPatients(PatientRepository *repos) { | |
cout << endl << "Creating default patients..."; | |
repos->save(new Patient("Vasilii", "Vasilev", 21, Patient::male, "Vasilevsk", "atit")); | |
repos->save(new Patient("Petr", "Petrov", 22, Patient::male, "Petrovsk", "schizophrenia")); | |
repos->save(new Patient("Bred", "Bredovich", 20, Patient::male, "Vasilevsk", "atit")); | |
repos->save(new Patient("Ekaterina", "Lopireva", 19, Patient::female, "Minsk", "cancer")); | |
repos->save(new Patient("Graf", "Drakula", 18, Patient::male, "Norilsk", "schizophrenia")); | |
repos->save(new Patient("Yura", "Ermakovich", 16, Patient::male, "Minsk", "psyhozis")); | |
} | |
void seedUsers(UserRepository *repos) { | |
cout << endl << "Creating default users..."; | |
repos->save(new User("admin", "password", User::admin)); | |
repos->save(new User("user", "password", User::user)); | |
} | |
void showAllWhereCityNotIn(TableView *view, PatientRepository *repos) { | |
string city; | |
do { | |
cout << endl << "Enter City: "; | |
getline(cin, city); | |
} while(!city.length()); | |
vector<RepositoryObject*> patients = repos->getAllWhereCityNot(city); | |
view->display(patients); | |
} | |
// функция показать все где диагноз и возраст | |
// функция принимает на вход view - указатель на объект который помогает рисовать в консольке таблицу юзеров | |
// и репазиторий (хранилище) пациентов - там где * это всегда указатель на какой-то объект | |
// указатель это такой типа данных, типа как ярлык на рабочем столе | |
void showAllWhereDiagnosisAndAge(TableView *view, PatientRepository *repos) { | |
// инициализируем переменные вспомогательные | |
string age, diagnosis; | |
int userAge = -1; | |
// цикл ввода диагноза с клавиатуры | |
do { | |
cout << endl << "Enter Diagnosis: "; //говорим что надо ввести | |
getline(cin, diagnosis);//вводим (заполняем переменную-буфер) | |
} while(!diagnosis.length()); //выходим из цикла только тогда когда что-то введено - т.е. когда длинна строки НЕ равно НУЛЮ | |
// тоже самое но для возраста, цикл ввода возраста | |
do { | |
cout << endl << "Enter Age: "; | |
getline(cin, age); | |
// все что вводится с клавиатуры изначально это строка, | |
//т.к. возраст это число, мы должны сконвертировать строку скажем "21" в число 21 | |
try { | |
userAge = stoi(age); //конвертируем | |
} | |
catch(const invalid_argument& ex) { //если конвертация невозможно, например ты ввел asdfaskjdlfha то возникаем ошибка конвертации, | |
// отлавливаем это исключение и чистим переменную-буфер, длинна строки становится равной нулю | |
age.clear(); | |
} | |
} while(!age.length()); //выходим из цикла когда в строке что-то есть, если была ошлибка - строка чиститься и ввод начинается сначала | |
//когда ввод диагноза и конвертация возраста завершены мы можем начать поиск в хранилище пациентов | |
//ищи продолжение в методе getAllWhereDiagnosisAndAge | |
vector<RepositoryObject*> patients = repos->getAllWhereDiagnosisAndAge(diagnosis, userAge); | |
//выводим таблицу пациентов на экран | |
view->display(patients); | |
} | |
int main(int argc, char** argv) { | |
SQLManager *db = new SQLManager("database.db"); | |
PatientRepository *patientsRepos = new PatientRepository(db); | |
UserRepository *usersRepos = new UserRepository(db); | |
// create some default patients | |
if (patientsRepos->getAll().size() == 0) { | |
seedPatients(patientsRepos); | |
} | |
// create default users | |
if (usersRepos->getAll().size() == 0) { | |
seedUsers(usersRepos); | |
} | |
LoginManager *manager = new LoginManager(usersRepos); | |
User *currentUser = manager->authorize(); | |
UsersView *usersView = new UsersView(); | |
PatientsView *patientsView = new PatientsView(); | |
if (currentUser) { | |
bool exit = false; | |
ProgramMenu *menu = new ProgramMenu(currentUser); | |
while(!exit) { | |
int step = menu->step(); | |
switch(step) { | |
case -1: | |
exit = true; | |
break; | |
case 11: // Show All Users | |
usersView->display(usersRepos->getAll()); | |
break; | |
case 12: // Add User | |
usersView->add(usersRepos); | |
break; | |
case 13: // Update User | |
usersView->update(usersRepos); | |
break; | |
case 14: // Remove User | |
usersView->remove(usersRepos); | |
break; | |
case 22: // Add Patient | |
patientsView->add(patientsRepos); | |
break; | |
case 23: // Update Patient | |
patientsView->update(patientsRepos); | |
break; | |
case 24: // Remove Patient | |
patientsView->remove(patientsRepos); | |
break; | |
case 31: // Show All Patients | |
patientsView->display(patientsRepos->getAll()); | |
break; | |
case 32: // Show All Where City is not in | |
showAllWhereCityNotIn(patientsView, patientsRepos); | |
break; | |
case 33: // Show All Where Diagnosis and Age | |
showAllWhereDiagnosisAndAge(patientsView, patientsRepos); | |
break; | |
case 41: // Sort by first name | |
patientsView->display(patientsRepos->getAllSortedBy("firstName")); | |
break; | |
case 42: // Sort by last name | |
patientsView->display(patientsRepos->getAllSortedBy("lastName")); | |
break; | |
case 43: // Sort by age name | |
patientsView->display(patientsRepos->getAllSortedBy("age")); | |
break; | |
case 44: // Sort by city name | |
patientsView->display(patientsRepos->getAllSortedBy("city")); | |
break; | |
} | |
} | |
} | |
else { | |
cout << endl << "Authorization failed. Exiting..."; | |
} | |
delete patientsRepos; | |
delete usersRepos; | |
delete db; | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment