You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

151 lines
3.8 KiB

6 years ago
import * as TypeORM from "typeorm";
import Model from "./common";
declare var syzoj, ErrorMessage: any;
import User from "./user";
import Problem from "./problem";
import ContestRanklist from "./contest_ranklist";
import ContestPlayer from "./contest_player";
enum ContestType {
NOI = "noi",
IOI = "ioi",
ICPC = "acm"
}
@TypeORM.Entity()
export default class Contest extends Model {
@TypeORM.PrimaryGeneratedColumn()
id: number;
@TypeORM.Column({ nullable: true, type: "varchar", length: 80 })
title: string;
@TypeORM.Column({ nullable: true, type: "text" })
subtitle: string;
@TypeORM.Column({ nullable: true, type: "integer" })
start_time: number;
@TypeORM.Column({ nullable: true, type: "integer" })
end_time: number;
@TypeORM.Index()
@TypeORM.Column({ nullable: true, type: "integer" })
holder_id: number;
// type: noi, ioi, acm
6 years ago
@TypeORM.Column({ nullable: true, type: "enum", enum: ContestType })
type: ContestType;
8 years ago
6 years ago
@TypeORM.Column({ nullable: true, type: "text" })
information: string;
8 years ago
6 years ago
@TypeORM.Column({ nullable: true, type: "text" })
problems: string;
@TypeORM.Column({ nullable: true, type: "text" })
admins: string;
@TypeORM.Index()
@TypeORM.Column({ nullable: true, type: "integer" })
ranklist_id: number;
@TypeORM.Column({ nullable: true, type: "boolean" })
is_public: boolean;
@TypeORM.Column({ nullable: true, type: "boolean" })
hide_statistics: boolean;
holder?: User;
ranklist?: ContestRanklist;
8 years ago
async loadRelationships() {
6 years ago
this.holder = await User.findById(this.holder_id);
this.ranklist = await ContestRanklist.findById(this.ranklist_id);
8 years ago
}
async isSupervisior(user) {
return user && (user.is_admin || this.holder_id === user.id || this.admins.split('|').includes(user.id.toString()));
8 years ago
}
allowedSeeingOthers() {
if (this.type === 'acm') return true;
else return false;
}
allowedSeeingScore() { // If not, then the user can only see status
if (this.type === 'ioi') return true;
else return false;
}
allowedSeeingResult() { // If not, then the user can only see compile progress
if (this.type === 'ioi' || this.type === 'acm') return true;
else return false;
}
allowedSeeingTestcase() {
if (this.type === 'ioi') return true;
return false;
8 years ago
}
async getProblems() {
if (!this.problems) return [];
8 years ago
return this.problems.split('|').map(x => parseInt(x));
}
async setProblemsNoCheck(problemIDs) {
this.problems = problemIDs.join('|');
}
8 years ago
async setProblems(s) {
let a = [];
await s.split('|').forEachAsync(async x => {
6 years ago
let problem = await Problem.findById(x);
8 years ago
if (!problem) return;
a.push(x);
});
this.problems = a.join('|');
}
async newSubmission(judge_state) {
if (!(judge_state.submit_time >= this.start_time && judge_state.submit_time <= this.end_time)) {
return;
}
8 years ago
let problems = await this.getProblems();
if (!problems.includes(judge_state.problem_id)) throw new ErrorMessage('当前比赛中无此题目。');
8 years ago
await syzoj.utils.lock(['Contest::newSubmission', judge_state.user_id], async () => {
let player = await ContestPlayer.findInContest({
8 years ago
contest_id: this.id,
user_id: judge_state.user_id
});
8 years ago
if (!player) {
player = await ContestPlayer.create({
contest_id: this.id,
user_id: judge_state.user_id
});
}
await player.updateScore(judge_state);
await player.save();
8 years ago
await this.loadRelationships();
await this.ranklist.updatePlayer(this, player);
await this.ranklist.save();
});
8 years ago
}
6 years ago
isRunning(now?) {
if (!now) now = syzoj.utils.getCurrentDate();
8 years ago
return now >= this.start_time && now < this.end_time;
}
6 years ago
isEnded(now?) {
if (!now) now = syzoj.utils.getCurrentDate();
return now >= this.end_time;
}
8 years ago
}