Setup getConfig with typebox validations
This commit is contained in:
@@ -31,7 +31,6 @@
|
|||||||
"kysely": "^0.29.2",
|
"kysely": "^0.29.2",
|
||||||
"ml-levenberg-marquardt": "^5.0.1",
|
"ml-levenberg-marquardt": "^5.0.1",
|
||||||
"pg": "^8.22.0",
|
"pg": "^8.22.0",
|
||||||
"pino": "^10.3.1",
|
|
||||||
"zipcodes-us": "^1.1.3"
|
"zipcodes-us": "^1.1.3"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
import { LevelCalculator, Standards, DEFAULT_STANDARDS_DATA } from "@blade-and-brawn/calculator";
|
import { LevelCalculator, Standards, DEFAULT_STANDARDS_DATA, type StandardsConfig, StandardsConfigSchema } from "@blade-and-brawn/calculator";
|
||||||
import type { ActivityPerformance, Player } from "@blade-and-brawn/domain";
|
import type { ActivityPerformance, Player } from "@blade-and-brawn/domain";
|
||||||
|
import { db } from "../database/db";
|
||||||
|
import { Value } from "@sinclair/typebox/value";
|
||||||
|
|
||||||
export class CalculatorService {
|
export class CalculatorService {
|
||||||
private readonly levelCalculator;
|
private readonly levelCalculator;
|
||||||
@@ -13,4 +15,18 @@ export class CalculatorService {
|
|||||||
calculate(player: Player, activityPerformances: ActivityPerformance[]) {
|
calculate(player: Player, activityPerformances: ActivityPerformance[]) {
|
||||||
return this.levelCalculator.calculate(player, activityPerformances)
|
return this.levelCalculator.calculate(player, activityPerformances)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async getConfig(opt: { skipCache?: boolean } = {}): Promise<StandardsConfig> {
|
||||||
|
if (!opt.skipCache) return this.levelCalculator.standards.cfg;
|
||||||
|
|
||||||
|
const result = await db.selectFrom("calculator_configs")
|
||||||
|
.select(["parameters"])
|
||||||
|
.where("is_selected", "=", true)
|
||||||
|
.limit(1)
|
||||||
|
.executeTakeFirstOrThrow({ errorConstructor: () => new Error("No calculator config selected") });
|
||||||
|
|
||||||
|
const standardsConfig = result.parameters;
|
||||||
|
Value.Assert(StandardsConfigSchema, standardsConfig);
|
||||||
|
return standardsConfig;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,10 @@
|
|||||||
"workspaces": {
|
"workspaces": {
|
||||||
"": {
|
"": {
|
||||||
"name": "blade-and-brawn",
|
"name": "blade-and-brawn",
|
||||||
|
"dependencies": {
|
||||||
|
"@sinclair/typebox": "^0.34.48",
|
||||||
|
"pino": "^10.3.1",
|
||||||
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/bun": "^1.3.14",
|
"@types/bun": "^1.3.14",
|
||||||
"typescript": "^6.0.3",
|
"typescript": "^6.0.3",
|
||||||
@@ -23,7 +27,6 @@
|
|||||||
"kysely": "^0.29.2",
|
"kysely": "^0.29.2",
|
||||||
"ml-levenberg-marquardt": "^5.0.1",
|
"ml-levenberg-marquardt": "^5.0.1",
|
||||||
"pg": "^8.22.0",
|
"pg": "^8.22.0",
|
||||||
"pino": "^10.3.1",
|
|
||||||
"zipcodes-us": "^1.1.3",
|
"zipcodes-us": "^1.1.3",
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
@@ -60,22 +63,18 @@
|
|||||||
"version": "0.0.0",
|
"version": "0.0.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@blade-and-brawn/domain": "workspace:*",
|
"@blade-and-brawn/domain": "workspace:*",
|
||||||
"ml-levenberg-marquardt": "^5.0.0",
|
"ml-levenberg-marquardt": "^5.0.1",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"packages/commerce": {
|
"packages/commerce": {
|
||||||
"name": "@blade-and-brawn/commerce",
|
"name": "@blade-and-brawn/commerce",
|
||||||
"version": "0.0.0",
|
"version": "0.0.0",
|
||||||
"dependencies": {
|
|
||||||
"pino": "^10.3.1",
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
"packages/domain": {
|
"packages/domain": {
|
||||||
"name": "@blade-and-brawn/domain",
|
"name": "@blade-and-brawn/domain",
|
||||||
"version": "0.0.0",
|
"version": "0.0.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@blade-and-brawn/domain": "workspace:*",
|
"@blade-and-brawn/domain": "workspace:*",
|
||||||
"@sinclair/typebox": "^0.34.48",
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -14,5 +14,9 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/bun": "^1.3.14",
|
"@types/bun": "^1.3.14",
|
||||||
"typescript": "^6.0.3"
|
"typescript": "^6.0.3"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"pino": "^10.3.1",
|
||||||
|
"@sinclair/typebox": "^0.34.48"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
"version": "0.0.0",
|
"version": "0.0.0",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"ml-levenberg-marquardt": "^5.0.0",
|
"ml-levenberg-marquardt": "^5.0.1",
|
||||||
"@blade-and-brawn/domain": "workspace:*"
|
"@blade-and-brawn/domain": "workspace:*"
|
||||||
},
|
},
|
||||||
"exports": {
|
"exports": {
|
||||||
|
|||||||
@@ -11,6 +11,8 @@ import {
|
|||||||
type StandardUnit,
|
type StandardUnit,
|
||||||
} from "@blade-and-brawn/domain";
|
} from "@blade-and-brawn/domain";
|
||||||
import { levenbergMarquardt as LM } from "ml-levenberg-marquardt";
|
import { levenbergMarquardt as LM } from "ml-levenberg-marquardt";
|
||||||
|
import { Type, type Static } from "@sinclair/typebox";
|
||||||
|
import { Value } from "@sinclair/typebox/value";
|
||||||
import defaultConfig from "./config.json" with { type: "json" };
|
import defaultConfig from "./config.json" with { type: "json" };
|
||||||
import defaultStandardsJson from "./data/default-standards.json" with { type: "json" };
|
import defaultStandardsJson from "./data/default-standards.json" with { type: "json" };
|
||||||
import { getAvgWeight } from "./avg-weights";
|
import { getAvgWeight } from "./avg-weights";
|
||||||
@@ -211,26 +213,27 @@ export class LevelCalculator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export type StandardsConfig = {
|
const StandardsActivityConfigSchema = Type.Object({
|
||||||
global: {
|
weightModifier: Type.Number(),
|
||||||
maxLevel: number;
|
weightSkew: Type.Number(),
|
||||||
};
|
ageModifier: Type.Number(),
|
||||||
activity: Record<
|
enableGeneration: Type.Boolean(),
|
||||||
Activity,
|
difficultyModifier: Type.Number(),
|
||||||
{
|
peakAge: Type.Number(),
|
||||||
weightModifier: number;
|
stretch: Type.Object({
|
||||||
weightSkew: number;
|
upper: Type.Number(),
|
||||||
ageModifier: number;
|
lower: Type.Number(),
|
||||||
enableGeneration: boolean;
|
}),
|
||||||
difficultyModifier: number;
|
});
|
||||||
peakAge: number;
|
|
||||||
stretch: {
|
export const StandardsConfigSchema = Type.Object({
|
||||||
upper: number;
|
global: Type.Object({
|
||||||
lower: number;
|
maxLevel: Type.Number(),
|
||||||
};
|
}),
|
||||||
}
|
activity: Type.Record(Type.Enum(Activity), StandardsActivityConfigSchema),
|
||||||
>;
|
});
|
||||||
};
|
|
||||||
|
export type StandardsConfig = Static<typeof StandardsConfigSchema>;
|
||||||
|
|
||||||
export class Standards {
|
export class Standards {
|
||||||
readonly cfg: StandardsConfig;
|
readonly cfg: StandardsConfig;
|
||||||
|
|||||||
@@ -6,7 +6,5 @@
|
|||||||
"exports": {
|
"exports": {
|
||||||
".": "./src/index.ts"
|
".": "./src/index.ts"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {}
|
||||||
"pino": "^10.3.1"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,8 +4,7 @@
|
|||||||
"version": "0.0.0",
|
"version": "0.0.0",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@blade-and-brawn/domain": "workspace:*",
|
"@blade-and-brawn/domain": "workspace:*"
|
||||||
"@sinclair/typebox": "^0.34.48"
|
|
||||||
},
|
},
|
||||||
"exports": {
|
"exports": {
|
||||||
".": "./src/index.ts"
|
".": "./src/index.ts"
|
||||||
|
|||||||
Reference in New Issue
Block a user