refactor(remote_judger): waitForSubmission

This commit is contained in:
Baoshuo Ren 2023-02-06 11:24:45 +08:00
parent 00fea4675f
commit 4c0167ee6e
Signed by: baoshuo
GPG Key ID: 00CB9680AB29F51A
7 changed files with 447 additions and 417 deletions

View File

@ -20,10 +20,10 @@ export interface IBasicProvider {
end: NextFunction
): Promise<string | void>;
waitForSubmission(
problem_id: string,
id: string,
next: NextFunction,
end: NextFunction
end: NextFunction,
problem_id?: string
): Promise<void>;
}

View File

@ -8,7 +8,7 @@ import Logger from '../utils/logger';
proxy(superagent);
const logger = new Logger('remote/atcoder');
const langs_map = {
const LANGS_MAP = {
C: {
name: 'C (GCC 9.2.1)',
id: 4001,
@ -182,7 +182,7 @@ export default class AtcoderProvider implements IBasicProvider {
next,
end
) {
const programType = langs_map[lang] || langs_map['C++'];
const programType = LANGS_MAP[lang] || LANGS_MAP['C++'];
const comment = programType.comment;
if (comment) {
@ -244,90 +244,96 @@ export default class AtcoderProvider implements IBasicProvider {
.getAttribute('data-id');
}
async waitForSubmission(problem_id: string, id: string, next, end) {
let i = 0;
async waitForSubmission(id: string, next, end, problem_id: string) {
let count = 0;
let fail = 0;
const [contestId] = parseProblemId(problem_id);
const status_url = `/contests/${contestId}/submissions/me/status/json?reload=true&sids[]=${id}`;
while (true) {
if (++i > 180) {
return await end({
id,
error: true,
status: 'Judgment Failed',
message: 'Failed to fetch submission details.',
});
}
while (count < 180 && fail < 10) {
count++;
await sleep(1000);
const { body, error, header } = await this.get(status_url).retry(3);
if (header['set-cookie']) {
this.cookie = header['set-cookie'];
}
try {
const { body, header } = await this.get(status_url).retry(3);
if (error) continue;
if (header['set-cookie']) {
this.cookie = header['set-cookie'];
}
const result = body.Result[id];
const {
window: { document },
} = new JSDOM(`<table>${result.Html}</table>`);
const result = body.Result[id];
const {
window: { document },
} = new JSDOM(`<table>${result.Html}</table>`);
const elements = document.querySelectorAll('td');
const statusTd = elements[0];
const statusElem = statusTd.querySelector('span');
const elements = document.querySelectorAll('td');
const statusTd = elements[0];
const statusElem = statusTd.querySelector('span');
if (
statusElem.title === 'Waiting for Judging' ||
statusElem.title === 'Waiting for Re-judging' ||
['WJ', 'WR'].includes(statusElem.innerHTML.trim())
) {
await next({ test_id: 0 });
if (
statusElem.title === 'Waiting for Judging' ||
statusElem.title === 'Waiting for Re-judging' ||
['WJ', 'WR'].includes(statusElem.innerHTML.trim())
) {
await next({ test_id: 0 });
continue;
}
continue;
}
if (
statusElem.title === 'Judging' ||
(statusTd.colSpan == 3 && statusTd.className.includes('waiting-judge'))
) {
await next({ test_id: /(\d+)/.exec(statusElem.innerHTML)[1] || 0 });
if (
statusElem.title === 'Judging' ||
(statusTd.colSpan == 3 &&
statusTd.className.includes('waiting-judge'))
) {
await next({ test_id: /(\d+)/.exec(statusElem.innerHTML)[1] || 0 });
continue;
}
continue;
}
if (statusElem.title === 'Compilation Error') {
return await end({
id,
error: true,
status: 'Compile Error',
message: '',
});
}
if (statusElem.title === 'Internal Error') {
return await end({
error: true,
status: 'Judgment Failed',
message: 'AtCoder Internal Error.',
});
}
const time = parseInt(elements[1].innerHTML.trim());
const memory = parseInt(elements[2].innerHTML.trim());
if (statusElem.title === 'Compilation Error') {
return await end({
id,
error: true,
status: 'Compile Error',
message: '',
status: statusElem.title || 'None',
score:
statusElem.title === 'Accepted' ||
statusElem.innerHTML.trim() === 'AC'
? 100
: 0,
time,
memory,
});
} catch (e) {
logger.error(e);
fail++;
}
if (statusElem.title === 'Internal Error') {
return await end({
error: true,
status: 'Judgment Failed',
message: 'AtCoder Internal Error.',
});
}
const time = parseInt(elements[1].innerHTML.trim());
const memory = parseInt(elements[2].innerHTML.trim());
return await end({
id,
status: statusElem.title || 'None',
score:
statusElem.title === 'Accepted' ||
statusElem.innerHTML.trim() === 'AC'
? 100
: 0,
time,
memory,
});
}
return await end({
id,
error: true,
status: 'Judgment Failed',
message: 'Failed to fetch submission details.',
});
}
}

View File

@ -344,104 +344,113 @@ export default class CodeforcesProvider implements IBasicProvider {
.getAttribute('data-submission-id');
}
async waitForSubmission(problem_id: string, id: string, next, end) {
let i = 0;
while (true) {
if (++i > 180) {
return await end({
id,
error: true,
status: 'Judgment Failed',
message: 'Failed to fetch submission details.',
});
}
async waitForSubmission(id: string, next, end) {
let count = 0;
let fail = 0;
while (count < 180 && fail < 10) {
count++;
await sleep(1000);
const { body, error } = await this.post('/data/submitSource')
.send({
csrf_token: this.csrf,
submissionId: id,
})
.retry(3);
if (error) continue;
if (body.compilationError === 'true') {
try {
const { body } = await this.post('/data/submitSource')
.send({
csrf_token: this.csrf,
submissionId: id,
})
.retry(3);
if (body.compilationError === 'true') {
return await end({
id,
error: true,
status: 'Compile Error',
message: crlf(body['checkerStdoutAndStderr#1'], LF),
});
}
const time = mathSum(
Object.keys(body)
.filter(k => k.startsWith('timeConsumed#'))
.map(k => +body[k])
);
const memory =
Math.max(
...Object.keys(body)
.filter(k => k.startsWith('memoryConsumed#'))
.map(k => +body[k])
) / 1024;
await next({ test_id: body.testCount });
if (body.waiting === 'true') continue;
const testCount = +body.testCount;
const status =
VERDICT[
Object.keys(VERDICT).find(k => normalize(body.verdict).includes(k))
];
let tests: string[] = [];
for (let i = 1; i <= testCount; i++) {
let test_info = '';
let info_text =
VERDICT[
Object.keys(VERDICT).find(k =>
normalize(body[`verdict#${i}`]).includes(k)
)
];
test_info += `<test num="${i}" info="${info_text}" time="${
body[`timeConsumed#${i}`]
}" memory="${+body[`memoryConsumed#${i}`] / 1024}">`;
const parse = (id: string) => crlf(body[id], LF);
test_info += `<in>${parse(`input#${i}`)}</in>\n`;
test_info += `<out>${parse(`output#${i}`)}</out>\n`;
test_info += `<ans>${parse(`answer#${i}`)}</ans>\n`;
test_info += `<res>${parse(`checkerStdoutAndStderr#${i}`)}</res>\n`;
test_info += '</test>';
tests.push(test_info);
}
const remote_handle = stripHtml(body.partyName).result;
const details =
'<div>' +
'<div class="border-bottom p-3">' +
`<p><b>Contest:</b> ${stripHtml(body.contestName).result}</p>` +
`<p><b>Problem:</b> ${stripHtml(body.problemName).result}</p>` +
`<p><b>Remote submission:</b> <a href="https://codeforces.com${body.href}" target="_blank">${id}</a></p>` +
`<p><b>Remote account:</b> <a href="https://codeforces.com/profile/${remote_handle}" target="_blank">${remote_handle}</a></p>` +
`<p class="mb-0"><b>Verdict:</b> ${
stripHtml(body.verdict).result
}</p>` +
'</div>' +
`<tests>${tests.join('\n')}</tests>` +
'</div>';
return await end({
id,
error: true,
status: 'Compile Error',
message: crlf(body['checkerStdoutAndStderr#1'], LF),
status,
score: status === 'Accepted' ? 100 : 0,
time,
memory,
details,
});
} catch (e) {
logger.error(e);
fail++;
}
const time = mathSum(
Object.keys(body)
.filter(k => k.startsWith('timeConsumed#'))
.map(k => +body[k])
);
const memory =
Math.max(
...Object.keys(body)
.filter(k => k.startsWith('memoryConsumed#'))
.map(k => +body[k])
) / 1024;
await next({ test_id: body.testCount });
if (body.waiting === 'true') continue;
const testCount = +body.testCount;
const status =
VERDICT[
Object.keys(VERDICT).find(k => normalize(body.verdict).includes(k))
];
let tests: string[] = [];
for (let i = 1; i <= testCount; i++) {
let test_info = '';
let info_text =
VERDICT[
Object.keys(VERDICT).find(k =>
normalize(body[`verdict#${i}`]).includes(k)
)
];
test_info += `<test num="${i}" info="${info_text}" time="${
body[`timeConsumed#${i}`]
}" memory="${+body[`memoryConsumed#${i}`] / 1024}">`;
const parse = (id: string) => crlf(body[id], LF);
test_info += `<in>${parse(`input#${i}`)}</in>\n`;
test_info += `<out>${parse(`output#${i}`)}</out>\n`;
test_info += `<ans>${parse(`answer#${i}`)}</ans>\n`;
test_info += `<res>${parse(`checkerStdoutAndStderr#${i}`)}</res>\n`;
test_info += '</test>';
tests.push(test_info);
}
const remote_handle = stripHtml(body.partyName).result;
const details =
'<div>' +
'<div class="border-bottom p-3">' +
`<p><b>Contest:</b> ${stripHtml(body.contestName).result}</p>` +
`<p><b>Problem:</b> ${stripHtml(body.problemName).result}</p>` +
`<p><b>Remote submission:</b> <a href="https://codeforces.com${body.href}" target="_blank">${id}</a></p>` +
`<p><b>Remote account:</b> <a href="https://codeforces.com/profile/${remote_handle}" target="_blank">${remote_handle}</a></p>` +
`<p class="mb-0"><b>Verdict:</b> ${
stripHtml(body.verdict).result
}</p>` +
'</div>' +
`<tests>${tests.join('\n')}</tests>` +
'</div>';
return await end({
id,
status,
score: status === 'Accepted' ? 100 : 0,
time,
memory,
details,
});
}
return await end({
id,
error: true,
status: 'Judgment Failed',
message: 'Failed to fetch submission details.',
});
}
}

View File

@ -285,7 +285,7 @@ export default class LibreojProvider implements IBasicProvider {
return user_id === submission_user_id;
}
async waitForSubmission(problem_id: string, id: string, next, end) {
async waitForSubmission(id: string, next, end, problem_id: string) {
if (!(await this.ensureLogin())) {
await end({
error: true,
@ -296,226 +296,234 @@ export default class LibreojProvider implements IBasicProvider {
return null;
}
let i = 0;
while (true) {
if (++i > 180) {
return await end({
id,
error: true,
status: 'Judgment Failed',
message: 'Failed to fetch submission details.',
});
}
let count = 0;
let fail = 0;
while (count < 180 && fail < 10) {
count++;
await sleep(1000);
const { body, error } = await this.post('/submission/getSubmissionDetail')
.send({ submissionId: String(id), locale: 'zh_CN' })
.retry(3);
if (error) continue;
try {
const { body } = await this.post('/submission/getSubmissionDetail')
.send({ submissionId: String(id), locale: 'zh_CN' })
.retry(3);
if (body.meta.problem.displayId != problem_id) {
return await end({
id,
error: true,
status: 'Judgment Failed',
message: 'Submission does not match current problem.',
});
}
if (!body.progress) {
await next({ status: 'Waiting for Remote Judge' });
continue;
}
await next({
status: `${body.progress.progressType}`,
});
if (body.progress.progressType !== 'Finished') {
continue;
}
const status =
VERDICT[
Object.keys(VERDICT).find(k =>
normalize(body.meta.status).includes(k)
)
];
if (status === 'Compile Error') {
await end({
error: true,
id,
status: 'Compile Error',
message: stripVTControlCharacters(body.progress.compile.message),
});
}
if (status === 'Judgment Failed') {
await end({
error: true,
id,
status: 'Judgment Failed',
message: 'Error occurred on remote online judge.',
});
}
const parse = (str: string) => crlf(str, LF);
const getSubtaskStatusDisplayText = (testcases: any): string => {
let result: string = null;
for (const testcase of testcases) {
if (!testcase.testcaseHash) {
result = 'Skipped';
break;
} else if (
body.progress.testcaseResult[testcase.testcaseHash].status !==
'Accepted'
) {
result = body.progress.testcaseResult[testcase.testcaseHash].status;
break;
}
if (body.meta.problem.displayId != problem_id) {
return await end({
id,
error: true,
status: 'Judgment Failed',
message: 'Submission does not match current problem.',
});
}
result ||= 'Accepted';
result =
VERDICT[
Object.keys(VERDICT).find(k => normalize(result).includes(k))
];
if (!body.progress) {
await next({ status: 'Waiting for Remote Judge' });
return result;
};
continue;
}
const getTestcaseBlock = (id: string, index: number): string => {
const testcase = body.progress.testcaseResult[id];
await next({
status: `${body.progress.progressType}`,
});
if (!testcase) return '';
if (body.progress.progressType !== 'Finished') {
continue;
}
const status =
VERDICT[
Object.keys(VERDICT).find(k =>
normalize(testcase.status).includes(k)
normalize(body.meta.status).includes(k)
)
];
let test_info = '';
test_info += `<test num="${
index + 1
}" info="${status}" time="${Math.round(testcase.time || 0)}" memory="${
testcase.memory
}">`;
if (testcase.input) {
if (typeof testcase.input === 'string') {
test_info += `<in>${parse(testcase.input)}</in>\n`;
} else {
test_info += `<in>${parse(testcase.input.data)}\n\n(${
testcase.input.omittedLength
} bytes omitted)</in>\n`;
}
if (status === 'Compile Error') {
await end({
error: true,
id,
status: 'Compile Error',
message: stripVTControlCharacters(body.progress.compile.message),
});
}
if (testcase.userOutput) {
if (typeof testcase.userOutput === 'string') {
test_info += `<out>${parse(testcase.userOutput)}</out>\n`;
} else {
test_info += `<out>${parse(testcase.userOutput.data)}\n\n(${
testcase.userOutput.omittedLength
} bytes omitted)</out>\n`;
}
if (status === 'Judgment Failed') {
await end({
error: true,
id,
status: 'Judgment Failed',
message: 'Error occurred on remote online judge.',
});
}
if (testcase.output) {
if (typeof testcase.output === 'string') {
test_info += `<ans>${parse(testcase.output)}</ans>\n`;
} else {
test_info += `<ans>${parse(testcase.output.data)}\n\n(${
testcase.output.omittedLength
} bytes omitted)</ans>\n`;
const parse = (str: string) => crlf(str, LF);
const getSubtaskStatusDisplayText = (testcases: any): string => {
let result: string = null;
for (const testcase of testcases) {
if (!testcase.testcaseHash) {
result = 'Skipped';
break;
} else if (
body.progress.testcaseResult[testcase.testcaseHash].status !==
'Accepted'
) {
result =
body.progress.testcaseResult[testcase.testcaseHash].status;
break;
}
}
result ||= 'Accepted';
result =
VERDICT[
Object.keys(VERDICT).find(k => normalize(result).includes(k))
];
return result;
};
const getTestcaseBlock = (id: string, index: number): string => {
const testcase = body.progress.testcaseResult[id];
if (!testcase) return '';
const status =
VERDICT[
Object.keys(VERDICT).find(k =>
normalize(testcase.status).includes(k)
)
];
let test_info = '';
test_info += `<test num="${
index + 1
}" info="${status}" time="${Math.round(
testcase.time || 0
)}" memory="${testcase.memory}">`;
if (testcase.input) {
if (typeof testcase.input === 'string') {
test_info += `<in>${parse(testcase.input)}</in>\n`;
} else {
test_info += `<in>${parse(testcase.input.data)}\n\n(${
testcase.input.omittedLength
} bytes omitted)</in>\n`;
}
}
if (testcase.userOutput) {
if (typeof testcase.userOutput === 'string') {
test_info += `<out>${parse(testcase.userOutput)}</out>\n`;
} else {
test_info += `<out>${parse(testcase.userOutput.data)}\n\n(${
testcase.userOutput.omittedLength
} bytes omitted)</out>\n`;
}
}
if (testcase.output) {
if (typeof testcase.output === 'string') {
test_info += `<ans>${parse(testcase.output)}</ans>\n`;
} else {
test_info += `<ans>${parse(testcase.output.data)}\n\n(${
testcase.output.omittedLength
} bytes omitted)</ans>\n`;
}
}
if (testcase.checkerMessage) {
if (typeof testcase.checkerMessage === 'string') {
test_info += `<res>${parse(testcase.checkerMessage)}</res>\n`;
} else {
test_info += `<res>${parse(testcase.checkerMessage.data)}\n\n(${
testcase.checkerMessage.omittedLength
} bytes omitted)</res>\n`;
}
}
test_info += '</test>';
return test_info;
};
let details = '';
details +=
'<div class="border-bottom p-3">' +
`<p><b>Problem:</b> #${body.meta.problem.displayId}. ${body.meta.problemTitle}</p>` +
`<p><b>Remote submission:</b> <a href="https://loj.ac/s/${id}" target="_blank">${id}</a></p>` +
`<p><b>Remote submit time:</b> ${new Date(
body.meta.submitTime
).toLocaleString('zh-CN')}</p>` +
`<p><b>Remote account:</b> <a href="https://loj.ac/user/${body.meta.submitter.id}" target="_blank">${body.meta.submitter.username}</a></p>` +
`<p class="mb-0"><b>Verdict:</b> ${status}</p>` +
'</div>';
// Samples
if (body.progress.samples) {
details += `<subtask title="Samples" info="${getSubtaskStatusDisplayText(
body.progress.samples
)}" num="0">${body.progress.samples
.map((item, index) =>
item.testcaseHash
? getTestcaseBlock(item.testcaseHash, index)
: `<test num="${index + 1}" info="Skipped"></test>`
)
.join('\n')}</subtask>`;
}
if (testcase.checkerMessage) {
if (typeof testcase.checkerMessage === 'string') {
test_info += `<res>${parse(testcase.checkerMessage)}</res>\n`;
} else {
test_info += `<res>${parse(testcase.checkerMessage.data)}\n\n(${
testcase.checkerMessage.omittedLength
} bytes omitted)</res>\n`;
}
// Tests
if (body.progress.subtasks.length === 1) {
details += `<tests>${body.progress.subtasks[0].testcases
.map((item, index) =>
item.testcaseHash
? getTestcaseBlock(item.testcaseHash, index)
: `<test num="${index + 1}" info="Skipped"></test>`
)
.join('\n')}</tests>`;
} else {
details += `<tests>${body.progress.subtasks
.map(
(subtask, index) =>
`<subtask num="${
index + 1
}" info="${getSubtaskStatusDisplayText(
subtask.testcases
)}">${subtask.testcases
.map((item, index) =>
item.testcaseHash
? getTestcaseBlock(item.testcaseHash, index)
: `<test num="${index + 1}" info="Skipped"></test>`
)
.join('\n')}</subtask>`
)
.join('\n')}</tests>`;
}
test_info += '</test>';
return await end({
id,
status: body.meta.status,
score: body.meta.score,
time: body.meta.timeUsed,
memory: body.meta.memoryUsed,
details: `<div>${details}</div>`,
});
} catch (e) {
logger.error(e);
return test_info;
};
let details = '';
details +=
'<div class="border-bottom p-3">' +
`<p><b>Problem:</b> #${body.meta.problem.displayId}. ${body.meta.problemTitle}</p>` +
`<p><b>Remote submission:</b> <a href="https://loj.ac/s/${id}" target="_blank">${id}</a></p>` +
`<p><b>Remote submit time:</b> ${new Date(
body.meta.submitTime
).toLocaleString('zh-CN')}</p>` +
`<p><b>Remote account:</b> <a href="https://loj.ac/user/${body.meta.submitter.id}" target="_blank">${body.meta.submitter.username}</a></p>` +
`<p class="mb-0"><b>Verdict:</b> ${status}</p>` +
'</div>';
// Samples
if (body.progress.samples) {
details += `<subtask title="Samples" info="${getSubtaskStatusDisplayText(
body.progress.samples
)}" num="0">${body.progress.samples
.map((item, index) =>
item.testcaseHash
? getTestcaseBlock(item.testcaseHash, index)
: `<test num="${index + 1}" info="Skipped"></test>`
)
.join('\n')}</subtask>`;
fail++;
}
// Tests
if (body.progress.subtasks.length === 1) {
details += `<tests>${body.progress.subtasks[0].testcases
.map((item, index) =>
item.testcaseHash
? getTestcaseBlock(item.testcaseHash, index)
: `<test num="${index + 1}" info="Skipped"></test>`
)
.join('\n')}</tests>`;
} else {
details += `<tests>${body.progress.subtasks
.map(
(subtask, index) =>
`<subtask num="${index + 1}" info="${getSubtaskStatusDisplayText(
subtask.testcases
)}">${subtask.testcases
.map((item, index) =>
item.testcaseHash
? getTestcaseBlock(item.testcaseHash, index)
: `<test num="${index + 1}" info="Skipped"></test>`
)
.join('\n')}</subtask>`
)
.join('\n')}</tests>`;
}
return await end({
id,
status: body.meta.status,
score: body.meta.score,
time: body.meta.timeUsed,
memory: body.meta.memoryUsed,
details: `<div>${details}</div>`,
});
}
return await end({
id,
error: true,
status: 'Judgment Failed',
message: 'Failed to fetch submission details.',
});
}
}

View File

@ -250,11 +250,11 @@ export default class LuoguProvider implements IBasicProvider {
return result.body.rid;
}
async waitForSubmission(problem_id: string, id: string, next, end) {
async waitForSubmission(id: string, next, end) {
let fail = 0;
let count = 0;
while (count < 180 && fail < 5) {
while (count < 180 && fail < 10) {
await sleep(1000);
count++;

View File

@ -9,7 +9,7 @@ import sleep from '../utils/sleep';
proxy(superagent);
const logger = new Logger('remote/uoj');
const langs_map = {
const LANGS_MAP = {
C: {
name: 'C',
id: 'C',
@ -175,7 +175,7 @@ export default class UOJProvider implements IBasicProvider {
next,
end
) {
const programType = langs_map[lang] || langs_map['C++'];
const programType = LANGS_MAP[lang] || LANGS_MAP['C++'];
const comment = programType.comment;
if (comment) {
@ -206,65 +206,72 @@ export default class UOJProvider implements IBasicProvider {
.innerHTML.split('#')[1];
}
async waitForSubmission(problem_id: string, id: string, next, end) {
let i = 0;
while (true) {
if (++i > 180) {
return await end({
id,
error: true,
status: 'Judgment Failed',
message: 'Failed to fetch submission details.',
});
}
async waitForSubmission(id: string, next, end) {
let count = 0;
let fail = 0;
while (count < 180 && fail < 10) {
count++;
await sleep(1000);
const { text } = await this.get(`/submission/${id}`);
const {
window: { document },
} = new JSDOM(text);
const find = (content: string) =>
Array.from(
document.querySelectorAll('.panel-heading>.panel-title')
).find(n => n.innerHTML === content).parentElement.parentElement
.children[1];
if (text.includes('Compile Error')) {
try {
const { text } = await this.get(`/submission/${id}`);
const {
window: { document },
} = new JSDOM(text);
const find = (content: string) =>
Array.from(
document.querySelectorAll('.panel-heading>.panel-title')
).find(n => n.innerHTML === content).parentElement.parentElement
.children[1];
if (text.includes('Compile Error')) {
return await end({
error: true,
id,
status: 'Compile Error',
message: find('详细').children[0].innerHTML,
});
}
await next({});
const summary = document.querySelector('tbody>tr');
if (!summary) continue;
const time = parseTimeMS(summary.children[4].innerHTML);
const memory = parseMemoryMB(summary.children[5].innerHTML) * 1024;
let panel = document.getElementById(
'details_details_accordion_collapse_subtask_1'
);
if (!panel) {
panel = document.getElementById('details_details_accordion');
if (!panel) continue;
}
if (document.querySelector('tbody').innerHTML.includes('Judging'))
continue;
const score = +summary.children[3]?.children[0]?.innerHTML || 0;
const status = score === 100 ? 'Accepted' : 'Unaccepted';
return await end({
error: true,
id,
status: 'Compile Error',
message: find('详细').children[0].innerHTML,
status,
score,
time,
memory,
});
} catch (e) {
logger.error(e);
fail++;
}
await next({});
const summary = document.querySelector('tbody>tr');
if (!summary) continue;
const time = parseTimeMS(summary.children[4].innerHTML);
const memory = parseMemoryMB(summary.children[5].innerHTML) * 1024;
let panel = document.getElementById(
'details_details_accordion_collapse_subtask_1'
);
if (!panel) {
panel = document.getElementById('details_details_accordion');
if (!panel) continue;
}
if (document.querySelector('tbody').innerHTML.includes('Judging'))
continue;
const score = +summary.children[3]?.children[0]?.innerHTML || 0;
const status = score === 100 ? 'Accepted' : 'Unaccepted';
return await end({
id,
status,
score,
time,
memory,
});
}
return await end({
id,
error: true,
status: 'Judgment Failed',
message: 'Failed to fetch submission details.',
});
}
}

View File

@ -35,7 +35,7 @@ class AccountService {
if (!rid) return;
await this.api.waitForSubmission(problem_id, rid, next, end);
await this.api.waitForSubmission(rid, next, end, problem_id);
} catch (e) {
logger.error(e);
@ -178,7 +178,7 @@ class VJudge {
if (!rid) return;
await provider.waitForSubmission(problem_id, rid, next, end);
await provider.waitForSubmission(rid, next, end, problem_id);
} catch (e) {
logger.error(e);
@ -204,10 +204,10 @@ class VJudge {
if (await provider.ensureIsOwnSubmission(config.remote_submission_id)) {
await provider.waitForSubmission(
problem_id,
config.remote_submission_id,
next,
end
end,
problem_id
);
} else {
return await end({