test : changed test format + added playwright support
This commit is contained in:
@@ -2,6 +2,11 @@
|
||||
import * as XLSX from "https://cdn.sheetjs.com/xlsx-0.20.3/package/xlsx.mjs";
|
||||
import { useEffect, useRef } from "preact/hooks";
|
||||
import { useSignal } from "@preact/signals";
|
||||
import {
|
||||
calculateWeightedAverage,
|
||||
getEffectiveNote,
|
||||
roundGrade,
|
||||
} from "$root/logic/grades.ts";
|
||||
import ImportResultPopup, {
|
||||
type ImportDetail,
|
||||
type ImportResult,
|
||||
@@ -393,19 +398,19 @@ export default function ImportNotes() {
|
||||
const ueMods = orderedCols.filter(
|
||||
(c) => c.type === "module" && c.ueId === col.ueId,
|
||||
);
|
||||
let total = 0, coeffSum = 0;
|
||||
for (const um of ueMods) {
|
||||
|
||||
const notesRecord: Record<string, { note: number; noteSession2: number | null }> = {};
|
||||
ueMods.forEach(um => {
|
||||
const n = sNotes.get(um.id);
|
||||
if (n && um.coeff) {
|
||||
total += n.note * um.coeff;
|
||||
coeffSum += um.coeff;
|
||||
}
|
||||
}
|
||||
row.push(
|
||||
coeffSum > 0
|
||||
? Math.round((total / coeffSum) * 100) / 100
|
||||
: null,
|
||||
if (n) notesRecord[um.id] = n;
|
||||
});
|
||||
|
||||
const avg = calculateWeightedAverage(
|
||||
ueMods.map(m => ({ idModule: m.id, coeff: m.coeff ?? 0 })),
|
||||
notesRecord
|
||||
);
|
||||
|
||||
row.push(avg !== null ? roundGrade(avg) : null);
|
||||
}
|
||||
}
|
||||
s1Rows.push(row);
|
||||
@@ -425,20 +430,19 @@ export default function ImportNotes() {
|
||||
const ueMods = orderedCols.filter(
|
||||
(c) => c.type === "module" && c.ueId === col.ueId,
|
||||
);
|
||||
let total = 0, coeffSum = 0;
|
||||
for (const um of ueMods) {
|
||||
|
||||
const notesRecord: Record<string, { note: number; noteSession2: number | null }> = {};
|
||||
ueMods.forEach(um => {
|
||||
const n = sNotes.get(um.id);
|
||||
if (n && um.coeff) {
|
||||
const noteVal = n.noteSession2 ?? n.note;
|
||||
total += noteVal * um.coeff;
|
||||
coeffSum += um.coeff;
|
||||
}
|
||||
}
|
||||
row.push(
|
||||
coeffSum > 0
|
||||
? Math.round((total / coeffSum) * 100) / 100
|
||||
: null,
|
||||
if (n) notesRecord[um.id] = n;
|
||||
});
|
||||
|
||||
const avg = calculateWeightedAverage(
|
||||
ueMods.map(m => ({ idModule: m.id, coeff: m.coeff ?? 0 })),
|
||||
notesRecord
|
||||
);
|
||||
|
||||
row.push(avg !== null ? roundGrade(avg) : null);
|
||||
}
|
||||
}
|
||||
s2Rows.push(row);
|
||||
|
||||
@@ -1,6 +1,12 @@
|
||||
import { useEffect, useState } from "preact/hooks";
|
||||
import {
|
||||
applyAjustement,
|
||||
calculateWeightedAverage,
|
||||
getEffectiveNote,
|
||||
} from "$root/logic/grades.ts";
|
||||
|
||||
type Student = {
|
||||
// ...
|
||||
numEtud: number;
|
||||
nom: string;
|
||||
prenom: string;
|
||||
@@ -37,11 +43,6 @@ function noteClass(n: number): string {
|
||||
return n >= 10 ? "note-chip note-chip--ok" : "note-chip note-chip--fail";
|
||||
}
|
||||
|
||||
/** Returns the effective note (session 2 if exists, otherwise session 1). */
|
||||
function effectiveNote(n: Note): number {
|
||||
return n.noteSession2 ?? n.note;
|
||||
}
|
||||
|
||||
export default function NoteRecap({ numEtud }: Props) {
|
||||
const [student, setStudent] = useState<Student | null>(null);
|
||||
const [ueList, setUeList] = useState<UE[]>([]);
|
||||
@@ -108,19 +109,6 @@ export default function NoteRecap({ numEtud }: Props) {
|
||||
load();
|
||||
}, [numEtud]);
|
||||
|
||||
function calcAvg(ueMods: UEModule[]): number | null {
|
||||
let total = 0,
|
||||
coeff = 0;
|
||||
for (const um of ueMods) {
|
||||
const n = noteMap.get(um.idModule);
|
||||
if (n === undefined) return null;
|
||||
const val = effectiveNote(n);
|
||||
total += val * um.coeff;
|
||||
coeff += um.coeff;
|
||||
}
|
||||
return coeff > 0 ? total / coeff : null;
|
||||
}
|
||||
|
||||
async function saveNote(
|
||||
idModule: string,
|
||||
field: "note" | "noteSession2",
|
||||
@@ -280,18 +268,11 @@ export default function NoteRecap({ numEtud }: Props) {
|
||||
</p>
|
||||
)
|
||||
: ueList.map((ue) => {
|
||||
const ueMods = ueModules.filter((um) => um.idUE === ue.id);
|
||||
const avg = calcAvg(ueMods);
|
||||
const ajust = ajustements.find((a) => a.idUE === ue.id);
|
||||
|
||||
// Final displayed average: if ajust.valeur exists it replaces avg, then subtract malus
|
||||
let finalAvg = avg;
|
||||
if (ajust) {
|
||||
finalAvg = ajust.valeur;
|
||||
if (ajust.malus > 0) {
|
||||
finalAvg = (finalAvg ?? 0) - ajust.malus;
|
||||
}
|
||||
}
|
||||
const ueMods = ueList.length > 0 ? ueModules.filter((um) => um.idUE === ue.id) : [];
|
||||
const notesRecord = Object.fromEntries(noteMap);
|
||||
const avg = calculateWeightedAverage(ueMods, notesRecord);
|
||||
const ajust = ajustements.find((a) => a.idUE === ue.id) ?? null;
|
||||
const finalAvg = applyAjustement(avg, ajust);
|
||||
|
||||
return (
|
||||
<div key={ue.id} class="edit-section">
|
||||
@@ -341,7 +322,7 @@ export default function NoteRecap({ numEtud }: Props) {
|
||||
const noteVal = noteObj?.note;
|
||||
const noteS2 = noteObj?.noteSession2;
|
||||
const effective = noteObj
|
||||
? effectiveNote(noteObj)
|
||||
? getEffectiveNote(noteObj)
|
||||
: undefined;
|
||||
const nomMod = moduleMap.get(um.idModule) ?? um.idModule;
|
||||
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
import { useEffect, useState } from "preact/hooks";
|
||||
import {
|
||||
applyAjustement,
|
||||
calculateWeightedAverage,
|
||||
getEffectiveNote,
|
||||
} from "$root/logic/grades.ts";
|
||||
|
||||
type Note = {
|
||||
numEtud: number;
|
||||
@@ -6,6 +11,7 @@ type Note = {
|
||||
note: number;
|
||||
noteSession2: number | null;
|
||||
};
|
||||
// ... rest of types unchanged ...
|
||||
type UE = { id: number; nom: string };
|
||||
type UEModule = {
|
||||
idModule: string;
|
||||
@@ -36,11 +42,6 @@ function avgClass(avg: number | null): string {
|
||||
return avg >= 10 ? "avg-good" : "avg-warn";
|
||||
}
|
||||
|
||||
/** Returns the effective note (session 2 if exists, otherwise session 1). */
|
||||
function effectiveNote(n: Note): number {
|
||||
return n.noteSession2 ?? n.note;
|
||||
}
|
||||
|
||||
export default function NotesView({ numEtud, prenom }: Props) {
|
||||
const [notes, setNotes] = useState<Note[]>([]);
|
||||
const [ues, setUes] = useState<UE[]>([]);
|
||||
@@ -175,29 +176,9 @@ export default function NotesView({ numEtud, prenom }: Props) {
|
||||
if (!ue) return null;
|
||||
|
||||
const ueModsForUE = filteredUeModules.filter((um) => um.idUE === ueId);
|
||||
let weightedSum = 0;
|
||||
let coveredCoeff = 0;
|
||||
ueModsForUE.forEach((um) => {
|
||||
const noteObj = noteMap[um.idModule];
|
||||
if (noteObj) {
|
||||
const val = effectiveNote(noteObj);
|
||||
weightedSum += val * um.coeff;
|
||||
coveredCoeff += um.coeff;
|
||||
}
|
||||
});
|
||||
|
||||
const avg = coveredCoeff > 0 ? weightedSum / coveredCoeff : null;
|
||||
const avg = calculateWeightedAverage(ueModsForUE, noteMap);
|
||||
const ajust = ajMap[ueId] ?? null;
|
||||
|
||||
// If ajust.valeur exists, it replaces the calculated average
|
||||
// Then malus is subtracted
|
||||
let finalAvg: number | null = avg;
|
||||
if (ajust) {
|
||||
finalAvg = ajust.valeur;
|
||||
if (ajust.malus > 0) {
|
||||
finalAvg = (finalAvg ?? 0) - ajust.malus;
|
||||
}
|
||||
}
|
||||
const finalAvg = applyAjustement(avg, ajust);
|
||||
|
||||
return (
|
||||
<div key={ueId} class="ue-card">
|
||||
@@ -218,7 +199,7 @@ export default function NotesView({ numEtud, prenom }: Props) {
|
||||
{ueModsForUE.map((um) => {
|
||||
const mod = moduleMap[um.idModule];
|
||||
const noteObj = noteMap[um.idModule] ?? null;
|
||||
const effective = noteObj ? effectiveNote(noteObj) : null;
|
||||
const effective = noteObj ? getEffectiveNote(noteObj) : null;
|
||||
const hasS2 = noteObj?.noteSession2 != null;
|
||||
|
||||
return (
|
||||
|
||||
Reference in New Issue
Block a user