需求:Hydrooj本身自带的IOI赛制在相同分数下排名是相同的。为了确保能区分不同排名。CodeFun2000在此基础上做更改,使得分数相同的情况下,按到达此分数的时刻升序排序.
查询本比赛每道题目的最大得分的提交时刻的最小值。从中获取JudgeAt的最大值。一些必要细节请阅读源码
contest_addon/index.ts
import {
BadRequestError,
Context, db, DocumentModel, ForbiddenError, Handler , PRIV,
RecordModel, SettingModel, SystemModel, Time , UserModel, DomainModel,
MessageModel, Types , param , ProblemModel , StorageModel , ContestModel ,
STATUS
} from 'hydrooj';
export async function apply(ctx: Context) {
// ---------------contest-ioi-addon------------------------
/**
* 1.分数越高排越前
* 2.分数相同比较<达到这个分数的时刻的时间戳>的大小,按升序排序
*/
const vaildStatus = [
STATUS.STATUS_ACCEPTED ,
STATUS.STATUS_WRONG_ANSWER ,
STATUS.STATUS_TIME_LIMIT_EXCEEDED,
STATUS.STATUS_MEMORY_LIMIT_EXCEEDED,
STATUS.STATUS_RUNTIME_ERROR
];
ctx.on('handler/after/ContestScoreboard', async (that) => {
var tdoc = that.response.body.tdoc;
if (tdoc.rule != 'ioi') return ;
var rows = that.response.body.rows;
var n = rows.length;
var j = 1;
//console.log(that.response.body);
for (var i = 1 ; i < n ; i = j){
// deal with the same score
while (j < n && rows[i][2].value === rows[j][2].value){
j += 1;
}
console.log(i , j - 1 , rows[i][0].value , rows[i][2].value);
for (var k = i ; k < j ; k++){
var lvtArr : any = [];
// get last valid timestamp for every problem
for (var pid of tdoc.pids){
var uid = Number(rows[k][1].raw);
var arr = await RecordModel.getMulti('system' , {
uid : uid ,
pid : pid ,
contest : {$exists : true , $eq : tdoc.docId} ,
status : { $in : vaildStatus}
}).toArray();
if (arr.length === 0) continue;
var maxScore = Math.max(...(arr.map(a => {return a['score']})) );
var ms_arr = arr.filter(a => {return a['score'] === maxScore});
var lvt = Math.min(...(ms_arr.map(a => {return new Date(a['judgeAt']).getTime()})) );
lvtArr.push(lvt);
console.log(k , pid , arr.map(a => {return a['judgeAt']}));
}
rows[k]['lastValidTimestamp'] = Math.max(...lvtArr);
console.log(k , rows[k]['lastValidTimestamp']);
}
var tmp = rows.slice(i , j).sort((r1 , r2) => {
return r1['lastValidTimestamp'] - r2['lastValidTimestamp'];
});
for (var k = i ; k < j ; k++)
rows[k] = tmp[k - i];
// reset the rank
for (var k = i ; k < j ; k++){
if (rows[k][2].value === 0){
rows[k][0].value = i;
}else{
rows[k][0].value = k;
}
}
}
that.response.body.rows = rows;
});
}
By signing up a CodeFun2000 universal account, you can submit code and join discussions in all online judging services provided by us.