Advertisement
Guest User

Untitled

a guest
Jun 1st, 2016
109
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 32.40 KB | None | 0 0
  1. #include <iostream>
  2. #include <iomanip>
  3. #include <stdexcept>
  4. #include <vector>
  5. #include <cstdlib>
  6. #include <sstream>
  7. #include <cstring>
  8. #include <algorithm>
  9.  
  10. using namespace std;
  11.  
  12. #include "sqltools.h"
  13. #include "repository_object.h"
  14. #include "repository.h"
  15.  
  16. // ---------------- MODELS -------------------- //
  17.  
  18. class User : public RepositoryObject {
  19. public:
  20. enum Role { admin, user };
  21. static const char* roleTitles[];
  22.  
  23. string login;
  24. string password;
  25. Role role;
  26.  
  27. public:
  28. User() : RepositoryObject() {
  29.  
  30. }
  31.  
  32. User(const string login, const string password, const Role role) : RepositoryObject() {
  33. this->login = login;
  34. this->password = password;
  35. this->role = role;
  36. }
  37.  
  38. const char* roleTitle() {
  39. return User::roleTitles[role];
  40. }
  41.  
  42. static Role getRoleByTitle(const string title) {
  43. return User::getRoleByTitle(title.c_str());
  44. }
  45.  
  46. static Role getRoleByTitle(const char* title) {
  47. if (strcmp(title, "admin") == 0) {
  48. return Role::admin;
  49. }
  50.  
  51. if (strcmp(title, "user") == 0) {
  52. return Role::user;
  53. }
  54.  
  55. return (Role)-1;
  56. }
  57.  
  58. virtual bool isValid() {
  59. if (login.length() && password.length() && (role == user || role == admin)) {
  60. return true;
  61. }
  62.  
  63. return false;
  64. }
  65.  
  66. protected:
  67. virtual RepositoryObject* setAttribute(const char *attrName, const char *attrValue) {
  68. if (strcmp(attrName, "login") == 0) {
  69. this->login = attrValue;
  70. }
  71. else if (strcmp(attrName, "password") == 0) {
  72. this->password = attrValue;
  73. }
  74. else if (strcmp(attrName, "role") == 0) {
  75. this->role = (Role)_atoi64(attrValue);
  76. }
  77.  
  78. return RepositoryObject::setAttribute(attrName, attrValue);
  79. }
  80. };
  81.  
  82. class Patient : public RepositoryObject {
  83. public:
  84. enum Sex { male, female };
  85. static const char* sexTitles[];
  86.  
  87. string firstName;
  88. string lastName;
  89.  
  90. string city;
  91. string diagnosis;
  92.  
  93. int age;
  94. Sex sex;
  95.  
  96. public:
  97. Patient() : RepositoryObject() {
  98.  
  99. }
  100.  
  101. Patient(const string firstName, const string lastName, const int age, Sex sex, const string city, const string diagnosis) : RepositoryObject() {
  102. this->firstName = firstName;
  103. this->lastName = lastName;
  104. this->age = age;
  105. this->sex = sex;
  106. this->city = city;
  107. this->diagnosis = diagnosis;
  108. }
  109.  
  110. const char* sexTitle() {
  111. return sexTitles[sex];
  112. }
  113.  
  114. static Sex getSexByTitle(const string title) {
  115. return Patient::getSexByTitle(title.c_str());
  116. }
  117.  
  118. static Sex getSexByTitle(const char* title) {
  119. if (strcmp(title, "male") == 0) {
  120. return Sex::male;
  121. }
  122.  
  123. if (strcmp(title, "female") == 0) {
  124. return Sex::female;
  125. }
  126.  
  127. return (Sex)-1;
  128. }
  129.  
  130. bool isValid() {
  131. if (firstName.length() && lastName.length() && city.length() && diagnosis.length() && age > 0 && (sex == male || sex == female))
  132. return true;
  133.  
  134. return false;
  135. }
  136.  
  137. protected:
  138. RepositoryObject* setAttribute(const char *attrName, const char *attrValue) {
  139. if (strcmp(attrName, "lastName") == 0) {
  140. this->lastName = attrValue;
  141. }
  142. else if (strcmp(attrName, "firstName") == 0) {
  143. this->firstName = attrValue;
  144. }
  145. else if (strcmp(attrName, "age") == 0) {
  146. this->age = strtoul(attrValue, NULL, 0);
  147. }
  148. else if (strcmp(attrName,"sex") == 0) {
  149. this->sex = (Sex)strtoul(attrValue, NULL, 0);
  150. }
  151. else if (strcmp(attrName, "city") == 0) {
  152. this->city = attrValue;
  153. }
  154. else if (strcmp(attrName, "diagnosis") == 0) {
  155. this->diagnosis = attrValue;
  156. }
  157.  
  158. return RepositoryObject::setAttribute(attrName, attrValue);
  159. }
  160. };
  161.  
  162. // ------------ STATIC INITIALIZATION -------- //
  163.  
  164. const char* User::roleTitles[] = { "admin", "user" };
  165. const char* Patient::sexTitles[] = { "male", "female" };
  166.  
  167. // ------------- REPOSITORIES --------------- //
  168.  
  169. class UserRepository : public Repository {
  170. public:
  171. UserRepository(SQLManager *db) : Repository(db) {
  172. _createSchema();
  173. }
  174.  
  175. User* getByLoginAndPassowrd(const string login, const string password) {
  176. string queryStr = "SELECT * FROM " + _getTableName() + " WHERE login = ? AND password = ?;";
  177. SQLQuery *query = dbManager->prepareQuery(queryStr.c_str());
  178.  
  179. query->setTextParam(1, login);
  180. query->setTextParam(2, password);
  181.  
  182. vector<RepositoryObject*> objects = fillInObjects(dbManager->selectQuery(query));
  183. return objects.size() == 1 ? (User*)objects[0] : nullptr;
  184. }
  185.  
  186. protected:
  187. virtual RepositoryObject* _initNewRecord() {
  188. return new User();
  189. }
  190.  
  191. virtual string _getTableName() {
  192. return "users";
  193. }
  194.  
  195. virtual vector<string> _getColumnNames() {
  196. return { "id", "login", "password", "role" };
  197. }
  198.  
  199. //реализация метода вставки нового пользователя у класса хранилища пользователя
  200. //принимает в себя объект с аттрибудами
  201. virtual bool _insertRecord(RepositoryObject *object) {
  202. //тут уже полиморфизм не прокатит, нам нужно работать с конкретными аттрибутами класса, поэтому преобразовываем базовый класс в его непосредственную реализацию
  203. User *user = (User*)object;
  204. //формирем запрос вставки, как и прежде вопросики это параметры (можно было сделать также через + как с _getTableName, просто так безопаснее)
  205. SQLQuery *query = dbManager->prepareQuery("INSERT INTO " + _getTableName() + " (login, password, role) VALUES (?, ?, ?);");
  206.  
  207. query->setTextParam(1, user->login); //сетаем на первый вопросик логине
  208. query->setTextParam(2, user->password); //на второй пассворс
  209. query->setIntParam(3, user->role); //на третий роль, т.е. роль типа enum, а enum это грубо говоря хранится как цифра, то использем метод для установки числового параметра
  210.  
  211. // вызываем библиотечную функцию которая исполняет SQL в базе данных, возращает true если всё ок, если не прокатило то false.
  212. return _insertSQL(object, query);
  213. }
  214.  
  215.  
  216. // тож самое что и выше, только другой запрос - на обновление
  217. virtual bool _updateRecord(RepositoryObject *object) {
  218. User *user = (User*)object;
  219. SQLQuery *query = dbManager->prepareQuery("UPDATE " + _getTableName() + " SET login=?, password=?, role=? WHERE id=?;");
  220.  
  221. query->setTextParam(1, user->login);
  222. query->setTextParam(2, user->password);
  223. query->setIntParam(3, user->role);
  224. query->setIntParam(4, user->getID());
  225.  
  226. return _execSQL(query);
  227. };
  228.  
  229. virtual void _createSchema() {
  230. string tableSchemaQuery =
  231. "CREATE TABLE IF NOT EXISTS " + _getTableName() + " (\
  232. id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, \
  233. login VARCHAR(255) UNIQUE NOT NULL, \
  234. password VARCHAR(255) NOT NULL, \
  235. role INTEGER NOT NULL \
  236. );";
  237.  
  238. return _createSQLSchema(tableSchemaQuery);
  239. }
  240. };
  241.  
  242. class PatientRepository : public Repository {
  243. public:
  244. PatientRepository(SQLManager *db) : Repository(db) {
  245. _createSchema();
  246. }
  247.  
  248. vector<RepositoryObject*> getAllSortedBy(string attrName) {
  249. SQLQuery *query = dbManager->prepareQuery("SELECT * FROM " + _getTableName() + " ORDER BY " + attrName + " COLLATE NOCASE;");
  250. return fillInObjects(dbManager->selectQuery(query));
  251. }
  252.  
  253. //метод хранилища пациентов для поиска по диагнозу и возрасту, принимает строку диагноза и цифру возраста
  254. vector<RepositoryObject*> getAllWhereDiagnosisAndAge(string diagnosis, int age) {
  255. //формируем строку запроса в базу данных - это SQL код
  256. //dbManager это наш самопальный библиотечный класс, помогает работать с SQL и базой данный SQLITE3
  257. //На выходе это *query должен содержать строку запроса и всякую вспомогательную и не интересную нам ерунду для SQLITE3
  258. //Запрос будет выглядеть типа так SELECT * FROM patients WHERE diagnosis = 'анемия' AND age > 21
  259. //Где стоят вопросики в строке это места для параметров, что бы их установить используется индекс их позиций
  260. //Для первого вопросика индекс - 1, для второго - 2, для третьего - 3 и так далее
  261. SQLQuery *query = dbManager->prepareQuery("SELECT * FROM " + _getTableName() + " WHERE diagnosis = ? AND age > ?;");
  262.  
  263. //Устанавливаем значение параметра 1, т.к. он у нас текстовый используем setTextParam
  264. //Этот вызов грубо говоря должен внутри запроса вместо diagnosis = ? сделать diagnosis = 'анемия'
  265. //Короче подставить вместо ? значение из переменной diagnosis
  266. query->setTextParam(1, diagnosis);
  267.  
  268. //тож самое но для числового возраста
  269. query->setIntParam(2, age);
  270.  
  271. //выполняем получившийся запрос в базу данных, получаем данные из базы и вызываем/отправляем эти данные в метод fillInObjects
  272. //дальше описание смотри в методе fillInObjects - он описан в другом файле -repository.h
  273. return fillInObjects(dbManager->selectQuery(query));
  274. }
  275.  
  276. vector<RepositoryObject*> getAllWhereCityNot(string city) {
  277. SQLQuery *query = dbManager->prepareQuery("SELECT * FROM " + _getTableName() + " WHERE city != ? COLLATE NOCASE;");
  278. query->setTextParam(1, city);
  279.  
  280. return fillInObjects(dbManager->selectQuery(query));
  281. }
  282.  
  283. protected:
  284. virtual RepositoryObject* _initNewRecord() {
  285. return new Patient();
  286. }
  287.  
  288. virtual string _getTableName() {
  289. return "patients";
  290. }
  291. virtual vector<string> _getColumnNames() {
  292. return { "id", "firstName", "lastName", "age", "sex", "city", "diagnosis" };
  293. }
  294.  
  295. virtual bool _insertRecord(RepositoryObject *object) {
  296. SQLQuery *query = dbManager->prepareQuery("INSERT INTO " + _getTableName() + " (firstName, lastName, age, sex, city, diagnosis) VALUES (?, ?, ?, ?, ?, ?);");
  297. Patient *patient = (Patient*)object;
  298.  
  299. query->setTextParam(1, patient->firstName);
  300. query->setTextParam(2, patient->lastName);
  301. query->setIntParam(3, patient->age);
  302. query->setIntParam(4, patient->sex);
  303. query->setTextParam(5, patient->city);
  304. query->setTextParam(6, patient->diagnosis);
  305.  
  306. return _insertSQL(object, query);
  307. }
  308.  
  309. virtual bool _updateRecord(RepositoryObject *object) {
  310. Patient *patient = (Patient*)object;
  311. SQLQuery *query = dbManager->prepareQuery("UPDATE " + _getTableName() + " SET firstName=?, lastName=?, age=?, sex=?, city=?, diagnosis=? WHERE id=?;");
  312.  
  313. query->setTextParam(1, patient->firstName);
  314. query->setTextParam(2, patient->lastName);
  315. query->setIntParam(3, patient->age);
  316. query->setIntParam(4, patient->sex);
  317. query->setTextParam(5, patient->city);
  318. query->setTextParam(6, patient->diagnosis);
  319. query->setIntParam(7, patient->getID());
  320.  
  321. return _execSQL(query);
  322. };
  323.  
  324. virtual void _createSchema() {
  325. string tableSchemaQuery =
  326. "CREATE TABLE IF NOT EXISTS " + _getTableName() + " (\
  327. id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, \
  328. firstName VARCHAR(255) NOT NULL, \
  329. lastName VARCHAR(255) NOT NULL, \
  330. age INTEGER NOT NULL DEFAULT 0, \
  331. sex VARCHAR(10) NOT NULL, \
  332. city VARCHAR(50) NOT NULL, \
  333. diagnosis VARCHAR(255) NOT NULL \
  334. );";
  335.  
  336. return _createSQLSchema(tableSchemaQuery);
  337. }
  338. };
  339.  
  340. class TableView {
  341. protected:
  342. vector<int> _colsWidth;
  343.  
  344. static void consoleClear() {
  345. system("cls");
  346. }
  347.  
  348. virtual void displayRow(RepositoryObject* object) = 0;
  349. virtual void displayHeader() = 0;
  350.  
  351. template<typename T> void displayCell(int index, T t) {
  352. cout << "|" << setw(_colsWidth[index]) << t;
  353. }
  354.  
  355. void displayEndRow() {
  356. cout << "|" << endl;
  357. }
  358.  
  359. void displayLast() {
  360. stringstream buff;
  361.  
  362. buff << "|";
  363. for(int i = 0; i < _colsWidth.size(); i++) {
  364. buff << string(_colsWidth[i], '-');
  365.  
  366. if (i + 1 != _colsWidth.size())
  367. buff << '-';
  368. }
  369. buff << "|";
  370.  
  371. cout << buff.str() << endl;
  372. }
  373.  
  374. void log(string logText) {
  375. cout << endl << endl << logText << endl;
  376. }
  377.  
  378. public:
  379. TableView(const vector<int> colsWidth) {
  380. _colsWidth = colsWidth;
  381. }
  382.  
  383. ~TableView() {
  384.  
  385. }
  386.  
  387. virtual RepositoryObject* findById(Repository *repos) = 0;
  388. virtual bool add(Repository *repos) = 0;
  389. virtual bool remove(Repository *repos) = 0;
  390. virtual bool update(Repository *repos) = 0;
  391.  
  392. void display(vector<RepositoryObject*> objects, bool clear = true) {
  393. if (clear) {
  394. TableView::consoleClear();
  395. }
  396.  
  397. displayHeader();
  398. displayLast();
  399.  
  400. if (objects.size() > 0) {
  401. for(int i = 0; i < objects.size(); i++) {
  402. displayRow(objects[i]);
  403. }
  404.  
  405. }
  406.  
  407. displayLast();
  408. }
  409. };
  410.  
  411. class UsersView : public TableView {
  412. private:
  413. virtual void displayRow(RepositoryObject* object) {
  414. User *user = (User*)object;
  415. int colIndex = 0;
  416.  
  417. displayCell(colIndex++, user->getID());
  418. displayCell(colIndex++, user->login);
  419. displayCell(colIndex++, user->password);
  420. displayCell(colIndex++, user->roleTitle());
  421.  
  422. displayEndRow();
  423. };
  424.  
  425. virtual void displayHeader() {
  426. int colIndex = 0;
  427.  
  428. displayCell(colIndex++, "ID");
  429. displayCell(colIndex++, "Login");
  430. displayCell(colIndex++, "Password");
  431. displayCell(colIndex++, "Role");
  432.  
  433. displayEndRow();
  434. };
  435.  
  436. public:
  437. UsersView() : TableView({3, 20, 20, 5}) {
  438.  
  439. }
  440.  
  441. virtual RepositoryObject* findById(Repository* repos) {
  442. RepositoryObject *user = nullptr;
  443. string userID;
  444.  
  445. cout << endl << "User ID: ";
  446. getline(cin, userID);
  447.  
  448. if (userID.length()){
  449. row_id id = _atoi64(userID.c_str());
  450. user = repos->getById(id);
  451. }
  452.  
  453. return user;
  454. }
  455.  
  456. //добавление нового пользователя
  457. //что бы лучше понимать в голове просто представить себе 3 типа классов
  458. //1) класс данных который хранится - обычно их называют Model
  459. //2) класс хранилища (Repasitory) он реализует все методы о том как сохранить, удалить, выбрать Model
  460. //3) класс отображения (View) - он занимается взаимодействием с пользователем
  461. // сейчас мы в классе типа View
  462.  
  463. //метод добавления нового пользователя, принимает в себя хранилище пользователей что бы потом в него сохранить
  464. virtual bool add(Repository *repos) {
  465. //подготавливаем переменные
  466. User *user = nullptr;
  467. string login, password, role;
  468.  
  469. //говорим что мы счя делаем
  470. log("Add new user: ");
  471.  
  472. cout << "Login: ";
  473. getline(cin, login); //все как обычно говорим что ввести и вводим
  474.  
  475. cout << "Password: ";
  476. getline(cin, password);
  477.  
  478. cout << "Role (admin, user): ";
  479. getline(cin, role);
  480.  
  481. // проверям все ли мы ввели, все ли строки не пустые
  482. if (login.length() && password.length() && role.length()) {
  483. //пытаемся найти роль по её имени, роли у нас хранятся как enum
  484. //enum это такой тип данных который используется для перечисления какиех-то константных штук
  485. //грубо говоря метод ниже просто преобразовывает строку 'admin' в типа данных enum со значением admin
  486. User::Role userRole = User::getRoleByTitle(role);
  487.  
  488. //создаем нового пользователя с логин пароль роль которые мы ввели
  489. user = new User(login, password, userRole);
  490. }
  491.  
  492. //если мы ничего не введем то и условие выше не выполнится, а следовательно и пользователя не будет создано,
  493. //поэтому проверям, смогли ли мы инициализировать нового пользователя
  494. if (user) {
  495. //смогли инициализировать, теперь пробуем сохранить (записать) в хранилище
  496. //если метод save вернет true то смогли записать, если фолс, то не смогли
  497. //дальше смотри метод save в repository.h
  498. if (repos->save(user)) {
  499. log("User successfully saved");
  500. return true;
  501. }
  502. else {
  503. log("User couldn't be saved");
  504. }
  505. }
  506. else {
  507. //не смогли, говорим об этом
  508. log("Please check your input");
  509. }
  510.  
  511. return false;
  512. }
  513.  
  514. virtual bool remove(Repository *repos) {
  515. RepositoryObject *user = nullptr;
  516.  
  517. log("Remove user: ");
  518.  
  519. if (user = findById(repos)) {
  520. log("User found! Deleting...");
  521.  
  522. if (repos->remove(user)) {
  523. log("User successfully deleted");
  524. return true;
  525. }
  526. else {
  527. log("Can't delete user");
  528. }
  529. }
  530. else {
  531. log("User not found!");
  532. }
  533.  
  534. return false;
  535. }
  536.  
  537. virtual bool update(Repository *repos) {
  538. User *user = nullptr;
  539. string login, password, role;
  540.  
  541. log("Update user: ");
  542.  
  543. if (user = (User*)findById(repos)) {
  544. log("User found!");
  545.  
  546. cout << "Login: ";
  547. getline(cin, login);
  548.  
  549. cout << "Password: ";
  550. getline(cin, password);
  551.  
  552. cout << "Role (admin, user): ";
  553. getline(cin, role);
  554.  
  555. if (login.length()) {
  556. user->login = login;
  557. }
  558.  
  559. if (password.length()) {
  560. user->password = password;
  561. }
  562.  
  563. if (role.length()) {
  564. User::Role userRole = User::getRoleByTitle(role);
  565. user->role = userRole;
  566. }
  567.  
  568. if (repos->save(user)) {
  569. log("User successfully updated");
  570. return true;
  571. }
  572. else {
  573. log("Can't update user");
  574. }
  575. }
  576. else {
  577. log("User not found!");
  578. }
  579.  
  580. return false;
  581. }
  582. };
  583.  
  584. class PatientsView : public TableView {
  585. private:
  586. virtual void displayRow(RepositoryObject* object) {
  587. Patient *patient = (Patient*)object;
  588. int colIndex = 0;
  589.  
  590. displayCell(colIndex++, patient->getID());
  591. displayCell(colIndex++, patient->firstName);
  592. displayCell(colIndex++, patient->lastName);
  593. displayCell(colIndex++, patient->age);
  594. displayCell(colIndex++, patient->sexTitle());
  595. displayCell(colIndex++, patient->city);
  596. displayCell(colIndex++, patient->diagnosis);
  597.  
  598. displayEndRow();
  599. };
  600.  
  601. virtual void displayHeader() {
  602. int colIndex = 0;
  603.  
  604. displayCell(colIndex++, "ID");
  605. displayCell(colIndex++, "First Name");
  606. displayCell(colIndex++, "Last Name");
  607. displayCell(colIndex++, "Age");
  608. displayCell(colIndex++, "Sex");
  609. displayCell(colIndex++, "City");
  610. displayCell(colIndex++, "Diagnosis");
  611.  
  612. displayEndRow();
  613. };
  614.  
  615. public:
  616. PatientsView() : TableView({ 3, 13, 13, 3, 6, 15, 15 }) {
  617.  
  618. }
  619.  
  620. virtual RepositoryObject* findById(Repository* repos) {
  621. RepositoryObject *patient = nullptr;
  622. string patientID;
  623.  
  624. cout << endl << "Patient ID: ";
  625. getline(cin, patientID);
  626.  
  627. if (patientID.length()){
  628. row_id id = _atoi64(patientID.c_str());
  629. patient = repos->getById(id);
  630. }
  631.  
  632. return patient;
  633. }
  634.  
  635. virtual bool add(Repository *repos) {
  636. Patient *patient = nullptr;
  637. string firstName, lastName, city, sex, diagnosis, age;
  638.  
  639. log("Add new patient: ");
  640.  
  641. cout << "First Name: ";
  642. getline(cin, firstName);
  643.  
  644. cout << "Last Name: ";
  645. getline(cin, lastName);
  646.  
  647. cout << "City: ";
  648. getline(cin, city);
  649.  
  650. cout << "Sex (male, female): ";
  651. getline(cin, sex);
  652.  
  653. cout << "Age: ";
  654. getline(cin, age);
  655.  
  656. cout << "Diagnosis: ";
  657. getline(cin, diagnosis);
  658.  
  659. if (firstName.length() && lastName.length() && city.length() && sex.length() && age.length() && diagnosis.length()) {
  660. Patient::Sex userSex = Patient::getSexByTitle(sex);
  661. patient = new Patient(firstName, lastName, atoi(age.c_str()), userSex, city, diagnosis);
  662. }
  663.  
  664. if (patient) {
  665. if (repos->save(patient)) {
  666. log("Patient successfully saved");
  667. return true;
  668. }
  669. else {
  670. log("Patient couldn't be saved");
  671. }
  672. }
  673. else {
  674. log("Please check your input");
  675. }
  676.  
  677. return false;
  678. }
  679.  
  680. virtual bool update(Repository *repos) {
  681. Patient *patient = nullptr;
  682. string firstName, lastName, city, sex, diagnosis, age;
  683.  
  684. log("Update patient: ");
  685.  
  686. if (patient = (Patient*)findById(repos)) {
  687. log("Patient found!");
  688.  
  689. cout << "First Name: ";
  690. getline(cin, firstName);
  691.  
  692. cout << "Last Name: ";
  693. getline(cin, lastName);
  694.  
  695. cout << "City: ";
  696. getline(cin, city);
  697.  
  698. cout << "Sex (male, female): ";
  699. getline(cin, sex);
  700.  
  701. cout << "Age: ";
  702. getline(cin, age);
  703.  
  704. cout << "Diagnosis: ";
  705. getline(cin, diagnosis);
  706.  
  707. if (firstName.length()) {
  708. patient->firstName = firstName;
  709. }
  710.  
  711. if (lastName.length()) {
  712. patient->lastName = lastName;
  713. }
  714.  
  715. if (city.length()) {
  716. patient->city = city;
  717. }
  718.  
  719. if (sex.length()) {
  720. Patient::Sex patientSex = Patient::getSexByTitle(sex);
  721. patient->sex = patientSex;
  722. }
  723.  
  724. if (age.length()) {
  725. patient->age = atoi(age.c_str());
  726. }
  727.  
  728. if (diagnosis.length()) {
  729. patient->diagnosis = diagnosis;
  730. }
  731.  
  732. if (repos->save(patient)) {
  733. log("Patient successfully updated");
  734. return true;
  735. }
  736. else {
  737. log("Can't update Patient");
  738. }
  739. }
  740. else {
  741. log("Patient not found!");
  742. }
  743.  
  744. return false;
  745. }
  746.  
  747. virtual bool remove(Repository *repos) {
  748. RepositoryObject *patient = nullptr;
  749.  
  750. log("Remove patient: ");
  751.  
  752. if (patient = findById(repos)) {
  753. log("Patient found! Deleting...");
  754.  
  755. if (repos->remove(patient)) {
  756. log("Patient successfully deleted");
  757. return true;
  758. }
  759. else {
  760. log("Can't delete patient");
  761. }
  762. }
  763. else {
  764. log("Patient not found!");
  765. }
  766.  
  767. return false;
  768. }
  769. };
  770.  
  771. class LoginManager {
  772. private:
  773. UserRepository *_repos;
  774. unsigned int _attempts;
  775.  
  776. public:
  777. LoginManager(UserRepository *repos, unsigned int attempts = 3) {
  778. this->_repos = repos;
  779. this->_attempts = attempts;
  780. }
  781.  
  782. User* authorize() {
  783. string login, password;
  784. unsigned int maxLoginAttempts = _attempts;
  785.  
  786. do {
  787. cout << endl << endl << "Please authorize!" << endl;
  788. cout << endl << "Login: ";
  789. getline(cin, login);
  790.  
  791. cout << "Password: ";
  792. getline(cin, password);
  793.  
  794. if (login.length() && password.length()) {
  795. if (User *user = _repos->getByLoginAndPassowrd(login, password)) {
  796. return user;
  797. }
  798. else {
  799. cout << endl << "User not found...";
  800. }
  801. }
  802.  
  803. } while(maxLoginAttempts--);
  804.  
  805. return nullptr;
  806. }
  807. };
  808.  
  809. class ProgramMenu {
  810. private:
  811. User *_currentUser;
  812. unsigned int _state = 0;
  813.  
  814. int _userChoice() {
  815. string userInput;
  816.  
  817. do {
  818. cout << endl << "Your choice: ";
  819. getline(cin, userInput);
  820. } while(!userInput.length());
  821.  
  822. try {
  823. return stoi(userInput);
  824. }
  825. catch(const invalid_argument& ex) {
  826. return -1;
  827. }
  828. }
  829.  
  830. bool _isUserAdmin() {
  831. return _currentUser->role == User::admin;
  832. }
  833.  
  834. public:
  835. ProgramMenu(User *user) {
  836. this->_currentUser = user;
  837. }
  838.  
  839. int back(int state = 0) {
  840. _state = state;
  841. return step();
  842. }
  843.  
  844. int step() {
  845. switch(_state) {
  846. case 0:
  847. return showStartMenu();
  848. case 1:
  849. return showUsersManagement();
  850. case 2:
  851. return showPatiaentsManagement();
  852. case 3:
  853. return showPatiaentsListing();
  854. case 4:
  855. return showSortMenu();
  856. default:
  857. return -1;
  858. }
  859. }
  860.  
  861. int showStartMenu() {
  862. _state = 0;
  863.  
  864. if (_isUserAdmin()) {
  865. return showAdminMenu();
  866. }
  867. else {
  868. return showUserMenu();
  869. }
  870. }
  871.  
  872. int showAdminMenu() {
  873. cout << endl;
  874. cout << "1. Users Management" << endl;
  875. cout << "2. Patients Management" << endl;
  876. cout << "3. Exit" << endl;
  877.  
  878. do {
  879. int choice = _userChoice();
  880. switch(choice) {
  881. case 1:
  882. return showUsersManagement();
  883. case 2:
  884. return showPatiaentsManagement();
  885. case 3:
  886. return -1;
  887. }
  888. } while(true);
  889. }
  890.  
  891. int showUserMenu() {
  892. return showPatiaentsListing();
  893. }
  894.  
  895. int showUsersManagement() {
  896. _state = 1;
  897.  
  898. cout << endl;
  899. cout << "1. Show All Users" << endl;
  900. cout << "2. Add User" << endl;
  901. cout << "3. Update User" << endl;
  902. cout << "4. Delete User" << endl;
  903. cout << "5. Back" << endl;
  904.  
  905. do {
  906. int choice = _userChoice();
  907. switch(choice) {
  908. case 1:
  909. return 11;
  910. case 2:
  911. return 12;
  912. case 3:
  913. return 13;
  914. case 4:
  915. return 14;
  916. case 5:
  917. return back();
  918. }
  919. } while(true);
  920. }
  921.  
  922. int showPatiaentsManagement() {
  923. _state = 2;
  924.  
  925. cout << endl;
  926. cout << "1. Patients Listing (Show All, Sort, Search)" << endl;
  927. cout << "2. Add Patient" << endl;
  928. cout << "3. Update Patient" << endl;
  929. cout << "4. Delete Patient" << endl;
  930. cout << "5. Back" << endl;
  931.  
  932. do {
  933. int choice = _userChoice();
  934. switch(choice) {
  935. case 1:
  936. return showPatiaentsListing();
  937. case 2:
  938. return 22;
  939. case 3:
  940. return 23;
  941. case 4:
  942. return 24;
  943. case 5:
  944. return back();
  945. }
  946. } while(true);
  947. }
  948.  
  949. int showPatiaentsListing() {
  950. _state = 3;
  951.  
  952. cout << endl;
  953. cout << "1. Show All Patients" << endl;
  954. cout << "2. Show All Where city is not in {city}" << endl;
  955. cout << "3. Show All Where diagnosis is {diagnosis} and age older than {age}" << endl;
  956. cout << "4. Sort Menu" << endl;
  957.  
  958. if (_isUserAdmin()) {
  959. cout << "5. Back" << endl;
  960. }
  961. else {
  962. cout << "5. Exit" << endl;
  963. }
  964.  
  965. do {
  966. int choice = _userChoice();
  967. switch(choice) {
  968. case 1:
  969. return 31;
  970. case 2:
  971. return 32;
  972. case 3:
  973. return 33;
  974. case 4:
  975. return showSortMenu();
  976. case 5:
  977. if (_isUserAdmin()) {
  978. return back(2);
  979. }
  980. else {
  981. return -1;
  982. }
  983. }
  984. } while(true);
  985. }
  986.  
  987. int showSortMenu() {
  988. _state = 4;
  989.  
  990. cout << endl;
  991. cout << "1. Sort By First Name" << endl;
  992. cout << "2. Sort By Last Name" << endl;
  993. cout << "3. Sort By Age" << endl;
  994. cout << "4. Sort By City" << endl;
  995. cout << "5. Back" << endl;
  996.  
  997. do {
  998. int choice = _userChoice();
  999.  
  1000. switch(choice) {
  1001. case 1:
  1002. return 41;
  1003. case 2:
  1004. return 42;
  1005. case 3:
  1006. return 43;
  1007. case 4:
  1008. return 44;
  1009. case 5:
  1010. return back(3);
  1011. }
  1012. } while(true);
  1013. }
  1014. };
  1015.  
  1016. void seedPatients(PatientRepository *repos) {
  1017. cout << endl << "Creating default patients...";
  1018.  
  1019. repos->save(new Patient("Vasilii", "Vasilev", 21, Patient::male, "Vasilevsk", "atit"));
  1020. repos->save(new Patient("Petr", "Petrov", 22, Patient::male, "Petrovsk", "schizophrenia"));
  1021. repos->save(new Patient("Bred", "Bredovich", 20, Patient::male, "Vasilevsk", "atit"));
  1022. repos->save(new Patient("Ekaterina", "Lopireva", 19, Patient::female, "Minsk", "cancer"));
  1023. repos->save(new Patient("Graf", "Drakula", 18, Patient::male, "Norilsk", "schizophrenia"));
  1024. repos->save(new Patient("Yura", "Ermakovich", 16, Patient::male, "Minsk", "psyhozis"));
  1025. }
  1026.  
  1027. void seedUsers(UserRepository *repos) {
  1028. cout << endl << "Creating default users...";
  1029.  
  1030. repos->save(new User("admin", "password", User::admin));
  1031. repos->save(new User("user", "password", User::user));
  1032. }
  1033.  
  1034. void showAllWhereCityNotIn(TableView *view, PatientRepository *repos) {
  1035. string city;
  1036.  
  1037. do {
  1038. cout << endl << "Enter City: ";
  1039. getline(cin, city);
  1040. } while(!city.length());
  1041.  
  1042.  
  1043. vector<RepositoryObject*> patients = repos->getAllWhereCityNot(city);
  1044. view->display(patients);
  1045. }
  1046.  
  1047. // функция показать все где диагноз и возраст
  1048. // функция принимает на вход view - указатель на объект который помогает рисовать в консольке таблицу юзеров
  1049. // и репазиторий (хранилище) пациентов - там где * это всегда указатель на какой-то объект
  1050. // указатель это такой типа данных, типа как ярлык на рабочем столе
  1051. void showAllWhereDiagnosisAndAge(TableView *view, PatientRepository *repos) {
  1052. // инициализируем переменные вспомогательные
  1053. string age, diagnosis;
  1054. int userAge = -1;
  1055.  
  1056. // цикл ввода диагноза с клавиатуры
  1057. do {
  1058. cout << endl << "Enter Diagnosis: "; //говорим что надо ввести
  1059. getline(cin, diagnosis);//вводим (заполняем переменную-буфер)
  1060. } while(!diagnosis.length()); //выходим из цикла только тогда когда что-то введено - т.е. когда длинна строки НЕ равно НУЛЮ
  1061.  
  1062.  
  1063. // тоже самое но для возраста, цикл ввода возраста
  1064. do {
  1065. cout << endl << "Enter Age: ";
  1066. getline(cin, age);
  1067.  
  1068. // все что вводится с клавиатуры изначально это строка,
  1069. //т.к. возраст это число, мы должны сконвертировать строку скажем "21" в число 21
  1070. try {
  1071. userAge = stoi(age); //конвертируем
  1072. }
  1073. catch(const invalid_argument& ex) { //если конвертация невозможно, например ты ввел asdfaskjdlfha то возникаем ошибка конвертации,
  1074. // отлавливаем это исключение и чистим переменную-буфер, длинна строки становится равной нулю
  1075. age.clear();
  1076. }
  1077. } while(!age.length()); //выходим из цикла когда в строке что-то есть, если была ошлибка - строка чиститься и ввод начинается сначала
  1078.  
  1079.  
  1080. //когда ввод диагноза и конвертация возраста завершены мы можем начать поиск в хранилище пациентов
  1081. //ищи продолжение в методе getAllWhereDiagnosisAndAge
  1082. vector<RepositoryObject*> patients = repos->getAllWhereDiagnosisAndAge(diagnosis, userAge);
  1083.  
  1084. //выводим таблицу пациентов на экран
  1085. view->display(patients);
  1086. }
  1087.  
  1088. int main(int argc, char** argv) {
  1089. SQLManager *db = new SQLManager("database.db");
  1090.  
  1091. PatientRepository *patientsRepos = new PatientRepository(db);
  1092. UserRepository *usersRepos = new UserRepository(db);
  1093.  
  1094. // create some default patients
  1095. if (patientsRepos->getAll().size() == 0) {
  1096. seedPatients(patientsRepos);
  1097. }
  1098.  
  1099. // create default users
  1100. if (usersRepos->getAll().size() == 0) {
  1101. seedUsers(usersRepos);
  1102. }
  1103.  
  1104. LoginManager *manager = new LoginManager(usersRepos);
  1105. User *currentUser = manager->authorize();
  1106.  
  1107. UsersView *usersView = new UsersView();
  1108. PatientsView *patientsView = new PatientsView();
  1109.  
  1110. if (currentUser) {
  1111. bool exit = false;
  1112. ProgramMenu *menu = new ProgramMenu(currentUser);
  1113.  
  1114. while(!exit) {
  1115. int step = menu->step();
  1116.  
  1117. switch(step) {
  1118. case -1:
  1119. exit = true;
  1120. break;
  1121. case 11: // Show All Users
  1122. usersView->display(usersRepos->getAll());
  1123. break;
  1124. case 12: // Add User
  1125. usersView->add(usersRepos);
  1126. break;
  1127. case 13: // Update User
  1128. usersView->update(usersRepos);
  1129. break;
  1130. case 14: // Remove User
  1131. usersView->remove(usersRepos);
  1132. break;
  1133. case 22: // Add Patient
  1134. patientsView->add(patientsRepos);
  1135. break;
  1136. case 23: // Update Patient
  1137. patientsView->update(patientsRepos);
  1138. break;
  1139. case 24: // Remove Patient
  1140. patientsView->remove(patientsRepos);
  1141. break;
  1142. case 31: // Show All Patients
  1143. patientsView->display(patientsRepos->getAll());
  1144. break;
  1145. case 32: // Show All Where City is not in
  1146. showAllWhereCityNotIn(patientsView, patientsRepos);
  1147. break;
  1148. case 33: // Show All Where Diagnosis and Age
  1149. showAllWhereDiagnosisAndAge(patientsView, patientsRepos);
  1150. break;
  1151. case 41: // Sort by first name
  1152. patientsView->display(patientsRepos->getAllSortedBy("firstName"));
  1153. break;
  1154. case 42: // Sort by last name
  1155. patientsView->display(patientsRepos->getAllSortedBy("lastName"));
  1156. break;
  1157. case 43: // Sort by age name
  1158. patientsView->display(patientsRepos->getAllSortedBy("age"));
  1159. break;
  1160. case 44: // Sort by city name
  1161. patientsView->display(patientsRepos->getAllSortedBy("city"));
  1162. break;
  1163. }
  1164. }
  1165. }
  1166. else {
  1167. cout << endl << "Authorization failed. Exiting...";
  1168. }
  1169.  
  1170. delete patientsRepos;
  1171. delete usersRepos;
  1172. delete db;
  1173.  
  1174. return 0;
  1175. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement