移除官方版本文档和题目示例

This commit is contained in:
MascoSkray 2017-04-05 13:09:06 +00:00 committed by Too-Naive
parent a0ac25e42e
commit 949ef0e573
16 changed files with 0 additions and 489 deletions

1
docs/.gitignore vendored
View File

@ -1 +0,0 @@
site/

View File

@ -1,4 +0,0 @@
# 关于
文档编写vfleaking
邮件vfleaking@163.com

View File

@ -1,3 +0,0 @@
# 比赛
<p style="font-size:233px"></p>

View File

@ -1,50 +0,0 @@
# 开发
听说你想写代码?
svn://local\_uoj.ac/uoj 和 svn://local\_uoj.ac/judge_client 欢迎你(如果你没改 UOJ 的 hostname 的话),这是两个 svn 仓库,至于 svn 仓库权限问题……你需要手工加一下……
在 /var/svn/uoj/conf/passwd 这个文件中你可以加一行
<pre>
uoj = 666666
</pre>
来增加一位名为 "<samp>uoj</samp>",密码为 "<samp>666666</samp>" 的 svn 仓库管理员。
之后你就可以随意用 svn 玩耍了哇咔咔……
在本地写完之后,如果你想与别人分享,你可以把代码再放到 git 中(什么鬼?)再 push 到 github。
如果你想更新的东西已经不局限于网站代码,还想对数据库、文件系统之类的折腾一番,请在 app/upgrade 目录下建立文件夹,举个例子,叫 `2333_create_table_qaq`。即,以一串数字开头,后面加一个下划线,再后面随便取名字吧,仅能包含数字字母和下划线。
在这个文件夹下你可以放一些小脚本。大概 UOJ 运行这些小脚本是这么个逻辑:
```php
if (is_file("{$dir}/upgrade.php")) {
$fun = include "{$dir}/upgrade.php";
$fun("up");
}
if (is_file("{$dir}/up.sql")) {
runSQL("{$dir}/up.sql");
}
if (is_file("{$dir}/upgrade.sh")) {
runShell("/bin/bash {$dir}/upgrade.sh up");
}
```
你只需要在 /var/www/uoj/app 下执行 `php cli.php upgrade:up 2333_create_table_qaq` 就可以运行了,这个运行过程我们称为 `up`
请务必再写一下还原的小脚本,我们称为 `down`。写完代码后你需要保证 `up``down` 能回到原来的系统。与 `up` 类似,你需要执行 `php cli.php upgrade:down 2333_create_table_qaq`,执行 `down` 的逻辑如下:
```php
if (is_file("{$dir}/upgrade.php")) {
$fun = include "{$dir}/upgrade.php";
$fun("down");
}
if (is_file("{$dir}/down.sql")) {
runSQL("{$dir}/down.sql");
}
if (is_file("{$dir}/upgrade.sh")) {
runShell("/bin/bash {$dir}/upgrade.sh down");
}
```
在数据库中UOJ 会记录自己已经加载了哪些 upgrade当你执行 `php cli.php upgrade:latest` 的时候UOJ 会把所有已经在 app/upgrade 文件夹下但还没有加载的 upgrade 都给 `up` 一下,并且是按前缀上的那一串数字从小到大执行。所以写好了这种小 upgrade 之后,你就可以跟别人分享了!
不过关于架构什么的介绍我还是先
<p style="font-size:233px">坑着</p>

View File

@ -1,4 +0,0 @@
.hljs-preprocessor .hljs-keyword {
color: #999;
font-weight: bold;
}

View File

@ -1,11 +0,0 @@
# 概述
写点 UOJ 的文档方便大家。
(喂怎么概述就这么短这么懒啊?)
哎呀懒得废话那么多啦……
要想竞赛搞得好,网上刷题不可少;在线题库哪里找?通用测评大法好!
[UOJ](http://uoj.ac/)

View File

@ -1,107 +0,0 @@
# 安装
## 教练我想安装!
请参见 [README.md](https://github.com/vfleaking/uoj/blob/master/README.md) 来安装。
嘿嘿现在我假设你已经是超级管理员了!
那么你就可以新建题目了!
看看看problem/1 这个文件夹,里面有一道样题,赶紧动手上传!(啊感觉我应该多给几道样题的)
关于如何传题请参见[题目文档](problem/)
啊如果你在 “与svn仓库同步” 的过程中发现 <samp>compile error</samp> 并且还说 <samp>no comment</samp> 的话……多半是……UOJ 尝试 ptrace 然而 ptrace 被禁了……
被禁了可能是被 docker 禁了,可以加一句 `--cap-add SYS_PTRACE` (见 [README.md](https://github.com/vfleaking/uoj/blob/master/README.md))……要是这样不能解决问题……是 Ubuntu/openSUSE 环境嘛?请尝试用下面的命令阻止 AppArmor 对 docker 的行为产生影响。当然把第二行加到 `rc.local` 里就不用每次重启都输入一遍啦~(详细解释戳 [→ 这里](https://github.com/docker/docker/issues/7276)
```sh
sudo apt-get install apparmor-utils
aa-complain /etc/apparmor.d/docker
```
要是这样还是不能解决问题……估计就是被黑恶势力禁掉了。。。大概就不是咱们这边的锅了,找找是哪个黑恶势力禁的吧。。。
另:如果上述方法不能解决 ptrace 问题也可以考虑使用 `--privileged`,但是这么做会导致 docker 失去其原有的隔离性而带来潜在的风险,不建议在生产环境中使用。
传题都没问题的话,感觉就可以愉快使用 UOJ 了!
## 教练我还想折腾!
嗯!来来来我们来折腾一波。
有个很厉害的配置文件,在 /var/www/uoj/app/.config.php 里,你可以配置一波……一个完全体如下:(有可能本文档没有跟上代码更新的速度,请以旁边的那个 .default-config.php 为准)
```php
<?php
return [
'database' => [ // 数据库相关
'database' => 'app_uoj233', // 数据库名称
'username' => 'root', // 用户名
'password' => '', // 密码
'host' => '127.0.0.1' // 数据库主机名
],
'web' => [ // 网址相关
'main' => [ // 网站主体
'protocol' => 'http', // 传输协议
'host' => 'local_uoj.ac', // 主机名
'port' => 80 // 端口
],
'blog' => [ // UOJ 博客 (用户名放前面之后成为完整的域名)
'protocol' => 'http', // 传输协议
'host' => 'blog.local_uoj.ac', // 主机名
'port' => 80 // 端口
]
],
'security' => [ // 安全相关(不要动)
'user' => [
'client_salt' => 'salt0'
],
'cookie' => [
'checksum_salt' => ['salt1', 'salt2', 'salt3']
],
],
'mail' => [ // 邮件相关SMTP 协议发送)
'noreply' => [ // noreply 邮箱
'username' => 'noreply@none',
'password' => 'noreply',
'host' => 'smtp.sina.com',
'port' => 25
]
],
'judger' => [ // 测评相关(不要动)
'socket' => [ // 与测评机的 socket 服务器通讯的设置
'port' => '233', // 端口
'password' => 'password233' // 认证密码(证明自己 UOJ 服务器)
]
],
'svn' => [ // svn 相关(不要动)
'our-root' => [ // 每个题目的 svn 仓库自带的仓库管理员
'username' => 'our-root', // 管理员用户名
'password' => 'our-root' // 密码
]
],
'switch' => [ // 一些开关
'ICP-license' => false, // ICP 备案信息的显示
'web-analytics' => false, // 网站流量统计(记 uoj.ac 名下……想统计自己的得改代码)
'blog-use-subdomain' => true // 每个人的博客使用独立的子域名
]
];
```
### 域名
如果你想使用自己的域名,改 config 即可。
如果你是搭校内网站这种的,可能没有 DNS。你可以选择自己搭校内的 DNS 解析,或者自己改 hosts。
或者你想成为一条咸鱼,可以直接在 config 里的 host 那里写 ip。
Q为什么博客用不了
A博客的话需要给每个用户的博客域名进行解析最好是用泛解析解决这是出于安全考虑。如果没这条件可以将配置文件里`switch`中的`blog-use-subdomain`改成false这样博客url将以子目录的形式出现。
### 邮箱
noreply 邮箱的目的是发一些莫名其妙的邮件,比如 svn 密码和 “找回密码”。
你可以随便找一个邮箱小号把账号密码塞这里,但是记得查查邮件服务商的 SMTP 服务器名和端口。以及,有些邮箱是需要手动开启某个开关才能允许 SMTP 发送邮件的。

View File

@ -1,35 +0,0 @@
# 维护
## 数据可持久化
我并不是在说函数式线段树233
有同学表示重启后 docker 丢失了数据。在这里要科普下 docker 的 image 和 container 的概念。
`run` 命令的功能是读一个 image 并运行,跑起来的 image 是一名光荣的 container跑完的 container 还是一名光荣的 container。
所以当你关掉了你的 container 之后,使用 `run` 命令试图让它复活是不对的。。。
首先,你需要
```sh
docker ps -a
```
来查看所有正在运行或运行结束的 container找到你刚才掐掉的那个通常就是第一个然后复制下它的 container id。然后
```sh
docker restart <container-id>
```
这家伙就在后台默默跑起来了!如果你想让它回到前台,请用
```sh
docker attach <container-id>
```
当当复活了你以为丢失了的数据都回来了container 其实可以起名的这种进阶用法自己探索吧233
## 更新
当 github 上有更新的时候,如何更新自己本地的版本呢?
求看眼[开发](/dev/)最前面几行关于使用 svn 仓库的。
嗯好,假设你已经看完了。如果是 uoj 和 judge_client 的更新,那么你可以 svn checkout 一下,然后把 git 里的新版本 commit 上去……不过你以前 checkout 过的话就可以留着那个文件夹,下次就不用重新 checkout 了。
随着 UOJ 代码的更新,可能会有一些数据哇文件系统哇之类的更新,这种会被打包放在 app/upgrade 目录下。你只需要在 /var/www/uoj/app 下执行 `php cli.php upgrade:latest` 就好啦!

View File

@ -1,263 +0,0 @@
# 题目
## 上传题目
新建题目只有超级管理员有权限,所以想加题先要联系超级管理员君,点一下题库右下方的 “新建题目” 按钮。
新建题目后,超级管理员或该题目的题目管理员可以看到题目后台。后台分为三个选项卡:
1. 编辑:题面编辑页面
2. 管理者:题目管理员列表管理页面
3. 数据:题目数据管理页面
当然还有最后个 “返回” 选项卡退出后台。下面将逐一介绍这三个选项卡。
###编辑
该页面可以对题面本身进行编辑,还可以管理题目的标签。
####编辑题面
题面用 Markdown 编写。
理论上题面是可以自由编写的,但还是有一些推荐的格式。可参照 UOJ 上对应类型的题面(传统题,交互题,提交答案题等)
一些推荐的规则:
1. 中文与英文、数字之间加一个空格隔开。
2. 输入输出样例用 `<pre>` 标签包围,并且以一个空行结尾。(方便大家复制样例到终端后不用再打回车)
3. 题面中最高级标题为三级标题。这是因为题目名称是二级标题。
4. 名称超过一个字符的数学符号要用 mathrm。例如 `\mathrm{sgn}` `\mathrm{lca}`
4. 注意 `\max`, `\min`, `\gcd` 都是有现成的。
5. 注意 xor 这种名称超过一个字符的二元运算符请用 `\mathbin{\mathrm{xor}}`
6. 一行内的计算机输入输出和常量字符串表达式请用 `<samp>` 标签,例如 `请输出 “<samp>NO SOLUTION</samp>”` `<samp>aaa</samp> 中有三个 <samp>a</samp>`
7. 一行内的计算机代码请用 <code>`</code> 括起来,就像上面的规则那样。
可参考下面这个例子:
```markdown
读入一个整数 $n$,表示题目中提到的 $3$ 位大爷 AC 的总题数。请输出他们分别 AC 的总题数。如果你不能正确读入,那么将获得 $0$ 分。前 $3$ 个测试点你正确读入即可获得 $6$ 分,第 4 个测试点你正确读入只能获得 $3$ 分。如果你不会做这道题,请直接输出 “<samp>WOBUHUI</samp>
下面有一个样例:
<pre>
233
</pre>
```
####编辑标签
只需要用英文逗号隔开标签填入文本框就行。
推荐你使用如下几条规则填写标签:
1. 标签的目的是标出题目类型,方便用户检索题目。一般来说,标签顺序基本为从小范围到大范围。
2. 最前面的几个标签是这题所需要的前置技能,这里假定 “二分查找” 之类过于基础的技能选手已经掌握。
3. 接下来是这道题的大方法,比如 “贪心”、“DP”、“乱搞”、“构造”、“分治”……
4. 接下来,如果这道题是非传统题,用一个标签注明非传统题类型,比如 “提交答案”、“交互式”、“通讯”。
5. 接下来,如果这道题是模板题,用一个标签注明 “模板题”。
6. 接下来,如果这道题是不用脑子想就能做出的题,例如 NOIP 第一题难度,用一个标签注明 “水题”。
7. 最后,如果这题的来源比较重要,用一个标签注明。比如 “UOJ Round”、“NOI”、“WC”。
8. 前置技能中,“数学” 太过宽泛不能作为标签,但 “数论” 可以作为前置技能。
9. 如果有多个解法,每个解法的前值技能和大方法都不太一样,那么尽可能都标上去。
10. “乱搞” 标签不宜滥用。
###管理者
只有题目管理员和超级管理员才能看到后台,但只有题目管理员才能管理题目数据。
可以通过这个页面增加或删除题目管理员。
###数据
UOJ 使用 svn 管理题目数据svn 仓库地址可以在本页面上找到。当你点了本页面的某个按钮后UOJ 将把 svn 密码发送到你的邮箱。这个 svn 密码是不随题目变化而变化的。
但是,初始时 UOJ 是没有配置过用于给大家发邮件的邮箱的。所以如果你还没有配置过,请直接在数据库的 user\_info 表中找到 svn\_password 一栏存储的值;如果你愿意折腾一下,可以在 /var/www/uoj/app/.config.php 里配置一下邮箱,详情见[安装](/install/)咯~
1. 下载 svn即 subversion。如果是 win 可以用 TortoiseSVN如果是 ubuntu 直接 apt-get 一发,也可以用 smartsvn。
2. 学习怎么使用 svn。蛮好懂的吧会用 checkoutaddremovecommit 什么的就行了)
3. 在题目数据管理页面,获取 svn 密码。
4. checkout 这道题。
5. 在你的 working copy 下,建立文件夹 1然后在 1 这个文件夹下放置题目数据什么的。
6. 搞完之后 commit。
7. 在网页上点“与SVN仓库同步”就可以啦
####题目配置格式
主要麻烦是要写个 problem.conf下面主要介绍传统题的配置。
例如:
<pre>
use_builtin_judger on
use_builtin_checker ncmp
n_tests 10
n_ex_tests 5
n_sample_tests 1
input_pre www
input_suf in
output_pre www
output_suf out
time_limit 1
memory_limit 256
output_limit 64
</pre>
假如你 input 文件是 www1.in, www2.in, ... 这个样子,那么你需要在 problem.conf 里记录:
<pre>
input_pre www
input_suf in
</pre>
output 文件同理。
extra test 是指额外数据,在 AC 的情况下会测额外数据如果某个额外数据通不过会被倒扣3分。
至于样例,样例一定是前几个额外数据,所以有一个 `n_sample_tests` 表示是前多少组是样例。你需要把题面中的样例和大样例放进额外数据里。
额外数据命名形如 ex\_www1.in, ex\_www2.in, ... 这个样子。
checker 是指判断选手输出是否正确的。一般来说输出结果为整数序列,用 ncmp 就够了它会比较标准答案的整数序列和选手输出的整数序列。如果是忽略所有空白字符进行字符串序列的比较可以用wcmp。如果你想按行比较不忽略行末空格但忽略文末回车可以使用 fcmp。如果想手写 checker请使用 Codeforces 的 [testlib](http://codeforces.com/testlib) 库写 checker。
你需要写好后命名为 chk.cpp然后在 problem.conf 中去掉 “use\_builtin\_checker” 一行。
如果你的题目的输入数据可以被检验是否满足题目要求,那么请写一个 validator。比如“保证数据随机”“保证数据均为人手工输入”等就无法检验输入数据是否满足题目要求。
validator 的作用就是检查你输入数据造得是否合法。比如你输入保证是个连通图validator 就得检验这个图是不是连通的。还是请用 testlib 写,教程还是之前提到的那个教程。写好后命名为 val.cpp 就行。
另外注意时间限制**不能为小数**。
#### 提交答案题的配置
范例:
<pre>
use_builtin_judger on
submit_answer on
n_tests 10
input_pre www
input_suf in
output_pre www
output_suf out
</pre>
So easy
不过还没完……你要写个 checker。当然如果你是道 [最小割计数](http://uoj.ac/problem/85) 就不用写了。。。老样子写个 use\_builtin\_checker ncmp 就行。
提答题经常会面临给部分分,请使用 quitp 函数。由于一些历史原因(求不吐槽 QAQ假设测试点满分为 a
```cpp
quitp(x, "haha");
```
将会给 floor(a * round(100x) / 100) 分。是不是很复杂……其实很简单,当你这个测试点想给 p 分的时候,只要
```cpp
quitp(ceil(100.0 * p / a) / 100, "haha");
```
就行了。(好麻烦啊)
假设你已经写好了,赞!
但是下发的本地 checker 怎么办?
首先你得会写本地 checker。如果只是传参进来一个测试点编号检查测试点是否正确那么只要善用 registerTestlib 就行了。如果你想让 checker 与用户交互,请使用 registerInteraction。特别地如果你想让 checker 通过终端与用户进行交互,请使用如下代码(好丑啊)
```cpp
char *targv[] = {argv[0], "inf_file.out", (char*)"stdout"};
#ifdef __EMSCRIPTEN__
setvbuf(stdin, NULL, _IONBF, 0);
#endif
registerInteraction(3, targv);
```
那么怎么下发文件呢?你可以在文件夹 1/ 下新建一个文件夹 download里面放的所有东西都会打包发给选手啦
#### 交叉编译
由于你的本地 checker 可能需要发布到各个平台,所以你也许需要交叉编译。交叉编译的意思是在一个平台上编译出其他平台上的可执行文件。好!下面是 Ubuntu 上交叉编译小教程时间。
首先不管三七二十一装一些库:(请注意 libc 和 libc++ 可能有更新的版本)
```sh
sudo apt-get install libc6-dev-i386
sudo apt-get install lib32stdc++6 lib32stdc++-4.8-dev
sudo apt-get install mingw32
```
然后就能编译啦:
```sh
g++ localchk.cpp -o checker_linux64 -O2
g++ localchk.cpp -m32 -o checker_linux32 -O2
i586-mingw32msvc-g++ localchk.cpp -o checker_win32.exe -O2
```
问:那其他系统怎么办?有个叫 emscripten 的东西,可以把 C++ 代码编译成 javascript。请务必使用 UOJ 上的 testlib而不是 CF 上的那个版本。由于 testlib 有些黑科技UOJ 上的 testlib 对 emscripten 才是兼容的。
[emscripten 下载地址](http://kripken.github.io/emscripten-site/docs/getting_started/downloads.html) (建议翻墙提升下载速度)
编译就用
```sh
em++ localchk.cpp -o checker.js -O2
```
#### 交互题的配置
嘛……其实并没有 UOJ 内部并没有显式地支持交互式(真正的程序与程序交互的版本还没发布出来),只是提供了 require、implementer 和 token 这两个东西。
除了前文所述的 download 这个文件夹,还有一个叫 require 的神奇文件夹。在测评时,这个文件夹里的所有文件均会被移动到与选手源程序同一目录下。在这个文件夹下,你可以放置交互库,供编译时使用。
再来说 implementer 的用途。如果你在 problem.conf 里设置 `with_implementer on` 的话,各个语言的编译命令将变为:
* C++: g++ code implementer.cpp code.cpp -lm -O2 -DONLINE_JUDGE
* C: gcc code implementer.c code.c -lm -O2 -DONLINE_JUDGE
* Pascal: fpc implementer.pas -o code -O2
好……不管那些奇怪的选手的话,一个交互题就搞好了……你需要写 implementer.cpp、implementer.c 和 implementer.pas。当然你不想兹瓷某个语言的话不写对应的交互库就好了。
如果是 C/C++,正确姿势是搞一个统一的头文件放置接口,让 implementer 和选手程序都 include 这个头文件。把主函数写在 implementer 里,连起来编译时程序就是从 implementer 开始执行的了。
如果是 Pascal正确姿势是让选手写一个 pascal unit 上来,在 implementer.pas 里 uses 一下。除此之外也要搞另外一个 pascal unit里面存交互库的各种接口让 implementer 和选手程序都 uses 一下。
哦另外 require 文件夹的内容显然不会被下发……如果你想下发一个样例交互库,可以放到 download 文件夹里。
好下面来解释什么是 token……考虑一道典型的交互题交互库跟选手函数交流得很愉快最后给了个满分。此时交互库输出了 “AC!!!” 的字样,也可能输出了选手一共调用了几次接口。但是聪明的选手发现,只要自己手动输出一下 “AC!!!” 然后果断退出似乎就能骗过测评系统了娃哈哈。
这是因为选手函数和交互库已经融为一体成为了一个统一的程序测评系统分辨出谁是谁。这时候token 就出来拯救世界了。
在 problem.conf 里配置一个奇妙的 token比如 `token wahaha233`,然后把这个 token 写进交互库的代码里(线上交互库,不是样例交互库)。在交互库准备输出任何东西之前,先输出一下这个 token。当测评系统要给选手判分时首先判断文件的第一行是不是 token如果不是直接零分。这样就避免了奇怪的选手 hack 测评系统了。这里的 token 判定是在调用 checker 之前,测评系统会把 token 去掉之后的选手输出喂给 checker。所以一道交互题的 token 要好好保护好)
另外另外,记得在 C/C++ 的交互库里给全局变量开 static意为仅本文件可访问。
#### 意想不到的非传统题
吼,假如你有一道题不属于上述任何一种题目类型 —— 恭喜你中奖啦!得自己写 judger 啦!
judger 的任务:给你选手提交的文件,把测评结果告诉我。
把 problem.conf 里的 `use_builtin_judger on` 这行去掉,搞一个 judger 放在题目目录下,就好了。
噢对怎么搞这个 judger 呢。。。全自动啦233。。。你需要写个 Makefile……比如
```makefile
export INCLUDE_PATH
CXXFLAGS = -I$(INCLUDE_PATH) -O2
all: chk judger
% : %.cpp
$(CXX) $(CXXFLAGS) $< -o $@
```
什么?你问 judger 应该怎么写?
很抱歉的是这部分我封装得并不是很方便……请 include 一下 uoj_judger.h 来辅助你写 judger……参照 QUINE 这个样题……
说实在的 uoj_judger.h 写得太丑了不过反正我会用2333。期待神犇再来造一遍轮子或者用 python 码个框架(需要解决 python 启动就耗时 40ms 的坑爹问题)
哦对,要使用自己的 judger 的话就只有超级管理员能 “与 SVN 仓库同步” 了。另外无论你的 judger 如何折腾,测评也是有 10 分钟 的时间限制的。
## 样题
在 problem 文件夹下有我们给出的几道样题。
1. 一个典型的传统题
* \#1. A + B Problem。
2. 一个典型的非传统题:
* \#8. Quine。
3. 一个典型的交互题:
* \#52. 【UR \#4】元旦激光炮。
4. 一个典型的 ACM 赛制题(错一个就 0 分):
* \#79. 一般图最大匹配。
5. 一个典型的提交答案题:
* \#116. 【ZJOI2015】黑客技术。
6. 一个典型的 subtask 制的题:
* \#225. 【UR #15】奥林匹克五子棋。

View File

@ -1,11 +0,0 @@
site_name: UOJ Documentation
pages:
- 主页: 'index.md'
- 安装: 'install.md'
- 维护: 'maintain.md'
- 题目: 'problem.md'
- 比赛: 'contest.md'
- 开发: 'dev.md'
- 关于: 'about.md'
theme: cerulean
extra_css: [extra.css]

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.