output) {
45 | this.output = output;
46 | }
47 |
48 | public Integer getTimeLimit() {
49 | return timeLimit;
50 | }
51 |
52 | public void setTimeLimit(Integer timeLimit) {
53 | this.timeLimit = timeLimit;
54 | }
55 |
56 | public Integer getMemoryLimit() {
57 | return memoryLimit;
58 | }
59 |
60 | public void setMemoryLimit(Integer memoryLimit) {
61 | this.memoryLimit = memoryLimit;
62 | }
63 |
64 | public Integer getJudgeId() {
65 | return judgeId;
66 | }
67 |
68 | public void setJudgeId(Integer judgeId) {
69 | this.judgeId = judgeId;
70 | }
71 |
72 | public String getSrc() {
73 | return src;
74 | }
75 |
76 | public void setSrc(String src) {
77 | this.src = src;
78 | }
79 |
80 | public String getCallBack() {
81 | return callBack;
82 | }
83 |
84 | public void setCallBack(String callBack) {
85 | this.callBack = callBack;
86 | }
87 | }
88 |
--------------------------------------------------------------------------------
/producer/src/main/java/cn/wzy/producer/vo/ResultCase.java:
--------------------------------------------------------------------------------
1 | package cn.wzy.producer.vo;
2 |
3 | public class ResultCase {
4 |
5 | private Integer status;
6 |
7 | private Integer timeUsed;
8 |
9 | private Integer memoryUsed;
10 |
11 | private String errorMessage;
12 |
13 | public ResultCase(Integer status, Integer timeUsed, Integer memoryUsed, String errorMessage) {
14 | this.status = status;
15 | this.timeUsed = timeUsed;
16 | this.memoryUsed = memoryUsed;
17 | this.errorMessage = errorMessage;
18 | }
19 |
20 | public Integer getStatus() {
21 | return status;
22 | }
23 |
24 | public void setStatus(Integer status) {
25 | this.status = status;
26 | }
27 |
28 | public Integer getTimeUsed() {
29 | return timeUsed;
30 | }
31 |
32 | public void setTimeUsed(Integer timeUsed) {
33 | this.timeUsed = timeUsed;
34 | }
35 |
36 | public Integer getMemoryUsed() {
37 | return memoryUsed;
38 | }
39 |
40 | public void setMemoryUsed(Integer memoryUsed) {
41 | this.memoryUsed = memoryUsed;
42 | }
43 |
44 | public String getErrorMessage() {
45 | return errorMessage;
46 | }
47 |
48 | public void setErrorMessage(String errorMessage) {
49 | this.errorMessage = errorMessage;
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/producer/src/main/resources/application.properties:
--------------------------------------------------------------------------------
1 | server.servlet.context-path=/producer
2 | server.port=8081
3 | # kafka configuration
4 | spring.kafka.bootstrap-servers=202.115.161.211:19092
5 | spring.kafka.producer.retries=0
6 | spring.kafka.producer.batch-size=16384
7 | spring.kafka.producer.buffer-memory=33554432
8 | # encoding
9 | spring.kafka.producer.key-serializer=org.apache.kafka.common.serialization.StringSerializer
10 | spring.kafka.producer.value-serializer=org.apache.kafka.common.serialization.StringSerializer
11 |
--------------------------------------------------------------------------------
/producer/src/main/resources/log4j.properties:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangxiaoshuai-lucky/online-judge/de6c6d4d2b2e947e23d68037a9b3af406d746865/producer/src/main/resources/log4j.properties
--------------------------------------------------------------------------------
/producer/src/main/resources/static/error/405.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | OnlineJudge
6 |
7 |
8 |
9 | 405-请求接口仅支持POST请求
12 |
13 |
14 | 此项目仅提供POST提交接口,接收结果回调接口需要外网服务器地址。
15 |
16 |
17 | GitHub地址:https://github.com/1510460325/online-judge
19 |
20 |
21 | 请求实例:
22 |
23 |
24 | url:POST:http://wangzhengyu.cn:8081/producer/judge.do
26 |
27 |
28 | Content-Type:application/json
30 |
31 |
32 | body:
33 |
34 |
35 | {
36 | "input":["12 12","12 12"],
37 | "output":["24","24"],
38 | "timeLimit":1000,
39 | "memoryLimit":65535,
40 | "judgeId":1,
41 | "src":"#include<iostream>\nusing namespace std;\nint main()\n{\n\tint a,b;\n\tcin>>a>>b;\n int c=a+b;\n cout<<c;\n\n\treturn 0;\n}\n",
42 | "callBack":"http://wangzhengyu.cn:8081/producer/result.do?key=111&submitId=12"
43 | }
44 |
45 | 参数列表(json):
46 |
47 |
49 | -
50 |
51 | 题目id(题目id为本人数据库指定题目id,指定后测试数据为本人系统提供)
52 |
53 |
54 | -
55 |
56 | 输入样例数组(自定义输入样例,输入id之后忽略)
57 |
58 |
59 | -
60 |
61 | 输出样例数组(自定义输出样例,输入id之后忽略)
62 |
63 |
64 | -
65 |
66 | 时间限制:ms
67 |
68 |
69 | -
70 |
71 | 内存限制:kb
72 |
73 |
74 | -
75 |
76 | 判题语言:语言列表1-14
77 |
78 |
79 | -
80 |
81 | 源代码
82 |
83 |
84 | -
85 |
86 | callBack地址:为put请求方式的地址
87 |
88 |
89 |
90 |
91 | 判题语言支持:
92 |
93 |
95 | -
96 |
97 | GCC
98 |
99 |
100 |
101 | -
102 |
103 | GNU C90
104 |
105 |
106 | -
107 |
108 | GNU C99
109 |
110 |
111 | -
112 |
113 | GNU C11
114 |
115 |
116 |
117 | -
118 |
119 | G++
120 |
121 |
122 |
123 | -
124 |
125 | GNU C++98
126 |
127 |
128 | -
129 |
130 | GNU C++11
131 |
132 |
133 | -
134 |
135 | GNU C++14
136 |
137 |
138 | -
139 |
140 | GNU C++17
141 |
142 |
143 |
144 | -
145 |
146 | Java 1.8
147 |
148 |
149 | -
150 |
151 | python2.7
152 |
153 |
154 | -
155 |
156 | python3.6
157 |
158 |
159 | -
160 |
161 | JavaScript
162 |
163 |
164 | -
165 |
166 | C#
167 |
168 |
169 | -
170 |
171 | Ruby
172 |
173 |
174 | -
175 |
176 | GO
177 |
178 |
179 |
180 |
181 | 判题采用异步回调更新函数,网站服务器将判题任务和该id提交给判题服务器,判题服务器判题结束自动调用回调函数携带判题结果。
如上述任务会将结果返回到callBack的put接口中,网站服务器只需要指定一个PUT类型回调地址即可,参数submitId为了分辨是哪个任务的回调结果。
为了回调接口安全,防止其他人篡改结果,建议外加一个密钥:"callBack"
182 | :"http://ip:port/demo/update.do?submitId=111&key=1asdf112asdfasdf",
184 | 由于这个接口地址由网站服务器指定之后发送给判题服务器的,所以只有这两个服务器知道密钥,所以其他人不能修改结果。
回调接口样例:https://github.com/1510460325/online-judge/blob/master/producer/src/main/java/cn/wzy/producer/controller/JudgeController.java
返回数据(json):
187 |
188 |
223 | {
224 | "globalMsg": null,
225 | "result": [
226 | {
227 | "result": 4,
228 | "timeused": 0,
229 | "memoryused": 0,
230 | "errormessage": null
231 | },
232 | {
233 | "result": 1,
234 | "timeused": 0,
235 | "memoryused": 0,
236 | "errormessage": null
237 | },
238 | {
239 | "result": 0,
240 | "timeused": 1,
241 | "memoryused": 6896,
242 | "errormessage": null
243 | }
244 | ]
245 | }
246 |
247 | 返回结果集:0 ~ 8
248 |
249 |
251 | -
252 |
253 | 'Accepted'
254 |
255 |
256 | -
257 |
258 | 'Presentation Error'
259 |
260 |
261 | -
262 |
263 | 'Time Limit Exceeded'
264 |
265 |
266 | -
267 |
268 | 'Memory Limit Exceeded'
269 |
270 |
271 | -
272 |
273 | 'Wrong Answer'
274 |
275 |
276 | -
277 |
278 | 'Runtime Error'
279 |
280 |
281 | -
282 |
283 | 'Output Limit Exceeded'
284 |
285 |
286 | -
287 |
288 | 'Compile Error'
289 |
290 |
291 | -
292 |
293 | 'System Error'
294 |
295 |
296 |
297 |
298 |
299 |
300 |
301 |
--------------------------------------------------------------------------------
/producer/src/test/java/cn/wzy/producer/ProducerApplicationTests.java:
--------------------------------------------------------------------------------
1 | package cn.wzy.producer;
2 |
3 | import org.junit.Test;
4 | import org.junit.runner.RunWith;
5 | import org.springframework.boot.test.context.SpringBootTest;
6 | import org.springframework.test.context.junit4.SpringRunner;
7 |
8 | @RunWith(SpringRunner.class)
9 | @SpringBootTest
10 | public class ProducerApplicationTests {
11 |
12 | @Test
13 | public void contextLoads() {
14 | }
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/readme.md:
--------------------------------------------------------------------------------
1 | ## ACM独立判题服务
2 | 开源项目地址:[github](https://github.com/1510460325/online-judge/)
3 | 可针对性的添加判题语言,或者修改判题细节
4 | ## 判题语言支持:
5 | * GCC
6 | * GNU C90
7 | * GNU C99
8 | * GNU C11
9 | * G++
10 | * GNU C++98
11 | * GNU C++11
12 | * GNU C++14
13 | * GNU C++17
14 | * Java 1.8
15 | * python2.7
16 | * python3.6
17 | * JavaScript
18 | * C#
19 | * Ruby
20 | * GO
21 | ## 判题接口
22 | POST http://wangzhengyu.cn:8081/producer/judge.do
23 | 参数列表(json):
24 | * 题目id(题目id为本人数据库指定题目id,指定后测试数据为本人系统提供)
25 | * 输入样例数组(自定义输入样例,输入id之后忽略)
26 | * 输出样例数组(自定义输出样例,输入id之后忽略)
27 | * "input":["12 12","13 12"] 相当于两个测试用例,第一次测试输入12 12,第二次测试输入13 12
28 | * "output":["24","25"] 对应上面的输出用例的标准输出,第一次测试输出24,第二次测试输出25
29 | * 时间限制:ms
30 | * 内存限制:kb
31 | * 判题语言:上述语言列表1-14
32 | * 源代码
33 | * callBack地址:为put请求方式的地址
34 | ~~~
35 | {
36 | "proId":15,
37 | "input":["99 1","99 1","99 1"], // 有多少个测试数据数组就多长
38 | "output":["98","100\n","100"], // 对应上面每个输入的标准输出
39 | "timeLimit":1000,
40 | "memoryLimit":65535,
41 | "judgeId":1,
42 | "src":"#include\nint main()\n{\n\tint a,b,sum;\n\tscanf(\"%d %d\",&a,&b);\n\tsum=a+b;\n\tprintf(\"%d\",sum);\n\treturn 0;\n}",
43 | "callBack" :"http://ip:port/demo/update.do?submitId=111"
44 | }
45 | ~~~
46 | 判题采用异步回调更新函数,网站服务器将判题任务和该id提交给判题服务器,判题服务器判题结束自动调用回调函数携带判题结果。
47 | 如上述任务会将结果返回到callBack的put接口中,网站服务器只需要指定一个PUT类型回调地址即可,参数submitId为了分辨是哪个任务的回调结果。
48 | 为了回调接口安全,防止其他人篡改结果,建议外加一个密钥:"callBack" :"http://ip:port/demo/update.do?submitId=111&key=1asdf112asdfasdf",
49 | 由于这个接口地址由网站服务器指定之后发送给判题服务器的,所以只有这两个服务器知道密钥,所以其他人不能修改结果。
50 | 回调接口样例:https://github.com/1510460325/online-judge/blob/master/producer/src/main/java/cn/wzy/producer/controller/JudgeController.java
51 | 返回数据(json):
52 | * 全局信息:编译错误信息之类的,判题正常为null
53 | * 判题信息(按参数组数顺序):
54 | * 结果:
55 | * 时间消耗
56 | * 空间消耗
57 | * 运行错误信息:运行正常为null
58 | ~~~
59 | {
60 | "globalMsg": null,
61 | "result": [
62 | {
63 | "status": 4,
64 | "timeUsed": 0,
65 | "memoryUsed": 0,
66 | "errorMessage": null
67 | },
68 | {
69 | "status": 1,
70 | "timeUsed": 0,
71 | "memoryUsed": 0,
72 | "errorMessage": null
73 | },
74 | {
75 | "status": 0,
76 | "timeUsed": 1,
77 | "memoryUsed": 6896,
78 | "errorMessage": null
79 | }
80 | ]
81 | }
82 | ~~~
83 | 返回结果集:0 ~ 8
84 | * 'Accepted'
85 | * 'Presentation Error'
86 | * 'Time Limit Exceeded'
87 | * 'Memory Limit Exceeded'
88 | * 'Wrong Answer'
89 | * 'Runtime Error'
90 | * 'Output Limit Exceeded'
91 | * 'Compile Error'
92 | * 'System Error'
93 | ## 项目整体架构
94 | * 一个判题接收服务:运行在真实服务器上
95 | * kafka消息队列:保存判题任务,让下游服务消费
96 | * docker虚拟服务:运行判题服务消费判题任务,多台负载均衡
97 |
98 | 
99 | ## 打包
100 | 原本想将项目打包成一个镜像的,但是考虑到kafka的配置,打包成一个镜像实在有些牵强,还是自己配置方便得多。
101 |
102 |
103 | ## 源码说明及个人搭建教程
104 | ### 1.源码结构
105 | * producer:接受外部的POST接口请求,发送到kafka消息对列
106 | * consumer:消费kafka任务,判题后将结果回调到callback中
107 | ### 2.运行环境(linux 环境)
108 | * kakfa:用于producer和consumer之间的通信
109 | * 安装教程:略
110 | ### 3.搭建教程
111 | * clone 此项目
112 | * 修改配置文件
113 | * kafka的地址:spring.kafka.bootstrap-servers=192.168.0.115:9092
114 | * 判题程序编译:用于测试用户时间和内存消耗,是c语言写的,需要编译一下
115 | 命令:g++ judge.c -o judge
116 | * 修改判题文件配置:judge.scriptPath=/home/hadoop/judge/test/judge
117 | * 打包:mvn clean package -DskipTests
118 | * 启动项目:
119 | * java -jar consumer-0.0.1-SNAPSHOT.jar &
120 | * java -jar producer-0.0.1-SNAPSHOT.jar &
121 | * 测试:
122 | ~~~
123 | 1.PostMan 测试接口:POST http://你的IP:8081/producer/judge.do
124 | 数据为JSON格式,body如下:
125 | {
126 | "proId":15,
127 | "input":["99 1","99 1","99 1"], // 有多少个测试数据数组就多长
128 | "output":["98","100\n","100"], // 对应上面每个输入的标准输出
129 | "timeLimit":1000,
130 | "memoryLimit":65535,
131 | "judgeId":1,
132 | "src":"#include\nint main()\n{\n\tint a,b,sum;\n\tscanf(\"%d %d\",&a,&b);\n\tsum=a+b;\n\tprintf(\"%d\",sum);\n\treturn 0;\n}",
133 | "callBack" :"http://你的IP:8081/producer/result.do"
134 | }
135 | 2.检查返回数据为OK
136 | 3.查看判题回调result接口里面会有日志输出
137 | 2019-09-29 22:03:15 [ http-nio-8081-exec-5:3730303310 ] - [ INFO ]
138 | ************
139 | 收到任务,将回调到:http://wangzhengyu.cn:8081/producer/result.do?key=111&submitId=12
140 | ************
141 | 2019-09-29 22:03:18 [ http-nio-8081-exec-2:3730305567 ] - [ INFO ]
142 | *****************
143 | key: 111
144 | submitId: 12
145 | result: JudgeResult(globalMsg=null, result=[ResultCase(status=1, timeUsed=0, memoryUsed=0, errorMessage=null), ResultCase(status=1, timeUsed=0, memoryUsed=0, errorMessage=null)])
146 | *****************
147 | ~~~
148 | ***如果此项目对您有帮助,希望能给个star!***
149 | ***如果有爱心人士能给个红包买瓶快乐肥宅水喝也是对我这个小可爱最大的鼓励哟***
150 |
151 |
--------------------------------------------------------------------------------