diff --git a/src/caches/GameSlice.ts b/src/caches/GameSlice.ts index 646c0dc..f9061be 100644 --- a/src/caches/GameSlice.ts +++ b/src/caches/GameSlice.ts @@ -1,4 +1,4 @@ -import { createSlice, PayloadAction } from "@reduxjs/toolkit" +import { createSelector, createSlice, PayloadAction } from "@reduxjs/toolkit" import { GameState, GameStatus } from "../model/Game" import { Player } from "../model/Player" @@ -31,39 +31,71 @@ export const gameSlice = createSlice({ export const { updateGame, updatePlayers, resetGame } = gameSlice.actions export const getGame = (state: RootState) => state.game -export const getGamePlayers = (state: RootState) => state.game.players -export const getRound = (state: RootState) => state.game.round -export const getCards = (state: RootState) => state.game.cards -export const getSuit = (state: RootState) => state.game.round?.suit -export const getGameId = (state: RootState) => state.game.id -export const getHasGame = (state: RootState) => - state.game.status === GameStatus.ACTIVE || - state.game.status === GameStatus.NONE -export const getGameStatus = (state: RootState) => state.game.status -export const isGameActive = (state: RootState) => - state.game.status === GameStatus.ACTIVE -export const getIsRoundCalling = (state: RootState) => - state.game.round?.status === RoundStatus.CALLING -export const getIsRoundCalled = (state: RootState) => - state.game.round?.status === RoundStatus.CALLED -export const getIsRoundBuying = (state: RootState) => - state.game.round?.status === RoundStatus.BUYING -export const getIsRoundPlaying = (state: RootState) => - state.game.round?.status === RoundStatus.PLAYING -export const isDoublesGame = (state: RootState) => - state.game.players.length === 6 -export const getCanBuyCards = (state: RootState) => - state.game.isMyGo && - state.game.iamGoer && - state.game.round && - state.game.round.status === RoundStatus.BUYING +export const getGamePlayers = createSelector(getGame, game => game.players) +export const getMe = createSelector(getGame, game => game.me) -export const getIsInBunker = (state: RootState) => - state.game.isMyGo && - state.game.round?.status === RoundStatus.CALLING && - state.game.me && - state.game.me?.score < -30 +export const getRound = createSelector(getGame, game => game.round) +export const getCards = createSelector(getGame, game => game.cards) +export const getSuit = createSelector(getRound, round => round?.suit) +export const getGameId = createSelector(getGame, game => game.id) -export const getIsMyGo = (state: RootState) => state.game.isMyGo -export const getIamGoer = (state: RootState) => state.game.iamGoer -export const getIamSpectator = (state: RootState) => state.game.iamSpectator +export const getGameStatus = createSelector(getGame, game => game.status) + +export const getHasGame = createSelector( + getGameStatus, + status => status === GameStatus.ACTIVE || status === GameStatus.NONE, +) +export const isGameActive = createSelector( + getGameStatus, + status => status === GameStatus.ACTIVE, +) + +export const isGameFinished = createSelector( + getGameStatus, + status => status === GameStatus.FINISHED, +) + +export const getRoundStatus = createSelector(getRound, round => round?.status) +export const getIsRoundCalling = createSelector( + getRoundStatus, + status => status === RoundStatus.CALLING, +) +export const getIsRoundCalled = createSelector( + getRoundStatus, + status => status === RoundStatus.CALLED, +) +export const getIsRoundBuying = createSelector( + getRoundStatus, + status => status === RoundStatus.BUYING, +) +export const getIsRoundPlaying = createSelector( + getRoundStatus, + status => status === RoundStatus.PLAYING, +) + +export const isDoublesGame = createSelector( + getGamePlayers, + players => players.length === 6, +) + +export const getIsMyGo = createSelector(getGame, game => game.isMyGo) +export const getIamGoer = createSelector(getGame, game => game.iamGoer) +export const getIamSpectator = createSelector( + getGame, + game => game.iamSpectator, +) + +export const getCanBuyCards = createSelector( + getIsMyGo, + getIamGoer, + getIsRoundBuying, + (isMyGo, iamGoer, isRoundBuying) => isMyGo && iamGoer && isRoundBuying, +) + +export const getIsInBunker = createSelector( + getIsMyGo, + getIsRoundCalling, + getMe, + (isMyGo, isRoundCalling, me) => + isMyGo && isRoundCalling && me && me?.score < -30, +) diff --git a/src/components/Leaderboard/DoublesLeaderboard.tsx b/src/components/Leaderboard/DoublesLeaderboard.tsx index 7980f3d..cd69646 100644 --- a/src/components/Leaderboard/DoublesLeaderboard.tsx +++ b/src/components/Leaderboard/DoublesLeaderboard.tsx @@ -2,25 +2,43 @@ import React, { useCallback, useMemo } from "react" import DataTable, { TableColumn } from "react-data-table-component" import TrophyImage from "../../assets/icons/trophy.png" import { useAppSelector } from "../../caches/hooks" -import { getGame } from "../../caches/GameSlice" +import { + getGame, + getGamePlayers, + getRound, + isGameFinished, +} from "../../caches/GameSlice" import { getPlayerProfiles } from "../../caches/PlayerProfilesSlice" import { GameStatus } from "../../model/Game" import { compareScore, compareTeamIds } from "../../utils/PlayerUtils" -import { Player, Team } from "../../model/Player" +import { Player } from "../../model/Player" import { customStyles } from "../Tables/CustomStyles" +interface LeaderBoardPlayer { + cardsBought?: number + name: string + picture: string + previousCard?: string +} + +interface DoublesLeaderboardItem { + teamId: string + score: number + rings: number + player1: LeaderBoardPlayer + player2: LeaderBoardPlayer + winner: boolean +} + const DoublesLeaderboard = () => { - const game = useAppSelector(getGame) + const round = useAppSelector(getRound) + const players = useAppSelector(getGamePlayers) const playerProfiles = useAppSelector(getPlayerProfiles) + const gameOver = useAppSelector(isGameFinished) const previousHand = useMemo(() => { - if (game.round) - return game.round.completedHands[ - game.round.completedHands.length - 1 - ] - }, [game]) - - const gameOver = useMemo(() => game.status === GameStatus.FINISHED, [game]) + if (round) return round.completedHands[round.completedHands.length - 1] + }, [round]) const getProfile = useCallback( (player: Player) => @@ -28,43 +46,60 @@ const DoublesLeaderboard = () => { [playerProfiles], ) - const teams = useMemo(() => { - const ps = game.players.sort(compareTeamIds) + const mapToLeaderboard = useCallback( + (player: Player): LeaderBoardPlayer => { + const profile = getProfile(player) + if (!profile) throw Error("No profile for player") + const previousCard = previousHand?.playedCards.find( + c => c.playerId === player.id, + ) + return { + cardsBought: player.cardsBought, + name: profile.name, + picture: profile.picture, + previousCard: previousCard?.card, + } + }, + [previousHand], + ) + + const leaderboardData = useMemo(() => { + const ps = [...players].sort(compareTeamIds) if (!ps) { return [] } - const teams: Team[] = [ + const items: DoublesLeaderboardItem[] = [ { - id: ps[0].teamId, + teamId: ps[0].teamId, score: ps[0].score, rings: ps[0].rings, - player1: ps[0], - player2: ps[1], + player1: mapToLeaderboard(ps[0]), + player2: mapToLeaderboard(ps[1]), winner: ps[0].winner, }, { - id: ps[2].teamId, + teamId: ps[2].teamId, score: ps[2].score, rings: ps[2].rings, - player1: ps[2], - player2: ps[3], + player1: mapToLeaderboard(ps[2]), + player2: mapToLeaderboard(ps[3]), winner: ps[2].winner, }, { - id: ps[4].teamId, + teamId: ps[4].teamId, score: ps[4].score, rings: ps[4].rings, - player1: ps[4], - player2: ps[5], + player1: mapToLeaderboard(ps[4]), + player2: mapToLeaderboard(ps[5]), winner: ps[4].winner, }, ] - return teams.sort(compareScore) - }, []) + return items.sort(compareScore) + }, [players]) - const columns: TableColumn[] = [ + const columns: TableColumn[] = [ { name: "Player 1", cell: row => ( @@ -72,28 +107,18 @@ const DoublesLeaderboard = () => {
Image Preview - {!gameOver && !!previousHand ? ( + {!gameOver && !!row.player1.previousCard ? (
{previousHand ? ( { - p.playerId === - row.player1.id, - )?.card - } + alt={row.player1.previousCard} src={ "/cards/thumbnails/" + - previousHand.playedCards.find( - p => - p.playerId === - row.player1.id, - )?.card + + row.player1.previousCard + ".png" } className="thumbnail_size_small cardNotSelected" @@ -119,7 +144,7 @@ const DoublesLeaderboard = () => {
Image Preview @@ -127,16 +152,10 @@ const DoublesLeaderboard = () => {
{previousHand ? ( { p.playerId === row.player2.id, - )?.card - } + alt={row.player2.previousCard} src={ "/cards/thumbnails/" + - previousHand.playedCards.find( - p => p.playerId === row.player1.id, - )?.card + + row.player2.previousCard + ".png" } className="thumbnail_size_small cardNotSelected" @@ -180,12 +199,7 @@ const DoublesLeaderboard = () => { }, ] - if ( - !game || - !game.status || - !playerProfiles || - playerProfiles.length === 0 - ) { + if (!playerProfiles || playerProfiles.length === 0) { return null } @@ -194,7 +208,7 @@ const DoublesLeaderboard = () => {