diff --git a/app/game/post-match.tsx b/app/game/post-match.tsx index 9d529a8..746dae0 100644 --- a/app/game/post-match.tsx +++ b/app/game/post-match.tsx @@ -35,6 +35,7 @@ import React from "react"; import { Checkbox } from "../../lib/components/Checkbox"; import { RobotRole } from "../../lib/collection/RobotRole"; import { MatchEventType } from "../../lib/collection/MatchEventType"; +import { stealingTypeDescriptions } from "../../lib/collection/StealingType"; export default function PostMatch() { const reportState = useReportStateStore(); @@ -59,7 +60,7 @@ export default function PostMatch() { ); const hasEndgameClimbEvent = reportState.hasEndgameClimbEvent(); - + const hasAutoClimbEvent = reportState.hasAutoClimbEvent(); const endgameClimbIsMismatched = hasEndgameClimbEvent && reportState.climbResult === EndgameClimb.NotAttempted; @@ -128,6 +129,19 @@ export default function PostMatch() { multiSelect /> )} + {reportState.robotRole.includes(RobotRole.Stealing) && ( + ({ + label: desc.localizedDescription, + description: desc.localizedLongDescription, + value: desc.stealingType, + }))} + selected={reportState.stealingType} + onChange={reportState.setStealingType} + multiSelect + /> + )} {shouldShowDefenseEffectiveness && ( - ({ - label: desc.localizedDescription, - description: desc.localizedLongDescription, - value: desc.climb, - }))} - selected={reportState.autoClimb} - onChange={reportState.setAutoClimb} - /> + {hasAutoClimbEvent && ( + ({ + label: desc.localizedDescription, + description: desc.localizedLongDescription, + value: desc.climb, + }))} + selected={reportState.autoClimb} + onChange={reportState.setAutoClimb} + /> + )} + {hasEndgameClimbEvent && ( - ({ - label: desc.localizedDescription, - description: desc.localizedLongDescription, - value: desc.scoresWhileMoving, - }))} - selected={reportState.scoresWhileMoving} - onChange={reportState.setScoresWhileMoving} - /> + {reportState.hasEventOfType(MatchEventType.StartScoring) && ( + ({ + label: desc.localizedDescription, + description: desc.localizedLongDescription, + value: desc.scoresWhileMoving, + }))} + selected={reportState.scoresWhileMoving} + onChange={reportState.setScoresWhileMoving} + /> + )} void; setIntakeType: (value: IntakeType) => void; setFeederType: (value: FeederType[]) => void; + setStealingType: (value: StealingType[]) => void; setBeached: (value: Beached) => void; setDefenseEffectiveness: (value: DefenseEffectiveness) => void; setScoresWhileMoving: (value: ScoresWhileMoving) => void; diff --git a/lib/collection/RobotRole.ts b/lib/collection/RobotRole.ts index f401675..de2e4c6 100644 --- a/lib/collection/RobotRole.ts +++ b/lib/collection/RobotRole.ts @@ -4,6 +4,7 @@ export enum RobotRole { Feeding, Defending, Immobile, + Stealing, } export type RobotRoleDescription = { @@ -49,4 +50,11 @@ export const robotRoleDescriptions = [ "The robot was immobile or non-functional during the match.", num: 4, }, + { + role: RobotRole.Stealing, + localizedDescription: "Stealing", + localizedLongDescription: + "The robot steals fuel from the opposing alliance.", + num: 5, + }, ] as const satisfies RobotRoleDescription[]; diff --git a/lib/collection/ScoutReport.ts b/lib/collection/ScoutReport.ts index 66bd774..13e3264 100644 --- a/lib/collection/ScoutReport.ts +++ b/lib/collection/ScoutReport.ts @@ -20,6 +20,7 @@ export const RobotRoleString = z.enum([ "FEEDING", "DEFENDING", "IMMOBILE", + "STEALING", ]); export const AutoClimbString = z.enum(["NOT_ATTEMPTED", "FAILED", "SUCCEEDED"]); export const IntakeTypeString = z.enum([ @@ -28,7 +29,13 @@ export const IntakeTypeString = z.enum([ "BOTH", "NEITHER", ]); -export const FeederTypeString = z.enum(["CONTINUOUS", "STOP_TO_SHOOT", "DUMP"]); +export const FeederTypeString = z.enum([ + "CONTINUOUS", + "STOP_TO_SHOOT", + "DUMP", + "PUSH", +]); +export const StealingTypeString = z.enum(["TO_ALLIANCE", "TO_NEUTRAL"]); export const BeachedString = z.enum(["ON_FUEL", "ON_BUMP", "BOTH", "NEITHER"]); export const EndgameClimbString = z.enum([ "NOT_ATTEMPTED", @@ -55,8 +62,9 @@ export const scoutReportSchema = z.object({ autoClimb: AutoClimbString, intakeType: IntakeTypeString, feederTypes: z.array(FeederTypeString), + stealingType: z.array(StealingTypeString), beached: BeachedString, - defenseEffectiveness: z.number(), + defenseEffectiveness: z.number().or(z.null()), scoresWhileMoving: z.boolean(), endgameClimb: EndgameClimbString, driverAbility: z.number(), diff --git a/lib/collection/StealingType.ts b/lib/collection/StealingType.ts new file mode 100644 index 0000000..b968a2e --- /dev/null +++ b/lib/collection/StealingType.ts @@ -0,0 +1,28 @@ +export enum StealingType { + toAlliance, + toNeutral, +} + +export type StealingTypeDescription = { + stealingType: StealingType; + localizedDescription: string; + localizedLongDescription: string; + num: number; +}; + +export const stealingTypeDescriptions = [ + { + stealingType: StealingType.toAlliance, + localizedDescription: "To Alliance", + localizedLongDescription: + "The robot moves fuel from the opposing alliance zone to its alliance zone.", + num: 0, + }, + { + stealingType: StealingType.toNeutral, + localizedDescription: "To Neutral", + localizedLongDescription: + "The robot moves fuel from the opposing alliance zone to the neutral zone.", + num: 1, + }, +] as const satisfies StealingTypeDescription[]; diff --git a/lib/collection/reportStateStore.ts b/lib/collection/reportStateStore.ts index 6a66cee..e2bf07b 100644 --- a/lib/collection/reportStateStore.ts +++ b/lib/collection/reportStateStore.ts @@ -21,6 +21,7 @@ import { ScoresWhileMoving } from "./ScoresWhileMoving"; import { EndgameClimb } from "./EndgameClimb"; import { MatchEventType } from "./MatchEventType"; import Constants from "expo-constants"; +import { StealingType } from "./StealingType"; const initialState = { events: [], @@ -39,6 +40,7 @@ const initialState = { climbResult: EndgameClimb.NotAttempted, driverAbility: DriverAbility.Average, notes: "", + stealingType: [] as StealingType[], }; export const useReportStateStore = create((set, get) => ({ @@ -75,6 +77,7 @@ export const useReportStateStore = create((set, get) => ({ setClimbResult: (value) => set({ climbResult: value }), setDriverAbility: (value) => set({ driverAbility: value }), setNotes: (value) => set({ notes: value }), + setStealingType: (value) => set({ stealingType: value }), hasEventOfType: (...types: MatchEventType[]) => { const reportState = get(); @@ -220,7 +223,13 @@ export const useReportStateStore = create((set, get) => ({ // Map RobotRole enum to string const robotRoleToString = ( role: RobotRole, - ): "CYCLING" | "SCORING" | "FEEDING" | "DEFENDING" | "IMMOBILE" => { + ): + | "CYCLING" + | "SCORING" + | "FEEDING" + | "DEFENDING" + | "IMMOBILE" + | "STEALING" => { switch (role) { case RobotRole.Cycling: return "CYCLING"; @@ -231,7 +240,10 @@ export const useReportStateStore = create((set, get) => ({ case RobotRole.Defending: return "DEFENDING"; case RobotRole.Immobile: + default: return "IMMOBILE"; + case RobotRole.Stealing: + return "STEALING"; } }; @@ -284,14 +296,27 @@ export const useReportStateStore = create((set, get) => ({ // Map FeederType enum to string const feederTypeToString = ( feederType: FeederType, - ): "CONTINUOUS" | "STOP_TO_SHOOT" | "DUMP" => { + ): "CONTINUOUS" | "STOP_TO_SHOOT" | "PUSH" => { switch (feederType) { case FeederType.Continuous: return "CONTINUOUS"; case FeederType.StopToShoot: return "STOP_TO_SHOOT"; - case FeederType.Dump: - return "DUMP"; + case FeederType.Push: + return "PUSH"; + default: + return "PUSH"; + } + }; + + const stealingTypeToString = ( + stealingType: StealingType, + ): "TO_ALLIANCE" | "TO_NEUTRAL" => { + switch (stealingType) { + case StealingType.toAlliance: + return "TO_ALLIANCE"; + case StealingType.toNeutral: + return "TO_NEUTRAL"; } }; @@ -367,6 +392,7 @@ export const useReportStateStore = create((set, get) => ({ scoresWhileMoving: reportState.scoresWhileMoving === ScoresWhileMoving.Yes, endgameClimb: endgameClimbToString(reportState.climbResult), + stealingType: reportState.stealingType.map(stealingTypeToString), driverAbility: driverAbilityDescriptions.find( (desc) => desc.ability === reportState.driverAbility, )!.numericalRating,