Skip to content

Commit 407c8a2

Browse files
authored
Gradebook calculations tolerate undefined values in mean (#620)
1 parent c84100c commit 407c8a2

File tree

2 files changed

+199
-195
lines changed

2 files changed

+199
-195
lines changed

supabase/functions/gradebook-column-recalculate/expression/DependencySource.ts

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -959,7 +959,7 @@ export async function addDependencySourceFunctions({
959959
if (Array.isArray(value)) {
960960
// Log input to help diagnose issues
961961
console.log(
962-
`Mean called with ${value.length} values (weighted=${weighted}):`,
962+
`Mean called for student ${_context.student_id} with ${value.length} values (weighted=${weighted}):`,
963963
JSON.stringify(
964964
value.map((v) => ({
965965
score: isGradebookColumnStudent(v) ? v.score : "N/A",
@@ -991,8 +991,11 @@ export async function addDependencySourceFunctions({
991991
if (isArray(v)) {
992992
throw new Error("Unsupported nesting of arrays");
993993
}
994+
if (v === undefined || v === null) {
995+
return { score: undefined, max_score: undefined };
996+
}
994997
throw new Error(
995-
`Unsupported value type for mean. Mean can only be applied to gradebook columns because it expects a max_score for each value. Got: ${JSON.stringify(v, null, 2)}`
998+
`Unsupported value type for mean. Mean can only be applied to gradebook columns because it expects a max_score for each value.`
996999
);
9971000
});
9981001
const validValues = valuesToAverage.filter(
@@ -1099,9 +1102,9 @@ export async function addDependencySourceFunctions({
10991102
}));
11001103
console.log(`Drop_lowest called with ${value.length} values, dropping ${count}:`, JSON.stringify(inputSummary));
11011104

1102-
// Filter out entries with max_score <= 0 before sorting and selecting to drop
1105+
// Filter out entries with max_score <= 0 or score === null before sorting and selecting to drop
11031106
// These entries should be preserved and not count toward drop_lowest
1104-
const validEntries = value.filter((v) => (v.max_score ?? 0) > 0);
1107+
const validEntries = value.filter((v) => (v.max_score ?? 0) > 0 && v.score !== null);
11051108

11061109
// Sort to identify which items to drop by relative score (score/max_score), but preserve original order in output
11071110
const sorted = [...validEntries].sort((a, b) => {
@@ -1123,12 +1126,12 @@ export async function addDependencySourceFunctions({
11231126
}
11241127
}
11251128

1126-
// Return items in original order, excluding only those marked for dropping that have max_score > 0
1129+
// Return items in original order, excluding only those marked for dropping that have max_score > 0 and score !== null
11271130
// Preserve all entries with max_score <= 0 untouched
11281131
const ret: GradebookColumnStudentWithMaxScore[] = [];
11291132
for (const v of value) {
11301133
// Only exclude items that were chosen to drop AND have max_score > 0
1131-
if (!(toDrop.has(v) && (v.max_score ?? 0) > 0)) {
1134+
if (!toDrop.has(v) && (v.max_score ?? 0) > 0 && v.score !== null) {
11321135
ret.push(v);
11331136
}
11341137
}

0 commit comments

Comments
 (0)