diff --git a/BUGS.md b/BUGS.md
index 3b06cbe..c1089a6 100644
--- a/BUGS.md
+++ b/BUGS.md
@@ -1,7 +1,7 @@
# BUGS
-- nao esta a usar points das perguntas
+- codigo `hello world` nao esta a preservar o whitespace. O renderer de markdown gera a tag que não preserva whitespace. Necessario adicionar
.
- teste nao esta a mostrar imagens.
- se houver erros a abrir ficheiros .yaml de perguntas, depois dos testes diz "No errors found".
- dizer quanto desconta em cada pergunta de escolha multipla
@@ -19,6 +19,7 @@ ou usar push (websockets?)
# TODO
+- nao esta a usar points das perguntas
- test: mostrar duração do teste com progressbar no navbar.
- submissao fazer um post ajax?
- adicionar opcao para eliminar um teste em curso.
diff --git a/demo/questions/questions-tutorial.yaml b/demo/questions/questions-tutorial.yaml
index bbe1fc1..c210cf2 100644
--- a/demo/questions/questions-tutorial.yaml
+++ b/demo/questions/questions-tutorial.yaml
@@ -330,9 +330,10 @@
podem ser úteis por exemplo para introduzir código.
A resposta é enviada para um programa externo para ser avaliada.
- O programa externo é um programa qualquer executável pelo sistema.
- Este recebe a resposta submetida pelo aluno via `stdin` e devolve a
- classificação via `stdout`.
+ O programa externo é um programa escrito numa linguagem qualquer, desde que
+ seja executável pelo sistema operativo (pode ser um script ou binário).
+ Este programa recebe a resposta submetida pelo aluno via `stdin` e devolve
+ a classificação via `stdout`.
Exemplo:
```yaml
@@ -348,12 +349,13 @@
Neste exemplo, o programa de avaliação é um script python que verifica se a
resposta contém as três palavras red, green e blue, e calcula uma nota no
intervalo 0.0 a 1.0.
- O programa externo é um programa executável no sistema, escrito em
- qualquer linguagem de programação. A interacção com o servidor faz-se
+ O programa externo é executado num processo separado do sistema operativo.
+ Pode escrito em qualquer linguagem de programação, desde que . A interacção com o servidor faz-se
sempre via stdin/stdout.
Se o programa externo exceder o `timeout` indicado (em segundos),
- é automaticamente cancelado e é atribuída a classificação de 0.0 valores.
+ este é automaticamente terminado e é atribuída a classificação de 0.0
+ valores na pergunta.
Após terminar a correcção, o programa externo deve enviar a classificação
para o stdout.
@@ -377,8 +379,9 @@
O comentário é mostrado na revisão de prova.
answer: |
+ Aqui o aluno escreve a resposta.
Esta caixa aumenta de tamanho automaticamente e
- pode estar previamente preenchida (use answer: texto).
+ pode estar previamente preenchida como neste caso (use `answer: texto`).
correct: correct/correct-question.py
timeout: 5
@@ -423,7 +426,7 @@
text: |
Também não conta para avaliação. É apenas o aspecto gráfico que muda.
- Além das fórmulas LaTeX, também se pode escrever troços de código:
+ Além das fórmulas LaTeX, também se podem escrever troços de código:
```C
int main() {
diff --git a/package-lock.json b/package-lock.json
index b04e633..ca36c14 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -3,9 +3,9 @@
"lockfileVersion": 1,
"dependencies": {
"@fortawesome/fontawesome-free": {
- "version": "5.8.1",
- "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-free/-/fontawesome-free-5.8.1.tgz",
- "integrity": "sha512-GJtx6e55qLEOy2gPOsok2lohjpdWNGrYGtQx0FFT/++K4SYx+Z8LlPHdQBaFzKEwH5IbBB4fNgb//uyZjgYXoA=="
+ "version": "5.11.1",
+ "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-free/-/fontawesome-free-5.11.1.tgz",
+ "integrity": "sha512-DtXLVYAkDU0ce1cFUgLvZaMd1R2J/LviBYih9xr4ZLhQMrgvYX7w2vOxlpKLRALfIj5GyC5zoVrcACOkLcFgvg=="
},
"bootstrap": {
"version": "4.3.1",
@@ -13,9 +13,14 @@
"integrity": "sha512-rXqOmH1VilAt2DyPzluTi2blhk17bO7ef+zLLPlWvG494pDxcM234pJ8wTc/6R40UWizAIIMgxjvxZg5kmsbag=="
},
"codemirror": {
- "version": "5.45.0",
- "resolved": "https://registry.npmjs.org/codemirror/-/codemirror-5.45.0.tgz",
- "integrity": "sha512-c19j644usCE8gQaXa0jqn2B/HN9MnB2u6qPIrrhrMkB+QAP42y8G4QnTwuwbVSoUS1jEl7JU9HZMGhCDL0nsAw=="
+ "version": "5.48.4",
+ "resolved": "https://registry.npmjs.org/codemirror/-/codemirror-5.48.4.tgz",
+ "integrity": "sha512-pUhZXDQ6qXSpWdwlgAwHEkd4imA0kf83hINmUEzJpmG80T/XLtDDEzZo8f6PQLuRCcUQhmzqqIo3ZPTRaWByRA=="
+ },
+ "commander": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-3.0.1.tgz",
+ "integrity": "sha512-UNgvDd+csKdc9GD4zjtkHKQbT8Aspt2jCBqNSPp53vAS0L1tS9sXB2TCEOPHJ7kt9bN/niWkYj8T3RQSoMXdSQ=="
},
"datatables": {
"version": "1.10.18",
@@ -25,20 +30,62 @@
"jquery": ">=1.7"
}
},
+ "esm": {
+ "version": "3.2.25",
+ "resolved": "https://registry.npmjs.org/esm/-/esm-3.2.25.tgz",
+ "integrity": "sha512-U1suiZ2oDVWv4zPO56S0NcR5QriEahGtdN2OR6FiOG4WJvcjBVFB0qI4+eKoWFH483PKGuLuu6V8Z4T5g63UVA=="
+ },
"jquery": {
- "version": "3.3.1",
- "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.3.1.tgz",
- "integrity": "sha512-Ubldcmxp5np52/ENotGxlLe6aGMvmF4R8S6tZjsP6Knsaxd/xp3Zrh50cG93lR6nPXyUFwzN3ZSOQI0wRJNdGg=="
+ "version": "3.4.1",
+ "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.4.1.tgz",
+ "integrity": "sha512-36+AdBzCL+y6qjw5Tx7HgzeGCzC81MDDgaUP8ld2zhx58HdqXGoBd+tHdrBMiyjGQs0Hxs/MLZTu/eHNJJuWPw=="
},
"mathjax": {
- "version": "2.7.5",
- "resolved": "https://registry.npmjs.org/mathjax/-/mathjax-2.7.5.tgz",
- "integrity": "sha512-OzsJNitEHAJB3y4IIlPCAvS0yoXwYjlo2Y4kmm9KQzyIBZt2d8yKRalby3uTRNN4fZQiGL2iMXjpdP1u2Rq2DQ=="
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/mathjax/-/mathjax-3.0.0.tgz",
+ "integrity": "sha512-z4uLbDHNbs/aRuR6zCcnzwFQuMixkHCcWqgVaommfK/3cA1Ahq7OXemn+m8JwTYcBApSHgcrSbPr9sm3sZFL+A==",
+ "requires": {
+ "mathjax-full": "git://github.com/mathjax/MathJax-src.git"
+ }
+ },
+ "mathjax-full": {
+ "version": "git://github.com/mathjax/MathJax-src.git#0d74266e1820220d33cb6b29d4ca3575b352ac0d",
+ "from": "git://github.com/mathjax/MathJax-src.git",
+ "requires": {
+ "esm": "^3.2.25",
+ "mj-context-menu": "^0.2.0",
+ "speech-rule-engine": "^3.0.0-beta.6"
+ }
+ },
+ "mj-context-menu": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/mj-context-menu/-/mj-context-menu-0.2.0.tgz",
+ "integrity": "sha512-yJxrWBHCjFZEHsZgfs7m5g9OSCNzsVYadW6f6lX3pgZL67vmodtSW/4zhsYmuDKweXfHs0M1kJge1uQIasWA+g=="
},
"popper.js": {
"version": "1.15.0",
"resolved": "https://registry.npmjs.org/popper.js/-/popper.js-1.15.0.tgz",
"integrity": "sha512-w010cY1oCUmI+9KwwlWki+r5jxKfTFDVoadl7MSrIujHU5MJ5OR6HTDj6Xo8aoR/QsA56x8jKjA59qGH4ELtrA=="
+ },
+ "speech-rule-engine": {
+ "version": "3.0.0-beta.6",
+ "resolved": "https://registry.npmjs.org/speech-rule-engine/-/speech-rule-engine-3.0.0-beta.6.tgz",
+ "integrity": "sha512-B7gcT53jAsKpx7WvFYQcyUlFmgS3Wa9KlDy0FY8SOTa+Wz5EqmI0MpCD5/fYm8/2qiCPp8HwZg+H3cBgM+sNVw==",
+ "requires": {
+ "commander": "*",
+ "wicked-good-xpath": "*",
+ "xmldom-sre": "^0.1.31"
+ }
+ },
+ "wicked-good-xpath": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/wicked-good-xpath/-/wicked-good-xpath-1.3.0.tgz",
+ "integrity": "sha1-gbDpXoZQ5JyUsiKY//hoa1VTz2w="
+ },
+ "xmldom-sre": {
+ "version": "0.1.31",
+ "resolved": "https://registry.npmjs.org/xmldom-sre/-/xmldom-sre-0.1.31.tgz",
+ "integrity": "sha512-f9s+fUkX04BxQf+7mMWAp5zk61pciie+fFLC9hX9UVvCeJQfNHRHXpeo5MPcR0EUf57PYLdt+ZO4f3Ipk2oZUw=="
}
}
}
diff --git a/package.json b/package.json
index e41ecff..1f191e6 100644
--- a/package.json
+++ b/package.json
@@ -2,12 +2,12 @@
"description": "Javascript libraries required to run the server",
"email": "mjsb@uevora.pt",
"dependencies": {
- "@fortawesome/fontawesome-free": "^5.8.1",
- "bootstrap": "^4.3.1",
- "codemirror": "^5.45.0",
- "datatables": "^1.10.18",
- "jquery": "^3.3.1",
- "mathjax": "^2.7.5",
- "popper.js": "^1.15.0"
+ "@fortawesome/fontawesome-free": "^5.11.1",
+ "bootstrap": "^4.3",
+ "codemirror": "^5.48",
+ "datatables": "^1.10",
+ "jquery": "^3.4.1",
+ "mathjax": "^3",
+ "popper.js": "^1.15"
}
}
diff --git a/perguntations/__init__.py b/perguntations/__init__.py
index f38c675..bf956b7 100644
--- a/perguntations/__init__.py
+++ b/perguntations/__init__.py
@@ -32,7 +32,7 @@ proof of submission and for review.
'''
APP_NAME = 'perguntations'
-APP_VERSION = '2019.06.dev1'
+APP_VERSION = '2019.09.dev1'
APP_DESCRIPTION = __doc__
__author__ = 'Miguel Barão'
diff --git a/perguntations/serve.py b/perguntations/serve.py
index 60dff56..0d232b5 100644
--- a/perguntations/serve.py
+++ b/perguntations/serve.py
@@ -17,6 +17,7 @@ import ssl
# user installed libraries
import tornado.ioloop
import tornado.web
+# import tornado.websocket
import tornado.httpserver
# this project
@@ -27,19 +28,6 @@ from perguntations.parser_markdown import md_to_html
# ----------------------------------------------------------------------------
-# Decorator used to restrict access to the administrator
-# ----------------------------------------------------------------------------
-def admin_only(func):
- @functools.wraps(func)
- async def wrapper(self, *args, **kwargs):
- if self.current_user != '0':
- raise tornado.web.HTTPError(403) # forbidden
- else:
- await func(self, *args, **kwargs)
- return wrapper
-
-
-# ----------------------------------------------------------------------------
# Web Application. Routes to handler classes.
# ----------------------------------------------------------------------------
class WebApplication(tornado.web.Application):
@@ -51,7 +39,8 @@ class WebApplication(tornado.web.Application):
(r'/review', ReviewHandler),
(r'/admin', AdminHandler),
(r'/file', FileHandler),
- # (r'/ws', AdminWebSocketHandler),
+ # (r'/root', MainHandler), # FIXME
+ # (r'/ws', AdminSocketHandler),
(r'/', RootHandler), # TODO multiple tests
]
@@ -69,6 +58,19 @@ class WebApplication(tornado.web.Application):
# ----------------------------------------------------------------------------
+# Decorator used to restrict access to the administrator
+# ----------------------------------------------------------------------------
+def admin_only(func):
+ @functools.wraps(func)
+ async def wrapper(self, *args, **kwargs):
+ if self.current_user != '0':
+ raise tornado.web.HTTPError(403) # forbidden
+ else:
+ await func(self, *args, **kwargs)
+ return wrapper
+
+
+# ----------------------------------------------------------------------------
# Base handler. Other handlers will inherit this one.
# ----------------------------------------------------------------------------
class BaseHandler(tornado.web.RequestHandler):
@@ -83,6 +85,113 @@ class BaseHandler(tornado.web.RequestHandler):
# ----------------------------------------------------------------------------
+# class MainHandler(BaseHandler):
+
+# @tornado.web.authenticated
+# @admin_only
+# def get(self):
+# self.render("admin-ws.html", students=self.testapp.get_students_state())
+
+
+# # ----------------------------------------------------------------------------
+# class AdminSocketHandler(tornado.websocket.WebSocketHandler):
+# waiters = set()
+# # cache = []
+
+# # def get_compression_options(self):
+# # return {} # Non-None enables compression with default options.
+
+# # called when opening connection
+# def open(self):
+# logging.debug('[AdminSocketHandler.open]')
+# AdminSocketHandler.waiters.add(self)
+
+# # called when closing connection
+# def on_close(self):
+# logging.debug('[AdminSocketHandler.on_close]')
+# AdminSocketHandler.waiters.remove(self)
+
+# # @classmethod
+# # def update_cache(cls, chat):
+# # logging.debug(f'[AdminSocketHandler.update_cache] "{chat}"')
+# # cls.cache.append(chat)
+
+# # @classmethod
+# # def send_updates(cls, chat):
+# # logging.info("sending message to %d waiters", len(cls.waiters))
+# # for waiter in cls.waiters:
+# # try:
+# # waiter.write_message(chat)
+# # except Exception:
+# # logging.error("Error sending message", exc_info=True)
+
+# # handle incomming messages
+# def on_message(self, message):
+# logging.info(f"[AdminSocketHandler.onmessage] got message {message}")
+# parsed = tornado.escape.json_decode(message)
+# print(parsed)
+# chat = {"id": str(uuid.uuid4()), "body": parsed["body"]}
+# print(chat)
+# chat["html"] = tornado.escape.to_basestring(
+# '
- {{ md('**Solução:** ' + q['solution']) }}
+ {{ md('**Solução:** \n\n' + q['solution']) }}
{% end %}