Get ui logic into working state
This commit is contained in:
+45
-39
@@ -4751,7 +4751,7 @@
|
|||||||
{
|
{
|
||||||
"metrics": {
|
"metrics": {
|
||||||
"age": 10,
|
"age": 10,
|
||||||
"weight": -1,
|
"weight": 0,
|
||||||
"gender": "Male"
|
"gender": "Male"
|
||||||
},
|
},
|
||||||
"levels": {
|
"levels": {
|
||||||
@@ -4765,7 +4765,7 @@
|
|||||||
{
|
{
|
||||||
"metrics": {
|
"metrics": {
|
||||||
"age": 15,
|
"age": 15,
|
||||||
"weight": -1,
|
"weight": 0,
|
||||||
"gender": "Male"
|
"gender": "Male"
|
||||||
},
|
},
|
||||||
"levels": {
|
"levels": {
|
||||||
@@ -4779,7 +4779,7 @@
|
|||||||
{
|
{
|
||||||
"metrics": {
|
"metrics": {
|
||||||
"age": 20,
|
"age": 20,
|
||||||
"weight": -1,
|
"weight": 0,
|
||||||
"gender": "Male"
|
"gender": "Male"
|
||||||
},
|
},
|
||||||
"levels": {
|
"levels": {
|
||||||
@@ -4793,7 +4793,7 @@
|
|||||||
{
|
{
|
||||||
"metrics": {
|
"metrics": {
|
||||||
"age": 25,
|
"age": 25,
|
||||||
"weight": -1,
|
"weight": 0,
|
||||||
"gender": "Male"
|
"gender": "Male"
|
||||||
},
|
},
|
||||||
"levels": {
|
"levels": {
|
||||||
@@ -4807,7 +4807,7 @@
|
|||||||
{
|
{
|
||||||
"metrics": {
|
"metrics": {
|
||||||
"age": 30,
|
"age": 30,
|
||||||
"weight": -1,
|
"weight": 0,
|
||||||
"gender": "Male"
|
"gender": "Male"
|
||||||
},
|
},
|
||||||
"levels": {
|
"levels": {
|
||||||
@@ -4821,7 +4821,7 @@
|
|||||||
{
|
{
|
||||||
"metrics": {
|
"metrics": {
|
||||||
"age": 35,
|
"age": 35,
|
||||||
"weight": -1,
|
"weight": 0,
|
||||||
"gender": "Male"
|
"gender": "Male"
|
||||||
},
|
},
|
||||||
"levels": {
|
"levels": {
|
||||||
@@ -4835,7 +4835,7 @@
|
|||||||
{
|
{
|
||||||
"metrics": {
|
"metrics": {
|
||||||
"age": 40,
|
"age": 40,
|
||||||
"weight": -1,
|
"weight": 0,
|
||||||
"gender": "Male"
|
"gender": "Male"
|
||||||
},
|
},
|
||||||
"levels": {
|
"levels": {
|
||||||
@@ -4849,7 +4849,7 @@
|
|||||||
{
|
{
|
||||||
"metrics": {
|
"metrics": {
|
||||||
"age": 45,
|
"age": 45,
|
||||||
"weight": -1,
|
"weight": 0,
|
||||||
"gender": "Male"
|
"gender": "Male"
|
||||||
},
|
},
|
||||||
"levels": {
|
"levels": {
|
||||||
@@ -4863,7 +4863,7 @@
|
|||||||
{
|
{
|
||||||
"metrics": {
|
"metrics": {
|
||||||
"age": 50,
|
"age": 50,
|
||||||
"weight": -1,
|
"weight": 0,
|
||||||
"gender": "Male"
|
"gender": "Male"
|
||||||
},
|
},
|
||||||
"levels": {
|
"levels": {
|
||||||
@@ -4877,7 +4877,7 @@
|
|||||||
{
|
{
|
||||||
"metrics": {
|
"metrics": {
|
||||||
"age": 55,
|
"age": 55,
|
||||||
"weight": -1,
|
"weight": 0,
|
||||||
"gender": "Male"
|
"gender": "Male"
|
||||||
},
|
},
|
||||||
"levels": {
|
"levels": {
|
||||||
@@ -4891,7 +4891,7 @@
|
|||||||
{
|
{
|
||||||
"metrics": {
|
"metrics": {
|
||||||
"age": 60,
|
"age": 60,
|
||||||
"weight": -1,
|
"weight": 0,
|
||||||
"gender": "Male"
|
"gender": "Male"
|
||||||
},
|
},
|
||||||
"levels": {
|
"levels": {
|
||||||
@@ -4905,7 +4905,7 @@
|
|||||||
{
|
{
|
||||||
"metrics": {
|
"metrics": {
|
||||||
"age": 65,
|
"age": 65,
|
||||||
"weight": -1,
|
"weight": 0,
|
||||||
"gender": "Male"
|
"gender": "Male"
|
||||||
},
|
},
|
||||||
"levels": {
|
"levels": {
|
||||||
@@ -4919,7 +4919,7 @@
|
|||||||
{
|
{
|
||||||
"metrics": {
|
"metrics": {
|
||||||
"age": 70,
|
"age": 70,
|
||||||
"weight": -1,
|
"weight": 0,
|
||||||
"gender": "Male"
|
"gender": "Male"
|
||||||
},
|
},
|
||||||
"levels": {
|
"levels": {
|
||||||
@@ -4933,7 +4933,7 @@
|
|||||||
{
|
{
|
||||||
"metrics": {
|
"metrics": {
|
||||||
"age": 75,
|
"age": 75,
|
||||||
"weight": -1,
|
"weight": 0,
|
||||||
"gender": "Male"
|
"gender": "Male"
|
||||||
},
|
},
|
||||||
"levels": {
|
"levels": {
|
||||||
@@ -4947,7 +4947,7 @@
|
|||||||
{
|
{
|
||||||
"metrics": {
|
"metrics": {
|
||||||
"age": 80,
|
"age": 80,
|
||||||
"weight": -1,
|
"weight": 0,
|
||||||
"gender": "Male"
|
"gender": "Male"
|
||||||
},
|
},
|
||||||
"levels": {
|
"levels": {
|
||||||
@@ -4961,7 +4961,7 @@
|
|||||||
{
|
{
|
||||||
"metrics": {
|
"metrics": {
|
||||||
"age": 85,
|
"age": 85,
|
||||||
"weight": -1,
|
"weight": 0,
|
||||||
"gender": "Male"
|
"gender": "Male"
|
||||||
},
|
},
|
||||||
"levels": {
|
"levels": {
|
||||||
@@ -4975,7 +4975,7 @@
|
|||||||
{
|
{
|
||||||
"metrics": {
|
"metrics": {
|
||||||
"age": 90,
|
"age": 90,
|
||||||
"weight": -1,
|
"weight": 0,
|
||||||
"gender": "Male"
|
"gender": "Male"
|
||||||
},
|
},
|
||||||
"levels": {
|
"levels": {
|
||||||
@@ -4989,7 +4989,7 @@
|
|||||||
{
|
{
|
||||||
"metrics": {
|
"metrics": {
|
||||||
"age": 10,
|
"age": 10,
|
||||||
"weight": -1,
|
"weight": 0,
|
||||||
"gender": "Female"
|
"gender": "Female"
|
||||||
},
|
},
|
||||||
"levels": {
|
"levels": {
|
||||||
@@ -5003,7 +5003,7 @@
|
|||||||
{
|
{
|
||||||
"metrics": {
|
"metrics": {
|
||||||
"age": 15,
|
"age": 15,
|
||||||
"weight": -1,
|
"weight": 0,
|
||||||
"gender": "Female"
|
"gender": "Female"
|
||||||
},
|
},
|
||||||
"levels": {
|
"levels": {
|
||||||
@@ -5017,7 +5017,7 @@
|
|||||||
{
|
{
|
||||||
"metrics": {
|
"metrics": {
|
||||||
"age": 20,
|
"age": 20,
|
||||||
"weight": -1,
|
"weight": 0,
|
||||||
"gender": "Female"
|
"gender": "Female"
|
||||||
},
|
},
|
||||||
"levels": {
|
"levels": {
|
||||||
@@ -5031,7 +5031,7 @@
|
|||||||
{
|
{
|
||||||
"metrics": {
|
"metrics": {
|
||||||
"age": 25,
|
"age": 25,
|
||||||
"weight": -1,
|
"weight": 0,
|
||||||
"gender": "Female"
|
"gender": "Female"
|
||||||
},
|
},
|
||||||
"levels": {
|
"levels": {
|
||||||
@@ -5045,7 +5045,7 @@
|
|||||||
{
|
{
|
||||||
"metrics": {
|
"metrics": {
|
||||||
"age": 30,
|
"age": 30,
|
||||||
"weight": -1,
|
"weight": 0,
|
||||||
"gender": "Female"
|
"gender": "Female"
|
||||||
},
|
},
|
||||||
"levels": {
|
"levels": {
|
||||||
@@ -5059,7 +5059,7 @@
|
|||||||
{
|
{
|
||||||
"metrics": {
|
"metrics": {
|
||||||
"age": 35,
|
"age": 35,
|
||||||
"weight": -1,
|
"weight": 0,
|
||||||
"gender": "Female"
|
"gender": "Female"
|
||||||
},
|
},
|
||||||
"levels": {
|
"levels": {
|
||||||
@@ -5073,7 +5073,7 @@
|
|||||||
{
|
{
|
||||||
"metrics": {
|
"metrics": {
|
||||||
"age": 40,
|
"age": 40,
|
||||||
"weight": -1,
|
"weight": 0,
|
||||||
"gender": "Female"
|
"gender": "Female"
|
||||||
},
|
},
|
||||||
"levels": {
|
"levels": {
|
||||||
@@ -5087,7 +5087,7 @@
|
|||||||
{
|
{
|
||||||
"metrics": {
|
"metrics": {
|
||||||
"age": 45,
|
"age": 45,
|
||||||
"weight": -1,
|
"weight": 0,
|
||||||
"gender": "Female"
|
"gender": "Female"
|
||||||
},
|
},
|
||||||
"levels": {
|
"levels": {
|
||||||
@@ -5101,7 +5101,7 @@
|
|||||||
{
|
{
|
||||||
"metrics": {
|
"metrics": {
|
||||||
"age": 50,
|
"age": 50,
|
||||||
"weight": -1,
|
"weight": 0,
|
||||||
"gender": "Female"
|
"gender": "Female"
|
||||||
},
|
},
|
||||||
"levels": {
|
"levels": {
|
||||||
@@ -5115,7 +5115,7 @@
|
|||||||
{
|
{
|
||||||
"metrics": {
|
"metrics": {
|
||||||
"age": 55,
|
"age": 55,
|
||||||
"weight": -1,
|
"weight": 0,
|
||||||
"gender": "Female"
|
"gender": "Female"
|
||||||
},
|
},
|
||||||
"levels": {
|
"levels": {
|
||||||
@@ -5129,7 +5129,7 @@
|
|||||||
{
|
{
|
||||||
"metrics": {
|
"metrics": {
|
||||||
"age": 60,
|
"age": 60,
|
||||||
"weight": -1,
|
"weight": 0,
|
||||||
"gender": "Female"
|
"gender": "Female"
|
||||||
},
|
},
|
||||||
"levels": {
|
"levels": {
|
||||||
@@ -5143,7 +5143,7 @@
|
|||||||
{
|
{
|
||||||
"metrics": {
|
"metrics": {
|
||||||
"age": 65,
|
"age": 65,
|
||||||
"weight": -1,
|
"weight": 0,
|
||||||
"gender": "Female"
|
"gender": "Female"
|
||||||
},
|
},
|
||||||
"levels": {
|
"levels": {
|
||||||
@@ -5157,7 +5157,7 @@
|
|||||||
{
|
{
|
||||||
"metrics": {
|
"metrics": {
|
||||||
"age": 70,
|
"age": 70,
|
||||||
"weight": -1,
|
"weight": 0,
|
||||||
"gender": "Female"
|
"gender": "Female"
|
||||||
},
|
},
|
||||||
"levels": {
|
"levels": {
|
||||||
@@ -5171,7 +5171,7 @@
|
|||||||
{
|
{
|
||||||
"metrics": {
|
"metrics": {
|
||||||
"age": 75,
|
"age": 75,
|
||||||
"weight": -1,
|
"weight": 0,
|
||||||
"gender": "Female"
|
"gender": "Female"
|
||||||
},
|
},
|
||||||
"levels": {
|
"levels": {
|
||||||
@@ -5185,7 +5185,7 @@
|
|||||||
{
|
{
|
||||||
"metrics": {
|
"metrics": {
|
||||||
"age": 80,
|
"age": 80,
|
||||||
"weight": -1,
|
"weight": 0,
|
||||||
"gender": "Female"
|
"gender": "Female"
|
||||||
},
|
},
|
||||||
"levels": {
|
"levels": {
|
||||||
@@ -5199,7 +5199,7 @@
|
|||||||
{
|
{
|
||||||
"metrics": {
|
"metrics": {
|
||||||
"age": 85,
|
"age": 85,
|
||||||
"weight": -1,
|
"weight": 0,
|
||||||
"gender": "Female"
|
"gender": "Female"
|
||||||
},
|
},
|
||||||
"levels": {
|
"levels": {
|
||||||
@@ -5213,7 +5213,7 @@
|
|||||||
{
|
{
|
||||||
"metrics": {
|
"metrics": {
|
||||||
"age": 90,
|
"age": 90,
|
||||||
"weight": -1,
|
"weight": 0,
|
||||||
"gender": "Female"
|
"gender": "Female"
|
||||||
},
|
},
|
||||||
"levels": {
|
"levels": {
|
||||||
@@ -5230,6 +5230,12 @@
|
|||||||
"metadata": {
|
"metadata": {
|
||||||
"attribute": "Power",
|
"attribute": "Power",
|
||||||
"generators": [
|
"generators": [
|
||||||
|
{
|
||||||
|
"metric": "age",
|
||||||
|
"spread": 4,
|
||||||
|
"step": 10,
|
||||||
|
"ratio": "inverse"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"metric": "weight",
|
"metric": "weight",
|
||||||
"spread": 3,
|
"spread": 3,
|
||||||
@@ -5243,8 +5249,8 @@
|
|||||||
"standards": [
|
"standards": [
|
||||||
{
|
{
|
||||||
"metrics": {
|
"metrics": {
|
||||||
"age": 18,
|
"age": 20,
|
||||||
"weight": -1,
|
"weight": 0,
|
||||||
"gender": "Male"
|
"gender": "Male"
|
||||||
},
|
},
|
||||||
"levels": {
|
"levels": {
|
||||||
@@ -5258,7 +5264,7 @@
|
|||||||
{
|
{
|
||||||
"metrics": {
|
"metrics": {
|
||||||
"age": 18,
|
"age": 18,
|
||||||
"weight": -1,
|
"weight": 0,
|
||||||
"gender": "Female"
|
"gender": "Female"
|
||||||
},
|
},
|
||||||
"levels": {
|
"levels": {
|
||||||
@@ -5289,7 +5295,7 @@
|
|||||||
{
|
{
|
||||||
"metrics": {
|
"metrics": {
|
||||||
"age": 18,
|
"age": 18,
|
||||||
"weight": -1,
|
"weight": 0,
|
||||||
"gender": "Male"
|
"gender": "Male"
|
||||||
},
|
},
|
||||||
"levels": {
|
"levels": {
|
||||||
@@ -5303,7 +5309,7 @@
|
|||||||
{
|
{
|
||||||
"metrics": {
|
"metrics": {
|
||||||
"age": 18,
|
"age": 18,
|
||||||
"weight": -1,
|
"weight": 0,
|
||||||
"gender": "Female"
|
"gender": "Female"
|
||||||
},
|
},
|
||||||
"levels": {
|
"levels": {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { Activity, Attribute, Gender, getAvgWeight, lbToKg, type ActivityPerformance, type Player, type StandardUnit } from "./util";
|
import { Activity, Attribute, Gender, getAvgWeight, kgToLb, lbToKg, type ActivityPerformance, type Player, type StandardUnit } from "./util";
|
||||||
|
|
||||||
// SOURCES
|
// SOURCES
|
||||||
// Squat, Bench, Dead Lift:
|
// Squat, Bench, Dead Lift:
|
||||||
@@ -182,7 +182,7 @@ export class LevelCalculator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type StandardsConfig = {
|
export type StandardsConfig = {
|
||||||
maxLevel: number
|
maxLevel: number
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -210,7 +210,55 @@ export class Standards {
|
|||||||
|
|
||||||
const ageGenerators = allGenerators.filter(g => g.metric === "age");
|
const ageGenerators = allGenerators.filter(g => g.metric === "age");
|
||||||
for (const ageGenerator of ageGenerators) {
|
for (const ageGenerator of ageGenerators) {
|
||||||
// TODO
|
for (const gender of Object.values(Gender)) {
|
||||||
|
const referenceAge = 50;
|
||||||
|
|
||||||
|
const skewRatio = 0; // 0 = normal, 1 = max skew
|
||||||
|
const minAge = referenceAge - (ageGenerator.step * ageGenerator.spread * (1 - skewRatio));
|
||||||
|
const maxAge = referenceAge + (ageGenerator.step * ageGenerator.spread * (1 + skewRatio));
|
||||||
|
|
||||||
|
const referenceStandard = this
|
||||||
|
.byActivity(activity)
|
||||||
|
.byMetrics({ weight: getAvgWeight(gender, referenceAge), gender, age: referenceAge })
|
||||||
|
.getOneInterpolated();
|
||||||
|
|
||||||
|
let currAge = minAge;
|
||||||
|
while (currAge <= maxAge) {
|
||||||
|
const newStandard: Standard = {
|
||||||
|
metrics: {
|
||||||
|
weight: getAvgWeight(gender, currAge),
|
||||||
|
age: currAge,
|
||||||
|
gender
|
||||||
|
},
|
||||||
|
levels: {}
|
||||||
|
};
|
||||||
|
|
||||||
|
// apply allometric scaling to generate levels
|
||||||
|
for (const lvl in referenceStandard.levels) {
|
||||||
|
if (!referenceStandard.levels[lvl]) continue;
|
||||||
|
|
||||||
|
const scalingExponent = .1;
|
||||||
|
const coefficient = ageGenerator.ratio === "inverse" ?
|
||||||
|
referenceAge / currAge :
|
||||||
|
currAge / referenceAge;
|
||||||
|
newStandard.levels[lvl] = referenceStandard.levels[lvl] * (coefficient ** scalingExponent);
|
||||||
|
}
|
||||||
|
|
||||||
|
// prefer real data over generated data
|
||||||
|
const overlappingStandard = this
|
||||||
|
.byActivity(activity)
|
||||||
|
.byMetrics(newStandard.metrics)
|
||||||
|
.getOne();
|
||||||
|
if (!overlappingStandard)
|
||||||
|
this.activityStandards[activity].standards.push(newStandard);
|
||||||
|
|
||||||
|
currAge += ageGenerator.step;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// now that we generated metric data, remove the old data
|
||||||
|
this.activityStandards[activity].standards = this.activityStandards[activity].standards
|
||||||
|
.filter(s => s.metrics.weight)
|
||||||
}
|
}
|
||||||
|
|
||||||
const weightGenerators = allGenerators.filter(g => g.metric === "weight");
|
const weightGenerators = allGenerators.filter(g => g.metric === "weight");
|
||||||
@@ -247,6 +295,7 @@ export class Standards {
|
|||||||
const coefficient = weightGenerator.ratio === "inverse" ?
|
const coefficient = weightGenerator.ratio === "inverse" ?
|
||||||
referenceWeight / currWeight :
|
referenceWeight / currWeight :
|
||||||
currWeight / referenceWeight;
|
currWeight / referenceWeight;
|
||||||
|
|
||||||
newStandard.levels[lvl] = referenceStandard.levels[lvl] * (coefficient ** scalingExponent);
|
newStandard.levels[lvl] = referenceStandard.levels[lvl] * (coefficient ** scalingExponent);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -265,9 +314,19 @@ export class Standards {
|
|||||||
|
|
||||||
// now that we generated metric data, remove the old data
|
// now that we generated metric data, remove the old data
|
||||||
this.activityStandards[activity].standards = this.activityStandards[activity].standards
|
this.activityStandards[activity].standards = this.activityStandards[activity].standards
|
||||||
.filter(s => s.metrics.weight !== -1);
|
.filter(s => s.metrics.weight);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.activityStandards[activity].standards = this.activityStandards[activity].standards
|
||||||
|
.sort((a, b) => {
|
||||||
|
const genderOrder: Record<Gender, number> = { Male: 0, Female: 1 };
|
||||||
|
const gA = genderOrder[b.metrics.gender] ?? 99;
|
||||||
|
const gB = genderOrder[b.metrics.gender] ?? 99;
|
||||||
|
if (gA !== gB) return gA - gB;
|
||||||
|
if (a.metrics.age !== b.metrics.age)
|
||||||
|
return a.metrics.age - b.metrics.age;
|
||||||
|
return a.metrics.weight - b.metrics.weight;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -324,6 +383,7 @@ export class Standards {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const interpolateByAgeAndWeight = (metrics: Metrics): Standard => {
|
const interpolateByAgeAndWeight = (metrics: Metrics): Standard => {
|
||||||
|
console.log(metrics);
|
||||||
const interpolateByWeight = (targetAge: number): Levels => {
|
const interpolateByWeight = (targetAge: number): Levels => {
|
||||||
const { lower: lowerAgeWeightStandard, upper: upperAgeWeightStandard } = this
|
const { lower: lowerAgeWeightStandard, upper: upperAgeWeightStandard } = this
|
||||||
.byActivity(activity)
|
.byActivity(activity)
|
||||||
@@ -367,10 +427,15 @@ export class Standards {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const getAllInterpolated = (): Standard[] => {
|
const getAllInterpolated = (opt?: { normalizeForLb?: boolean }): Standard[] => {
|
||||||
const metrics: Metrics = state as Metrics;
|
const metrics: Metrics = state as Metrics;
|
||||||
|
|
||||||
const interpolatedStandards: Standard[] = this.weightsFor(activity, metrics)
|
let weights = this.weightsFor(activity, metrics.gender, metrics.age);
|
||||||
|
if (opt?.normalizeForLb) {
|
||||||
|
weights = weights.map(w => lbToKg(Math.round(kgToLb(w))));
|
||||||
|
}
|
||||||
|
|
||||||
|
const interpolatedStandards: Standard[] = weights
|
||||||
.map(weight => interpolateByAgeAndWeight({ ...metrics, weight }));
|
.map(weight => interpolateByAgeAndWeight({ ...metrics, weight }));
|
||||||
|
|
||||||
return interpolatedStandards;
|
return interpolatedStandards;
|
||||||
@@ -420,17 +485,26 @@ export class Standards {
|
|||||||
return activities;
|
return activities;
|
||||||
}
|
}
|
||||||
|
|
||||||
public weightsFor(activity: Activity, metrics: Metrics) {
|
// TODO: turn these into queries?
|
||||||
const { lower } = this
|
public weightsFor(activity: Activity, gender: Gender, age: number) {
|
||||||
|
const { lower, upper } = this
|
||||||
.byActivity(activity)
|
.byActivity(activity)
|
||||||
.byGender(metrics.gender)
|
.byGender(gender)
|
||||||
.getNearest("age", metrics.age);
|
.getNearest("age", age);
|
||||||
|
|
||||||
|
const lowerDiff = Math.abs(lower.metrics.age - age);
|
||||||
|
const upperDiff = Math.abs(upper.metrics.age - age);
|
||||||
|
const closestAge = lowerDiff < upperDiff ?
|
||||||
|
lower.metrics.age :
|
||||||
|
upper.metrics.age;
|
||||||
|
|
||||||
const weights = this
|
const weights = this
|
||||||
.byActivity(activity)
|
.byActivity(activity)
|
||||||
.byGender(metrics.gender)
|
.byGender(gender)
|
||||||
.byAge(lower.metrics.age)
|
.byAge(closestAge)
|
||||||
.getAll().map((s) => s.metrics.weight);
|
.getAll().map((s) => s.metrics.weight);
|
||||||
|
|
||||||
|
console.log({ age, closestAge, weights });
|
||||||
return weights;
|
return weights;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
import { Activity, feetToCm, Gender, getAvgWeight, inchesToCm, kgToLb, lbToKg, minToMs, secToMs, type ActivityPerformance, type Player } from "$lib/services/calculator/util";
|
import { Standards, type ActivityStandards } from "$lib/services/calculator/main";
|
||||||
|
import { Activity, ftToCm, Gender, getAvgWeight, inToCm, kgToLb, lbToKg, minToMs, secToMs, type ActivityPerformance, type Player } from "$lib/services/calculator/util";
|
||||||
|
import allStandardsRaw from "$lib/data/standards.json" assert { type: "json" };
|
||||||
|
|
||||||
const player: Player = {
|
const player: Player = {
|
||||||
metrics: {
|
metrics: {
|
||||||
@@ -25,7 +27,7 @@ const computedPerformances: ActivityPerformance[] = [
|
|||||||
// POWER
|
// POWER
|
||||||
{
|
{
|
||||||
activity: Activity.BroadJump,
|
activity: Activity.BroadJump,
|
||||||
performance: feetToCm(105) + inchesToCm(5),
|
performance: ftToCm(105) + inToCm(5),
|
||||||
},
|
},
|
||||||
// ENDURANCE
|
// ENDURANCE
|
||||||
{
|
{
|
||||||
@@ -39,10 +41,7 @@ const computedPerformances: ActivityPerformance[] = [
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
for (let age = 15; age < 80; ++age) {
|
const standards = new Standards(allStandardsRaw as ActivityStandards, { maxLevel: 10 });
|
||||||
const avgWeightKG = getAvgWeight(Gender.Female, age);
|
|
||||||
console.log(`${age}: ${kgToLb(avgWeightKG).toFixed(1)}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
// const newStandards: Standards = {
|
// const newStandards: Standards = {
|
||||||
// "Back Squat": [],
|
// "Back Squat": [],
|
||||||
|
|||||||
+73
-67
@@ -2,7 +2,9 @@
|
|||||||
import {
|
import {
|
||||||
Standards,
|
Standards,
|
||||||
type ActivityStandards,
|
type ActivityStandards,
|
||||||
|
type Metrics,
|
||||||
type Standard,
|
type Standard,
|
||||||
|
type StandardsConfig,
|
||||||
} from "$lib/services/calculator/main";
|
} from "$lib/services/calculator/main";
|
||||||
import allStandardsRaw from "$lib/data/standards.json" assert { type: "json" };
|
import allStandardsRaw from "$lib/data/standards.json" assert { type: "json" };
|
||||||
import {
|
import {
|
||||||
@@ -15,21 +17,39 @@
|
|||||||
range,
|
range,
|
||||||
} from "$lib/services/calculator/util";
|
} from "$lib/services/calculator/util";
|
||||||
|
|
||||||
const selected = $state({
|
const input = $state({
|
||||||
activity: Activity.BenchPress,
|
activity: Activity.BenchPress,
|
||||||
|
metrics: {
|
||||||
gender: Gender.Male,
|
gender: Gender.Male,
|
||||||
age: 18,
|
age: "",
|
||||||
weight: 0,
|
weight: "",
|
||||||
maxLevel: 5,
|
},
|
||||||
|
cfg: {
|
||||||
|
maxLevel: "5",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const selected = $derived({
|
||||||
|
activity: input.activity,
|
||||||
|
metrics: {
|
||||||
|
gender: input.metrics.gender,
|
||||||
|
age: +input.metrics.age,
|
||||||
|
weight: lbToKg(+input.metrics.weight),
|
||||||
|
} as Metrics,
|
||||||
|
cfg: {
|
||||||
|
maxLevel: +input.cfg.maxLevel,
|
||||||
|
} as StandardsConfig,
|
||||||
|
});
|
||||||
|
|
||||||
|
$effect(() => {
|
||||||
|
if (!input.metrics.age) input.metrics.weight = "";
|
||||||
});
|
});
|
||||||
|
|
||||||
const allStandards = $derived(
|
const allStandards = $derived(
|
||||||
new Standards(allStandardsRaw as ActivityStandards, {
|
new Standards(allStandardsRaw as ActivityStandards, selected.cfg),
|
||||||
maxLevel: selected.maxLevel,
|
|
||||||
}),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
const getFormattedLevelValue = (
|
const getLvlValue = (
|
||||||
activity: Activity,
|
activity: Activity,
|
||||||
standard: Standard,
|
standard: Standard,
|
||||||
lvl: number,
|
lvl: number,
|
||||||
@@ -55,13 +75,12 @@
|
|||||||
<div class="toolbar">
|
<div class="toolbar">
|
||||||
<fieldset class="group">
|
<fieldset class="group">
|
||||||
<legend>Metrics</legend>
|
<legend>Metrics</legend>
|
||||||
|
|
||||||
<label class="field">
|
<label class="field">
|
||||||
<span>Activity</span>
|
<span>Activity</span>
|
||||||
<select
|
<select
|
||||||
class="select"
|
class="select"
|
||||||
name="activities"
|
name="activities"
|
||||||
bind:value={selected.activity}
|
bind:value={input.activity}
|
||||||
>
|
>
|
||||||
{#each Object.values(Activity) as activity}
|
{#each Object.values(Activity) as activity}
|
||||||
<option value={activity}
|
<option value={activity}
|
||||||
@@ -78,7 +97,7 @@
|
|||||||
<select
|
<select
|
||||||
class="select"
|
class="select"
|
||||||
name="genders"
|
name="genders"
|
||||||
bind:value={selected.gender}
|
bind:value={input.metrics.gender}
|
||||||
>
|
>
|
||||||
{#each Object.values(Gender) as gender}
|
{#each Object.values(Gender) as gender}
|
||||||
<option value={gender}>{gender}</option>
|
<option value={gender}>{gender}</option>
|
||||||
@@ -93,19 +112,23 @@
|
|||||||
min="0"
|
min="0"
|
||||||
max="100"
|
max="100"
|
||||||
placeholder="18"
|
placeholder="18"
|
||||||
bind:value={selected.age}
|
bind:value={input.metrics.age}
|
||||||
/>
|
/>
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<label class="field w-24">
|
<label class="field w-24">
|
||||||
<span>Weight (lb)</span>
|
<span>Weight (lb)</span>
|
||||||
|
{#if selected.metrics.age}
|
||||||
<input
|
<input
|
||||||
type="number"
|
type="number"
|
||||||
min="0"
|
min="0"
|
||||||
max="600"
|
max="600"
|
||||||
placeholder="170"
|
placeholder="170"
|
||||||
bind:value={selected.weight}
|
bind:value={input.metrics.weight}
|
||||||
/>
|
/>
|
||||||
|
{:else}
|
||||||
|
<p style="margin: 0;">Requires age</p>
|
||||||
|
{/if}
|
||||||
</label>
|
</label>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
|
|
||||||
@@ -119,86 +142,70 @@
|
|||||||
min="1"
|
min="1"
|
||||||
max="100"
|
max="100"
|
||||||
placeholder="5"
|
placeholder="5"
|
||||||
bind:value={selected.maxLevel}
|
bind:value={input.cfg.maxLevel}
|
||||||
/>
|
/>
|
||||||
</label>
|
</label>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{#if !selected.gender || !selected.age}
|
<h1>{allStandards.byActivity(selected.activity).getMetadata().name}</h1>
|
||||||
<p>Not enough info entered</p>
|
<section class="gender-section">
|
||||||
|
<h2>{selected.metrics.gender}</h2>
|
||||||
|
{#if !selected.metrics.age}
|
||||||
|
{#each allStandards.agesFor(selected.activity, selected.metrics.gender) as age}
|
||||||
|
{@render standardsTable(selected.activity, {
|
||||||
|
...selected.metrics,
|
||||||
|
age,
|
||||||
|
})}
|
||||||
|
{/each}
|
||||||
{:else}
|
{:else}
|
||||||
{@render standardsTable(
|
{@render standardsTable(selected.activity, selected.metrics)}
|
||||||
selected.gender,
|
|
||||||
selected.age,
|
|
||||||
selected.weight,
|
|
||||||
)}
|
|
||||||
{/if}
|
{/if}
|
||||||
|
</section>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{#snippet standardsTable(gender: Gender, age: number, weight: number)}
|
{#snippet standardsTable(activity: Activity, metrics: Metrics)}
|
||||||
<section class="gender-section">
|
{#snippet standardsTableRow(standard: Standard)}
|
||||||
|
<tr>
|
||||||
|
<th scope="row"
|
||||||
|
>{parseFloat(kgToLb(standard.metrics.weight).toFixed(2))}</th
|
||||||
|
>
|
||||||
|
{#each range(selected.cfg.maxLevel) as lvl}
|
||||||
|
<td>{getLvlValue(activity, standard, lvl)}</td>
|
||||||
|
{/each}
|
||||||
|
</tr>
|
||||||
|
{/snippet}
|
||||||
<div class="age-section">
|
<div class="age-section">
|
||||||
|
<h3>{metrics.age}</h3>
|
||||||
<div class="standards-table">
|
<div class="standards-table">
|
||||||
<div class="scroll">
|
<div class="scroll">
|
||||||
<table>
|
<table>
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th class="levels-th">Body weight</th>
|
<th class="levels-th">Body weight</th>
|
||||||
{#each range(selected.maxLevel) as lvl}
|
{#each range(selected.cfg.maxLevel) as lvl}
|
||||||
<th class="levels-th">{lvl}</th>
|
<th class="levels-th">{lvl}</th>
|
||||||
{/each}
|
{/each}
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{#if weight}
|
{#if metrics.weight}
|
||||||
{@const standard = allStandards
|
{@const standard = allStandards
|
||||||
.byActivity(selected.activity)
|
.byActivity(activity)
|
||||||
.byGender(gender)
|
.byGender(metrics.gender)
|
||||||
.byAge(age)
|
.byAge(metrics.age)
|
||||||
.byWeight(lbToKg(weight))
|
.byWeight(metrics.weight)
|
||||||
.getOneInterpolated()}
|
.getOneInterpolated()}
|
||||||
|
{@render standardsTableRow(standard)}
|
||||||
<tr>
|
|
||||||
<th scope="row"
|
|
||||||
>{Math.round(
|
|
||||||
kgToLb(standard.metrics.weight),
|
|
||||||
)}</th
|
|
||||||
>
|
|
||||||
{#each range(selected.maxLevel) as lvl}
|
|
||||||
<td
|
|
||||||
>{getFormattedLevelValue(
|
|
||||||
selected.activity,
|
|
||||||
standard,
|
|
||||||
lvl,
|
|
||||||
)}</td
|
|
||||||
>
|
|
||||||
{/each}
|
|
||||||
</tr>
|
|
||||||
{:else}
|
{:else}
|
||||||
{@const standards = allStandards
|
{@const standards = allStandards
|
||||||
.byActivity(selected.activity)
|
.byActivity(activity)
|
||||||
.byGender(gender)
|
.byGender(metrics.gender)
|
||||||
.byAge(age)
|
.byAge(metrics.age)
|
||||||
.getAllInterpolated()}
|
.getAllInterpolated({ normalizeForLb: true })}
|
||||||
{#each standards as standard}
|
{#each standards as standard}
|
||||||
<tr>
|
{@render standardsTableRow(standard)}
|
||||||
<th scope="row"
|
|
||||||
>{Math.round(
|
|
||||||
kgToLb(standard.metrics.weight),
|
|
||||||
)}</th
|
|
||||||
>
|
|
||||||
{#each range(allStandards.cfg.maxLevel) as lvl}
|
|
||||||
<td
|
|
||||||
>{getFormattedLevelValue(
|
|
||||||
selected.activity,
|
|
||||||
standard,
|
|
||||||
lvl,
|
|
||||||
)}</td
|
|
||||||
>
|
|
||||||
{/each}
|
|
||||||
</tr>
|
|
||||||
{/each}
|
{/each}
|
||||||
{/if}
|
{/if}
|
||||||
</tbody>
|
</tbody>
|
||||||
@@ -206,7 +213,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
|
||||||
{/snippet}
|
{/snippet}
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
|||||||
Reference in New Issue
Block a user