Restructure submissions

This commit is contained in:
orosmatthew 2023-04-29 13:21:23 -04:00
parent bf830b0849
commit 9a9315c5aa
5 changed files with 96 additions and 23 deletions

View File

@ -8,10 +8,10 @@ datasource db {
}
model User {
id Int @id @default(autoincrement())
username String @unique
password String
sessions Session[]
id Int @id @default(autoincrement())
username String @unique
password String
Submission Session[]
}
model Session {
@ -31,21 +31,26 @@ model Submission {
id Int @id @default(autoincrement())
createdAt DateTime @default(now())
state SubmissionState
expectedOutput String
actualOutput String
message String?
team Team @relation(fields: [teamId], references: [id])
teamId Int
problem Problem @relation(fields: [problemId], references: [id])
problemId Int
}
model Problem {
id Int @id @default(autoincrement())
friendlyName String @unique
id Int @id @default(autoincrement())
friendlyName String @unique
sampleInput String
sampleOutput String
realInput String
realOutput String
Submission Submission[]
}
model Team {
id Int @id @default(autoincrement())
name String @unique
id Int @id @default(autoincrement())
name String @unique
Submission Submission[]
}

View File

@ -1,5 +1,9 @@
<script lang="ts">
import 'bootstrap/dist/css/bootstrap.min.css';
import { onMount } from 'svelte';
onMount(async () => {
await import('bootstrap');
});
</script>
<body class="container">

View File

@ -12,10 +12,14 @@ export const load = (async ({ params }) => {
if (!submission) {
throw redirect(302, '/admin/reviews');
}
const problem = await db.problem.findUnique({ where: { id: submission.problemId } });
if (!problem) {
throw error(500, 'Invalid problem');
}
let diff = Diff.createTwoFilesPatch(
'expected',
'actual',
submission.expectedOutput,
problem.realOutput,
submission.actualOutput
);
return { diff: diff };

View File

@ -3,13 +3,18 @@ import { SubmissionState } from '@prisma/client';
import type { Actions, PageServerLoad } from './$types';
export const load = (async () => {
const query = await db.submission.findMany({ where: { state: SubmissionState.InReview } });
query.sort((a, b) => {
return a.createdAt.valueOf() - b.createdAt.valueOf();
});
const submissions = await db.submission.findMany({ where: { state: SubmissionState.InReview } });
const teams = await db.team.findMany();
const problems = await db.problem.findMany();
return {
reviewList: query.map((row) => {
reviewList: submissions.map((row) => {
return { id: row.id, createdAt: row.createdAt };
}),
teams: teams.map((row) => {
return { id: row.id, name: row.name };
}),
problems: problems.map((row) => {
return { id: row.id, name: row.friendlyName };
})
};
}) satisfies PageServerLoad;
@ -17,20 +22,32 @@ export const load = (async () => {
export const actions = {
submission: async ({ request }) => {
const data = await request.formData();
const expected = data.get('expected');
const teamId = data.get('teamId');
const problemId = data.get('problemId');
const actual = data.get('actual');
if (!expected || !actual) {
if (!teamId || !problemId || !actual) {
return { success: false };
}
if (expected.toString() === actual.toString()) {
const problemIdInt = parseInt(problemId.toString());
const teamIdInt = parseInt(teamId.toString());
if (isNaN(problemIdInt) || isNaN(teamIdInt)) {
return { success: false };
}
const problem = await db.problem.findUnique({ where: { id: problemIdInt } });
if (!problem) {
return { success: false };
}
if (problem.realOutput === actual.toString()) {
return { success: true };
}
await db.submission.create({
data: {
state: SubmissionState.InReview,
expectedOutput: expected.toString(),
actualOutput: actual.toString()
actualOutput: actual.toString(),
teamId: teamIdInt,
problemId: problemIdInt
}
});
return { success: true };
}
} satisfies Actions;

View File

@ -4,6 +4,9 @@
export let data: PageData;
export let form: ActionData;
let selectedTeam: (typeof data.teams)[0] | null;
let selectedProblem: (typeof data.problems)[0] | null;
</script>
<svelte:head>
@ -30,15 +33,55 @@
{/if}
<form method="POST" action="?/submission" use:enhance>
<div class="row">
<div class="col-6">
<h5>Expected output (real data)</h5>
<textarea name="expected" class="form-control" />
<div class="col-3">
<h5>Team</h5>
<div class="dropdown">
<button class="btn btn-secondary dropdown-toggle" type="button" data-bs-toggle="dropdown">
{selectedTeam ? selectedTeam.name : 'Select Team'}
</button>
<ul class="dropdown-menu">
{#each data.teams as team}
<li>
<button
on:click={() => {
selectedTeam = team;
}}
type="button"
class="dropdown-item">{team.name}</button
>
</li>
{/each}
</ul>
</div>
</div>
<div class="col-3">
<h5>Problem</h5>
<div class="dropdown">
<button class="btn btn-secondary dropdown-toggle" type="button" data-bs-toggle="dropdown">
{selectedProblem ? selectedProblem.name : 'Select Problem'}
</button>
<ul class="dropdown-menu">
{#each data.problems as problem}
<li>
<button
on:click={() => {
selectedProblem = problem;
}}
type="button"
class="dropdown-item">{problem.name}</button
>
</li>
{/each}
</ul>
</div>
</div>
<div class="col-6">
<h5>Actual output (like from student output)</h5>
<textarea name="actual" class="form-control" />
</div>
</div>
<input name="teamId" type="hidden" value={selectedTeam ? selectedTeam.id : ''} />
<input name="problemId" type="hidden" value={selectedProblem ? selectedProblem.id : ''} />
<div class="row justify-content-end">
<div class="text-end">
<button type="submit" class="mt-3 btn btn-secondary">Submit</button>