Skip to content

Instantly share code, notes, and snippets.

@elja
Created June 1, 2016 10:03
Show Gist options
  • Save elja/8aa80fe557f6210ae0f396065ff08f52 to your computer and use it in GitHub Desktop.
Save elja/8aa80fe557f6210ae0f396065ff08f52 to your computer and use it in GitHub Desktop.
#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