Skip to content

Commit

Permalink
feat(user): scoreboard auto refresh
Browse files Browse the repository at this point in the history
  • Loading branch information
GZTimeWalker committed Jul 10, 2023
1 parent 7385fe4 commit ad057f9
Show file tree
Hide file tree
Showing 7 changed files with 85 additions and 62 deletions.
8 changes: 4 additions & 4 deletions src/GZCTF/ClientApp/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
"embla-carousel-react": "^7.1.0",
"katex": "^0.16.8",
"lz-string": "^1.5.0",
"marked": "^5.1.0",
"marked": "^5.1.1",
"pdfjs-dist": "3.6.172",
"prismjs": "^1.29.0",
"react": "^18.2.0",
Expand All @@ -49,13 +49,13 @@
"@trivago/prettier-plugin-sort-imports": "^4.1.1",
"@types/katex": "^0.16.0",
"@types/marked": "^5.0.0",
"@types/node": "20.4.0",
"@types/node": "20.4.1",
"@types/prismjs": "^1.26.0",
"@types/react": "^18.2.14",
"@types/react-dom": "^18.2.6",
"@typescript-eslint/eslint-plugin": "^5.61.0",
"@typescript-eslint/parser": "^5.61.0",
"@vitejs/plugin-react": "^4.0.2",
"@vitejs/plugin-react": "^4.0.3",
"axios": "^1.4.0",
"babel-plugin-prismjs": "^2.1.0",
"eslint": "8.44.0",
Expand All @@ -67,7 +67,7 @@
"swagger-typescript-api": "^12.0.4",
"tslib": "^2.6.0",
"typescript": "5.1.6",
"vite": "^4.4.1",
"vite": "^4.4.2",
"vite-plugin-pages": "^0.31.0",
"vite-plugin-prismjs": "^0.0.8",
"vite-plugin-webfont-dl": "^3.7.6"
Expand Down
60 changes: 30 additions & 30 deletions src/GZCTF/ClientApp/pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 3 additions & 5 deletions src/GZCTF/ClientApp/src/components/MobileScoreboardTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ import React, { FC, useEffect, useState } from 'react'
import { useParams } from 'react-router-dom'
import { Paper, Table, Group, Avatar, Box, Stack, Pagination, Select, Input } from '@mantine/core'
import { BloodBonus } from '@Utils/Shared'
import api, { ScoreboardItem, SubmissionType } from '@Api'
import { useGameScoreboard } from '@Utils/useGame'
import { ScoreboardItem, SubmissionType } from '@Api'
import MobileScoreboardItemModal from './MobileScoreboardItemModal'
import { ScoreboardProps, useScoreboardStyles } from './ScoreboardTable'

Expand Down Expand Up @@ -68,10 +69,7 @@ const MobileScoreboardTable: FC<ScoreboardProps> = ({ organization, setOrganizat
const [bloodBonus, setBloodBonus] = useState(BloodBonus.default)
const { classes, cx } = useScoreboardStyles()

const { data: scoreboard } = api.game.useGameScoreboard(numId, {
refreshInterval: 0,
revalidateOnFocus: false,
})
const { scoreboard } = useGameScoreboard(numId)

const filtered =
organization === 'all'
Expand Down
8 changes: 3 additions & 5 deletions src/GZCTF/ClientApp/src/components/ScoreboardTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ import {
import { Icon } from '@mdi/react'
import { BloodBonus, BloodsTypes, ChallengeTagLabelMap, SubmissionTypeIconMap } from '@Utils/Shared'
import { useTooltipStyles } from '@Utils/ThemeOverride'
import api, { ChallengeInfo, ChallengeTag, ScoreboardItem, SubmissionType } from '@Api'
import { useGameScoreboard } from '@Utils/useGame'
import { ChallengeInfo, ChallengeTag, ScoreboardItem, SubmissionType } from '@Api'
import ScoreboardItemModal from './ScoreboardItemModal'

export const useScoreboardStyles = createStyles((theme) => ({
Expand Down Expand Up @@ -260,10 +261,7 @@ const ScoreboardTable: FC<ScoreboardProps> = ({ organization, setOrganization })
const [activePage, setPage] = useState(1)
const [bloodBonus, setBloodBonus] = useState(BloodBonus.default)

const { data: scoreboard } = api.game.useGameScoreboard(numId, {
refreshInterval: 0,
revalidateOnFocus: false,
})
const { scoreboard } = useGameScoreboard(numId)

const filtered =
organization === 'all'
Expand Down
8 changes: 2 additions & 6 deletions src/GZCTF/ClientApp/src/components/TimeLine.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@ import ReactEcharts from 'echarts-for-react'
import { FC, useEffect, useState } from 'react'
import { useParams } from 'react-router-dom'
import { useMantineTheme } from '@mantine/core'
import { useGame } from '@Utils/useGame'
import api from '@Api'
import { useGame, useGameScoreboard } from '@Utils/useGame'

interface TimeLineProps {
organization: string | null
Expand All @@ -15,10 +14,7 @@ const TimeLine: FC<TimeLineProps> = ({ organization }) => {
const numId = parseInt(id ?? '-1')
const theme = useMantineTheme()

const { data: scoreboard } = api.game.useGameScoreboard(numId, {
refreshInterval: 0,
revalidateOnFocus: false,
})
const { scoreboard } = useGameScoreboard(numId)

const { game } = useGame(numId)

Expand Down
13 changes: 2 additions & 11 deletions src/GZCTF/ClientApp/src/pages/games/[id]/Index.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import dayjs from 'dayjs'
import { FC, useEffect, useState } from 'react'
import { Link, useNavigate, useParams } from 'react-router-dom'
import {
Expand All @@ -25,7 +24,7 @@ import MarkdownRender from '@Components/MarkdownRender'
import WithNavBar from '@Components/WithNavbar'
import { showErrorNotification } from '@Utils/ApiErrorHandler'
import { useBannerStyles, useIsMobile } from '@Utils/ThemeOverride'
import { useGame } from '@Utils/useGame'
import { getGameStatus, useGame } from '@Utils/useGame'
import { usePageTitle } from '@Utils/usePageTitle'
import { useTeams, useUser } from '@Utils/useUser'
import api, { GameJoinModel, ParticipationStatus } from '@Api'
Expand Down Expand Up @@ -95,15 +94,7 @@ const GameDetail: FC = () => {

const { classes, theme } = useBannerStyles()

const startTime = dayjs(game?.start) ?? dayjs()
const endTime = dayjs(game?.end) ?? dayjs()

const duriation = endTime.diff(startTime, 'minute')
const current = dayjs().diff(startTime, 'minute')

const finished = current > duriation
const started = current > 0
const progress = started ? (finished ? 100 : current / duriation) : 0
const { startTime, endTime, finished, started, progress } = getGameStatus(game)

const { user } = useUser()
const { teams } = useTeams()
Expand Down
42 changes: 41 additions & 1 deletion src/GZCTF/ClientApp/src/utils/useGame.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,25 @@
import api, { ParticipationStatus } from '@Api'
import dayjs from 'dayjs'
import api, { DetailedGameInfoModel, ParticipationStatus } from '@Api'

export const getGameStatus = (game?: DetailedGameInfoModel) => {
const startTime = dayjs(game?.start)
const endTime = dayjs(game?.end)

const duriation = endTime.diff(startTime, 'minute')
const current = dayjs().diff(startTime, 'minute')

const finished = current > duriation
const started = current > 0
const progress = started ? (finished ? 100 : current / duriation) : 0

return {
startTime,
endTime,
finished,
started,
progress,
}
}

export const useGame = (numId: number) => {
const {
Expand All @@ -12,3 +33,22 @@ export const useGame = (numId: number) => {

return { game, error, mutate, status: game?.status ?? ParticipationStatus.Unsubmitted }
}

export const useGameScoreboard = (numId: number) => {
const { game } = useGame(numId)

const { finished, started } = getGameStatus(game)

const inProgress = started && !finished

const {
data: scoreboard,
error,
mutate,
} = api.game.useGameScoreboard(numId, {
refreshInterval: inProgress ? 30 * 1000 : 0,
revalidateOnFocus: false,
})

return { scoreboard, error, mutate }
}

0 comments on commit ad057f9

Please sign in to comment.