Skip to content

Commit 0fe9074

Browse files
committedFeb 13, 2025
Added stats about opponents played against
1 parent 701fbcd commit 0fe9074

3 files changed

+563
-59
lines changed
 

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

+141-3
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,67 @@ const findPlayerWinStats = (
7677
};
7778
};
7879

80+
const findMatchesBetweenPlayers = (
81+
player1: PlayerWithStats,
82+
player2: PlayerWithStats
83+
) => {
84+
const sortedLogs = [...player1.eloLogs].sort(
85+
(a, b) => new Date(a.date).getTime() - new Date(b.date).getTime()
86+
);
87+
88+
const allMatches = [...player1.matchesAsWinner, ...player1.matchesAsLoser]
89+
.filter(
90+
(match) =>
91+
(match.winnerId === player1.id && match.loserId === player2.id) ||
92+
(match.winnerId === player2.id && match.loserId === player1.id)
93+
)
94+
.sort((a, b) => new Date(b.date).getTime() - new Date(a.date).getTime())
95+
.map((match) => {
96+
const matchLog = sortedLogs.find((log) => log.matchId === match.id);
97+
98+
let eloDiff = 0;
99+
let player1Elo = BASE_ELO;
100+
let player2Elo = BASE_ELO;
101+
102+
if (matchLog) {
103+
const matchIndex = sortedLogs.indexOf(matchLog);
104+
const previousElo =
105+
matchIndex === 0 ? BASE_ELO : sortedLogs[matchIndex - 1].elo;
106+
eloDiff = matchLog.elo - previousElo;
107+
player1Elo = matchLog.elo;
108+
}
109+
110+
return {
111+
...match,
112+
eloDiff: match.winnerId === player1.id ? eloDiff : -eloDiff,
113+
player1Elo,
114+
player2Elo,
115+
winner: match.winnerId === player1.id ? player1 : player2,
116+
loser: match.loserId === player1.id ? player1 : player2,
117+
accumulatedEloDiff: 0,
118+
};
119+
});
120+
121+
let runningTotal = 0;
122+
allMatches.reverse().forEach((match) => {
123+
const matchEloDiff = Math.abs(match.eloDiff);
124+
runningTotal +=
125+
match.winner.id === player1.id ? matchEloDiff : -matchEloDiff;
126+
match.accumulatedEloDiff = runningTotal;
127+
});
128+
allMatches.reverse();
129+
130+
return allMatches;
131+
};
132+
79133
export default function Index() {
80134
const navigate = useNavigate();
81135
const { playerOptions, player1, player2, player1WinStats } =
82136
useTypedLoaderData<typeof loader>();
83137

84-
// TODO: migrate datamodel to include elo gains/loses (recalculate elo values?)
138+
const matchHistory =
139+
player1 && player2 ? findMatchesBetweenPlayers(player1, player2) : [];
140+
85141
return (
86142
<div className={PageContainerStyling}>
87143
<div className="flex justify-center py-4">
@@ -154,15 +210,97 @@ export default function Index() {
154210
<div className="text-center">
155211
<div className="text-3xl font-bold text-blue-600 dark:text-blue-400">
156212
{player1WinStats?.winPercentage
157-
? player1WinStats.winPercentage.toFixed(2)
213+
? player1WinStats.winPercentage.toFixed(1)
158214
: 0}
159215
%
160216
</div>
161217
<div className="mt-1 text-sm text-gray-600 dark:text-gray-400">
162-
Overlegenhet
218+
Win rate
163219
</div>
164220
</div>
165221
</div>
222+
223+
<h2 className="mb-4 mt-8 text-2xl font-bold text-gray-900 dark:text-white">
224+
Kamphistorikk 📋
225+
</h2>
226+
<div className="overflow-x-auto rounded-lg bg-white p-6 shadow-lg dark:bg-gray-800">
227+
<table className="min-w-full">
228+
<thead>
229+
<tr className="border-b dark:border-gray-700">
230+
<th className="py-2 text-left text-gray-900 dark:text-white">
231+
Dato
232+
</th>
233+
<th className="py-2 text-left text-gray-900 dark:text-white">
234+
Vinner
235+
</th>
236+
<th className="py-2 text-left text-gray-900 dark:text-white">
237+
Taper
238+
</th>
239+
<th className="py-2 text-right text-gray-900 dark:text-white">
240+
ELO
241+
</th>
242+
<th className="py-2 text-right text-gray-900 dark:text-white">
243+
ELO totalt
244+
</th>
245+
</tr>
246+
</thead>
247+
<tbody>
248+
{matchHistory.map((match) => (
249+
<tr key={match.id} className="border-b dark:border-gray-700">
250+
<td className="py-2 text-gray-900 dark:text-white">
251+
{new Date(match.date).toLocaleString('no-NO', {
252+
year: 'numeric',
253+
month: 'short',
254+
day: '2-digit',
255+
})}
256+
</td>
257+
<td className="py-2 font-semibold text-gray-900 dark:text-white">
258+
{match.winner.name}{' '}
259+
<span className="font-normal text-gray-600 dark:text-gray-400">
260+
(
261+
{match.winner.id === player1.id
262+
? match.player1Elo
263+
: match.player2Elo}
264+
)
265+
</span>
266+
</td>
267+
<td className="py-2 font-semibold text-gray-900 dark:text-white">
268+
{match.loser.name}{' '}
269+
<span className="font-normal text-gray-600 dark:text-gray-400">
270+
(
271+
{match.loser.id === player1.id
272+
? match.player1Elo
273+
: match.player2Elo}
274+
)
275+
</span>
276+
</td>
277+
<td
278+
className={`py-2 text-right font-semibold ${
279+
match.winner.id === player1.id
280+
? 'text-green-600 dark:text-green-400'
281+
: 'text-red-600 dark:text-red-400'
282+
}`}
283+
>
284+
{match.winner.id === player1.id ? '+' : '-'}
285+
{Math.abs(match.eloDiff)}
286+
</td>
287+
<td
288+
className={`py-2 text-right font-semibold ${
289+
match.accumulatedEloDiff > 0
290+
? 'text-green-600 dark:text-green-400'
291+
: match.accumulatedEloDiff < 0
292+
? 'text-red-600 dark:text-red-400'
293+
: 'text-gray-900 dark:text-white'
294+
}`}
295+
>
296+
{match.accumulatedEloDiff > 0 ? '+' : ''}
297+
{match.accumulatedEloDiff}
298+
</td>
299+
</tr>
300+
))}
301+
</tbody>
302+
</table>
303+
</div>
166304
</div>
167305
)}
168306
</div>

0 commit comments

Comments
 (0)
Please sign in to comment.