Files
PolyMPR/logic/grades.ts
T
djalim 951c9c1fea
Check Deno code / Check Deno code (pull_request) Has been cancelled
Tests / Unit tests (pull_request) Has been cancelled
Tests / Integration tests (pull_request) Has been cancelled
Check Deno code / Check Deno code (push) Has been cancelled
Tests / Unit tests (push) Has been cancelled
Tests / Integration tests (push) Has been cancelled
test : changed test format + added playwright support
2026-05-03 21:52:02 +02:00

86 lines
1.8 KiB
TypeScript

/**
* Logique métier pour le calcul des notes et moyennes.
*/
export interface Note {
note: number;
noteSession2: number | null;
}
export interface UEModule {
idModule: string;
coeff: number;
}
export interface Ajustement {
valeur: number;
malus: number;
}
/**
* Retourne la note effective (Session 2 si présente, sinon Session 1).
*/
export function getEffectiveNote(n: Note): number {
return n.noteSession2 ?? n.note;
}
/**
* Calcule la moyenne pondérée d'une liste de modules.
* Retourne null si aucun module n'est noté.
*/
export function calculateWeightedAverage(
ueModules: UEModule[],
notesMap: Record<string, Note>,
): number | null {
let weightedSum = 0;
let coveredCoeff = 0;
for (const um of ueModules) {
const noteObj = notesMap[um.idModule];
if (noteObj) {
const val = getEffectiveNote(noteObj);
weightedSum += val * um.coeff;
coveredCoeff += um.coeff;
}
}
if (coveredCoeff === 0) return null;
return weightedSum / coveredCoeff;
}
/**
* Applique l'ajustement et le malus à une moyenne.
* L'ajustement REMPLACE la moyenne calculée si présent.
*/
export function applyAjustement(
calculatedAvg: number | null,
ajustement: Ajustement | null,
): number | null {
let finalAvg = calculatedAvg;
if (ajustement) {
// L'ajustement remplace la moyenne
finalAvg = ajustement.valeur;
if (ajustement.malus > 0) {
finalAvg = (finalAvg ?? 0) - ajustement.malus;
}
}
return finalAvg;
}
/**
* Arrondit une note à 2 décimales.
*/
export function roundGrade(grade: number): number {
return Math.round(grade * 100) / 100;
}
/**
* Formate une note pour l'affichage (2 décimales).
*/
export function formatGrade(grade: number | null): string {
if (grade === null) return "—";
return grade.toFixed(2);
}