mirror of
https://github.com/renbaoshuo/S2OJ.git
synced 2024-11-22 03:48:41 +00:00
feat(web,db): add groups
This commit is contained in:
parent
ee13bbcc29
commit
8703281ab3
@ -1,4 +1,4 @@
|
||||
FROM mysql:latest
|
||||
FROM mysql:5.7
|
||||
|
||||
ADD . /opt/uoj_db
|
||||
WORKDIR /opt/uoj_db
|
||||
|
@ -361,6 +361,33 @@ LOCK TABLES `custom_test_submissions` WRITE;
|
||||
/*!40000 ALTER TABLE `custom_test_submissions` ENABLE KEYS */;
|
||||
UNLOCK TABLES;
|
||||
|
||||
--
|
||||
-- Table structure for table `groups`
|
||||
--
|
||||
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8mb4 */;
|
||||
CREATE TABLE `groups` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`title` text NOT NULL,
|
||||
`is_hidden` tinyint(1) NOT NULL DEFAULT 0,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
--
|
||||
-- Table structure for table `groups_users`
|
||||
--
|
||||
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8mb4 */;
|
||||
CREATE TABLE `groups_users` (
|
||||
`group_id` int(11) NOT NULL,
|
||||
`username` varchar(20) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||
PRIMARY KEY (`group_id`, `username`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
--
|
||||
-- Table structure for table `hacks`
|
||||
--
|
||||
|
@ -10,6 +10,68 @@
|
||||
}
|
||||
genMoreContestInfo($contest);
|
||||
|
||||
if (isSuperUser($myUser)) {
|
||||
$add_new_contestant_form = new UOJForm('add_new_contestant_form');
|
||||
$add_new_contestant_form->addInput('new_username', 'text', '用户名', '',
|
||||
function ($x) {
|
||||
global $contest;
|
||||
|
||||
if (!validateUsername($x)) return '用户名不合法';
|
||||
$user = queryUser($x);
|
||||
if (!$user) return '用户不存在';
|
||||
|
||||
if (hasRegistered($user, $contest)) {
|
||||
return '该用户已经报名';
|
||||
}
|
||||
return '';
|
||||
},
|
||||
null
|
||||
);
|
||||
$add_new_contestant_form->submit_button_config['align'] = 'compressed';
|
||||
$add_new_contestant_form->submit_button_config['text'] = '注册该用户';
|
||||
$add_new_contestant_form->handle = function() {
|
||||
global $contest;
|
||||
$username = $_POST['new_username'];
|
||||
|
||||
$user = queryUser($username);
|
||||
if (!$user) return;
|
||||
|
||||
DB::query("replace into contests_registrants (username, user_rating, contest_id, has_participated) values ('{$user['username']}', {$user['rating']}, {$contest['id']}, 0)");
|
||||
|
||||
updateContestPlayerNum($contest);
|
||||
};
|
||||
$add_new_contestant_form->runAtServer();
|
||||
|
||||
$add_group_to_contest_form = new UOJForm('add_group_to_contest');
|
||||
$add_group_to_contest_form->addInput('group_id', 'text', '小组 ID', '',
|
||||
function ($x) {
|
||||
global $contest;
|
||||
|
||||
if (!validateUInt($x)) return '小组 ID 不合法';
|
||||
$group = queryGroup($x);
|
||||
if (!$group) return '小组不存在';
|
||||
|
||||
return '';
|
||||
},
|
||||
null
|
||||
);
|
||||
$add_group_to_contest_form->submit_button_config['align'] = 'compressed';
|
||||
$add_group_to_contest_form->submit_button_config['text'] = '注册该小组中的用户';
|
||||
$add_group_to_contest_form->handle = function() {
|
||||
global $contest;
|
||||
$group_id = $_POST['group_id'];
|
||||
|
||||
$users = DB::selectAll("select b.username as username, b.rating as rating from groups_users a inner join user_info b on a.username = b.username where a.group_id = $group_id");
|
||||
|
||||
foreach ($users as $user) {
|
||||
DB::query("replace into contests_registrants (username, user_rating, contest_id, has_participated) values ('{$user['username']}', {$user['rating']}, {$contest['id']}, 0)");
|
||||
}
|
||||
|
||||
updateContestPlayerNum($contest);
|
||||
};
|
||||
$add_group_to_contest_form->runAtServer();
|
||||
}
|
||||
|
||||
$has_contest_permission = hasContestPermission($myUser, $contest);
|
||||
$show_ip = $has_contest_permission;
|
||||
|
||||
@ -86,6 +148,14 @@
|
||||
array('page_len' => 100,
|
||||
'get_row_index' => '',
|
||||
'print_after_table' => function() {
|
||||
global $add_new_contestant_form, $add_group_to_contest_form;
|
||||
|
||||
if (isset($add_new_contestant_form)) {
|
||||
$add_new_contestant_form->printHTML();
|
||||
}
|
||||
if (isset($add_group_to_contest_form)) {
|
||||
$add_group_to_contest_form->printHTML();
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
|
@ -15,7 +15,7 @@
|
||||
$register_form = new UOJForm('register');
|
||||
$register_form->handle = function() {
|
||||
global $myUser, $contest;
|
||||
DB::query("insert into contests_registrants (username, contest_id, has_participated) values ('{$myUser['username']}', {$contest['id']}, 0)");
|
||||
DB::query("replace into contests_registrants (username, contest_id, has_participated) values ('{$myUser['username']}', {$contest['id']}, 0)");
|
||||
updateContestPlayerNum($contest);
|
||||
};
|
||||
$register_form->submit_button_config['class_str'] = 'btn btn-primary';
|
||||
@ -28,11 +28,11 @@
|
||||
<h1 class="page-header">比赛规则</h1>
|
||||
<ul>
|
||||
<li>比赛报名后不算正式参赛,报名后进了比赛页面也不算参赛,<strong>看了题目才算正式参赛</strong>。</li>
|
||||
<li>比赛中途可以提交,若同一题有多次提交按<strong>最后一次不是Compile Error的提交</strong>算成绩。(其实UOJ会自动无视你所有Compile Error的提交当作没看见)</li>
|
||||
<li>比赛中途可以提交,若同一题有多次提交按<strong>最后一次不是 Compile Error 的提交</strong>算成绩。(其实UOJ会自动无视你所有 Compile Error 的提交)</li>
|
||||
<li>比赛中途提交后,可以看到<strong>测样例</strong>的结果。(若为提交答案题则对于每个测试点,该测试点有分则该测试点为满分)</li>
|
||||
<li>比赛结束后会进行最终测试,最终测试后的排名为最终排名。</li>
|
||||
<li>比赛排名按分数为第一关键字,完成题目的总时间为第二关键字。完成题目的总时间等于完成每道题所花时间之和(无视掉爆零的题目)。</li>
|
||||
<li>请遵守比赛规则,一位选手在一场比赛内不得报名多个账号,选手之间不能交流或者抄袭代码,如果被检测到将以0分处理或者封禁。</li>
|
||||
<li>请遵守比赛规则,一位选手在一场比赛内不得报名多个账号,选手之间不能交流或者抄袭代码,如果被检测到将以 0 分处理或者封禁。</li>
|
||||
</ul>
|
||||
<?php $register_form->printHTML(); ?>
|
||||
<?php echoUOJPageFooter() ?>
|
||||
|
128
web/app/controllers/group.php
Normal file
128
web/app/controllers/group.php
Normal file
@ -0,0 +1,128 @@
|
||||
<?php
|
||||
requirePHPLib('form');
|
||||
requirePHPLib('judger');
|
||||
requirePHPLib('data');
|
||||
|
||||
$group_id = $_GET['id'];
|
||||
$group = queryGroup($group_id);
|
||||
|
||||
if (isSuperUser($myUser)) {
|
||||
$group_editor = new UOJBlogEditor();
|
||||
$group_editor->name = 'group';
|
||||
$group_editor->blog_url = null;
|
||||
$group_editor->cur_data = array(
|
||||
'title' => $group['title'],
|
||||
'tags' => array(),
|
||||
'is_hidden' => $group['is_hidden']
|
||||
);
|
||||
$group_editor->label_text = array_merge($group_editor->label_text, array(
|
||||
'view blog' => '保存小组信息',
|
||||
'blog visibility' => '小组可见性'
|
||||
));
|
||||
$group_editor->show_editor = false;
|
||||
$group_editor->show_tags = false;
|
||||
|
||||
$group_editor->save = function($data) {
|
||||
global $group_id, $group;
|
||||
DB::update("update `groups` set title = '".DB::escape($data['title'])."' where id = {$group_id}");
|
||||
|
||||
if ($data['is_hidden'] != $group['is_hidden'] ) {
|
||||
DB::update("update `groups` set is_hidden = {$data['is_hidden']} where id = {$group_id}");
|
||||
}
|
||||
};
|
||||
$group_editor->runAtServer();
|
||||
|
||||
$add_new_user_form = new UOJForm('add_new_user');
|
||||
$add_new_user_form->addInput('new_username', 'text', '用户名', '',
|
||||
function ($x) {
|
||||
global $group_id;
|
||||
|
||||
if (!validateUsername($x)) return '用户名不合法';
|
||||
$user = queryUser($x);
|
||||
if (!$user) return '用户不存在';
|
||||
|
||||
if (queryUserInGroup($group_id, $x)) {
|
||||
return '该用户已经在小组中';
|
||||
}
|
||||
|
||||
return '';
|
||||
},
|
||||
null
|
||||
);
|
||||
$add_new_user_form->submit_button_config['align'] = 'compressed';
|
||||
$add_new_user_form->submit_button_config['text'] = '添加到小组';
|
||||
$add_new_user_form->handle = function() {
|
||||
global $group_id, $myUser;
|
||||
$username = $_POST['new_username'];
|
||||
|
||||
DB::insert("insert into groups_users (group_id, username) values ({$group_id}, '{$username}')");
|
||||
};
|
||||
$add_new_user_form->runAtServer();
|
||||
|
||||
$delete_user_form = new UOJForm('delete_user');
|
||||
$delete_user_form->addInput('del_username', 'text', '用户名', '',
|
||||
function ($x) {
|
||||
global $group_id;
|
||||
|
||||
if (!validateUsername($x)) return '用户名不合法';
|
||||
if (!queryUserInGroup($group_id, $x)) {
|
||||
return '该用户不在小组中';
|
||||
}
|
||||
|
||||
return '';
|
||||
},
|
||||
null
|
||||
);
|
||||
$delete_user_form->submit_button_config['align'] = 'compressed';
|
||||
$delete_user_form->submit_button_config['text'] = '从小组中删除';
|
||||
$delete_user_form->handle = function() {
|
||||
global $group_id, $myUser;
|
||||
$username = $_POST['del_username'];
|
||||
|
||||
DB::query("delete from groups_users where username='{$username}' and group_id={$group_id}");
|
||||
};
|
||||
$delete_user_form->runAtServer();
|
||||
}
|
||||
?>
|
||||
|
||||
<?php echoUOJPageHeader(UOJLocale::get('groups')) ?>
|
||||
|
||||
<h2 style="margin-top: 24px"><?= $group['title'] ?></h2>
|
||||
<p>(<b>小组 ID</b>: <?= $group['id'] ?>)</p>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-sm-12 mt-4">
|
||||
<h5><?= UOJLocale::get('news') ?></h5>
|
||||
<ul>
|
||||
<?php
|
||||
$current_ac = queryGroupCurrentAC($group['id']);
|
||||
foreach ($current_ac as $ac) {
|
||||
echo '<li>';
|
||||
echo getUserLink($ac['submitter']);
|
||||
echo ' 解决了问题 ';
|
||||
echo '<a href="/problem/', $ac['problem_id'], '">', $ac['problem_title'], '</a> ';
|
||||
echo '<time class="time">(', $ac['submit_time'], ')</time>';
|
||||
echo '</li>';
|
||||
}
|
||||
if (!$current_ac) {
|
||||
echo '(无)';
|
||||
}
|
||||
?>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php if (isSuperUser($myUser)): ?>
|
||||
<h5>编辑小组信息</h5>
|
||||
<div class="mb-4">
|
||||
<?php $group_editor->printHTML(); ?>
|
||||
</div>
|
||||
|
||||
<h5>添加用户到小组</h5>
|
||||
<?php $add_new_user_form->printHTML(); ?>
|
||||
|
||||
<h5>从小组中删除用户</h5>
|
||||
<?php $delete_user_form->printHTML(); ?>
|
||||
<?php endif ?>
|
||||
|
||||
<?php echoUOJPageFooter() ?>
|
78
web/app/controllers/groups.php
Normal file
78
web/app/controllers/groups.php
Normal file
@ -0,0 +1,78 @@
|
||||
<?php
|
||||
requirePHPLib('form');
|
||||
requirePHPLib('judger');
|
||||
requirePHPLib('data');
|
||||
|
||||
if (isSuperUser($myUser)) {
|
||||
$new_group_form = new UOJForm('new_group');
|
||||
$new_group_form->handle = function() {
|
||||
DB::query("insert into `groups` (title, is_hidden) values ('新小组', 1)");
|
||||
};
|
||||
$new_group_form->submit_button_config['align'] = 'right';
|
||||
$new_group_form->submit_button_config['class_str'] = 'btn btn-primary';
|
||||
$new_group_form->submit_button_config['text'] = UOJLocale::get('add new group');
|
||||
$new_group_form->submit_button_config['smart_confirm'] = '';
|
||||
$new_group_form->runAtServer();
|
||||
}
|
||||
|
||||
function echoGroup($group) {
|
||||
global $myUser;
|
||||
|
||||
echo '<tr class="text-center">';
|
||||
echo '<td>';
|
||||
echo '#', $group['group_id'], '</td>';
|
||||
|
||||
echo '<td class="text-left">';
|
||||
if ($group['is_hidden']) {
|
||||
echo ' <span class="text-danger">[隐藏]</span> ';
|
||||
}
|
||||
echo '<a href="/group/', $group['group_id'], '">', $group['title'], '</a>';
|
||||
echo '</td>';
|
||||
|
||||
echo "<td>{$group['user_count']}</td>";
|
||||
|
||||
echo '</tr>';
|
||||
}
|
||||
?>
|
||||
|
||||
<?php echoUOJPageHeader(UOJLocale::get('groups')) ?>
|
||||
|
||||
<?php
|
||||
$groups_caption = UOJLocale::get('groups');
|
||||
$users_caption = UOJLocale::get('users count');
|
||||
$header = <<<EOD
|
||||
<tr>
|
||||
<th class="text-center" style="width:5em;">ID</th>
|
||||
<th>{$groups_caption}</th>
|
||||
<th class="text-center" style="width:8em;">{$users_caption}</th>
|
||||
</tr>
|
||||
EOD;
|
||||
|
||||
if (isSuperUser($myUser)) {
|
||||
$cond = "1";
|
||||
} else {
|
||||
$cond = 'is_hidden = 0';
|
||||
}
|
||||
|
||||
$from = "`groups` a left join groups_users b on a.id = b.group_id";
|
||||
|
||||
echoLongTable(
|
||||
array('a.id as group_id', 'a.title as title', 'a.is_hidden as is_hidden', 'count(b.username) as user_count'),
|
||||
$from, $cond, 'group by a.id order by a.id asc',
|
||||
$header,
|
||||
'echoGroup',
|
||||
array('page_len' => 100,
|
||||
'table_classes' => array('table', 'table-bordered', 'table-hover', 'table-striped'),
|
||||
'print_after_table' => function() {
|
||||
global $myUser;
|
||||
if (isSuperUser($myUser)) {
|
||||
global $new_group_form;
|
||||
$new_group_form->printHTML();
|
||||
}
|
||||
},
|
||||
'head_pagination' => true
|
||||
)
|
||||
);
|
||||
?>
|
||||
|
||||
<?php echoUOJPageFooter() ?>
|
@ -82,6 +82,22 @@ function queryContestProblem($id) {
|
||||
return DB::selectFirst("select * from contest_problems where contest_id = $id", MYSQLI_ASSOC);
|
||||
}
|
||||
|
||||
function queryGroup($id) {
|
||||
return DB::selectFirst("select * from groups where id = $id", MYSQLI_ASSOC);
|
||||
}
|
||||
function queryUserInGroup($group_id, $username) {
|
||||
return DB::selectFirst("select * from groups_users where username='$username' and group_id='$group_id'", MYSQLI_ASSOC);
|
||||
}
|
||||
function queryGroupOfUser($username) {
|
||||
return DB::selectAll("select b.title as title, b.id as id from groups_users a inner join groups b on a.group_id = b.id where a.username = '$username' and b.is_hidden = 0 order by id", MYSQLI_ASSOC);
|
||||
}
|
||||
function queryGroupmateCurrentAC($username) {
|
||||
return DB::selectAll("select a.problem_id as problem_id, a.submitter as submitter, a.submission_id as submission_id, b.submit_time as submit_time, c.group_id as group_id, c.group_name as group_name, d.title as problem_title, b.submit_time as submit_time, e.realname as realname from best_ac_submissions a inner join submissions b on (a.submission_id = b.id) inner join (select a.username as username, any_value(a.group_id) as group_id, any_value(c.title) as group_name from groups_users a inner join (select a.group_id as group_id from groups_users a inner join groups b on a.group_id = b.id where a.username = '$username' and b.is_hidden = 0) b on a.group_id = b.group_id inner join groups c on a.group_id = c.id group by a.username) c on a.submitter = c.username inner join problems d on (a.problem_id = d.id and d.is_hidden = 0) inner join user_info e on a.submitter = e.username where b.submit_time > addtime(now(), '-360:00:00') order by b.submit_time desc limit 10", MYSQLI_ASSOC);
|
||||
}
|
||||
function queryGroupCurrentAC($group_id) {
|
||||
return DB::selectAll("select a.problem_id as problem_id, a.submitter as submitter, a.submission_id as submission_id, b.submit_time as submit_time, d.title as problem_title, b.submit_time as submit_time, e.realname as realname from best_ac_submissions a inner join submissions b on (a.submission_id = b.id) inner join groups_users c on (a.submitter = c.username and c.group_id = $group_id) inner join problems d on (a.problem_id = d.id and d.is_hidden = 0) inner join user_info e on (a.submitter = e.username) where b.submit_time > addtime(now(), '-360:00:00') order by b.submit_time desc limit 10", MYSQLI_ASSOC);
|
||||
}
|
||||
|
||||
function queryZanVal($id, $type, $user) {
|
||||
if ($user == null) {
|
||||
return 0;
|
||||
|
@ -11,6 +11,9 @@ return [
|
||||
'system manage' => 'System Manage',
|
||||
'contests' => 'Contests',
|
||||
'problems' => 'Problems',
|
||||
'groups' => 'Groups',
|
||||
'add new group' => 'Add new group',
|
||||
'users count' => 'Users',
|
||||
'submissions' => 'Submissions',
|
||||
'hacks' => 'Hack!',
|
||||
'blogs' => 'Blogs',
|
||||
@ -18,6 +21,7 @@ return [
|
||||
'all the announcements' => 'All the Announcements……',
|
||||
'help' => 'Help',
|
||||
'search' => 'Search',
|
||||
'news' => 'News',
|
||||
'username' => 'Username',
|
||||
'password' => 'Password',
|
||||
'new password' => 'New password',
|
||||
|
@ -11,6 +11,9 @@ return [
|
||||
'system manage' => '系统管理',
|
||||
'contests' => '比赛',
|
||||
'problems' => '题库',
|
||||
'groups' => '小组',
|
||||
'add new group' => '添加新小组',
|
||||
'users count' => '用户数量',
|
||||
'submissions' => '提交记录',
|
||||
'hacks' => 'Hack!',
|
||||
'blogs' => '博客',
|
||||
@ -18,6 +21,7 @@ return [
|
||||
'all the announcements' => '所有公告……',
|
||||
'help' => '帮助',
|
||||
'search' => '搜索',
|
||||
'news' => '最新动态',
|
||||
'username' => '用户名',
|
||||
'password' => '密码',
|
||||
'new password' => '新密码',
|
||||
|
@ -38,6 +38,9 @@ Route::group([
|
||||
Route::any('/hacks', '/hack_list.php');
|
||||
Route::any('/hack/{id}', '/hack.php');
|
||||
|
||||
Route::any('/groups', '/groups.php');
|
||||
Route::any('/group/{id}', '/group.php');
|
||||
|
||||
Route::any('/blogs', '/blogs.php');
|
||||
if (UOJConfig::$data['switch']['blog-domain-mode'] != 3) {
|
||||
Route::any('/blog/{id}', '/blog_show.php');
|
||||
|
@ -4,11 +4,15 @@
|
||||
<div class="col-sm-6">
|
||||
<?= HTML::div_vinput("{$editor->name}_title", 'text', $editor->label_text['title'], html_entity_decode($editor->cur_data['title'])) ?>
|
||||
</div>
|
||||
<?php if ($editor->show_tags): ?>
|
||||
<div class="col-sm-6">
|
||||
<?= HTML::div_vinput("{$editor->name}_tags", 'text', $editor->label_text['tags'], join(', ', $editor->cur_data['tags'])) ?>
|
||||
</div>
|
||||
<?php endif ?>
|
||||
</div>
|
||||
<?php if ($editor->show_editor): ?>
|
||||
<?= HTML::div_vtextarea("{$editor->name}_content_md", $editor->label_text['content'], $editor->cur_data['content_md']) ?>
|
||||
<?php endif ?>
|
||||
<div class="row mt-2">
|
||||
<div class="col-sm-6">
|
||||
<?php if ($editor->blog_url): ?>
|
||||
|
@ -7,6 +7,7 @@
|
||||
<ul class="nav navbar-nav mr-auto">
|
||||
<li class="nav-item"><a class="nav-link" href="<?= HTML::url('/contests') ?>"><span class="glyphicon glyphicon-stats"></span> <?= UOJLocale::get('contests') ?></a></li>
|
||||
<li class="nav-item"><a class="nav-link" href="<?= HTML::url('/problems') ?>"><span class="glyphicon glyphicon-list-alt"></span> <?= UOJLocale::get('problems') ?></a></li>
|
||||
<li class="nav-item"><a class="nav-link" href="<?= HTML::url('/groups') ?>"><span class="glyphicon glyphicon-education"></span> <?= UOJLocale::get('groups') ?></a></li>
|
||||
<li class="nav-item"><a class="nav-link" href="<?= HTML::url('/submissions') ?>"><span class="glyphicon glyphicon-tasks"></span> <?= UOJLocale::get('submissions') ?></a></li>
|
||||
<li class="nav-item"><a class="nav-link" href="<?= HTML::url('/hacks') ?>"><span class="glyphicon glyphicon-flag"></span> <?= UOJLocale::get('hacks') ?></a></li>
|
||||
<li class="nav-item"><a class="nav-link" href="<?= HTML::blog_list_url() ?>"><span class="glyphicon glyphicon-edit"></span> <?= UOJLocale::get('blogs') ?></a></li>
|
||||
|
Loading…
Reference in New Issue
Block a user