summaryrefslogtreecommitdiff
path: root/readme.md
blob: 4abfbdb1dbb8a65945ca9fd97957a5763afe0019 (plain)
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

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