Browsed by
分类:PHP

PHP

[看着不爽] NEUCrack 替代掌上东大的网页端查询工具

[看着不爽] NEUCrack 替代掌上东大的网页端查询工具

不得不吐槽一下, 学生竟然需要为了查询寝室班级信息而去下载一个只会用一次, 没错只会用一次, 的软件, 叫掌上东大

因而本着造福大家+宣传我网络部+自己闲着没事玩玩这三个原则, 将掌上东大给实现为了一个网站

 

传送门

16级的目前还不能查询到自己的信息, 无论是用我这个web还是用app都不行, 目前登陆的时候,你们会看到这样的提示

Screenshot from 2016-08-15 13-49-39

而当大家信息可以查询的时候, 就会变成这个样子

Screenshot from 2016-08-15 13-50-51

 

可以查询掌上东大能查到的各种信息, 主要是给新生使用的 因为这些信息对于13 14 15级的没有什么用= =

 

下面上几张使用截图

3f1e5d92446e2b21 -7b7bea5bfaacb908 -6d9f9f2ceca30ab4

 

 

 

Gitlab DroneCI 配置记录

Gitlab DroneCI 配置记录

OJ的代码越来越多了, 功能也越来越多= = 也就导致bug越来越多, 测试的必要性就很高了, 因此我们需要用 CI平台鞋好的代码进行及时的测试, 因为OJ的代码是私有的,不能直接用DroneCI 或者是 TravisCI, 因而自己需要搭建一个DroneCI,具体操作如下, 根据DroneCI 官方文档说明  gitlab配置droneCI还有点麻烦, 之间也真遇到了几个坑= = 因此纪录一下过程

服务器端使用CentOS 首先安装docker, 并且 fetch DroneCI的镜像image到本地, 这就是一个基本的DroneCI环境了

根据DroneCI的说明 , 在  gitlab里首先创建一个application Oauth 接口,  配置为

Callback URL:即DroneCI所在的auth URL :http://202.118.31.226:3322/authorize这里为这个

然后会生成application id ****(A) 和 application secret *****(B)

将这两个写在 DroneCI Server的 /etc/drone/dronerc内 分别对应 A=> client_id B=> client_secret

注意REMOTE_DRIVER为 gitlab

REMOTE_CONFIG为 http://example.yourgitlab.com?client_id=A&client_secret=B

然后将 这个保存为脚本

然后运行脚本之后, DroneCI就搭建好了~ 点击登陆会跳转到相应的gitlab Oauth页面, 最开始因为没有弄清楚Oauth的关系, 把secret还有 CallbackURL全填写错了导致一直登陆失败QAQ

[NEUOJ日记] #1 Hello World

[NEUOJ日记] #1 Hello World

写在前面:

NEUOJ的开发即将满五个月, 算是我在大学阶段做的最大的一个项目了(因为搞ACM的缘故没有在大一大二做什么项目出来) 在开发过程中遇到了很多问题  & 学到了很多东西, 谨以此系列文章记录开发过程以及开发心得体会

文章的格式:

每一篇文章都会以: 一个主标题 开头, 然后 分为多个副标题, 每个副标题后面会跟一个解释下面要讲的内容的commit-id

Hello World

Why we start (No commit id)

两年半的ACM生涯结束了, 老师征求我们对于重写OJ的想法, 我们队伍的大家早就有自己写一个OJ的想法了, 作为挖坑小能手的我 ( Qrz ) 本来还有点因为自己的时间+个人原因不是很想搞(其实内心是非常想搞的) 被两个队友拉着就果断入坑了, 我们想写出一个能够给大家一个梯度训练, 界面友好, 测评多样化, 符合当今Web开发潮流的新的Online judge 系统, 于是我们队伍+ sjm + wyf就开始了对OJ的开发, 最初的分工是 我们队伍搞 Web 后端开发, sjm 搞前端开发, wyf + 我搞测评端研究

How we design (No commit id)

开发OJ对我来说最陌生的就是测评后端的开发, 不知道如何下手, 好在老师给我们提供了一个开源的测评系统 domjudge, domjudge的后端judgehost已经非常完善了, 支持多语言多环境多测试样例的安全测评, 于是我们初期就直接使用judgehost来做我们的测评后端, 然后前端我们使用的是Bootstrap框架, Web后端使用Laravel框架, 然后我们初步设计了一下表的结构, 参考了hustoj的数据表结构 & 我们自己的表结构,对表进行了设计, 最初的表有

 

(之后会在不同的阶段介绍表的具体结构  & 修改)

How we start(No commit id)

经过一周的讨论, 我们最后定下来了第一版的目标 先做出一个可以让用户提交代码(不管能不能测评)能看题的一个壳出来(虽然这个后来很快就实现了), 前端为 sjm 开始学习前端的知识(Bootstrap jQuery等等),后端为 accelercode队伍(即我们队) 我的另外两个队友都没有Web开发的经验, 因此给他们安排的任务是先学习PHP, 然后学Laravel, 在此同时我先开始熟悉laravel5(我之前用的是laravel4) 熟悉5之后, 开始建表, 建Model,建route, wyf 和 我的测评后端的任务是(刚开始没有让我搞测评后端, 我感觉搞OJ最有趣的地方就是测评后端了于是自己也主动去看了) 搭建domjudge, 并且研究judgehost的源码

Build the Domjudge(No commit id)

回去之后,我就开始了自己本地搭建domjudge的过程, 其中遇到了一些问题, 比如 archlinux下 jsoncpp头文件的名字和domjudge 的configure脚本里的名字不符,会导致就算安装了jsoncpp-devel还是找不到头文件, 这时候我在/usr/include/下面mkdir jsoncpp/json/ 然后把所有json/下的头文件拷贝到 jsoncpp/json/下 ,然后 再次configure就OK了 另外在下载源码之后没有configure文件, 需要先./bootstrap才行, 然而 bootstrap的时候会make 一次 latex的东西, 如果电脑里没有latex的东西, 你需要自己将 Makefile里关于latex的东西注释掉,也就是注释掉 make distclean下面的那一行,然后就可以了

Make the Plan for 1.0(931612-ffb28b)

这是我们的第一条commit, 在这个commit的时候, 我将大家拉入了我Bearychat的讨论组 NEUOJ-accelercode(private)

并且, 使用学校的gitlab 服务器 (219.216.96.46)对代码进行托管, 新建了 README.md 当时的计划如下:

 

然后为laravel工程建立了.gitignore, 并将laravel工程建好,配好了PHPStorm, laravel的环境, 配laravel的环境使用的是一键式傻瓜XAMPP, 我们的OJ开发正式开始 [Wed Nov 25 19:35:11 2015 +0800]

[NEUOJ] 测评后端分析 测评过程分析(judgedaemon.main.php)

[NEUOJ] 测评后端分析 测评过程分析(judgedaemon.main.php)

还没有整理, 先放生肉(Draft)

DOMJudge 测评后端API分析
====

### 调用流程简介:
1. domserver存储有所有数据信息,包括测评必须的信息
2. domserver提供一套RESTful API供judgedaemon客户端调用, judgedaemon可以有多个实例同时运行
3. judgedaemon运行之后, 每隔一定时间向domserver的api请求数据, 如果有数据的话, server会返回给judgedaemon一个json包,包含要运行的judge所需要的所有信息
4. judgedaemon将信息解析之后, 制作出相应的程序执行,和编译脚本 compile.sh , run.sh 之后执行(可以选择在CHROOT环境下执行, 暂时没有考虑)
5. 执行后的结果通过参数和返回值的形式返回给judgedaemon , 之后judgedaemon将测评结果数据提交给domserver, domserver随即更新数据库内的信息

### judgedaemon.main.php内函数分析

* dbconfig_get_rest
* fetch_executable
* judge
* read_credentials
* request
* rest_encode_file
* usage

#### dbconfig_get_rest
* arguments:
$name: 用于表示想要get的配置的名称

* description:
获取服务器的配置信息

* retval
服务器的相应的配置信息

#### fetch_executable
__核心函数,用于下载用户提交的代码,并且将代码编译, 生成运行测评的脚本run.sh 并且返回run.sh的绝对路径共后续调用使用__

* arguments:
$workdirpath: 测评路径
$execid: 需要fetch的执行脚本archive的id
$md5sum: zip的校验和
* description:
该函数根据提供的三个参数, 先检查是否本地已经存在运行本次测评需要的所有脚本(或者二进制文件), 如果不存在则从server 访问 REST/executable ,获取下来相应的execid对应的base64加密后的zip文件,解码,然后在本地的workdir/executable/$execid/下进行解压 ,并且根据不同语言写入不同的脚本内容
* retval:
返回值为相应的执行脚本(run.sh)所在的绝对路径

#### judge(主测评函数)
* arguments:
$row: 一个数组,里面含有测评所需要的所有信息, $row是在服务器端获得数据之后decode,然后存入的数据
* description:
该函数实现比较复杂, 将该函数的整个执行以流程的形式说明
1. 检查是否有创建文件等一系列的权限
2. 获取比赛队员提交的文件 需要访问RESTapi 的 submission_files ,id存在$row[‘submitid’]内
3. 获取编译该语言代码所需的 compile script ,调用fetch_executable, 取出所需的compile_script,并且返回一个绝对路径 $execrunpath
4. 运行LIBJUDGE_DIR下的compile.sh脚本, 对代码进行编译
5. 检查compile的成功与否, 成功则继续,否则退出,并将compile result返回给server
6. 如果有CHROOT的设置,则建立chroot环境
7. 循环获取每个testcase, 本地无testcase则去远端获取(input & output) ,将他们放在 $workdirpath/testcase/下
8. 获取hardtimelimit(运行时限), __**未解决**__为什么要用overshoot_time这个函数来求运行时限(line 612左右 定义在 lib/lib.misc.php下)
9. 执行testcase run脚本, 测评开始
10. 判断测评结果(返回值的含义)
11. 尝试从program.metadata中读取测评耗时(等信息)
12. 将测评结果返回给server RESTapi POST 请求 judging_runs 返回的数据如下:(数据的解释可能有偏差)


testcaseid: 测试数据id
runresult: 执行结果
runtime: 执行时间
judgehost: 测评的host名
output_run: 测评标准输出
output_error: 测评中的地方发
output_system: 测评信息
output_diff: 测评diff

13. 如果有chroot环境则destroy掉
14. 一次judge结束

* retval:NULL
#### read_credentials
* arguments: NULL
* description:
获取配置文件(ETCDIR/restapi.secret)中的认证信息并且添加到全局认证变量 $endpoints 中.配置文件中通过空白字符对每个信息域进行分割, 信息含有 认证记录的index(字符串), RESTAPI的入口地址 和访问RESTAPI需要的用户名和密码.
* retval
实际上是将全局变量 $endpoints的信息更新了, 不过没有返回值

#### request
* arguments:
$url:请求的restapi的路径
$verb: 请求方式(GET POST PUT…)
$data: 通过curl GET or POST时候附带给server的数据
$failonerror: 表示这个函数失败的时候是fail还是报警告
* description:
所有的curl请求通过这个函数进行, 这个函数就是封装好的curl请求函数, 当 $verb 参数为GET时, 表示通过GET请求数据, 即请求的是 restapi 中的 xxxx_GET的API 执行过程如下, 先通过curl_init 初始化curl进程, 然后经过setopt设置好各种参数, 然后通过curl_exec向服务器发出请求, 将服务器回传的信息通过$response变量存储起来,并且通过curl_getinfo得到服务器的响应代码,然后进行error handling(如果response为NULL说明函数执行失败)

* retval
返回值为从服务器获得的回传数据, json格式
返回数据样例:

[{"filename":"a.c","content":"LyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKICAgID4gRmlsZSBOYW1lOiAvdG1wL2EuYwogICAgPiBBdXRob3I6IFZPSURfMTMzCiAgICA+ICMjIyMjIyMjIyMjIyMjIyMjIyMgCiAgICA+IE1haWw6ICMjIyMjIyMjIyMjIyMjIyMjIyMgCiAgICA+IENyZWF0ZWQgVGltZTogVHVlIDAxIERlYyAyMDE1IDEyOjQ2OjM5IFBNIENTVAogKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqLwojaW5jbHVkZTxzdGRpby5oPgoKaW50IG1haW4odm9pZCkKewogICAgcHJpbnRmKCJIZWxsbyB3b3JsZCFcbiIpOwogICAgcmV0dXJuIDA7Cn0K"}]

#### reset_encode_file
* arguments:
$file: 文件所在路径
$sizelimit: 是否限制文件的大小 (传递给 dj_get_file_contents)
* description:
将文件用base64和urlencode进行编码,并返回其值, 如果限定了$sizelimit = TRUE 的话, 文件会被限制在50000B
* retval:
返回文件encode之后的字符串

#### usage
* arguments: NULL
* description:
显示说明信息并退出
* retval: NULL

##JSON format


---- POST api/judgings ----
{
"submitid":24,
"cid":2,
"teamid":2,
"probid":4,
"langid":"cpp",
"rejudgingid":null,
"maxruntime":1,
"memlimit":524288,
"outputlimit":4096,
"run":"run",
"compare":"compare",
"compare_args":null,
"compile_script":"cpp",
"compare_md5sum":"71306aae6e243f8a030ab1bd7d6b354b",
"run_md5sum":"c2cb7864f2f7343d1ab5094b8fd40da4",
"compile_script_md5sum":"cf76014b4e27a6e25378055f53733a7a",
"judgingid":37
}
---- GET api/config ----
{
"clar_categories":{
"general":"General issue",
"tech":"Technical issue"
},
"script_timelimit":30,
"script_memory_limit":2097152,
"script_filesize_limit":65536,
"memory_limit":524288,
"output_limit":4096,
"process_limit":64,
"sourcesize_limit":256,
"sourcefiles_limit":100,
"timelimit_overshoot":"1s|10%",
"verification_required":0,
"show_affiliations":1,
"show_pending":0,
"show_compile":2,
"show_sample_output":0,
"show_balloons_postfreeze":1,
"penalty_time":20,
"compile_penalty":1,
"results_prio":{
"memory-limit":"99",
"output-limit":"99",
"run-error":"99",
"timelimit":"99",
"wrong-answer":"30",
"no-output":"10",
"correct":"1"
},
"results_remap":[

],
"lazy_eval_results":1,
"enable_printing":0,
"time_format":"%H:%M",
"default_compare":"compare",
"default_run":"run",
"allow_registration":0,
"judgehost_warning":30,
"judgehost_critical":120,
"thumbnail_size":128
}
---- GET api/submission_files ----
[
{
"filename":"biubiubiu.cpp",
"content":"I2luY2x1ZGUgPGNzdGRpbz4NCmludCBtYWluKCl7DQogcHJpbnRmKCIyMDRcbiIpOw0KIHJldHVybiAwOw0KfQ0K"
}
]

---- GET api/testcases ----
{
"testcaseid":6,
"rank":1,
"probid":4,
"md5sum_input":"495804e297ee23dbbef4ab1b7bb845ab",
"md5sum_output":"495804e297ee23dbbef4ab1b7bb845ab"
}
---- GET api/executable ----
String(base64_encode zip archive)

---- GET api/testcase_files ----
String(base64_encode plain file)

---- POST api/judging_runs ----
// POST omit

[NEUOJ] 测评后端分析 judgehost文件结构分析

[NEUOJ] 测评后端分析 judgehost文件结构分析

NEUOJ的测评后端暂时使用的是domjudge 的 judgehost作为测评后端 下面分析一下judgehost的工作原理

首先分析一下judgehost的几个核心文件的功能

[这里省略了从clone domjudge repo 到编译安装好judgehost这个过程, 我认为来看这篇文章的应该都是已经可以自己安装好domjudge的人,不然可能这篇文章对于你来说还不适合阅读]

首先看bin下面的文件

runguard 是负责保证用户程序的安全运行, 不会对系统进行破坏的程序, 这个的代码利用了 rlmit, cgroup timeout等方式对用户程序进行限制

judgedaemon 一个php脚本, 测评后端的完整进程, 包括通过服务器下载数据, 到调用相应可执行文件对代码进行编译运行比对之后. 将结果返回给webserver的整个过程都是由这个程序进行的

runpipe: 用于在runjury(特殊的测评程序) 和 user program之间建立双向管道,进行交互式测评(目前只了解这些)

create_cgroups: 在设置了enable_cgroup 的编译参数之后, 通过这个来创建domjudge的 control group, cgroup能够获得更精确的运行时间和使用资源情况

dj_make_chroot, dj_make_ubuntu_chroot: 用于让java程序可以在chroot环境下运行

再看etc文件夹下的文件

sudoers.domjudge: 这个文件配置好了 运行测评的时候的用户的sudo权限配置

common-config.php: 一些通常的config文件

judgehost-static.php: 通过make 和 make install生成的静态config文件,不要进行修改

restapi.secret: 里面存有向API请求的时候的API地址和认证信息

再看judgings文件夹

judgings文件夹下, 所有的文件都是测评的时候生成的, 他的第一级给每一个judgehost分配一个不同的文件夹,名字为 HOSTNAME-n  , 每一个judgehost都要以一个不同的用户来运行, 不然会产生问题

每个judgings文件夹下, 有多个endpoint, 每一个endpoint对应你再 restapi.secret里面配置的不同的名字

如endpoint-neuoj

每个endpoint下 , 有 这样的文件夹: c[n]-s[n]-j[n]  每一个文件夹内都是一次测评,如果这个测评之前被测过了, 重新测评的时候, 原来的测评会叫做 c[n]-s[n]-j[n]-old-timestamp , 除了每一个测评一个文件夹以外, 还有两个文件夹, 一个用于存从服务器fetch来的input output, 一个用于存从服务器fetch来的 executable 分别叫testcase executable

对于每一个测评文件夹下的文件分析留到之后解释

再看看log文件夹, log文件夹内只存了必要的log信息, 没有其他东西, 至于run 和 tmp文件夹, 目前不清楚

最后看lib文件夹 ,仅介绍主要的几个文件, 我们看 lib/judge下的文件

testcase_run.sh 是用于运行程序测评的脚本, 脚本接受多个参数 会在介绍judge流程的时候具体介绍

sh-static 一个静态的 shell

judgedaemon.main.php 整个测评运行的主要程序, 实际上 bin下的judgedaemon就是来调用这个程序的

chroot-startstop.sh: 处理chroot

check_diff.sh: 简单的compare脚本

compile.sh: 一个用于调用其他compile executable的wrapper,并且保证compile不超时, 不超资源

 

以上就是judgehost的一个简单的分析, 下一篇会介绍judgedaemon的测评流程

 

 

 

 

空间红包谜题解法(Linux + base64 + HTTP Header + 摩尔斯电码)

空间红包谜题解法(Linux + base64 + HTTP Header + 摩尔斯电码)

题目

解密红包, 支付宝中文口令红包

(后来被人说二维码扫完还得用电脑重输一遍网址好麻烦 = = 于是我就把二维码对应的网址给出来了 : http://1.justquiz.sinaapp.com/voidmengmengda) —- 这就是完整的题干了, 谜题总共有三关, 个人认为难度是递增的, 下面放出每一关的解法

解法

* 第一关

首先看第一关的内容, 网页本身查看源码并没有什么用处, 不过注意到标题, “请用桌面浏览器打开哦~” 桌面浏览器(即Chrome Firefox) 和一般的移动端浏览器的区别就是, 桌面浏览器支持开发者视图, 可以看到更多详细信息, 除了看到源码, 我们还可以看到cookie session storage等东西, 也包括请求的header, 而这一关的线索就藏在了header里, 在服务器Response你的Request的时候, 会在header里带上下一关的线索,  之后我在空间里也对第一关进行了提示, 有十多人在提示之后到达了第二关QAQ 比我预期的少了很多 附上第一关解决的截图(点击可查看大图) 图中的 HintURL 就是第二关的线索

 

* 第二关

( 列出服务器网站目录) 进入到第二关, 你会发现看到一个在线编译器, 以及这样一段提示想信息:

Happy New Year~! Congrats! You have solve the first Challenge! See what you can find here
Remember : This is a BUGGY online Compiler
This is a BUGGY online Compiler 表示这个在线编译器是有bug的, 具体是什么bug就需要大家自己去找了, 这一关我没有再给提示, 大家稍微尝试之后就会发现, 这个online Compiler没有禁止系统指令的执行, (虽然用户权限是正确的, 无法删除root 的文件, 但是还是有很多事情可以做的)  因而编写下面代码到在线编译器里 , (我选用C语言做示例)

执行之后 ,会显示如下信息 :

稍微留心一下, 就会发现, 你列出的目录, 就是你当前访问的网站所在的目录, 同一级 ,再仔细看一眼列表 ,找到提示文件 thisIStheHintYouNeed.html 通过浏览器访问这个文件 , 得到下一关的提示信息, 本关解决. 附上本关解决之后的截图(点击查看大图)

 

* 第三关

这是本谜题的最后一关了, 也是我制作的时候花时间最多的一关(毕竟第一次用CoolEdit 以前从来没玩过QAQ) 通过第二关的最后提示, 得到一个网址 : 在浏览器里访问改网址 得到类似下面的东西(仅截取部分做展示)

看到这种形式的文件, 第一反应就是base64编码, 尝试用在线解码器进行解码 , 结果发现解出乱码了 , 推测这可能是一个二进制文件, 于是用Linux下自带的解码工具 (Windows下也许也有,不过我不清楚00.00) 将文件解码之后, 输出到另一个文件, 注意不要带后缀名, 带后缀名会影响linux对文件类型的推测, 一会儿要进行文件类型的推测 执行下面指令得到解码后的文件 :

然后推测文件类型 , 通过hexdump xxd 等工具并没有看出文件是什么类型的 = = (也许是我自己能力不够) 因此使用linux下的file指令推测文件类型

通过这个可以看出, 这应该是一个媒体文件 , 因此用播放器对其进行播放 , (linux 下有工具 playsound 或者修改后缀名进行播放) 听到电报音, 长短结合,  想到可能是摩尔斯电码, 然后根据摩尔斯电码表对应下来 密码为  100081  转成中文 一零零八一, 输入进口令, 然而并不对 , 这是这一关的最后一个陷阱, 发现不对之后, 回去看一下第二关的提示URL :  最后面 drowssap.txt 看起来是不是很眼熟,  他就是单词password的逆转, 这是重要的提示信息,因此就说明要对摩尔斯电码进行逆转, 那么到底是把所有的数字颠倒顺序, 还是指把点(.) 和划(-) 的表示颠倒? 尝试之后发现 , 逆转得到的密码为  180001  而将点划表示颠倒之后得到的密码为  655536  作为一个程序员, 这两个选择哪个就不难决定了吧~  到此整个谜题全部解开了, 在支付宝页面输入正确的密码对应的中文, 就会拿到红包啦~    

 

 

后记 : 最后也没有人拿到那个红包QAQ,  不过还是有很多人很接近答案了~ 解密红包的乐趣在于解密而不是红包~ 我是玩的很愉快, 大家也玩的很愉快就好~

 

附上解密后的音频文件:

hint

以及摩尔斯电码对照表

数字

字符 电码符号 字符 电码符号 字符 电码符号 字符 电码符号
0 ━ ━ ━ ━ ━ 1 .━ ━ ━ ━ 2 ..━ ━ ━ 3 ...━ ━
4 ....━ 5 ..... 6 ━ .... 7 ━ ━ ...
8 ━ ━ ━ .. 9 ━ ━ ━ ━ .

 

[被迫参加的hackathon] 在线编译系统开发小记

[被迫参加的hackathon] 在线编译系统开发小记

吐槽

因为某种原因我没有参加MSC举办的Hackathon, 不过我的部员们参加了 0.0 然后我本来想去蹭点Pizza之类的东西吃,结果(我感觉他们是给我诱拐过去了) 到了比赛现场之后告诉我, 这里封馆了 Orz 于是乎我就被迫开始写代码(连电脑都没有带只为了去蹭口pizza吃的我TAT[结果最后还没吃到pizza])

实现的是一个简单的在线编译系统 TOC (Toy Online Compiler) 支持多种语言, 下面简单说一下实现的思路和核心的代码

实现思路

简单分析一下这个系统,由两部分组成 ,代码提交模块和代码编译运行模块 ,前者负责将代码交给后者,后者编译运行完毕将结果返回给前者,然后前者将结果展示给用户.

具体实现方式是: 代码提交模块负责将代码文件保存到服务器, 然后通过socket将消息通知到代码编译模块,然后代码编译模块执行完毕的结果再通过通信的方式传递回来, 很显然实现代码提交模块实现难度很容易,主要的问题在后者的编译模块的通信和编译问题, 下面给出编译模块的核心代码

这段代码就是编译模块的核心逻辑, 我使用了一个队列来维护所有在队列内的通信, 队列最多有5个元素,   代码运行起来会持续检查队列是否为空,如果队列不为空,就会取出队列头的socket,处理socket传来的消息,编译相应的代码,然后产生结果通过封装好的socket_write SockWrite,将运行结果回传给代码提交模块,重复上述操作.

为了保证代码的可读性, 封装了一个编译类 actionClass 来进行编译和运行, 编译和运行的方式是通过exec调用系统命令,下面会具体说明

 

实现细节

  •  编译和运行的方式是使用exec调用系统指令, exec指令可以直接将执行结果作为返回值,不过他的结果只能返回stdout里的内容,stderr的内容不能返回, 因此我使用的方式是 将stderr的内容重定向到文件 cerr.txt 然后检测此文件是否为空, 如果不为空的话说明出错了
  • 不过在最初实现的时候出现了这样的问题, 当你提交一个编译错误的代码之后,再提交一个可以正常运行的代码,编译模块仍然会报编译错误, 而如果手动查看这个文件发现这个文件大小为0 , 通过打印filesize(“cerr.txt”)的返回值,发现了 filesize的返回值不为0 ,但是此时cerr.txt文件大小为0 (du -h cerr.txt )  查资料发现,  filesize 的结果会调用缓存的结果  “Note: The results of this function are cached. See clearstatcache() for more details.“[php.net 原文] . 因此在每次取得filesize之后, 都要使用clearstatcache()将之前的状态清除掉
  • 另外遇到的一个问题就是在停止掉后端编译模块之后, 再次启动这个模块会报错 Unable to bind , address already in use , 这个问题在php.net 的官网也有说明

If you want to reuse address and port, and get rid of error: unable to bind, address already in use, you have to use socket_setopt (check actual spelling for this function in you PHP verison) before calling bind:

设置上   SO_REUSEADDR

 

  • 另外代码运行时限是使用Linux中的timeout的功能实现的
  • 当程序执行结果为空的时候(不产生任何输出) 代码提交模块会一直在socket_read()处等待到来消息, 因此通过自己实现了封装好的SockRead和SockWrite 来避免这个问题

 

 

目前实现阶段

  • 支持PHP C++ C Python Ruby 的编译(解释)运行
  • 可以在Raspberry Pi上搭建整个系统

待解决问题

  • 编译时使用sandbox来保证安全性 , 暂定使用chroot来实现sandbox功能
  • 登录和注册没有完全实现
  • 将这个代码布置到拥有防火墙的CentOS服务器上, 两个模块之间不能互相通信(这个问题一直还没解决)

 

[Laravel] 配置phpstorm支持laravel语法补全

[Laravel] 配置phpstorm支持laravel语法补全

QAQ 不得不说,想使用我喜欢的vim来完美的做到larvel的智能补全太难了(以后自己试试能不能写出来插件吧QAQ*()

因此我回到了以前开发时用过的phpstorm, 给phpstorm配置laravel插件, 操作很简单, 不过要注意版本的兼容问题.

1. (其实没有顺序啦) 安装PhpStorm的Laravel Plugin

在phpstorm里连按两下Shift ,打开指令输入窗口,输入 Plugin,  选择 Install Plugin, 搜索laravel插件并且安装.

2.使用Composer 安装 laravel-ide-helper

这个laravel-ide-helper插件是我们要想让上面的插件实现补全的必备依赖, 如果不安装这个插件的话是没有办法使用laravel的补全的功能的, 而这个插件安装的版本要和自己的laravel版本配套

  • 使用的是 4.2.*版本的laravel 需要安装1.11.*的插件
  • 5.* 版本的安装2.*的插件

注意如果版本不匹配是不能安装成功的 , 会提示你缺少依赖

 

附上laravel-ide-helper插件的地址: Laravel-Ide-Helper

[Laravel] 使用artisan时遇到的问题 (更新中)

[Laravel] 使用artisan时遇到的问题 (更新中)

运行 php artisan migrate 的时候 报错(错误信息见下面) 的解决方法

报错信息如下

这是因为配置里面少了 一个参数 “migrations” 的值, 加上这个参数

之后问题就解决了 ~~~

 

执行db:seed 时,遇到问题(问题见下文)

主要错误信息:

参考这篇文章:http://laravel.com/docs/5.1/upgrade#upgrade-4.1.26

在User.php 中加入 :

再次运行php artisan db:seed 就可以了~

justQuiz!开发计划-1

justQuiz!开发计划-1





justQuiz Develop Plan







justQuiz Develop Plan

1 WORKING STEP1 简易答题&判题(客观题)的实现

1.1 WORKING A 题目管理

本阶段要实现题目管理的基本功能 及试题录入以及试卷生成
所有试题初期决定为存入同一个数据表,每一道试题包含的数据域有

  • PID 题目ID
  • title 题目标题
  • body 题目内容
  • attachment 附件路径 为以后使用
  • isObjective 题目是否为选择题
  • isMulti 题目为单选or多选
  • item1 item2 item3 item4 item5 item6 item7 选项内容
  • answer 正确答案 (正确答案支持三种格式 1.单选答案 2.多选答案(可以用XML可以用字符串)3.主观题答案(

支持关键字匹配,全部匹配为正确,部分匹配的情况没有考虑 初期只开发单选)

  • correctNum 答对的次数
  • wrongNum 答错的次数

另外一个数据表存放生成的试卷信息
每一张试卷的数据域有

  • EID 试卷的ID
  • items 题目ID组成的字串
  • rankAnum rankBnum rankCnum rankDnum 各分段学生数量统计
  • TimingInfo 暂时不明确如何存储时限信息,也许用xml STEP1不考虑

1.1.1 DONE Func1-添加题目到题库

CLOSED: 2015-02-07 六 19:59

  • DONE 建立PItemclass类的数据库写入和从POST读入功能
    CLOSED: 2015-02-07 六 13:30
    定义一个PItemclass类,这个类封装一道试题的所有信息以及对试题进行的操作

1.1.2 TODO Func2-用题库的题目组成试卷

1.1.3 DONE 系统初始化的实现

CLOSED: 2015-02-06 五 20:04
暂时搁置这个功能 先采取在数据库内预先生成一套试卷的功能来测试答题判题功能是否工作正常

1.2 DONE B 答题功能

CLOSED: 2015-02-07 六 19:58

1.2.1 DONE Func3-抓取特定试卷的题目显示到答题区

CLOSED: 2015-02-07 六 19:58
为实现本功能,将设计一个Examclass类来对试卷进行操作
examclass类内存有用户的答案和一个PItemclass类数组,并且具有判断题目是否正确的函数
为了保证用户只通过这一个页面就能够访问所有的题目,使用PHPSESSION对其进行管理,Examclass类
内含有显示试题这一函数,因而可以直接使用此函数调取相应的题目

  • DONE 设计Examclass类 完成上述功能
    CLOSED: 2015-02-07 六 13:30

    • DONE 设计Examclass类的同时需要对quiz.php的逻辑进行梳理
      CLOSED: 2015-02-07 六 15:59
  • DONE 扩展PItemclass类的功能,使其支持根据题目ID加载题目
    CLOSED: 2015-02-07 六 13:30

    • DONE 解决中文乱码问题
      CLOSED: 2015-02-07 六 00:23
  • DONE 使用session完成题目在同一页面上显示不同题目,以及对试卷的整体判题
    CLOSED: 2015-02-07 六 13:30
    逻辑关系设计
    判断用户是否为GET到此页面(即第一次访问此页面) 是的话输出选择试卷表单
    否则 判断用户是否已经获得试卷,是的话 输出下一题 否的话 判断用户是否填写了
    选择试卷表单的信息 是则获得试卷,否则输出选择试卷表单

1.2.2 TODO Func4-判题功能

2 TODO STEP2 支持题目上传附件

3 TODO STEP3 支持用户注册,登录

4 TODO STEP4 支持显示该套卷的分数分布

5 TODO STEP5 人工批改功能的添加

6 TODO STEP6 加入不同的答题模式

7 TODO STEP7 UI优化 jQuery Bootstrap优化UI

8 TODO STEP… 其它功能的添加

Date: 2015-02-07T20:13+0800

Author: VOID001

Org version 7.9.3f with Emacs version 24

Validate XHTML 1.0