Commit 7f279056 authored by Yechang's avatar Yechang
Browse files

feat(submission feedback): allow leaving feedback score undetermined

parent 90c65eb2
Loading
Loading
Loading
Loading
+30 −0
Original line number Diff line number Diff line
<script lang="ts">
	import { cn } from '$lib/utils';

	// your script goes here
	export let color: 'blue' | 'yellow' = 'blue';
</script>

<div
	class={cn(
		'mb-4 flex items-center rounded-lg  p-4 text-sm  dark:bg-gray-800',
		`bg-${color}-50 text-${color}-800 dark:text-${color}-300`
	)}
	role="alert"
>
	<svg
		class="me-3 inline h-4 w-4 flex-shrink-0"
		aria-hidden="true"
		xmlns="http://www.w3.org/2000/svg"
		fill="currentColor"
		viewBox="0 0 20 20"
	>
		<path
			d="M10 .5a9.5 9.5 0 1 0 9.5 9.5A9.51 9.51 0 0 0 10 .5ZM9.5 4a1.5 1.5 0 1 1 0 3 1.5 1.5 0 0 1 0-3ZM12 15H8a1 1 0 0 1 0-2h1v-3H8a1 1 0 0 1 0-2h2a1 1 0 0 1 1 1v4h1a1 1 0 0 1 0 2Z"
		/>
	</svg>
	<span class="sr-only">Info</span>
	<div>
        <slot></slot>
	</div>
</div>
+49 −0
Original line number Diff line number Diff line
import { z } from 'zod';

export const contentSchema = z.discriminatedUnion('type', [
    z.object({
        type: z.literal('ansi'),
        value: z.string()
    }),
    z.object({
        type: z.literal('testcases'),
        value: z
            .object({
                status: z.string(),
                score: z.number(),
                testcaseInfo: z.object({
                    timeLimit: z.number(),
                    memoryLimit: z.number(),
                    inputFile: z.string(),
                    outputFile: z.string()
                }),
                time: z.number(),
                memory: z.number(),
                checkerMessage: z
                    .object({
                        data: z.string(),
                        omittedLength: z.number()
                    })
                    .or(z.string())
            })
            .array()
    }),
    z.object({
        type: z.literal("status"),
        value: z.enum(["Accepted",
            "FileError",
            "RuntimeError",
            "TimeLimitExceeded",
            "MemoryLimitExceeded",
            "OutputLimitExceeded",
            "PartiallyCorrect",
            "WrongAnswer",
            "JudgementFailed"
        ])
    }),
    z.object({
        type: z.literal("score"),
        value: z.number()
    })
])
    .array();
 No newline at end of file
+43 −16
Original line number Diff line number Diff line
import { db } from '$lib/server/db'
import { redis } from '$lib/server/redis'
import type { contentSchema } from '$lib/shared/feedback.js'
import { TaskStatus } from '@prisma/client'
import { error, json } from '@sveltejs/kit'
import _ from 'lodash'
@@ -94,8 +95,6 @@ export const PUT = async ({ request, params }) => {
                result: JSON.stringify(data)
            }
        })


        const parsed = schema.safeParse(data)

        if (!parsed.success) {
@@ -108,7 +107,7 @@ export const PUT = async ({ request, params }) => {
        if (res.status === 'CompilationError') {
            const feedback = await db.submissionFeedback.create({
                data: {
                    score: res.score,
                    score: 0,
                    description: "Compile Error",
                    descriptionHTML: "",
                    content: [
@@ -116,7 +115,7 @@ export const PUT = async ({ request, params }) => {
                            type: "ansi",
                            value: res.compile.message
                        }
                    ],
                    ] as z.infer<typeof contentSchema>,
                    tasks: {
                        connect: [
                            {
@@ -131,25 +130,53 @@ export const PUT = async ({ request, params }) => {

            return json({ ok: true })
        }
        if (res.status === 'JudgementFailed') {

            return json({ ok: true })
        if (res.status === 'JudgementFailed' ||
            res.status === 'ConfigurationError' ||
            res.status === 'SystemError' ||
            res.status === 'FileError') {
            await db.submissionFeedback.create({
                data: {
                    score: 0,
                    description: res.status,
                    descriptionHTML: "",
                    content: [
                        {
                            type: "status",
                            value: res.status
                        },
                        {
                            type: "score",
                            value: 0
                        },
                    ] as z.infer<typeof contentSchema>,
                    tasks: {
                        connect: [
                            {
                                id: task.id
                            }
        if (res.status === 'ConfigurationError') {

            return json({ ok: true })
                        ]
                    },
                    submissionId: task.submissionId,
                    isValid: false
                }
        if (res.status === 'SystemError') {

            })
            return json({ ok: true })
        }

        const feedback = await db.submissionFeedback.create({
            data: {
                score: res.score,
                score: -1,
                description: res.status,
                descriptionHTML: "",
                content: [
                    {
                        type: "status",
                        value: res.status
                    },
                    {
                        type: "score",
                        value: res.score
                    },
                    {
                        type: "testcases",
                        value: _.entries(res.testcaseResult).map(([key, v]) => {
@@ -157,7 +184,7 @@ export const PUT = async ({ request, params }) => {
                            return data
                        })
                    }
                ],
                ] as z.infer<typeof contentSchema>,
                tasks: {
                    connect: [
                        {
+23 −35
Original line number Diff line number Diff line
@@ -12,44 +12,14 @@
	import _ from 'lodash';
	import Viewer from '$lib/components/file/viewer.svelte';
	import { browser, dev } from '$app/environment';
	import { z } from 'zod';
	import * as Accordion from '$lib/components/ui/accordion';
	import { contentSchema } from '$lib/shared/feedback';
	import MyAlert from '$lib/components/Alert.svelte';
	export let data: PageData;

	const { submission } = data;
	const { submitter, problem, feedback, task } = submission;
	const schema = z
		.discriminatedUnion('type', [
			z.object({
				type: z.literal('ansi'),
				value: z.string()
			}),
			z.object({
				type: z.literal('testcases'),
				value: z
					.object({
						status: z.string(),
						score: z.number(),
						testcaseInfo: z.object({
							timeLimit: z.number(),
							memoryLimit: z.number(),
							inputFile: z.string(),
							outputFile: z.string()
						}),
						time: z.number(),
						memory: z.number(),
						checkerMessage: z
							.object({
								data: z.string(),
								omittedLength: z.number()
							})
							.or(z.string())
					})
					.array()
			})
		])
		.array();
	const result = schema.safeParse(feedback?.content || '[]');
	const result = contentSchema.safeParse(feedback?.content || '[]');
</script>

<div class="h-full px-4 py-6 lg:px-8">
@@ -117,14 +87,32 @@
				<Alert.Title>No submission feedback yet</Alert.Title>
				<!-- <Alert.Description></Alert.Description> -->
			</Alert.Root>
		{:else}
			{#if feedback.score === -1}
				<MyAlert color="yellow">
					<div>
						<span class="font-medium">Notice</span> The final score is not undetermined.
					</div>
				</MyAlert>
			{:else}
				<div>Score: {feedback.score}</div>

			{/if}
			{#each result.data as item}
				{#if item.type === 'ansi'}
					<code class="whitespace-pre">
						{@html ansi_up.ansi_to_html(item.value)}
					</code>
				{:else if item.type === 'score'}
					<div>Score: {item.value}</div>
				{:else if item.type === 'status'}
					<div>Status: {item.value}</div>
					{#if item.value in ['JudgementFailed', 'ConfigurationError', 'SystemError', 'FileError', 'CompilationError']}
						<MyAlert color="blue">
							<div>
								This submission with {item.value} will not count towards the number of attempts.
							</div>
						</MyAlert>
					{/if}
				{:else}
					{@const testcases = item.value}
					<Accordion.Root>