#include <iostream>
#include <vector>
#include <string>
#include <algorithm>

using namespace::std;

#define check( s, a, b ) { \
if( (a) != (b) ) { \
cout << "## FAIL (" << (s) << "): " << (a) << " != " << (b) << endl; \
} \
else cout << "## PASS (" << (s) << "): " <<  (a) << endl; \
}

class Person {
private:
    // Data
    int age;
    string name;
    char gender;
    string schoolname;
    vector<string> favorite;
    vector<string> dislike;
    
public:
    // Constructors
    Person(string name, char gender) {
        this->name = name;
        age = 1;
        
        if(gender != 'M' && gender != 'F')
            this->gender = 'F';
        else
            this->gender = gender;
        
        schoolname = "NO SCHOOL";
        favorite.clear();
        dislike.clear();
    }
    
    // Getters
    string get_name() const;
    int get_age() const;
    char get_gender() const;
    string get_favorite(int i) const;
    string get_dislike(int i) const;
    int get_fav_cnt() const;
    int get_dis_cnt() const;
    
    // Setters
    void set_name(string name);
    void set_age(int age);
    
    // Checkers
    bool is_female();
    bool is_schoolkid();
    
    // Other functions
    void goto_school(string schoolname);
    void add_favorite(string thing);
    void add_dislike(string thing);
    
    // Operator overloading
    Person& operator++();

    friend bool operator >(const Person lhs, const Person rhs);
};

/////////////////////////////////////////////////
string Person::get_name() const {
    return this->name;
}

int Person::get_age() const {
    return this->age;
}

char Person::get_gender() const {
    return this->gender;
}

string Person::get_favorite(int i) const {
    return this->favorite.at(i);
}

string Person::get_dislike(int i) const {
    return this->dislike.at(i);
}

int Person::get_fav_cnt() const {
    return this->favorite.size();
}

int Person::get_dis_cnt() const {
    return this->dislike.size();
}

//////////////////////////////////////////////
void Person::set_name(string name) {
    this->name = name;
}
void Person::set_age(int age) {
    this->age = age;
}

/////////////////////////////////////////////
bool Person::is_female() {
    return this->gender == 'F';
}

bool Person::is_schoolkid() {
    return this->age >= 7 && this->age <= 19;
}

/////////////////////////////////////////////
void Person::goto_school(string schoolname) {
    if(!is_schoolkid())
        this->schoolname = schoolname;
    else
        this->schoolname = "NO SCHOOL";
}
void Person::add_favorite(string thing) {
    this->favorite.erase(remove(this->favorite.begin(), this->favorite.end(), thing), this->favorite.end());
    this->dislike.erase(remove(this->dislike.begin(), this->dislike.end(), thing), this->dislike.end());
    this->favorite.push_back(thing);

}

void Person::add_dislike(string thing) {
    this->favorite.erase(remove(this->favorite.begin(), this->favorite.end(), thing), this->favorite.end());
    this->dislike.erase(remove(this->dislike.begin(), this->dislike.end(), thing), this->dislike.end());
    this->dislike.push_back(thing);

}

///////////////////////////////////////////
Person& Person::operator++() {
    age++;
    return *this;
}

bool operator >(const Person lhs, const Person rhs) {
    return lhs.age > rhs.age;
}


////////////////////////////////////////////
int main() {
    Person p1("철수", 'M');
    check("1. 이름", p1.get_name(), "철수"); // 생성자
    
    Person p2("영희", 'S');
    check("2. 성별", p2.get_gender(), 'F'); // 생성자
    
    Person p3("태희", 'F');
    p3.set_name("혜교");
    check("3. 이름", p3.get_name(), "혜교"); // getter 점검
    p3.set_age(15);
    check("4. 나이", p3.is_schoolkid(), true); // checker 점검
    
    Person p4("영수", 'M');
    Person p5("민아", 'T');
    ++p4;
    check("5. 나이", p4 > p5, true); // opertor overloading 점검
    
    Person p7("민식", 'M');
    p7.add_favorite("자동차");
    p7.add_favorite("영화");
    p7.add_favorite("책");
    p7.add_favorite("장난감");
    p7.add_favorite("장난감");
    p7.add_favorite("영화");
    check("6. 추가-2점", p7.get_favorite(1), "책"); // vector 중복점검 (2점)
    check("7. 추가", p7.get_fav_cnt(), 4); // vector 갯수 점검
    
    Person p8("강현", 'F');
    p8.add_favorite("노래");
    p8.add_favorite("춤");
    p8.add_favorite("가수");
    p8.add_dislike("춤");
    check("8. 추가-2점", p8.get_favorite(1), "가수"); // vector 중복제거 점검 (2점)
    
    system("pause");
}
