@@ -4,6 +4,7 @@ import { PlayerWithStats, getPlayers } from '../services/player-service';
44import { typedjson , useTypedLoaderData } from 'remix-typedjson' ;
55import Select , { createFilter } from 'react-select' ;
66import { PageContainerStyling } from './team-duel' ;
7+ import { BASE_ELO } from '../utils/constants' ;
78
89export const meta : MetaFunction = ( ) => {
910 return [
@@ -76,12 +77,70 @@ const findPlayerWinStats = (
7677 } ;
7778} ;
7879
80+ const findMatchesBetweenPlayers = (
81+ player1 : PlayerWithStats ,
82+ player2 : PlayerWithStats
83+ ) => {
84+ const sortedLogs1 = [ ...player1 . eloLogs ] . sort (
85+ ( a , b ) => new Date ( a . date ) . getTime ( ) - new Date ( b . date ) . getTime ( )
86+ ) ;
87+ const sortedLogs2 = [ ...player2 . eloLogs ] . sort (
88+ ( a , b ) => new Date ( a . date ) . getTime ( ) - new Date ( b . date ) . getTime ( )
89+ ) ;
90+
91+ const allMatches = [ ...player1 . matchesAsWinner , ...player1 . matchesAsLoser ]
92+ . filter (
93+ ( match ) =>
94+ ( match . winnerId === player1 . id && match . loserId === player2 . id ) ||
95+ ( match . winnerId === player2 . id && match . loserId === player1 . id )
96+ )
97+ . sort ( ( a , b ) => new Date ( b . date ) . getTime ( ) - new Date ( a . date ) . getTime ( ) )
98+ . map ( ( match ) => {
99+ const matchLog = sortedLogs1 . find ( ( log ) => log . matchId === match . id ) ;
100+
101+ let eloDiff = 0 ;
102+ let player1Elo = BASE_ELO ;
103+ let player2Elo = BASE_ELO ;
104+
105+ if ( matchLog ) {
106+ const matchIndex = sortedLogs1 . indexOf ( matchLog ) ;
107+ const previousElo =
108+ matchIndex === 0 ? BASE_ELO : sortedLogs1 [ matchIndex - 1 ] . elo ;
109+ eloDiff = matchLog . elo - previousElo ;
110+ player1Elo = matchLog . elo ;
111+ }
112+
113+ return {
114+ ...match ,
115+ eloDiff : match . winnerId === player1 . id ? eloDiff : - eloDiff ,
116+ player1Elo,
117+ player2Elo,
118+ winner : match . winnerId === player1 . id ? player1 : player2 ,
119+ loser : match . loserId === player1 . id ? player1 : player2 ,
120+ accumulatedEloDiff : 0 ,
121+ } ;
122+ } ) ;
123+
124+ let runningTotal = 0 ;
125+ allMatches . reverse ( ) . forEach ( ( match ) => {
126+ const matchEloDiff = Math . abs ( match . eloDiff ) ;
127+ runningTotal +=
128+ match . winner . id === player1 . id ? matchEloDiff : - matchEloDiff ;
129+ match . accumulatedEloDiff = runningTotal ;
130+ } ) ;
131+ allMatches . reverse ( ) ;
132+
133+ return allMatches ;
134+ } ;
135+
79136export default function Index ( ) {
80137 const navigate = useNavigate ( ) ;
81138 const { playerOptions, player1, player2, player1WinStats } =
82139 useTypedLoaderData < typeof loader > ( ) ;
83140
84- // TODO: migrate datamodel to include elo gains/loses (recalculate elo values?)
141+ const matchHistory =
142+ player1 && player2 ? findMatchesBetweenPlayers ( player1 , player2 ) : [ ] ;
143+
85144 return (
86145 < div className = { PageContainerStyling } >
87146 < div className = "flex justify-center py-4" >
@@ -154,15 +213,97 @@ export default function Index() {
154213 < div className = "text-center" >
155214 < div className = "text-3xl font-bold text-blue-600 dark:text-blue-400" >
156215 { player1WinStats ?. winPercentage
157- ? player1WinStats . winPercentage . toFixed ( 2 )
216+ ? player1WinStats . winPercentage . toFixed ( 1 )
158217 : 0 }
159218 %
160219 </ div >
161220 < div className = "mt-1 text-sm text-gray-600 dark:text-gray-400" >
162- Overlegenhet
221+ Win rate
163222 </ div >
164223 </ div >
165224 </ div >
225+
226+ < h2 className = "mb-4 mt-8 text-2xl font-bold text-gray-900 dark:text-white" >
227+ Kamphistorikk 📋
228+ </ h2 >
229+ < div className = "overflow-x-auto rounded-lg bg-white p-6 shadow-lg dark:bg-gray-800" >
230+ < table className = "min-w-full" >
231+ < thead >
232+ < tr className = "border-b dark:border-gray-700" >
233+ < th className = "py-2 text-left text-gray-900 dark:text-white" >
234+ Dato
235+ </ th >
236+ < th className = "py-2 text-left text-gray-900 dark:text-white" >
237+ Vinner
238+ </ th >
239+ < th className = "py-2 text-left text-gray-900 dark:text-white" >
240+ Taper
241+ </ th >
242+ < th className = "py-2 text-right text-gray-900 dark:text-white" >
243+ ELO
244+ </ th >
245+ < th className = "py-2 text-right text-gray-900 dark:text-white" >
246+ ELO totalt
247+ </ th >
248+ </ tr >
249+ </ thead >
250+ < tbody >
251+ { matchHistory . map ( ( match ) => (
252+ < tr key = { match . id } className = "border-b dark:border-gray-700" >
253+ < td className = "py-2 text-gray-900 dark:text-white" >
254+ { new Date ( match . date ) . toLocaleString ( 'no-NO' , {
255+ year : 'numeric' ,
256+ month : 'short' ,
257+ day : '2-digit' ,
258+ } ) }
259+ </ td >
260+ < td className = "py-2 font-semibold text-gray-900 dark:text-white" >
261+ { match . winner . name } { ' ' }
262+ < span className = "font-normal text-gray-600 dark:text-gray-400" >
263+ (
264+ { match . winner . id === player1 . id
265+ ? match . player1Elo
266+ : match . player2Elo }
267+ )
268+ </ span >
269+ </ td >
270+ < td className = "py-2 font-semibold text-gray-900 dark:text-white" >
271+ { match . loser . name } { ' ' }
272+ < span className = "font-normal text-gray-600 dark:text-gray-400" >
273+ (
274+ { match . loser . id === player1 . id
275+ ? match . player1Elo
276+ : match . player2Elo }
277+ )
278+ </ span >
279+ </ td >
280+ < td
281+ className = { `py-2 text-right font-semibold ${
282+ match . winner . id === player1 . id
283+ ? 'text-green-600 dark:text-green-400'
284+ : 'text-red-600 dark:text-red-400'
285+ } `}
286+ >
287+ { match . winner . id === player1 . id ? '+' : '-' }
288+ { Math . abs ( match . eloDiff ) }
289+ </ td >
290+ < td
291+ className = { `py-2 text-right font-semibold ${
292+ match . accumulatedEloDiff > 0
293+ ? 'text-green-600 dark:text-green-400'
294+ : match . accumulatedEloDiff < 0
295+ ? 'text-red-600 dark:text-red-400'
296+ : 'text-gray-900 dark:text-white'
297+ } `}
298+ >
299+ { match . accumulatedEloDiff > 0 ? '+' : '' }
300+ { match . accumulatedEloDiff }
301+ </ td >
302+ </ tr >
303+ ) ) }
304+ </ tbody >
305+ </ table >
306+ </ div >
166307 </ div >
167308 ) }
168309 </ div >
0 commit comments