/*
    Exemplo de agregacao - exercicio 6 descrito em:
	http://gse.ufsc.br/bezerra/disciplinas/cpp/aulas/dia1_9_4.html
*/

#include <iostream>
#include <stdlib.h>

using namespace std;

class Aluno
{
     private:
     int matr;
     float n1;
     float n2;
     public:
     void setMatr(int matr);
     void setN1(float nota1);
     void setN2(float nota2);
     int getMatr();
     float getN1();
     float getN2();
     float calcMedia();
};

class VetAluno
{
    private:
    Aluno vAlunos[20];
    bool valido[20];
    public:
    VetAluno();
    void listaVet();
    void inclui(int matr, float n1, float n2);
    void exclui(int matr);
    void consulta(int matr);
    void altera(int matr);
};

int main()
{
   bool sair = false;
   int opcao, matr;
   float n1, n2;
   VetAluno CadAlunos;
   cout << "Programa de cadastro de alunos - EEL 510232 - UFSC 2015";
    do
     {
         //Mostra todas as opções
         cout << "\n1. Cadastrar aluno" << endl;
         cout << "2. Consultar aluno" << endl;
         cout << "3. Listar turma" << endl;
         cout << "4. Excluir aluno" << endl;
         cout << "5. Alterar aluno" << endl;
         cout << "6. Sair" << endl;
         cout << "Digite a opcao desejada: ";
         cin >> opcao;
         //Switch para direcionar a escolha aos metodos da classe CadAlunos
         switch (opcao)
         {
             case 1:
                 cout << "\nDigite a matricula: "; cin >> matr;
                 cout << "Digite a nota 1: "; cin >> n1;
                 cout << "Digite a nota 2: "; cin >> n2;
                 CadAlunos.inclui(matr,n1,n2);
                 break;
             case 2:
                cout << "\nDigite a matricula do aluno a consultar: "; cin >> matr;
                CadAlunos.consulta(matr);
                break;
             case 3:
                cout << "\nOpcao listar turma, listando:\n";
                CadAlunos.listaVet();
                break;
             case 4:
                cout << "\nDigite a matricula do aluno a excluir: "; cin >> matr;
                CadAlunos.exclui(matr);
                break;
             case 5:
                cout << "\nDigite a matricula do aluno a consultar: "; cin >> matr;
                CadAlunos.altera(matr);
                break;
             case 6:
                sair = true;
                break;
             default:
                cout << "\nA opcao digitada nao existe! Tente novamente. \n\n";
         }
     } while(!sair);
   return 0;
}

// Montando cada um dos métodos para a classe alunos
void Aluno::setMatr(int matricula)
{
    matr = matricula;
}
void Aluno::setN1(float nota1)
{
    n1 = nota1;
}
void Aluno::setN2(float nota2)
{
    n2 = nota2;
}
int Aluno::getMatr()
{
    return matr;
}
float Aluno::getN1()
{
    return n1;
}
float Aluno::getN2()
{
    return n2;
}
float Aluno::calcMedia()
{
    return (n1+n2)/2;
}

//Montando cada um dos métodos para a classe VetAluno
//Metodo construtivo com objetivo de inicializar a classe de maneira correta
VetAluno::VetAluno()
{
    for(int i=0; i<20; i++)
    {
        valido[i]=0;            // Liberar a escrita no vetor vAlunos
        vAlunos[i].setMatr(-1); // Evitar problemas de matricula duplicada
    }
}
//Metodo para a listagem dos alunos da turma
void VetAluno::listaVet()
{
    for (int i=0; i<20; i++)
    {
        if(valido[i])
        {
           cout << "Aluno matricula: " << vAlunos[i].getMatr() << endl;
           cout << "Nota prova 1: " << vAlunos[i].getN1() << endl;
           cout << "Nota prova 2: " << vAlunos[i].getN2() << endl;
           cout << "Media final: " << vAlunos[i].calcMedia() << endl << endl;
        }
    }
}
//Metodo para a inclusao de alunos
/*
    Realizei algumas modificacoes em relacao a aula,
    porem a ideia foi bem semelhante
*/
void VetAluno::inclui(int matr, float n1, float n2)
{
    int i = 0;
    int guardaPosicao;
    bool sai = false;
    bool termina = false;
    do
    {
        for (int x=0; x<20; x++)
        {
            if (matr == vAlunos[x].getMatr())
            {
                cout << "Matricula duplicada! Erro" << endl;
                sai = true;
            }
        }
        if (!sai && !valido[i])
        {
            guardaPosicao = i;
            termina = true;
        }
        i++;
    } while (i<20 && !sai && !termina);
    // Caso sai = true, o encerramento foi devido a um problema de matricula
    // duplicada, nao podendo ser gravado os dados no objeto
    // A flag 'termina' existe para direcionar o fluxo caso haja um espaco livre no vetor valido[i]
    if (!sai && termina)
    {
        vAlunos[guardaPosicao].setMatr(matr);
        vAlunos[guardaPosicao].setN1(n1);
        vAlunos[guardaPosicao].setN2(n2);
        valido[guardaPosicao] = 1; // Indica o preenchimeto de um objeto
    }
}
//Metodo para a exclusao de um aluno. Caso a matricula digitada for correta, libera-se a escrita atraves
//do vetor de controle 'valido'
void VetAluno::exclui(int matr)
{
    bool found = 0;
    int i = 0;
    while (!found && i<20)
    {
        if (matr == vAlunos[i].getMatr())
        {
            found = 1;
            valido[i] = 0;
            vAlunos[i].setMatr(-1); //Numero invalido para liberar o repreenchimento
            cout << "Aluno excluido!\n\n";
        }
        i++;
    }
    if (!found) cout << "Aluno nao encontrado! Tente novamente.\n\n";
}
//Metodo para consulta de apenas uma matricula
void VetAluno::consulta(int matr)
{
    bool found = 0;
    int i = 0;
    while (!found && i<20)
    {
        if (matr == vAlunos[i].getMatr())
        {
            found = 1;
            cout << "Nota 1: " << vAlunos[i].getN1() << endl;
            cout << "Nota 2: " << vAlunos[i].getN2() << endl;
            cout << "Media final: " << vAlunos[i].calcMedia() << endl << endl;
        }
        i++;
    }
    if (!found) cout << "Aluno nao encontrado! Tente novamente.\n\n";
}
//Alteracao das notas de um determinado aluno
void VetAluno::altera(int matr)
{
    bool found = 0;
    int i = 0;
    float nota1, nota2;
    while (!found && i<20)
    {
        if (matr == vAlunos[i].getMatr())
        {
            found = 1;
            cout << "Digite a nova nota 1: "; cin >> nota1;
            cout << "\nDigite a nova nota 2: "; cin >> nota2;
            vAlunos[i].setN1(nota1);
            vAlunos[i].setN2(nota2);
        }
        i++;
    }
    if (!found) cout << "Aluno nao encontrado! Tente novamente.\n\n";
}
