Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 | 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 2x 1x 1x 1x 1x 1x 1x 1x 1x 1x | import { match } from 'ts-pattern';
import { type LtiPlanKpi } from '@amalia/lti/types';
/**
* TODO: Works only for LINEAR KPI configuration.
*
* @param kpi
* @param value
*/
export const getEarnedRatioForKpi = (kpi: Pick<LtiPlanKpi, 'configuration'>, value: number) => {
const steps = kpi.configuration.steps;
// plateau check (below first step or above last step)
const lastStep = steps.at(-1);
const plateauValue = match(value)
.when(
(v) => v < steps[0][0],
() => steps[0][1],
)
.when(
(v) => !!lastStep && v >= lastStep[0],
() => lastStep![1],
)
.otherwise(() => undefined);
if (plateauValue !== undefined) {
return plateauValue;
}
let underStepIndex = -1;
let upperStepIndex = -1;
for (let i = 0; i < steps.length - 1; i++) {
const [underTier] = steps[i];
const [upperTier] = steps[i + 1];
if (value >= underTier && value < upperTier) {
underStepIndex = i;
upperStepIndex = i + 1;
break;
}
}
if (underStepIndex === -1 || upperStepIndex === -1) {
// should not happen
throw new Error('Bad code');
}
// Calculate linear interpolation
const [underTier, underEarned] = steps[underStepIndex];
const [upperTier, upperEarned] = steps[upperStepIndex];
const slope = (upperEarned - underEarned) / (upperTier - underTier);
return underEarned + slope * (value - underTier);
};
|