4 players: [], //array of objects, filled later
15 <tr v-for="p in sortedPlayers" v-if="p.available" @click="toggleAvailability(p.index)">
16 <td>{{ p.prenom }}</td>
24 <tr v-for="p in sortedPlayers" v-if="!p.available" @click="toggleAvailability(p.index)">
25 <td>{{ p.prenom }}</td>
33 sortedPlayers: function() {
35 .map( (p
,i
) => { return Object
.assign({}, p
, {index: i
}); })
37 return a
.nom
.localeCompare(b
.nom
);
42 toggleAvailability: function(i
) {
43 this.players
[i
].available
= 1 - this.players
[i
].available
;
44 this.$forceUpdate(); //TODO (Vue.set... ?!)
57 <table class="ranking">
61 <th @click="sortMethod='score'" class="scoring" :class="{active: sortMethod=='score'}">Score</th>
62 <th @click="sortMethod='pdt'" class="scoring" :class="{active: sortMethod=='pdt'}">PdT</th>
64 <tr v-for="(p,i) in sortedPlayers">
66 <td>{{ p.prenom }} {{ p.nom }}</td>
67 <td>{{ p.score }}</td>
74 sortedPlayers: function() {
75 let sortFunc
= this.sortMethod
== "score"
79 .map( p
=> { return p
; }) //to not alter original array
84 sortByScore: function(a
,b
) {
85 return b
.score
- a
.score
;
87 sortByPdt: function(a
,b
) {
97 tables: [], //array of arrays of players indices
98 scores: [], //scores for each table (3 or 4 players)
99 pdts: [], //"points de table" for each table (3 or 4 players)
100 currentIndex: -1, //table index for scoring
105 <div v-show="currentIndex < 0">
106 <button class="block btn" @click="shuffle()">Appariement</button>
107 <div class="pairing" v-for="(table,index) in tables" :class="{scored: scores[index].length > 0}"
108 @click="showScoreForm(table,index)">
109 <p>Table {{ index+1 }}</p>
111 <tr v-for="(i,j) in table">
112 <td>{{ players[i].prenom }} {{ players[i].nom }}</td>
113 <td class="score"><span v-show="pdts[index].length > 0">{{ pdts[index][j] }}</span></td>
115 <tr v-if="table.length < 4">
121 <div v-if="unpaired.length>0" class="pairing unpaired">
123 <div v-for="i in unpaired">
124 {{ players[i].prenom }} {{ players[i].nom }}
128 <div id="scoreInput" v-if="currentIndex >= 0">
130 <tr v-for="(index,i) in tables[currentIndex]">
131 <td>{{ players[tables[currentIndex][i]].prenom }} {{ players[tables[currentIndex][i]].nom }}</td>
132 <td><input type="text" v-model="pdts[currentIndex][i]" value="0"/></td>
135 <div class="button-container">
136 <button class="btn" @click="setScore()">Enregistrer</button>
137 <button class="btn cancel" @click="resetScore()">Annuler</button>
143 doPairings: function() {
144 // Simple case first: 4 by 4
146 let currentTable
= [];
147 let ordering
= _
.shuffle(_
.range(this.players
.length
)); //TODO: take scores into account?
148 for (let i
=0; i
<ordering
.length
; i
++)
150 if ( ! this.players
[ordering
[i
]].available
)
152 if (currentTable
.length
>= 4)
154 tables
.push(currentTable
);
157 currentTable
.push(ordering
[i
]);
161 if (currentTable
.length
!= 0)
163 if (currentTable
.length
< 3)
165 let missingPlayers
= 3 - currentTable
.length
;
166 // Pick players from 'missingPlayers' random different tables, if possible
167 if (tables
.length
>= missingPlayers
)
169 let tblNums
= _
.sample(_
.range(tables
.length
), missingPlayers
);
170 tblNums
.forEach( num
=> {
171 currentTable
.push(tables
[num
].pop());
175 if (currentTable
.length
>= 3)
176 tables
.push(currentTable
);
178 this.unpaired
= currentTable
;
180 this.tables
= tables
;
181 this.scores
= tables
.map( t
=> { return []; }); //empty scores
182 this.pdts
= tables
.map( t
=> { return []; }); //empty pdts
184 shuffle: function() {
187 showScoreForm: function(table
,index
) {
188 if (this.scores
[index
].length
> 0)
189 return; //already scored
190 this.scores
[index
] = _
.times(table
.length
, _
.constant(0));
191 this.pdts
[index
] = _
.times(table
.length
, _
.constant(0));
192 this.currentIndex
= index
;
194 setScore: function() {
195 let sortedPdts
= this.pdts
[this.currentIndex
]
196 .map( (s
,i
) => { return {value:s
, index:i
}; })
197 .sort( (a
,b
) => { return parseInt(b
.value
) - parseInt(a
.value
); });
198 let scores
= [4, 2, 1, 0]; //TODO: biased for 3-players tables. TODO: ex-aequos ?!
199 for (let i
=0; i
<this.tables
[this.currentIndex
].length
; i
++)
201 this.players
[this.tables
[this.currentIndex
][sortedPdts
[i
].index
]].score
+= scores
[i
];
202 this.players
[this.tables
[this.currentIndex
][i
]].pdt
+= parseInt(this.pdts
[this.currentIndex
][i
]);
204 this.currentIndex
= -1;
205 this.writeScoreToDb();
207 resetScore: function() {
208 this.scores
[this.currentIndex
] = [];
209 this.pdts
[this.currentIndex
] = [];
210 this.currentIndex
= -1;
212 writeScoreToDb: function()
214 let xhr
= new XMLHttpRequest();
215 xhr
.open("POST", "scripts/rw_players.php");
216 xhr
.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
217 let orderedPlayers
= this.players
218 .map( p
=> { return Object
.assign({}, p
); }) //deep (enough) copy
219 .sort( (a
,b
) => { return b
.score
- a
.score
; });
220 xhr
.send("players="+encodeURIComponent(JSON
.stringify(orderedPlayers
)));
225 created: function() {
226 let xhr
= new XMLHttpRequest();
228 xhr
.onreadystatechange = function() {
229 if (this.readyState
== 4 && this.status
== 200)
231 let players
= JSON
.parse(xhr
.responseText
);
232 players
.forEach( p
=> {
233 p
.score
= !!p
.score
? parseInt(p
.score
) : 0;
234 p
.pdt
= !!p
.pdt
? parseInt(p
.pdt
) : 0;
235 p
.available
= !!p
.available
? p
.available : 1; //use integer for fputcsv PHP func
237 self
.players
= players
;
240 xhr
.open("GET", "scripts/rw_players.php", true);