diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..276017e --- /dev/null +++ b/.env.example @@ -0,0 +1,6 @@ +DB_HOST = "0" +DB_USER = "0" +DB_PASSWORD = "0" +POSTGRES_DATABASE = "0" +USE_DB = "false" +DB_PORT = "0" \ No newline at end of file diff --git a/bun.lockb b/bun.lockb index 79162bd..ceef880 100755 Binary files a/bun.lockb and b/bun.lockb differ diff --git a/migrations/DB.sql b/migrations/DB.sql new file mode 100644 index 0000000..ebf367c --- /dev/null +++ b/migrations/DB.sql @@ -0,0 +1,171 @@ +CREATE TYPE tele_action_type AS ENUM ( + 'IntakeTote', + 'IntakeBalloon', + 'TakeBalloonFromCoral', + + 'ScoreYourHeldTote', + 'ScoreOtherHeldTote', + 'ScoreExternalTote', + 'ScoreLowBalloon' +); +CREATE TYPE auto_action_type as ENUM ( + 'IntakeTote', + 'IntakeBalloon', + 'TakeBalloonFromCoral', + + 'ScoreYourHeldTote', + 'ScoreOtherHeldTote', + 'ScoreExternalTote', + 'ScoreLowBalloon', + + 'IntakeBunny', + 'ScoreBunnyTote', + 'ScoreBunnyLowZone' +); +CREATE TYPE tele_action_data AS ( + act tele_action_type, + success BOOLEAN +); +CREATE TYPE auto_action_data AS ( + act auto_action_type, + success BOOLEAN +); +CREATE TYPE drivetrain_enum as ENUM ( + 'Swerve', + 'Tank', + 'Other' +); + +CREATE TABLE "Users"( + "id" SERIAL PRIMARY KEY, + "name" VARCHAR(255) NOT NULL, + "is_admin" BOOLEAN NOT NULL +); +CREATE TABLE "Teams"( + "team_key" VARCHAR(255) NOT NULL, + "nickname" VARCHAR(255) NOT NULL +); +ALTER TABLE + "Teams" ADD PRIMARY KEY("team_key"); +CREATE TABLE "Matches"( + "match_key" VARCHAR(255) NOT NULL, + "event_key" VARCHAR(255) NOT NULL +); +ALTER TABLE + "Matches" ADD PRIMARY KEY("match_key"); +CREATE TABLE "TeamMatches"( + "id" SERIAL PRIMARY KEY, + "scout_id" VARCHAR(255) NOT NULL, + "match_key" VARCHAR(255) NOT NULL, + "team_key" VARCHAR(255) NOT NULL, + "skill_field_awareness" SMALLINT NOT NULL, + "skill_quickness" SMALLINT NOT NULL, + "notes" VARCHAR(255) NOT NULL, + "broke" BOOLEAN NOT NULL, + "died" BOOLEAN NOT NULL, + "tele_action_id" SMALLINT NOT NULL, + "auto_action_id" SMALLINT NOT NULL +); +CREATE TABLE "TeleActions"( + "id" SERIAL PRIMARY KEY, + "tote_intake_success" SMALLINT NOT NULL, + "tote_intake_failure" SMALLINT NOT NULL, + "tote_eject_success" SMALLINT NOT NULL, + "tote_eject_failure" SMALLINT NOT NULL, + "balloon_intake_success" SMALLINT NOT NULL, + "balloon_intake_failure" SMALLINT NOT NULL, + "balloon_eject_success" SMALLINT NOT NULL, + "balloon_eject_failure" SMALLINT NOT NULL, + "score_low_success" SMALLINT NOT NULL, + "score_low_failure" SMALLINT NOT NULL, + "score_internal_success" SMALLINT NOT NULL, + "score_internal_failure" SMALLINT NOT NULL, + "score_external_success" SMALLINT NOT NULL, + "score_external_failure" SMALLINT NOT NULL, + "score_uncontrolled_success" SMALLINT NOT NULL, + "score_uncontrolled_failure" SMALLINT NOT NULL, + "bunny_eject_success" SMALLINT NOT NULL, + "bunny_eject_failure" SMALLINT NOT NULL, + "actions" tele_action_data[] +); +CREATE TABLE "AutoActions"( + "id" SERIAL PRIMARY KEY, + "tote_intake_success" SMALLINT NOT NULL, + "tote_intake_failure" SMALLINT NOT NULL, + "tote_eject_success" SMALLINT NOT NULL, + "tote_eject_failure" SMALLINT NOT NULL, + "balloon_intake_success" SMALLINT NOT NULL, + "balloon_intake_failure" SMALLINT NOT NULL, + "balloon_eject_success" SMALLINT NOT NULL, + "balloon_eject_failure" SMALLINT NOT NULL, + "score_low_success" SMALLINT NOT NULL, + "score_low_failure" SMALLINT NOT NULL, + "score_internal_sucess" SMALLINT NOT NULL, + "score_internal_failure" SMALLINT NOT NULL, + "score_external_success" SMALLINT NOT NULL, + "score_external_failure" SMALLINT NOT NULL, + "score_uncontrolled_success" SMALLINT NOT NULL, + "score_uncontrolled_failure" SMALLINT NOT NULL, + "bunny_intake_success" SMALLINT NOT NULL, + "bunny_intake_failure" SMALLINT NOT NULL, + "bunny_eject_success" SMALLINT NOT NULL, + "bunny_eject_failure" SMALLINT NOT NULL, + "bunny_internal_success" SMALLINT NOT NULL, + "bunny_internal_failure" SMALLINT NOT NULL, + "bunny_external_success" SMALLINT NOT NULL, + "bunny_external_failure" SMALLINT NOT NULL, + "bunny_uncontrolled_success" SMALLINT NOT NULL, + "bunny_uncontrolled_failure" SMALLINT NOT NULL, + "bunny_low_success" SMALLINT NOT NULL, + "bunny_low_failure" SMALLINT NOT NULL, + "actions" auto_action_data[] +); +CREATE TABLE "AllianceMatches"( + "id" SERIAL PRIMARY KEY, + "scout_id" VARCHAR(255) NOT NULL, + "match_key" VARCHAR(255) NOT NULL, + "alliance_key" VARCHAR(255) NOT NULL, + "one_strengths" VARCHAR(255) NOT NULL, + "two_strengths" VARCHAR(255) NOT NULL, + "three_strengths" VARCHAR(255) NOT NULL, + "one_weaknesses" VARCHAR(255) NOT NULL, + "two_weaknesses" VARCHAR(255) NOT NULL, + "three_weaknesses" VARCHAR(255) NOT NULL, + "notes" VARCHAR(255) NOT NULL, + "match_notes" VARCHAR(255) NOT NULL +); +CREATE TABLE "TeamEvents"( + "id" SERIAL PRIMARY KEY, + "scout_id" VARCHAR(255) NOT NULL, + "team_key" VARCHAR(255) NOT NULL, + "width" SMALLINT NOT NULL, + "length" SMALLINT NOT NULL, + "height" SMALLINT NOT NULL, + "is_camera" BOOLEAN NOT NULL, + "drivetrain_enum" drivetrain_enum NOT NULL, + "is_slippery" BOOLEAN NOT NULL, + "is_tote_intake" BOOLEAN NOT NULL, + "is_balloon_intake" BOOLEAN NOT NULL, + "number_bunny_autos" SMALLINT NOT NULL, + "polish" SMALLINT NOT NULL, + "robot_notes" VARCHAR(255) NOT NULL, + "minibot_notes" VARCHAR(255) NOT NULL +); +-- ALTER TABLE +-- "TeamEvents" ADD CONSTRAINT "teamevents_scout_id_foreign" FOREIGN KEY("scout_id") REFERENCES "Users"("id"); +-- ALTER TABLE +-- "AllianceMatches" ADD CONSTRAINT "alliancematches_match_key_foreign" FOREIGN KEY("match_key") REFERENCES "Matches"("match_key"); +-- ALTER TABLE +-- "TeamMatches" ADD CONSTRAINT "teammatches_team_key_foreign" FOREIGN KEY("team_key") REFERENCES "Teams"("team_key"); +-- ALTER TABLE +-- "TeamMatches" ADD CONSTRAINT "teammatches_match_key_foreign" FOREIGN KEY("match_key") REFERENCES "Matches"("match_key"); +-- ALTER TABLE +-- "TeamMatches" ADD CONSTRAINT "teammatches_scout_id_foreign" FOREIGN KEY("scout_id") REFERENCES "Users"("id"); +-- ALTER TABLE +-- "TeamMatches" ADD CONSTRAINT "teammatches_auto_id_foreign" FOREIGN KEY("auto_action_id") REFERENCES "AutoActions"("id"); +-- ALTER TABLE +-- "TeamEvents" ADD CONSTRAINT "teamevents_team_key_foreign" FOREIGN KEY("team_key") REFERENCES "Teams"("team_key"); +-- ALTER TABLE +-- "TeamMatches" ADD CONSTRAINT "teammatches_tele_id_foreign" FOREIGN KEY("tele_action_id") REFERENCES "TeleActions"("id"); +-- ALTER TABLE +-- "AllianceMatches" ADD CONSTRAINT "alliancematches_scout_id_foreign" FOREIGN KEY("scout_id") REFERENCES "Users"("id"); \ No newline at end of file diff --git a/package.json b/package.json index 6ab1768..dfd5712 100644 --- a/package.json +++ b/package.json @@ -13,25 +13,34 @@ }, "devDependencies": { "@sveltejs/adapter-auto": "^3.3.1", - "@sveltejs/kit": "^2.9.0", - "@sveltejs/vite-plugin-svelte": "^4.0.2", + "@sveltejs/kit": "^2.8.1", + "@types/node": "^22.9.0", + "@types/pg": "^8.11.10", + "@typescript-eslint/eslint-plugin": "^8.14.0", + "@typescript-eslint/parser": "^8.14.0", + "@sveltejs/vite-plugin-svelte": "^4.0.0", "@types/eslint": "^9.6.1", - "autoprefixer": "^10.4.20", - "eslint": "^9.16.0", + "eslint": "^9.14.0", "eslint-config-prettier": "^9.1.0", - "eslint-plugin-svelte": "^2.46.1", - "globals": "^15.13.0", - "prettier": "^3.4.1", - "prettier-plugin-svelte": "^3.3.2", - "prettier-plugin-tailwindcss": "^0.6.9", - "svelte": "^5.5.2", - "svelte-check": "^4.1.1", - "tailwindcss": "^3.4.16", - "typescript": "^5.7.2", - "typescript-eslint": "^8.17.0", - "vite": "^5.4.11" + "eslint-plugin-svelte": "^2.46.0", + "postcss": "^8.4.49", + "globals": "^15.12.0", + "prettier": "^3.3.3", + "prettier-plugin-svelte": "^3.2.8", + "svelte": "^5.1.16", + "svelte-check": "^4.0.7", + "tslib": "^2.8.1", + "prettier-plugin-tailwindcss": "^0.6.8", + "typescript": "^5.6.3" }, "dependencies": { + "autoprefixer": "^10.4.20", + "mysql2": "^3.11.4", + "pg": "^8.13.1", + "postgresql": "^0.0.1", + "tailwindcss": "^3.4.14", + "typescript-eslint": "^8.14.0", + "vite": "^5.4.11", "lucide-svelte": "^0.460.1", "socket.io": "^4.8.1", "socket.io-client": "^4.8.1" diff --git a/src/lib/server-assets/database.ts b/src/lib/server-assets/database.ts new file mode 100644 index 0000000..e3cb8c0 --- /dev/null +++ b/src/lib/server-assets/database.ts @@ -0,0 +1,227 @@ +import pg from 'pg'; +const { Client } = pg; +import { + DB_HOST, + DB_USER, + DB_PASSWORD, + POSTGRES_DATABASE, + DB_PORT, + USE_DB +} from '$env/static/private'; +import type { + AutoAction, + AutoActionData, + AutoActionsTM, + TeamMatch, + TeleAction, + TeleActionData, + TeleActionsTM +} from '$lib/types'; + +// Whether or not the database is currently being used +const use_db: boolean = USE_DB === 'true'; + +console.log(Number.parseInt(DB_PORT)); + +const db = new Client({ + user: DB_USER, + password: DB_PASSWORD, + host: DB_HOST, + port: Number.parseInt(DB_PORT), + database: POSTGRES_DATABASE +}); +await db.connect(); + +// Returns the number of occurences of the action val with success status success in the auto-actions of match +function countAuto(val: AutoAction, success: boolean, match: TeamMatch): number { + return match.auto_actions.filter((data) => data.action === val && data.success == success) + .length; +} + +// Returns the number of occurences of the action val with success status success in the tele-actions of match +function countTele(val: TeleAction, success: boolean, match: TeamMatch): number { + return match.tele_actions.filter((data) => data.action === val && data.success == success) + .length; +} + +// Returns the TeleActionsTM object associated to any TeamMatch by counting the occurrences of each TeleAction and then passing along the array of TeleActionDatas. +function matchToTeleActionsTM(match: TeamMatch): TeleActionsTM { + return { + id: match.id, + tote_intake_success: countTele('IntakeTote', true, match), + tote_intake_failure: countTele('IntakeTote', false, match), + tote_eject_success: countTele('EjectTote', true, match), + tote_eject_failure: countTele('EjectTote', false, match), + balloon_intake_success: countTele('IntakeBalloon', true, match), + balloon_intake_failure: countTele('IntakeBalloon', false, match), + balloon_eject_success: countTele('EjectBalloon', true, match), + balloon_eject_failure: countTele('EjectBalloon', false, match), + score_low_success: countTele('ScoreBalloonLow', true, match), + score_low_failure: countTele('ScoreBalloonLow', false, match), + score_internal_success: countTele('ScoreBalloonInternalTote', true, match), + score_internal_failure: countTele('ScoreBalloonInternalTote', false, match), + score_external_success: countTele('ScoreBalloonExternalTote', true, match), + score_external_failure: countTele('ScoreBalloonExternalTote', false, match), + score_uncontrolled_success: countTele('ScoreBalloonUncontrolledTote', true, match), + score_uncontrolled_failure: countTele('ScoreBalloonUncontrolledTote', false, match), + bunny_eject_success: countTele('EjectBunny', false, match), + bunny_eject_failure: countTele('EjectBunny', false, match), + actions: match.tele_actions + }; +} + +// Returns the AutoActionsTM object associated to any TeamMatch by counting the occurrences of each AutoAction and then passing along the array of AutoActionDatas. +function matchToAutoActionsTM(match: TeamMatch): AutoActionsTM { + return { + id: match.id, + tote_intake_success: countAuto('IntakeTote', true, match), + tote_intake_failure: countAuto('IntakeTote', false, match), + tote_eject_success: countAuto('EjectTote', true, match), + tote_eject_failure: countAuto('EjectTote', false, match), + balloon_intake_success: countAuto('IntakeBalloon', true, match), + balloon_intake_failure: countAuto('IntakeBalloon', false, match), + balloon_eject_success: countAuto('EjectBalloon', true, match), + balloon_eject_failure: countAuto('EjectBalloon', false, match), + score_low_success: countAuto('ScoreBalloonLow', true, match), + score_low_failure: countAuto('ScoreBalloonLow', false, match), + score_internal_success: countAuto('ScoreBalloonInternalTote', true, match), + score_internal_failure: countAuto('ScoreBalloonInternalTote', false, match), + score_external_success: countAuto('ScoreBalloonExternalTote', true, match), + score_external_failure: countAuto('ScoreBalloonExternalTote', false, match), + score_uncontrolled_success: countAuto('ScoreBalloonUncontrolledTote', true, match), + score_uncontrolled_failure: countAuto('ScoreBalloonUncontrolledTote', false, match), + bunny_eject_success: countAuto('EjectBunny', false, match), + bunny_eject_failure: countAuto('EjectBunny', false, match), + bunny_intake_success: countAuto('IntakeBunny', true, match), + bunny_intake_failure: countAuto('IntakeBunny', false, match), + bunny_internal_success: countAuto('ScoreBunnyInternalTote', true, match), + bunny_internal_failure: countAuto('ScoreBunnyInternalTote', false, match), + bunny_external_success: countAuto('ScoreBunnyExternalTote', true, match), + bunny_external_failure: countAuto('ScoreBunnyExternalTote', false, match), + bunny_uncontrolled_success: countAuto('ScoreBunnyUncontrolledTote', true, match), + bunny_uncontrolled_failure: countAuto('ScoreBunnyUncontrolledTote', false, match), + bunny_low_success: countAuto('ScoreBunnyLow', true, match), + bunny_low_failure: countAuto('ScoreBunnyLow', false, match), + actions: match.auto_actions + }; +} + +// Black magic string sorcery to turn a string of actions into an sql-suitable form +function convertTele(arr: TeleActionData[]): string { + return ( + 'ARRAY[' + + arr.map((a) => "ROW('" + a.action + "', " + a.success + ')').join(', ') + + ']::tele_action_data[]' + ); +} + +function convertAuto(arr: AutoActionData[]): string { + return ( + 'ARRAY[' + + arr.map((a) => "ROW('" + a.action + "', " + a.success + ')').join(', ') + + ']::auto_action_data[]' + ); +} + +export async function insertTeamMatch(match: TeamMatch): Promise { + if (!use_db) return true; + + const teledata = matchToTeleActionsTM(match); + const autodata = matchToAutoActionsTM(match); + let { scout_id, match_key, team_key, awareness, quickness, notes, broke, died } = match; + + try { + const tele_query = await db.query( + 'INSERT INTO "TeleActions" VALUES (DEFAULT, $1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, ' + + convertTele(teledata.actions) + + ') RETURNING id', + [ + teledata.tote_intake_success, + teledata.tote_intake_failure, + teledata.tote_eject_success, + teledata.tote_eject_failure, + teledata.balloon_intake_success, + teledata.balloon_intake_failure, + teledata.balloon_eject_success, + teledata.balloon_eject_failure, + teledata.score_low_success, + teledata.score_low_failure, + teledata.score_internal_success, + teledata.score_internal_failure, + teledata.score_external_success, + teledata.score_external_failure, + teledata.score_uncontrolled_success, + teledata.score_uncontrolled_failure, + teledata.bunny_eject_success, + teledata.bunny_eject_failure + ] + ); + const tele_id = tele_query.rows[0].id; + + const auto_query = await db.query( + 'INSERT INTO "AutoActions" VALUES (DEFAULT, $1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21, $22, $23, $24, $25, $26, $27, $28, ' + + convertAuto(autodata.actions) + + ') RETURNING id', + [ + autodata.tote_intake_success, + autodata.tote_intake_failure, + autodata.tote_eject_success, + autodata.tote_eject_failure, + autodata.balloon_intake_success, + autodata.balloon_intake_failure, + autodata.balloon_eject_success, + autodata.balloon_eject_failure, + autodata.score_low_success, + autodata.score_low_failure, + autodata.score_internal_success, + autodata.score_internal_failure, + autodata.score_external_success, + autodata.score_external_failure, + autodata.score_uncontrolled_success, + autodata.score_uncontrolled_failure, + autodata.bunny_intake_success, + autodata.bunny_intake_failure, + autodata.bunny_eject_success, + autodata.bunny_eject_failure, + autodata.bunny_internal_success, + autodata.bunny_internal_failure, + autodata.bunny_external_success, + autodata.bunny_external_failure, + autodata.bunny_uncontrolled_success, + autodata.bunny_uncontrolled_failure, + autodata.bunny_low_success, + autodata.bunny_low_failure + ] + ); + const auto_id = auto_query.rows[0].id; + + await db.query( + 'INSERT INTO "TeamMatches" VALUES (DEFAULT, $1, $2, $3, $4, $5, $6, $7, $8, $9, $10)', + [ + scout_id, + match_key, + team_key, + awareness, + quickness, + notes, + broke, + died, + tele_id, + auto_id + ] + ); + + return true; + } catch (error) { + console.error(error); + return false; + } +} + +export async function select(matchkey: string, teamkey: string) { + let response = await db.query( + 'SELECT * FROM "TeamMatches" WHERE "match_key" = $1 AND "team_key" = $2', + [matchkey, teamkey] + ); + return response.rows; +} diff --git a/src/lib/types.ts b/src/lib/types.ts index a18847c..8b4cff0 100644 --- a/src/lib/types.ts +++ b/src/lib/types.ts @@ -12,6 +12,24 @@ export type User = { }; /// Counts +export type AutoActionsTM = ActionsTM & { + bunny_intake_success: number; + bunny_intake_failure: number; + bunny_internal_success: number; + bunny_internal_failure: number; + bunny_external_success: number; + bunny_external_failure: number; + bunny_uncontrolled_success: number; + bunny_uncontrolled_failure: number; + bunny_low_success: number; + bunny_low_failure: number; + actions: AutoActionData[]; +}; + +export type TeleActionsTM = ActionsTM & { + actions: TeleActionData[]; +}; + export type ActionsTM = { id: number; tote_intake_success: number; @@ -19,29 +37,19 @@ export type ActionsTM = { tote_eject_success: number; tote_eject_failure: number; balloon_intake_success: number; - bollon_intake_failure: number; + balloon_intake_failure: number; + balloon_eject_success: number; + balloon_eject_failure: number; score_low_success: number; score_low_failure: number; score_internal_success: number; score_internal_failure: number; score_external_success: number; score_external_failure: number; - score_other_robot_success: number; - score_other_robot_failure: number; -}; - -export type AutoActionsTM = ActionsTM & { - bunny_intake_success: number; - bunny_intake_failure: number; - bunny_tote_success: number; - bunny_tote_failure: number; - bunny_low_success: number; - bunny_low_failure: number; - actions: AutoActionData[]; -}; - -export type TeleActionsTM = ActionsTM & { - actions: TeleActionData[]; + score_uncontrolled_success: number; + score_uncontrolled_failure: number; + bunny_eject_success: number; + bunny_eject_failure: number; }; export type TeamMatch = { @@ -49,7 +57,7 @@ export type TeamMatch = { scout_id: string; match_key: string; team_key: string; - speed: number; + quickness: number; awareness: number; notes: string; broke: boolean; @@ -58,14 +66,14 @@ export type TeamMatch = { tele_actions: TeleActionData[]; }; -export type TeleActionData = { - action: TeleAction; +export type AutoActionData = { + action: AutoAction; success: boolean; ok: boolean; }; -export type AutoActionData = { - action: AutoAction; +export type TeleActionData = { + action: TeleAction; success: boolean; ok: boolean; }; @@ -75,7 +83,6 @@ export type AutoActionData = { export type TeleAction = | 'IntakeTote' | 'IntakeBalloon' - | 'IntakeBalloonCoral' | 'ScoreBalloonInternalTote' // Held by scorer | 'ScoreBalloonExternalTote' // Held by alliance member | 'ScoreBalloonUncontrolledTote' diff --git a/src/routes/api/read/[matchkey]/[teamkey]/+server.ts b/src/routes/api/read/[matchkey]/[teamkey]/+server.ts new file mode 100644 index 0000000..a03d8cb --- /dev/null +++ b/src/routes/api/read/[matchkey]/[teamkey]/+server.ts @@ -0,0 +1,7 @@ +import { json } from '@sveltejs/kit'; +import type { RequestHandler } from './$types'; +import { select } from '$lib/server-assets/database'; + +export const GET: RequestHandler = async ({ params }: any) => { + return json(await select(params.matchkey, params.teamkey)); +}; diff --git a/src/routes/api/submit/+server.ts b/src/routes/api/submit/+server.ts new file mode 100644 index 0000000..c59ab37 --- /dev/null +++ b/src/routes/api/submit/+server.ts @@ -0,0 +1,9 @@ +import type { TeamMatch } from '$lib/types'; +import { json } from '@sveltejs/kit'; +import type { RequestHandler } from './$types'; +import { insertTeamMatch } from '$lib/server-assets/database'; + +export const POST: RequestHandler = async ({ request }) => { + const match: TeamMatch = await request.json(); + return json(await insertTeamMatch(match)); +}; diff --git a/src/routes/scout/[team_data]/+page.svelte b/src/routes/scout/[team_data]/+page.svelte index 2c3f99b..d624f31 100644 --- a/src/routes/scout/[team_data]/+page.svelte +++ b/src/routes/scout/[team_data]/+page.svelte @@ -23,7 +23,7 @@ // The furthest index in actions that was made during auto let furthest_auto_index = $state(0); - let speed = $state(3); + let quickness = $state(3); let awareness = $state(3); let broke = $state(false); let died = $state(false); @@ -46,7 +46,7 @@ } }); - function submit() { + async function submit() { const auto_actions = actions.slice(0, furthest_auto_index + 1); const tele_actions = actions.slice(furthest_auto_index + 1) as TeleActionData[]; // TODO: Add verification function to ensure that this always works const match: TeamMatch = { @@ -54,7 +54,7 @@ scout_id: username, team_key: data.team_key, match_key: data.match_key, - speed, + quickness, awareness, broke, died, @@ -63,6 +63,15 @@ tele_actions }; + const response = await fetch('/api/submit', { + method: 'POST', + body: JSON.stringify(match), + headers: { + 'Content-Type': 'application/json' + } + }); + + console.log(response); socket.emit('submit_team_match', match); goto('/'); } @@ -123,7 +132,7 @@ bind:displaying={timeline_extended} /> {:else} - + let { - speed = $bindable(), + quickness = $bindable(), awareness = $bindable(), broke = $bindable(), died = $bindable(), notes = $bindable() }: { - speed: number; + quickness: number; awareness: number; broke: boolean; died: boolean; @@ -14,22 +14,24 @@ } = $props(); -
-

Post Match

-
-

Driver Skill

-
-
- Quickness: {speed} - -
-
- Field awareness: {awareness} - +
+
+

Post Match

+
+
+
+

Robot

diff --git a/tailwind.config.mjs b/tailwind.config.mjs new file mode 100644 index 0000000..37606ac --- /dev/null +++ b/tailwind.config.mjs @@ -0,0 +1,26 @@ +const defaultTheme = require('tailwindcss/defaultTheme'); + +/** @type {import('tailwindcss').Config} */ +export default { + content: ['./src/**/*.{html,js,svelte,ts}'], + theme: { + extend: { + fontFamily: { + sans: ['Poppins', ...defaultTheme.fontFamily.sans], + heading: ['Teko', ...defaultTheme.fontFamily.sans] + }, + colors: { + white: '#ffffff', + eerie_black: '#1C1C1C', + yolk_yellow: '#FFC145', + flaming_red: '#ED2C2C', + steel_blue: '#358188', + gunmetal: '#20282C', + chicken_orange: '#F7901E', + eminence: '#6C3082', + jungle_green: '#49A078' + } + } + }, + plugins: [] +};