-
Notifications
You must be signed in to change notification settings - Fork 0
/
code_check.py
139 lines (119 loc) · 4.8 KB
/
code_check.py
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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
#!/usr/bin/env python3
"""
check the security and functionability of uploaded code
- forbid from importing os
- random chessboard check
- some special case check
"""
import imp
import traceback
import sys
import os
import numpy as np
# from timeout_decorator import timeout
FORBIDDEN_LIST = ['import os', 'exec']
class CodeCheck():
def __init__ (self, script_file_path, chessboard_size):
self.time_out = 5
self.script_file_path = script_file_path
self.chessboard_size = chessboard_size
self.agent = None
self.errormsg = 'Error'
# sys.stdout = open(os.devnull, 'w')
# sys.stderr = open(os.devnull, 'w')
# print(self.chessboard)
# Call this function and get True or False, self.errormsg has the massage
def check_code(self):
# check if contains forbidden library
if self.__check_forbidden_import() == False:
return False
# check initialization
try:
self.agent = imp.load_source('AI', self.script_file_path).AI(self.chessboard_size, 1, self.time_out)
self.agent = imp.load_source('AI', self.script_file_path).AI(self.chessboard_size, -1, self.time_out)
except Exception:
self.errormsg = "Fail to init"
return False
# check simple condition
if not self.__check_simple_chessboard():
self.errormsg = "Can not pass usability test."
return False
# check advance condition, online test contain more test case than this demo
if not self.__check_advance_chessboard():
self.errormsg = "Your code is too weak, fail to pass base test."
return False
return True
def __check_forbidden_import(self):
with open(self.script_file_path, 'r', encoding='UTF-8') as myfile:
data = myfile.read()
for keyword in FORBIDDEN_LIST:
idx = data.find(keyword)
if idx != -1:
self.errormsg = "import forbidden"
return False
return True
def __check_go (self, chessboard):
self.agent = imp.load_source('AI', self.script_file_path).AI(self.chessboard_size, -1, self.time_out)
try:
self.agent.go(np.copy(chessboard))
except Exception:
self.errormsg = "Error:" + traceback.format_exc()
return False
return True
def __check_result (self, chessboard, result):
if not self.__check_go(chessboard):
return False
if not self.agent.candidate_list or list(self.agent.candidate_list[-1]) not in result:
return False
return True
def __check_simple_chessboard(self):
# empty chessboard
if not self.__check_go(np.zeros((self.chessboard_size, self.chessboard_size), dtype=np.int)):
print("empty chessboard")
return False
# only one empty position remain
chessboard = np.ones((self.chessboard_size, self.chessboard_size))
chessboard[:, ::2] = -1
for i in range(0, self.chessboard_size, 4):
chessboard[i] = -chessboard[i]
x, y = np.random.choice(self.chessboard_size, 2)
chessboard[x, y] = 0
if not self.__check_result(chessboard, [[x, y]]):
print("only one empty position remain")
return False
return True
def __check_advance_chessboard (self):
# win
chessboard = np.zeros((self.chessboard_size, self.chessboard_size), dtype=np.int)
chessboard[0, 0:4] = -1
chessboard[1, 0:4] = 1
if not self.__check_result(chessboard, [[0, 4]]):
print("win")
return False
# defense 5 inline
chessboard = np.zeros((self.chessboard_size, self.chessboard_size), dtype=np.int)
chessboard[0, 0:2] = -1
chessboard[0, 7] = -1
chessboard[1, 1:4] = 1
if not self.__check_result(chessboard, [[1, 4], [1, 0]]):
print("defense 5 inline")
return False
# two three
chessboard = np.zeros((self.chessboard_size, self.chessboard_size), dtype=np.int)
chessboard[1, 1:3] = -1
chessboard[2:4, 3] = -1
chessboard[1, 6:8] = 1
chessboard[2:4, 8] = 1
if not self.__check_result(chessboard, [[1, 3]]):
print("two three")
return False
# defense
chessboard = np.zeros((self.chessboard_size, self.chessboard_size), dtype=np.int)
chessboard[0, 0:2] = -1
chessboard[0:2, self.chessboard_size - 1] = -1
chessboard[1, 6:8] = 1
chessboard[2:4, 8] = 1
if not self.__check_result(chessboard, [[0, 8], [1, 8], [4, 8], [5, 8], [1, 5], [1, 9], [1, 10]]):
print("defense")
return False
return True