summaryrefslogtreecommitdiff
path: root/readme.md
blob: 789fc959799b565e2edabd7ec488d97a621b0c2c (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
Installation
============

These instructions assume you are running Debian Jessie. Install dependencies:

    apt install apache2 nodejs npm python3 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 2 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

    http://codeq.si/libseccomp2_2.2.3-2_amd64.deb
    http://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
    mate terminator
    sudo setcap cap_setuid,cap_setgid+ep sandbox
    sudo setcap cap_setuid,cap_setgid+ep terminator

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'>

Set up apache:

    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/

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

Misc.
=====

Add a new problem to the database by running

    python -m scripts.add_problem

in the toplevel directory. This will ask for language and problem group (groups
can be shared between languages, e.g. Introduction can be used for both Prolog
and Python). The script will print the ID and path for the new problem.

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).')

Traces
======

Actions and corresponding additional attributes are specified here.

Generic:
  - open(time)     # when opening the problem page, time = Date.now() on client
  - close()        # when closing the problem page
  - ins(off, txt)  # offset, text
  - rm(off, txt)   # offset, text, was rm(off, len)
  - plan()
  - hint(feedback)  # feedback = list of returned hint objects
  - test(feedback)  # feedback = list of returned hint objects

Prolog:
  - prolog_solve(query)  # was slv(qry)
  - prolog_next()        # was nxt
  - prolog_end()         # was stp

Python:
  - python_run(program)
  - python_stop()
  - python_input(txt)

Robot:
  - robot_run(program)
  - robot_stop()

Obsolete actions:
  - slva(query)    # "solve all" from tuProlog
  - hnt            # hint button press
  - tst(tot, pas)  # test results (total / passed)