// Так как реализовать конструктор с параметрами в файле со всеми остальными заданиями не представляется возможным,
// то было принято решение создать файл, основанный на коде только из 1 задания. Соответсвенно,
// данный файл представляет собой реализацию ТОЛЬКО задания на конструкторы, а точнее - только конструктор с параметром по умолчанию,
// в который передаётся общее количество студентов в журнале (NumberOfStudents).

#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(int _number_of_students = 2){ // в данной реализации конструктор заменяет собой ф-цию NumberOfStudents
        cout << "\n\t\t\t\t\t\t\t\tИнициализация конструктора с параметром по умолчанию для объекта " << this << "\n"; // вывод информации о инициализации конструктора
        NumberOfStudents = _number_of_students;
        students = new Student[NumberOfStudents];
    }

    ~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;
    cout << "Введите количество школ: ";
    cin >> kolschool;
    // указатель на массив с объектами класса Journal и размером kolschool
    Journal* journals[kolschool];
    for (int i = 0; i < kolschool; i++) {
        cout << "\nВведите номер школы: ";
        cin >> numofschool;
        cout << "Введите количество учеников: ";
        cin >> kolstudents;
        // если введённое количество студентов меньше 1, то конструктор по умолчанию инициализирует 
        // объект с количеством студентов равным 2, после идёт изменение переменной kolstudents на 2 для нормализации дальнейшей работы программы,
        // а также об этом выведется сообщение на экран
        if (kolstudents < 1) { cout << "Количество студентов не может быть меньше 1!\n"; journals[i] = new Journal(); kolstudents = 2; }
        else journals[i] = new Journal(kolstudents); // если количество студентов больше или равно 1, то идёт стандартная инициализация объекта как в основной реализации
        // обращение к объекту через указатель "(*journals[i])" необходимо, так как в массиве лежат указатели, а не сами объекты
        (*journals[i]).NumOfSchool(kolschool,numofschool);
            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; // конец программы
}