Skip to content

Commit 68af405

Browse files
committed
Added stats about opponents played against
1 parent 701fbcd commit 68af405

File tree

3 files changed

+491
-59
lines changed

3 files changed

+491
-59
lines changed

app/routes/compare-players.$player1Id.$player2Id.tsx

Lines changed: 144 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { PlayerWithStats, getPlayers } from '../services/player-service';
44
import { typedjson, useTypedLoaderData } from 'remix-typedjson';
55
import Select, { createFilter } from 'react-select';
66
import { PageContainerStyling } from './team-duel';
7+
import { BASE_ELO } from '../utils/constants';
78

89
export 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+
79136
export 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

Comments
 (0)