feat: edit contest self reviews

This commit is contained in:
Baoshuo Ren 2022-09-20 07:49:45 +08:00
parent b0773acab8
commit 945bd35776
Signed by: baoshuo
GPG Key ID: 00CB9680AB29F51A
5 changed files with 129 additions and 50 deletions

View File

@ -283,6 +283,56 @@
} else { } else {
$reply_question = null; $reply_question = null;
} }
} elseif ($cur_tab == 'self_reviews') {
if (hasParticipated(Auth::user(), $contest)) {
$self_reviews_update_form = new UOJForm('self_review_update');
$self_reviews_update_form->ctrl_enter_submit = true;
$contest_problems = DB::selectAll("select problem_id from contests_problems where contest_id = {$contest['id']} order by dfn, problem_id");
for ($i = 0; $i < count($contest_problems); $i++) {
$contest_problems[$i]['problem'] = queryProblemBrief($contest_problems[$i]['problem_id']);
}
for ($i = 0; $i < count($contest_problems); $i++) {
$content = DB::selectFirst("select content from contests_reviews where contest_id = {$contest['id']} and problem_id = {$contest_problems[$i]['problem_id']} and poster = '{$myUser['username']}'")['content'];
$self_reviews_update_form->addVTextArea('self_review_update__problem_' . chr(ord('A') + $i), '<b>' . chr(ord('A') + $i) . '</b>: ' . $contest_problems[$i]['problem']['title'], $content,
function ($content) {
return '';
},
null,
true
);
}
$content = DB::selectFirst("select content from contests_reviews where contest_id = {$contest['id']} and problem_id = -1 and poster = '{$myUser['username']}'")['content'];
$self_reviews_update_form->addVTextArea('self_review_update__overall', '比赛总结', $content,
function ($content) {
return '';
},
null,
true
);
$self_reviews_update_form->handle = function() {
global $contest, $contest_problems, $myUser;
for ($i = 0; $i < count($contest_problems); $i++) {
if (isset($_POST['self_review_update__problem_' . chr(ord('A') + $i)])) {
$esc_content = DB::escape($_POST['self_review_update__problem_' . chr(ord('A') + $i)]);
$problem_id = $contest_problems[$i]['problem_id'];
DB::query("replace into contests_reviews (contest_id, problem_id, poster, content) values ({$contest['id']}, $problem_id, '{$myUser['username']}', '$esc_content')");
}
}
if (isset($_POST['self_review_update__overall'])){
$esc_content = DB::escape($_POST['self_review_update__overall']);
DB::query("replace into contests_reviews (contest_id, problem_id, poster, content) values ({$contest['id']}, -1, '{$myUser['username']}', '$esc_content')");
}
};
$self_reviews_update_form->runAtServer();
}
} }
function echoDashboard() { function echoDashboard() {
@ -508,7 +558,7 @@ EOD;
<?php endif ?> <?php endif ?>
<div class="col-sm-3"> <div class="col-sm-3">
<?php <?php
if ($contest['cur_progress'] <= CONTEST_IN_PROGRESS) { if ($contest['cur_progress'] <= CONTEST_IN_PROGRESS) {
echoContestCountdown(); echoContestCountdown();
} elseif ($contest['cur_progress'] <= CONTEST_TESTING) { } elseif ($contest['cur_progress'] <= CONTEST_TESTING) {
@ -517,21 +567,21 @@ EOD;
echoContestFinished(); echoContestFinished();
} }
?> ?>
<?php if ($cur_tab == 'standings' || $cur_tab == 'after_contest_standings'): ?> <?php if ($cur_tab == 'standings' || $cur_tab == 'after_contest_standings' || $cur_tab == 'self_reviews'): ?>
</div> </div>
<div class="col-sm-3"> <div class="col-sm-3">
<?php endif ?> <?php endif ?>
<?php if (!isset($contest['extra_config']['contest_type']) || $contest['extra_config']['contest_type']=='OI'):?> <?php if (!isset($contest['extra_config']['contest_type']) || $contest['extra_config']['contest_type']=='OI'):?>
<p>此次比赛为OI赛制。</p> <p>此次比赛为OI赛制。</p>
<p><strong>注意:比赛时只显示测样例的结果。</strong></p> <p><strong>注意:比赛时只显示测样例的结果。</strong></p>
<?php elseif ($contest['extra_config']['contest_type']=='IOI'):?> <?php elseif ($contest['extra_config']['contest_type'] == 'IOI'): ?>
<p>此次比赛为IOI赛制。</p> <p>此次比赛为IOI赛制。</p>
<p><strong>注意:比赛时显示测试所有数据的结果,但无法看到详细信息。</strong></p> <p><strong>注意:比赛时显示测试所有数据的结果,但无法看到详细信息。</strong></p>
<?php endif?> <?php endif?>
<a href="/contest/<?=$contest['id']?>/registrants" class="btn btn-info btn-block"><?= UOJLocale::get('contests::contest registrants') ?></a> <a href="/contest/<?=$contest['id']?>/registrants" class="btn btn-info btn-block"><?= UOJLocale::get('contests::contest registrants') ?></a>
<?php if (isSuperUser($myUser)): ?> <?php if (isSuperUser($myUser)): ?>
<a href="/contest/<?=$contest['id']?>/manage" class="btn btn-primary btn-block">管理</a> <a href="/contest/<?=$contest['id']?>/manage" class="btn btn-primary btn-block">管理</a>
<?php if (isset($start_test_form)): ?> <?php if (isset($start_test_form)): ?>
<div class="top-buffer-sm"> <div class="top-buffer-sm">
<?php $start_test_form->printHTML(); ?> <?php $start_test_form->printHTML(); ?>
@ -543,24 +593,28 @@ EOD;
</div> </div>
<?php endif ?> <?php endif ?>
<?php endif ?> <?php endif ?>
<?php if (isset($self_reviews_update_form)) { ?>
<?php if ($contest['extra_config']['links']) { ?> </div>
<div class="col-sm-6">
<h4>修改我的赛后总结</h4>
<?php $self_reviews_update_form->printHTML(); ?>
<?php } elseif ($contest['extra_config']['links'] && $cur_tab != 'self_reviews') { ?>
<?php if ($cur_tab == 'standings'): ?> <?php if ($cur_tab == 'standings'): ?>
</div> </div>
<div class="col-sm-3"> <div class="col-sm-3">
<div class="card border-info"> <div class="card border-info">
<?php else: ?> <?php else: ?>
<div class="card border-info top-buffer-lg"> <div class="card border-info top-buffer-lg">
<?php endif ?> <?php endif ?>
<div class="card-header bg-info"> <div class="card-header bg-info">
<h3 class="card-title">比赛资料</h3> <h3 class="card-title">比赛资料</h3>
</div>
<div class="list-group">
<?php foreach ($contest['extra_config']['links'] as $link) { ?>
<a href="/blogs/<?=$link[1]?>" class="list-group-item"><?=$link[0]?></a>
<?php } ?>
</div>
</div> </div>
<div class="list-group">
<?php foreach ($contest['extra_config']['links'] as $link) { ?>
<a href="/blogs/<?=$link[1]?>" class="list-group-item"><?=$link[0]?></a>
<?php } ?>
</div>
</div>
<?php } ?> <?php } ?>
</div> </div>
</div> </div>

View File

@ -109,12 +109,20 @@ function calcStandings($contest, $contest_data, &$score, &$standings, $update_co
} }
$score[$submission[2]][$submission[3]] = array($submission[4], $penalty, $submission[0]); $score[$submission[2]][$submission[3]] = array($submission[4], $penalty, $submission[0]);
}
if ($show_reviews) { if ($show_reviews) {
$review_result = DB::selectFirst("select content from contests_reviews where contest_id = {$contest['id']} and problem_id = {$contest_data['problems'][$submission[3]]} and poster = '{$person[0]}'"); foreach ($contest_data['people'] as $person) {
foreach ($contest_data['problems'] as $key => $problem) {
$review_result = DB::selectFirst("select content from contests_reviews where contest_id = {$contest['id']} and problem_id = {$problem} and poster = '{$person[0]}'");
if ($review_result['content']) { if (!isset($score[$person[0]][$key])) {
$score[$submission[2]][$submission[3]][] = $review_result['content']; $score[$person[0]][$key] = array(0, 0, 0);
}
if ($review_result['content']) {
$score[$person[0]][$key][] = $review_result['content'];
}
} }
} }
} }
@ -135,7 +143,7 @@ function calcStandings($contest, $contest_data, &$score, &$standings, $update_co
} }
if ($show_reviews) { if ($show_reviews) {
$review_result = DB::selectFirst("select content from contests_reviews where contest_id = {$contest['id']} and poster = '{$person[0]}'"); $review_result = DB::selectFirst("select content from contests_reviews where contest_id = {$contest['id']} and problem_id = -1 and poster = '{$person[0]}'");
if ($review_result['content']) { if ($review_result['content']) {
$cur[] = $review_result['content']; $cur[] = $review_result['content'];

View File

@ -71,12 +71,18 @@
$this->ajax_submit_js = $js; $this->ajax_submit_js = $js;
} }
public function add($name, $html, $validator_php, $validator_js) { public function add($name, $html, $validator_php, $validator_js, $no_val = false) {
$this->main_html .= $html; $this->main_html .= $html;
$this->data[] = array( $data = array(
'name' => $name, 'name' => $name,
'validator_php' => $validator_php, 'validator_php' => $validator_php,
'validator_js' => $validator_js); 'validator_js' => $validator_js);
if ($no_val) {
$data['no_val'] = '';
}
$this->data[] = $data;
} }
public function appendHTML($html) { public function appendHTML($html) {
$this->main_html .= $html; $this->main_html .= $html;
@ -183,7 +189,7 @@ EOD;
); );
} }
public function addTextArea($name, $label_text, $default_value, $validator_php, $validator_js) { public function addTextArea($name, $label_text, $default_value, $validator_php, $validator_js, $no_val = false) {
$default_value = htmlspecialchars($default_value); $default_value = htmlspecialchars($default_value);
$this->is_big = true; $this->is_big = true;
$html = <<<EOD $html = <<<EOD
@ -195,9 +201,9 @@ EOD;
</div> </div>
</div> </div>
EOD; EOD;
$this->add($name, $html, $validator_php, $validator_js); $this->add($name, $html, $validator_php, $validator_js, $no_val);
} }
public function addVTextArea($name, $label_text, $default_value, $validator_php, $validator_js) { public function addVTextArea($name, $label_text, $default_value, $validator_php, $validator_js, $no_val = false) {
$default_value = htmlspecialchars($default_value); $default_value = htmlspecialchars($default_value);
$this->is_big = true; $this->is_big = true;
$html = <<<EOD $html = <<<EOD
@ -207,7 +213,7 @@ EOD;
<span class="help-block" id="help-$name"></span> <span class="help-block" id="help-$name"></span>
</div> </div>
EOD; EOD;
$this->add($name, $html, $validator_php, $validator_js); $this->add($name, $html, $validator_php, $validator_js, $no_val);
} }
public function addCheckBox($name, $label_text, $default_value) { public function addCheckBox($name, $label_text, $default_value) {
$default_value = htmlspecialchars($default_value); $default_value = htmlspecialchars($default_value);

View File

@ -41,6 +41,11 @@ function hasRegistered($user, $contest) {
function hasAC($user, $problem) { function hasAC($user, $problem) {
return DB::selectFirst("select * from best_ac_submissions where submitter = '${user['username']}' and problem_id = ${problem['id']}") != null; return DB::selectFirst("select * from best_ac_submissions where submitter = '${user['username']}' and problem_id = ${problem['id']}") != null;
} }
function hasParticipated($user, $contest) {
$result = DB::selectFirst("select * from contests_registrants where username = '${user['username']}' and contest_id = ${contest['id']}");
return $result != null && $result['has_participated'];
}
function queryUser($username) { function queryUser($username) {
if (!validateUsername($username)) { if (!validateUsername($username)) {

View File

@ -1079,25 +1079,31 @@ function showStandings() {
col_tr += '<td>' + getUserLink(row[2][0], row[2][1]) + '</td>'; col_tr += '<td>' + getUserLink(row[2][0], row[2][1]) + '</td>';
col_tr += '<td>' + '<div><span class="uoj-score" data-max="' + problems.length * 100 + '" style="color:' + getColOfScore(row[0] / problems.length) + '">' + row[0] + '</span></div>' + '<div>' + getPenaltyTimeStr(row[1]) + '</div></td>'; col_tr += '<td>' + '<div><span class="uoj-score" data-max="' + problems.length * 100 + '" style="color:' + getColOfScore(row[0] / problems.length) + '">' + row[0] + '</span></div>' + '<div>' + getPenaltyTimeStr(row[1]) + '</div></td>';
for (var i = 0; i < problems.length; i++) { for (var i = 0; i < problems.length; i++) {
col_tr += '<td>'; col_tr += '<td' + (show_self_reviews ? ' style="vertical-align: text-top"' : '') + '>';
col = score[row[2][0]][i]; col = score[row[2][0]][i];
if (col != undefined) { if (col != undefined) {
col_tr += '<div><a href="/submission/' + col[2] + '" class="uoj-score" style="color:' + getColOfScore(col[0]) + '">' + col[0] + '</a></div>'; col_tr += '<div>';
if (standings_version < 2) {
col_tr += '<div>' + getPenaltyTimeStr(col[1]) + '</div>'; if (col[2]) col_tr += '<a href="/submission/' + col[2] + '" class="uoj-score" style="color:' + getColOfScore(col[0]) + '">' + col[0] + '</a>';
} else { else col_tr += '<span class="uoj-score" style="color:' + getColOfScore(col[0]) + '">' + col[0] + '</span>';
if (col[0] > 0) {
col_tr += '<div>' + getPenaltyTimeStr(col[1]) + '</div>'; col_tr += '</div>';
}
}
if (show_self_reviews) { if (show_self_reviews) {
col_tr += '<div id="review-' + row[2][0] + '-' + i + '"></div>' col_tr += '<div id="review-' + row[2][0] + '-' + i + '"></div>'
+ '<script>' + '<script>'
+ '$(function() {' + '$(function() {'
+ 'var purify_result = DOMPurify.sanitize(\'' + String(col[3] || '').replace(/'/g, '\\\'').replace(new RegExp('</scr' + 'ipt>', 'gi'), '</scr\' + \'ipt>') + '\', {ALLOWED_TAGS: ["a", "b", "i", "u", "em", "strong", "sub", "sup", "small", "del"], ALLOWED_ATTR: ["href"]});' + 'var purify_result = DOMPurify.sanitize(decodeURIComponent("' + encodeURIComponent(String(col[3] || '')) + '"), {ALLOWED_TAGS: ["a", "b", "i", "u", "em", "strong", "sub", "sup", "small", "del", "br"], ALLOWED_ATTR: ["href"]});'
+ '$("#review-' + row[2][0] + '-' + i + '")' + '$("#review-' + row[2][0] + '-' + i + '")'
+ '.html(purify_result ? \'<div class="mt-3 pt-2 border-top">\' + purify_result + \'</div>\' : \'\'); });' + '.html(purify_result ? \'<div class="mt-2 pt-2 border-top">\' + purify_result + \'</div>\' : \'\'); });'
+ '</scr' + 'ipt>'; + '</scr' + 'ipt>';
} else {
if (standings_version < 2) {
col_tr += '<div>' + getPenaltyTimeStr(col[1]) + '</div>';
} else {
if (col[0] > 0) {
col_tr += '<div>' + getPenaltyTimeStr(col[1]) + '</div>';
}
}
} }
} }
col_tr += '</td>'; col_tr += '</td>';
@ -1107,7 +1113,7 @@ function showStandings() {
col_tr += '<td><div id="review-' + row[2][0] + '"></div>' col_tr += '<td><div id="review-' + row[2][0] + '"></div>'
+ '<script>' + '<script>'
+ '$(function() { $("#review-' + row[2][0] + '")' + '$(function() { $("#review-' + row[2][0] + '")'
+ '.html(DOMPurify.sanitize(\'' + String(row[4] || '').replace(/'/g, '\\\'').replace(new RegExp('</scr' + 'ipt>', 'gi'), '</scr\' + \'ipt>') + '\', {ALLOWED_TAGS: ["a", "b", "i", "u", "em", "strong", "sub", "sup", "small", "del"], ALLOWED_ATTR: ["href"]})); });' + '.html(DOMPurify.sanitize(decodeURIComponent("' + encodeURIComponent(String(row[4] || '')) + '"), {ALLOWED_TAGS: ["a", "b", "i", "u", "em", "strong", "sub", "sup", "small", "del"], ALLOWED_ATTR: ["href"]})); });'
+ '</scr' + 'ipt></td>'; + '</scr' + 'ipt></td>';
} }
col_tr += '</tr>'; col_tr += '</tr>';