CS207-HW3/Clinic.cpp

173 lines
5.0 KiB
C++

#include "Patient.hpp"
#include <algorithm>
#include <fstream>
#include <functional>
#include <iostream>
#include <optional>
#include <sstream>
#include <sys/types.h>
#ifndef CLINIC_
#define CLINIC_
enum class MenuChoice {
NewPatient = 1,
NewVisit = 2,
DisplayPatient = 3,
Quit = 4,
};
struct Clinic {
public:
std::vector<Patient> patients;
std::string filename;
private:
// C++ types are getting crazy here :( I really miss Rust
// `std::optional` needed because a patient might not be found
// `std::reference_wrapper` because `std::optional` deoesn't accept references
// I want to reference because (I want to save cpu cycles from memory copies)
std::optional<std::reference_wrapper<Patient>>
find_patient(u_int32_t patient_id) {
auto it = std::find_if(patients.begin(), patients.end(),
[&id = patient_id](const Patient &p) -> bool {
return p.get_id() == id;
});
if (it != patients.end())
return *it;
return std::nullopt;
};
public:
Clinic(std::string filename) : filename(filename) {
/// this file contains a list of patient IDs.
// 1
// 2
// 4 (could be non-sequential
// but always sorted!)
u_int32_t patient_id;
std::ifstream file{filename};
if (!file.is_open()) {
std::cerr << "File " << filename << " couldn't be opened :(\n";
exit(1);
}
while (file >> patient_id)
patients.push_back(Patient(patient_id));
}
// writes the patients.txt file containing patient IDs.
void write_file() {
std::ofstream file{filename};
for (auto p : patients)
file << p.get_id() << "\n";
}
u_int32_t generate_id() {
u_int32_t id{};
// O(n), could be improved by using UUIDs, or store max_id in Clinic
for (auto p : patients)
id = std::max(id, p.get_id());
id++;
return id;
}
MenuChoice menu_main() {
int choice{};
std::cout << "==============================================\n";
std::cout << "Please choose a command:\n";
std::cout << "1. add new patient\n";
std::cout << "2. add new visit\n";
std::cout << "3. display patient information\n";
std::cout << "4. quit\n";
std::cout << ">> ";
std::cin >> choice;
while (choice < int(MenuChoice::NewPatient) ||
choice > int(MenuChoice::Quit)) {
std::cout << "Invalid input! Try again :)\n";
std::cout << "Please choose a command:\n";
std::cout << "1. add new patient\n";
std::cout << "2. add new visit\n";
std::cout << "3. display patient information\n";
std::cout << "4. quit\n";
std::cout << ">> ";
std::cin >> choice;
}
return static_cast<MenuChoice>(choice);
}
void menu_patient_info() {
int patient_id;
std::cout << "Patient file number: ";
std::cin >> patient_id;
auto patient = find_patient(patient_id);
if (patient.has_value())
std::cout << patient.value();
else
std::cout << "No Patient exists with id= " << patient_id << "\n";
std::cout << "--------------------\n\n";
}
void menu_add_new_patient() {
std::string reading_string;
std::string input_string;
Patient patient{};
std::stringstream patient_stream;
// not the most optimal way, but the lazy way
// see: https://ammar.engineer/posts/2023/06/03/laziness/
// this "emulates" a file so that I can resuse my >> operator
reading_string += std::to_string(generate_id()) + "\n";
std::cout << "Generate " << reading_string;
std::cout << "First name (no spaces): ";
std::cin >> input_string;
reading_string += input_string + "\n";
std::cout << "Last name (no spaces): ";
std::cin >> input_string;
reading_string += input_string + "\n";
std::cout << "Gender (M or F): ";
std::cin >> input_string;
reading_string += input_string + "\n";
std::cout << "Age: ";
std::cin >> input_string;
reading_string += input_string + "\n";
std::cout << reading_string;
patient_stream = std::stringstream(reading_string);
// all of that just for this moment:
patient_stream >> patient;
patients.push_back(patient); // save in memory
patient.write_patient(); // write to file
write_file();
}
void menu_add_vist() {
std::string reading_string;
std::string input_string;
int patient_id;
std::cout << "Patient file number: ";
std::cin >> patient_id;
std::cout << "Date:";
std::cin >> input_string;
reading_string += input_string + " ";
std::cout << "Doctor's First Name: ";
std::cin >> input_string;
reading_string += input_string + " ";
std::cout << "Doctors's Last Name: ";
std::cin >> input_string;
reading_string += input_string + " ";
std::stringstream visit_stream = std::stringstream(reading_string);
Visit visit;
visit_stream >> visit;
auto patient = find_patient(patient_id);
if (patient.has_value())
patient.value().get().add_visit(visit);
else
std::cout << "No Patient exists with id= " << patient_id << "\n";
}
};
#endif