Fixes
This commit is contained in:
@@ -220,7 +220,10 @@ export type StandardsConfig = {
|
|||||||
enableGeneration: boolean;
|
enableGeneration: boolean;
|
||||||
difficultyModifier: number;
|
difficultyModifier: number;
|
||||||
peakAge: number;
|
peakAge: number;
|
||||||
stretch: number;
|
stretch: {
|
||||||
|
upper: number;
|
||||||
|
lower: number;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
>;
|
>;
|
||||||
};
|
};
|
||||||
@@ -246,7 +249,10 @@ export class Standards {
|
|||||||
difficultyModifier:
|
difficultyModifier:
|
||||||
activity === Activity.BroadJump ? 0.05 : 0,
|
activity === Activity.BroadJump ? 0.05 : 0,
|
||||||
peakAge: 27,
|
peakAge: 27,
|
||||||
stretch: 0,
|
stretch: {
|
||||||
|
upper: 0,
|
||||||
|
lower: 0,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
]),
|
]),
|
||||||
) as Record<Activity, StandardsConfig["activity"][Activity]>;
|
) as Record<Activity, StandardsConfig["activity"][Activity]>;
|
||||||
@@ -264,15 +270,15 @@ export class Standards {
|
|||||||
// STRETCH
|
// STRETCH
|
||||||
for (const activity of Object.values(Activity)) {
|
for (const activity of Object.values(Activity)) {
|
||||||
const BASE_MAX_LEVEL = 5;
|
const BASE_MAX_LEVEL = 5;
|
||||||
const newLevelCount = Math.max(
|
|
||||||
Math.round(this.cfg.activity[activity].stretch),
|
|
||||||
0,
|
|
||||||
);
|
|
||||||
|
|
||||||
function expDecayModel([A, B, C]: number[]) {
|
function expDecayModel([A, B, C]: number[]) {
|
||||||
return (i: number) => A * Math.exp(-B * i) + C;
|
return (i: number) => A * Math.exp(-B * i) + C;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!this.cfg.activity[activity].enableGeneration) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
for (const gender of Object.values(Gender)) {
|
for (const gender of Object.values(Gender)) {
|
||||||
const standardsByGender = this.activityStandards[
|
const standardsByGender = this.activityStandards[
|
||||||
activity
|
activity
|
||||||
@@ -327,29 +333,43 @@ export class Standards {
|
|||||||
// UPDATE THE DATA
|
// UPDATE THE DATA
|
||||||
for (const standard of standards) {
|
for (const standard of standards) {
|
||||||
const newLevels: Levels = {};
|
const newLevels: Levels = {};
|
||||||
|
const newLowerLevelCount = Math.max(
|
||||||
|
Math.round(
|
||||||
|
this.cfg.activity[activity].stretch.lower,
|
||||||
|
),
|
||||||
|
0,
|
||||||
|
);
|
||||||
|
const newUpperLevelCount = Math.max(
|
||||||
|
Math.round(
|
||||||
|
this.cfg.activity[activity].stretch.upper,
|
||||||
|
),
|
||||||
|
0,
|
||||||
|
);
|
||||||
|
|
||||||
let prev = standard.levels["1"];
|
const oldLevels = standard.levels as Levels;
|
||||||
for (const i of range(newLevelCount).reverse()) {
|
let prev = oldLevels["1"];
|
||||||
|
for (const i of range(newLowerLevelCount).reverse()) {
|
||||||
const level = i + 1;
|
const level = i + 1;
|
||||||
const ratio = getDecayRatio(-i);
|
const ratio = getDecayRatio(-i - 1);
|
||||||
prev = isIncreasing ? prev / ratio : prev * ratio;
|
prev = isIncreasing ? prev / ratio : prev * ratio;
|
||||||
newLevels[level] = Math.round(prev);
|
newLevels[level] = Math.round(prev);
|
||||||
}
|
}
|
||||||
|
|
||||||
const oldLevels = standard.levels as Levels;
|
|
||||||
for (const i of range(BASE_MAX_LEVEL)) {
|
for (const i of range(BASE_MAX_LEVEL)) {
|
||||||
const level = i + 1;
|
const level = i + 1;
|
||||||
newLevels[level + newLevelCount] = oldLevels[level];
|
newLevels[level + newLowerLevelCount] =
|
||||||
|
oldLevels[level];
|
||||||
}
|
}
|
||||||
|
|
||||||
prev = standard.levels[BASE_MAX_LEVEL];
|
prev = oldLevels[BASE_MAX_LEVEL];
|
||||||
for (const i of range(newLevelCount)) {
|
for (const i of range(newUpperLevelCount)) {
|
||||||
const level =
|
const level =
|
||||||
BASE_MAX_LEVEL + newLevelCount + (i + 1);
|
BASE_MAX_LEVEL + newLowerLevelCount + (i + 1);
|
||||||
const ratio = getDecayRatio(level - 1);
|
const ratio = getDecayRatio(level - 1);
|
||||||
prev = isIncreasing ? prev * ratio : prev / ratio;
|
prev = isIncreasing ? prev * ratio : prev / ratio;
|
||||||
newLevels[level] = Math.round(prev);
|
newLevels[level] = Math.round(prev);
|
||||||
}
|
}
|
||||||
|
|
||||||
standard.levels = newLevels;
|
standard.levels = newLevels;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -796,12 +816,16 @@ export class Standards {
|
|||||||
if (i == 0) {
|
if (i == 0) {
|
||||||
return levels;
|
return levels;
|
||||||
}
|
}
|
||||||
|
const levelKeys = Object.keys(levels)
|
||||||
|
.map(Number)
|
||||||
|
.sort((a, b) => a - b);
|
||||||
|
|
||||||
const newLevels: Levels = {};
|
const newLevels: Levels = {};
|
||||||
let j = 1;
|
let j = 1;
|
||||||
for (let k = 0; k < Object.keys(levels).length; ++k) {
|
|
||||||
const currLevel = Object.keys(levels)[k];
|
for (let k = 0; k < levelKeys.length; ++k) {
|
||||||
const nextLevel = Object.keys(levels)[k + 1];
|
const currLevel = levelKeys[k];
|
||||||
|
const nextLevel = levelKeys[k + 1];
|
||||||
|
|
||||||
newLevels[j++] = levels[currLevel];
|
newLevels[j++] = levels[currLevel];
|
||||||
|
|
||||||
@@ -813,28 +837,43 @@ export class Standards {
|
|||||||
return this.expandLevels(newLevels, i - 1);
|
return this.expandLevels(newLevels, i - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
private compressLevels(levels: Levels, targetLevel: number): Levels {
|
private compressLevels(levels: Levels, targetLvl: number): Levels {
|
||||||
const levelsAmount = Object.keys(levels).length;
|
const keys = Object.keys(levels)
|
||||||
if (levelsAmount < targetLevel) {
|
.map(Number)
|
||||||
|
.sort((a, b) => a - b);
|
||||||
|
const lvlCnt = keys.length;
|
||||||
|
|
||||||
|
if (targetLvl <= 0) {
|
||||||
|
throw new Error("Target levels amount must be a positive integer");
|
||||||
|
}
|
||||||
|
if (lvlCnt === 0) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
if (targetLvl === 1) {
|
||||||
|
return { 1: levels[keys[0]] };
|
||||||
|
}
|
||||||
|
if (lvlCnt < targetLvl) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
"Target levels amount must be greater than or equal to the current levels amount",
|
"Target levels amount must be less than or equal to the current levels amount",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const ratio = levelsAmount / targetLevel;
|
// Linear resample
|
||||||
const compressedLevels: Levels = {};
|
const compressedLevels: Levels = {};
|
||||||
|
|
||||||
for (let i = 0; i < targetLevel; ++i) {
|
for (let targetIndex = 0; targetIndex < targetLvl; ++targetIndex) {
|
||||||
const ratioIndex = i * ratio;
|
const sourcePos = (targetIndex * (lvlCnt - 1)) / (targetLvl - 1);
|
||||||
const lowerIndex = Math.floor(ratioIndex);
|
|
||||||
const upperIndex = Math.ceil(ratioIndex);
|
|
||||||
|
|
||||||
const lowerValue = levels[lowerIndex + 1];
|
const sourceIndexLower = Math.floor(sourcePos);
|
||||||
const upperValue = levels[upperIndex + 1];
|
const sourceIndexUpper = Math.min(sourceIndexLower + 1, lvlCnt - 1);
|
||||||
|
|
||||||
const weight = ratioIndex - lowerIndex;
|
const interpolationWeight = sourcePos - sourceIndexLower;
|
||||||
compressedLevels[i + 1] =
|
|
||||||
lowerValue + (upperValue - lowerValue) * weight;
|
const lowerValue = levels[keys[sourceIndexLower]];
|
||||||
|
const upperValue = levels[keys[sourceIndexUpper]];
|
||||||
|
|
||||||
|
compressedLevels[targetIndex + 1] =
|
||||||
|
lowerValue + (upperValue - lowerValue) * interpolationWeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
return compressedLevels;
|
return compressedLevels;
|
||||||
|
|||||||
@@ -50,9 +50,16 @@
|
|||||||
peakAge: String(
|
peakAge: String(
|
||||||
defaultStandards.cfg.activity[activity].peakAge,
|
defaultStandards.cfg.activity[activity].peakAge,
|
||||||
),
|
),
|
||||||
stretch: String(
|
stretch: {
|
||||||
defaultStandards.cfg.activity[activity].stretch,
|
upper: String(
|
||||||
),
|
defaultStandards.cfg.activity[activity]
|
||||||
|
.stretch.upper,
|
||||||
|
),
|
||||||
|
lower: String(
|
||||||
|
defaultStandards.cfg.activity[activity]
|
||||||
|
.stretch.lower,
|
||||||
|
),
|
||||||
|
},
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
}),
|
}),
|
||||||
@@ -83,7 +90,10 @@
|
|||||||
difficultyModifier:
|
difficultyModifier:
|
||||||
+input.cfg.activity[activity].difficultyModifier,
|
+input.cfg.activity[activity].difficultyModifier,
|
||||||
peakAge: +input.cfg.activity[activity].peakAge,
|
peakAge: +input.cfg.activity[activity].peakAge,
|
||||||
stretch: +input.cfg.activity[activity].stretch,
|
stretch: {
|
||||||
|
lower: +input.cfg.activity[activity].stretch.lower,
|
||||||
|
upper: +input.cfg.activity[activity].stretch.upper,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
]),
|
]),
|
||||||
),
|
),
|
||||||
@@ -147,22 +157,6 @@
|
|||||||
bind:value={input.cfg.global.maxLevel}
|
bind:value={input.cfg.global.maxLevel}
|
||||||
/>
|
/>
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<label>
|
|
||||||
<span class="label mb-1">Stretch</span>
|
|
||||||
<input
|
|
||||||
class="input w-full"
|
|
||||||
type="number"
|
|
||||||
min="0"
|
|
||||||
max="10"
|
|
||||||
step="1"
|
|
||||||
bind:value={
|
|
||||||
input.cfg.activity[selected.activity].stretch
|
|
||||||
}
|
|
||||||
disabled={!selected.cfg.activity[selected.activity]
|
|
||||||
.enableGeneration}
|
|
||||||
/>
|
|
||||||
</label>
|
|
||||||
</div>
|
</div>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
|
|
||||||
@@ -262,6 +256,46 @@
|
|||||||
.enableGeneration}
|
.enableGeneration}
|
||||||
/>
|
/>
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
|
<fieldset class="fieldset bg-base-200 p-3 max-w-xl">
|
||||||
|
<legend class="fieldset-legend text-sm font-semibold">
|
||||||
|
Stretch
|
||||||
|
</legend>
|
||||||
|
<label>
|
||||||
|
<span class="label mb-1">Lower</span>
|
||||||
|
<input
|
||||||
|
class="input w-full"
|
||||||
|
type="number"
|
||||||
|
min="0"
|
||||||
|
max="10"
|
||||||
|
step="1"
|
||||||
|
bind:value={
|
||||||
|
input.cfg.activity[selected.activity]
|
||||||
|
.stretch.lower
|
||||||
|
}
|
||||||
|
disabled={!selected.cfg.activity[
|
||||||
|
selected.activity
|
||||||
|
].enableGeneration}
|
||||||
|
/>
|
||||||
|
</label>
|
||||||
|
<label>
|
||||||
|
<span class="label mb-1">Upper</span>
|
||||||
|
<input
|
||||||
|
class="input w-full"
|
||||||
|
type="number"
|
||||||
|
min="0"
|
||||||
|
max="10"
|
||||||
|
step="1"
|
||||||
|
bind:value={
|
||||||
|
input.cfg.activity[selected.activity]
|
||||||
|
.stretch.upper
|
||||||
|
}
|
||||||
|
disabled={!selected.cfg.activity[
|
||||||
|
selected.activity
|
||||||
|
].enableGeneration}
|
||||||
|
/>
|
||||||
|
</label>
|
||||||
|
</fieldset>
|
||||||
</div>
|
</div>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user