diff --git a/src/controllers/code.controller.ts b/src/controllers/code.controller.ts index 6a7a72a..ceecd9f 100644 --- a/src/controllers/code.controller.ts +++ b/src/controllers/code.controller.ts @@ -37,29 +37,12 @@ export class CodeController { } async runByCaseImplement(body: ICodeRunBody) { - const { code, questionId, languageId, once } = body; - - const question = await this.codeService.getQuestion(questionId); - const language = await this.codeService.getLanguage(languageId); - const result = []; - - for (const testcase of question.cases) { - const codeCommand = await this.codeService.prepareRunCommand( - language, - code, - question.entry, - testcase, - ); - - const _result = await this.codeService.run(languageId, codeCommand); - result.push(_result); - - if (once || !_result.isSuccess) { - break; - } + const { code, questionId, languageId } = body; + if (!languageId || !questionId || !code) { + return ''; } - return result; + return await this.codeService.runCodeByCase(body); } @Post('run') diff --git a/src/dtos/code.ts b/src/dtos/code.ts index 96b17f4..3707b98 100644 --- a/src/dtos/code.ts +++ b/src/dtos/code.ts @@ -19,7 +19,16 @@ export interface IQuestionDto { code: string; } -export interface ICodeResult { +export interface ICodeRunResult { isSuccess: boolean; data: any; } + +export interface IRunCaseResult { + comments: string; + input: string; + output: string; + codeOutput?: string; + elapsedTime?: string; + logs?: string; +} diff --git a/src/entities/questionBank.entity.ts b/src/entities/questionBank.entity.ts index cdd4a68..aee786c 100644 --- a/src/entities/questionBank.entity.ts +++ b/src/entities/questionBank.entity.ts @@ -21,6 +21,7 @@ export class QuestionBank { } export class IQuestionCase { - case: any; - assert: any; + comments: string; + input: any; + output: any; } diff --git a/src/services/code.service.ts b/src/services/code.service.ts index 7e91f69..546a555 100644 --- a/src/services/code.service.ts +++ b/src/services/code.service.ts @@ -1,10 +1,11 @@ import config from '@config/config'; -import { ICodeResult } from '@dtos/code'; +import { ICodeRunResult, ICodeRunBody, IRunCaseResult } from '@dtos/code'; import { IQuestionCase, QuestionBank } from '@entities/questionBank.entity'; import { LanguageModel } from '@models/language.model'; import { Injectable } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; import { httpGet, httpPost } from '@utils/httpRequest'; +import { matchCaseResult } from '@utils/utils'; import { Repository } from 'typeorm'; @Injectable() @@ -31,47 +32,65 @@ export class CodeService { ); } - prepareCodeCommands(language: LanguageModel, code: string) { - const commands = `${language.beforInjectionCodeCmd} - code="${code.replace(/"/g, '\\"')}" - cat <<< "$code" > ${language.fileName} - ${language.afterInjectionCodeCmd} - `; - return commands; - } - - async prepareTestCaseCode( - entry: string, - cases: IQuestionCase, - captureCode: string, - ) { - const testCaseCode = captureCode - .replace('${entry}', entry) - .replace('${case}', cases.case); - return testCaseCode; - } - - async prepareRunCommand( + async prepareCodeCase( language: LanguageModel, code: string, entry: string, cases: IQuestionCase, ) { - const testCaseCode = await this.prepareTestCaseCode( - entry, - cases, - language.captureCode, - ); + const testCaseCode = language.captureCode + .replace('${entry}', entry) + .replace('${input}', cases.input); code += testCaseCode; - return await this.prepareCodeCommands(language, code); + return code; } - async run(languageId: number, code: string): Promise { - return await httpPost(`${config.services.codeService}/run`, { - body: JSON.stringify({ - languageId: languageId, - code: code, - }), - }); + extractCaseResult(value: string) { + value = value ?? ''; + return { + elapsedTime: matchCaseResult('ElapsedTime', value), + codeOutput: matchCaseResult('Output', value), + }; + } + + async runCodeByCase(params: ICodeRunBody) { + const { code, questionId, languageId, once } = params; + + const question = await this.getQuestion(questionId); + const language = await this.getLanguage(languageId); + + const result = [] as IRunCaseResult[]; + for (const testcase of question.cases) { + const codeCommand = await this.prepareCodeCase( + language, + code, + question.entry, + testcase, + ); + + const _result = await this.run(languageId, codeCommand); + result.push({ + ...testcase, + ...this.extractCaseResult(_result.data), + logs: _result.data, + }); + + if (once || !_result.isSuccess) { + break; + } + } + return result; + } + + async run(languageId: number, code: string): Promise { + return await httpPost( + `${config.services.codeService}/run`, + { + body: JSON.stringify({ + languageId: languageId, + code: code, + }), + }, + ); } } diff --git a/src/utils/utils.ts b/src/utils/utils.ts index 62fa03f..245010d 100644 --- a/src/utils/utils.ts +++ b/src/utils/utils.ts @@ -63,3 +63,9 @@ const timeSleep = (time: number): Promise => { export const sleep = (second: number) => { return timeSleep(second * 1000); }; + +export const matchCaseResult = (key: string, value: string) => { + const matchList = value.match(new RegExp(`${key}: (.+?)\n`)); + if (matchList?.length > 1) return matchList[1]; + return null; +};