/*
Si considerino cinque studenti.
Un primo tipo di studenti segue i corsi A e B.
Un secondo tipo di studenti segue i corsi A, B e C.
Per ciascuno studente si vuole mantenere informazione relativamente al suo nome
(tratto a caso dall'insieme {"Silvia", "Guido","Mattia", "Angelo", "Marina"}).
Si vuole anche  mantenere informazione riguardo ai voti conseguiti nei corsi frequentati.

Scrivere codice JAVA che consenta di:
a) inizializzare a caso l'insieme degli studenti;
b) stampare a schermo informazioni complete su tutti gli studenti (ridefinendo il metodo toString());
c) stampare il nome dello studente com media massima e dello studente con media minima;
d) dire se ci sono due studenti con lo stesso nome;

*/
interface nominativi {
  public static final String[] NOMI = {"Silvia", "Guido", "Angelo", "Marina"};
}

abstract class studente implements nominativi {
  protected String nome;
  protected int votoA, votoB;
  //costruttore
  public studente() {
    nome = NOMI[(int)(Math.random()*NOMI.length)];
    votoA = (int)(Math.random()*13+18);
    votoB = (int)(Math.random()*13+18);
  }
  //metodo astratto (la media dipende dal numero di corsi seguiti)
  abstract float getMedia();
  
  //metodi pubblici
  public int getVotoA() {return votoA;}
  public int getVotoB() {return votoB;}
  public String getNome() {return nome;}
}

class studAB extends studente {
  //questo studente segue i corsi A e B
  public studAB() {super();}
  //metodo implementato
  public float getMedia() {return (votoA + votoB) / 2;}
  
  public String toString() {return nome + " frequenta i corsi A e B "+
                            "VotoA="+votoA+" VotoB="+votoB;}
}

class studABC extends studente {
  //questo studente segue i corsi A B C
  private int votoC;
  public studABC() {
    super();
    votoC = (int)(Math.random()*13+18);
  }
  //metodo implementato
  public float getMedia() {return (votoA + votoB + votoC) / 3;}

  public String toString() {return nome + " frequenta i corsi A, B e C "+
                            "VotoA="+votoA+" VotoB="+votoB+" VotoC="+votoC;}
}

class corso {
  private int numstud;  //numero studenti
  //costruttore
  private studente[] studenti;
  public corso(int ns) {
    numstud = ns;
    studenti = new studente[numstud];
    for (int c=0; c < numstud; c++)
      if (Math.random()>.5) studenti[c] = new studAB();
      else studenti[c] = new studABC();
  }
  //metodi pubblici
  public void stampa() {
    for (int c=0; c < numstud; c++)
      System.out.println(studenti[c]);
  }
  
  public void stampaMediaMax() {
    //calcola la media max per ogni studente
    float max=0; int index=0;
    for (int c=0; c < numstud; c++)
      if (studenti[c].getMedia() > max) {
        max = studenti[c].getMedia();
        index = c;
      }
    System.out.println("Studente con media massima: " + studenti[index] +
                       "\nMedia= " + max);
      
  }
  
  public void stampaMediaMin() {
    //calcola la media min per ogni studente
    float min=studenti[0].getMedia(); int index=0;
    for (int c=0; c < numstud; c++)
      if (studenti[c].getMedia() < min) {
        min = studenti[c].getMedia();
        index = c;
      }
    System.out.println("Studente con media minima: " + studenti[index] +
                       "\nMedia= " + min);
          
  }
 
  //controlla se ci sono doppioni
  public void stampaDoppioni() {
    System.out.println("Doppioni:");
    String[] doppi = new String[numstud/2];
    int cnt = 0; boolean flag;
    for (int c = 0; c < numstud - 1; c++) {
      flag = false;
      for (int d = c + 1; d < numstud; d++)
        if (studenti[c].getNome().equals(studenti[d].getNome())) {
          //inserisce in un vettore solo se sono doppioni "unici"
          for (int k=0; k<cnt; k++)
            if (doppi[k].equals(studenti[c].getNome())) flag = true;
          //put!
          if (!flag) {
            doppi[cnt++] = studenti[c].getNome();
            System.out.println("\t -" + studenti[c].getNome());
          }
        }
    }
  }
}

public class Cinquestudenti {
  public static void main(String[] args) {
    corso classe = new corso(5);
    classe.stampa();
    classe.stampaMediaMax();
    classe.stampaMediaMin();
    classe.stampaDoppioni();
  }
}