Commit 33117daf authored by Yechang's avatar Yechang
Browse files

feat(submission feedback): penalty score

parent 7f279056
Loading
Loading
Loading
Loading
Loading
+84 −0
Original line number Diff line number Diff line
import _ from "lodash"
import { db } from ".";
import type { SubmissionFeedback } from "@prisma/client";
import { contentSchema } from "$lib/shared/feedback";


const getFeedbackScore = async (feedback: SubmissionFeedback): Promise<number> => {
    const contentResult = contentSchema.safeParse(feedback.content)
    if (!contentResult.success) {
        return 0
    }

    const { data } = contentResult
    for (const x of data) {
        if (x.type !== 'score') continue
        return x.value
    }
    return 0;
}

// null for undetermined
export const fixAndCalculatePenalty = async (currentSubmissionId: number): Promise<number | null> => {
    // find the submission
    const submission = await db.submission.findUnique({
        where: { id: currentSubmissionId }, include: {
            problem: true
        }
    })
    if (_.isNil(submission)) {
        return 0;
    }

    // determine the problem's penalty
    const { problem } = submission
    const penalty = problem.penalty || 0
    const penaltyAfter = problem.penaltyAfter || 0
    if (penalty === 0) {
        return 0
    }

    const submissions = await db.submission.findMany({
        where: {
            id: {
                lte: submission.id
            },
            submitterId: submission.id,
            problemId: problem.id
        },
        orderBy: {
            id: 'asc'
        },
        include: {
            feedback: true
        }
    })

    let num = 0;
    const cal = (num: number) => (_.max([num - penaltyAfter, 0]) || 0) * penalty;
    for (const s of submissions) {
        if (_.isNil(s.feedback)) {
            // no feedback
            return null
        }
        const { feedback } = s
        if (feedback.score >= 0) {
            // already had score
            continue
        }
        num += feedback.isValid ? 1 : 0;
        const penaltyScore = cal(num)
        const originalScore = await getFeedbackScore(s.feedback)
        const finalScore = _.max([originalScore - penaltyScore, 0]) || 0;

        await db.submissionFeedback.update({
            where: {
                id: feedback.id
            },
            data: {
                score: finalScore
            }
        })
    }
    return cal(num + 1)
}
 No newline at end of file
+8 −5
Original line number Diff line number Diff line
import { db } from '$lib/server/db'
import { fixAndCalculatePenalty } from '$lib/server/db/feedback.js'
import { redis } from '$lib/server/redis'
import type { contentSchema } from '$lib/shared/feedback.js'
import { TaskStatus } from '@prisma/client'
@@ -99,7 +100,7 @@ export const PUT = async ({ request, params }) => {

        if (!parsed.success) {
            console.log(parsed.error)
            return json({ ok: true })
            return new Response(null, { status: 201 })
        }

        const res = parsed.data
@@ -128,7 +129,7 @@ export const PUT = async ({ request, params }) => {
                }
            })

            return json({ ok: true })
            return new Response(null, { status: 201 })
        }
        if (res.status === 'JudgementFailed' ||
            res.status === 'ConfigurationError' ||
@@ -160,12 +161,14 @@ export const PUT = async ({ request, params }) => {
                    isValid: false
                }
            })
            return json({ ok: true })
            return new Response(null, { status: 201 })
        }

        const penalty = await fixAndCalculatePenalty(task.submissionId)
        const score = _.isNil(penalty) ? -1 : (_.max([res.score - penalty, 0]) || 0)
        const feedback = await db.submissionFeedback.create({
            data: {
                score: -1,
                score,
                description: res.status,
                descriptionHTML: "",
                content: [
@@ -198,5 +201,5 @@ export const PUT = async ({ request, params }) => {
        })

    }
    return json({ ok: true })
    return new Response(null, { status: 201 })
}
 No newline at end of file