/*
  In una borsa valori ideali sono quotati tre titoli azionari.
  In borsa operano n investitori.
  Essi hanno un budget iniziale da spendere per l'acquisto di azioni.
  Essi decidono ogni giorno, con l'aiuto di CONSULENTI privati che li consigliano,
  gli acquisti e le vendite da fare e se compatibili
  con il budget tali acquisti producono il loro "portafoglio".
  Il prezzo delle azioni viene cambiato in maniera random da un giorno all'altro
  producendo un aggiornamento nel valore del portafoglio degli investitori.
  Al termine del quinto giorno di contrattazioni per ciascun investitore
  si calcola il guadagno o perdita complessiva subita rispetto al budget iniziale e viene
  assegnato il titolo di "fesso della settimana" o "genio della finanza".
*/

interface costanti {
  /*
    Dimostrazione di come usare le interfacce per definire valori
    costanti da importare all'interno delle classi.
    Notare che il modificatore di accesso "public" e la parola chiave "static"
    sono FACOLTATIVI, dato che la variabili dichiarate dentro una interfaccia
    sono IMPLICITAMENTE FINAL e STATIC!!
  */
  int VENDI                     = 0;
  int COMPRA                    = 1;
  int NONOPERATIVO              = 2;
  int NUMCLIENTI                = 5;
  float CAPITALEINIZIALE        = 100;
  int NUMTITOLI                 = 3;
  int GIORNI                    = 5;
}

/* *********************************************
   **********Classe INVESTITORE*****************
  ********************************************* */
class investitore {
  private float initialbudget;
  private float currentbudget;
    
  //costruttire
  investitore(float capitaleiniziale) {
    initialbudget = capitaleiniziale;  
    currentbudget = initialbudget;
  }
  
  //metodi pubblici
  public void vendo(int numazioni, float prezzo) {
    float importo = numazioni * prezzo;
    currentbudget += importo;
  }
  
  public void compro(int numazioni, float prezzo) {
    float importo = numazioni * prezzo;
    if (importo <= currentbudget) currentbudget -= importo;
    else System.out.println("\t\tNon ho abbastanza soldi!!");
  }  
  
  //Quanto possiedo in questo momento?
  public float getCurrentbudget() {
    return currentbudget;
  }
  /*
    calcola il guadagno come differenza tra il valore iniziale e quello
    ottenuto a borsa chiusa. Se il valore è >0 allora ha guadagnato,
    altrimenti ha perso.
  */
  public float getGuadagno() {
    return currentbudget - initialbudget;
  }
}



/* *********************************************
   **************Classe TITOLO******************
   ********************************************* */
class titolo {
  private String nome;
  private float valore;
  //costruttore
  titolo(String nome, float valore) {
    this.nome = nome;
    this.valore = valore;
  }
  //metodi pubblici
  public String getNome()       {return nome;}
  public float getValore()      {return valore;}
  
  public void aggiorna() {
    int delta = (int)(Math.random() * 11) - 5 ;      //numero casuale tra -5 e 5
    valore += delta;
    if (valore < 0) valore=0;
  }
}

/* *********************************************
   **********Classe CONSULENTE******************
   *********************************************
    Il consulente (privato per ogni investitore),
    consiglia il suo cliente su quale titolo e
    quante azioni vendere o comprare.
*/
class consulente implements costanti{
  private int[] IDTitolo;       //Contiene i codici dei titoli su cui investire
  private int[] numazioni;      //Contiene il numero di azioni da investire
  private int consiglio[];     //Contiene il consiglio: se vendere(0),comprare(1), o stare fermo(2)
  /* Il consulente si pianifica i giorni di contrattazione
     stabilendo giorno per giorno cosa consigliare al
     suo cliente */
  consulente(int giorni) {
    IDTitolo = new int[giorni];
    numazioni = new int[giorni];
    consiglio = new int[giorni];
    //PIANIFICA per tutti i giorni!!
    for (int c=0; c<giorni; c++) {
      IDTitolo[c] = (int)(Math.random() * NUMTITOLI);   //stabilisce quale azione vend/comp
      numazioni[c] = (int)(Math.random() * 10);          //stab. quanto investire
      consiglio[c] = (int)(Math.random() * 3);           //vendere,comprare o stare fermi?
    }
  }
  
  //metodi pubblici
  public int getIDTitolo(int giorno) {return IDTitolo[giorno];}
  public int getNumazioni(int giorno) {return numazioni[giorno];}
  public int getConsiglio(int giorno) {return consiglio[giorno];}
  
}



/* *********************************************
   **********CLASSE PRINCIPALE******************
   *******(contiene il metodo main)*************
   *********************************************
*/
public class borsa implements costanti {
  
  public static void main(String[] args) {
    
    //creo gli investitori e i loro PERSONALI consulenti
    investitore[] clienti = new investitore[NUMCLIENTI];
    consulente[] consulenti = new consulente[NUMCLIENTI];
    //inizializzo clienti  e consulenti
    for (int i=0; i<NUMCLIENTI; i++) {
      clienti[i] = new investitore(CAPITALEINIZIALE);
      //creo un consulente col n° di giorni da pianificare
      consulenti[i] = new consulente(GIORNI);
    }
    
    
    //creo i titoli
    titolo[] titoli = new titolo[NUMTITOLI];
    titoli[0] = new titolo("FIAT", 10);
    titoli[1] = new titolo("TORO", 12);
    titoli[2] = new titolo("TELECOM", 8);
    
    
    //variabili gestite dai consulenti durante le giornate di contrattazione
    int unTitolo;               //il titolo consigliato dal consulente
    int unNumeroazioni;         //il numero di azioni consigliate dal consulente
    int unConsiglio;            //consiglio del consulente su vendere, comprare, stare fermi
    String tipoAzione="";
  
    System.out.println("LA BORSA E' APERTA!!!!");
    System.out.println("(Ci saranno " + GIORNI + " giorni di contrattazioni)\n");
    
    //Iniziano le giornate
    for (int g=0; g<GIORNI; g++) {
      
      System.out.println("***********Inizio " + (g+1) + "° giorno di contrattazione***************");
      
      //Aggiornamento dei titoli per la giornata odierna
      System.out.println("Oggi i titoli valgono:");
      for (int t=0; t<NUMTITOLI; t++) {
        titoli[t].aggiorna();
        System.out.println("\t" + titoli[t].getNome() + ": " + titoli[t].getValore());
      }
      System.out.println();
      
      //tutti i clienti fanno le loro contrattazioni
      for (int k=0; k<NUMCLIENTI; k++) {
        
        //consideriamoli uno ad uno: un consulente a tu per tu con un investitore
        consulente ilConsulente = consulenti[k];
        investitore ilCliente = clienti[k];
        
        //Cosa consiglia il consulente oggi?
          unTitolo         = ilConsulente.getIDTitolo(g);    //Di questo specifico TITOLO...
          unNumeroazioni   = ilConsulente.getNumazioni(g);   //...investi questo NUMERO DI AZIONI...
          unConsiglio      = ilConsulente.getConsiglio(g);   //...effettuando una [vendita|acquisto|nothing]
        
        //Il cliente obbedisce ai consigli del SUO consulente
        if (unConsiglio == VENDI) {
          ilCliente.vendo(unNumeroazioni, titoli[unTitolo].getValore());
          tipoAzione = "VENDE";
        }
        else if (unConsiglio == COMPRA) {
          ilCliente.compro(unNumeroazioni, titoli[unTitolo].getValore());
          tipoAzione = "COMPRA";
        }
        else
          tipoAzione = "NON OPERA!\n";
        //Messaggio che informa della transazione avvenuta
          System.out.print("\t- Cliente n°" + (k+1) + " " + tipoAzione);
          if (unConsiglio < 2)
            System.out.println(" n°" + unNumeroazioni + " azioni " +
                        titoli[unTitolo].getNome() + " (portafoglio attuale: " + ilCliente.getCurrentbudget() +")");          

      }
      
      System.out.println("***********Fine del " + (g+1) + "° giorno di contrattazione***************\n");
      
    }
    
    System.out.println("LA BORSA E' CHIUSA!!!!\n");
    
    //Determinazione del miglior investitore
    float max=0, min=0;
    int itemMax=0, itemMin=0;
    System.out.println("Situazione degli investitori:\n");
    for (int i=0; i<NUMCLIENTI; i++) {
      System.out.print("\t- Cliente n°" + (i+1) +" ");
      if(clienti[i].getGuadagno()>0) {
        System.out.println("ha GUADAGNATO " + clienti[i].getGuadagno() + " euro");
        if (clienti[i].getGuadagno()>max) {max=clienti[i].getGuadagno(); itemMax=i;}
      }
      else {
        System.out.println("ha PERSO " + clienti[i].getGuadagno()*-1 + " euro");
        if (clienti[i].getGuadagno()<min) {min=clienti[i].getGuadagno(); itemMin=i;}
      }
    }
    
    if(max>0) System.out.println("\nIl GENIO DELLA FINANZA e' stato Cliente n°" +(itemMax+1)+", che ha guadagnato "+max+" euro.");
    if(min<0) System.out.println("Il FESSO DELLA SETTIMANA e' stato Cliente n°" +(itemMin+1)+", che ha perso "+min*-1+" euro.");
  }
}