229 lines
6.0 KiB
SQL
229 lines
6.0 KiB
SQL
-- name: UpsertStudentAnswer :one
|
|
INSERT INTO student_answers (
|
|
assignment_id,
|
|
question_id,
|
|
student_id,
|
|
answer_text,
|
|
solve_mode,
|
|
working_steps,
|
|
ai_feedback,
|
|
teacher_feedback,
|
|
status,
|
|
submitted_at,
|
|
reviewed_at,
|
|
is_correct
|
|
) VALUES (
|
|
$1,
|
|
$2,
|
|
$3,
|
|
$4,
|
|
$5,
|
|
$6,
|
|
$7,
|
|
$8,
|
|
$9,
|
|
$10,
|
|
$11,
|
|
$12
|
|
)
|
|
ON CONFLICT (assignment_id, question_id, student_id) DO UPDATE
|
|
SET
|
|
answer_text = EXCLUDED.answer_text,
|
|
solve_mode = EXCLUDED.solve_mode,
|
|
working_steps = EXCLUDED.working_steps,
|
|
ai_feedback = EXCLUDED.ai_feedback,
|
|
teacher_feedback = EXCLUDED.teacher_feedback,
|
|
status = EXCLUDED.status,
|
|
submitted_at = EXCLUDED.submitted_at,
|
|
reviewed_at = EXCLUDED.reviewed_at,
|
|
is_correct = EXCLUDED.is_correct,
|
|
updated_at = NOW()
|
|
RETURNING *;
|
|
|
|
-- name: UpdateAnswerAIReview :one
|
|
UPDATE student_answers
|
|
SET
|
|
ai_feedback = $2,
|
|
review_needs_attention = $3,
|
|
review_issue_reason = $4,
|
|
review_correctness_score = $5,
|
|
review_understanding_score = $6,
|
|
review_question_score = $7,
|
|
review_confidence = $8,
|
|
updated_at = NOW()
|
|
WHERE id = $1
|
|
RETURNING *;
|
|
|
|
-- name: ListAnswersForAssignment :many
|
|
SELECT *
|
|
FROM student_answers
|
|
WHERE assignment_id = $1
|
|
ORDER BY created_at ASC;
|
|
|
|
-- name: ListAnswersForStudent :many
|
|
SELECT *
|
|
FROM student_answers
|
|
WHERE student_id = $1
|
|
ORDER BY created_at DESC;
|
|
|
|
-- name: ListQuestionDetailsForAssignmentStudent :many
|
|
WITH student_question_set AS (
|
|
SELECT
|
|
asq.assignment_id,
|
|
asq.question_id,
|
|
asq.position
|
|
FROM assignment_student_questions asq
|
|
WHERE asq.assignment_id = $1
|
|
AND asq.student_id = $2
|
|
),
|
|
selected_questions AS (
|
|
SELECT
|
|
sq.assignment_id,
|
|
sq.question_id,
|
|
sq.position
|
|
FROM student_question_set sq
|
|
UNION ALL
|
|
SELECT
|
|
aq.assignment_id,
|
|
aq.question_id,
|
|
aq.position
|
|
FROM assignment_questions aq
|
|
WHERE aq.assignment_id = $1
|
|
AND NOT EXISTS (SELECT 1 FROM student_question_set)
|
|
)
|
|
SELECT
|
|
aq.assignment_id,
|
|
aq.question_id,
|
|
aq.position,
|
|
q.title,
|
|
q.prompt,
|
|
q.subject,
|
|
q.source,
|
|
COALESCE(
|
|
ARRAY(
|
|
SELECT t.name
|
|
FROM question_tags qt
|
|
JOIN tags t ON t.id = qt.tag_id
|
|
WHERE qt.question_id = aq.question_id
|
|
ORDER BY t.name ASC
|
|
),
|
|
ARRAY[]::TEXT[]
|
|
)::TEXT[] AS question_tags,
|
|
q.status AS question_status,
|
|
q.correct_answer,
|
|
aa.ai_feedback AS assignment_ai_feedback,
|
|
aa.teacher_feedback AS assignment_teacher_feedback,
|
|
review_summary.overall_score,
|
|
a.pass_threshold,
|
|
aa.next_step_outcome,
|
|
aa.pass_status_override,
|
|
COALESCE(
|
|
aa.pass_status_override,
|
|
CASE
|
|
WHEN review_summary.overall_score IS NULL THEN 'pending'::assignment_pass_status
|
|
WHEN review_summary.overall_score >= a.pass_threshold THEN 'pass'::assignment_pass_status
|
|
ELSE 'no_pass'::assignment_pass_status
|
|
END
|
|
) AS pass_status,
|
|
sa.id AS answer_id,
|
|
sa.student_id,
|
|
sa.answer_text,
|
|
sa.solve_mode,
|
|
sa.working_steps,
|
|
sa.is_correct,
|
|
sa.ai_feedback,
|
|
sa.teacher_feedback,
|
|
sa.status AS answer_status,
|
|
sa.review_needs_attention,
|
|
sa.review_issue_reason,
|
|
sa.review_correctness_score,
|
|
sa.review_understanding_score,
|
|
sa.review_question_score,
|
|
sa.review_confidence,
|
|
sa.review_tags,
|
|
sa.submitted_at,
|
|
sa.reviewed_at,
|
|
sa.created_at AS answer_created_at,
|
|
sa.updated_at AS answer_updated_at
|
|
FROM selected_questions aq
|
|
JOIN assignments a ON a.id = aq.assignment_id
|
|
JOIN questions q ON q.id = aq.question_id
|
|
LEFT JOIN assignment_assignees aa
|
|
ON aa.assignment_id = aq.assignment_id
|
|
AND aa.student_id = $2
|
|
LEFT JOIN LATERAL (
|
|
SELECT CASE
|
|
WHEN COUNT(sa2.id) = 0 THEN NULL::NUMERIC(5,2)
|
|
ELSE ROUND((AVG(
|
|
CASE
|
|
WHEN sa2.is_correct IS NULL THEN COALESCE(sa2.review_understanding_score, 0)::NUMERIC
|
|
ELSE (
|
|
((CASE WHEN sa2.is_correct THEN 1 ELSE 0 END)::NUMERIC) + COALESCE(sa2.review_understanding_score, 0)::NUMERIC
|
|
) / 2
|
|
END
|
|
) * 10)::NUMERIC, 2)::NUMERIC(5,2)
|
|
END AS overall_score
|
|
FROM selected_questions aq2
|
|
LEFT JOIN student_answers sa2
|
|
ON sa2.assignment_id = aq2.assignment_id
|
|
AND sa2.question_id = aq2.question_id
|
|
AND sa2.student_id = $2
|
|
WHERE aq2.assignment_id = aq.assignment_id
|
|
) review_summary ON TRUE
|
|
LEFT JOIN student_answers sa
|
|
ON sa.assignment_id = aq.assignment_id
|
|
AND sa.question_id = aq.question_id
|
|
AND sa.student_id = $2
|
|
WHERE aq.assignment_id = $1
|
|
ORDER BY aq.position ASC, aq.question_id ASC;
|
|
|
|
-- name: UpdateAnswerReview :one
|
|
UPDATE student_answers
|
|
SET
|
|
status = $2,
|
|
review_needs_attention = $3,
|
|
review_issue_reason = $4,
|
|
review_correctness_score = $5,
|
|
review_understanding_score = $6,
|
|
review_question_score = $7,
|
|
review_confidence = $8,
|
|
review_tags = $9,
|
|
reviewed_at = CASE
|
|
WHEN $2::answer_status = 'reviewed' THEN NOW()
|
|
ELSE NULL
|
|
END,
|
|
updated_at = NOW()
|
|
WHERE id = $1
|
|
RETURNING *;
|
|
|
|
-- name: ListStudentPlanningPerformance :many
|
|
SELECT
|
|
sa.assignment_id,
|
|
sa.question_id,
|
|
q.topic,
|
|
q.subject,
|
|
q.difficulty,
|
|
COALESCE(
|
|
ARRAY(
|
|
SELECT t.name
|
|
FROM question_tags qt
|
|
JOIN tags t ON t.id = qt.tag_id
|
|
WHERE qt.question_id = sa.question_id
|
|
ORDER BY t.name ASC
|
|
),
|
|
ARRAY[]::TEXT[]
|
|
)::TEXT[] AS question_tags,
|
|
sa.is_correct,
|
|
sa.review_understanding_score,
|
|
sa.review_needs_attention,
|
|
sa.review_issue_reason,
|
|
sa.status,
|
|
sa.submitted_at,
|
|
sa.reviewed_at,
|
|
sa.updated_at
|
|
FROM student_answers sa
|
|
JOIN questions q ON q.id = sa.question_id
|
|
WHERE sa.student_id = $1
|
|
AND sa.status IN ('submitted'::answer_status, 'reviewed'::answer_status)
|
|
ORDER BY COALESCE(sa.reviewed_at, sa.submitted_at, sa.updated_at) DESC, sa.id DESC;
|