summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--scripts/build_web_resources.py71
-rw-r--r--server/prolog_session.py22
-rw-r--r--server/python_session.py18
-rw-r--r--server/robot_session.py21
4 files changed, 83 insertions, 49 deletions
diff --git a/scripts/build_web_resources.py b/scripts/build_web_resources.py
index 919ccc1..643920e 100644
--- a/scripts/build_web_resources.py
+++ b/scripts/build_web_resources.py
@@ -80,9 +80,6 @@ problem_common_props = { # for common.py inside the problem subdirectory
'hint_type': {}, # type definitions of problem hints
}
-languages = {} # programming languages, info from database
-groups = {} # problem groups, info from database
-
if not os.path.exists(output_path):
os.mkdir(output_path)
@@ -96,11 +93,11 @@ def load_translation_data(package, defaults):
try:
mod = server.problems.load_module(package + '.' + lang)
except:
- traceback.print_exc()
+ traceback.print_exc(limit=0)
lang_data = {}
result[lang] = lang_data
if mod is None:
- print('Could not load module {}'.format(package + '.' + lang))
+ print('Could not load translation module {}'.format(package + '.' + lang))
for prop, default in defaults.items():
lang_data[prop] = default
else:
@@ -109,26 +106,21 @@ def load_translation_data(package, defaults):
return result
def load_common_data(package, defaults):
- result = {}
+ mod = None
path = os.sep.join(package.split('.'))
mod_path = os.path.join(problems_path, path, 'common.py')
if os.path.exists(mod_path) and os.path.isfile(mod_path):
- mod = None
try:
mod = server.problems.load_module(package + '.common')
except:
- traceback.print_exc()
- if mod is None:
- print('Could not load module {}'.format(package + '.common'))
- for prop, default in defaults.items():
- result[prop] = default
- else:
- for prop, default in defaults.items():
- result[prop] = getattr(mod, prop, default)
- else:
- print('Module {} does not exist'.format(package + '.common'))
- for prop, default in defaults.items():
- result[prop] = default
+ print('Error loading module {}:'.format(mod_path))
+ traceback.print_exc(limit=0)
+ if mod is None:
+ return None
+
+ result = {}
+ for prop, default in defaults.items():
+ result[prop] = getattr(mod, prop, default)
return result
def process_hint_type(hint_type):
@@ -157,15 +149,14 @@ def copy_web_resources(package, dst_dir_fragments):
node[filename] = True
def dump_language_defs(data, output_path):
- if data:
- # sort groups and problems
- groups = data['groups']
- for group in groups:
- group['problems'].sort(key=lambda p: p.get('number', 0))
- groups.sort(key=lambda p: p.get('number', 0))
- # write out the JSON file
- with open(os.path.join(output_path, 'language.json'), 'w') as f:
- json.dump(data, f, indent=2)
+ # sort groups and problems
+ groups = data['groups']
+ for group in groups:
+ group['problems'].sort(key=lambda p: p.get('number', 0))
+ groups.sort(key=lambda p: p.get('number', 0))
+ # write out the JSON file
+ with open(os.path.join(output_path, 'language.json'), 'w') as f:
+ json.dump(data, f, indent=2)
conn = db.get_connection()
cur = conn.cursor()
@@ -191,9 +182,8 @@ def db_add(table, id, data):
try:
# get problem descriptors
for lang_identifier in os.listdir(problems_path):
- lang_path = os.path.join(problems_path, lang_identifier)
- if (not os.path.exists(os.path.join(lang_path, 'common.py')) or
- not os.path.exists(os.path.join(lang_path, 'problems'))):
+ lang_data = load_common_data(lang_identifier, language_common_props)
+ if lang_data is None:
continue
# create language output directory
@@ -201,7 +191,6 @@ try:
if not os.path.exists(lang_output_path):
os.mkdir(lang_output_path)
- lang_data = load_common_data(lang_identifier, language_common_props)
lang_data['hint_type'] = process_hint_type(lang_data.get('hint_type', {}))
lang_data['identifier'] = lang_identifier
lang_data['groups'] = []
@@ -210,10 +199,11 @@ try:
db_add('language', lang_data['id'],
{'id': lang_data['id'], 'identifier': lang_identifier})
- groups_path = os.path.join(lang_path, 'problems')
+ groups_path = os.path.join(problems_path, lang_identifier, 'problems')
for group_identifier in os.listdir(groups_path):
- group_path = os.path.join(groups_path, group_identifier)
- if not os.path.exists(os.path.join(group_path, 'common.py')):
+ group_package = lang_identifier + '.problems.' + group_identifier
+ group_data = load_common_data(group_package, group_common_props)
+ if group_data is None:
continue
# create group directory
@@ -221,23 +211,20 @@ try:
if not os.path.exists(group_output_path):
os.mkdir(group_output_path)
- group_package = lang_identifier + '.problems.' + group_identifier
- group_data = load_common_data(group_package, group_common_props)
group_data['identifier'] = group_identifier
group_data['problems'] = []
group_data['translations'] = load_translation_data(group_package, group_props)
db_add('problem_group', group_data['id'],
{'id': group_data['id'], 'identifier': group_identifier})
+ group_path = os.path.join(groups_path, group_identifier)
for problem_identifier in os.listdir(group_path):
- problem_path = os.path.join(group_path, problem_identifier)
- if not os.path.exists(os.path.join(problem_path, 'common.py')):
- continue
-
problem_package = group_package + '.' + problem_identifier
common_data = load_common_data(problem_package, problem_common_props)
- common_data['identifier'] = problem_identifier
+ if common_data is None:
+ continue
+ common_data['identifier'] = problem_identifier
if not common_data['visible']:
continue # problem is not visible, do not generate anything
del common_data['visible'] # we don't need this field in the GUI
diff --git a/server/prolog_session.py b/server/prolog_session.py
index ac18400..6cf6651 100644
--- a/server/prolog_session.py
+++ b/server/prolog_session.py
@@ -121,17 +121,32 @@ class PrologSession(server.LanguageSession):
problem_module = load_problem(problem.language, problem.group, problem.identifier, 'common')
aux_code = self._aux_code(session.get_uid(), problem, program)
+ # experiment support for allowing none/automatic/manual/all hints
+ # descriptor: {'id': 'hints', 'group': 'none|automatic|manual|all'}
+ allowed_hints = 'all'
+ for experiment in session.get_experiments():
+ if experiment.get('id') == 'hints':
+ allowed_hints = experiment.get('group')
+ break
+
# check if the program is correct
n_correct, n_all, msgs = problem_module.test(program, aux_code=aux_code)
if n_correct == n_all:
session.update_solution(problem_id, solution=program, done=True)
else:
hints = []
+ # syntax check
if not hints and hasattr(language_module, 'check_syntax'):
hints = language_module.check_syntax(program, aux_code=aux_code)
- if not hints and hasattr(problem_module, 'hint'):
+
+ # manually defined problem-specific hints
+ if not hints and hasattr(problem_module, 'hint') and \
+ allowed_hints in ('all', 'manual'):
hints = problem_module.hint(program, aux_code=aux_code)
- if not hints and problem_id in _edits:
+
+ # automatic hints
+ if not hints and problem_id in _edits and \
+ allowed_hints in ('all', 'automatic'):
# Testing function for monkey.
def tester(code):
n_correct, n_all, _ = problem_module.test(code, aux_code=aux_code)
@@ -140,8 +155,11 @@ class PrologSession(server.LanguageSession):
program, _edits[problem_id], tester, timeout=3)
if solution and steps:
hints = [{'id': 'monkey_main'}] + monkey.fix_hints(program, steps)
+
+ # generic language hints (style etc.)
if not hints and hasattr(language_module, 'hint'):
hints = language_module.hint(program, aux_code=aux_code)
+
if hints:
msgs.extend(hints)
diff --git a/server/python_session.py b/server/python_session.py
index 52a54de..ecb075a 100644
--- a/server/python_session.py
+++ b/server/python_session.py
@@ -102,21 +102,35 @@ class PythonSession(server.LanguageSession):
return []
def test(self, sid, problem_id, program):
+ session = server.user_session.get_session_by_id(sid)
p = Problem.get(id=problem_id)
+
language_module = server.problems.load_language(p.language, 'common')
problem_module = server.problems.load_problem(p.language, p.group, p.identifier, 'common')
+ # experiment support for allowing none/automatic/manual/all hints
+ # descriptor: {'id': 'hints', 'group': 'none|automatic|manual|all'}
+ allowed_hints = 'all'
+ for experiment in session.get_experiments():
+ if experiment.get('id') == 'hints':
+ allowed_hints = experiment.get('group')
+ break
+
# check if the program is correct
passed, msgs = problem_module.test(self.run, program)
if passed:
- session = server.user_session.get_session_by_id(sid)
session.update_solution(problem_id, solution=program, done=True)
else:
hints = []
+ # manually defined problem-specific hints
if not hints and hasattr(language_module, 'hint'):
hints = language_module.hint(self.run, program)
- if not hints and hasattr(problem_module, 'hint'):
+
+ # generic language hints (style etc.)
+ if not hints and hasattr(problem_module, 'hint') and \
+ allowed_hints in ('all', 'manual'):
hints = problem_module.hint(self.run, program)
+
if hints:
msgs.extend(hints)
diff --git a/server/robot_session.py b/server/robot_session.py
index 649159a..5477c72 100644
--- a/server/robot_session.py
+++ b/server/robot_session.py
@@ -40,15 +40,30 @@ class RobotSession(server.LanguageSession):
pass
def hint(self, sid, problem_id, program):
+ session = server.user_session.get_session_by_id(sid)
p = Problem.get(id=problem_id)
+
language_module = server.problems.load_language(p.language, 'common')
problem_module = server.problems.load_problem(p.language, p.group, p.identifier, 'common')
+ # experiment support for allowing none/automatic/manual/all hints
+ # descriptor: {'id': 'hints', 'group': 'none|automatic|manual|all'}
+ allowed_hints = 'all'
+ for experiment in session.get_experiments():
+ if experiment.get('id') == 'hints':
+ allowed_hints = experiment.get('group')
+ break
+
hints = []
- if hasattr(language_module, 'hint'):
- hints = language_module.hint(program)
- if not hints and hasattr(problem_module, 'hint'):
+ # manually defined problem-specific hints
+ if not hints and hasattr(problem_module, 'hint') and \
+ allowed_hints in ('all', 'manual'):
hints = problem_module.hint(program)
+
+ # generic language hints (style etc.)
+ if not hints and hasattr(language_module, 'hint'):
+ hints = language_module.hint(program)
+
if not hints:
hints = [{'id': 'no_hint'}]