/**
 * @fileOverview Calculateur de classement Elo et une fonction exemple "process" pour montrer comment l'utiliser.
 * @author Samuel GIFFARD a.k.a Mulugrutz
 * @version 1.0.42
 */

/**
 * Le K value représente le maximum de points qu'une entité peut gagner/perdre en un match.
 * @constant
 * @type entier
 */
var K_VALUE = 64;

/**
 * La différence de classement Elo à partir de laquelle il n'est plus intéressant de jouer contre.
 * @constant
 * @type entier
 */
var RANGE = 400;

/**
 * Cette fonction sert à calculer le classement elo après un match entre
   deux entités (équipe ou joueur), en connaissant le vainqueur.
		<br>Appelée par {@link process}.
		<br>Appelle {@link elo_calculator}.
 * @param {entier} elo1 Le classement Elo de la première entité
 * @param {entier} elo2 Le classement Elo de la deuxième entité
 * @param {booléen} result Si vrai, entité 1 gagne. Si faux, entité 2 gagne.
 * @returns {Tableau Associatif JS} ('new_elo1'=>xx1,'new_elo2'=>xx2,'change1'=>yy1,'change2'=>yy2) avec:
   <br>new_elo1 {entier} First entity's new elo rating
   <br>new_elo2 {entier} Second entity's new elo rating
   <br>change1 {Chaîne de caractères} Le nombre de points gagnés/perdus par l'entité 1
   <br>change2 {Chaîne de caractères} Le nombre de points gagnés/perdus par l'entité 2
 */
function easy_elo(elo1,elo2,result)
{
	return elo_calculator((result?1:0),(result?0:1),elo1,elo2);
}

/**
 * Cette fonction sert à calculer le classement elo après un match entre
   deux entités (équipe ou joueur), en connaissant le score.
		<br>Appelée par {@link easy_elo} et {@link process}.
 * @param {entier} score1 Le score de la première entité
 * @param {entier} score2 Le score de la deuxième entité
 * @param {entier} elo1 Le classement Elo de la première entité
 * @param {entier} elo2 Le classement Elo de la deuxième entité
 * @returns {Tableau Associatif JS} ('new_elo1'=>xx1,'new_elo2'=>xx2,'change1'=>yy1,'change2'=>yy2) avec:
   <br>new_elo1 {entier} First entity's new elo rating
   <br>new_elo2 {entier} Second entity's new elo rating
   <br>change1 {Chaîne de caractères} Le nombre de points gagnés/perdus par l'entité 1
   <br>change2 {Chaîne de caractères} Le nombre de points gagnés/perdus par l'entité 2
 */
function elo_calculator(score1,score2,e1,e2)
{
	var elo1 = parseInt(e1);
	var elo2 = parseInt(e2);
	var e;
	var r = [];
	if(score1 != score2)	// le match n'est pas une égalité, il existe un vainqueur
	{
		if(score1 > score2)	// le vainqueur est l'entité 1
		{
			e=K_VALUE-Math.round(1/(1+Math.pow(10,((elo2-elo1)/RANGE)))*K_VALUE);
			r['new_elo1'] = elo1 + e;
			r['new_elo2'] = elo2 - e;
		}
		else				// le vainqueur est l'entité 2
		{
			e=K_VALUE-Math.round(1/(1+Math.pow(10,((elo1-elo2)/RANGE)))*K_VALUE);
			r['new_elo1'] = elo1 - e;
			r['new_elo2'] = elo2 + e;
		}
	}
	else					// le match est une égalité, il n'existe pas de vainqueur
	{
		if(elo1 == elo2)	// les deux entités ont le même classement elo
		{
			r['new_elo1'] = elo1;
			r['new_elo2'] = elo2;
		}
		else				// les deux entités n'ont pas le même classement elo
		{
			if(elo1 > elo2)	// l'entité 1 a un classement elo plus élevé
			{
				e=(K_VALUE-Math.round(1/(1+Math.pow(10,((elo1-elo2)/RANGE)))*K_VALUE))-(K_VALUE-Math.round(1/(1+Math.pow(10,((elo2-elo1)/RANGE)))*K_VALUE));
				r['new_elo1'] = elo1 - e;
				r['new_elo2'] = elo2 + e;
			}
			else			// l'entité 2 a un classement elo plus élevé
			{
				e=(K_VALUE-Math.round(1/(1+Math.pow(10,((elo2-elo1)/RANGE)))*K_VALUE))-(K_VALUE-Math.round(1/(1+Math.pow(10,((elo1-elo2)/RANGE)))*K_VALUE));
				r['new_elo1'] = elo1 + e;
				r['new_elo2'] = elo2 - e;
			}
		}
	}
	r['change1'] = ((r['new_elo1'] - elo1) > 0) ? ('+'+(r['new_elo1'] - elo1)) : ((r['new_elo1'] - elo1)+'');
	r['change2'] = ((r['new_elo2'] - elo2) > 0) ? ('+'+(r['new_elo2'] - elo2)) : ((r['new_elo2'] - elo2)+'');
	return r;
}

/**
 * Cette fonction est un exemple pour montrer comment utiliser le calculateur elo
		<br>Appelle {@link easy_elo} et {@link elo_calculator}.
 * @param {booléen} easy Si vrai, utilise le calculateur simplifié. Si faux, utilise le calculateur complet.
 * @returns {booléen} Pour arrêter les futurs évènements, si nécessaire.
 */
function process(easy)
{
	// On associe des handles aux objets HTML
	var elo1 = document.getElementById('id_elo1');
	var elo2 = document.getElementById('id_elo2');
	var score1 = document.getElementById('id_score1');
	var score2 = document.getElementById('id_score2');
	var change1 = document.getElementById('id_change1');
	var change2 = document.getElementById('id_change2');
	var new_elo1 = document.getElementById('id_new_elo1');
	var new_elo2 = document.getElementById('id_new_elo2');
	var output = document.getElementById('id_output_text');
	
	// On choisit quelle fonction sera exécutée plus tard (fermeture)
	var fnc;
	if(easy)
	{
		fnc = (function(){ 
			output.innerHTML = "Contrôle simplifié terminé...";
			if(score1.value != score2.value) return easy_elo(elo1.value,elo2.value,(parseInt(score1.value) > parseInt(score2.value)));
			else return false;
		});
	}
	else
	{
		fnc = (function(){
			output.innerHTML = "Contrôle complet terminé...";
			return elo_calculator(score1.value,score2.value,elo1.value,elo2.value);
		});
	}
	
	// On exécute la fonction sélectionnée et on stocke les résultats
	var r = fnc();
	
	// Si on n'a pas utilisé le calculateur simplifié alors que le match est nul
	if(r !== false)
	{
		change1.innerHTML = r['change1'];
		change2.innerHTML = r['change2'];
		new_elo1.value = r['new_elo1'];
		new_elo2.value = r['new_elo2'];
	}
	else
	{
		output.innerHTML += "<br>Attention : le contrôle simplifié n'est possible que s'il existe un vainqueur... Là, il y a égalité !!!";
		change1.innerHTML = "";
		change2.innerHTML = "";
		new_elo1.value = "";
		new_elo2.value = "";
	}
	return false;
}