分类目录归档:hustoj

转发自 http://phdwu.com/2015/04/special-judge-usage-in-hustoj/

 

本文介绍了在流行、开源的ACM Online Judge平台——HUSTOJ上创建Special Judge题目的方法,并以两道题目为例,给出了具体的操作过程。

1 简介

随着ACM/ICPC比赛的不断发展,中国大陆地区已经有越来越多的高校参与到此项赛事中。这里这里可以看到2014年ACM/ICPC中国区六大赛区的参赛情况。

HUSTOJ(Google Code地址Github地址)是一款出色的开源项目,由华中科技大学前ACM队员Sempr等同学开发,2008年5月14日首先上线于华中科技大学,目前已有近百家学校、公司使用HUSTOJ进行计算机程序设计竞赛、计算机程序设计日常教学与测验、人才招聘等。

2 Special Judge

通常的ACM题目包括以下几项内容:题目描述(Description)、输入描述(Input)、输出描述(Output)、样例输入(Sample Input)、样例输出(Sample Out),在后台则包括测试输入(Input Data)和测试输出(Output Data)两项。在评测用户提交的程序正确与否时,系统会将样例输入和测试输入重定向作为程序的标准输入,通过判断程序对应的输出是否与期待的输出完全相同,来判断解答是否正确。

对于同一道题目,用户可能使用各种不同的方法来解答,所以对于某些特殊的题目,其结果可能不唯一,但都符合题目要求。此类题目就需要进行特判(Special Judge)。HUSTOJ便提供了特判功能。

这些题目主要有:
1、答案不唯一。见下例一
2、控制精度。题目要求输出精度在某eps之内。见下例二
3、其他。(欢迎留言补充)

3 Special Judge在HUSTOJ中的使用

主要步骤有:

1、在题目后台编辑页面启用该选项,如图1所示。

图1

2、编制data.indata.outspj.cc(或spj.c)。

3、编译出spj,设执行权限,连同2中的三个文件一起上传至服务器。

例一

下面以UPCOJ中的一道题目为例说明SPJ在HUSTOJ中的使用。
题目版权归原平台、作者所有,本文给出示例并不代表原题目使用同样方法进行评测。

给出一个不小于12的正整数n,请你输出两个合数,使他们的和等于n

分析题意,可以得出系统判断用户输出是否正确的两个条件是:

  1. 输出的两个数是否均为合数;
  2. 输出的两个数之和是否为n

首先分别制定data.in(测试输入)、data.out(测试输出)如下:

filename: data.in
1
2
3
4
3
12
15
1000
filename: data.out
1
2
3
8 4
9 6
500 500

然后编写spj.cc(特判程序)。HUSTOJ中的spj.cc需要有3个文件名参数传入:测试输入、测试输出、用户输出。
spj的返回值决定着判断结果,成功返回(0)表示AC,其他非零值表示WA。
下面给出一个本题spj.cc的示例代码。

filename: spj.cc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include <stdio.h>
bool is_prime(int x)//判断素数,伪代码
{
if(x是素数)
return true;
else
return false;
}
int main(int argc,char *args[])//主函数
{
FILE * f_in=fopen(args[1],“r”);//测试输入
FILE * f_out=fopen(args[2],“r”);//测试输出
FILE * f_user=fopen(args[3],“r”);//用户输出
int ret=0;//返回值
int T,n,a,b;
fscanf(f_in,“%d”,&T);//从输入中读取数据组数T
while(T–)
{
fscanf(f_in,“%d”,&n);
fscanf(f_user,“%d%d”,&a,&b);
if(a+b!=n || is_prime(a) || is_prime(b))
ret = 1;//Wrong Answer
}
fclose(f_in);
fclose(f_out);
fclose(f_user);
return ret;
}

编制完spj.cc后,将这些文件上传至服务器。

登录服务器以后进入/home/judge/data/[题号]文件夹,执行以下操作:

/home/judge/data/1000
1
2
3
acm@acm:/home/judge/data/1000$ sudo vim spj.cc #Edit the file spj.cc
acm@acm:/home/judge/data/1000$ sudo g++ -o spj spj.cc # gcc -o spj spj.c
acm@acm:/home/judge/data/1000$ sudo chmod +x spj

测试:

/home/judge/data/1000
1
2
3
4
5
6
acm@acm:/home/judge/data/1000$ ./spj data.in data.out data.out
acm@acm:/home/judge/data/1000$ echo $?
0 #Accepted
acm@acm:/home/judge/data/1000$ ./spj data.in data.out data.in
acm@acm:/home/judge/data/1000$ echo $?
1 #Wrong Answer

在本地HUSTOJ测试,通过网页提交,通过。

例二

某题目要求经过一定复杂计算后输出一个实数结果,精度要求控制在104内。
分析题意,可知spj需要判断测试输出a与用户输出x之差是否在eps之内。
spj.cc 如下:

filename: spj.cc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include <stdio.h>
const double eps = 1e-4;
int main(int argc,char *args[])//主函数
{
FILE * f_in=fopen(args[1],“r”);//测试输入
FILE * f_out=fopen(args[2],“r”);//测试输出
FILE * f_user=fopen(args[3],“r”);//用户输出
int ret=0;//返回值
int T;
double a,x;
fscanf(f_in,“%d”,&T);//从输入中读取数据组数T
while(T–)
{
fscanf(f_out,“%lf”,&a);
fscanf(f_user,“%lf”,&x);
if(fabs(a-x)>eps)
ret = 1;//Wrong Answer
}
fclose(f_in);
fclose(f_out);
fclose(f_user);
return ret;
}

hustoj的用法

  1. 注册codeup.cn,开通校级账号,全网访问。
  2. 自建服务器,物理机虚拟机均可,校园网访问。
  3. 服务器托管学校机房,开通外网端口,外网访问
  4. 使用新浪云挂Web端,内网判题,全网访问。
  5. AWS免费服务器,低速全网访问。
  6. ————备案、收费的分割线————
  7. 廉价VPS,低速全网访问。
  8. 使用阿里云,高速全网访问。
  9. 新浪云挂Web,阿里云挂判题,利用新浪云提供域名及免费流量。
  10. 专用服务器,托管双线机房。

以上方案,从上到下,技术难度递增,成本、费用递增。

升级HUSTOJ

简单说就是

检出最新web,复制原upload目录到新目录,测试后切换。

检出最新core,./make.sh。

管理员登陆后台,更新数据库。

以前升级hustoj可以用update-hustoj命令快速完成,自从googlecode光荣的进入被墙的黑名单后,很多用户长时间没有做过升级了。

现在的最新代码放在github(愿习大大保佑github不封,保佑台湾是中国不可分割的一部分),因此升级需要从github取得最新源码。

如果你是用apache的,老脚本安装的。

 sudo svn checkout https://github.com/zhblue/hustoj/trunk/trunk/web /var/www/new/

sudo cp -a /var/www/JudgeOnline/include/db_info.inc.php  /var/www/new/include/

到这里找到函数pdo_query
https://github.com/zhblue/hustoj/blob/master/trunk/web/include/db_info.inc.php
把它添加到/var/www/new/include/db_info.inc.php中

sudo cp -a /var/www/JudgeOnline/upload  /var/www/new/

sudo svn checkout https://github.com/zhblue/hustoj/trunk/trunk/core core

cd core

sudo pkill -9 judged

sudo ./make.sh

sudo judged

访问http://原OJ地址/new

登陆,后台,更新数据库。

测试无误后

sudo mv /var/www/JudgeOnline /var/www/oldOJ

sudo mv /var/www/new /var/www/JudgeOnline

如果你是用nginx,新脚本安装的

sudo su
cd /home/judge/src
svn up .
cd core
pkill -9 judged
./make.sh
judged

 

 

……待续

 

 

 

[原]给HUSTOJ用户提供的源码阅读与修改建议

 

0、 准备知识

a)        最新系统源码可以用svn取得,或在下述地址直接浏览

i.  http://code.google.com/p/hustoj/source/browse/   墙外老版

ii.  https://github.com/zhblue/hustoj                         无墙新版

b)       系统分为Web和Core两个部分

c)        简化ER图

hustoj-db

d)       Web与core的连接方式有两种,实际运行可选其中一种

i.   数据库连接【默认】

1.        Web插入Solution表

2.        core轮询solution表,发现新纪录

3.        core更新solution表result等字段

4.        Web端轮询soltuion显示result等字段。

ii.   HTTP方式

1.        Web插入Solution表

2.        core访问Web端admin/problem_judge.php,发现新纪录

3.        core向Web端admin/problem_judge.php提交数据,problem_judge.php更新solution表result等字段

4.        Web端轮询soltuion显示result等字段。

1、 Web部分

a)        阅读配置文件,弄清各设置含义

i.      参考

 

db_info.inc.php


static $DB_HOST="localhost"; 数据库的服务器地址
static $DB_NAME="jol"; 数据库名
static $DB_USER="root"; 数据库用户名
static $DB_PASS="root"; 数据库密码
// connect db
static $OJ_NAME="HUSTOJ"; OJ的名字,将取代页面标题等位置HUSTOJ字样。
static $OJ_HOME="./"; OJ的首页地址
static $OJ_ADMIN="root@localhost"; 管理员email
static $OJ_DATA="/home/judge/data"; 测试数据所在目录,实际位置。
static $OJ_BBS="discuss";//"bbs" 论坛的形式,discuss为自带的简单论坛,bbs为外挂论坛,参考bbs.php代码。
static $OJ_ONLINE=false; 是否使用在线监控,需要消耗一定的内存和计算,因此如果并发大建议关闭
static $OJ_LANG="en"; 默认的语言,中文为cn
static $OJ_SIM=true; 是否显示相似度检测的结果。
static $OJ_DICT=true; 是否启用在线英字典
static $OJ_LANGMASK=1008; //1mC 2mCPP 4mPascal 8mJava 16mRuby 32mBash 1008 for security reason to mask all other language 用掩码表示的OJ接受的提交语言,可以被比赛设定覆盖。
static $OJ_EDITE_AREA=true;// 是否启用高亮语法显示的提交界面,可以在线编程,无须IDE。
static $OJ_AUTO_SHARE=false;//true: 自动分享代码,启用的话,做出一道题就可以在该题的Status中看其他人的答案。
static $OJ_CSS="hoj.css"; 默认的css,可以选择dark.css和gcode.css,具有有限的界面制定效果。
static $OJ_SAE=false; //是否是在新浪的云平台运行web部分
static $OJ_VCODE=true; 是否启用图形登录、注册验证码。
static $OJ_APPENDCODE=false; 是否启用自动添加代码,启用的话,提交时会参考$OJ_DATA对应目录里是否有append.c一类的文件,有的话会把其中代码附加到对应语言的答案之后,巧妙使用可以指定main函数而要求学生编写main部分调用的函数。
static $OJ_MEMCACHE=false;是否使用memcache作为页面缓存,如果不启用则用/cache目录
static $OJ_MEMSERVER="127.0.0.1"; memcached的服务器地址
static $OJ_MEMPORT=11211; memcached的端口
static $OJ_RANK_LOCK_PERCENT=0; //比赛封榜时间的比率,如5小时比赛设为0.2则最后1小时封榜。
static $OJ_SHOW_DIFF=false; //显示WrongAnswer时的对比

 

b)       制定自己的前台模板(即改变页面效果)

i.      复制template/bs3目录,放置在template目录中,并改为新模板名。

ii.     在db_info.inc.php中修改$OJ_TEMPLATE变量为新模板名

iii.   浏览前台,打开要修改的页面,根据地址栏修改新目录中对应的php、css、images等文件,保存后刷新页面看修改效果。

c)        模板制定成功以后应该有足够的知识开始修改template目录以外的部分了

d)       论坛

i.    建议集成GPL的phpbb,参考。

ii.    集成Discuz

1.   建议购买商业许可。

2.   参考/web/include/login-discuz.php

e)        比赛根据数据通过率排名,而不只看AC数量

i.             数据库solution表pass_rate字段表示改条通过率。

ii.             把contestrank.php中的solved字段变成浮点对待。

iii.            这里,修改积分方式,按照希望的方式积分。可能需要给TM增加字段$p_wa_best_rate记录每题最大通过率。

f)        对有志于重写整个前台的勇士

i.             希望你选择一种魔法师编程语言(node.js/ror/python/go)。

ii.             如果做不到前面那条,请做好长时间开发的心理准备。

iii.             理论上任何现存web编程模型都可以,推荐JSP/SSH(前方高能坑……)。

iv.             建议实现admin/problem_judge.php的仿真,方便直接集成原版core。(get/post/ servlet-mapping)

2、 Core部分

a)        阅读配置文件,弄清各设置含义

i.    参考


judge.conf  不要复制下面的注释进入实际文件,judged和judge_client不能识别#注释。

OJ_HOST_NAME=127.0.0.1 #mysql host ip
OJ_USER_NAME=root #mysql host username
OJ_PASSWORD=root #mysql host password
OJ_DB_NAME=jol #mysql DB name
OJ_PORT_NUMBER=3306 #mysql port
OJ_RUNNING=4 #max concurrent threads number of judge_client
OJ_SLEEP_TIME=5 #judged work interval
OJ_TOTAL=1 #Deprecated: total number of judged (hosts/processes)
OJ_MOD=0 #Deprecated: the number of this judged(host)
OJ_JAVA_TIME_BONUS=2 #java's extral time
OJ_JAVA_MEMORY_BONUS=512 #java's extral memory
OJ_SIM_ENABLE=0 #using sim
OJ_HTTP_JUDGE=0 #using http link to database(if enabled,mysql is not used anymore)
OJ_HTTP_BASEURL=http://127.0.0.1/JudgeOnline #http link basedir
OJ_HTTP_USERNAME=admin #account in db that has http_judge privilege
OJ_HTTP_PASSWORD=admin #password of this account
OJ_OI_MODE=0 #using oi (Olympiad in Informatics) mode
OJ_SHM_RUN=0 #using /dev/shm for fast running & low harddisk wear
OJ_USE_MAX_TIME=0 #use the max time of all testcase rather than total time
OJ_LANG_SET=0,1,2,3,4 #selective judge solution of languagesOJ_HOST_NAME=127.0.0.1 如果用mysql连接读取数据库,数据库的主机地址
OJ_USER_NAME=root 数据库帐号
OJ_PASSWORD=root 数据库密码
OJ_DB_NAME=jol 数据库名称
OJ_PORT_NUMBER=3306 数据库端口
OJ_RUNNING=4 judged会启动judge_client判题,这里规定最多同时运行几个judge_client
OJ_SLEEP_TIME=5 judged通过轮询数据库发现新任务,轮询间隔的休息时间,单位秒
OJ_TOTAL=1 老式并发处理中总的judged数量
OJ_MOD=0 老式并发处理中,本judged负责处理solution_id按照TOTAL取模后余数为几的任务。
OJ_JAVA_TIME_BONUS=2 Java等虚拟机语言获得的额外运行时间。
OJ_JAVA_MEMORY_BONUS=512 Java等虚拟机语言获得的额外内存。
OJ_SIM_ENABLE=0 是否使用sim进行代码相似度的检测
OJ_HTTP_JUDGE=0 是否使用HTTP方式连接数据库,如果启用,则前面的HOST_NAME等设置忽略。
OJ_HTTP_BASEURL=http://127.0.0.1/JudgeOnline 使用HTTP方式连接数据库的基础地址,就是OJ的首页地址。
OJ_HTTP_USERNAME=admin 使用HTTP方式所用的用户帐号(HTTP_JUDGE权限),该帐号登录时不能启用VCODE图形验证码,但可以登录成功后启用。
OJ_HTTP_PASSWORD=admin 密码
OJ_OI_MODE=0 是否启用OI模式,即无论是否出错都继续判剩余的数据,在ACM比赛中一旦出错就停止运行。
OJ_SHM_RUN=0 是否使用/dev/shm的共享内存虚拟磁盘来运行答案,如果启用能提高判题速度,但需要较多内存。
OJ_USE_MAX_TIME=1 是否使用所有测试数据中最大的运行时间作为最后运行时间,如果不启用则以所有测试数据的总时间作为超时判断依据。
OJ_LANG_SET=0,1,2,3,4 #判哪些语言的题目

OJ_COMPILE_CHROOT=0  是否在编译时使用chroot环境,避免某些编译期攻击。

OJ_TURBO_MODE=0 是否放弃用户表和问题表的数据一致性,以在大型比赛中添加更多的判题机来提高判题速度。

ii.      源码https://github.com/zhblue/hustoj/blob/master/trunk/core/judge_client/

b)       查阅Linux文档中关于下述关键词的内容

i.  Ptrace

ii.  Chroot

iii. Setuid

iv.  Proc

v. shm

c)        所有API限定在okcalls.h

d)       代码查重工具sim

i.   https://github.com/zhblue/hustoj/tree/master/trunk/core/sim

e)        对于计划改造Core来适应你自己的OJ前台的朋友

i. 参考1.c.iv

ii. 在judge_client.cc中搜索关键词wget

f)        HUSTOJ的沙箱模型

i.  相对openjudge.net的sandbox libraries而言并不严谨

ii.  对于OJ而言,基本满足需求

iii.  容易理解、容易实现、容易修改

f) 莫名其妙的Runtime Error,请点击RuntimeError打开详细信息,并做英译汉。

对于okcalls23/64.h进行修改,请只修改符合你的操作系统架构(32位/64位)的那个,0只能在首位,末尾必须为0。非0callid请加在中间任意位置。

CSDN网友的源码注释

http://blog.csdn.net/legan/article/details/40746829

http://blog.csdn.net/legan/article/details/40789939

[原]开源在线IDE,欢迎测试

昨天花了整整一天来编码和完善,终于上线。

测试地址

http://hustoj.sinaapp.com/submitpage.php?id=0


  整体是个OJ系统,IDE是其中附带,无需注册,guest身份使用。

本系统正在参加开源软件评选,如果你觉得它还行,请投它一票。

http://www.oschina.net/project/top_cn_2012#hustoj


它的名字叫做HUSTOJ

我们的项目主页地址 http://code.google.com/p/hustoj

IDE源码已经进入SVN,欢迎留言指出其中的BUG。

作者:zhblue 发表于2012-12-15 8:20:26 原文链接
阅读:2205 评论:13 查看评论
]]>

[原]HUSTOJ随笔10-用其他系统账号登陆

最新的变动,将login中的check_login分离出来,放在login-XXX.php中引用。

这样可以方便的切换为其他系统账号登陆,只需自行实现check_login这个函数即可。

函数接受用户名和密码,如果登陆成功返回用户名,如果登陆失败返回false

目前svn中提供下面三个例子:

login-hustoj.php  传统数据库账号

login-ldap.php    远程LDAP服务器账号

login-moodle.php Moodle系统账号

注意使用时需要配置、调整相应文件中的参数,比如moodle需要系统的salt。

利用这一接口,可以方便的开发其他系统的登录支持,如discuz论坛之类,不过由于开源协议的兼容问题,主线不会直接提供其代码,用户可自行开发使用。

作者:zhblue 发表于2012-5-5 13:06:29 原文链接
阅读:1317 评论:1 查看评论
]]>

[原]HUSTOJ随笔9-模板分离

     针对很多学校希望自定义OJ界面风格的需求,对原代码进行了初步的模板分离,在template目录下存放模板,原有风格定义为classic。在include/db_info.inc.php文件中新建$OJ_TEMPLATE用于指定模板名。

     今后如果需要制作新的模板,可以选择复制classic目录。然后修改其中的php、css、imgae等文件,在db_info.inc.php中修改$OJ_TEMPLATE变量为新模板名即可。

    有条件的也可以请美工重新设计整个页面,然后切图形成html,再针对每个页面进行代码嵌入,从classic的php中提取显示用的代码段,放入新模板的html中,并命名为正确的*.php文件,放入新模板目录即可。

     下面是一个修改后的样例,mario风格。(其中图片、图标为网上收集,有版权,勿做商用)


作者:zhblue 发表于2012-4-30 9:08:25 原文链接
阅读:1467 评论:6 查看评论
]]>

[原]HUSTOJ随笔8-判题端测试数据按需下载

       今天开发了测试数据分发系统,这个点子最早是群里讨论时freefcw或者是Sempr提出来的,具体记不清了。

  1. 扩展了admin/problem_judge.php的功能,使之能够提供数据目录里的文件列表和指定文件内容。
  2. 增加了judge_client中http_judge模式下get_test_file这个函数,获取列表,获取文件。
  3. 当文件为spj.c/spj.cc时编译特殊裁判。

       最终实现,当判题端缺少测试数据时能够直接从web上下载测试数据,就不用事先复制大量测试数据了,方便动态添加judge客户端。

       测试中发现网络不稳定可能造成数据有破损,等有空做一下md5sum之类,在此之前建议只在稳定可靠的局域网使用这项功能。

     

作者:zhblue 发表于2012-4-25 20:12:59 原文链接
阅读:1687 评论:1 查看评论
]]>

[原]HUSTOJ随笔7-SAE部署

SAE(sina application engine) 是新浪的云计算平台,最大的特点是跟LAMP平台几乎无缝的兼容性。

因此在SAE上部署HUSTOJ的Web部分是完全没有问题的,只需在db_info.inc.php设置

static  $OJ_SAE=true; 

然后参考

http://code.google.com/p/hustoj/wiki/HTTPJudge

进行judged的配置。

这里需要说明的是,新浪云平台具有较多的安全限制,支持的计算平台仅限web,并不能支持编译、运行、监控等操作。

所以,必须另行架设判题机运行judged/judge_client,但是由于SAE已经提供了公网Web出口,所以对于没有自己互联网出口的学校来说就是非常难得的资源。

而judged可以在内网运行,甚至可以不必24小时在线,比如只在8-16点(上班时间)在线,老师可以用自己办公室的机器上装个虚拟机的方式来解决。

实际上HTTPJudge的运行机制正是为SAE量身打造的。

因为传统的judged必须连接mysql来轮询和完成任务,而SAE没有提供外部网络连接mysql的机制,这就逼迫我思考如何让judged能够连接到SAE的数据库上去。

因为SAE唯一的对外出口就是Web(HTTP),因此在HTTP基础上实现一套判题任务的查询、更新机制就是最直接的答案。

当然有很多标准可以采纳,如WebService,XML-RPC,json-rpc等,但是由于我比较懒、也比较笨,所以就自行定制了一套最为简化的实现,类似Unix的管道流的文本界面。

此外,由于SAE不支持文件操作API,所以类似图片上传等功能都不能正常运行。有能力的用户可以自行修改代码,使用SAE的Storage功能实现模拟文件操作。

没有开发能力的用户可以在本地搭建完全相同题库和数据的OJ,在加题后采用SAE的SVN界面进行上传同步,可以最大化减少SAE的维护工作量。

作者:zhblue 发表于2012-3-25 19:33:20 原文链接
阅读:1869 评论:1 查看评论
]]>