diff --git a/src/taskmaster.ts b/src/taskmaster.ts index c3d871f..cf63298 100644 --- a/src/taskmaster.ts +++ b/src/taskmaster.ts @@ -4,7 +4,9 @@ import * as amqp from 'amqplib/callback_api' import {Connection} from 'amqplib/callback_api' import { execute } from './tasks' import config = require('../config.js') -import { SubmitJob, RunJob } from 'tasks/job'; +import {SubmitJob} from './tasks/jobs/submission'; +import {ProjectJob} from './tasks/jobs/project'; +import {RunJob} from './tasks/jobs/run'; import { mkdir } from 'shelljs' // =============== Setup Raven @@ -41,6 +43,9 @@ amqp.connect(`amqp://${config.AMQP.USER}:${config.AMQP.PASS}@${config.AMQP.HOST} case 'run': job = new RunJob(payload) break + case 'project': + job = new ProjectJob(payload) + break default: throw new Error("Scenario not declared") } diff --git a/src/tasks/index.ts b/src/tasks/index.ts index 0a8739d..7e1744c 100644 --- a/src/tasks/index.ts +++ b/src/tasks/index.ts @@ -1,14 +1,19 @@ -import { Result, RunResult, SubmissionResult } from 'types/result' +import { Result, RunResult, SubmissionResult, ProjectResult } from 'types/result' import config = require('../../config.js') import {exec, mkdir, rm} from 'shelljs' import * as path from 'path' import RunScenario from './scenarios/run' import SubmissionScenario from './scenarios/submission' -import { RunJob, SubmitJob, Job } from "./job"; +import ProjectScenario from './scenarios/project' +import {Job } from './job' +import {RunJob} from './jobs/run' +import {SubmitJob} from './jobs/submission'; +import {ProjectJob} from './jobs/project'; export function execute(job: RunJob): Promise export function execute(job: SubmitJob): Promise +export function execute(job: ProjectJob): Promise export async function execute (job: Job) { // Create RUNBOX const currentJobDir = path.join(config.RUNBOX.DIR, job.id.toString()) @@ -19,6 +24,8 @@ export async function execute (job: Job) { scenario = new RunScenario() } else if (job instanceof SubmitJob) { scenario = new SubmissionScenario() + } else if (job instanceof ProjectJob) { + scenario = new ProjectScenario() } // Setup RUNBOX diff --git a/src/tasks/job.ts b/src/tasks/job.ts index b2ccf33..45a426a 100644 --- a/src/tasks/job.ts +++ b/src/tasks/job.ts @@ -1,25 +1,10 @@ -interface JobConstructorOpts { +export interface JobConstructorOpts { id: number source: string lang: string scenario: "run" | "submit" | "project" timelimit?: number } -interface RunJobConstructorOpts extends JobConstructorOpts { - stdin: string -} -interface TestcaseOpts { - id: number, - input: string, - output: string -} -interface SubmitJobConstructorOpts extends JobConstructorOpts { - testcases: Array -} - -interface ProjectConstructorOpts extends JobConstructorOpts { - problem: string -} export class Job { id: number @@ -37,29 +22,4 @@ export class Job { } } -export class RunJob extends Job { - stdin: string - - constructor({ id, source, lang, timelimit, scenario, stdin }: RunJobConstructorOpts) { - super({id, source, lang, timelimit, scenario}) - this.stdin = stdin - } -} -export class SubmitJob extends Job { - testcases: Array - - constructor({ id, source, lang, timelimit, scenario, testcases }: SubmitJobConstructorOpts) { - super({id, source, lang, timelimit, scenario}) - this.testcases = testcases - } -} - -export class ProjectJob extends Job { - problem: string - - constructor({ id, source, lang, timelimit, scenario, problem}: ProjectConstructorOpts) { - super({ id, source, lang, timelimit, scenario}) - this.problem = problem - } -} diff --git a/src/tasks/jobs/project.ts b/src/tasks/jobs/project.ts new file mode 100644 index 0000000..0734737 --- /dev/null +++ b/src/tasks/jobs/project.ts @@ -0,0 +1,16 @@ +import {Job, JobConstructorOpts} from '../job'; + +interface ProjectConstructorOpts extends JobConstructorOpts { + problem: string, + submissionDirs: string +} +export class ProjectJob extends Job { + problem: string + submissionDirs: string + + constructor({ id, source, lang, timelimit, scenario, problem, submissionDirs}: ProjectConstructorOpts) { + super({ id, source, lang, timelimit, scenario}) + this.problem = problem + this.submissionDirs = submissionDirs + } +} diff --git a/src/tasks/jobs/run.ts b/src/tasks/jobs/run.ts new file mode 100644 index 0000000..b8ae888 --- /dev/null +++ b/src/tasks/jobs/run.ts @@ -0,0 +1,14 @@ +import {Job, JobConstructorOpts} from '../job'; + +interface RunJobConstructorOpts extends JobConstructorOpts { + stdin: string +} + +export class RunJob extends Job { + stdin: string + + constructor({ id, source, lang, timelimit, scenario, stdin }: RunJobConstructorOpts) { + super({id, source, lang, timelimit, scenario}) + this.stdin = stdin + } +} \ No newline at end of file diff --git a/src/tasks/jobs/submission.ts b/src/tasks/jobs/submission.ts new file mode 100644 index 0000000..1b0239b --- /dev/null +++ b/src/tasks/jobs/submission.ts @@ -0,0 +1,20 @@ +import {Job, JobConstructorOpts} from '../job'; + +interface TestcaseOpts { + id: number, + input: string, + output: string +} + +interface SubmitJobConstructorOpts extends JobConstructorOpts { + testcases: Array +} + +export class SubmitJob extends Job { + testcases: Array + + constructor({ id, source, lang, timelimit, scenario, testcases }: SubmitJobConstructorOpts) { + super({id, source, lang, timelimit, scenario}) + this.testcases = testcases + } +} diff --git a/src/tasks/scenarios/project.ts b/src/tasks/scenarios/project.ts index aa68084..d944d0c 100644 --- a/src/tasks/scenarios/project.ts +++ b/src/tasks/scenarios/project.ts @@ -1,32 +1,74 @@ import config = require('../../../config.js') -import {cat, exec, mkdir, rm, touch, head} from 'shelljs' -import { ProjectJob } from 'tasks/job' +import { cat, exec, mkdir} from 'shelljs' +import { ProjectJob } from '../jobs/project' import { ProjectResult } from 'types/result' import * as path from 'path' -import * as fs from 'fs' import { Scenario } from 'tasks/scenario' import { download } from 'utils/request' export default class ProjectScenario extends Scenario { async setup(currentJobDir: string, job: ProjectJob) { - // TODO - const problemDir = path.join(currentJobDir, job.problem) - await download(job.problem, problemDir) + const problemZipDir = path.join(currentJobDir, 'problem.zip') + const solutionZipDir = path.join(currentJobDir, 'solution.zip') + await download(job.problem, problemZipDir) + await download(job.source, solutionZipDir) - const solutionDir = path.join(currentJobDir, job.source) - await download(job.problem, solutionDir) + const problemDir = path.join(currentJobDir, 'problem') + mkdir('-p', problemDir) + exec(`unzip ${problemZipDir} -d ${problemDir}`) + + const solutionDir = path.join(currentJobDir, 'solution') + mkdir('-p', solutionDir) + exec(`unzip ${solutionZipDir} -d ${solutionDir}`) + } + + run(currentJobDir: string, job: ProjectJob) { + const PROJECT_CONFIG = config.PROJECT[job.lang] + return exec(`docker run \\ + --cpus="${PROJECT_CONFIG.CPU_SHARE}" \\ + --memory="${PROJECT_CONFIG.MEM_LIMIT}" \\ + --rm \\ + -v "${currentJobDir}":/usr/src/runbox \\ + -w /usr/src/runbox codingblocks/project-worker-"${job.lang}" \\ + /bin/judge.sh -s "${job.submissionDirs}" + `); } async result(currentJobDir: string, job: ProjectJob): Promise { - // TODO + const result_code = cat(path.join(currentJobDir, 'result.code')).toString() + if (result_code === '25') { + //problem hash and solution hash were not equal + return { + id: job.id, + stderr: cat(path.join(currentJobDir, 'result.stderr')).toString(), + stdout: '', + code: parseInt(result_code), + time: 0, + score: 0 + } + } + + const build_stderr = cat(path.join(currentJobDir, 'build.stderr')).toString() + const result_time = cat(path.join(currentJobDir, 'result.time').toString()) || '0' + + if (build_stderr) { + return { + id: job.id, + stderr: build_stderr, + stdout: '', + code: parseInt(result_code), + time: parseFloat(result_time), + score: 0 + } + } return { id: job.id, - stderr: '', - stdout: '', - time: 0, - code: 0, - score: 0 + stderr: cat((path.join(currentJobDir, 'run.stderr')).toString()), + stdout: cat(path.join(currentJobDir, 'run.stdout')).toString(), + code: parseInt(result_code), + time: parseFloat(result_time), + score: parseInt(result_code) === 0 ? 100 : 0 } } } diff --git a/src/tasks/scenarios/run.ts b/src/tasks/scenarios/run.ts index 53b32ab..2ee538d 100644 --- a/src/tasks/scenarios/run.ts +++ b/src/tasks/scenarios/run.ts @@ -1,6 +1,6 @@ import config = require('../../../config.js') -import {cat, exec, mkdir, rm, touch, head} from 'shelljs' -import { RunJob } from '../job' +import { cat, exec, mkdir, rm, touch, head } from 'shelljs' +import { RunJob} from '../jobs/run' import { RunResult } from 'types/result' import * as path from 'path' import * as fs from 'fs' diff --git a/src/tasks/scenarios/submission.ts b/src/tasks/scenarios/submission.ts index c805b1d..09e1e7f 100644 --- a/src/tasks/scenarios/submission.ts +++ b/src/tasks/scenarios/submission.ts @@ -1,6 +1,6 @@ import config = require('../../../config.js') import { cat, ls, mkdir, exec } from 'shelljs' -import { SubmitJob } from 'tasks/job' +import { SubmitJob } from '../jobs/submission' import { SubmissionResult } from 'types/result' import * as path from 'path' import * as fs from 'fs' diff --git a/test/run/run.c.spec.ts b/test/run/run.c.spec.ts index 3010a36..cd6e657 100644 --- a/test/run/run.c.spec.ts +++ b/test/run/run.c.spec.ts @@ -1,6 +1,7 @@ import {execute} from '../../src/tasks/' import {expect} from 'chai' -import { RunJob } from '../../src/tasks/job' +import {RunJob} from '../../src/tasks/jobs/run' + describe('run - c', () => { it('.c file runs correctly', async () => { const runResult = await execute(new RunJob({ diff --git a/test/run/run.cpp.spec.ts b/test/run/run.cpp.spec.ts index 8987b7b..ae02820 100644 --- a/test/run/run.cpp.spec.ts +++ b/test/run/run.cpp.spec.ts @@ -1,6 +1,7 @@ import {execute} from '../../src/tasks/' import {expect} from 'chai' -import { RunJob } from '../../src/tasks/job' +import {RunJob} from '../../src/tasks/jobs/run' + describe('run - cpp', () => { it('.cpp file runs correctly', async () => { diff --git a/test/run/run.csharp.spec.ts b/test/run/run.csharp.spec.ts index 6cb50b2..852363d 100644 --- a/test/run/run.csharp.spec.ts +++ b/test/run/run.csharp.spec.ts @@ -1,6 +1,7 @@ import {execute} from '../../src/tasks/' import {expect} from 'chai' -import { RunJob } from '../../src/tasks/job' +import {RunJob} from '../../src/tasks/jobs/run' + describe('run - csharp', () => { it('.cs file runs correctly', async () => { diff --git a/test/run/run.java8.spec.ts b/test/run/run.java8.spec.ts index 2017918..2083a0c 100644 --- a/test/run/run.java8.spec.ts +++ b/test/run/run.java8.spec.ts @@ -1,6 +1,7 @@ import {execute} from '../../src/tasks/' import {expect} from 'chai' -import { RunJob } from '../../src/tasks/job' +import {RunJob} from '../../src/tasks/jobs/run' + describe('run - java8', () => { it('.java file runs correctly (Java8)', async () => { diff --git a/test/run/run.nodejs10.spec.ts b/test/run/run.nodejs10.spec.ts index 50a90b1..d441947 100644 --- a/test/run/run.nodejs10.spec.ts +++ b/test/run/run.nodejs10.spec.ts @@ -1,6 +1,7 @@ import {execute} from '../../src/tasks/' import {expect} from 'chai' -import { RunJob } from '../../src/tasks/job' +import {RunJob} from '../../src/tasks/jobs/run' + describe('run - nodejs10', () => { it('.js file runs correctly (NodeJS 6)', async () => { const runResult = await execute(new RunJob({ diff --git a/test/run/run.nodejs8.spec.ts b/test/run/run.nodejs8.spec.ts index f55bb4b..42e5212 100644 --- a/test/run/run.nodejs8.spec.ts +++ b/test/run/run.nodejs8.spec.ts @@ -1,6 +1,7 @@ import {execute} from '../../src/tasks/' import {expect} from 'chai' -import { RunJob } from '../../src/tasks/job' +import {RunJob} from '../../src/tasks/jobs/run' + describe('run - nodejs8', () => { it('.js file runs correctly (NodeJS 8)', async () => { diff --git a/test/run/run.py2.spec.ts b/test/run/run.py2.spec.ts index 27a0d91..3e92d37 100644 --- a/test/run/run.py2.spec.ts +++ b/test/run/run.py2.spec.ts @@ -1,6 +1,7 @@ import {execute} from '../../src/tasks/' import {expect} from 'chai' -import { RunJob } from '../../src/tasks/job' +import {RunJob} from '../../src/tasks/jobs/run' + describe('run - py2', () => { it('.py file runs correctly (Python 2.7)', async () => { diff --git a/test/run/run.py3.spec.ts b/test/run/run.py3.spec.ts index 40f3a41..0a436dd 100644 --- a/test/run/run.py3.spec.ts +++ b/test/run/run.py3.spec.ts @@ -1,6 +1,7 @@ import {execute} from '../../src/tasks/' import {expect} from 'chai' -import { RunJob } from '../../src/tasks/job' +import {RunJob} from '../../src/tasks/jobs/run' + describe('run - py3', () => { it('.py file runs correctly (Python 3.0)', async () => { diff --git a/test/run/run.ruby.spec.ts b/test/run/run.ruby.spec.ts index 6358584..e60170f 100644 --- a/test/run/run.ruby.spec.ts +++ b/test/run/run.ruby.spec.ts @@ -1,6 +1,7 @@ import {execute} from '../../src/tasks/' import {expect} from 'chai' -import { RunJob } from '../../src/tasks/job' +import {RunJob} from '../../src/tasks/jobs/run' + describe('run - ruby', () => { it('.rb file runs correctly', async () => { diff --git a/test/scenarios/projectScenario.spec.ts b/test/scenarios/projectScenario.spec.ts index 710d7be..92a8fb3 100644 --- a/test/scenarios/projectScenario.spec.ts +++ b/test/scenarios/projectScenario.spec.ts @@ -1,16 +1,16 @@ import { expect } from 'chai' -import { ProjectJob } from '../../src/tasks/job' +import { ProjectJob } from '../../src/tasks/jobs/project'; import ProjectScenarion from '../../src/tasks/scenarios/project' describe('Project Scenario', () => { it('should setup', async () => { - const job: ProjectJob = { - id: 1, - source: '', - lang: 'nodejs', - timelimit: 20, - scenario: 'problem', - problem: '' - } + // const job: ProjectJob = { + // id: 1, + // source: '', + // lang: 'nodejs', + // timelimit: 20, + // scenario: 'problem', + // problem: '' + // } }) }) diff --git a/test/scenarios/runScenario.spec.ts b/test/scenarios/runScenario.spec.ts index 172a16e..ae1896d 100644 --- a/test/scenarios/runScenario.spec.ts +++ b/test/scenarios/runScenario.spec.ts @@ -3,7 +3,7 @@ import { mkdir, rm } from 'shelljs' import RunScenario from '../../src/tasks/scenarios/run' import config = require('../../config.js') import * as path from 'path' -import { RunJob } from '../../src/tasks/job' +import {RunJob} from '../../src/tasks/jobs/run' import * as fs from 'fs' describe('Run Scenario', () => { diff --git a/test/scenarios/submissionScenario.spec.ts b/test/scenarios/submissionScenario.spec.ts index 86e5ad6..303830a 100644 --- a/test/scenarios/submissionScenario.spec.ts +++ b/test/scenarios/submissionScenario.spec.ts @@ -4,7 +4,7 @@ import { mkdir, rm } from 'shelljs' import config = require('../../config.js') import * as path from 'path' import SubmissionScenario from '../../src/tasks/scenarios/submission' -import { SubmitJob } from '../../src/tasks/job' +import { SubmitJob } from '../../src/tasks/jobs/submission' describe('Submission Scenario', () => { it('should setup', async () => { diff --git a/test/submission/submit.c.spec.ts b/test/submission/submit.c.spec.ts index e42c72a..ce8018a 100644 --- a/test/submission/submit.c.spec.ts +++ b/test/submission/submit.c.spec.ts @@ -1,6 +1,6 @@ import { execute } from '../../src/tasks/' import { expect } from 'chai' -import { SubmitJob } from '../../src/tasks/job' +import { SubmitJob } from "../../src/tasks/jobs/submission" import { SubmissionResult } from '../../src/types/result' describe('submit - c', () => { diff --git a/test/submission/submit.cpp.spec.ts b/test/submission/submit.cpp.spec.ts index 39bd8c4..dce6063 100644 --- a/test/submission/submit.cpp.spec.ts +++ b/test/submission/submit.cpp.spec.ts @@ -1,6 +1,6 @@ import { execute } from '../../src/tasks/' import { expect } from 'chai' -import { SubmitJob } from '../../src/tasks/job' +import { SubmitJob } from "../../src/tasks/jobs/submission" import { SubmissionResult } from '../../src/types/result' describe('submit - cpp', () => { diff --git a/test/submission/submit.csharp.spec.ts b/test/submission/submit.csharp.spec.ts index 7bc2ed8..0593a5e 100644 --- a/test/submission/submit.csharp.spec.ts +++ b/test/submission/submit.csharp.spec.ts @@ -1,6 +1,6 @@ import { execute } from '../../src/tasks/' import { expect } from 'chai' -import { SubmitJob } from '../../src/tasks/job' +import { SubmitJob } from "../../src/tasks/jobs/submission" import { SubmissionResult } from '../../src/types/result' describe('submit - csharp', () => { diff --git a/test/submission/submit.java8.spec.ts b/test/submission/submit.java8.spec.ts index 87d175b..56434c2 100644 --- a/test/submission/submit.java8.spec.ts +++ b/test/submission/submit.java8.spec.ts @@ -1,6 +1,6 @@ import { execute } from '../../src/tasks/' import { expect } from 'chai' -import { SubmitJob } from '../../src/tasks/job' +import { SubmitJob } from "../../src/tasks/jobs/submission" import { SubmissionResult } from '../../src/types/result' describe('submit - java8', () => { diff --git a/test/submission/submit.nodejs10.spec.ts b/test/submission/submit.nodejs10.spec.ts index f7df9f1..204a443 100644 --- a/test/submission/submit.nodejs10.spec.ts +++ b/test/submission/submit.nodejs10.spec.ts @@ -1,6 +1,6 @@ import { execute } from '../../src/tasks/' import { expect } from 'chai' -import { SubmitJob } from '../../src/tasks/job' +import { SubmitJob } from "../../src/tasks/jobs/submission" import { SubmissionResult } from '../../src/types/result' describe('submit - nodejs10', () => { diff --git a/test/submission/submit.nodejs8.spec.ts b/test/submission/submit.nodejs8.spec.ts index 9ecf188..c80cf29 100644 --- a/test/submission/submit.nodejs8.spec.ts +++ b/test/submission/submit.nodejs8.spec.ts @@ -1,6 +1,6 @@ import { execute } from '../../src/tasks/' import { expect } from 'chai' -import { SubmitJob } from '../../src/tasks/job' +import { SubmitJob } from "../../src/tasks/jobs/submission" import { SubmissionResult } from '../../src/types/result' describe('submit - nodejs8', () => { diff --git a/test/submission/submit.py2.spec.ts b/test/submission/submit.py2.spec.ts index 9e260f2..e568eef 100644 --- a/test/submission/submit.py2.spec.ts +++ b/test/submission/submit.py2.spec.ts @@ -1,6 +1,6 @@ import { execute } from '../../src/tasks/' import { expect } from 'chai' -import { SubmitJob } from '../../src/tasks/job' +import { SubmitJob } from "../../src/tasks/jobs/submission" import { SubmissionResult } from '../../src/types/result' describe('submit - py2', () => { diff --git a/test/submission/submit.py3.spec.ts b/test/submission/submit.py3.spec.ts index 9898431..6695fdb 100644 --- a/test/submission/submit.py3.spec.ts +++ b/test/submission/submit.py3.spec.ts @@ -1,6 +1,6 @@ import { execute } from '../../src/tasks/' import { expect } from 'chai' -import { SubmitJob } from '../../src/tasks/job' +import { SubmitJob } from "../../src/tasks/jobs/submission" import { SubmissionResult } from '../../src/types/result' describe('submit - py3', () => { diff --git a/test/submission/submit.ruby.spec.ts b/test/submission/submit.ruby.spec.ts index c5c5702..51762b4 100644 --- a/test/submission/submit.ruby.spec.ts +++ b/test/submission/submit.ruby.spec.ts @@ -1,6 +1,6 @@ import { execute } from '../../src/tasks/' import { expect } from 'chai' -import { SubmitJob } from '../../src/tasks/job' +import { SubmitJob } from "../../src/tasks/jobs/submission" import { SubmissionResult } from '../../src/types/result' describe('submit - ruby', () => {