import * as TypeORM from "typeorm"; import Model from "./common"; declare var syzoj: any; import JudgeState from "./judge_state"; import UserPrivilege from "./user_privilege"; import Article from "./article"; @TypeORM.Entity() export default class User extends Model { @TypeORM.PrimaryGeneratedColumn() id: number; @TypeORM.Index({ unique: true }) @TypeORM.Column({ nullable: true, type: "varchar", length: 80 }) username: string; @TypeORM.Column({ nullable: true, type: "varchar", length: 120 }) email: string; @TypeORM.Column({ nullable: true, type: "varchar", length: 120 }) password: string; @TypeORM.Column({ nullable: true, type: "varchar", length: 80 }) nickname: string; @TypeORM.Column({ nullable: true, type: "text" }) nameplate: string; @TypeORM.Column({ nullable: true, type: "text" }) information: string; @TypeORM.Index() @TypeORM.Column({ nullable: true, type: "integer" }) ac_num: number; @TypeORM.Index() @TypeORM.Column({ nullable: true, type: "integer" }) submit_num: number; @TypeORM.Column({ nullable: true, type: "boolean" }) is_admin: boolean; @TypeORM.Index() @TypeORM.Column({ nullable: true, type: "boolean" }) is_show: boolean; @TypeORM.Column({ nullable: true, type: "boolean", default: true }) public_email: boolean; @TypeORM.Column({ nullable: true, type: "boolean", default: true }) prefer_formatted_code: boolean; @TypeORM.Column({ nullable: true, type: "integer" }) sex: number; @TypeORM.Column({ nullable: true, type: "integer" }) rating: number; @TypeORM.Column({ nullable: true, type: "integer" }) register_time: number; static async fromEmail(email): Promise { return User.findOne({ where: { email: email } }); } static async fromName(name): Promise { return User.findOne({ where: { username: name } }); } async isAllowedEditBy(user) { if (!user) return false; if (await user.hasPrivilege('manage_user')) return true; return user && (user.is_admin || this.id === user.id); } getQueryBuilderForACProblems() { return JudgeState.createQueryBuilder() .select(`DISTINCT(problem_id)`) .where('user_id = :user_id', { user_id: this.id }) .andWhere('status = :status', { status: 'Accepted' }) .andWhere('type != 1') .orderBy({ problem_id: 'ASC' }) } async refreshSubmitInfo() { await syzoj.utils.lock(['User::refreshSubmitInfo', this.id], async () => { this.ac_num = await JudgeState.countQuery(this.getQueryBuilderForACProblems()); this.submit_num = await JudgeState.count({ user_id: this.id, type: TypeORM.Not(1) // Not a contest submission }); await this.save(); }); } async getACProblems() { let queryResult = await this.getQueryBuilderForACProblems().getRawMany(); return queryResult.map(record => record['problem_id']) } async getArticles() { return await Article.find({ where: { user_id: this.id } }); } async getStatistics() { let statuses = { "Accepted": ["Accepted"], "Wrong Answer": ["Wrong Answer", "File Error", "Output Limit Exceeded"], "Runtime Error": ["Runtime Error"], "Time Limit Exceeded": ["Time Limit Exceeded"], "Memory Limit Exceeded": ["Memory Limit Exceeded"], "Compile Error": ["Compile Error"] }; let res = {}; for (let status in statuses) { res[status] = 0; for (let s of statuses[status]) { res[status] += await JudgeState.count({ user_id: this.id, type: 0, status: s }); } } return res; } async renderInformation() { this.information = await syzoj.utils.markdown(this.information); } async getPrivileges() { let privileges = await UserPrivilege.find({ where: { user_id: this.id } }); return privileges.map(x => x.privilege); } async setPrivileges(newPrivileges) { let oldPrivileges = await this.getPrivileges(); let delPrivileges = oldPrivileges.filter(x => !newPrivileges.includes(x)); let addPrivileges = newPrivileges.filter(x => !oldPrivileges.includes(x)); for (let privilege of delPrivileges) { let obj = await UserPrivilege.findOne({ where: { user_id: this.id, privilege: privilege } }); await obj.destroy(); } for (let privilege of addPrivileges) { let obj = await UserPrivilege.create({ user_id: this.id, privilege: privilege }); await obj.save(); } } async hasPrivilege(privilege) { if (this.is_admin) return true; let x = await UserPrivilege.findOne({ where: { user_id: this.id, privilege: privilege } }); return !!x; } async getLastSubmitLanguage() { let a = await JudgeState.findOne({ where: { user_id: this.id }, order: { submit_time: 'DESC' } }); if (a) return a.language; return null; } }