CCCPaste
/*
1. Към класа CAddress от упражнение 3 да се добави глобална приятелска функция (оператор) за извеждане на данните за адреса по указан като параметър изходен поток,например:
friend ostream& operator<<(ostream& toStream, const CAddress& addr)
2. Към класа CPerson от упражнение 3 да се добави частна функция за получаване на година, месец и ден от подадения като параметър единен граждански номер,например:
void getYMD(const string& strEGN,int &iYear,int &iMonth, int &iDay)const;
3. Към класа CPerson от упражнение 3 да се добави глобална приятелска функция (оператор) за извеждане на данните за личността по указан като параметър изходен поток,например:
friend ostream& operator<<(ostream& toStream, const CPerson& pers)
4. Към класа CStudent от упражнение 3 да се добави глобална приятелска функция за конзолен вход към единен граждански номер на подадения като параметър обект от класа CStudent,например:
friend void ConsoleInputEGN(CStudent& stud)
5. Към класа CStudent от упражнение 3 да се добави глобална приятелска функция (оператор) за извеждане на данните за студента по указан като параметър изходен поток,например:
friend ostream& operator<<(ostream& toStream, const CStudent& stud)
6. Към класа CStudent от упражнение 3 да се добавят следните глобални приятелски функции (оператори) за сравнение на двама студента (параметри):
? За равенство по възраст ==;
? За неравенство по възраст !=;
? За по-малко по възраст <;
? За по-голямо по възраст >;
7. Да се състави подходяща главна функция за проверка на създадените функции и оператори.*/


#include <iostream>
#include <string>
#include <ctime>
using namespace std;

class CAddress {
string street;
string post;
string city;
public:

friend ostream& operator<<(ostream& toStream, const CAddress& addr);

CAddress() {
street = "";
post = "";
city = "";
}

explicit CAddress(string s, string p, string c) {
street = s;
post = p;
city = c;
}

CAddress(const CAddress& a) //copy constructor
{
street = a.street;
post = a.post;
city = a.city;
}

CAddress(const CAddress* a) //copy constructor
{
street = a->street;
post = a->post;
city = a->city;
}

string GetStreet() {
return street;
}

void SetStreet(string s) {
street = s;
}

string GetPost() {
return post;
}

void SetPost(string p) {
post = p;
}

string GetCity() {
return city;
}

void SetCity(string c) {
city = c;
}

ostream& Output(ostream& toStream) {
toStream << street << ";" << post << ";" << city;
return toStream;
}

};

class CPerson {
public:
enum Gender { male, female, undef };
private:
string name;
string egn;
Gender gender;
public:
friend ostream& operator<<(ostream& toStream, const CPerson& pers);
CPerson() {
name = "";
gender = undef;
egn = "";
}

explicit CPerson(string szName, Gender szGender) {
name = szName;
gender = szGender;
egn = "";
}

explicit CPerson(string name, string egn, Gender gender) {
this->name = name;
if (checkEGN(egn))
this->egn = egn;
else
this->egn = "1111111111";
this->gender = gender;
}

void SetName(string szName) {
name = szName;
}

string GetName() {
return name;
}

void SetGender(Gender szGender) {
gender = szGender;
}

Gender GetGender() {
return gender;
}

bool SetEGN(string e) {
if (checkEGN(e)) {
egn = e;
return true;
}
else if (e == "1111111111") {
egn = e;
return true;
}
else
return false;
}

string GetEGN() {
return egn;
}
private:
bool isCorrectDateOfEGN(std::string yymmdd) {
if (yymmdd.length() != 6)
return false;

int dayspermon[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };

int month, day, year;

year = atoi(yymmdd.substr(0, 2).c_str());
month = atoi(yymmdd.substr(2, 2).c_str());
day = atoi(yymmdd.substr(4, 2).c_str());

if (!(year != 0 && month != 0 && day != 0))
return false;
if (year < 0 || month < 1 || day < 1) {
return false;
}

if (month >= 13 && month <= 20) {
return false;
}
else if (month >= 21 && month <= 32) {
month = month - 20;
}
else if (month >= 33 && month <= 40) {
return false;
}
else if (month >= 41 && month <= 52) {
month = month - 40;
}
else if (month > 52) {
return false;
}

if (month == 2)
if ((year % 4) == 0)
dayspermon[2] = 29;

if (day > dayspermon[month - 1]) {
return false;
}

return true;
}

bool checkEGN(std::string egn) {
int ctrSum = 0;
int ctrField = 0;
int teglo[] = { 2, 4, 8, 5, 10, 9, 7, 3, 6 };

if (egn.length() != 10)
return false;

long long tmpEgn = atoi(egn.c_str());
if (tmpEgn == 0)
return false;

if (!isCorrectDateOfEGN(egn.substr(0, 6))) {
return false;
}

for (int i = 0; i < egn.length() - 1; ++i) {
string t = egn.substr(i, 1);
ctrSum += teglo[i] * atoi(t.c_str());
}

ctrField = (ctrSum % 11) % 10;

if (ctrField != atoi(egn.substr(9, 1).c_str()))
return false;
else return true;
}

void getYMD(const string& strEGN, int& iYear, int& iMonth, int& iDay) const {
iYear = atoi(strEGN.substr(0, 2).c_str());
iMonth = atoi(strEGN.substr(2, 2).c_str());
iDay = atoi(strEGN.substr(4, 2).c_str());

if (iMonth >= 21 && iMonth <= 32) {
iMonth = iMonth - 20;
iYear = iYear + 1800;
}
else if (iMonth >= 41 && iMonth <= 52) {
iMonth = iMonth - 40;
iYear = iYear + 2000;
}
else iYear = iYear + 1900;
}

public:

void getYMD(int& iYear, int& iMonth, int& iDay) const {
iYear = atoi(egn.substr(0, 2).c_str());
iMonth = atoi(egn.substr(2, 2).c_str());
iDay = atoi(egn.substr(4, 2).c_str());

if (iMonth >= 21 && iMonth <= 32) {
iMonth = iMonth - 20;
iYear = iYear + 1800;
}
else if (iMonth >= 41 && iMonth <= 52) {
iMonth = iMonth - 40;
iYear = iYear + 2000;
}
else iYear = iYear + 1900;
}

Gender stringToGender(const string& strGender) const {
if (strGender == "male")
return Gender::male;
else if (strGender == "female")
return Gender::female;
else return Gender::undef;
}

string genderToString() const {
switch (gender) {
case male:
return "male";
case female:
return "female";
case undef:
return "undef";
}
}
};

class CStudent : public CPerson {
string fnumber;
CAddress address;
public:
friend ostream& operator<<(ostream& toStream, CStudent& stud);
friend void ConsoleInputEGN(CStudent& stud);
friend bool operator==(CStudent& s1, CStudent& s2);
friend bool operator!=(CStudent& s1, CStudent& s2);
friend bool operator>(CStudent& s1, CStudent& s2);
friend bool operator<(CStudent& s1, CStudent& s2);
CStudent() {
fnumber = "";
address = new CAddress();
}

explicit CStudent(string n, string egn, Gender g, string s, string c, string p) : CPerson(n, egn, g) {
address = new CAddress();
address.SetStreet(s);
address.SetCity(c);
address.SetPost(p);
}

explicit CStudent(string n, string egn, Gender g, string s, string c, string p, string fn) : CPerson(n, egn, g) {
address = new CAddress();
address.SetStreet(s);
address.SetCity(c);
address.SetPost(p);
fnumber = fn;
}

CStudent(CStudent& a) {
address = a.address;
fnumber = a.fnumber;
this->SetName(a.GetName());
this->SetGender(a.GetGender());
this->SetEGN(a.GetEGN());
}

void SetAddress(CAddress& a) {
address = a;
}

CAddress& GetAddress() {
return address;
}

void SetFNum(string fn) {
this->fnumber = fn;
}

string GetFNum() {
return fnumber;
}

ostream& Output(ostream& out) {
out << GetName() << ";" << GetGender() << ";" << GetEGN() << ";";
address.Output(out);
out << ";" << fnumber << endl;
return out;
}
};

ostream& operator<<(ostream& toStream, const CAddress& addr) {
toStream << addr.street << ";" << addr.post << ";" << addr.city;
return toStream;
}

ostream& operator<<(ostream& toStream, const CPerson& pers) {
toStream << pers.name << ";" << pers.gender << ";" << pers.egn;
return toStream;
}

ostream& operator<<(ostream& toStream, CStudent& stud) {
toStream << stud.GetName() << ";" << stud.GetGender() << ";" << stud.GetEGN() << ";";
toStream << stud.GetAddress();
toStream << ";" << stud.fnumber;
return toStream;
}

void ConsoleInputEGN(CStudent& stud) {
string input;
while (true) {
cout << "Enter valid EGN:";
cin >> input;
if (stud.SetEGN(input))
break;
else cout << "Invalid EGN." << endl;
}
}

bool operator==(CStudent& s1, CStudent& s2) {
int s1year, s1month, s1day;
int s2year, s2month, s2day;
s1.getYMD(s1year, s1month, s1day);
s2.getYMD(s2year, s2month, s2day);

if ((s1year == s2year) && (s1month == s2month) && (s1day == s2day))
return true;
else return false;
}

bool operator!=(CStudent& s1, CStudent& s2) {
int s1year, s1month, s1day;
int s2year, s2month, s2day;
s1.getYMD(s1year, s1month, s1day);
s2.getYMD(s2year, s2month, s2day);
if ((s1year != s2year) || (s1month != s2month) || (s1day != s2day))
return true;
else return false;
}

bool operator>(CStudent& s1, CStudent& s2) {
int s1year, s1month, s1day;
int s2year, s2month, s2day;
s1.getYMD(s1year, s1month, s1day);
s2.getYMD(s2year, s2month, s2day);

if (s1year > s2year)
return false;
else if (s1year == s2year) {
if (s1month > s2month)
return false;
else if (s1month == s2month) {
if (s1day > s2day)
return false;
else return true;
}
else return true;
}
else return true;
}

bool operator<(CStudent& s1, CStudent& s2) {
int s1year, s1month, s1day;
int s2year, s2month, s2day;
s1.getYMD(s1year, s1month, s1day);
s2.getYMD(s2year, s2month, s2day);

if (s1year < s2year)
return false;
else if (s1year == s2year) {
if (s1month < s2month)
return false;
else if (s1month == s2month) {
if (s1day < s2day)
return false;
else return true;
}
else return true;
}
else return true;
}


int main() {
// https://georgi.unixsol.org/programs/egn.php

CStudent s1("Gosho", "5412065927", CPerson::male, "Roza", "Varna", "9000", "24621449");
CStudent s2("Mariya", "3108208010", CPerson::female, "Kon", "Dobrich", "8000", "24621507");

if (s1 > s2) {
"S1 e po-vuzrasten ot S2";
}
else if (s1 < s2) {
"S2 e po-vuzrasten ot S1";
}
else {
cout << "Dvata studenta sa astralni bliznaci";
}
return 0;
}