S2OJ/web/app/models/UOJContestProblem.php

167 lines
4.5 KiB
PHP

<?php
class UOJContestProblem extends UOJProblem {
public $contest = null;
public $problem_number = -1;
public static function query($id, UOJContest $contest = null) {
$problem = parent::query($id);
if ($problem === null) {
return $problem;
}
if ($contest === null) {
$contest = UOJContest::cur();
}
return new UOJContestProblem($problem->info, $contest);
}
public function __construct($info, UOJContest $contest) {
parent::__construct($info);
$this->contest = $contest;
}
public function valid() {
return $this->contest && $this->contest->hasProblem($this);
}
public function getProblemNumber() {
if ($this->problem_number !== -1) {
return $this->problem_number;
}
$contest_problems = DB::selectAll([
DB::lc(), "select problem_id from contests_problems",
"where", [
'contest_id' => $this->contest->info['id'],
],
"order by level, problem_id"
]);
return $this->problem_number = array_search(['problem_id' => $this->info['id']], $contest_problems);
}
public function getLetter() {
$num = $this->getProblemNumber();
if ($num === null) {
return null;
}
return chr(ord('A') + $num);
}
public function getTitle(array $cfg = []) {
$cfg += [
'with' => 'id',
'simplify' => false
];
$title = parent::getTitle(['with' => null] + $cfg);
if ($cfg['simplify']) {
$letter = $this->getLetter();
if (strStartWith($title, $letter)) {
if (strStartWith($title, $letter . '.')) {
$title = substr($title, strlen($letter) + 1);
} else if (strStartWith($title, $letter . ' - ')) {
$title = substr($title, strlen($letter) + 3);
}
$title = trim($title);
}
}
if ($cfg['with'] == 'letter') {
if (!isset($letter)) {
$letter = $this->getLetter();
}
return "{$letter}. {$title}";
} elseif ($cfg['with'] == 'id') {
return "#{$this->info['id']}. {$title}";
} else {
return $title;
}
}
public function getUri($where = '') {
if (!$this->contest) {
return false;
}
return "/contest/{$this->contest->info['id']}/problem/{$this->info['id']}{$where}";
}
public function queryUserSubmissionCountInContest(array $user = null) {
if (!$user) {
return 0;
}
return DB::selectCount([
DB::lc(), "select count(*) from submissions",
"where", [
"submitter" => $user['username'],
"problem_id" => $this->info['id'],
"contest_id" => $this->contest->info['id'],
DB::lor([
[UOJSubmission::sqlForActualScore(), "is not", null],
['status', 'not like', 'Judged%']
])
]
]);
}
public function getJudgeTypeInContest() {
if (!isset($this->contest->info['extra_config']["problem_{$this->info['id']}"])) {
return $this->contest->defaultProblemJudgeType();
} else {
return $this->contest->info['extra_config']["problem_{$this->info['id']}"];
}
}
public function isBonus() {
return isset($this->contest->info['extra_config']['bonus']["problem_{$this->info['id']}"]);
}
public function submitTimeLimit() {
if (isset($this->contest->info['extra_config']['submit_time_limit']["problem_{$this->info['id']}"])) {
return $this->contest->info['extra_config']['submit_time_limit']["problem_{$this->info['id']}"];
} else {
return -1;
}
}
public function userCanClickZan(array $user = null) {
return $this->userCanView($user) && $this->contest->progress() > CONTEST_IN_PROGRESS;
}
public function userCanView(array $user = null, array $cfg = []) {
$cfg += ['check-register' => true];
return $this->contest->userCanView($user, $cfg);
}
public function userCanDownloadAttachments(array $user = null) {
return $this->userCanView($user);
}
public function preHackCheck(array $user = null) {
return $this->info['hackable'] && !$this->info['is_hidden'];
}
public function preSubmitCheck() {
if ($this->contest->userCanManage(Auth::user())) {
return true;
}
if ($this->contest->progress() > CONTEST_IN_PROGRESS && !parent::userCanView(Auth::user())) {
return '比赛已结束,请耐心等待管理员在题库公开题目后再提交哦~';
}
return true;
}
public function additionalSubmissionComponentsCannotBeSeenByUser(array $user = null, UOJSubmission $submission) {
// excluding manager_view, score; don't check whether $user is a manager
if ($this->contest->progress() == CONTEST_IN_PROGRESS) {
if ($submission->userIsSubmitter($user)) {
if ($this->getJudgeTypeInContest() == 'no-details') {
return ['low_level_details'];
} else {
return [];
}
} else {
return ['content', 'high_level_details', 'low_level_details'];
}
} else {
return [];
}
}
}