#include <iostream>
#include <vector>

using namespace std;

class Student {
    string last_name; // фамилия ученика
    int grade; // оценка ученика

    public:

    void input(){
        // переменные для ввода фамилии и оценки
        string last_name;
        int grade = 0;

        while (last_name.empty()){
            cout << "\t\t\tInput student's last name: ";
            cin >> last_name;
            cin.get();
        }

        while (grade < 2 || grade > 5){
            cout << "\t\t\tInput student's grade: ";
            cin >> grade;
            cin.get();
        }
        
        cout << "\n";
        // присваивание переменным объекта значений из переменных ввода
        this->last_name = last_name;
        this->grade = grade;
    }

    void output(){ // вывод фамилии и оценки
        cout << "Student's last name: " << this->last_name << "\n\t\t\t";
        cout << "Student's grade: " << this->grade << "\n\n";
    }

    string get_last_name(){ return this->last_name; } // получение фамилии

    int get_grade(){ return this->grade; } // получение оценки
};

class Journal {
    vector <Student> journal; // массив с объектами класса Student
    vector <int> bad_grades; // массив для подсчёта количества двоешников

    public:

    void input(){ // ввод объектов класса Student
        int count = 0;

        while (count < 1){
            cout << "\tInput students count: ";
            cin >> count;
            cin.get();
            cout << "\n";
        }

        journal.resize(count);
        
        for (int i = 0; i < count; i++){
            cout << "\t\tInput " << i+1 << " student's data:\n\n";
            journal[i].input();
        }
        
        cout << "\n";
    }

    void output(){ // вывод массива с объектами Student
        for (int i = 0; i < journal.size(); i++){
            cout << "\t\t" << i+1 << " student's data:\n\n\t\t\t";
            journal[i].output();
        }
    }

    int get_bad_grade(){ // получение количества и индексов учеников с оценкой 2
        for (int i = 0; i < journal.size(); i++){
            if (journal[i].get_grade() == 2) // если оценка равна 2
                this->bad_grades.push_back(i); // добавляем индекс в массив двоешников
        }
        
        return this->bad_grades.size(); // возвращаем размер массива, то бишь количество двоешников
    }

    void output_bad_grade(){ // вывод двоешников
        for (int i = 0; i < this->bad_grades.size(); i++){
            cout << "\t\t" << i+1 << " student's data:\n\n\t\t\t";
            journal[this->bad_grades[i]].output();
        }
    }

    void delete_in_list(){ // функция для удаления учеников с фамилиями, совпадающими со списком пользователя 
        vector <Student> new_journal; // создание нового объекта

        for (int i = 0; i < journal.size(); i++){
            if (journal[i].get_grade() == 2){ // если фамилия есть в списке пользователя
                continue; // пропускаем её
            }
            new_journal.push_back(journal[i]); // добавляем ученика в новый список 
        }

        this->journal = new_journal; // присваиваем значение нового журнала в переменную объекта
    }
};

class JournalsDB {
    vector <Journal> journal_db; // массив с объектами класса Journal
    vector <int> bad_grades; // целочисленный массив для подсчёта двоешников

    public:

    JournalsDB(int count = 1){
        cout << "Constructor " << this << " initialized\n\n";
        input(count); // выхов функции ввода у объекта
    }

    ~JournalsDB(){ // деструктор
        cout << "\nDestructor " << this << " initialized\n\n"; //
    }

    void input(int count){ // функция ввода
        journal_db.resize(count);

        for (int i = 0; i < count; i++){
            cout << "Input " << i+1 << " journal:\n\n";
            journal_db[i].input();
        }
        
        cout << "\n\n";
    }

    void output(){ // функция вывода
        cout << "Output jouranls database\n\n";

        for (int i = 0; i < journal_db.size(); i++){
            cout << i+1 << " journal:\n\n";
            journal_db[i].output();
        }

        cout << "\n\n";
    }

    int get_bag_grade(){ // функция получения двоешников
        int count = 0; // количество двоешников в целом

        bad_grades.resize(journal_db.size());

        for (int i = 0; i < bad_grades.size(); i++){
            bad_grades[i] = journal_db[i].get_bad_grade(); // получаем значения на каждый отдельный журнал
        }

        for (int i = 0; i < bad_grades.size(); i++){
            count += bad_grades[i]; // подсчитываем общее количество
        }

        return count; // возвращаем общее количество двоешников
    }

    int get_wost_journal(){ // функция нахождения журнала с наибольшим количеством двоешников
        int worst_journal = -1; // по умолчанию индекс отсутствует
        int count = 0; // переменная для нахождения наибольшего значения
        // обычный алгоритм поиска наибольшего значения
        for (int i = 0; i < bad_grades.size(); i++){
            if (bad_grades[i] > count){
                count = bad_grades[i];
                worst_journal = i; // если значение в массиве больше count, то обновляем последний, а также индекс худшего журнала
            }
        }

        return worst_journal; // возвращаем индекс
    }

    void output_bad_grade(){ // вывод учеников с оценкой 2
        cout << "Output jouranls with worst students\n\n";

        for (int i = 0; i < bad_grades.size(); i++){
            if (bad_grades[i] <= 0)
                continue;
            cout << i+1 << " journal:\n\n";
            journal_db[i].output_bad_grade();
        }
    }

    void delete_in_list(int worst_journal){ // удаление введённых фамилий
        journal_db[worst_journal].delete_in_list(); // вызов функции удаления в журнале с найденным индексом
    }
};

int main(){
    JournalsDB* school_journals_db;

    int worst_journal = -1; // индекс журнала с большим количеством двоешников
    int bad_grade_count = 0; // общее количество двоешников

    int count;
    
    cout << "Input journals count: ";
    cin >> count;
    cin.get();
    cout << "\n";

    if (count < 1){
        cout << "The count of journals in DB can't be less than 1! So, I set 1 as a default value in DB." << "\n\n";
        school_journals_db = new JournalsDB();
    }
    else {
        school_journals_db = new JournalsDB(count);
    }

    bad_grade_count = (*school_journals_db).get_bag_grade(); // получение общего количества двоешников

    cout << "Total number of worst students: " << bad_grade_count << "\n\n"; // вывод общего количества двоешников

    (*school_journals_db).output_bad_grade(); // вывод всех двоешников

    worst_journal = (*school_journals_db).get_wost_journal(); // получение индекса журнала с наибольшим количеством двоешников

    if (worst_journal == -1){ // если такого журнала нет, то выводим сообщение об этом и завершаем программу
        cout << "The worst journal doesn't exist.\n";
        return 0;
    }

    cout << "\n\nThe worst journal is " << worst_journal+1 << "\n\n"; // вывод полученного индекса 

    (*school_journals_db).delete_in_list(worst_journal); // вызов функции для удаления фамилий

    (*school_journals_db).output(); // вывод журналов

    delete school_journals_db;

    return 0; // конец
}