=test_update_homework_tests_and_work_log
Some checks failed
CI / build-deploy (push) Has been cancelled
Some checks failed
CI / build-deploy (push) Has been cancelled
This commit is contained in:
@@ -1,9 +1,10 @@
|
||||
import { db } from "@/shared/db"
|
||||
import { exams } from "@/shared/db/schema"
|
||||
import { exams, examQuestions, questions, subjects, grades } from "@/shared/db/schema"
|
||||
import { eq, desc, like, and, or } from "drizzle-orm"
|
||||
import { cache } from "react"
|
||||
|
||||
import type { Exam, ExamDifficulty, ExamStatus } from "./types"
|
||||
import type { AiGeneratedQuestion, AiGeneratedStructureNode } from "./ai-pipeline"
|
||||
|
||||
export type GetExamsParams = {
|
||||
q?: string
|
||||
@@ -158,3 +159,139 @@ export const omitScheduledAtFromDescription = (description: string | null): stri
|
||||
return description || "{}"
|
||||
}
|
||||
}
|
||||
|
||||
export const resolveSubjectGradeNames = async (input: {
|
||||
subjectId?: string
|
||||
gradeId?: string
|
||||
}) => {
|
||||
const [subjectRecord, gradeRecord] = await Promise.all([
|
||||
input.subjectId
|
||||
? db.query.subjects.findFirst({
|
||||
where: eq(subjects.id, input.subjectId),
|
||||
})
|
||||
: Promise.resolve(null),
|
||||
input.gradeId
|
||||
? db.query.grades.findFirst({
|
||||
where: eq(grades.id, input.gradeId),
|
||||
})
|
||||
: Promise.resolve(null),
|
||||
])
|
||||
return {
|
||||
subjectName: subjectRecord?.name,
|
||||
gradeName: gradeRecord?.name,
|
||||
}
|
||||
}
|
||||
|
||||
export const buildExamDescription = (input: {
|
||||
subject: string
|
||||
grade: string
|
||||
difficulty: number
|
||||
totalScore: number
|
||||
durationMin: number
|
||||
scheduledAt?: string
|
||||
questionCount?: number
|
||||
}) => JSON.stringify({
|
||||
subject: input.subject,
|
||||
grade: input.grade,
|
||||
difficulty: input.difficulty,
|
||||
totalScore: input.totalScore,
|
||||
durationMin: input.durationMin,
|
||||
scheduledAt: input.scheduledAt,
|
||||
questionCount: input.questionCount,
|
||||
})
|
||||
|
||||
export const persistExamDraft = async (input: {
|
||||
examId: string
|
||||
title: string
|
||||
creatorId: string
|
||||
subjectId: string
|
||||
gradeId: string
|
||||
scheduledAt?: string
|
||||
description: string
|
||||
}) => {
|
||||
await db.insert(exams).values({
|
||||
id: input.examId,
|
||||
title: input.title,
|
||||
description: input.description,
|
||||
creatorId: input.creatorId,
|
||||
subjectId: input.subjectId,
|
||||
gradeId: input.gradeId,
|
||||
startTime: input.scheduledAt ? new Date(input.scheduledAt) : null,
|
||||
status: "draft",
|
||||
})
|
||||
}
|
||||
|
||||
const buildOrderedQuestionsFromStructure = (
|
||||
structure: AiGeneratedStructureNode[],
|
||||
generated: AiGeneratedQuestion[]
|
||||
) => {
|
||||
const questionById = new Map(generated.map((q) => [q.id, q] as const))
|
||||
const orderedQuestions: Array<{ id: string; score: number }> = []
|
||||
const collectOrder = (nodes: AiGeneratedStructureNode[]) => {
|
||||
for (const node of nodes) {
|
||||
if (node.type === "question" && typeof node.questionId === "string" && node.questionId) {
|
||||
const score = typeof node.score === "number" ? node.score : questionById.get(node.questionId)?.score ?? 0
|
||||
orderedQuestions.push({ id: node.questionId, score })
|
||||
continue
|
||||
}
|
||||
if (node.type === "group" && Array.isArray(node.children) && node.children.length > 0) {
|
||||
collectOrder(node.children)
|
||||
}
|
||||
}
|
||||
}
|
||||
collectOrder(structure)
|
||||
if (orderedQuestions.length === 0) {
|
||||
return generated.map((q) => ({ id: q.id, score: q.score ?? 0 }))
|
||||
}
|
||||
return orderedQuestions
|
||||
}
|
||||
|
||||
export const persistAiGeneratedExamDraft = async (input: {
|
||||
examId: string
|
||||
title: string
|
||||
creatorId: string
|
||||
subjectId: string
|
||||
gradeId: string
|
||||
scheduledAt?: string
|
||||
description: string
|
||||
structure: AiGeneratedStructureNode[]
|
||||
generated: AiGeneratedQuestion[]
|
||||
}) => {
|
||||
const orderedQuestions = buildOrderedQuestionsFromStructure(input.structure, input.generated)
|
||||
await db.transaction(async (tx) => {
|
||||
await tx.insert(exams).values({
|
||||
id: input.examId,
|
||||
title: input.title,
|
||||
description: input.description,
|
||||
creatorId: input.creatorId,
|
||||
subjectId: input.subjectId,
|
||||
gradeId: input.gradeId,
|
||||
startTime: input.scheduledAt ? new Date(input.scheduledAt) : null,
|
||||
status: "draft",
|
||||
structure: input.structure,
|
||||
})
|
||||
|
||||
if (input.generated.length > 0) {
|
||||
await tx.insert(questions).values(
|
||||
input.generated.map((q) => ({
|
||||
id: q.id,
|
||||
content: q.content,
|
||||
type: q.type,
|
||||
difficulty: q.difficulty,
|
||||
authorId: input.creatorId,
|
||||
}))
|
||||
)
|
||||
}
|
||||
|
||||
if (orderedQuestions.length > 0) {
|
||||
await tx.insert(examQuestions).values(
|
||||
orderedQuestions.map((q, idx) => ({
|
||||
examId: input.examId,
|
||||
questionId: q.id,
|
||||
score: q.score ?? 0,
|
||||
order: idx,
|
||||
}))
|
||||
)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user