-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #69 from soham2k06/feat/player-team-stats
batting stats
- Loading branch information
Showing
10 changed files
with
292 additions
and
15 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
import { useQuery } from "@tanstack/react-query"; | ||
import { getPlayerStats } from "@/services/player/getPlayerStats"; | ||
|
||
export function usePlayerStats(id: string | undefined) { | ||
const { data, isLoading, isFetching, error } = useQuery({ | ||
queryKey: ["playerStats", id], | ||
queryFn: () => getPlayerStats(id), | ||
enabled: !!id, | ||
}); | ||
|
||
return { | ||
data, | ||
isLoading, | ||
isFetching, | ||
error, | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
import prisma from "@/lib/db/prisma"; | ||
import { getScore, validateUser } from "@/lib/utils"; | ||
import { BallEvent } from "@prisma/client"; | ||
import { NextResponse } from "next/server"; | ||
|
||
export async function GET( | ||
_: unknown, | ||
{ params: { id } }: { params: { id: string } }, | ||
) { | ||
try { | ||
validateUser(); | ||
|
||
const playerBallEvents = await prisma.ballEvent.findMany({ | ||
where: { OR: [{ batsmanId: id }, { bowlerId: id }] }, | ||
}); | ||
|
||
const groupedMatches: { [matchId: string]: BallEvent[] } = {}; | ||
|
||
for (const event of playerBallEvents) { | ||
const matchId = event.matchId ?? "no-data"; | ||
if (!groupedMatches[matchId]) { | ||
groupedMatches[matchId] = []; | ||
} | ||
groupedMatches[matchId].push(event); | ||
} | ||
|
||
let fifties = 0; | ||
let centuries = 0; | ||
let highestScore = 0; | ||
for (const matchId in groupedMatches) { | ||
const matchEvents = groupedMatches[matchId]; | ||
|
||
const { runs } = getScore( | ||
matchEvents.map((event) => event.type), | ||
true, | ||
); | ||
|
||
if (runs >= 50 && runs < 100) fifties++; | ||
if (runs >= 100) centuries++; | ||
if (runs > highestScore) highestScore = runs; | ||
} | ||
|
||
const matchIds = playerBallEvents.map((event) => event.matchId); | ||
const uniqueMatchIds = new Set(matchIds); | ||
const matchesPlayed = uniqueMatchIds.size; | ||
|
||
const battingEvents = playerBallEvents | ||
.filter((event) => event.batsmanId === id) | ||
.map((event) => event.type); | ||
|
||
const bowlingEvents = playerBallEvents | ||
.filter((event) => event.bowlerId === id) | ||
.map((event) => event.type); | ||
|
||
const { | ||
runs: runsScored, | ||
totalBalls: ballsFaced, | ||
wickets: outs, | ||
} = getScore(battingEvents, true); | ||
|
||
const battingStats = { | ||
runs: runsScored, | ||
balls: ballsFaced, | ||
wickets: outs, | ||
}; | ||
|
||
const { | ||
runs: runsConceded, | ||
totalBalls: ballsBowled, | ||
wickets: wicketsTaken, | ||
} = getScore(bowlingEvents); | ||
|
||
const bowlingStats = { | ||
runs: runsConceded, | ||
balls: ballsBowled, | ||
wickets: wicketsTaken, | ||
}; | ||
|
||
const playerStats = { | ||
matchesPlayed, | ||
batting: { ...battingStats, fifties, centuries, highestScore }, | ||
bowling: bowlingStats, | ||
}; | ||
|
||
if (!playerStats) | ||
return NextResponse.json({ error: "No data found" }, { status: 404 }); | ||
|
||
return NextResponse.json(playerStats, { status: 200 }); | ||
} catch (error) { | ||
console.error(error); | ||
return NextResponse.json( | ||
{ error: "Internal server error" }, | ||
{ status: 500 }, | ||
); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
import { usePlayerStats } from "@/apiHooks/player"; | ||
import { Dialog, DialogContent, DialogHeader } from "../ui/dialog"; | ||
|
||
function PlayerStats({ | ||
openedPlayer, | ||
setOpenedPlayer, | ||
}: { | ||
openedPlayer: | ||
| { | ||
id: string | undefined; | ||
name: string | undefined; | ||
} | ||
| undefined; | ||
setOpenedPlayer: (playerId: string | undefined) => void; | ||
}) { | ||
const playerId = openedPlayer?.id; | ||
const playerName = openedPlayer?.name; | ||
const { data } = usePlayerStats(playerId); | ||
|
||
const matchesPlayed = data?.matchesPlayed; | ||
|
||
const batStrikeRate = | ||
Math.round( | ||
((data?.batting.runs ?? 0) / (data?.batting.balls ?? 1)) * 1000, | ||
) / 10; | ||
|
||
const isNotOutYet = data?.batting.wickets === 0; | ||
const batAverage = (data?.batting.runs ?? 0) / (matchesPlayed ?? 0) ?? 0; | ||
|
||
return ( | ||
<Dialog | ||
open={!!playerId} | ||
onOpenChange={() => setOpenedPlayer(playerId ? undefined : playerId)} | ||
> | ||
<DialogContent> | ||
<DialogHeader className="flex-row items-center gap-4 space-y-0"> | ||
<div className="text-lg font-bold">{playerName}</div> | ||
<div className="text-sm font-bold">Matches - {matchesPlayed}</div> | ||
</DialogHeader> | ||
{data ? ( | ||
<div className="overflow-hidden rounded-md"> | ||
<div className="mb-1 bg-primary p-2 text-primary-foreground"> | ||
<h4 className="text-lg font-semibold md:text-xl">Batting</h4> | ||
</div> | ||
<div className="grid grid-cols-3 gap-1"> | ||
<Stat data={data.batting.runs} dataKey="Runs" /> | ||
<Stat | ||
data={matchesPlayed ? batAverage : "-"} | ||
dataKey="Average" | ||
showStar={isNotOutYet} | ||
/> | ||
<Stat | ||
data={data.batting.balls ? batStrikeRate : "-"} | ||
dataKey="Strike rate" | ||
/> | ||
<Stat data={data.batting.fifties} dataKey="Fifties" /> | ||
<Stat data={data.batting.centuries} dataKey="Centuries" /> | ||
<Stat data={data.batting.highestScore} dataKey="High. Score" /> | ||
</div> | ||
</div> | ||
) : ( | ||
<p>No data found</p> | ||
)} | ||
</DialogContent> | ||
</Dialog> | ||
); | ||
} | ||
|
||
function Stat({ | ||
data, | ||
dataKey, | ||
showStar, | ||
}: { | ||
dataKey: string; | ||
data: number | "-"; | ||
showStar?: boolean; | ||
}) { | ||
return ( | ||
<div className="bg-muted p-2"> | ||
<h5 className="font-semibold uppercase text-muted-foreground max-md:text-sm"> | ||
{dataKey} | ||
</h5> | ||
<p className="text-2xl font-bold max-md:text-xl"> | ||
{data} | ||
{showStar && "*"} | ||
</p> | ||
</div> | ||
); | ||
} | ||
|
||
export default PlayerStats; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
import { axiosInstance } from "../axiosInstance"; | ||
import { PlayerStats } from "@/types"; | ||
|
||
export const getPlayerStats = async (id: string | null | undefined) => { | ||
try { | ||
if (!id) throw new Error("Player not found"); | ||
|
||
const res = await axiosInstance.get(`/players/stats/${id}`); | ||
if (res.status !== 200) throw new Error("Network response was not ok"); | ||
|
||
return res.data as PlayerStats; | ||
} catch (error) { | ||
console.error("Error while fetching a player:", error); | ||
throw new Error((error as Error).message); | ||
} | ||
}; |
Oops, something went wrong.