"use server"; import prisma from "@/lib/prisma"; import { auth, signIn } from "@/lib/auth"; import { revalidatePath } from "next/cache"; import { Language, Locale, Status } from "@/generated/client"; import { analyzeCode } from "@/app/actions/analyze-code"; import { inngest } from "@/inngest/client"; import { createSubmissionWithStatus, updateSubmissionStatus, } from "@/lib/submission-status"; export const judge = async ( problemId: string, language: Language, content: string, assignmentId?: string, locale: Locale = "zh" ): Promise => { const session = await auth(); const userId = session?.user?.id; if (!userId) { await signIn(); return Status.SE; } try { const actor = await prisma.user.findUnique({ where: { id: userId }, select: { id: true, role: true }, }); if (!actor) { return Status.SE; } const createSystemErrorSubmission = async ( message: string, options?: { assignmentId?: string | null } ) => { await createSubmissionWithStatus({ language, content, status: Status.SE, message, userId, problemId, assignmentId: options?.assignmentId ?? null, }); }; let validatedAssignmentId: string | undefined; if (assignmentId) { const assignment = await prisma.assignment.findUnique({ where: { id: assignmentId }, select: { id: true, published: true, course: { select: { archived: true, teacherId: true, enrollments: { where: { userId }, select: { userId: true }, }, }, }, problems: { where: { problemId }, select: { problemId: true }, }, }, }); if (!assignment) { await createSystemErrorSubmission("Assignment not found"); return Status.SE; } const isTeacherOwner = assignment.course.teacherId === userId; const isStudentEnrolled = assignment.course.enrollments.length > 0; const canAccessAssignment = actor.role === "ADMIN" || (actor.role === "TEACHER" && isTeacherOwner) || (actor.role === "STUDENT" && isStudentEnrolled); if (!canAccessAssignment) { await createSystemErrorSubmission("No permission for assignment", { assignmentId: assignment.id, }); return Status.SE; } if (assignment.course.archived) { await createSystemErrorSubmission("Course is archived", { assignmentId: assignment.id, }); return Status.SE; } if (!assignment.published && actor.role === "STUDENT") { await createSystemErrorSubmission("Assignment is not published", { assignmentId: assignment.id, }); return Status.SE; } if (assignment.problems.length === 0) { await createSystemErrorSubmission( "Problem does not belong to assignment", { assignmentId: assignment.id, } ); return Status.SE; } validatedAssignmentId = assignment.id; } const problem = await prisma.problem.findUnique({ where: { id: problemId, }, }); if (!problem) { await createSystemErrorSubmission("Problem not found", { assignmentId: validatedAssignmentId, }); return Status.SE; } const testcases = await prisma.testcase.findMany({ where: { problemId, }, }); if (!testcases.length) { await createSystemErrorSubmission( "No testcases available for this problem", { assignmentId: validatedAssignmentId } ); return Status.SE; } const dockerConfig = await prisma.dockerConfig.findUnique({ where: { language, }, }); if (!dockerConfig) { await createSystemErrorSubmission( `Docker configuration not found for language: ${language}`, { assignmentId: validatedAssignmentId } ); return Status.SE; } const submission = await createSubmissionWithStatus({ language, content, status: Status.QD, userId, problemId, assignmentId: validatedAssignmentId, }); const executeAnalyzeCode = async () => { await analyzeCode({ content, submissionId: submission.id, locale, }); } executeAnalyzeCode(); try { await inngest.send({ name: "submissions/create", data: { submissionId: submission.id, }, }); } catch (inngestError) { console.error("Failed to enqueue judge event:", inngestError); await updateSubmissionStatus(submission.id, Status.SE, { message: "Failed to enqueue judge event", }); return Status.SE; } return Status.QD; } catch (error) { console.error("Error in judge:", error); return Status.SE; } finally { revalidatePath(`/problems/${problemId}`); } };