1
+ import { createInitialRating , findBestTeamMatch , updateRatings } from './elo.js' ;
2
+
1
3
const LOCAL_STORAGE_KEY = "matche_days" ;
4
+ const LOCAL_STORAGE_ELO_KEY = "players_elo" ;
5
+
2
6
let maxPoints ;
3
7
let currentMatchMaxPoints ;
4
8
let playersPerTeam ;
@@ -52,6 +56,33 @@ function getFromLocalStorage() {
52
56
return gameDays || [ ] ;
53
57
}
54
58
59
+ function getRatingsFromStorage ( players ) {
60
+ const playersElo = JSON . parse ( localStorage . getItem ( LOCAL_STORAGE_ELO_KEY ) ) ;
61
+ return players . map ( player => {
62
+ return {
63
+ ...player ,
64
+ ...playersElo [ player . name ]
65
+ }
66
+ } ) ;
67
+ }
68
+
69
+ function storeUpdatedRatings ( [ updatedVictory , updatedLosing ] ) {
70
+ const playersElo = JSON . parse ( localStorage . getItem ( LOCAL_STORAGE_ELO_KEY ) ) ;
71
+ updatedVictory . forEach ( player => {
72
+ playersElo [ player . name ] = {
73
+ mu : player . mu ,
74
+ sigma : player . sigma
75
+ }
76
+ } ) ;
77
+ updatedLosing . forEach ( player => {
78
+ playersElo [ player . name ] = {
79
+ mu : player . mu ,
80
+ sigma : player . sigma
81
+ }
82
+ } ) ;
83
+ localStorage . setItem ( LOCAL_STORAGE_ELO_KEY , JSON . stringify ( playersElo ) ) ;
84
+ }
85
+
55
86
function sortPlayers ( a , b ) {
56
87
if ( a . lastPlayedMatch === b . lastPlayedMatch ) {
57
88
if ( a . matches < b . matches ) return - 1 ;
@@ -65,18 +96,34 @@ function sortPlayers(a, b) {
65
96
return 0 ;
66
97
}
67
98
99
+ $ ( '#dev-mode' ) . change ( function ( ) {
100
+ updatePlayerList ( ) ;
101
+ } )
102
+
68
103
function updatePlayerList ( ) {
69
104
$ ( "#players" ) . empty ( ) ;
70
- const playersToList = players . sort ( ( a , b ) => sortPlayers ( a , b ) ) ;
105
+ const playersToList = getRatingsFromStorage ( players )
106
+ . sort ( ( a , b ) => sortPlayers ( a , b ) )
107
+
108
+ const devMode = $ ( "#dev-mode" ) . is ( ":checked" ) ;
109
+ if ( devMode ) {
110
+ $ ( "#elo-header" ) . show ( ) ;
111
+ } else {
112
+ $ ( "#elo-header" ) . hide ( ) ;
113
+ }
114
+
71
115
playersToList . forEach ( player => {
72
116
const playerIsPlayingNow = playingTeams . flat ( ) . some ( p => p . name === player . name ) ;
117
+ const formatter = new Intl . NumberFormat ( 'pt-BR' , { maximumFractionDigits : 2 , minimumFractionDigits : 2 } ) ;
118
+ const elo = devMode ? `${ formatter . format ( player . mu ) } /${ formatter . format ( player . sigma ) } ` : '' ;
73
119
$ ( "#players" ) . append ( `
74
120
<tr ${ playerIsPlayingNow ? 'class="is-selected"' : '' } >
75
121
<th>${ player . name } </th>
76
122
<td>${ player . matches } </td>
77
123
<td>${ player . victories } </td>
78
124
<td>${ player . defeats } </td>
79
125
<td>${ player . lastPlayedMatch } </td>
126
+ ${ devMode ? `<td>${ elo } </td>` : '' }
80
127
<td ${ ! player . playing ? 'class="is-danger remove-player"' : 'class="remove-player"' } style="cursor: pointer">${ player . playing ? 'Sim ' : 'Não' } ${ playerIsPlayingNow ? '<i class="fa-solid fa-repeat"></i>' : '<i class="fa-solid fa-volleyball"></i>' } </td>
81
128
</tr>` ) ;
82
129
} ) ;
@@ -137,6 +184,13 @@ $("#new-match-day").click(function() {
137
184
$ ( "#new-match-day-button" ) . hide ( ) ;
138
185
} ) ;
139
186
187
+ function addPlayerToEloSystem ( player ) {
188
+ const playersElo = JSON . parse ( localStorage . getItem ( LOCAL_STORAGE_ELO_KEY ) ) ;
189
+ if ( playersElo [ player . name ] ) return ;
190
+ playersElo [ player . name ] = createInitialRating ( ) ;
191
+ localStorage . setItem ( LOCAL_STORAGE_ELO_KEY , JSON . stringify ( playersElo ) ) ;
192
+ }
193
+
140
194
function addNewPlayer ( ) {
141
195
const playerName = $ ( "#new-player-name" ) . val ( ) ;
142
196
@@ -161,6 +215,7 @@ function addNewPlayer(){
161
215
lastPlayedMatch : 0 ,
162
216
playing : true ,
163
217
} ) ;
218
+ addPlayerToEloSystem ( { name : playerName } ) ;
164
219
165
220
$ ( "#player-list" ) . append ( `<li>${ playerName } </li>` ) ;
166
221
@@ -175,21 +230,13 @@ $("input").on("keydown",function search(e) {
175
230
}
176
231
} ) ;
177
232
178
- function generateRandomTeams ( players ) {
179
- const teams = [ ] ;
180
- // Generate two random teams
181
- for ( let i = 0 ; i < 2 ; i ++ ) {
182
- const team = [ ] ;
183
- for ( let j = 0 ; j < playersPerTeam ; j ++ ) {
184
- const playerIndex = Math . floor ( Math . random ( ) * players . length ) ;
185
- const player = players [ playerIndex ] ;
186
- team . push ( player ) ;
187
- players . splice ( playerIndex , 1 ) ;
188
- }
189
- teams . push ( team ) ;
190
- }
191
-
192
- return teams ;
233
+ function generateTeams ( players ) {
234
+ const playersWithElo = getRatingsFromStorage ( players ) ;
235
+ const bestMatch = findBestTeamMatch ( playersWithElo ) ;
236
+ return [
237
+ bestMatch . teamA ,
238
+ bestMatch . teamB
239
+ ] ;
193
240
}
194
241
195
242
function updateCurrentMatch ( teams ) {
@@ -249,7 +296,7 @@ $("#start-match-day").click(function() {
249
296
250
297
251
298
saveOnLocalStorage ( ) ;
252
- updateCurrentMatch ( generateRandomTeams ( firstPlayers ) ) ;
299
+ updateCurrentMatch ( generateTeams ( firstPlayers ) ) ;
253
300
randomServe ( ) ;
254
301
} ) ;
255
302
@@ -277,6 +324,12 @@ function endMatch(victoryTeam) {
277
324
alert ( `Time ${ playingTeams [ victoryTeam ] [ 0 ] . name } venceu a partida!` ) ;
278
325
matches += 1 ;
279
326
327
+ const victoryTeamRating = getRatingsFromStorage ( playingTeams [ victoryTeam ] )
328
+ const losingTeamRating = getRatingsFromStorage ( playingTeams [ 1 - victoryTeam ] )
329
+
330
+ const updatedRatings = updateRatings ( victoryTeamRating , losingTeamRating ) ;
331
+ storeUpdatedRatings ( updatedRatings ) ;
332
+
280
333
// Add one match to every player and one victory to each player on winning team
281
334
playingTeams [ victoryTeam ] . forEach ( player => {
282
335
const playerIndex = players . findIndex ( p => p . name === player . name ) ;
@@ -298,15 +351,24 @@ function endMatch(victoryTeam) {
298
351
saveOnLocalStorage ( ) ;
299
352
}
300
353
354
+ function findPlayerByName ( players , name ) {
355
+ return players . find ( player => player . name === name ) ;
356
+ }
357
+
301
358
function startNewMatch ( winningPlayers , losingPlayers ) {
302
359
$ ( "#match" ) . show ( ) ;
303
360
$ ( "#score-team-1" ) . text ( "0" ) ;
304
361
$ ( "#score-team-2" ) . text ( "0" ) ;
305
362
306
- const notPlayingPlayers = players . filter ( player => ! player . playing ) ;
363
+ const notPlayingPlayers = players
364
+ . filter ( player => ! player . playing ) ;
307
365
let newPlayers = [ ...winningPlayers ] ;
308
366
let playersToPlay = [ ] ;
309
- let playerList = players . sort ( ( a , b ) => sortPlayers ( a , b ) ) . filter ( player => ! winningPlayers . includes ( player ) && ! losingPlayers . includes ( player ) && ! notPlayingPlayers . includes ( player ) ) ;
367
+ let playerList = players
368
+ . sort ( ( a , b ) => sortPlayers ( a , b ) )
369
+ . filter ( player => ! findPlayerByName ( winningPlayers , player . name )
370
+ && ! findPlayerByName ( losingPlayers , player . name )
371
+ && ! findPlayerByName ( notPlayingPlayers , player . name ) ) ;
310
372
311
373
// Is there any players that didn't play yet?
312
374
if ( players . length > playersPerTeam * 2 ) {
@@ -320,19 +382,25 @@ function startNewMatch(winningPlayers, losingPlayers) {
320
382
for ( let i = 0 ; i < playersPerTeam ; i ++ ) {
321
383
const playerIndex = Math . floor ( Math . random ( ) * playersToPlay . length ) ;
322
384
const player = playersToPlay [ playerIndex ] ;
323
- if ( ! newPlayers . includes ( player ) ) {
385
+ if ( ! findPlayerByName ( newPlayers , player . name ) ) {
324
386
newPlayers . push ( player ) ;
325
387
}
326
388
}
327
389
}
328
390
} else {
329
391
// I don't have substitutes to play, let's just keep playing
330
- updateCurrentMatch ( generateRandomTeams ( players ) ) ;
392
+ updateCurrentMatch ( generateTeams ( players ) ) ;
331
393
return ;
332
394
}
333
395
334
396
// Remove players that are already playing, get players with less matches but that played the longest time ago
335
- const sortedPlayers = players . filter ( player => ! newPlayers . includes ( player ) && ! winningPlayers . includes ( player ) && ! playerList . includes ( player ) && ! notPlayingPlayers . includes ( player ) ) . sort ( ( a , b ) => sortPlayers ( a , b ) ) . slice ( 0 , ( playersPerTeam * 2 ) - newPlayers . length ) ;
397
+ const sortedPlayers = players
398
+ . filter ( player => ! findPlayerByName ( newPlayers , player . name )
399
+ && ! findPlayerByName ( winningPlayers , player . name )
400
+ && ! findPlayerByName ( playerList , player . name )
401
+ && ! findPlayerByName ( notPlayingPlayers , player . name ) )
402
+ . sort ( ( a , b ) => sortPlayers ( a , b ) )
403
+ . slice ( 0 , ( playersPerTeam * 2 ) - newPlayers . length ) ;
336
404
337
405
while ( newPlayers . length < playersPerTeam * 2 ) {
338
406
// Just to be sure, remove any duplicates
@@ -341,14 +409,14 @@ function startNewMatch(winningPlayers, losingPlayers) {
341
409
const playerIndex = Math . floor ( Math . random ( ) * sortedPlayers . length ) ;
342
410
const player = sortedPlayers [ playerIndex ] ;
343
411
344
- if ( ! newPlayers . includes ( player ) ) {
412
+ if ( ! findPlayerByName ( newPlayers , player . name ) ) {
345
413
newPlayers . push ( player ) ;
346
414
}
347
415
}
348
416
349
417
currentMatchMaxPoints = maxPoints ;
350
418
randomServe ( ) ;
351
- updateCurrentMatch ( generateRandomTeams ( newPlayers ) ) ;
419
+ updateCurrentMatch ( generateTeams ( newPlayers ) ) ;
352
420
saveOnLocalStorage ( ) ;
353
421
}
354
422
@@ -574,8 +642,22 @@ $("#historic-days").on("click", ".match-historic", function() {
574
642
showFinalPlayerList ( playersByWinPercentage ) ;
575
643
} ) ;
576
644
645
+ function initEloSystem ( players ) {
646
+ const playersElo = { }
647
+ players . forEach ( player => {
648
+ const rating = createInitialRating ( ) ;
649
+ playersElo [ player . name ] = rating ;
650
+ } )
651
+ localStorage . setItem ( LOCAL_STORAGE_ELO_KEY , JSON . stringify ( playersElo ) ) ;
652
+ }
653
+
577
654
$ ( document ) . ready ( function ( ) {
578
655
const gameDays = getFromLocalStorage ( ) ;
656
+ const hasElo = localStorage . getItem ( LOCAL_STORAGE_ELO_KEY ) ;
657
+
658
+ if ( ! hasElo ) {
659
+ initEloSystem ( gameDays . flatMap ( gameDay => gameDay . players ) ) ;
660
+ }
579
661
580
662
if ( gameDays . length > 0 ) {
581
663
const lastGameDay = gameDays [ gameDays . length - 1 ] ;
0 commit comments