S2OJ/web/app/models/UOJSubmissionLikeTrait.php

287 lines
7.9 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
trait UOJSubmissionLikeTrait {
use UOJDataTrait;
/**
* @var UOJProblem|UOJContestProblem
*/
public $problem = null;
public static function getAndRememberSubmissionLanguage(array $content) {
$language = '/';
foreach ($content['config'] as $row) {
if (strEndWith($row[0], '_language')) {
$language = $row[1];
break;
}
}
if ($language != '/') {
Cookie::set('uoj_preferred_language', $language, time() + 60 * 60 * 24 * 365, '/');
}
return $language;
}
public function setProblem(array $cfg = []) {
$cfg += ['problem' => 'auto'];
$problem = $cfg['problem'] === 'auto' ? UOJProblem::query($this->info['problem_id']) : $cfg['problem'];
if (!($problem instanceof UOJProblem && $problem->info['id'] == $this->info['problem_id'])) {
return false;
}
if (isset($this->info['contest_id'])) {
if (!($problem instanceof UOJContestProblem && $problem->contest->info['id'] == $this->info['contest_id'])) {
$problem = new UOJContestProblem($problem->info, UOJContest::query($this->info['contest_id']));
if (!$problem->valid()) {
return false;
}
}
} else {
if ($problem instanceof UOJContestProblem) {
$problem = new UOJProblem($problem->info);
}
}
$this->problem = $problem;
return true;
}
public function userIsSubmitter(array $user = null) {
return $user && $this->info['submitter'] === $user['username'];
}
public function userCanView(array $user = null, array $cfg = []) {
$cfg += ['ensure' => false];
if (!$this->problem->userCanView($user) && !$this->userIsSubmitter($user)) {
$cfg['ensure'] && UOJResponse::page403();
return false;
} elseif (!$this->info['is_hidden']) {
return true;
} elseif ($this->userCanManageProblemOrContest($user)) {
return true;
} else {
$cfg['ensure'] && UOJResponse::page404();
return false;
}
}
public function userCanManageProblemOrContest(array $user = null) {
if (!$this->problem instanceof UOJContestProblem && $this->problem->userCanManage($user)) {
return true;
} elseif ($this->problem instanceof UOJContestProblem && $this->problem->contest->userCanManage($user)) {
return true;
} else {
return false;
}
}
public function userCanDelete(array $user = null) {
return isSuperUser($user);
}
public function publicStatus() {
return explode(', ', $this->info['status'])[0];
}
public function isWaiting() {
$status = $this->publicStatus();
return $status === 'Waiting' || $status === 'Waiting Rejudge';
}
public function hasJudged() {
return $this->publicStatus() === 'Judged';
}
public function userPermissionCodeCheck(array $user = null, $perm_code) {
switch ($perm_code) {
case 'SELF':
return $this->userIsSubmitter($user);
default:
return $this->problem->userPermissionCodeCheck($user, $perm_code);
}
}
public function viewerCanSeeStatusDetailsHTML(array $user = null) {
return $this->userIsSubmitter($user) && !$this->hasJudged();
}
public function getStatusDetailsHTML() {
return getSubmissionStatusDetailsHTML($this->publicStatus(), $this->info['status_details']);
}
public function getUri() {
return $this->info['id'];
}
public function getLink() {
return '<a class="text-decoration-none" href="' . $this->getUri() . '">#' . $this->info['id'] . '</a></td>';
}
public function getResult($key = null) {
if (!isset($this->info['result'])) {
return null;
}
$result = json_decode($this->info['result'], true);
if ($key === null) {
return $result;
}
return isset($result[$key]) ? $result[$key] : null;
}
public function getContent($key = null) {
if (!isset($this->info['content'])) {
return null;
}
$content = json_decode($this->info['content'], true);
if ($key === null) {
return $content;
}
return isset($content[$key]) ? $content[$key] : null;
}
public function echoContent() {
$content = $this->getContent();
if (!$content) {
return false;
}
$zip_file = new ZipArchive();
if ($zip_file->open(UOJContext::storagePath() . $content['file_name'], ZipArchive::RDONLY) !== true) {
echo <<<EOD
<div class="card mb-3">
<div class="card-header text-bg-danger fw-bold">
提交内容
</div>
<div class="card-body">
木有
</div>
</div>
EOD;
return false;
}
$config = [];
foreach ($content['config'] as $val) {
$config[$val[0]] = $val[1];
}
foreach ($this->problem->getSubmissionRequirement() as $req) {
if ($req['type'] == "source code") {
$file_content = $zip_file->getFromName("{$req['name']}.code");
if ($file_content === false) {
$file_content = '';
}
if (isset($config["{$req['name']}_language"])) {
$file_language = $config["{$req['name']}_language"];
} else {
$file_language = '?';
}
$file_content = uojTextEncode($file_content, array('allow_CR' => true, 'html_escape' => true));
$footer_text = UOJLocale::get('problems::source code') . ': ';
$footer_text .= UOJLang::getLanguageDisplayName($file_language);
$sh_class = UOJLang::getLanguagesCSSClass($file_language);
echo <<<EOD
<div class="card mb-3">
<div class="card-header fw-bold">
{$req['name']}
</div>
<div class="card-body">
<pre><code class="$sh_class bg-light rounded p-3">{$file_content}\n</code></pre>
</div>
<div class="card-footer">$footer_text</div>
</div>
EOD;
} elseif ($req['type'] == "text") {
$file_content = $zip_file->getFromName("{$req['file_name']}", 504);
if ($file_content === false) {
$file_content = '';
}
$file_content = strOmit($file_content, 500);
$file_content = uojTextEncode($file_content, array('allow_CR' => true, 'html_escape' => true));
$footer_text = UOJLocale::get('problems::text file');
echo <<<EOD
<div class="card mb-3">
<div class="card-header">
{$req['file_name']}
</div>
<div class="card-body">
<pre>\n{$file_content}\n</pre>
</div>
<div class="card-footer">$footer_text</div>
</div>
EOD;
} else if ($req['type'] == "remote submission") {
$remote_provider = UOJRemoteProblem::$providers[$req['name']];
$content = '';
if ($req['name'] == 'luogu') {
$content .= HTML::tag('div', [], [
'远端评测 ID',
HTML::tag(
'a',
[
'href' => "{$remote_provider['url']}/record/{$config['luogu_submission_id']}"
],
'R' . $config['luogu_submission_id']
),
]);
}
HTML::echoPanel('mb-3', '远端评测记录', $content);
}
}
$zip_file->close();
return true;
}
protected function echoStatusBarTDBase($name, array $cfg) {
switch ($name) {
case 'id':
echo $this->getLink();
break;
case 'problem':
if ($this->problem) {
echo $this->problem->getLink(isset($cfg['problem_title']) ? $cfg['problem_title'] : []);
} else {
echo '<span class="text-danger">?</span>';
}
break;
case 'submitter':
case 'owner':
case 'hacker':
echo UOJUser::getLink($this->info[$name]);
break;
case 'used_time':
if ($cfg['show_actual_score']) {
echo $this->info['used_time'] . 'ms';
} else {
echo '/';
}
break;
case 'used_memory':
if ($cfg['show_actual_score']) {
echo $this->info['used_memory'] . 'kb';
} else {
echo '/';
}
break;
case 'tot_size':
if ($this->info['tot_size'] < 1024) {
echo $this->info['tot_size'] . 'b';
} else {
echo sprintf("%.1f", $this->info['tot_size'] / 1024) . 'kb';
}
break;
case 'submit_time':
case 'judge_time':
echo '<small>', $this->info[$name], '</small>';
break;
default:
echo '?';
break;
}
}
}