summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTimotej Lazar <timotej.lazar@araneo.org>2015-09-10 22:38:58 +0200
committerTimotej Lazar <timotej.lazar@araneo.org>2015-09-10 22:38:58 +0200
commit86669872fb166cf4c41fd4b136c48244f726befa (patch)
treeeeeb26e433300978bc4f41d4f9d502d6bf013242
parent42f7fd57532c62e1de352061f4eb3386ab42ed3e (diff)
Add Hint classes for normal and sequence hints
-rw-r--r--server/hints.py29
-rw-r--r--server/prolog_session.py43
2 files changed, 56 insertions, 16 deletions
diff --git a/server/hints.py b/server/hints.py
new file mode 100644
index 0000000..c70c596
--- /dev/null
+++ b/server/hints.py
@@ -0,0 +1,29 @@
+# coding=utf-8
+
+import server.user_session
+
+# Hint.instantiate takes a hint object (dictionary) to be sent to the client
+# and sets additional fields based on previously sent hints.
+
+# Simple hint: don't do anything.
+class Hint(object):
+ def __init__(self, name):
+ self.name = name
+
+ def instantiate(self, hint, prev_hints):
+ pass
+
+# Hint sequence: each time this hint is sent, increase the message index until
+# the last message is reached, then repeat that.
+class HintSequence(Hint):
+ def __init__(self, name, length):
+ self.name = name
+ self.length = length
+
+ def instantiate(self, hint, prev_hints):
+ index = 0
+ for prev_hint in prev_hints:
+ if prev_hint['id'] == self.name:
+ index = max(index, prev_hint['indices'][0]+1)
+ index = min(index, self.length-1)
+ hint['indices'] = [index]
diff --git a/server/prolog_session.py b/server/prolog_session.py
index 8a7b635..3e48cbc 100644
--- a/server/prolog_session.py
+++ b/server/prolog_session.py
@@ -42,6 +42,7 @@ class PrologSession(object):
self._access_lock = threading.Lock()
self._engine_id = None
self._problem_id = -1
+ self._sent_hints = []
def run(self, code):
with self._access_lock:
@@ -92,28 +93,24 @@ class PrologSession(object):
def hint(self, sid, problem_id, program):
session = server.user_session.get_session_by_id(sid)
language, problem_group, problem = Problem.get_identifier(problem_id)
+ language_module = problems.load_language(language, 'common')
problem_module = problems.load_problem(language, problem_group, problem, 'common')
- # If compilation fails just return compiler messages.
- engine_id, output = prolog.engine.create(code=program)
- if engine_id is not None:
- prolog.engine.destroy(engine_id)
- if 'error' in map(operator.itemgetter(0), output):
- errors_msg = '\n'.join(['{}: {}'.format(m_type, m_text) for m_type, m_text in output])
- return [{'id': 'syntax_error', 'args': {'messages': errors_msg}}]
-
- # Otherwise try problem-specific hints.
- if hasattr(problem_module, 'hint'):
+ hints = []
+ if hasattr(language_module, 'hint'):
+ hints = language_module.hint(program)
+ if not hints and hasattr(problem_module, 'hint'):
hints = problem_module.hint(session, program)
- if hints:
- return hints
+ if not hints:
+ hints = [{'id': 'no_hint'}]
- # Finally return a generic "try thinking a bit" message.
- return [{'id': 'no_hint'}]
+ self._instantiate_and_save_hints(language_module, problem_module, hints)
+ return hints
def test(self, sid, problem_id, program):
session = server.user_session.get_session_by_id(sid)
language, problem_group, problem = Problem.get_identifier(problem_id)
+ language_module = problems.load_language(language, 'common')
problem_module = problems.load_problem(language, problem_group, problem, 'common')
solved_problems = [p for p in CodeqUser.solved_problems(session.get_uid(), language)
@@ -123,9 +120,23 @@ class PrologSession(object):
try:
n_correct, n_all = problem_module.test(session, code)
- return [{'id': 'test_results', 'args': {'passed': n_correct, 'total': n_all}}]
+ hints = [{'id': 'test_results', 'args': {'passed': n_correct, 'total': n_all}}]
except AttributeError as ex:
- return [{'id': 'test_results', 'args': {'passed': 0, 'total': 0}}]
+ hints = [{'id': 'test_results', 'args': {'passed': 0, 'total': 0}}]
+
+ self._instantiate_and_save_hints(language_module, problem_module, hints)
+ return hints
+
+ # Add hint parameters (such as message index) based on hint class. Append
+ # the finalized hints to the list of sent hints.
+ def _instantiate_and_save_hints(self, language_mod, problem_mod, hints):
+ with self._access_lock:
+ for hint in hints:
+ for mod in [language_mod, problem_mod]:
+ if hasattr(mod, 'hint_defs') and hint['id'] in mod.hint_defs:
+ hint_def = mod.hint_defs[hint['id']]
+ hint_def.instantiate(hint, self._sent_hints)
+ self._sent_hints.extend(hints)
def run_for_user(self, user_id, problem_id, program, query):
"""A "shorthand" method to start a Prolog session, load correct solutions of all user's solved