diff --git a/package.json b/package.json index f30c749..901cec8 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,8 @@ "lint": "eslint src --ext ts,tsx --report-unused-disable-directives --max-warnings 0", "preview": "vite preview", "filldb": "tsx --tsconfig ./tsconfig.node.json scripts/filldb.ts", - "resetdb": "tsx --tsconfig ./tsconfig.node.json scripts/resetdb.ts" + "resetdb": "tsx --tsconfig ./tsconfig.node.json scripts/resetdb.ts", + "stats": "tsx --tsconfig ./tsconfig.node.json scripts/stats.ts" }, "dependencies": { "bootstrap": "^5.2.3", diff --git a/scripts/filldb.ts b/scripts/filldb.ts index adbdc95..e5ae63e 100644 --- a/scripts/filldb.ts +++ b/scripts/filldb.ts @@ -8,12 +8,19 @@ import { parseTeamsPlayers } from './filldb/parse'; import { addMembersToTeams, createEmptyTeams } from './filldb/teams'; import { createPlayers } from './filldb/players'; import { createGames, createTeachersGame } from './filldb/games'; +import { confirm } from './util'; const { POCKETBASE_ENDPOINT, POCKETBASE_ADMIN_EMAIL, POCKETBASE_ADMIN_PASSWORD } = process.env; assert(POCKETBASE_ENDPOINT, 'missing env var POCKETBASE_ENDPOINT'); assert(POCKETBASE_ADMIN_EMAIL, 'missing env var POCKETBASE_ADMIN_EMAIL'); assert(POCKETBASE_ADMIN_PASSWORD, 'missing env var POCKETBASE_ADMIN_PASSWORD'); +console.log(`Do you really want to fill the db at ${POCKETBASE_ENDPOINT} with teams and players?`) +console.warn('This might lead to duplicit data!'); +console.log('Confirm with y') +if (!await confirm()) + process.exit(1); + const csv = fs.readFileSync('./tymy.csv', 'utf8'); const teams = parseTeamsPlayers(csv); @@ -35,3 +42,4 @@ const nextNo = await createGames(studentTeams, pb); const teachersTeam = emptyTeams.find(t => t.teachers); assert(teachersTeam); await createTeachersGame(teachersTeam, nextNo, pb); +process.exit(0); diff --git a/scripts/resetdb.ts b/scripts/resetdb.ts index c30266e..f6cfd12 100644 --- a/scripts/resetdb.ts +++ b/scripts/resetdb.ts @@ -2,12 +2,19 @@ import assert from 'assert'; import 'dotenv/config'; import PocketBase from 'pocketbase'; import type { Game, GameState, Goal, News, Player, Team } from '../src/types'; +import { confirm } from './util'; const { POCKETBASE_ENDPOINT, POCKETBASE_ADMIN_EMAIL, POCKETBASE_ADMIN_PASSWORD } = process.env; assert(POCKETBASE_ENDPOINT, 'missing env var POCKETBASE_ENDPOINT'); assert(POCKETBASE_ADMIN_EMAIL, 'missing env var POCKETBASE_ADMIN_EMAIL'); assert(POCKETBASE_ADMIN_PASSWORD, 'missing env var POCKETBASE_ADMIN_PASSWORD'); +console.log(`Do you really want to reset the db at ${POCKETBASE_ENDPOINT}?`) +console.warn('This will delete data!'); +console.log('Confirm with y') +if (!await confirm()) + process.exit(1); + const TEACHERS_TEAM_ID = 'pg7a6r910fvfhlq'; const pb = new PocketBase(POCKETBASE_ENDPOINT); @@ -108,3 +115,4 @@ console.log(); console.log('DONE'); +process.exit(0); diff --git a/scripts/stats.ts b/scripts/stats.ts new file mode 100644 index 0000000..df4cac0 --- /dev/null +++ b/scripts/stats.ts @@ -0,0 +1,42 @@ +import assert from 'assert'; +import 'dotenv/config'; +import PocketBase from 'pocketbase'; +import type { Game, GameState, Goal, News, Player, Team } from '../src/types'; + +const { POCKETBASE_ENDPOINT, POCKETBASE_ADMIN_EMAIL, POCKETBASE_ADMIN_PASSWORD } = process.env; +assert(POCKETBASE_ENDPOINT, 'missing env var POCKETBASE_ENDPOINT'); +assert(POCKETBASE_ADMIN_EMAIL, 'missing env var POCKETBASE_ADMIN_EMAIL'); +assert(POCKETBASE_ADMIN_PASSWORD, 'missing env var POCKETBASE_ADMIN_PASSWORD'); + +const transformTeam = (team: Team, allGames: Game[]) => { + const { id, no, name, points } = team; + return { id, no, name, points, games: completedGames(team, allGames) }; +}; + +const completedGames = (team: Team, allGames: Game[]) => { + let res = 0; + for (const game of allGames) { + if (!game.finished) + continue; + + if (game.team1 === team.id || game.team2 === team.id) + res += 1; + } + + return res >= 9 ? 'DONE' : res; +}; + +const TEACHERS_TEAM_ID = 'pg7a6r910fvfhlq'; + +const pb = new PocketBase(POCKETBASE_ENDPOINT); +await pb.admins.authWithPassword(POCKETBASE_ADMIN_EMAIL, POCKETBASE_ADMIN_PASSWORD); + +const teamsColl = pb.collection('teams'); +const teams = await teamsColl.getFullList(); + +const gamesColl = pb.collection('games'); +const games = await gamesColl.getFullList(); + +const sortedTeams = [...teams].sort((a, b) => b.points - a.points); + +console.table(sortedTeams.map(t => transformTeam(t, games))); diff --git a/scripts/util.ts b/scripts/util.ts new file mode 100644 index 0000000..f174a27 --- /dev/null +++ b/scripts/util.ts @@ -0,0 +1,11 @@ +export const confirm = () => { + return new Promise((resolve, reject) => { + process.stdin.once('data', data => { + const letterCode = data[0]; + if (letterCode === 121) + resolve(true); + else + resolve(false); + }); + }); +}; diff --git a/src/admin-logic.ts b/src/admin-logic.ts index 1e7862a..62ec858 100644 --- a/src/admin-logic.ts +++ b/src/admin-logic.ts @@ -18,24 +18,24 @@ export const useAdminLogic = () => { gameMiscActions, } = useGameLogic(); - const startMatchFromStart = () => { - gameMiscActions.update(gameState.id as ReferenceTo, { + const startMatchFromStart = async () => { + await gameMiscActions.update(gameState.id as ReferenceTo, { matchStarted: true, currentGameNo: 0, currentGameStart: new Date(), }); }; - const startMatchFromNo = (no: number) => { - gameMiscActions.update(gameState.id as ReferenceTo, { + const startMatchFromNo = async (no: number) => { + await gameMiscActions.update(gameState.id as ReferenceTo, { matchStarted: true, currentGameNo: no, currentGameStart: new Date(), }); }; - const startGameNo = (no: number) => { - gameMiscActions.update(gameState.id as ReferenceTo, { + const startGameNo = async (no: number) => { + await gameMiscActions.update(gameState.id as ReferenceTo, { currentGameNo: no, currentGameStart: new Date(), }); @@ -68,13 +68,21 @@ export const useAdminLogic = () => { }; } - gamesActions.update(game.id as ReferenceTo, gameObjChange); - playersActions.update(player.id as ReferenceTo, { goals: [...player.goals, theGoal.id] } as Partial); + await Promise.all([ + gamesActions.update(game.id as ReferenceTo, gameObjChange), + playersActions.update(player.id as ReferenceTo, { goals: [...player.goals, theGoal.id] } as Partial), + ]); }; - const savePoints = (team1: Team, team2: Team, newPoints1: number, newPoints2: number) => { - teamsActions.update(team1.id as ReferenceTo, { points: team1.points + newPoints1 } as Partial); - teamsActions.update(team2.id as ReferenceTo, { points: team2.points + newPoints2 } as Partial); + const savePoints = async (team1: Team, team2: Team, newPoints1: number, newPoints2: number) => { + await Promise.all([ + teamsActions.update(team1.id as ReferenceTo, { points: team1.points + newPoints1 } as Partial), + teamsActions.update(team2.id as ReferenceTo, { points: team2.points + newPoints2 } as Partial), + ]); + }; + + const finishGame = async (game: Game) => { + await gamesActions.update(game.id as ReferenceTo, { finished: true } as Partial); }; return { @@ -83,5 +91,6 @@ export const useAdminLogic = () => { startGameNo, newGoal, savePoints, + finishGame, }; }; diff --git a/src/components/app-header.tsx b/src/components/app-header.tsx index f62ae60..556f79a 100644 --- a/src/components/app-header.tsx +++ b/src/components/app-header.tsx @@ -19,7 +19,6 @@ export const AppHeader: React.FC = () => { Velká tabulka Bufet Hlasování - Admin diff --git a/src/pages/admin/home.tsx b/src/pages/admin/home.tsx index 9e5146d..2506c6b 100644 --- a/src/pages/admin/home.tsx +++ b/src/pages/admin/home.tsx @@ -19,6 +19,7 @@ export const AdminHomePage: React.FC = () => { teams, games, gameState, + currentGame, // startNextGame, // prevGame, // startMatch, @@ -29,6 +30,7 @@ export const AdminHomePage: React.FC = () => { startMatchFromNo, startGameNo, savePoints, + finishGame, } = useAdminLogic(); const [showGameNo, setShowGameNo] = useState(gameState.currentGameNo); @@ -80,20 +82,17 @@ export const AdminHomePage: React.FC = () => { setShowGameNo(prev => prev - 1); }; - const startNextGame = () => { - showNextGame(); - startGameNo(showGameNo + 1); - }; - - const startCurrentGame = () => { - startGameNo(showGameNo); + const startCurrentGame = async () => { + await startGameNo(showGameNo); }; - const saveStartNext = () => { - if (!team1 || !team2) + const saveStartNext = async () => { + if (!team1 || !team2 || !currentGame.game) return; - savePoints(team1, team2, newPoints1, newPoints2); - startNextGame(); + await savePoints(team1, team2, newPoints1, newPoints2); + await finishGame(currentGame.game); + await startGameNo(showGameNo + 1); + showNextGame(); } return (