245 lines
5.2 KiB
C++
245 lines
5.2 KiB
C++
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <iostream>
|
|
#include <string>
|
|
#include <vector>
|
|
#include <unordered_set>
|
|
#include <algorithm>
|
|
|
|
#include "Employee.hpp"
|
|
#include "Worker.hpp"
|
|
#include "Contractee.hpp"
|
|
#include "Manager.hpp"
|
|
#include "Company.hpp"
|
|
|
|
#include "help_message.h"
|
|
|
|
using namespace std;
|
|
|
|
/* globális példaértékű Company példány amin a "shell" operálhat
|
|
*/
|
|
Company mycompany("Beadandó Inc.");
|
|
|
|
// Ambiens Osztály
|
|
|
|
/* vissza adja a felhasználói input 'i'-edik mezejét,
|
|
* ahol a mezők white space szeparált string-ek ként vannak definiálva
|
|
*/
|
|
string parse_field(const string &line, int i) {
|
|
/* ezt a függvényt könyebb C string-ekkel implementálni,
|
|
* de az input std::string-ként jut ide kényelmesen,
|
|
* ezért "átváltjuk"
|
|
*/
|
|
const char * line_p = line.c_str(); // mező eleje
|
|
const char * end_p = line_p; // mező vége
|
|
for (int h = 0; h < i; h++) { // iterate
|
|
line_p = end_p;
|
|
while (isspace(*line_p)) { // find begin
|
|
++line_p;
|
|
}
|
|
end_p = line_p;
|
|
while (!isspace(*end_p) // find end
|
|
&& *end_p != '\0') {
|
|
++end_p;
|
|
}
|
|
}
|
|
|
|
string r = string(line_p, (end_p) - line_p);
|
|
|
|
return r;
|
|
}
|
|
|
|
/* felhasználói parancs értelmezése
|
|
*/
|
|
void command(const string &line) {
|
|
if (line == "q") { // "Quit"
|
|
throw int();
|
|
} else if (line[0] == 'h') { // "Help"
|
|
puts(help_message);
|
|
return;
|
|
} else if (line.substr(0, 2) == "c ") { // "Create"
|
|
// ?! példa
|
|
if (line.size() < 5) {
|
|
return;
|
|
}
|
|
|
|
string name = parse_field(line, 3);
|
|
//puts(name.c_str());
|
|
|
|
const char type = line[2];
|
|
Employee * e;
|
|
switch (type) {
|
|
case 'w': {
|
|
e = (Employee *)(new Worker(name));
|
|
} break;
|
|
case 'c': {
|
|
e = (Employee *)(new Contractee(name));
|
|
} break;
|
|
case 'm': {
|
|
e = (Employee *)(new Manager(name, &mycompany));
|
|
} break;
|
|
default: {
|
|
fputs("No employee created.", stderr);
|
|
return;
|
|
} break;
|
|
}
|
|
mycompany.employees.push_back(e);
|
|
puts("Employee created.");
|
|
return;
|
|
} else if (line.substr(0, 2) == "i ") { // "Info"
|
|
string id = parse_field(line, 2);
|
|
|
|
Employee * e = mycompany.by_id(id);
|
|
if (e) {
|
|
e->details();
|
|
puts("");
|
|
}
|
|
|
|
return;
|
|
} else if (line.substr(0, 2) == "m ") { // "Modify"
|
|
string id = parse_field(line, 2);
|
|
string modification = parse_field(line, 3);
|
|
|
|
Employee * e = mycompany.by_id(id);
|
|
if (e) {
|
|
puts(e->modify(modification) ? "Modification performed." : "Modification error.");
|
|
}
|
|
|
|
return;
|
|
} else if (line.substr(0, 2) == "d ") { // "Delete"
|
|
string id = parse_field(line, 2);
|
|
for (size_t i = 0; i < mycompany.employees.size(); i++) {
|
|
if (std::to_string(mycompany.employees[i]->id_m) == id) {
|
|
mycompany.employees.erase(mycompany.employees.begin() + i);
|
|
break;
|
|
}
|
|
}
|
|
|
|
return;
|
|
} else if (line[0] == 'l') { // "List"
|
|
mycompany.print();
|
|
return;
|
|
/* ------
|
|
* a biztonsági mentés beégetve pusztán azért,
|
|
* hogy kényelmesebb legyen tesztelni
|
|
*/
|
|
} else if (line[0] == 'w') { // "Write"
|
|
mycompany.bak("./data/bak.csv");
|
|
return;
|
|
} else if (line[0] == 'r') { // "Read"
|
|
mycompany.load("./data/bak.csv");
|
|
return;
|
|
/* ---
|
|
*/
|
|
} else {
|
|
puts(help_message);
|
|
return;
|
|
}
|
|
}
|
|
|
|
void filter(unordered_set<Employee*> &s, const char * const f) {
|
|
if (not *f) { return; }
|
|
|
|
switch (f[0]) {
|
|
case '.': { // mező érték alapú szűrés
|
|
for (const auto &i : mycompany.employees) {
|
|
if (i->is_match(f)) {
|
|
s.insert(i);
|
|
}
|
|
}
|
|
} break;
|
|
default: { // feltehetőleg név
|
|
auto t = mycompany.by_name(f);
|
|
s.insert(t.begin(), t.end());
|
|
} break;
|
|
}
|
|
}
|
|
|
|
void search(string line) {
|
|
/* vissza térési lista;
|
|
* `set`, hogy ne kézzel kelljen duplikált bejegyzéseket ellenőrizni
|
|
*/
|
|
unordered_set<Employee*> r;
|
|
|
|
/* space szeparált mezőnként szűrünk;
|
|
* a találatokat hozzáfűzzük az eddigiekhez;
|
|
* a szűrők között "vagy" kapcsolat áll fen
|
|
*/
|
|
char * dup = strdup(line.c_str()+1);
|
|
const char * delim = " ";
|
|
char * data = strtok(dup, delim);
|
|
int i = 0;
|
|
do {
|
|
filter(r, data);
|
|
++i;
|
|
} while((data = strtok(NULL, delim), data));
|
|
|
|
for (const auto &e : r) {
|
|
e->details();
|
|
puts("");
|
|
}
|
|
|
|
free(dup);
|
|
}
|
|
|
|
/* top-level user input kezelő
|
|
*/
|
|
void input() {
|
|
// Beolvasás
|
|
string line;
|
|
fputs("$ ", stdout);
|
|
std::getline(std::cin, line);
|
|
|
|
if (std::cin.eof()) {
|
|
puts("");
|
|
throw int();
|
|
}
|
|
|
|
// Értelmezés
|
|
switch (line[0]) {
|
|
case '/': { // keresés
|
|
search(line);
|
|
} break;
|
|
default: { // parancs
|
|
command(line);
|
|
};
|
|
}
|
|
}
|
|
|
|
bool init() {
|
|
/* (lehet, hogy) keverjük a C/C++ I/O-t ezért szinkronizáljuk az
|
|
* std iostream objektumokat az stdio függvényekkel;
|
|
* számomra a C stílusú output és a C++ stílusú input esik kézre,
|
|
* valós projektben persze csak az egyiket használnám
|
|
*/
|
|
std::ios_base::sync_with_stdio(true);
|
|
return true; // megszokásból
|
|
}
|
|
|
|
signed main() {
|
|
init();
|
|
//#include "dummy_constructors.inc"
|
|
//mycompany.bak("./data/employees.csv");
|
|
|
|
if(mycompany.load("./data/employees.csv")) {
|
|
fputs("Fatális hiba: adatok betöltése sikertelen", stderr);
|
|
return 1;
|
|
}
|
|
|
|
mycompany.print();
|
|
|
|
/* a kilépést kizárólag azért implementálom kivételel,
|
|
* mert szerettem volna kivételkezelést használni a programban,
|
|
* de máshol sem lett volna kevésbe értelmetlen
|
|
*/
|
|
try {
|
|
for (;;) {
|
|
input();
|
|
}
|
|
} catch (...) {
|
|
;
|
|
}
|
|
|
|
return 0;
|
|
}
|