From dc778644bef884bacb8cfbe35df07a95623336e7 Mon Sep 17 00:00:00 2001 From: Ty Tremblay Date: Thu, 11 Jan 2024 09:39:47 -0500 Subject: [PATCH 1/3] Add initial config for Crescendo --- config/2024/config.json | 278 ++++++++++++++++++++++++++++++++++++++++ config/schema.json | 3 + 2 files changed, 281 insertions(+) create mode 100644 config/2024/config.json diff --git a/config/2024/config.json b/config/2024/config.json new file mode 100644 index 0000000..5e79928 --- /dev/null +++ b/config/2024/config.json @@ -0,0 +1,278 @@ +{ + "$schema": "../schema.json", + "title": "QRScout", + "page_title": "Crescendo", + "sections": [ + { + "name": "Prematch", + "preserveDataOnReset": true, + "fields": [ + { + "title": "Scouter Initials", + "type": "text", + "required": true, + "code": "scouter" + }, + { + "title": "Match Number", + "type": "number", + "required": true, + "code": "matchNumber" + }, + { + "title": "Robot", + "type": "select", + "required": true, + "code": "robot", + "choices": { + "R1": "Red 1", + "R2": "Red 2", + "R3": "Red 3", + "B1": "Blue 1", + "B2": "Blue 2", + "B3": "Blue 3" + }, + "defaultValue": "R1" + }, + { + "title": "Team Number", + "type": "number", + "required": true, + "code": "teamNumber" + }, + { + "title": "Human Player at Amp", + "type": "boolean", + "required": false, + "defaultValue": false, + "code": "humanPlayer" + }, + { + "title": "No Show", + "type": "boolean", + "defaultValue": false, + "required": false, + "code": "noShow" + } + ] + }, + { + "name": "Autonomous", + "fields": [ + { + "code": "auamp", + "title": "Amp Scored", + "type": "counter", + "defaultValue": 0, + "min": 0, + "required": false + }, + { + "code": "auampm", + "title": "Amp Missed", + "type": "counter", + "defaultValue": 0, + "min": 0, + "required": false + }, + { + "code": "ausc", + "title": "Speaker Scored", + "type": "counter", + "defaultValue": 0, + "min": 0, + "required": false + }, + { + "code": "auln", + "title": "Loaded More Notes?", + "type": "counter", + "defaultValue": 0, + "min": 0, + "required": false + }, + { + "code": "auf", + "title": "Auto Foul", + "type": "boolean", + "defaultValue": false, + "required": false + } + ] + }, + { + "name": "Teleop", + "fields": [ + { + "code": "tcoop", + "title": "Coopertition", + "type": "boolean", + "defaultValue": false, + "required": false + }, + { + "code": "tamps", + "title": "Amp Scored", + "type": "counter", + "defaultValue": 0, + "min": 0, + "required": false + }, + { + "code": "tampm", + "title": "Amp Missed", + "type": "counter", + "defaultValue": 0, + "min": 0, + "required": false + }, + { + "code": "tsc", + "title": "Speaker Scored", + "type": "counter", + "defaultValue": 0, + "min": 0, + "required": false + }, + { + "code": "tsm", + "title": "Speaker Missed", + "type": "counter", + "defaultValue": 0, + "min": 0, + "required": false + }, + { + "title": "Note Pickup Location", + "type": "select", + "required": true, + "code": "Npl", + "choices": { + "N": "None", + "G": "Ground", + "MS": "Manually Set", + "B": "Both" + }, + "defaultValue": "None" + } + ] + }, + { + "name": "Endgame", + "fields": [ + { + "title": "End Position", + "type": "select", + "required": true, + "code": "epo", + "choices": { + "No": "No Climb", + "P": "Parked", + "Os": "Onstage", + "Sl": "Spotlight" + }, + "defaultValue": "No Climb" + }, + { + "code": "cn", + "title": "Note in Trap?", + "type": "boolean", + "defaultValue": 0, + "required": false + }, + { + "title": "Harmony", + "type": "select", + "required": true, + "code": "harm", + "choices": { + "Not": "Not Completed", + "Fir": "First on Chain", + "Sec": "Second on Chain", + "Thir": "Third on Chain" + }, + "defaultValue": "Not Completed" + }, + { + "title": "High Note", + "type": "select", + "required": true, + "code": "harm", + "choices": { + "Noo": "None", + "hupl": "Human Player", + "ro": "Robot" + }, + "defaultValue": "None" + } + ] + }, + { + "name": "Postmatch", + "fields": [ + { + "code": "or", + "title": "Offense Skill", + "type": "select", + "choices": { + "1": "Not Effective", + "2": "Average", + "3": "Very Effective", + "x": "Not Observed" + }, + "required": false + }, + { + "code": "dr", + "title": "Defense Skill", + "type": "select", + "choices": { + "1": "Not Effective", + "2": "Average", + "3": "Very Effective", + "x": "Not Observed" + }, + "defaultValue": "x", + "required": false + }, + { + "code": "Fou/Tech", + "title": "Foul", + "type": "counter", + "defaultValue": 0, + "required": false + }, + { + "code": "d", + "title": "Died", + "type": "boolean", + "defaultValue": false, + "required": false + }, + { + "code": "to", + "title": "Tipped Over", + "type": "boolean", + "defaultValue": false, + "required": false + }, + { + "code": "yc", + "title": "Yellow/Red Card", + "type": "boolean", + "defaultValue": false, + "required": false + }, + + { + "code": "co", + "title": "Comments", + "type": "text", + "min": 0, + "max": 50, + "required": false + } + ] + } + ] +} diff --git a/config/schema.json b/config/schema.json index 04d7409..6b2c612 100644 --- a/config/schema.json +++ b/config/schema.json @@ -5,6 +5,9 @@ "Config": { "type": "object", "properties": { + "$schema": { + "type": "string" + }, "title": { "type": "string" }, From bd36e688d6e143383ea2b9913ff44446e96c8208 Mon Sep 17 00:00:00 2001 From: Ty Tremblay Date: Thu, 11 Jan 2024 09:41:14 -0500 Subject: [PATCH 2/3] set 2024 as default config --- src/store/store.ts | 82 +++++++++++++++++++++++----------------------- 1 file changed, 41 insertions(+), 41 deletions(-) diff --git a/src/store/store.ts b/src/store/store.ts index cc6db57..3ba2872 100644 --- a/src/store/store.ts +++ b/src/store/store.ts @@ -1,97 +1,97 @@ -import { Config } from '../inputs/BaseInputProps' -import configJson from '../../config/2023/config.json' -import { createStore } from './createStore' -import { ChangeEvent } from 'react' -import {produce} from 'immer' +import { produce } from 'immer'; +import { ChangeEvent } from 'react'; +import configJson from '../../config/2024/config.json'; +import { Config } from '../inputs/BaseInputProps'; +import { createStore } from './createStore'; function buildConfig(c: Config) { - let config: Config = { ...c } + let config: Config = { ...c }; config.sections - .map((s) => s.fields) + .map(s => s.fields) .flat() - .forEach((f) => (f.value = f.defaultValue)) - return config + .forEach(f => (f.value = f.defaultValue)); + return config; } function getDefaultConfig(): Config { - return buildConfig(configJson as Config) + return buildConfig(configJson as Config); } export interface QRScoutState { - formData: Config - showQR: boolean + formData: Config; + showQR: boolean; } const initialState: QRScoutState = { formData: getDefaultConfig(), showQR: false, -} +}; export const useQRScoutState = createStore( initialState, 'qrScout', { version: 1, - } -) + }, +); export function updateValue(sectionName: string, code: string, data: any) { useQRScoutState.setState( produce((state: QRScoutState) => { - let section = state.formData.sections.find((s) => s.name === sectionName) + let section = state.formData.sections.find(s => s.name === sectionName); if (section) { - let field = section.fields.find((f) => f.code === code) + let field = section.fields.find(f => f.code === code); if (field) { - field.value = data + field.value = data; } } - }) - ) + }), + ); } export function resetSections() { useQRScoutState.setState( produce((state: QRScoutState) => state.formData.sections - .filter((s) => !s.preserveDataOnReset) - .map((s) => s.fields) + .filter(s => !s.preserveDataOnReset) + .map(s => s.fields) .flat() - .forEach((f) => { - f.value = f.defaultValue - }) - ) - ) + .forEach(f => { + f.value = f.defaultValue; + }), + ), + ); } export function setFormData(config: Config) { - useQRScoutState.setState({ formData: buildConfig(config) }) + useQRScoutState.setState({ formData: buildConfig(config) }); } export function uploadConfig(evt: ChangeEvent) { - var reader = new FileReader() + var reader = new FileReader(); reader.onload = function (e) { - const configText = e.target?.result as string - const jsonData = JSON.parse(configText) - setFormData(jsonData as Config) - } + const configText = e.target?.result as string; + const jsonData = JSON.parse(configText); + setFormData(jsonData as Config); + }; if (evt.currentTarget.files && evt.currentTarget.files.length > 0) { - reader.readAsText(evt.currentTarget.files[0]) + reader.readAsText(evt.currentTarget.files[0]); } } export const inputSelector = (section: string, code: string) => (state: QRScoutState) => { - const formData = state.formData + const formData = state.formData; return formData.sections - .find((s) => s.name === section) - ?.fields.find((f) => f.code === code) - } + .find(s => s.name === section) + ?.fields.find(f => f.code === code); + }; export function getQRCodeData(): string { return useQRScoutState .getState() - .formData.sections.map((s) => s.fields) + .formData.sections.map(s => s.fields) .flat() - .map((v) => `${v.value}`.replace(/\n/g, ' ')) - .join('\t') + .map(v => `${v.value}`.replace(/\n/g, ' ')) + .join('\t'); } From a00c2052a6a99fbb130645712d8a68b59e63290c Mon Sep 17 00:00:00 2001 From: Ty Tremblay Date: Thu, 11 Jan 2024 09:49:59 -0500 Subject: [PATCH 3/3] add ability to reset to default config --- src/app.tsx | 58 +++++++++++++++++++++++++--------------------- src/store/store.ts | 4 ++++ 2 files changed, 35 insertions(+), 27 deletions(-) diff --git a/src/app.tsx b/src/app.tsx index 2920f33..2c7c682 100644 --- a/src/app.tsx +++ b/src/app.tsx @@ -7,6 +7,7 @@ import Button, { Variant } from './components/core/Button'; import { getQRCodeData, resetSections, + resetToDefaultConfig, uploadConfig, useQRScoutState, } from './store/store'; @@ -102,10 +103,9 @@ export function App() { Reset -
+
-
diff --git a/src/store/store.ts b/src/store/store.ts index 3ba2872..9105b91 100644 --- a/src/store/store.ts +++ b/src/store/store.ts @@ -35,6 +35,10 @@ export const useQRScoutState = createStore( }, ); +export function resetToDefaultConfig() { + useQRScoutState.setState(initialState); +} + export function updateValue(sectionName: string, code: string, data: any) { useQRScoutState.setState( produce((state: QRScoutState) => {