From 28c5b3df18996c4f397c5d1210b578962e260385 Mon Sep 17 00:00:00 2001 From: Dominic Ferrando Date: Sat, 4 Jul 2026 15:43:47 -0400 Subject: [PATCH] More models organization --- .../api/src/database/migrations/2026-06-03.ts | 2 +- apps/api/src/scripts/analyze.ts | 4 +- apps/api/src/server.ts | 12 +-- apps/api/src/services/calculator.ts | 26 ++--- .../src/lib/components/StandardsTable.svelte | 4 +- .../src/routes/(app)/calculator/+page.svelte | 30 +++--- packages/calculator/src/index.ts | 102 ++++-------------- packages/calculator/src/models.ts | 69 ++++++++++++ packages/domain/src/models.ts | 33 +++--- 9 files changed, 148 insertions(+), 134 deletions(-) create mode 100644 packages/calculator/src/models.ts diff --git a/apps/api/src/database/migrations/2026-06-03.ts b/apps/api/src/database/migrations/2026-06-03.ts index cfb76c4..9ed29f8 100644 --- a/apps/api/src/database/migrations/2026-06-03.ts +++ b/apps/api/src/database/migrations/2026-06-03.ts @@ -38,7 +38,7 @@ export async function up(db: Kysely): Promise { await db.schema.createTable("standards_configs") .$call(addDefaultColumns) .addColumn("name", "text", (cb) => cb.notNull().defaultTo("")) - .addColumn("parameters", "jsonb", (cb) => cb.notNull()) + .addColumn("params", "jsonb", (cb) => cb.notNull()) .addColumn("is_selected", "boolean", (cb) => cb.notNull().defaultTo(false)) .addColumn("dataset_id", "bigint", (cb) => cb.notNull()) .addForeignKeyConstraint( diff --git a/apps/api/src/scripts/analyze.ts b/apps/api/src/scripts/analyze.ts index ad108af..d244725 100644 --- a/apps/api/src/scripts/analyze.ts +++ b/apps/api/src/scripts/analyze.ts @@ -1,6 +1,6 @@ import { type Levels, - DEFAULT_STANDARDS_DATASET, + DEFAULT_STANDARDS_DATA, } from "@blade-and-brawn/calculator"; import { Activity, clamp, Gender, range } from "@blade-and-brawn/domain"; import { levenbergMarquardt as LM } from "ml-levenberg-marquardt"; @@ -15,7 +15,7 @@ for (const activity of Object.values(Activity)) { } for (const gender of Object.values(Gender)) { - const standardsByGender = DEFAULT_STANDARDS_DATASET[ + const standardsByGender = DEFAULT_STANDARDS_DATA[ activity ].standards.filter((s) => s["metrics"].gender === gender); const ages = [...new Set(standardsByGender.map((s) => s.metrics.age))]; diff --git a/apps/api/src/server.ts b/apps/api/src/server.ts index f398110..f5d98ec 100644 --- a/apps/api/src/server.ts +++ b/apps/api/src/server.ts @@ -18,7 +18,7 @@ import { CommerceService } from "./services/commerce"; import cluster from "node:cluster"; import { randomUUIDv7 } from "bun"; import { CalculatorService } from "./services/calculator"; -import { StandardsParametersSchema } from "@blade-and-brawn/calculator"; +import { StandardsParamsSchema } from "@blade-and-brawn/calculator"; // SERVICES // ----------- @@ -117,16 +117,16 @@ export const app = new Elysia() if (!token || !token.sessionId) throw status(401, "Unauthorized"); return { sessionId: token.sessionId.toString() }; }) - .put("/config/:id", async ({ params: { id }, body: { datasetId, parameters } }) => { + .put("/config/:id", async ({ params: { id }, body: { datasetId, params: parameters } }) => { await s.Calculator.Standards.Config.update(id, datasetId, parameters); }, { params: t.Object({ id: t.String() }), - body: t.Object({ datasetId: t.String(), parameters: StandardsParametersSchema }) + body: t.Object({ datasetId: t.String(), params: StandardsParamsSchema }) }) - .post("/config", async ({ body: { datasetId, parameters } }) => { - await s.Calculator.Standards.Config.create(datasetId, parameters); + .post("/config", async ({ body: { datasetId, params } }) => { + await s.Calculator.Standards.Config.create(datasetId, params); }, { - body: t.Object({ datasetId: t.String(), parameters: StandardsParametersSchema }) + body: t.Object({ datasetId: t.String(), params: StandardsParamsSchema }) }) .post("/config/:id/switch", async ({ params: { id } }) => { await s.Calculator.Standards.Config.switch(id); diff --git a/apps/api/src/services/calculator.ts b/apps/api/src/services/calculator.ts index 03756af..f86d733 100644 --- a/apps/api/src/services/calculator.ts +++ b/apps/api/src/services/calculator.ts @@ -1,11 +1,11 @@ -import { LevelCalculator, Standards, DEFAULT_STANDARDS_DATASET, type StandardsParameters, StandardsParametersSchema, StandardsDatasetSchema } from "@blade-and-brawn/calculator"; +import { LevelCalculator, Standards, DEFAULT_STANDARDS_DATA, type StandardsParams, StandardsParamsSchema, StandardsDataSchema } from "@blade-and-brawn/calculator"; import type { ActivityPerformance, Player } from "@blade-and-brawn/domain"; import { db } from "../database/db"; import { Value } from "@sinclair/typebox/value"; import { log } from "../util"; export class CalculatorService { - private Calculator = new LevelCalculator(new Standards(DEFAULT_STANDARDS_DATASET)); + private Calculator = new LevelCalculator(new Standards(DEFAULT_STANDARDS_DATA)); Standards: StandardsService = new StandardsService(this.Calculator); calculate(player: Player, activityPerformances: ActivityPerformance[]) { @@ -30,23 +30,23 @@ class StandardsConfigService { constructor(private Calculator: LevelCalculator) { } - async create(datasetId: string, parameters: StandardsParameters) { + async create(datasetId: string, params: StandardsParams) { await db.insertInto("standards_configs") - .values({ parameters, dataset_id: datasetId }) + .values({ params, dataset_id: datasetId }) .execute(); } /** Retrieves the currently selected configuration */ - async get(opt: { skipCache?: boolean } = {}): Promise { + async get(opt: { skipCache?: boolean } = {}): Promise { if (!opt.skipCache) return this.Calculator.Standards.params; await this.refresh(); return this.Calculator.Standards.params; } - async update(id: string, datasetId: string, parameters: StandardsParameters) { + async update(id: string, datasetId: string, params: StandardsParams) { const result = await db.updateTable("standards_configs") - .set({ parameters, dataset_id: datasetId }) + .set({ params, dataset_id: datasetId }) .where("id", "=", id) .execute(); if (result[0]?.numUpdatedRows === 0n) throw new Error(`No config with id "${id}"`); @@ -62,19 +62,19 @@ class StandardsConfigService { .innerJoin("standards_datasets", "standards_datasets.id", "standards_configs.dataset_id") .select([ "standards_configs.dataset_id as datasetId", - "standards_configs.parameters as parameters", - "standards_datasets.data as dataset", + "standards_configs.params as params", + "standards_datasets.data as data", ]) .where("standards_configs.is_selected", "=", true) .limit(1) .executeTakeFirstOrThrow({ errorConstructor: () => new Error("No standards config selected") }); - Value.Assert(StandardsParametersSchema, config.parameters); - Value.Assert(StandardsDatasetSchema, config.dataset); + Value.Assert(StandardsParamsSchema, config.params); + Value.Assert(StandardsDataSchema, config.data); - const parametersStringified = JSON.stringify(config.parameters); + const parametersStringified = JSON.stringify(config.params); if (parametersStringified === this.cachedParametersStringified && config.datasetId === this.cachedDatasetId) return; - this.Calculator.Standards = new Standards(config.dataset, config.parameters); + this.Calculator.Standards = new Standards(config.data, config.params); this.cachedParametersStringified = parametersStringified; this.cachedDatasetId = config.datasetId; } diff --git a/apps/portal/src/lib/components/StandardsTable.svelte b/apps/portal/src/lib/components/StandardsTable.svelte index cc3c3e6..18e9c3f 100644 --- a/apps/portal/src/lib/components/StandardsTable.svelte +++ b/apps/portal/src/lib/components/StandardsTable.svelte @@ -2,7 +2,7 @@ import { Standards, type Standard, - type StandardsParameters, + type StandardsParams, } from "@blade-and-brawn/calculator"; import { Activity, @@ -17,7 +17,7 @@ selected: { activity: Activity; metrics: Metrics; - params: StandardsParameters; + params: StandardsParams; }; } diff --git a/apps/portal/src/routes/(app)/calculator/+page.svelte b/apps/portal/src/routes/(app)/calculator/+page.svelte index 03921bf..6307f6d 100644 --- a/apps/portal/src/routes/(app)/calculator/+page.svelte +++ b/apps/portal/src/routes/(app)/calculator/+page.svelte @@ -1,8 +1,8 @@