318 lines
11 KiB
JavaScript
318 lines
11 KiB
JavaScript
|
function Resolver(problem_sub, sub_frozen, problems, users) {
|
||
|
this.problem_sub = problem_sub;
|
||
|
this.sub_frozen = sub_frozen;
|
||
|
this.problems = problems;
|
||
|
this.users = users;
|
||
|
this.frozen_seconds = 200;
|
||
|
this.operations = [];
|
||
|
this.frozen_op = 0;
|
||
|
this.isshow = [];
|
||
|
this.delay = false;
|
||
|
}
|
||
|
|
||
|
Resolver.prototype.status = function (problem) {
|
||
|
if (problem.old_verdict == 'NA' && problem.new_verdict == 'NA') {
|
||
|
return 'untouched';
|
||
|
} else if (problem.old_verdict == 'AC') {
|
||
|
return 'ac';
|
||
|
} else if (problem.old_verdict == 'PA' && problem.new_verdict == 'NA') {
|
||
|
return 'partially';
|
||
|
} else if (problem.new_verdict == 'NA' && problem.old_verdict == 'WA') {
|
||
|
return 'failed';
|
||
|
} else {
|
||
|
return "frozen";
|
||
|
}
|
||
|
}
|
||
|
|
||
|
Resolver.prototype.substatus = function (problem, subproblem) {
|
||
|
if (problem.old_verdict == 'NA' && problem.new_verdict == 'NA') {
|
||
|
return 'untouched';
|
||
|
} else if (problem[subproblem].old_verdict == 'AC') {
|
||
|
return 'ac';
|
||
|
} else if (problem[subproblem].old_verdict == 'PA' && problem.new_verdict == 'NA') {
|
||
|
return 'partially';
|
||
|
} else if (problem[subproblem].old_verdict == 'WA' && problem.new_verdict == 'NA') {
|
||
|
return 'failed';
|
||
|
}
|
||
|
else {
|
||
|
return 'frozen';
|
||
|
}
|
||
|
}
|
||
|
|
||
|
Resolver.prototype.pointstatus = function (point, problem, sub) {
|
||
|
if (sub == undefined) {
|
||
|
if (point == 100) return 'AC';
|
||
|
if (point == 0) return 'WA';
|
||
|
return 'PA';
|
||
|
}
|
||
|
if (point == this.problems[problem][sub]) return 'AC';
|
||
|
if (point == 0) return 'WA';
|
||
|
return 'PA';
|
||
|
}
|
||
|
|
||
|
Resolver.prototype.calcOperations = function () {
|
||
|
this.rank = {};
|
||
|
this.users_cnt = Object.keys(this.users).length;
|
||
|
for (let id = 1; id <= this.users_cnt; id++) {
|
||
|
this.rank[id] = {
|
||
|
'user_id': id,
|
||
|
'score': 0,
|
||
|
'rank_show': -1,
|
||
|
'last_submission': this.users[id].last_submission,
|
||
|
};
|
||
|
this.rank[id].problem = {}
|
||
|
for (let i = 1; i <= this.problem_sub.length; i++) {
|
||
|
this.rank[id].problem[i] = {
|
||
|
'old_point': 0,
|
||
|
'new_point': 0,
|
||
|
'old_verdict': 'NA',
|
||
|
'new_verdict': 'NA',
|
||
|
}
|
||
|
for (let j = 1; j <= this.problem_sub[i - 1]; j++) {
|
||
|
this.rank[id].problem[i][j] = {
|
||
|
'old_point': 0,
|
||
|
'new_point': 0,
|
||
|
'old_verdict': 'NA',
|
||
|
'new_verdict': 'NA'
|
||
|
};
|
||
|
}
|
||
|
}
|
||
|
for (let problemid in this.users[id].problems) {
|
||
|
for (let j = 1; j <= this.problem_sub[problemid - 1]; j++) {
|
||
|
if (j < this.sub_frozen[problemid - 1]) {
|
||
|
this.rank[id].problem[problemid][j].old_point = this.users[id].problems[problemid].frozen_points[j];
|
||
|
this.rank[id].problem[problemid].old_point += this.rank[id].problem[problemid][j].old_point;
|
||
|
this.rank[id].problem[problemid][j].old_verdict = this.pointstatus(this.users[id].problems[problemid].frozen_points[j], problemid, j);
|
||
|
if (this.users[id].problems[problemid].points[j] != -1) {
|
||
|
this.rank[id].problem[problemid][j].new_point = this.users[id].problems[problemid].points[j];
|
||
|
this.rank[id].problem[problemid].new_point += this.rank[id].problem[problemid][j].new_point;
|
||
|
this.rank[id].problem[problemid][j].new_verdict = this.pointstatus(this.users[id].problems[problemid].points[j], problemid, j);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
this.rank[id].problem[problemid].old_verdict = this.pointstatus(this.rank[id].problem[problemid].old_point);
|
||
|
this.rank[id].score += this.rank[id].problem[problemid].old_point;
|
||
|
if (this.users[id].problems[problemid].points[1] != -1) {
|
||
|
this.rank[id].problem[problemid].new_verdict = this.pointstatus(this.rank[id].problem[problemid].new_point);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
this.rank_frozen = $.extend(true, [], this.rank);
|
||
|
var uids = Object.keys(this.rank);
|
||
|
this.rankarr = [];
|
||
|
for (let key in uids) {
|
||
|
this.rankarr.push(this.rank[uids[key]]);
|
||
|
}
|
||
|
this.rankarr.sort(function (a, b) {
|
||
|
if (a.score != b.score) {
|
||
|
return (b.score - a.score);
|
||
|
} else {
|
||
|
return (a.last_submission - b.last_submission);
|
||
|
}
|
||
|
});
|
||
|
|
||
|
for (let i = 0; i < this.rankarr.length; i++) {
|
||
|
this.rankarr[i].rank_show = i + 1;
|
||
|
this.rank[this.rankarr[i].user_id].rank_show = i + 1;
|
||
|
this.rank_frozen[this.rankarr[i].user_id].rank_show = i + 1;
|
||
|
}
|
||
|
console.log(this.rank_frozen);
|
||
|
for (let i = this.rankarr.length - 1; i >= 0; i--) {
|
||
|
var flag = true;
|
||
|
while (flag) {
|
||
|
flag = false;
|
||
|
for (let j = 1; j <= this.problem_sub.length; j++) {
|
||
|
if (this.status(this.rankarr[i].problem[j]) == 'frozen') {
|
||
|
frozen_op = true;
|
||
|
flag = true;
|
||
|
for (let sub = 1; sub < this.sub_frozen[j - 1]; sub++) {
|
||
|
if (this.rankarr[i].problem[j][sub].old_verdict == 'AC') continue;
|
||
|
var op = {
|
||
|
id: this.operations.length,
|
||
|
type: 'sub',
|
||
|
frozen: 'no',
|
||
|
user_id: this.rankarr[i].user_id,
|
||
|
problem_index: j,
|
||
|
problem_sub: sub,
|
||
|
old_point: this.rankarr[i].problem[j][sub].old_point,
|
||
|
new_point: this.rankarr[i].problem[j][sub].new_point,
|
||
|
old_verdict: this.rankarr[i].problem[j][sub].old_verdict,
|
||
|
new_verdict: this.rankarr[i].problem[j][sub].new_verdict,
|
||
|
};
|
||
|
var tmp = this.rankarr[i];
|
||
|
tmp.problem[j][sub].old_point = tmp.problem[j][sub].new_point;
|
||
|
tmp.problem[j][sub].new_point = 0;
|
||
|
tmp.problem[j][sub].old_verdict = tmp.problem[j][sub].new_verdict;
|
||
|
tmp.problem[j][sub].new_verdict = 'NA';
|
||
|
this.operations.push(op);
|
||
|
}
|
||
|
var op = {
|
||
|
id: this.operations.length,
|
||
|
type: 'problem',
|
||
|
frozen: 'no',
|
||
|
user_id: this.rankarr[i].user_id,
|
||
|
problem_index: j,
|
||
|
old_point: this.rankarr[i].problem[j].old_point,
|
||
|
new_point: this.rankarr[i].problem[j].new_point,
|
||
|
old_verdict: this.rankarr[i].problem[j].old_verdict,
|
||
|
new_verdict: this.rankarr[i].problem[j].new_verdict,
|
||
|
old_rank: i + 1,
|
||
|
new_rank: -1,
|
||
|
};
|
||
|
var tmp = this.rankarr[i];
|
||
|
if (tmp.problem[j].new_point > tmp.problem[j].old_point) {
|
||
|
tmp.score += tmp.problem[j].new_point - tmp.problem[j].old_point;
|
||
|
}
|
||
|
tmp.problem[j].old_point = tmp.problem[j].new_point;
|
||
|
tmp.problem[j].new_point = 0;
|
||
|
tmp.problem[j].old_verdict = tmp.problem[j].new_verdict;
|
||
|
tmp.problem[j].new_verdict = 'NA';
|
||
|
var k = i - 1;
|
||
|
while (k >= 0 && this.rankarr[k].score < tmp.score) {
|
||
|
tmp.rank_show--;
|
||
|
this.rankarr[k].rank_show++;
|
||
|
this.rankarr[k + 1] = this.rankarr[k];
|
||
|
k--;
|
||
|
}
|
||
|
this.rankarr[k + 1] = tmp;
|
||
|
op.new_rank = k + 2;
|
||
|
this.operations.push(op);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
this.check = [];
|
||
|
for (let i = 1; i <= this.users_cnt; i++) {
|
||
|
var usercheck = [];
|
||
|
for (let j = 1; j <= this.problem_sub.length; j++) {
|
||
|
var cc = [];
|
||
|
for (let k = 1; k <= this.sub_frozen[j - 1] - 1; k++) {
|
||
|
cc.push(k);
|
||
|
}
|
||
|
usercheck.push(cc);
|
||
|
}
|
||
|
this.check.push(usercheck);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
Resolver.prototype.showrank = function () {
|
||
|
for (let rankid = this.rankarr.length - 1; rankid >= 0; rankid--) {
|
||
|
if (this.isshow.indexOf(this.rankarr[rankid].user_id) != -1) continue;
|
||
|
var ok = true;
|
||
|
for (let problemid in this.users[this.rankarr[rankid].user_id].problems) {
|
||
|
for (let sub = 1; sub <= this.problem_sub[problemid - 1]; sub++) {
|
||
|
if (this.check[this.rankarr[rankid].user_id - 1][problemid - 1].indexOf(sub) == -1) {
|
||
|
ok = false;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
if (ok) {
|
||
|
var op = {
|
||
|
id: this.operations.length,
|
||
|
type: 'show',
|
||
|
user_id: this.rankarr[rankid].user_id,
|
||
|
};
|
||
|
this.delay = true;
|
||
|
this.isshow.push(this.rankarr[rankid].user_id);
|
||
|
this.operations.push(op);
|
||
|
return true;
|
||
|
} else {
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
Resolver.prototype.next_operation = function () {
|
||
|
if (this.delay) {
|
||
|
var op = {
|
||
|
id: this.operations.length,
|
||
|
type: 'delay',
|
||
|
};
|
||
|
this.delay = false;
|
||
|
this.operations.push(op);
|
||
|
return true;
|
||
|
}
|
||
|
var isshowrank = this.showrank();
|
||
|
if (isshowrank == true) return true;
|
||
|
for (let i = this.rankarr.length - 1; i >= 0; i--) {
|
||
|
for (let problemid = 1; problemid <= this.problem_sub.length; problemid++) {
|
||
|
let ok = false;
|
||
|
var id = this.rankarr[i].user_id;
|
||
|
for (let cc in this.users[id].problems) {
|
||
|
if (cc == problemid) ok = true;
|
||
|
}
|
||
|
if (ok == false) {
|
||
|
continue;
|
||
|
}
|
||
|
for (let sub = this.sub_frozen[problemid - 1]; sub <= this.problem_sub[problemid - 1]; sub++) {
|
||
|
if (this.check[this.rankarr[i].user_id - 1][problemid - 1].indexOf(sub) == -1) {
|
||
|
this.operation(i, problemid, sub);
|
||
|
return true;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
Resolver.prototype.operation = function (rankid, problemid, sub) {
|
||
|
var id = this.rankarr[rankid].user_id;
|
||
|
if (this.check[this.rankarr[rankid].user_id - 1][problemid - 1].indexOf(sub) != -1) return false;
|
||
|
this.check[this.rankarr[rankid].user_id - 1][problemid - 1].push(sub);
|
||
|
this.rankarr[rankid].problem[problemid][sub].new_point = this.users[id].problems[problemid].points[sub];
|
||
|
this.rankarr[rankid].problem[problemid][sub].new_verdict = this.pointstatus(this.rankarr[rankid].problem[problemid][sub].new_point, problemid, sub);
|
||
|
this.rankarr[rankid].problem[problemid].new_point =
|
||
|
this.rankarr[rankid].problem[problemid].old_point + this.rankarr[rankid].problem[problemid][sub].new_point - this.rankarr[rankid].problem[problemid][sub].old_point;
|
||
|
this.rankarr[rankid].problem[problemid].new_verdict = this.pointstatus(this.rankarr[rankid].problem[problemid].new_point);
|
||
|
var op = {
|
||
|
id: this.operations.length,
|
||
|
type: 'sub',
|
||
|
frozen: 'ok',
|
||
|
user_id: this.rankarr[rankid].user_id,
|
||
|
problem_index: problemid,
|
||
|
problem_sub: sub,
|
||
|
old_point: this.rankarr[rankid].problem[problemid][sub].old_point,
|
||
|
new_point: this.rankarr[rankid].problem[problemid][sub].new_point,
|
||
|
old_verdict: this.rankarr[rankid].problem[problemid][sub].old_verdict,
|
||
|
new_verdict: this.rankarr[rankid].problem[problemid][sub].new_verdict,
|
||
|
};
|
||
|
var tmp = this.rankarr[rankid];
|
||
|
tmp.problem[problemid][sub].old_point = tmp.problem[problemid][sub].new_point;
|
||
|
tmp.problem[problemid][sub].new_point = 0;
|
||
|
tmp.problem[problemid][sub].old_verdict = tmp.problem[problemid][sub].new_verdict;
|
||
|
tmp.problem[problemid][sub].new_verdict = 'NA';
|
||
|
this.operations.push(op);
|
||
|
var op1 = {
|
||
|
id: this.operations.length,
|
||
|
type: 'problem',
|
||
|
frozen: 'ok',
|
||
|
user_id: this.rankarr[rankid].user_id,
|
||
|
problem_index: problemid,
|
||
|
old_point: this.rankarr[rankid].problem[problemid].old_point,
|
||
|
new_point: this.rankarr[rankid].problem[problemid].new_point,
|
||
|
old_verdict: this.rankarr[rankid].problem[problemid].old_verdict,
|
||
|
new_verdict: this.rankarr[rankid].problem[problemid].new_verdict,
|
||
|
old_rank: rankid + 1,
|
||
|
new_rank: -1,
|
||
|
};
|
||
|
if (tmp.problem[problemid].new_point > tmp.problem[problemid].old_point) {
|
||
|
tmp.score += tmp.problem[problemid].new_point - tmp.problem[problemid].old_point;
|
||
|
}
|
||
|
tmp.problem[problemid].old_point = tmp.problem[problemid].new_point;
|
||
|
tmp.problem[problemid].new_point = 0;
|
||
|
tmp.problem[problemid].old_verdict = tmp.problem[problemid].new_verdict;
|
||
|
tmp.problem[problemid].new_verdict = 'NA';
|
||
|
var k = rankid - 1;
|
||
|
while (k >= 0 && (this.rankarr[k].score < tmp.score || (this.rankarr[k].score == tmp.score && this.rankarr[k].last_submission > tmp.last_submission))) {
|
||
|
tmp.rank_show--;
|
||
|
this.rankarr[k].rank_show++;
|
||
|
this.rankarr[k + 1] = this.rankarr[k];
|
||
|
k--;
|
||
|
}
|
||
|
this.rankarr[k + 1] = tmp;
|
||
|
op1.new_rank = k + 2;
|
||
|
this.operations.push(op1);
|
||
|
return true;
|
||
|
}
|