Skip to content

Commit

Permalink
feat: add experimental output only judge
Browse files Browse the repository at this point in the history
  • Loading branch information
seo-rii committed Dec 29, 2021
1 parent 3cee25a commit 19de162
Show file tree
Hide file tree
Showing 10 changed files with 166 additions and 64 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
"name": "hana",
"version": "1.0.0",
"dependencies": {
"body-parser": "^1.19.1",
"express": "^4.17.2",
"express-ws": "^5.0.2",
"serve-favicon": "^2.5.0",
Expand Down
39 changes: 33 additions & 6 deletions res/test.html
Original file line number Diff line number Diff line change
Expand Up @@ -126,16 +126,24 @@
tws.onmessage = function (event) {
const res = JSON.parse(event.data)
if (res.type === 'JUDGE_FINISH')
setCard(res.data.uid, 1, res.data.reason)
setCard(
res.data.uid,
1,
`${reasonString[res.data.reason]} / ${
(res.data.result.reduce((a, b) => a + b, 0) /
2) *
100
}%`
)
if (res.type === 'JUDGE_PROGRESS')
setCard(
res.data.uid,
res.data.progress,
res.data.reason
reasonString[res.data.reason]
)
if (res.type === 'JUDGE_STATUS') {
for (let i of res.data.waitList) {
setCard(i, 0, 'PD')
setCard(i, 0, reasonString['PD'])
}
}
}
Expand All @@ -148,8 +156,7 @@
let card = document.getElementById(`card-${id}`)
if (!card) card = addCard(id)
if (progress === 1) card.classList.add('success')
document.getElementById(`subtitle-${id}`).innerText =
reasonString[reason]
document.getElementById(`subtitle-${id}`).innerText = reason
setTimeout(() => {
mdcProgress[id].foundation.setProgress(progress)
}, 1)
Expand Down Expand Up @@ -189,7 +196,27 @@
}

function test() {
fetch(`//${window.location.host}/judge`)
fetch(`//${window.location.host}/judge`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
language: 'TEXT',
judgeType: 'OutputOnly',
source: [
{
name: '1',
source: '123',
},
],
dataSet: {
data: [{ output: '123' }, { output: '456' }],
},
timeLimit: 0,
memoryLimit: 0,
}),
})
}

document.addEventListener('DOMContentLoaded', () => {
Expand Down
39 changes: 29 additions & 10 deletions src/app.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,36 @@
import express from 'express'
import expressWs from 'express-ws'
import { v4 as uuid } from 'uuid'
import { init } from './socket'
import { requestJudge } from './judge'
import { Problem } from './types/problem'
import {v4 as uuid} from 'uuid'
import {init} from './socket'
import {requestJudge} from './judge'
import {JudgeRequest, SourceFile} from "./types/request";

import bodyParser from "body-parser";
import favicon from 'serve-favicon'
import path from 'path'

const app = expressWs(express()).app
init(app)
app.use(bodyParser.json())

app.get('/judge', (req, res) => {
const problem = {
uid: uuid(),
} as Problem
requestJudge(problem)
res.send({ success: true, uid: problem.uid })
app.post('/judge', (req, res) => {
try{
const problem = {
uid: uuid(),
language: req.body.language,
judgeType: req.body.judgeType,
source: req.body.source,
dataSet: req.body.dataSet,
timeLimit: req.body.timeLimit,
memoryLimit: req.body.memoryLimit
} as JudgeRequest
requestJudge(problem)
res.send({success: true, uid: problem.uid})
}
catch (e) {
res.status(400)
res.send({success: false})
}
})

app.get('/test', function (req, res) {
Expand All @@ -30,6 +45,10 @@ app.get('/', function (req, res) {
res.send('HANA v1.0')
})

app.use('*', function (req, res) {
res.redirect('http://jungol.co.kr')
})

app.use(favicon(__dirname + '/../res/logo.ico'))

app.listen(80)
35 changes: 12 additions & 23 deletions src/judge.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,19 @@
import { sendMessage } from './socket'
import type { Problem } from './types/problem'
import { WebSocketResponseType } from './types/response'
import { MultiJudgeCount } from './config'
import { JudgeRequest } from './types/request'
import executeJudge from './runner'
import { JudgeResult } from './types/response'

const waitList = [] as string[],
judgeList = [] as string[]
const problemMap = new Map<string, Problem>()
const problemMap = new Map<string, JudgeRequest>()

function judgeFinishHandler(problem: string) {
function judgeFinishHandler(problem: string, result: JudgeResult) {
if (judgeList.indexOf(problem) !== -1)
judgeList.splice(judgeList.indexOf(problem), 1)
if (problem) {
sendMessage(WebSocketResponseType.JUDGE_FINISH, {
uid: (problemMap.get(problem) as Problem).uid,
score: 100,
reason: 'AC',
})
sendMessage(WebSocketResponseType.JUDGE_FINISH, result)
}
while (judgeList.length < MultiJudgeCount && waitList.length)
judge(waitList.shift() as string)
Expand All @@ -24,26 +22,17 @@ function judgeFinishHandler(problem: string) {
function judge(problem: string) {
judgeList.push(problem)
sendMessage(WebSocketResponseType.JUDGE_PROGRESS, {
uid: (problemMap.get(problem) as Problem).uid,
uid: (problemMap.get(problem) as JudgeRequest).uid,
progress: 0,
reason: 'CP',
})
const rt = Math.random() * 500
for (let i = 1; i < 10; i++) {
setTimeout(() => {
sendMessage(WebSocketResponseType.JUDGE_PROGRESS, {
uid: (problemMap.get(problem) as Problem).uid,
progress: i / 10,
reason: 'RUN',
})
}, i * rt + 1000)
}
setTimeout(() => {
judgeFinishHandler(problem)
}, rt * 10 + 1000)
const result = executeJudge(
problemMap.get(problem) as JudgeRequest
) as JudgeResult
judgeFinishHandler(problem, result)
}

export function requestJudge(problem: Problem) {
export function requestJudge(problem: JudgeRequest) {
waitList.push(problem.uid)
problemMap.set(problem.uid, problem)
sendMessage(WebSocketResponseType.JUDGE_PROGRESS, {
Expand Down
14 changes: 14 additions & 0 deletions src/runner/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import {JudgeRequest, JudgeSourceType, JudgeType, OutputOnly} from "../types/request";

import judgeText from './text';

export default function (data: JudgeRequest) {
switch (data.judgeType) {
case JudgeType.OutputOnly:
return judgeText(data as JudgeRequest<JudgeType.OutputOnly, JudgeSourceType.TEXT, OutputOnly>);
case JudgeType.CommonJudge:
switch (data.language) {

}
}
}
33 changes: 33 additions & 0 deletions src/runner/text.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import {
JudgeRequest,
JudgeSourceType,
JudgeType,
OutputOnly,
} from '../types/request'
import { sendMessage } from '../socket'
import { WebSocketResponseType } from '../types/response'

export default function (
data: JudgeRequest<JudgeType.OutputOnly, JudgeSourceType.TEXT, OutputOnly>
) {
let match = Array(data.dataSet.data.length).fill(false)
for (const s in data.source) {
for (const i in data.dataSet.data) {
if (data.source[s].source === data.dataSet.data[i].output) {
match[i] = true
}
}
sendMessage(WebSocketResponseType.JUDGE_PROGRESS, {
uid: data.uid,
progress: (s as unknown as number) / data.source.length,
reason: 'RUN',
})
}
return {
uid: data.uid,
result: match,
reason: match.length === data.source.length ? 'AC' : 'WA',
time: 0,
memory: 0,
}
}
17 changes: 0 additions & 17 deletions src/types/problem.ts

This file was deleted.

35 changes: 28 additions & 7 deletions src/types/request.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@ export interface WebSocketRequest {
data?: any
}

export const enum JudgeType {
CommonJudge = 'CommonJudge',
OutputOnly = 'OutputOnly',
}

export const enum JudgeSourceType {
TEXT = 'TEXT',
C = 'C',
Expand All @@ -20,15 +25,31 @@ export const enum JudgeSourceType {

export interface SourceFile {
name: string
ext: JudgeSourceType
source: string
}

export interface JudgeRequest {
language: JudgeSourceType
source: string
input: string[]
output: string[]
export interface DataSet {
}

export interface OutputOnly extends DataSet {
data: {
output: string
}[]
}

export interface CommonDataSet extends DataSet {
data: {
input: string
output: string
}[]
}

export interface JudgeRequest<TJudgeType extends JudgeType = JudgeType, TJudgeSourceType extends JudgeSourceType = JudgeSourceType, TDataSet extends DataSet = DataSet> {
uid: string
language: TJudgeSourceType
judgeType: TJudgeType
source: SourceFile[]
dataSet: TDataSet
timeLimit: number
memoryLimit: number
}
}
15 changes: 15 additions & 0 deletions src/types/response.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
export type JudgeResultCode = 'AC' | 'WA' | 'RTE' | 'TLE' | 'MLE' | 'OLE' | 'CE'
export type JudgeStatusCode = JudgeResultCode | 'PD' | 'CP' | 'RUN'

export const enum WebSocketResponseType {
JUDGE_FINISH = 'JUDGE_FINISH',
JUDGE_PROGRESS = 'JUDGE_PROGRESS',
Expand All @@ -12,3 +15,15 @@ export interface WebSocketResponse {
data?: any
error?: string
}

export interface JudgeResult {
uid: string,
result: boolean[]
reason: JudgeResultCode
time: number
memory: number
example?: {
output: string
no: number
}
}
2 changes: 1 addition & 1 deletion yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -411,7 +411,7 @@ base64id@2.0.0, base64id@~2.0.0:
resolved "https://registry.yarnpkg.com/base64id/-/base64id-2.0.0.tgz#2770ac6bc47d312af97a8bf9a634342e0cd25cb6"
integrity sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==

body-parser@1.19.1:
body-parser@1.19.1, body-parser@^1.19.1:
version "1.19.1"
resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.19.1.tgz#1499abbaa9274af3ecc9f6f10396c995943e31d4"
integrity sha512-8ljfQi5eBk8EJfECMrgqNGWPEY5jWP+1IzkzkGdFFEwFQZZyaZ21UqdaHktgiMlH0xLHqIFtE/u2OYE5dOtViA==
Expand Down

0 comments on commit 19de162

Please sign in to comment.