|
|
@ -28,6 +28,7 @@ interface AcmJournal {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
interface AcmDetail extends AcmJournal {
|
|
|
|
interface AcmDetail extends AcmJournal {
|
|
|
|
naccept?: number;
|
|
|
|
naccept?: number;
|
|
|
|
|
|
|
|
npending?: number;
|
|
|
|
penalty: number;
|
|
|
|
penalty: number;
|
|
|
|
real: number;
|
|
|
|
real: number;
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -57,12 +58,17 @@ const acm = buildContestRule({
|
|
|
|
showRecord: (tdoc, now) => now > tdoc.endAt,
|
|
|
|
showRecord: (tdoc, now) => now > tdoc.endAt,
|
|
|
|
stat(tdoc, journal: AcmJournal[]) {
|
|
|
|
stat(tdoc, journal: AcmJournal[]) {
|
|
|
|
const naccept = Counter<number>();
|
|
|
|
const naccept = Counter<number>();
|
|
|
|
|
|
|
|
const npending = Counter<number>();
|
|
|
|
const effective: Record<number, AcmJournal> = {};
|
|
|
|
const effective: Record<number, AcmJournal> = {};
|
|
|
|
const detail: Record<number, AcmDetail> = {};
|
|
|
|
const detail: Record<number, AcmDetail> = {};
|
|
|
|
let accept = 0;
|
|
|
|
let accept = 0;
|
|
|
|
let time = 0;
|
|
|
|
let time = 0;
|
|
|
|
for (const j of journal) {
|
|
|
|
for (const j of journal) {
|
|
|
|
if (!this.submitAfterAccept && effective[j.pid]?.status === STATUS.STATUS_ACCEPTED) continue;
|
|
|
|
if (!this.submitAfterAccept && effective[j.pid]?.status === STATUS.STATUS_ACCEPTED) continue;
|
|
|
|
|
|
|
|
if (j.status === STATUS.STATUS_WAITING) {
|
|
|
|
|
|
|
|
npending[j.pid]++;
|
|
|
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
}
|
|
|
|
effective[j.pid] = j;
|
|
|
|
effective[j.pid] = j;
|
|
|
|
if (![STATUS.STATUS_ACCEPTED, STATUS.STATUS_COMPILE_ERROR, STATUS.STATUS_FORMAT_ERROR].includes(j.status)) {
|
|
|
|
if (![STATUS.STATUS_ACCEPTED, STATUS.STATUS_COMPILE_ERROR, STATUS.STATUS_FORMAT_ERROR].includes(j.status)) {
|
|
|
|
naccept[j.pid]++;
|
|
|
|
naccept[j.pid]++;
|
|
|
@ -73,7 +79,7 @@ const acm = buildContestRule({
|
|
|
|
const real = Math.floor((j.rid.getTimestamp().getTime() - tdoc.beginAt.getTime()) / 1000);
|
|
|
|
const real = Math.floor((j.rid.getTimestamp().getTime() - tdoc.beginAt.getTime()) / 1000);
|
|
|
|
const penalty = 20 * 60 * naccept[j.pid];
|
|
|
|
const penalty = 20 * 60 * naccept[j.pid];
|
|
|
|
detail[pid] = {
|
|
|
|
detail[pid] = {
|
|
|
|
...j, naccept: naccept[j.pid], time: real + penalty, real, penalty,
|
|
|
|
...j, naccept: naccept[j.pid], time: real + penalty, real, penalty, npending: npending[j.pid],
|
|
|
|
};
|
|
|
|
};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for (const d of Object.values(detail).filter((i) => i.status === STATUS.STATUS_ACCEPTED)) {
|
|
|
|
for (const d of Object.values(detail).filter((i) => i.status === STATUS.STATUS_ACCEPTED)) {
|
|
|
@ -143,8 +149,7 @@ const acm = buildContestRule({
|
|
|
|
for (const pid of tdoc.pids) {
|
|
|
|
for (const pid of tdoc.pids) {
|
|
|
|
const doc = tsddict[pid] || {} as Partial<AcmDetail>;
|
|
|
|
const doc = tsddict[pid] || {} as Partial<AcmDetail>;
|
|
|
|
const accept = doc.status === STATUS.STATUS_ACCEPTED;
|
|
|
|
const accept = doc.status === STATUS.STATUS_ACCEPTED;
|
|
|
|
const pending = doc.status === STATUS.STATUS_WAITING;
|
|
|
|
const colTime = accept ? formatSeconds(doc.real, false).toString() : '';
|
|
|
|
const colTime = pending ? '?' : accept ? formatSeconds(doc.real, false).toString() : '';
|
|
|
|
|
|
|
|
const colPenalty = doc.rid ? Math.ceil(doc.penalty / 60).toString() : '';
|
|
|
|
const colPenalty = doc.rid ? Math.ceil(doc.penalty / 60).toString() : '';
|
|
|
|
if (isExport) {
|
|
|
|
if (isExport) {
|
|
|
|
row.push(
|
|
|
|
row.push(
|
|
|
@ -155,17 +160,16 @@ const acm = buildContestRule({
|
|
|
|
let value = '';
|
|
|
|
let value = '';
|
|
|
|
if (doc.rid) value = `-${doc.naccept}`;
|
|
|
|
if (doc.rid) value = `-${doc.naccept}`;
|
|
|
|
if (accept) value = `${doc.naccept ? `+${doc.naccept}` : '<span class="icon icon-check"></span>'}\n${colTime}`;
|
|
|
|
if (accept) value = `${doc.naccept ? `+${doc.naccept}` : '<span class="icon icon-check"></span>'}\n${colTime}`;
|
|
|
|
if (pending) value = `<span style="color:blue">${doc.naccept}?</span>`;
|
|
|
|
else if (doc.npending) value += `${value ? ' ' : ''}<span style="color:orange">+${doc.npending}</span>`;
|
|
|
|
row.push({
|
|
|
|
row.push({
|
|
|
|
type: 'record',
|
|
|
|
type: 'record',
|
|
|
|
score: accept ? 100 : 0,
|
|
|
|
score: accept ? 100 : 0,
|
|
|
|
value,
|
|
|
|
value,
|
|
|
|
hover: accept ? formatSeconds(doc.time) : '',
|
|
|
|
hover: accept ? formatSeconds(doc.time) : '',
|
|
|
|
raw: doc.rid,
|
|
|
|
raw: doc.rid,
|
|
|
|
style: pending ? 'background-color: yellow'
|
|
|
|
style: accept && doc.rid.generationTime === meta?.first?.[pid]
|
|
|
|
: accept && doc.rid.generationTime === meta?.first?.[pid]
|
|
|
|
? 'background-color: rgb(217, 240, 199);'
|
|
|
|
? 'background-color: rgb(217, 240, 199);'
|
|
|
|
: undefined,
|
|
|
|
: undefined,
|
|
|
|
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|