[web] Recreate repos and start contest
This commit is contained in:
parent
87dd37c6a6
commit
85b1a48dd8
950
web/package-lock.json
generated
950
web/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -25,6 +25,7 @@
|
||||
"eslint-plugin-svelte3": "^4.0.0",
|
||||
"prettier": "^2.8.8",
|
||||
"prettier-plugin-svelte": "^2.10.0",
|
||||
"prisma-erd-generator": "^1.7.0",
|
||||
"svelte": "^3.58.0",
|
||||
"svelte-check": "^3.2.0",
|
||||
"tslib": "^2.5.0",
|
||||
@ -35,10 +36,12 @@
|
||||
"dependencies": {
|
||||
"@prisma/client": "^4.13.0",
|
||||
"@sveltejs/adapter-node": "^1.2.4",
|
||||
"@types/fs-extra": "^11.0.1",
|
||||
"axios": "^1.4.0",
|
||||
"bootstrap": "^5.2.3",
|
||||
"diff": "^5.1.0",
|
||||
"diff2html": "^3.4.35",
|
||||
"fs-extra": "^11.1.1",
|
||||
"highlight.js": "^11.8.0",
|
||||
"memfs": "^3.5.1",
|
||||
"node-git-server": "^1.0.0",
|
||||
|
1
web/prisma/ERD.svg
Normal file
1
web/prisma/ERD.svg
Normal file
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 43 KiB |
@ -2,6 +2,10 @@ generator client {
|
||||
provider = "prisma-client-js"
|
||||
}
|
||||
|
||||
generator erd {
|
||||
provider = "prisma-erd-generator"
|
||||
}
|
||||
|
||||
datasource db {
|
||||
provider = "postgresql"
|
||||
url = env("DATABASE_URL")
|
||||
|
@ -16,7 +16,7 @@ export function startGitServer() {
|
||||
const repoDir = 'repo';
|
||||
|
||||
repos = new Git(join(repoDir), {
|
||||
autoCreate: true,
|
||||
autoCreate: true
|
||||
});
|
||||
|
||||
repos.on('push', (push) => {
|
||||
|
@ -1,6 +1,9 @@
|
||||
import { error, redirect, type Actions } from '@sveltejs/kit';
|
||||
import type { PageServerLoad } from './$types';
|
||||
import { db } from '$lib/server/prisma';
|
||||
import fs from 'fs-extra';
|
||||
import { join } from 'path';
|
||||
import { createRepos } from '../util';
|
||||
|
||||
export const load = (async ({ params }) => {
|
||||
const contestId = parseInt(params.contestId);
|
||||
@ -9,7 +12,7 @@ export const load = (async ({ params }) => {
|
||||
}
|
||||
const contest = await db.contest.findUnique({
|
||||
where: { id: contestId },
|
||||
include: { problems: true, teams: true }
|
||||
include: { problems: true, teams: true, activeTeams: true }
|
||||
});
|
||||
if (!contest) {
|
||||
throw redirect(302, '/admin/contests');
|
||||
@ -17,11 +20,12 @@ export const load = (async ({ params }) => {
|
||||
return {
|
||||
name: contest.name,
|
||||
problems: contest.problems.map((problem) => {
|
||||
return { name: problem.friendlyName };
|
||||
return { id: problem.id, name: problem.friendlyName };
|
||||
}),
|
||||
teams: contest.teams.map((team) => {
|
||||
return { name: team.name };
|
||||
})
|
||||
return { id: team.id, name: team.name };
|
||||
}),
|
||||
activeTeams: contest.activeTeams.length
|
||||
};
|
||||
}) satisfies PageServerLoad;
|
||||
|
||||
@ -36,5 +40,68 @@ export const actions = {
|
||||
return { success: false };
|
||||
}
|
||||
throw redirect(302, '/admin/contests');
|
||||
},
|
||||
start: async ({ params }) => {
|
||||
if (!params.contestId) {
|
||||
return { success: false };
|
||||
}
|
||||
const contestId = parseInt(params.contestId);
|
||||
if (isNaN(contestId)) {
|
||||
return { success: false };
|
||||
}
|
||||
const contest = await db.contest.findUnique({
|
||||
where: { id: contestId },
|
||||
include: { activeTeams: true, teams: { include: { activeTeam: true } } }
|
||||
});
|
||||
if (
|
||||
!contest ||
|
||||
contest.teams.length === 0 ||
|
||||
contest.activeTeams.length !== 0 ||
|
||||
contest.teams.find((team) => {
|
||||
return team.activeTeam;
|
||||
})
|
||||
) {
|
||||
return { success: false };
|
||||
}
|
||||
|
||||
contest.teams.forEach(async (team) => {
|
||||
await db.activeTeam.create({ data: { teamId: team.id, contestId: contest.id } });
|
||||
});
|
||||
|
||||
return { success: true };
|
||||
},
|
||||
stop: async ({ params }) => {
|
||||
if (!params.contestId) {
|
||||
return { success: false };
|
||||
}
|
||||
const contestId = parseInt(params.contestId);
|
||||
if (isNaN(contestId)) {
|
||||
return { success: false };
|
||||
}
|
||||
const contest = await db.contest.findUnique({
|
||||
where: { id: contestId },
|
||||
include: { activeTeams: true }
|
||||
});
|
||||
if (!contest || contest.activeTeams.length === 0) {
|
||||
return { success: false };
|
||||
}
|
||||
contest.activeTeams.forEach(async (activeTeam) => {
|
||||
await db.activeTeam.delete({ where: { id: activeTeam.id } });
|
||||
});
|
||||
return { success: true };
|
||||
},
|
||||
repo: async ({ params }) => {
|
||||
if (!params.contestId) {
|
||||
return { success: false };
|
||||
}
|
||||
const contestId = parseInt(params.contestId);
|
||||
if (isNaN(contestId)) {
|
||||
return { success: false };
|
||||
}
|
||||
if (fs.existsSync(join('repo', contestId.toString()))) {
|
||||
fs.removeSync(join('repo', contestId.toString()));
|
||||
}
|
||||
await createRepos(contestId);
|
||||
return { success: true };
|
||||
}
|
||||
} satisfies Actions;
|
||||
|
@ -12,6 +12,10 @@
|
||||
|
||||
<h1 style="text-align:center" class="mb-4">{data.name}</h1>
|
||||
|
||||
{#if data.activeTeams !== 0}
|
||||
<div class="alert alert-success">In Progress</div>
|
||||
{/if}
|
||||
|
||||
{#if form && !form.success}
|
||||
<div class="alert alert-danger">An error occured</div>
|
||||
{/if}
|
||||
@ -20,11 +24,9 @@
|
||||
<div class="col-6">
|
||||
<a href="/admin/contests" class="btn btn-outline-primary">All Contests</a>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<div class="text-end">
|
||||
<div class="col-6 text-end">
|
||||
<form
|
||||
method="POST"
|
||||
action="?/delete"
|
||||
use:enhance={({ cancel }) => {
|
||||
if (!confirm('Are you sure?')) {
|
||||
cancel();
|
||||
@ -34,18 +36,25 @@
|
||||
};
|
||||
}}
|
||||
>
|
||||
<button type="submit" class="btn btn-danger">Delete</button>
|
||||
{#if data.activeTeams === 0}
|
||||
<button type="submit" formaction="?/delete" class="btn btn-danger">Delete</button>
|
||||
<button type="submit" formaction="?/repo" class="btn btn-warning">Recreate Repos</button>
|
||||
<button type="submit" formaction="?/start" class="btn btn-success">Start</button>
|
||||
{:else}
|
||||
<button type="submit" formaction="?/stop" class="btn btn-outline-danger">Stop</button>
|
||||
{/if}
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mt-3 row">
|
||||
<div class="col-6">
|
||||
<h4>Teams</h4>
|
||||
<div class="list-group">
|
||||
{#each data.teams as team}
|
||||
<div class="list-group-item">{team.name}</div>
|
||||
<a href={`/admin/teams/${team.id}`} class="list-group-item list-group-item-action"
|
||||
>{team.name}</a
|
||||
>
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
@ -53,7 +62,9 @@
|
||||
<h4>Problems</h4>
|
||||
<div class="list-group">
|
||||
{#each data.problems as problem}
|
||||
<div class="list-group-item">{problem.name}</div>
|
||||
<a href={`/admin/problems/${problem.id}`} class="list-group-item list-group-item-action"
|
||||
>{problem.name}</a
|
||||
>
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
|
@ -3,6 +3,7 @@ import path, { join } from 'path';
|
||||
import type { Actions, PageServerLoad } from './$types';
|
||||
import fs from 'fs';
|
||||
import { simpleGit } from 'simple-git';
|
||||
import { createRepos } from '../util';
|
||||
|
||||
export const load = (async () => {
|
||||
const teams = await db.team.findMany();
|
||||
@ -63,35 +64,8 @@ export const actions = {
|
||||
include: { teams: true, problems: true }
|
||||
});
|
||||
|
||||
// Create repos
|
||||
await createRepos(createdContest.id);
|
||||
|
||||
if (fs.existsSync('temp')) {
|
||||
fs.rmSync('temp', { recursive: true });
|
||||
}
|
||||
fs.mkdirSync('temp');
|
||||
createdContest.teams.forEach(async (team) => {
|
||||
fs.mkdirSync(join('temp', team.id.toString()));
|
||||
const git = simpleGit({ baseDir: join('temp', team.id.toString()) });
|
||||
await git.init();
|
||||
await git.checkoutLocalBranch('master');
|
||||
createdContest.problems.forEach((problem) => {
|
||||
fs.mkdirSync(join('temp', team.id.toString(), problem.pascalName));
|
||||
fs.writeFileSync(
|
||||
join('temp', team.id.toString(), problem.pascalName, problem.pascalName + '.java'),
|
||||
`public class ${problem.pascalName} {
|
||||
public static void main(String[] args) {
|
||||
System.out.println("Hello ${problem.pascalName}!");
|
||||
}
|
||||
}`
|
||||
);
|
||||
});
|
||||
await git.add('.');
|
||||
await git.commit('Initial', { '--author': 'Admin <>' });
|
||||
await git.push(
|
||||
'http://localhost:7006/' + createdContest.id.toString() + '/' + team.id.toString(),
|
||||
'master'
|
||||
);
|
||||
});
|
||||
return { success: true };
|
||||
}
|
||||
} satisfies Actions;
|
||||
|
41
web/src/routes/admin/contests/util.ts
Normal file
41
web/src/routes/admin/contests/util.ts
Normal file
@ -0,0 +1,41 @@
|
||||
import { db } from '$lib/server/prisma';
|
||||
import fs from 'fs-extra';
|
||||
import { join } from 'path';
|
||||
import simpleGit from 'simple-git';
|
||||
|
||||
export async function createRepos(contestId: number) {
|
||||
if (fs.existsSync('temp')) {
|
||||
fs.rmSync('temp', { recursive: true });
|
||||
}
|
||||
fs.mkdirSync('temp');
|
||||
const contest = await db.contest.findUnique({
|
||||
where: { id: contestId },
|
||||
include: { teams: true, problems: true }
|
||||
});
|
||||
if (!contest) {
|
||||
return;
|
||||
}
|
||||
contest.teams.forEach(async (team) => {
|
||||
fs.mkdirSync(join('temp', team.id.toString()));
|
||||
const git = simpleGit({ baseDir: join('temp', team.id.toString()) });
|
||||
await git.init();
|
||||
await git.checkoutLocalBranch('master');
|
||||
contest.problems.forEach((problem) => {
|
||||
fs.mkdirSync(join('temp', team.id.toString(), problem.pascalName));
|
||||
fs.writeFileSync(
|
||||
join('temp', team.id.toString(), problem.pascalName, problem.pascalName + '.java'),
|
||||
`public class ${problem.pascalName} {
|
||||
public static void main(String[] args) {
|
||||
System.out.println("Hello ${problem.pascalName}!");
|
||||
}
|
||||
}`
|
||||
);
|
||||
});
|
||||
await git.add('.');
|
||||
await git.commit('Initial', { '--author': 'Admin <>' });
|
||||
await git.push(
|
||||
'http://localhost:7006/' + contest.id.toString() + '/' + team.id.toString(),
|
||||
'master'
|
||||
);
|
||||
});
|
||||
}
|
@ -38,7 +38,7 @@
|
||||
|
||||
<div class="row">
|
||||
<div class="col-6">
|
||||
<a href="/admin/problems" class="btn btn-outline-primary">Back</a>
|
||||
<a href="/admin/problems" class="btn btn-outline-primary">All Problems</a>
|
||||
</div>
|
||||
<div class="col-6 text-end">
|
||||
<button on:click={deleteProblem} type="button" class="btn btn-danger">Delete</button>
|
||||
|
Loading…
Reference in New Issue
Block a user