分类
代码

Cena代码评测软件系列之三:让选手实时查询评测结果

上篇文章讲到约定源文件注释格式来提取正确文件名从而使用Cena评测Java代码,这篇文章分享使用php解析Cena生成的xml评测结果文件的方法从而使得选手能够在一轮评测后查看自己的成绩。

首先我们发现Cena把评测结果放在/试题/src/机器号/result.xml文件里,而且Cena查看成绩那个界面就是根据这个xml文件展示成绩的。

Cena评测结果窗口
Cena评测结果窗口

根据枚举测试我发现了status代表的含义,写在了下面的php代码里。所以我们只要解析这个xml并把各个值呈现出来就可以实现我们的目的了。
下面是主要的php代码:

<?php
 //error_reporting(E_ALL^E_NOTICE^E_WARNING);//关闭警告。http://www.jb51.net/article/38952.htm
 $path="D:\\TEST\\RunningCoder2\\src\\";
 ?>
 <!DOCtype html>
 <html>
 <head>
	<meta charset="utf-8" />
	<title>评测结果</title>
	<style>
		.wrap{background: wheat;}
		.w{margin:auto; width:50%;}
		.title,.filename{color:blue;}
		.filename{position: absolute;left: 55%;}
		.title{position: absolute;right: 55%;}
		.status{position: absolute;right: 55%;}
		.score{position: absolute;left: 55%;}
		a.back2main{float:left; height: .1em;padding:1.5em;
		background-color:#abc;text-decoration: none;font-weight:bold;}
		a.back2main:hover{background-color:#def;}
	</style>
</head>
 <?php
 if(isset($_GET['stuid'])){//http://zhidao.baidu.com/question/155293761.html
	$path=$path.$_GET["stuid"]."\\result.xml";
	if($_GET['stuid']==""){
		echo"<center><span style='font-size: x-large;'><a href=\"result.html\">请点击输入机器号!</a><span><center>";
		//return;	
	}
 }
 else{
	echo"<center><span style='font-size: x-large;'><a href=\"result.html\">请点击输入机器号!</a><span><center>";
	//return;	
 }
 //echo $path;
 ?>
 
<body>
<header style="background: burlywood;padding: 1em;">
<a href="index.html" class="back2main">首页</a>

<center><h1>评测结果</h1></center>
</header>
	<div class="wrap"><center>
	<div class="w">
	<?php
	$xml=new DOMDocument();
	if(!$xml->load($path)){//http://php.net/manual/en/domdocument.load.php
		echo("<b>输入错误或未评测,找不到评测文件!</b><br><code>".$path."</code><br><a href=\"result.html\" style='font-size: x-large;'>请点击输入机器号!</a>");
	}
	$sumscore=0;
	$pr=$xml->getElementsByTagName('problem');
	//对每一个题目,problem标签
	foreach($pr as $a){
		echo "<hr><div class='problem-wrap'><div class='prattwrap'>";
		//对每一problem的属性
		foreach($a->attributes as $b){
			$n=$b->nodeName;
			$v=$b->nodeValue;
			//属性
			switch($n){
				case "title":echo "<span class=\"title\">$v</span>";break;
				case "filename":echo "<span class=\"filename\">$v</span>";break;
				case "status":break;
				case "hash"://echo "<span>$v</span>";break;
						break;
				case "detail":break;
			}
			//echo "$b->nodeName : $b->nodeValue	";
		}?>
		</div><!--.prattwrap 试题头部--><br>
		<?php
		//选中problem标签的子标签
		$tc=$a->getElementsByTagName('testcase');
		//对每一个子标签 testcase标签
		foreach($tc as $ta){
			//echo " &nbsp;&nbsp;&nbsp;&nbsp;";
			//选中testcase属性
			foreach($ta->attributes as $tb){
				switch($tb->nodeName){
					case "status":echo "<span class=\"status\">".statusinfo($tb->nodeValue)."</span>";break;
					case "exitcode":echo "<span class=\"exitcode\">".exitcodeinfo($tb->nodeValue)."</span>";break;
					//case "detail":echo "<span class=\"testcase\">$tb->nodeValue</span>";break;
					//case "time":echo "<span class=\"testcase\">$tb->nodeValue</span>";break;
					//case "memory":echo "<span class=\"testcase\">$tb->nodeValue</span>";break;
					case "score":echo "<span class=\"score\">$tb->nodeValue</span>";
								$sumscore=$sumscore+$tb->nodeValue;break;
				}
				
			}
			echo "<br>";
		}
		?>
		</div><?php
	}
	echo "<hr><strong style='color:red;'>总得分:$sumscore</strong><br>";
	
	function statusinfo($status){
		switch($status){
			case 2:return "无法运行";
			case 3:return "超过时间限制";
			case 4:return "超过内存限制";
			case 5:return "运行时错误";
			case 6:return "崩溃";
			case 7:return "正确";
			case 8:return "错误的答案";
			case 9:return "部分正确";
			case 10:return "无输出";
			case 11:return "犯规";
			case 12:return "缺少标准输入";
			case 13:return "缺少标准输出";
			case 14:return "找不到程序";
			case 15:return "自定义编译器出错";
			default:return "";
			
		}
	}
	function exitcodeinfo($exitcode){
		switch($exitcode){
			case 3221225477:return "(访问无效内存)";
			case 3221225620:return "(整数被零除)";
			case 3221225725:return "(栈溢出)";
		}
	}?>
	</div></center>
	</div><!--.wrap-->
<footer style="background:rgb(95, 205, 77); padding: 2em;"><a href="result.html" class="back2main">&lt; 返回</a><center>
&copy;2015 <a href="http://jluibm.sinaapp.com" target="_blank" title="吉林大学IBM俱乐部">吉林大学IBM俱乐部</a> 页面制作:<a href="https://youthlin.com" target="_blank" title="霖博客">Youth.霖</a>
</center></footer>
 </body>
 </html>

这是两个辅助html文件:

<!DOCtype html>
<html>
<head>
	<meta charset="utf-8" />
	<title>Running Coder编程竞赛</title>
	<style>
	.nav{height:4em;border-top:#060 2px solid;border-bottom:#060 2px solid;background-color:#690;}
	.nav ul{list-style:none;line-height:40px;margin-left:50px;}
	.nav li{display:block;float:left;}
	.nav a{display:block;color:#fff;text-decoration:none;padding:0 20px;}
	.nav a:hover{background-color:#060;}
	</style>
</head>
<body>
<header style="background: burlywood;padding: 0.3em;">
<center><h1>首届RunningCoder编程竞赛</h1></center>
</header>

<div style="background: rgb(209, 216, 108);padding:0.5em;">

<div class="nav"><ul style="list-style:none;" class="u">
<li><a href="">下载客户端</a></li>
<li><a href="result.html">评测结果查询</a></li></ul>
</div><center>
<h3>说明</h3>

首先下载客户端并运行,安装成功后在右下角有图标。<br>
右击该图标,选择选项,<strong>选手将名称改为自定义:自己的名字拼音</strong>(不要有非英文字符),并查看工作目录。<br>
确定后,进入该目录(可能要新建该目录),将所有试题的源文件保存在该目录中。<hr>
源文件名需要依次(对应4道题目)命名为A、B、C、D(不包含扩展名)。<br>
如C++组第一题源文件名需为A.cpp,Java组第一题是A.java。<hr>
<strong>*************特别注意**************</strong><br>
C/C++组注意:<br>
请在main函数开头添加以下两条语句以便于机器评测重定向输入输出:<br>
<pre><code>freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);</code></pre>
Java组注意:<br>
请在.java源文件第一行添加一条双斜线开头的注释,注释内容为文件名,如A.java文件第一行应为<br>
<pre><code><i>//A.java</i></code><pre>
<center>
</div>

<footer style="background:rgb(95, 205, 77); padding: 1em;"><center>
&copy;2015 <a href="http://jluibm.sinaapp.com" target="_blank" title="吉林大学IBM俱乐部">吉林大学IBM俱乐部</a> 页面制作:<a href="https://youthlin.com" target="_blank" title="霖博客">Youth.霖</a>
</center></footer>
</body>
</html>
<!DOCtype html>
<html>
<head>
	<meta charset="utf-8" />
	<title>结果查询</title>
	<style>a.back2main{float:left;width:2.5em;padding:1.5em;
		background-color:#abc;text-decoration: none;font-weight:bold;}
		a.back2main:hover{background-color:#def;}
	</style>
</head>
<body>

<header style="background: burlywood;padding: 1em;">
<a href="index.html" class="back2main">首页</a>
<center><h1>评测结果查询</h1></center>
</header>

<div style="background: rgb(209, 216, 108);"><center style="padding:5em;font-size:x-large;">
	<form action="result.php" method="get" >
		机器号:<input type="text" name="stuid"/>
		<input type="submit"/>
	</form>
</center></div>
	<footer style="background:rgb(95, 205, 77); padding: 2em;"><center>
&copy;2015 <a href="http://jluibm.sinaapp.com" target="_blank"
	title="吉林大学IBM俱乐部">吉林大学IBM俱乐部</a> 页面制作:<a href="https://youthlin.com"
	target="_blank" title="霖博客">Youth.霖</a>
</center></footer>
</body>
</html>

这个页面效果起来是这个样子的:(如果你觉得界面好丑的话请无视之)

首页:注意事项及查询入口
首页:注意事项及查询入口
查询界面
查询界面
查询结果
查询结果

注意:由于是php实现的所以需要一个php环境,机房电脑都是同一个局域网,我使用xampp结果由于机器操作系统不符合啊什么的原因不能安装,幸好我机智早就准备了好几个php环境,以致于我忘记了当时用的是phpstudy还是appserv。。。
可能javascript也可以实现解析xml,那样的话就不需要php环境了,更方便些。

Cena是一个本地评测工具,本来就不适合在线用嘛。在线评测环境怎么搭建呢,PC2、OpenJudge…有待研究……


“Cena代码评测软件系列之三:让选手实时查询评测结果”上的5条回复

代码全看了一遍,感觉你下次直接把HTML部分去了,展示核心PHP函数方法就行了。
XML文档内容没有给出,不过大概看懂了。
Javscript可以实现,不用PHP环境。

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

[/鼓掌] [/难过] [/调皮] [/白眼] [/疑问] [/流泪] [/流汗] [/撇嘴] [/抠鼻] [/惊讶] [/微笑] [/得意] [/大兵] [/坏笑] [/呲牙] [/吓到] [/可爱] [/发怒] [/发呆] [/偷笑] [/亲亲]