From 04952c8065e8e711aef11eb75c387bf94fe01f7f Mon Sep 17 00:00:00 2001 From: Soren Zaiser Date: Wed, 11 Sep 2024 15:34:28 -0400 Subject: [PATCH] Update things and the models --- back-end/realtime/src/rooms/Match.ts | 5 +- front-end/src/api/use-socket.ts | 9 +++ .../apps/scorekeeper/hooks/use-prestart.ts | 7 +- .../seasons/fgc-generic/referee/TeamSheet.tsx | 21 ++++-- lib/models/src/seasons/FeedingTheFuture.ts | 71 +++++++++++++++++-- 5 files changed, 99 insertions(+), 14 deletions(-) diff --git a/back-end/realtime/src/rooms/Match.ts b/back-end/realtime/src/rooms/Match.ts index ea3b6e6c..342c7d6d 100644 --- a/back-end/realtime/src/rooms/Match.ts +++ b/back-end/realtime/src/rooms/Match.ts @@ -81,7 +81,6 @@ export default class Match extends Room { this.emitToAll(MatchSocketEvent.PRESTART, key); this.emitToAll(MatchSocketEvent.DISPLAY, 1); this.displayID = 1; - this.state = MatchState.PRESTART_COMPLETE; logger.info(`prestarting ${key.eventKey}-${key.tournamentKey}-${key.id}`); }); socket.on(MatchSocketEvent.ABORT, () => { @@ -177,6 +176,10 @@ export default class Match extends Room { })` ); } + } else { + logger.error( + `Failed to adjust match details field ${numberAdjustment.key} - match details not found` + ); } } ); diff --git a/front-end/src/api/use-socket.ts b/front-end/src/api/use-socket.ts index 88493948..90d29b61 100644 --- a/front-end/src/api/use-socket.ts +++ b/front-end/src/api/use-socket.ts @@ -2,6 +2,7 @@ import { createSocket } from '@toa-lib/client'; import { FcsPackets, FieldOptions, + Match, MatchKey, MatchSocketEvent } from '@toa-lib/models'; @@ -140,10 +141,18 @@ export function sendPrestart(key: MatchKey): void { socket?.emit(MatchSocketEvent.PRESTART, key); } +export function sendUpdate(match: Match): void { + socket?.emit(MatchSocketEvent.UPDATE, match); +} + export function setDisplays(): void { socket?.emit(MatchSocketEvent.DISPLAY, 2); } +export function once(key: MatchSocketEvent | string, callback: (data: any) => void): void { + socket?.once(key, callback); +} + export function sendPrepareField( fieldOptions?: FieldOptions, fcsPackets?: FcsPackets diff --git a/front-end/src/apps/scorekeeper/hooks/use-prestart.ts b/front-end/src/apps/scorekeeper/hooks/use-prestart.ts index a50b68c1..025766db 100644 --- a/front-end/src/apps/scorekeeper/hooks/use-prestart.ts +++ b/front-end/src/apps/scorekeeper/hooks/use-prestart.ts @@ -1,10 +1,10 @@ import { useRecoilCallback } from 'recoil'; import { useMatchControl } from './use-match-control'; -import { MatchState } from '@toa-lib/models'; +import { MatchSocketEvent, MatchState } from '@toa-lib/models'; import { matchOccurringAtom, socketConnectedAtom } from 'src/stores/recoil'; import { patchMatch, patchMatchParticipants } from 'src/api/use-match-data'; import { DateTime } from 'luxon'; -import { sendPrestart } from 'src/api/use-socket'; +import { once, sendPrestart, sendUpdate } from 'src/api/use-socket'; import { useSeasonFieldControl } from 'src/hooks/use-season-components'; export const usePrestartCallback = () => { @@ -37,6 +37,9 @@ export const usePrestartCallback = () => { match.participants ); fieldControl?.prestartField?.(); + // Once we recieve the prestart response, immediately send update to load socket with match + once(MatchSocketEvent.PRESTART, () => sendUpdate(match)); + // Send prestart to server sendPrestart({ eventKey, tournamentKey, id }); setState(MatchState.PRESTART_COMPLETE); }, diff --git a/front-end/src/seasons/fgc-generic/referee/TeamSheet.tsx b/front-end/src/seasons/fgc-generic/referee/TeamSheet.tsx index da697406..ebdef249 100644 --- a/front-end/src/seasons/fgc-generic/referee/TeamSheet.tsx +++ b/front-end/src/seasons/fgc-generic/referee/TeamSheet.tsx @@ -1,11 +1,12 @@ import { FC } from 'react'; -import { useRecoilState } from 'recoil'; +import { SetterOrUpdater, useRecoilState } from 'recoil'; import Box from '@mui/material/Box'; import ToggleButton from '@mui/material/ToggleButton'; import Typography from '@mui/material/Typography'; -import { CardStatusUpdate, MatchSocketEvent } from '@toa-lib/models'; +import { CardStatusUpdate, Match, MatchParticipant, MatchSocketEvent } from '@toa-lib/models'; import { useSocket } from 'src/api/use-socket'; import { useTeamIdentifiers } from 'src/hooks/use-team-identifier'; +import { matchOccurringAtom } from 'src/stores/recoil'; interface Props { station: number; @@ -13,11 +14,21 @@ interface Props { const TeamSheet: FC = ({ station }) => { const [socket] = useSocket(); - const [participant, setParticipant] = useRecoilState( - matchInProgressParticipantsByStationSelectorFam(station) - ); + const [match, setMatch]: [ + Match | null, + SetterOrUpdater | null> + ] = useRecoilState(matchOccurringAtom); const identifiers = useTeamIdentifiers(); + const participant = match?.participants?.find(p => p.station === station); + + const setParticipant = (participant: MatchParticipant) => { + if (match && match.participants) { + setMatch( + Object.assign({}, { ...match, participants: match.participants.map(p => (p.station === station ? participant : p)) }) + ); + } + }; const handleCardChange = (cardStatus: number) => { if (participant) { diff --git a/lib/models/src/seasons/FeedingTheFuture.ts b/lib/models/src/seasons/FeedingTheFuture.ts index 028866d5..38eadf8a 100644 --- a/lib/models/src/seasons/FeedingTheFuture.ts +++ b/lib/models/src/seasons/FeedingTheFuture.ts @@ -36,40 +36,76 @@ const functions: SeasonFunctions = { export interface MatchDetails extends MatchDetailBase { redResevoirConserved: number; - redNexusConserved: number; redFoodProduced: number; redFoodSecured: number; redRobotOneBalanced: number; redRobotTwoBalanced: number; redRobotThreeBalanced: number; + redNexusState: AllianceNexusGoalState; blueResevoirConserved: number; - blueNexusConserved: number; blueFoodProduced: number; blueFoodSecured: number; blueRobotOneBalanced: number; blueRobotTwoBalanced: number; blueRobotThreeBalanced: number; + blueNexusState: AllianceNexusGoalState; coopertition: number; } +export enum NexusGoalState { + Empty = 0, + BlueOnly = 1, + GreenOnly = 2, + Full = 3 +} +export interface AllianceNexusGoalState { + CW1: NexusGoalState; + CW2: NexusGoalState; + CW3: NexusGoalState; + CW4: NexusGoalState; + CW5: NexusGoalState; + CW6: NexusGoalState; + EC1: NexusGoalState; + EC2: NexusGoalState; + EC3: NexusGoalState; + EC4: NexusGoalState; + EC5: NexusGoalState; + EC6: NexusGoalState; +} + +export const defaultNexusGoalState: AllianceNexusGoalState = { + CW1: NexusGoalState.Empty, + CW2: NexusGoalState.Empty, + CW3: NexusGoalState.Empty, + CW4: NexusGoalState.Empty, + CW5: NexusGoalState.Empty, + CW6: NexusGoalState.Empty, + EC1: NexusGoalState.Empty, + EC2: NexusGoalState.Empty, + EC3: NexusGoalState.Empty, + EC4: NexusGoalState.Empty, + EC5: NexusGoalState.Empty, + EC6: NexusGoalState.Empty +}; + export const defaultMatchDetails: MatchDetails = { eventKey: '', id: -1, tournamentKey: '', redResevoirConserved: 0, - redNexusConserved: 0, redFoodProduced: 0, redFoodSecured: 0, redRobotOneBalanced: 0, redRobotTwoBalanced: 0, redRobotThreeBalanced: 0, + redNexusState: {...defaultNexusGoalState}, blueResevoirConserved: 0, - blueNexusConserved: 0, blueFoodProduced: 0, blueFoodSecured: 0, blueRobotOneBalanced: 0, blueRobotTwoBalanced: 0, blueRobotThreeBalanced: 0, + blueNexusState: {...defaultNexusGoalState}, coopertition: 0 }; @@ -347,9 +383,32 @@ export function getResevoirPoints(details: MatchDetails): [number, number] { } export function getNexusPoints(details: MatchDetails): [number, number] { + let [red, blue] = [0, 0]; + Object.keys(defaultNexusGoalState).forEach((key) => { + switch ((details.redNexusState as any)[key]) { + case NexusGoalState.BlueOnly: + case NexusGoalState.GreenOnly: + red += 1; + break; + case NexusGoalState.Full: + red += 2; + break; + } + + switch ((details.blueNexusState as any)[key]) { + case NexusGoalState.BlueOnly: + case NexusGoalState.GreenOnly: + blue += 1; + break; + case NexusGoalState.Full: + blue += 2; + break; + } + }); + return [ - details.redNexusConserved * ScoreTable.Conserved, - details.blueNexusConserved * ScoreTable.Conserved + red * ScoreTable.Conserved, + blue * ScoreTable.Conserved ]; }