summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--server/__init__.py3
-rw-r--r--server/handlers.py4
-rw-r--r--server/robot_session.py65
-rw-r--r--server/user_session.py14
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):