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
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
|
Installation
============
Minimum versions of required packages:
- python3-psycopg2 ≥ 2.5.4
- swi-prolog ≥ 7.3
These instructions assume you are running Debian Jessie. Install dependencies:
apt install apache2 nodejs npm python3 python3-nltk python3-ply \
python3-psycopg2 python3-termcolor python3-urllib3
SWI prolog
----------
To use the correct SWI prolog package (>= 7.3) on Debian, add a custom
repository by creating the file /etc/apt/sources.list.d/prolog.list containing
the following lines:
deb http://ppa.launchpad.net/swi-prolog/devel/ubuntu trusty main
deb-src http://ppa.launchpad.net/swi-prolog/devel/ubuntu trusty main
After that run the following sequence of shell statements to update the package
cache, register the new repository's key, and again refresh the package cache
using the additional key:
apt-get update
apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys EF8406856DBFCA18
apt-get update
libseccomp
----------
A new version of libseccomp (≥ 2.2) with Python bindings is needed to sandbox
Python interpreters. This is not available yet in most distributions. You can
download custom-built packages for Debian Jessie at
https://codeq.si/libseccomp2_2.2.3-2_amd64.deb
https://codeq.si/seccomp_2.2.3-2_amd64.deb
and install them using
dpkg --install libseccomp2_2.2.3-2_amd64.deb seccomp_2.2.3-2_amd64.deb
Alternatively, fetch the latest sources with
git clone https://github.com/seccomp/libseccomp
and configure with --enable-python.
nodejs
------
Run "npm install" inside the codeq-server/web directory to install all
dependencies (they will be installed inside the web directory)
sandbox
-------
Go to directory codeq-server/python/runner and run the following commands to
build the sandbox and set appropriate permissions:
make sandbox
sudo setcap cap_setuid,cap_setgid+ep sandbox
Settings
========
Replace $webroot in this section with the path to codeq-web repo. Remember to
grant read access to $webroot to the apache user.
Set environment variables:
CODEQ_PROBLEMS=<path to codeq-problems repo>
CODEQ_WEB_OUTPUT=$webroot/data
CODEQ_DB_HOST=<address of database server>
CODEQ_DB_DATABASE=<database name, default is 'codeq'>
CODEQ_DB_USER=<database user, default is 'codeq'>
CODEQ_DB_PASS=<database password, default is 'c0d3q'>
Apache
------
Enable required modules:
a2enmod proxy proxy_http proxy_wstunnel rewrite
Add the following directives to the VirtualHost configuration:
DocumentRoot "$webroot"
<Directory "$webroot">
Require all granted
</Directory>
RewriteEngine on
RewriteCond %{REQUEST_URI} ^/ws/ [NC]
RewriteCond %{QUERY_STRING} transport=websocket [NC]
RewriteRule /(.*) ws://localhost:8083/$1 [P,L]
ProxyPass /ws/ http://localhost:8083/ws/
ProxyPassReverse /ws/ http://localhost:8083/ws/
Robot
-----
A Python server on the EV3 brick allows communication between the robot and the
CodeQ application. First install the ev3dev environment on a microSD card by
following the steps on http://www.ev3dev.org/docs/getting-started/.
Copy robot/main.py to the ev3dev environment:
scp robot/main.py root@<robot's address>:/root
SSH into the ev3dev environment and install the required packages:
apt install python3 libboost-python1.55.0 python3-setuptools python3-pil
easy_install3 --user eventlet python-engineio python-ev3dev==0.2.2
Finally, ensure the server is run when the robot is powered on. Add the
following line to /etc/rc.local just before `exit 0`:
python3 /root/main.py &
Running
=======
- first build static JSON data with scripts/build_web_resources.py, read its heading comment for details
- run the prolog interpreter server: swipl prolog/runner/main.pl
- run the session daemon: python3 daemon.py
- run the web server for client communication: node web/main.js
Notes
=====
Testing
-------
You can test stuff in a python interpreter:
>>> import server
>>> session = server.user_session.authenticate_and_create_session(<user>, <pass>)
>>> session.get_problem_data('python', 'introduction', 'fahrenheit_to_celsius')
>>> python = session.get_python()
>>> python.test(231, 180, '''print('-17.7')''')
>>> python.hint(231, 180, '''print('-17.7')''')
>>> prolog = session.get_prolog()
>>> prolog.test(231, 96, 'sister(X,Y):- parent(P,X), parent(P,Y), female(X).')
>>> prolog.hint(231, 96, 'sister(X,Y):- parent(P,X), parent(P,Y), female(X).')
To check for errors in hint definitions you can use the problem_html script:
python3 -m scripts.problem_html python introduction ballistics sl > out.html
Traces
------
Actions and corresponding additional attributes are specified here.
Generic:
- open(timestamp) # opened the problem page; timestamp = Date.now() on client
- close() # closed the problem page
- ins(off, txt) # inserted text; off = offset, txt = inserted characters
- rm(off, txt) # deleted text; off = offset, txt = deleted characters
- plan() # clicked "plan"
- hint(feedback) # clicked "hint"; feedback = list of returned hint objects
- test(feedback) # clicked "test"; feedback = list of returned hint objects
Prolog:
- prolog_solve(query)
- prolog_next()
- prolog_end()
Python:
- python_run(program)
- python_stop()
- python_input(txt)
Robot:
- robot_run(program)
- robot_stop()
Obsolete actions:
- slva(qry) # "solve all" from tuProlog
- hnt # hint button press
|