diff --git a/front-end/src/seasons/fgc-2024/settings.tsx b/front-end/src/seasons/fgc-2024/settings.tsx index 4e278852..031837ec 100644 --- a/front-end/src/seasons/fgc-2024/settings.tsx +++ b/front-end/src/seasons/fgc-2024/settings.tsx @@ -19,7 +19,6 @@ import { goalGreenOnlyColorAtom, goalLedLengthAtom, matchEndBlueNexusGoalColorAtom, - matchEndRampColorAtom, matchEndRedNexusGoalColorAtom, prepareFieldColorAtom, rampBalancedColorAtom, @@ -49,9 +48,6 @@ export const Settings: FC = () => { useRecoilState(matchEndRedNexusGoalColorAtom); const [matchEndBlueNexusGoalColor, setMatchEndBlueNexusGoalColor] = useRecoilState(matchEndBlueNexusGoalColorAtom); - const [matchEndRampColor, setMatchEndRampColor] = useRecoilState( - matchEndRampColorAtom - ); const [redWledWebSocketAddress, setRedWledWebSocketAddress] = useRecoilState( redWledWebSocketAddressAtom ); @@ -154,13 +150,6 @@ export const Settings: FC = () => { format='string' inline /> - ({ effects: [localStorageEffect('ftf.matchEndBlueNexusGoalColor')] }); -export const matchEndRampColorAtom = atom({ - key: 'ftf.matchEndRampColor', - default: FeedingTheFutureFCS.defaultFieldOptions.matchEndRampColor, - effects: [localStorageEffect('ftf.matchEndRampColor')] -}); - export const redWledWebSocketAddressAtom = atom({ key: 'ftf.redWledWebSocketAddress', default: FeedingTheFutureFCS.defaultFieldOptions.redWledWebSocketAddress, @@ -167,7 +161,6 @@ export const fieldOptionsSelector: RecoilValueReadOnly void; private matchEmitter: EventEmitter; private actionQueue = new Map(); - private matchInProgress: boolean = false; + private matchState: 'prestart' | 'in progress' | 'ended' | 'aborted' = + 'prestart'; + + private previousBalanced = true; public constructor( fieldOptions: FieldOptions, @@ -247,7 +250,7 @@ export class PacketManager { }; public handleAbort = (): void => { - this.matchInProgress = false; + this.matchState = 'aborted'; const result: FieldControlUpdatePacket = { hubs: {}, wleds: {} }; applyPatternToStrips( @@ -287,7 +290,7 @@ export class PacketManager { }; public handleMatchStart = (): void => { - this.matchInProgress = true; + this.matchState = 'in progress'; const result: FieldControlUpdatePacket = { hubs: {}, wleds: {} }; applyPatternToStrips( @@ -309,7 +312,7 @@ export class PacketManager { }; public handleMatchEnd = (): void => { - this.matchInProgress = false; + this.matchState = 'ended'; const result: FieldControlUpdatePacket = { hubs: {}, wleds: {} }; applyPatternToStrips( @@ -322,11 +325,10 @@ export class PacketManager { LedStripA.ALL_RED_GOALS, result ); - applyPatternToStrips( - this.fieldOptions.matchEndRampColor, - [LedStripA.RAMP], - result - ); + + // Don't apply pattern to ramp. Keep current state and allow future updates + // directly from digital input + applySetpointToMotors(0, MotorA.ALL_GOALS, result); this.broadcastCallback(result); @@ -348,7 +350,7 @@ export class PacketManager { currentDetails: FeedingTheFuture.MatchDetails, broadcast: (update: FieldControlUpdatePacket) => void ) => { - if (!this.matchInProgress) return; + if (this.matchState !== 'in progress') return; this.handleGoalStateChange( previousDetails.redNexusState.CW1, @@ -567,12 +569,6 @@ export class PacketManager { 'blue', broadcast ); - - this.handleRampStateChange( - previousDetails.fieldBalanced, - currentDetails.fieldBalanced, - broadcast - ); }; private handleGoalStateChange = ( @@ -622,46 +618,42 @@ export class PacketManager { broadcast(result); }; - private handleRampStateChange = ( - previousBalanced: number, - currentBalanced: number, - broadcast: (update: FieldControlUpdatePacket) => void - ) => { - if (currentBalanced === previousBalanced) return; + public handleDigitalInputs = (packet: DigitalInputsResult) => { + const balanced = (packet.hubs[RevHub.CENTER_CONTROL_HUB] & 0x1) !== 1; + + if (balanced === this.previousBalanced) return; - // clearTimeout(this.timers.get('ramp')); this.actionQueue.delete('ramp'); - const hysteresisWindowMs = currentBalanced + const hysteresisWindowMs = balanced ? this.fieldOptions.rampBalancedHysteresisWindowMs : this.fieldOptions.rampUnbalancedHysteresisWindowMs; this.actionQueue.set('ramp', { timestamp: Date.now() + hysteresisWindowMs, callback: () => { - const result: FieldControlUpdatePacket = { hubs: {}, wleds: {} }; - applyPatternToStrips( - currentBalanced - ? this.fieldOptions.rampBalancedColor - : this.fieldOptions.rampUnbalancedColor, - [LedStripA.RAMP], - result - ); - broadcast(result); + if (this.matchState === 'in progress') { + this.matchEmitter.emit(MatchSocketEvent.MATCH_UPDATE_DETAILS_ITEM, { + key: 'fieldBalanced', + value: balanced + } satisfies ItemUpdate); + } + + if (this.matchState !== 'prestart' && this.matchState !== 'aborted') { + const result: FieldControlUpdatePacket = { hubs: {}, wleds: {} }; + applyPatternToStrips( + balanced + ? this.fieldOptions.rampBalancedColor + : this.fieldOptions.rampUnbalancedColor, + [LedStripA.RAMP], + result + ); + this.broadcastCallback(result); + } } }); }; - public handleDigitalInputs = (packet: DigitalInputsResult) => { - if (!this.matchInProgress) return; - - const balanced = (packet.hubs[RevHub.CENTER_CONTROL_HUB] & 0x1) !== 1; - this.matchEmitter.emit(MatchSocketEvent.MATCH_UPDATE_DETAILS_ITEM, { - key: 'fieldBalanced', - value: balanced - } satisfies ItemUpdate); - }; - runFoodProductionSequence = ( motor: MotorA, strip: LedStripA, @@ -671,7 +663,7 @@ export class PacketManager { const steps = 10; const recurse = (count: number) => { - if (!this.matchInProgress) return; + if (this.matchState !== 'in progress') return; // Base state. Food production is over, dispense food and update lights if (count === 0) { @@ -761,7 +753,6 @@ export interface FieldOptions { fieldFaultColor: string; matchEndRedNexusGoalColor: string; matchEndBlueNexusGoalColor: string; - matchEndRampColor: string; redWledWebSocketAddress: string; blueWledWebSocketAddress: string; centerWledWebSocketAddress: string; @@ -789,7 +780,6 @@ export const defaultFieldOptions: FieldOptions = { fieldFaultColor: 'ff0000', matchEndRedNexusGoalColor: 'ff0000', matchEndBlueNexusGoalColor: '0000ff', - matchEndRampColor: 'ff00ff', redWledWebSocketAddress: '', blueWledWebSocketAddress: '', centerWledWebSocketAddress: '',