From 8db5a09cab42b971c2c46483f5f68a362a6edbec Mon Sep 17 00:00:00 2001 From: Azalea Colburn <62953415+azaleacolburn@users.noreply.github.com> Date: Tue, 10 Dec 2024 21:17:18 -0800 Subject: [PATCH] Database + Crud Backend (#24) * feat: created DB file * feat: type model for scouting system * chore: update svelte * feat: tried * feat: nothing * feat: add none * feat: added DB.sql and migrations * refactor: type state model * feat: state transforms * add successfail screen * theme fixes * fix: package.json * fix: formating * fix: dependencies * format thingy * feat: implemented submit api * fix: removed unnecessary line * refactor: update types to match new schema * fix: id after clarifying with Brandon * update dep * style: format files * feat: pulled from main * style: format files * fix: dependencies * style: format files * fix: dependencies * fix: skill property name * fix: removed npm config * fix: bun dependencies * feat: finished submit function * feat: read route * feat: superscouting and pit scouting in db * fix: DB code * fix: updated queries to allow ids * fix: tailwind to CommonJS module * style: format files * fix: queries * style: format files * fix: types * style: format files * feat: hooked up frontend to backend * fix: queries * feat: functional queries * style: format files * fix: queries returning too much * more merge --------- Co-authored-by: Brandon Harad Co-authored-by: awwpotato Co-authored-by: awwpotato Co-authored-by: Brandon-Harad Co-authored-by: azaleacolburn --- .env.example | 6 + bun.lockb | Bin 158853 -> 167474 bytes migrations/DB.sql | 171 +++++++++++++ package.json | 39 +-- src/lib/server-assets/database.ts | 227 ++++++++++++++++++ src/lib/types.ts | 53 ++-- .../api/read/[matchkey]/[teamkey]/+server.ts | 7 + src/routes/api/submit/+server.ts | 9 + src/routes/scout/[team_data]/+page.svelte | 17 +- src/routes/scout/[team_data]/Postmatch.svelte | 36 +-- tailwind.config.mjs | 26 ++ 11 files changed, 532 insertions(+), 59 deletions(-) create mode 100644 .env.example create mode 100644 migrations/DB.sql create mode 100644 src/lib/server-assets/database.ts create mode 100644 src/routes/api/read/[matchkey]/[teamkey]/+server.ts create mode 100644 src/routes/api/submit/+server.ts create mode 100644 tailwind.config.mjs 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 79162bdbab35d79d9734512bc92dd94edf3a594f..ceef88073bca2b732e21e729f60c0326444a8916 100755 GIT binary patch delta 41588 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 S^dderf&#NqjIH3yV*U#^E^TuF delta 35524 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 h<%@I 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: [] +};