// Добавлены конструкторы без параметров, с параметрами, деструктор, а также динамическая инициализация экземпляра класса (2 и 4 задания)
// Конструктор с параметром по умолчанию находится в отдельном файле без нумерации
#include <iostream>
#include <string>
#include <windows.h>

using namespace std;
struct Student
{
    int mark;
    string name;
};
struct School
{
    int number;
};
struct Score
{
    double score;
};
class Journal
{
private:
    Student* students;
    School* schools;
    Score* scores;
    int NumberOfStudents = 0;
    int NOS = 0;
    int KolS = 0;
    int StudentData = 0;
    int AverageScore = 0;

public:

    Journal(){ // конструктор без параметров
        cout << "\n\t\t\t\t\t\t\t\tИнициализация конструктора без параметров для объекта " << this << "\n"; // вывод информации о инициализации конструктора
    }
    // конструктор с параметрами полностью повторяет ф-цию NumOfSchool
    Journal(int nos, int num){ // конструктор с параметром
        cout << "\n\t\t\t\t\t\t\t\tИнициализация конструктора с параметром для объекта " << this << "\n"; // вывод информации о инициализации конструктора
        NOS = nos;
        schools = new School[NOS];
        schools[KolS].number = num;
        KolS++;
    }

    ~Journal(){ // деструктор
        cout << "\n\t\t\t\t\t\t\t\tИнициализация деструктора для объекта " << this << "\n"; // вывод информации о инициализации деструктора
    }

    void NumOfSchool(int nos, int num)
    {
        NOS = nos;
        schools = new School[NOS];
        schools[KolS].number = num;
        KolS++;
    }
    void NumberOfStds(int kol)
    {
        NumberOfStudents = kol;
        students = new Student[NumberOfStudents];
    }
    void SetStds(string name, int mark)
    {
        students[StudentData].name = name;
        students[StudentData].mark = mark;
        StudentData++;
    }
    void SaR(double as) 
    {
        scores = new Score[NOS];
        scores[AverageScore].score = as;
    }
    string Spisok() 
    {
        string b;
        for (int i = 0; i < KolS; i++) {
            b = b + "Школа №: " + to_string(schools[i].number) + "\n";
        }
        return b;
    }
    string SpisokSt()
    {
        string sp;
        for (int i = 0; i < NumberOfStudents; i++) {
            sp = sp + " Фамилия: " + students[i].name + " Оценка: " + to_string(students[i].mark)+"\n";
        }
        return sp;
    }
    string AverScore()
    {
        string h;
        for (int i = 0; i < KolS; i++) {
            h = h + " Средний балл: " + to_string(scores[i].score)+"\n";
        }
        return h;
    }
    void Idol()
    {
        cout << "Фамилия ученика с баллом выше среднего: "<<"\n";
        string u;
        for (int i = 0; i < KolS; i++) {
            for (int j = 0; j < NumberOfStudents; j++) {
                if (scores[i].score < students[j].mark) {
                    u = u +" | "+students[j].name+" | "+"\n";
                }
            }
            cout << u << "\n";
        }
    }
};

int main()
{
    SetConsoleCP(1251);
    SetConsoleOutputCP(1251);
    setlocale(LC_ALL, "rus");
    int kolschool; // количество школ
    int kolstudents; // количество студентов
    int numofschool; // номер школы
    string familia; // фамилия студента
    int mark; // оценка студента
    double averagescore = 0; // средняя оценка
    char change_static_value; // переменная проверки на изменение статического значения класса
    // ввод количества школ
    cout << "Введите количество школ: "; 
    cin >> kolschool;
    // указатель на массив с объектами класса Journal и размером kolschool
    Journal* journals[kolschool];
    for (int i = 0; i < kolschool; i++) {
        cout << "\nВведите номер школы: ";
        cin >> numofschool;
        // таким образом, были реализованы 2 типа конструкторов из 3. Конструктор с параметром по умолчанию смотрите во 2 файле
        if (i % 2 == 1){ // если текущий элемент не делится на 2
            journals[i] = new Journal(); // используется конструктор без параметра
            (*journals[i]).NumOfSchool(kolschool, numofschool); // передача введённых значений
        }
        else { // если текущий элемент делиться на 2
            journals[i] = new Journal(kolschool, numofschool); // используется конструктор с параметрами, в который передаются введённые значения
        }
            cout << "Введите количество учеников: ";
            cin >> kolstudents;
            // обращение к объекту через указатель "(*journals[i])" необходимо, так как в массиве лежат указатели, а не сами объекты
            (*journals[i]).NumberOfStds(kolstudents);
            for (int j = 0; j < kolstudents; j++) { // был слегка изменён ввод данных ученика, так как теперь они реализованы через перегрузку оператора
                cout << "\nВведите фамилию для " << j + 1 << " ученика : ";
                cin >> familia;
                cout << "Введите оценку для " << j + 1 << " ученика : ";
                cin >> mark;
                (*journals[i]).SetStds(familia, mark);
                averagescore += mark;
            }
            averagescore = averagescore / kolstudents;
            (*journals[i]).SaR(averagescore);
            averagescore = 0;
    }
    for (int i = 0; i < kolschool; i++) {
        cout << "\n" << (*journals[i]).Spisok();
        cout << "\n" << (*journals[i]).SpisokSt();
        cout << "\n" << (*journals[i]).AverScore();
        (*journals[i]).Idol();
    }

    for (int i = 0; i < kolschool; i++) delete journals[i]; // удаление элементов динамического массива для очистки ОЗУ

    return 0; // конец программы
}