Chinaunix首页 | 论坛 | 博客
  • 博客访问: 70982
  • 博文数量: 24
  • 博客积分: 1410
  • 博客等级: 上尉
  • 技术积分: 260
  • 用 户 组: 普通用户
  • 注册时间: 2009-09-03 10:47
文章分类
文章存档

2011年(1)

2010年(1)

2009年(22)

我的朋友

分类:

2009-10-16 19:52:01

自己制作一个小小的OJ by darkfish

    这个OJ做完之后,并没有做严格的测试,只当自己练练shell编程。On-line Judge用shell script来写实在算不上什么难的事情,毕竟shell script就集合了Linux系统的所有工具,一个小小的OJ又算得了什么,只是过程繁琐了点而已。
    下面的OJ只实现了超时处理,并没有处理超内存的情况。因为超时和超内存都是由ulimit这个命令来控制的,需要直接加上就可以了。
    下面的OJ还用了gcc-3.3中的检查溢出功能,学校内有fbounds-checking的就只找到了gcc-3.3。

先来规划一下OJ要实现的功能。

给定一个目录,之下有new, run和finished,三个子目录
"oj-dir"
  \__new   是测试数据存放目录。存放测试数据格式为input.1、input.2,output.1、output.2……。如果有timelimit.1...则程序运行时间按照timelimit里面的数据来限制,否则是1S。
  \__run   编译之后的程序以及结果的存放目录,编译错误放在compile.stderr下面,stderr存放运行的错误信息,比如溢出。运行结果存放在result里面。
  \__finished 系统判定结果完毕之后,新建一个同名文件夹,把new里面的所有东西移到文件夹下。
        
我们的程序如下规划:
1.execute
   \__check_process    #第一次编译得到compile.stderr以判断CE 和 stderr以判断RE
   \__sub_process      #第二次编译编译执行得到output time
2.judge                #判断AC WA TLE RE
3.ojdaemon             #守护进程


execute脚本:
#!/bin/bash
#    name : execute

NOWDIR=`pwd`
cd "$1"
DATA=`pwd`
cd "$2"
RUN=`pwd`

TotalInput=`find $DATA -name "input.*" | wc -l`

#---get the timelimit-----------------
if [ -e $DATA/timelimit.$count ]
then
    TIMELIMIT=`cat $DATA/timelimit.$count`
else
    TIMELIMIT=1
fi
#--end-----

# in this part check the --------------------------------------CE
$NOWDIR/check_process $DATA $RUN $TIMELIMIT $TotalInput
if [ $? -eq 1 ]
then
    echo "CE" >> $RUN/result.txt
    exit 1
fi
#--end----


#--complie main.c to main in the directory of RUN.--
gcc $DATA/main.c -lm -o $RUN/main 2>/dev/null

for i in `seq 1 $TotalInput`
do
    /usr/bin/time -o $RUN/time.$i -f "%e" $NOWDIR/sub_process $DATA $RUN $i $TIMELIMIT
    echo "$?" > $RUN/"exitcode.$i"
done

check_process脚本:

#!/bin/bash
DATA=$1
RUN=$2
TIMELIMIT=`expr $3 + 1`
TotalInput=$4

gcc-3.3 -fbounds-checking $DATA/main.c -o $RUN/main_check -Wall 2>$RUN/compile.stderr
grep 'error' $RUN/compile.stderr > /dev/null 2>&1
if [ $? -eq 0 ]    #--------CE-----------------
then
    exit 1
fi
for i in `seq 1 $TotalInput`
do
    ulimit -t $TIMELIMIT
    exec $RUN/main_check < $DATA/input.$i >$RUN/output.$i 2>$RUN/stderr.$i
done
exit 0

sub_process脚本:
#!/bin/bash
DATA=$1
RUN=$2
NUM=$3 
TIMELIMIT=`expr $4 + 1 `
ulimit -t $TIMELIMIT
exec $RUN/main < $DATA/input.$NUM > $RUN/stdout.$NUM 2>/dev/null

judge脚本:
#!/bin/bash
#   name : judge

cd "$1"
DATA=`pwd`
cd "$2"
RUN=`pwd`
TotalInput=`find $DATA -name "input.*" | wc -l`

#The working directory is $RUN
count=1
while [ $count -le $TotalInput ]
do
    #------------------------------------------------test RE
    grep 'error' $RUN/stderr.$count >/dev/null 2>&1
    if [ $? -eq 0 ]
    then
        echo "$count RE" >> result.txt
        let count=$count+1
        continue
    fi
    #------end to test RE

    #test time -------------------------------------------TLE
    if [ -e $DATA/timelimit.$count ]
    then
        TIMELIMIT=`cat $DATA/timelimit.$count`
    else
        TIMELIMIT=1
    fi
    TIME=`tail -1 $RUN/time.$count | cut -c1`
    if [ $TIME -gt $TIMELIMIT ]
    then
        TIME=`tail -1 $RUN/time.$count`
        echo "$count TLE $TIME" >> $RUN/result.txt
        let count=$count+1
        continue
    fi
    #----- test time end
    #test correction------------------------------------WA/AC

    TIME=`tail -1 $RUN/time.$count`
    diff $DATA/output.$count $RUN/stdout.$count >/dev/null 2>&1
    if [ $? -eq 0 ]
    then
        echo "$count AC $TIME" >> "$RUN"/"result.txt"
    else
        echo "$count WA $TIME" >> "$RUN"/"result.txt"
    fi

    let count=$count+1
done

ojdaemon脚本:
#!/bin/bash
#     name : ojdaemon
OJDIR=$1
while :
do
    if [ `ls $OJDIR/new | wc -l` != 0 ]
    then
        FILE=`ls $OJDIR/new`
        for i in $FILE
        do
            echo "start file: $i"
            mkdir $OJDIR/run/$i
            ./execute $OJDIR/new/$i $OJDIR/run/$i
            if [ $? != 1 ]
            then
                ./judge $OJDIR/new/$i $OJDIR/run/$i
            fi
            mv $OJDIR/new/$i $OJDIR/finished/$i
            echo "finish file: $i"
        done
    fi
    sleep 1
done

阅读(1152) | 评论(1) | 转发(0) |
给主人留下些什么吧!~~

chinaunix网友2011-04-18 06:59:44

oj难在安全性……