/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package mcts;

//import java.util.Collections;
//import java.util.Comparator;

/**
 *
 * @author Lloyd
 */
public class UCT {
    
    public static double calculUCT(int nbVisiteParent, double scoreVictoire, int nbVisiteEnfant, double coefficientUCT) {
        if (nbVisiteEnfant == 0) {
            return Integer.MAX_VALUE;
        }
        return (scoreVictoire / (double) nbVisiteEnfant + coefficientUCT *  Math.sqrt(Math.log(nbVisiteParent) / (double) nbVisiteEnfant));
    }
    
    public static Noeud trouverNoeudPrometteurUCT(Noeud noeud, double coefficient) {
        int nbVisiteParent = noeud.getEtat().getNbVisite();
        Noeud noeudPrometteur = null;
        double uctNoeudPrometteur = Integer.MIN_VALUE;
        
        for (Noeud enfant : noeud.getListeEnfant()) {
            double scoreVictoireEnfant = enfant.getEtat().getScoreVictoire();
            int nbVisiteEnfant = enfant.getEtat().getNbVisite();
            double valeurUCTenfant = calculUCT(nbVisiteParent, scoreVictoireEnfant, nbVisiteEnfant, coefficient); 
                    
            if (valeurUCTenfant > uctNoeudPrometteur) {
                uctNoeudPrometteur = valeurUCTenfant;
                noeudPrometteur = enfant;
            }
        }
        
        return noeudPrometteur;
    }
    
    
    
    
    
    
    
    
    
    
    
    
    // !! TESTS PAS FINIS !!
    
    //RAVE SANS UCT
    
    public static double calculTEST(int nbVisiteParent, int nbVisiteEnfant, double scoreDernierCoup, int nbDernierCoup, double coefficientUCT) {
        if (nbVisiteEnfant == 0) {
            return Integer.MAX_VALUE;
        }
        return  scoreDernierCoup / (double) nbDernierCoup + coefficientUCT * Math.sqrt(Math.log(nbVisiteParent) / (double) nbVisiteEnfant);
    }
    
    public static Noeud trouverNoeudPrometteurTEST(Noeud noeud, double coefficientUCT) {
        int nbVisiteParent = noeud.getEtat().getNbVisite();
        Noeud noeudPrometteur = null;
        double testNoeudPrometteur = Integer.MIN_VALUE;
        
        for (Noeud enfant : noeud.getListeEnfant()) {
            int nbVisite = enfant.getEtat().getNbVisite();
            double scoreDernierCoup = enfant.getEtat().getScoreDernierCoup();
            int nbDernierCoup = enfant.getEtat().getNbDernierCoup();
            double valeurTEST = calculTEST(nbVisiteParent, nbVisite, scoreDernierCoup, nbDernierCoup, coefficientUCT);
                    
            if (valeurTEST > testNoeudPrometteur) {
                testNoeudPrometteur = valeurTEST;
                noeudPrometteur = enfant;
            }
        }
        
        return noeudPrometteur;
    }
    
    public static double calculRAVE(int nbVisiteParent, 
            double scoreVictoire, int nbVisiteEnfant, double scoreDernierCoup, int nbDernierCoup, double coefficientUCT, double coefficientRAVE) {
        if (nbVisiteEnfant == 0) {
            return Integer.MAX_VALUE;
        }
        double ratioUCT = scoreVictoire / (double) nbVisiteEnfant;
        double ratioRAVE = scoreDernierCoup / (double) nbDernierCoup;
        double beta = (double) nbDernierCoup / (2 * (double) nbVisiteEnfant + (double) nbDernierCoup 
                + coefficientRAVE * (double) nbDernierCoup * (double) nbVisiteEnfant);
        //double exploitation = (1-beta) * ratioUCT + beta * ratioRAVE;
        //double exploration = coefficientUCT * Math.sqrt(Math.log(nbVisiteParent) / (double) nbVisiteEnfant);
        return (1-beta) * ratioUCT + beta * ratioRAVE + ( coefficientUCT * Math.sqrt(Math.log(nbVisiteParent) / (double) nbVisiteEnfant) );
        //return (1-beta) * ratioUCT + beta * ratioRAVE;
    }
    
    public static Noeud trouverNoeudPrometteurRAVE(Noeud noeud, double coefficientUCT, double coefficientRAVE) {
        int nbVisiteParent = noeud.getEtat().getNbVisite();
        Noeud noeudPrometteur = null;
        double raveNoeudPrometteur = Integer.MIN_VALUE;
        
        for (Noeud enfant : noeud.getListeEnfant()) {
            double scoreVictoire = enfant.getEtat().getScoreVictoire();
            int nbVisite = enfant.getEtat().getNbVisite();
            double scoreDernierCoup = enfant.getEtat().getScoreDernierCoup();
            int nbDernierCoup = enfant.getEtat().getNbDernierCoup();
            double valeurRAVE = calculRAVE(nbVisiteParent, scoreVictoire, nbVisite, scoreDernierCoup, nbDernierCoup, coefficientUCT, coefficientRAVE);
            
                    
            if (valeurRAVE > raveNoeudPrometteur) {
                raveNoeudPrometteur = valeurRAVE;
                noeudPrometteur = enfant;
            }
        }
        
        return noeudPrometteur;
    }
}