diff options
Diffstat (limited to 'server')
-rw-r--r-- | server/__init__.py | 3 | ||||
-rw-r--r-- | server/handlers.py | 4 | ||||
-rw-r--r-- | server/robot_session.py | 65 | ||||
-rw-r--r-- | server/user_session.py | 14 |
4 files changed, 85 insertions, 1 deletions
diff --git a/server/__init__.py b/server/__init__.py index 0007e0a..526c6f9 100644 --- a/server/__init__.py +++ b/server/__init__.py @@ -3,7 +3,8 @@ from . import user_session from . import prolog_session from . import python_session +from . import robot_session from . import socket import server.problems -__all__ = ['socket', 'handlers', 'user_session', 'prolog_session', 'python_session', 'problems', 'start'] +__all__ = ['socket', 'handlers', 'user_session', 'prolog_session', 'python_session', 'robot_session', 'problems', 'start'] diff --git a/server/handlers.py b/server/handlers.py index 90b8e0b..6720cae 100644 --- a/server/handlers.py +++ b/server/handlers.py @@ -174,6 +174,8 @@ class Hint(CodeqService): lang_session = session.get_prolog() elif language == 'python': lang_session = session.get_python() + elif language == 'robot': + lang_session = session.get_robot() if lang_session is None: request.reply({'code': 3, 'message': 'Unknown language specified'}) @@ -200,6 +202,8 @@ class Test(CodeqService): lang_session = session.get_prolog() elif language == 'python': lang_session = session.get_python() + elif language == 'robot': + lang_session = session.get_robot() if lang_session is None: request.reply({'code': 3, 'message': 'Unknown language specified'}) diff --git a/server/robot_session.py b/server/robot_session.py new file mode 100644 index 0000000..e941641 --- /dev/null +++ b/server/robot_session.py @@ -0,0 +1,65 @@ +# coding=utf-8 + +import threading + +from db.models import Problem +from . import problems + +__all__ = ['RobotSession'] + +class RobotSession(object): + """Abstracts a Robot session. + Only public methods are available to the outside world due to the use of multiprocessing managers. + Therefore prefix any private methods with an underscore (_). + No properties are accessible; use getters and setters instead. + Values are passed by value instead of by reference (deep copy!). + """ + def __init__(self, output_cb=None): + self._access_lock = threading.Lock() + self._sent_hints = [] + + def destroy(self): + pass + + def __del__(self): + pass + + def hint(self, sid, problem_id, program): + 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') + + hints = [] + if hasattr(language_module, 'hint'): + hints = language_module.hint(program) + if not hints and hasattr(problem_module, 'hint'): + hints = problem_module.hint(program) + if not hints: + hints = [{'id': 'no_hint'}] + + self._instantiate_and_save_hints(language_module, problem_module, hints) + return hints + + def test(self, sid, problem_id, program): + 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') + + try: + passed, hints = problem_module.test(program) + except AttributeError as ex: + hints = [{'id': 'system_error', 'args': {'message': 'test function does not exist'}}] + + 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_type') and hint['id'] in mod.hint_type: + hint_type = mod.hint_type[hint['id']] + hint_type.instantiate(hint, self._sent_hints) + self._sent_hints.extend(hints) diff --git a/server/user_session.py b/server/user_session.py index 0fa7433..f53ae57 100644 --- a/server/user_session.py +++ b/server/user_session.py @@ -7,6 +7,7 @@ import base64 import random from . import prolog_session from . import python_session +from . import robot_session from . import problems from . import handlers import db @@ -33,6 +34,7 @@ class UserSession(object): self.username = username self.prolog_session = None self.python_session = None + self.robot_session = None self.settings = settings def destroy(self): @@ -46,6 +48,9 @@ class UserSession(object): if self.python_session is not None: self.python_session.destroy() self.python_session = None + if self.robot_session is not None: + self.robot_session.destroy() + self.robot_session = None # TODO: add any cleanups as features are added! def get_sid(self): @@ -86,6 +91,12 @@ class UserSession(object): output_cb=lambda text: self.send({'event': 'terminal_output', 'text': text})) return self.python_session + def get_robot(self): + with self._access_lock: + if self.robot_session is None: + self.robot_session = robot_session.RobotSession() + return self.robot_session + def get_problem_data(self, language, problem_group, problem): mod = problems.load_problem(language, problem_group, problem, 'sl') mod_language = problems.load_language(language, 'sl') @@ -170,6 +181,9 @@ class UserSession(object): if hasattr(self, 'python_session') and (self.python_session is not None): self.python_session.destroy() self.python_session = None + if hasattr(self, 'robot_session') and (self.python_session is not None): + self.robot_session.destroy() + self.robot_session = None # TODO: add any cleanups as features are added! def get_session_by_id(sid): |