Skip to content

Commit e5998e5

Browse files
authored
Merge pull request #86 from daithihearn/doubles-leaderboard
Fixing Doubles Leaderboard
2 parents ae99299 + 0a41d84 commit e5998e5

File tree

2 files changed

+136
-90
lines changed

2 files changed

+136
-90
lines changed

src/caches/GameSlice.ts

+67-35
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { createSlice, PayloadAction } from "@reduxjs/toolkit"
1+
import { createSelector, createSlice, PayloadAction } from "@reduxjs/toolkit"
22

33
import { GameState, GameStatus } from "../model/Game"
44
import { Player } from "../model/Player"
@@ -31,39 +31,71 @@ export const gameSlice = createSlice({
3131
export const { updateGame, updatePlayers, resetGame } = gameSlice.actions
3232

3333
export const getGame = (state: RootState) => state.game
34-
export const getGamePlayers = (state: RootState) => state.game.players
35-
export const getRound = (state: RootState) => state.game.round
36-
export const getCards = (state: RootState) => state.game.cards
37-
export const getSuit = (state: RootState) => state.game.round?.suit
38-
export const getGameId = (state: RootState) => state.game.id
39-
export const getHasGame = (state: RootState) =>
40-
state.game.status === GameStatus.ACTIVE ||
41-
state.game.status === GameStatus.NONE
42-
export const getGameStatus = (state: RootState) => state.game.status
43-
export const isGameActive = (state: RootState) =>
44-
state.game.status === GameStatus.ACTIVE
45-
export const getIsRoundCalling = (state: RootState) =>
46-
state.game.round?.status === RoundStatus.CALLING
47-
export const getIsRoundCalled = (state: RootState) =>
48-
state.game.round?.status === RoundStatus.CALLED
49-
export const getIsRoundBuying = (state: RootState) =>
50-
state.game.round?.status === RoundStatus.BUYING
51-
export const getIsRoundPlaying = (state: RootState) =>
52-
state.game.round?.status === RoundStatus.PLAYING
53-
export const isDoublesGame = (state: RootState) =>
54-
state.game.players.length === 6
55-
export const getCanBuyCards = (state: RootState) =>
56-
state.game.isMyGo &&
57-
state.game.iamGoer &&
58-
state.game.round &&
59-
state.game.round.status === RoundStatus.BUYING
34+
export const getGamePlayers = createSelector(getGame, game => game.players)
35+
export const getMe = createSelector(getGame, game => game.me)
6036

61-
export const getIsInBunker = (state: RootState) =>
62-
state.game.isMyGo &&
63-
state.game.round?.status === RoundStatus.CALLING &&
64-
state.game.me &&
65-
state.game.me?.score < -30
37+
export const getRound = createSelector(getGame, game => game.round)
38+
export const getCards = createSelector(getGame, game => game.cards)
39+
export const getSuit = createSelector(getRound, round => round?.suit)
40+
export const getGameId = createSelector(getGame, game => game.id)
6641

67-
export const getIsMyGo = (state: RootState) => state.game.isMyGo
68-
export const getIamGoer = (state: RootState) => state.game.iamGoer
69-
export const getIamSpectator = (state: RootState) => state.game.iamSpectator
42+
export const getGameStatus = createSelector(getGame, game => game.status)
43+
44+
export const getHasGame = createSelector(
45+
getGameStatus,
46+
status => status === GameStatus.ACTIVE || status === GameStatus.NONE,
47+
)
48+
export const isGameActive = createSelector(
49+
getGameStatus,
50+
status => status === GameStatus.ACTIVE,
51+
)
52+
53+
export const isGameFinished = createSelector(
54+
getGameStatus,
55+
status => status === GameStatus.FINISHED,
56+
)
57+
58+
export const getRoundStatus = createSelector(getRound, round => round?.status)
59+
export const getIsRoundCalling = createSelector(
60+
getRoundStatus,
61+
status => status === RoundStatus.CALLING,
62+
)
63+
export const getIsRoundCalled = createSelector(
64+
getRoundStatus,
65+
status => status === RoundStatus.CALLED,
66+
)
67+
export const getIsRoundBuying = createSelector(
68+
getRoundStatus,
69+
status => status === RoundStatus.BUYING,
70+
)
71+
export const getIsRoundPlaying = createSelector(
72+
getRoundStatus,
73+
status => status === RoundStatus.PLAYING,
74+
)
75+
76+
export const isDoublesGame = createSelector(
77+
getGamePlayers,
78+
players => players.length === 6,
79+
)
80+
81+
export const getIsMyGo = createSelector(getGame, game => game.isMyGo)
82+
export const getIamGoer = createSelector(getGame, game => game.iamGoer)
83+
export const getIamSpectator = createSelector(
84+
getGame,
85+
game => game.iamSpectator,
86+
)
87+
88+
export const getCanBuyCards = createSelector(
89+
getIsMyGo,
90+
getIamGoer,
91+
getIsRoundBuying,
92+
(isMyGo, iamGoer, isRoundBuying) => isMyGo && iamGoer && isRoundBuying,
93+
)
94+
95+
export const getIsInBunker = createSelector(
96+
getIsMyGo,
97+
getIsRoundCalling,
98+
getMe,
99+
(isMyGo, isRoundCalling, me) =>
100+
isMyGo && isRoundCalling && me && me?.score < -30,
101+
)

src/components/Leaderboard/DoublesLeaderboard.tsx

+69-55
Original file line numberDiff line numberDiff line change
@@ -2,98 +2,123 @@ import React, { useCallback, useMemo } from "react"
22
import DataTable, { TableColumn } from "react-data-table-component"
33
import TrophyImage from "../../assets/icons/trophy.png"
44
import { useAppSelector } from "../../caches/hooks"
5-
import { getGame } from "../../caches/GameSlice"
5+
import {
6+
getGame,
7+
getGamePlayers,
8+
getRound,
9+
isGameFinished,
10+
} from "../../caches/GameSlice"
611
import { getPlayerProfiles } from "../../caches/PlayerProfilesSlice"
712
import { GameStatus } from "../../model/Game"
813
import { compareScore, compareTeamIds } from "../../utils/PlayerUtils"
9-
import { Player, Team } from "../../model/Player"
14+
import { Player } from "../../model/Player"
1015
import { customStyles } from "../Tables/CustomStyles"
1116

17+
interface LeaderBoardPlayer {
18+
cardsBought?: number
19+
name: string
20+
picture: string
21+
previousCard?: string
22+
}
23+
24+
interface DoublesLeaderboardItem {
25+
teamId: string
26+
score: number
27+
rings: number
28+
player1: LeaderBoardPlayer
29+
player2: LeaderBoardPlayer
30+
winner: boolean
31+
}
32+
1233
const DoublesLeaderboard = () => {
13-
const game = useAppSelector(getGame)
34+
const round = useAppSelector(getRound)
35+
const players = useAppSelector(getGamePlayers)
1436
const playerProfiles = useAppSelector(getPlayerProfiles)
37+
const gameOver = useAppSelector(isGameFinished)
1538

1639
const previousHand = useMemo(() => {
17-
if (game.round)
18-
return game.round.completedHands[
19-
game.round.completedHands.length - 1
20-
]
21-
}, [game])
22-
23-
const gameOver = useMemo(() => game.status === GameStatus.FINISHED, [game])
40+
if (round) return round.completedHands[round.completedHands.length - 1]
41+
}, [round])
2442

2543
const getProfile = useCallback(
2644
(player: Player) =>
2745
playerProfiles.find(p => p.id === player.id, [playerProfiles]),
2846
[playerProfiles],
2947
)
3048

31-
const teams = useMemo<Team[]>(() => {
32-
const ps = game.players.sort(compareTeamIds)
49+
const mapToLeaderboard = useCallback(
50+
(player: Player): LeaderBoardPlayer => {
51+
const profile = getProfile(player)
52+
if (!profile) throw Error("No profile for player")
53+
const previousCard = previousHand?.playedCards.find(
54+
c => c.playerId === player.id,
55+
)
56+
return {
57+
cardsBought: player.cardsBought,
58+
name: profile.name,
59+
picture: profile.picture,
60+
previousCard: previousCard?.card,
61+
}
62+
},
63+
[previousHand],
64+
)
65+
66+
const leaderboardData = useMemo<DoublesLeaderboardItem[]>(() => {
67+
const ps = [...players].sort(compareTeamIds)
3368

3469
if (!ps) {
3570
return []
3671
}
37-
const teams: Team[] = [
72+
const items: DoublesLeaderboardItem[] = [
3873
{
39-
id: ps[0].teamId,
74+
teamId: ps[0].teamId,
4075
score: ps[0].score,
4176
rings: ps[0].rings,
42-
player1: ps[0],
43-
player2: ps[1],
77+
player1: mapToLeaderboard(ps[0]),
78+
player2: mapToLeaderboard(ps[1]),
4479
winner: ps[0].winner,
4580
},
4681
{
47-
id: ps[2].teamId,
82+
teamId: ps[2].teamId,
4883
score: ps[2].score,
4984
rings: ps[2].rings,
50-
player1: ps[2],
51-
player2: ps[3],
85+
player1: mapToLeaderboard(ps[2]),
86+
player2: mapToLeaderboard(ps[3]),
5287
winner: ps[2].winner,
5388
},
5489
{
55-
id: ps[4].teamId,
90+
teamId: ps[4].teamId,
5691
score: ps[4].score,
5792
rings: ps[4].rings,
58-
player1: ps[4],
59-
player2: ps[5],
93+
player1: mapToLeaderboard(ps[4]),
94+
player2: mapToLeaderboard(ps[5]),
6095
winner: ps[4].winner,
6196
},
6297
]
6398

64-
return teams.sort(compareScore)
65-
}, [])
99+
return items.sort(compareScore)
100+
}, [players])
66101

67-
const columns: TableColumn<Team>[] = [
102+
const columns: TableColumn<DoublesLeaderboardItem>[] = [
68103
{
69104
name: "Player 1",
70105
cell: row => (
71106
<>
72107
<div>
73108
<img
74109
alt="Image Preview"
75-
src={getProfile(row.player1)!.picture}
110+
src={row.player1.picture}
76111
className="avatar"
77112
/>
78113

79-
{!gameOver && !!previousHand ? (
114+
{!gameOver && !!row.player1.previousCard ? (
80115
<div>
81116
{previousHand ? (
82117
<img
83-
alt={
84-
previousHand.playedCards.find(
85-
p =>
86-
p.playerId ===
87-
row.player1.id,
88-
)?.card
89-
}
118+
alt={row.player1.previousCard}
90119
src={
91120
"/cards/thumbnails/" +
92-
previousHand.playedCards.find(
93-
p =>
94-
p.playerId ===
95-
row.player1.id,
96-
)?.card +
121+
row.player1.previousCard +
97122
".png"
98123
}
99124
className="thumbnail_size_small cardNotSelected"
@@ -119,24 +144,18 @@ const DoublesLeaderboard = () => {
119144
<div>
120145
<img
121146
alt="Image Preview"
122-
src={getProfile(row.player2)!.picture}
147+
src={row.player2.picture}
123148
className="avatar"
124149
/>
125150

126151
{!gameOver && previousHand ? (
127152
<div>
128153
{previousHand ? (
129154
<img
130-
alt={
131-
previousHand.playedCards.find(
132-
p => p.playerId === row.player2.id,
133-
)?.card
134-
}
155+
alt={row.player2.previousCard}
135156
src={
136157
"/cards/thumbnails/" +
137-
previousHand.playedCards.find(
138-
p => p.playerId === row.player1.id,
139-
)?.card +
158+
row.player2.previousCard +
140159
".png"
141160
}
142161
className="thumbnail_size_small cardNotSelected"
@@ -180,12 +199,7 @@ const DoublesLeaderboard = () => {
180199
},
181200
]
182201

183-
if (
184-
!game ||
185-
!game.status ||
186-
!playerProfiles ||
187-
playerProfiles.length === 0
188-
) {
202+
if (!playerProfiles || playerProfiles.length === 0) {
189203
return null
190204
}
191205

@@ -194,7 +208,7 @@ const DoublesLeaderboard = () => {
194208
<DataTable
195209
noHeader
196210
theme="solarized"
197-
data={teams}
211+
data={leaderboardData}
198212
columns={columns}
199213
highlightOnHover
200214
customStyles={customStyles}

0 commit comments

Comments
 (0)