From 942ca610ac679dba7ed09c10829d38b29c09bccc Mon Sep 17 00:00:00 2001
From: Benjamin Auder <benjamin.auder@somewhere>
Date: Sun, 7 Jan 2018 00:42:41 +0100
Subject: [PATCH] save state

---
 js/index.js | 84 +++++++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 82 insertions(+), 2 deletions(-)

diff --git a/js/index.js b/js/index.js
index 09f0c17..b51d590 100644
--- a/js/index.js
+++ b/js/index.js
@@ -122,15 +122,95 @@ new Vue({
 				</div>
 			`,
 			methods: {
-				// TODO: clic sur "Valider" télécharge la ronde courante
+				// TODO: télécharger la ronde courante
 				// TODO: mémoriser les appariements passés pour éviter que les mêmes joueurs se rencontrent plusieurs fois
 				// --> dans la base: tableau rounds, rounds[0] : {tables[0,1,...], chacune contenant 4 indices de joueurs; + sessions[0,1,...]}
 				// --> devrait séparer les components en plusieurs fichiers...
 				// cas à 5 joueurs : le joueur exempt doit tourner (c'est fait automatiquement en fait)
 				cancelRound: function() {
-					
+					this.scored.forEach( (s,i) => {
+						if (s)
+						{
+							// Cancel this table
+							this.currentIndex = i; //TODO: clumsy. funcions should take "index" as argument
+							this.resetScore();
+						}
+					});
+					this.currentIndex = -1;
+					this.doPairings();
 				},
 				doPairings: function() {
+					let rounds = JSON.parse(localStorage.getItem("rounds"));
+
+					if (this.scored.some( s => { return s; }))
+					{
+						this.commitScores(); //TODO: temporary: shouldn't be here... (incremental commit)
+						if (rounds === null)
+							rounds = [];
+						rounds.push(this.tables);
+					}
+
+					// 1) Compute the "meeting" matrix: who played who and how many times
+					let meetMat = _.range(this.players.length).map( i => {
+						_.range(this.players.length).map( j => {
+							return 0;
+						});
+					});
+					rounds.forEach( r => { //for each round
+						r.forEach( t => { //for each table within round
+							for (let i=0; i<4; i++) //TODO: these loops are ugly
+							{
+								for (let j=0; j<4; j++)
+								{
+									if (j!=i)
+										meetMat[i][j]++;
+								}
+							}
+						});
+					});
+
+					// 2) Pre-compute tables repartition (in numbers): depends on active players count % 4
+					let activePlayers = this.players
+						.map( (p,i) => { return Object.Assign({}, p, {index:i}); })
+						.filter( p => { return p.available; });
+					let repartition = _.times(Math.floor(activePlayers.length/4), _.constant(4));
+					switch (activePlayers.length % 4)
+					{
+						case 1:
+							// Need 2 more
+							if (repartition.length-1 >= 2)
+							{
+								repartition[0]--;
+								repartition[1]--;
+								repartition[repartition.length-1] += 2;
+							}
+							break;
+						case 2:
+							// Need 1 more
+							if (repartition.length-1 >= 1)
+							{
+								repartition[0]--;
+								repartition[repartition.length-1]++;
+							}
+							break;
+					}
+
+					// 3) Sort people by total games played (increasing) - naturally solve the potential unpaired case
+					let totalGames = _.range(this.players.length).map( i => { return 0; });
+					rounds.forEach( r => {
+						r.forEach(t => {
+							t.forEach( p => {
+								totalGames[p]++;
+							})
+						})
+					});
+					let sortedPlayers = activePlayers
+						.map( (p,i) => { return Object.Assign({}, p, {games:totalGames[p.index]}); })
+						.sort( (a,b) => { return a.games - b.games; });
+
+					// 4) Affect people on tables, following total games sorted order (with random sampling on ex-aequos)
+					// --> et surtout en minimisant la somme des rencontres précédentes (ci-dessus : cas particulier rare à peu de joueurs)
+//TODO
 					// Simple case first: 4 by 4
 					let tables = [];
 					let currentTable = [];
-- 
2.44.0