Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion app/.default-userinfo.php
Original file line number Diff line number Diff line change
Expand Up @@ -132,4 +132,4 @@ function (str) {
return $res;
}
)
);
);
3 changes: 3 additions & 0 deletions app/controllers/click_zan.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ function validateZan() {
if (!Auth::check()) {
die('<div class="text-danger">please <a href="' . HTML::url('/login') . '">login</a></div>');
}
if (!isBlogAllowedUser(Auth::user())) {
die('<div class="text-danger">permission denied</div>');
}

$id = $_POST['id'];
$delta = $_POST['delta'];
Expand Down
152 changes: 152 additions & 0 deletions app/controllers/collection.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
<?php
requirePHPLib('form');
requirePHPLib('judger');
requirePHPLib('data');
requirePHPLib('problem');

if (!Auth::check()) {
redirectToLogin();
}

function isValidProblemId($id) {
return preg_match('/^[a-z0-9]{1,12}$/', $id);
}

if (isset($_POST['state'])) {
$state = (int)$_POST['state'];
if(!isset($_POST['id'])) die('id not set');
$id = $_POST['id'];
if(!isValidProblemId($id)) die('invalid id');
if(!DB::selectCount("select count(*) from collection where id = '$id'")) die('no such problem');
if(!($state >= 0 && $state <= 2)) die('invalid state');
$username = Auth::id();
DB::insert("insert into collection_state (id, username, state) values ('$id', '$username', $state) on duplicate key update state = $state");
die('ok');
}

function echoProblem($problem) {
$username = Auth::id();
if (isBlogAllowedUser(Auth::user())) {
$state = 0;
$stateResult = DB::selectFirst("select state from collection_state where id = '{$problem['id']}' and username = '$username'");
if(isset($stateResult)) $state = $stateResult['state'];
$color = ['fff','feb','dfb'][$state];
echo '<tr style="background-color: #'.$color.'" id="problem-'.$problem['id'].'">';
echo '<td class="text-center">';
echo $problem['id'], '</td>';
echo '<td>';
echo '<div style="display: flex; justify-content: space-between">';
echo '<span style="text-align: left">';
echo '<a href="', $problem['url'], '">', $problem['title'], '</a>';
echo '</span>';
echo '<span style="text-align: right">';
echo '<a class="glyphicon glyphicon-remove" onclick=\'changeProblemState(0,"'.$problem['id'].'");\'></a> ';
echo '<a style="color: #aa0" class="glyphicon glyphicon-question-sign" onclick=\'changeProblemState(1,"'.$problem['id'].'");\'></a> ';
echo '<a class="glyphicon glyphicon-ok" onclick=\'changeProblemState(2,"'.$problem['id'].'");\'></a>';
echo '</span>';
echo '</div>';
echo '</td>';
echo '<td class="text-left">';
echo $problem['note'];
echo '</td>';
echo '</tr>';
}
}

$cur_tab = isset($_GET['type']) ? $_GET['type'] : 'null';

$cond = "exists (select 1 from collection_tags where collection_tags.collection_id = collection.id and collection_tags.tag = '{$cur_tab}')";

$header = '<tr>';
$header .= '<th class="text-center" style="width: 5em">ID</th>';
$header .= '<th>' . UOJLocale::get('problems::problem') . '</th>';
$header .= '<th>' . UOJLocale::get('note') . '</th>';
$header .= '</tr>';

$tabs_info = array(
'counting' => array(
'name' => 'Counting',
'url' => '/collection?type=counting'
),
'constructive' => array(
'name' => 'Constructive',
'url' => '/collection?type=constructive'
),
'interactive' => array(
'name' => 'Interactive',
'url' => '/collection?type=interactive'
),
);

$pag_config = array('page_len' => 1000);
$pag_config['col_names'] = array('*');
$username = Auth::id();
$pag_config['table_name'] = "collection";
$pag_config['cond'] = $cond;
$pag_config['tail'] = 'order by id asc';
$pag_config['max_extend'] = 5;
$pag_config['timeout'] = 1000;
$pag = new Paginator($pag_config);

$div_classes = array('table-responsive');
$table_classes = array('table', 'table-bordered', 'table-hover', 'table-striped');
?>
<?php echoUOJPageHeader(UOJLocale::get('problem collection')) ?>
<script>
function changeProblemState(state, id) {
title = document.getElementById('problem-' + id).children[1].children[0].children[0].textContent;
if(!confirm(id + ' - ' + title + '\n' + ['Unsolved', 'Uncertain', 'Solved'][state] + '?')) return;
$.post('/collection', {
'state': state,
'id': id,
}, function(msg) {
if (msg == 'ok') {
window.location.reload();
} else {
alert('修改失败:' + msg);
}
});
}
</script>
<div class="row">
<div class="col-xs-6 col-sm-6">
<?= HTML::tablist($tabs_info, $cur_tab, 'nav-pills') ?>
</div>
<?php if(isBlogAllowedUser(Auth::user())):?>
<div class="col-xs-3 col-sm-3">
<ul class="nav nav-pills" role="tablist"><li><a href="/collection/propose"><span class="glyphicon glyphicon-send"></span> <?= UOJLocale::get('propose') ?></a></li></ul>
</div>
<?php endif?>
<?php if(isProblemCreator(Auth::user())):?>
<div class="col-xs-3 col-sm-3">
<ul class="nav nav-pills" role="tablist"><li><a href="/collection/manage"><span class="glyphicon glyphicon-cog"></span> <?= UOJLocale::get('manage') ?></a></li></ul>
</div>
<?php endif?>
</div>
<div class="top-buffer-sm"></div>
<div class="top-buffer-sm"></div>
<div class="row">
<div class="col-xs-12 col-sm-12 input-group">
<?php echo $pag->pagination(); ?>
</div>
</div>
<div class="top-buffer-sm"></div>
<?php
echo '<div class="', join($div_classes, ' '), '">';
echo '<table class="', join($table_classes, ' '), '">';
echo '<thead>';
echo $header;
echo '</thead>';
echo '<tbody>';

foreach ($pag->get() as $idx => $row) {
echoProblem($row);
}

echo '</tbody>';
echo '</table>';
echo '</div>';

echo $pag->pagination();
?>
<?php echoUOJPageFooter() ?>
182 changes: 182 additions & 0 deletions app/controllers/collection_manage.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,182 @@
<?php
requirePHPLib('form');
requirePHPLib('judger');
requirePHPLib('data');
requirePHPLib('problem');

if (!Auth::check()) {
redirectToLogin();
}

if(!isProblemCreator(Auth::user())) {
become403Page();
}

function echoProblem($problem) {
if (isBlogAllowedUser(Auth::user())) {
echo '<tr class="text-center">';
echo '<td>';
echo $problem['id'], '</td>';
echo '<td class="text-left">';
echo '<a href="', $problem['url'], '">', $problem['title'], '</a>';
foreach (queryCollectionTags($problem['id']) as $tag) {
echo '<a class="uoj-collection-tag">', '<span class="badge">', HTML::escape($tag), '</span>', '</a>';
}
echo '</td>';
echo '<td class="text-left">';
echo $problem['note'];
echo '</td>';
echo '</tr>';
}
}

$cur_tab = isset($_GET['type']) ? $_GET['type'] : 'null';

$cond = "1";

$header = '<tr>';
$header .= '<th class="text-center" style="width: 5em">ID</th>';
$header .= '<th>' . UOJLocale::get('problems::problem') . '</th>';
$header .= '<th>' . UOJLocale::get('note') . '</th>';
$header .= '</tr>';

$pag_config = array('page_len' => 10000);
$pag_config['col_names'] = array('*');
$username = Auth::id();
$pag_config['table_name'] = "collection";
$pag_config['cond'] = $cond;
$pag_config['tail'] = 'order by id asc';
$pag_config['max_extend'] = 5;
$pag_config['timeout'] = 1000;
$pag = new Paginator($pag_config);

$div_classes = array('table-responsive');
$table_classes = array('table', 'table-bordered', 'table-hover', 'table-striped');

$proposal = DB::selectFirst("select * from collection_proposal");

$append_form = new UOJForm('append');

$append_form->addInput('id', 'text', 'id', $proposal['id'],
function($result) {
if(!preg_match('/^-?[a-z0-9]{1,12}$/', $result)) return '题号长度不能超过 12,且只能包含小写字母和数字';
return '';
},
null
);
$append_form->addInput('title', 'text', 'title', $proposal['title'],
function($result) {
if(strlen($result) > 100) return '长度不能超过 100 byte';
return '';
},
null
);
$append_form->addInput('url', 'text', 'url', $proposal['url'],
function($result) {
if(strlen($result) > 100) return '长度不能超过 100 byte';
return '';
},
null
);
$append_form->addInput('tag', 'text', 'tag', $proposal['tag'],
function($result) {
if(strlen($result) > 100) return '长度不能超过 100 byte';
return '';
},
null
);
$append_form->addInput('note', 'text', 'note', $proposal['note'],
function($result) {
if(strlen($result) > 100) return '长度不能超过 100 byte';
return '';
},
null
);

$append_form->handle = function() {
$id = $_POST['id'];
if ($id[0] == '-') {
$id = substr($id, 1);
DB::delete("delete from collection where id='$id'");
DB::delete("delete from collection_tags where collection_id='$id'");
return;
}
DB::delete("delete from collection_proposal where id='$id'");
$title = DB::escape($_POST['title']);
$url = DB::escape($_POST['url']);
$tag = DB::escape(strtolower($_POST['tag']));
$note = DB::escape($_POST['note']);

$upd_cmd = '';
if($title != '') $upd_cmd .= ", title='$title'";
if($url != '') $upd_cmd .= ", url='$url'";
if($note != '') {
if($note == '-') $note = '';
$upd_cmd .= ", note='$note'";
}
if($upd_cmd != '') {
DB::insert("insert into collection (id, title, url, note) values ('$id', '$title', '$url', '$note') on duplicate key update" . substr($upd_cmd, 1));
}
if($tag == '-') {
DB::delete("delete from collection_tags where collection_id='$id'");
}
else if($tag != '' && DB::selectCount("select count(*) from collection where id = '$id'")) {
DB::insert("insert ignore into collection_tags (collection_id, tag) values ('$id', '$tag')");
}
};
$append_form->runAtServer();
?>
<?php echoUOJPageHeader(UOJLocale::get('problem collection')) ?>
<?php echo '剩余:' . DB::selectCount("select count(*) from collection_proposal"); ?>
<?php $append_form->printHTML(); ?>
<h3>约定</h3>
选择一个题目所属的 OJ 时,按照以下顺序选择:
<ol>
<li>原出处,且有中文题面或英文题面</li>
<li>有中文题面</li>
<li>有英文题面</li>
<li>原出处,但无中文题面或英文题面</li>
<li>其他</li>
</ol>
有多个同一类的 OJ,按照以下优先级选择。
<h4>各 OJ 题号格式(按照优先级排序)</h4>
<table class="table table-bordered table-hover table-striped">
<tr><th>OJ</th><th>题号格式</th></tr>
<tr><td>AtCoder</td><td>agc001a</td></tr>
<tr><td>Codeforces Problemset</td><td>cf1a</td></tr>
<tr><td>UOJ</td><td>uoj1</td></tr>
<tr><td>QOJ</td><td>qoj1</td></tr>
<tr><td>LOJ</td><td>loj1</td></tr>
<tr><td>SOJ</td><td>soj1</td></tr>
<tr><td>Luogu</td><td>lg1001</td></tr>
<tr><td>Codeforces Gym</td><td>cf123456a</td></tr>
</table>
<ul>
<li>
对于 Codeforces 上的题目,使用<strong>题库风格 url</strong>。(<code>https://codeforces.com/problemset/problem/1/A</code>)
</li>
<li>
尽可能<strong>去除</strong> url 中的<strong>比赛编号</strong>。(<code>https://qoj.ac<del>/contest/259</del>/problem/2</code>)
</li>
</ul>
<h3>列表</h3>
<?php
echo '<div class="', join($div_classes, ' '), '">';
echo '<table class="', join($table_classes, ' '), '">';
echo '<thead>';
echo $header;
echo '</thead>';
echo '<tbody>';

foreach ($pag->get() as $idx => $row) {
echoProblem($row);
}

echo '</tbody>';
echo '</table>';
echo '</div>';

echo $pag->pagination();
?>
<script src="/js/soj_collection_id2url.js"></script>
<?php echoUOJPageFooter() ?>
Loading