Skip to content

Commit ca7d7f2

Browse files
authored
Merge pull request #17 from jvcByte/preview
Preview
2 parents ed97b40 + feb97ef commit ca7d7f2

2 files changed

Lines changed: 24 additions & 10 deletions

File tree

app/api/instructor/exercises/[id]/recalculate-scores/route.ts

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -42,23 +42,21 @@ export async function POST(
4242
const minResponseLength = ex.min_response_length ?? DEFAULT_MIN_LENGTH;
4343
const hasConstraints = ex.pass_mark !== null || ex.min_questions_required !== null || ex.flag_fails || ex.max_paste_chars !== null || ex.max_focus_loss !== null;
4444

45-
// 1. Mark submissions as final only if actually attempted
45+
// 1. Mark submissions as final only if actually attempted (not skipped)
4646
// (non-empty response OR has edit events — handles both written and code questions)
4747
await sql`
4848
UPDATE submissions SET is_final = true
4949
WHERE session_id IN (SELECT id FROM sessions WHERE exercise_id = ${exerciseId})
5050
AND is_final = false
51+
AND status != 'skipped'
5152
AND (
5253
LENGTH(TRIM(COALESCE(response_text, ''))) > 0
5354
OR EXISTS (SELECT 1 FROM edit_events ee WHERE ee.submission_id = submissions.id)
5455
)
5556
`;
5657

57-
// 2. Close open sessions
58-
await sql`
59-
UPDATE sessions SET closed_at = now()
60-
WHERE exercise_id = ${exerciseId} AND closed_at IS NULL AND started_at IS NOT NULL
61-
`;
58+
// 2. Close open sessions — intentionally removed.
59+
// Recalculate should only rescore; it must not force-close active sessions.
6260

6361
// 3. Re-evaluate paste flags with threshold
6462
if (ex.max_paste_chars !== null) {
@@ -174,7 +172,23 @@ export async function POST(
174172
const sessionData = await sql`
175173
SELECT
176174
s.id AS session_id,
177-
SUM(CASE WHEN sub.is_final THEN 1 ELSE 0 END)::int AS final_count,
175+
SUM(CASE
176+
WHEN sub.is_final AND sub.status != 'skipped' AND (
177+
(
178+
SELECT CASE
179+
WHEN q.test_cases IS NOT NULL THEN (CASE WHEN sub.tests_passed = true THEN 1 ELSE 0 END)
180+
ELSE (CASE WHEN
181+
LENGTH(TRIM(REPLACE(COALESCE(sub.response_text, ''), COALESCE(q.starter, ''), ''))) > 0
182+
OR EXISTS (SELECT 1 FROM edit_events ee WHERE ee.submission_id = sub.id)
183+
THEN 1 ELSE 0 END)
184+
END
185+
FROM questions q
186+
JOIN sessions s2 ON s2.exercise_id = q.exercise_id
187+
WHERE s2.id = s.id AND q.question_index = sub.question_index
188+
LIMIT 1
189+
) = 1
190+
) THEN 1 ELSE 0
191+
END)::int AS final_count,
178192
COALESCE(SUM(
179193
GREATEST(0,
180194
COALESCE(array_length(sub.flag_reasons, 1), 0)

lib/scoring.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,10 +51,10 @@ export async function recalculateSessionScore(sessionId: string): Promise<ScoreR
5151
// - code with test cases: is_final AND tests_passed = true
5252
// - code without test cases: is_final AND has edit events (unchanged behavior)
5353
const finalRows = await sql`
54-
SELECT SUM(CASE WHEN sub.is_final AND (
55-
-- Written question or code with no test cases: presence check
54+
SELECT SUM(CASE WHEN sub.is_final AND sub.status != 'skipped' AND (
55+
-- Written question or code with no test cases: must have content beyond the starter
5656
(q.test_cases IS NULL AND (
57-
LENGTH(TRIM(COALESCE(sub.response_text, ''))) > 0
57+
LENGTH(TRIM(REPLACE(COALESCE(sub.response_text, ''), COALESCE(q.starter, ''), ''))) > 0
5858
OR EXISTS (SELECT 1 FROM edit_events ee WHERE ee.submission_id = sub.id)
5959
))
6060
OR

0 commit comments

Comments
 (0)