This commit is contained in:
Dominic Ferrando
2025-09-15 15:30:41 -04:00
parent 5b7d15be9a
commit 17cbdbbe5e
3 changed files with 36 additions and 23 deletions
+33 -12
View File
@@ -15,6 +15,11 @@ type LevelCalculatorConfig = {
expandIters?: number; expandIters?: number;
} }
type LevelCalculatorOutput = {
player: number,
attributes: Record<Attribute, number>
}
export class LevelCalculator { export class LevelCalculator {
cfg: Required<LevelCalculatorConfig>; cfg: Required<LevelCalculatorConfig>;
standards: Standards; standards: Standards;
@@ -28,26 +33,38 @@ export class LevelCalculator {
} }
// ------------------------------------------------------------------------------------------------- // -------------------------------------------------------------------------------------------------
// Level calculations (public API) // Level calculations
// ------------------------------------------------------------------------------------------------- // -------------------------------------------------------------------------------------------------
public calculatePlayerLevel(player: Player, activityPerformances: ActivityPerformance[]): number { public calculate(player: Player, activityPerformances: ActivityPerformance[]): LevelCalculatorOutput {
const levels: LevelCalculatorOutput = {
player: 0,
attributes: {
[attributes.STRENGTH]: 0,
[attributes.POWER]: 0,
[attributes.ENDURANCE]: 0,
[attributes.AGILITY]: 0,
} as const
};
for (const value of Object.values(player)) { for (const value of Object.values(player)) {
if (!value) if (!value)
return 0; return levels;
} }
const attrLevels = this.calculateAllAttributeLevels(player, activityPerformances); levels.attributes = this.calculateAllAttributeLevels(player, activityPerformances);
for (const level of Object.values(attrLevels)) { for (const level of Object.values(levels.attributes)) {
if (!level) if (!level)
return 0; return levels;
} }
const attrLevelsSum = Object.values(attrLevels).reduce((sum, lvl) => sum + lvl, 0); const attrLevelsSum = Object.values(levels.attributes).reduce((sum, lvl) => sum + lvl, 0);
return Math.round(attrLevelsSum / Object.keys(attributes).length); levels.player = Math.round(attrLevelsSum / Object.keys(attributes).length);
return levels;
} }
public calculateAllAttributeLevels( private calculateAllAttributeLevels(
player: Player, player: Player,
activityPerformances: ActivityPerformance[], activityPerformances: ActivityPerformance[],
): Record<Attribute, number> { ): Record<Attribute, number> {
@@ -55,7 +72,6 @@ export class LevelCalculator {
[attributes.STRENGTH]: 0, [attributes.STRENGTH]: 0,
[attributes.POWER]: 0, [attributes.POWER]: 0,
[attributes.ENDURANCE]: 0, [attributes.ENDURANCE]: 0,
// [attributes.SPEED]: 0,
[attributes.AGILITY]: 0, [attributes.AGILITY]: 0,
} as const; } as const;
@@ -75,7 +91,7 @@ export class LevelCalculator {
} }
public calculateAttributeLevel( private calculateAttributeLevel(
attribute: Attribute, attribute: Attribute,
player: Player, player: Player,
activityPerformances: ActivityPerformance[], activityPerformances: ActivityPerformance[],
@@ -123,11 +139,12 @@ export class LevelCalculator {
const standard = this.standards.byActivity(activity).getOne(); const standard = this.standards.byActivity(activity).getOne();
if (standard.metrics.weight === -1) return standard.levels; if (standard.metrics.weight === -1) return standard.levels;
const { upper: upperAgeWeightStandard, lower: lowerAgeWeightStandard } = this.standards const { lower: lowerAgeWeightStandard, upper: upperAgeWeightStandard } = this.standards
.byActivity(activity) .byActivity(activity)
.byGender(metrics.gender) .byGender(metrics.gender)
.byAge(targetAge) .byAge(targetAge)
.getNearest("weight", metrics.weight); .getNearest("weight", metrics.weight);
const weightLower = lowerAgeWeightStandard.metrics.weight; const weightLower = lowerAgeWeightStandard.metrics.weight;
const weightUpper = upperAgeWeightStandard.metrics.weight; const weightUpper = upperAgeWeightStandard.metrics.weight;
@@ -146,9 +163,13 @@ export class LevelCalculator {
const ageLower = lowerAgeStandard.metrics.age; const ageLower = lowerAgeStandard.metrics.age;
const ageUpper = upperAgeStandard.metrics.age; const ageUpper = upperAgeStandard.metrics.age;
console.log(activity);
console.log("AGES: ", ageLower, ageUpper);
// Interpolate by age and weight // Interpolate by age and weight
let ageRatio = ageUpper === ageLower ? 1 : (metrics.age - ageLower) / (ageUpper - ageLower); let ageRatio = ageUpper === ageLower ? 1 : (metrics.age - ageLower) / (ageUpper - ageLower);
ageRatio = Math.max(0, Math.min(1, ageRatio)); ageRatio = Math.max(0, Math.min(1, ageRatio));
const interpolatedLevels = this.interpolateLevels( const interpolatedLevels = this.interpolateLevels(
interpolateByWeight(ageLower), interpolateByWeight(ageLower),
interpolateByWeight(ageUpper), interpolateByWeight(ageUpper),
+2 -7
View File
@@ -32,7 +32,7 @@ const computedPerformances: ActivityPerformance[] = [
// ENDURANCE // ENDURANCE
{ {
activity: activities.RUN, activity: activities.RUN,
performance: minToMs(5) + secToMs(20), performance: minToMs(6) + secToMs(11),
}, },
// AGILITY // AGILITY
{ {
@@ -44,12 +44,7 @@ const computedPerformances: ActivityPerformance[] = [
const standards = new Standards(rawStandards as StandardsMap); const standards = new Standards(rawStandards as StandardsMap);
const levelCalculator = new LevelCalculator(standards); const levelCalculator = new LevelCalculator(standards);
const levels = { console.log(levelCalculator.calculate(player, computedPerformances));
attributes: levelCalculator.calculateAllAttributeLevels(player, computedPerformances),
player: levelCalculator.calculatePlayerLevel(player, computedPerformances)
};
console.log(levels);
// const newStandards: Standards = { // const newStandards: Standards = {
// "Back Squat": [], // "Back Squat": [],
+1 -4
View File
@@ -42,10 +42,7 @@ const server = Bun.serve({
const levelCalculator = new LevelCalculator(MAIN_STANDARDS); const levelCalculator = new LevelCalculator(MAIN_STANDARDS);
return ClientResponse.json({ return ClientResponse.json({
levels: { levels: levelCalculator.calculate(player, activityPerformances)
attributes: levelCalculator.calculateAllAttributeLevels(player, activityPerformances),
player: levelCalculator.calculatePlayerLevel(player, activityPerformances)
}
}) })
} }
}, },