From 86669872fb166cf4c41fd4b136c48244f726befa Mon Sep 17 00:00:00 2001 From: Timotej Lazar Date: Thu, 10 Sep 2015 22:38:58 +0200 Subject: Add Hint classes for normal and sequence hints --- server/hints.py | 29 +++++++++++++++++++++++++++++ server/prolog_session.py | 43 +++++++++++++++++++++++++++---------------- 2 files changed, 56 insertions(+), 16 deletions(-) create mode 100644 server/hints.py 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 -- cgit v1.2.1