summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--css/codeq.css26
-rw-r--r--index.html95
-rw-r--r--js/codeq/hint.js68
-rw-r--r--js/codeq/login.js4
-rw-r--r--js/codeq/problem.js70
-rw-r--r--js/codeq/prolog.js8
-rw-r--r--js/codeq/python.js8
7 files changed, 184 insertions, 95 deletions
diff --git a/css/codeq.css b/css/codeq.css
index 0e4c689..3a9195f 100644
--- a/css/codeq.css
+++ b/css/codeq.css
@@ -44,6 +44,32 @@ body {
border-top-right-radius: 0;
}
+/* modalLogIn */
+
+#modalLogIn{
+ min-width: 250px;
+ padding: 14px 14px 0;
+ overflow:hidden;
+ background-color:rgba(255,255,255,.8);
+}
+#modalLogIn .help-block{
+ font-size:12px
+}
+#modalLogIn .bottom{
+ background-color:rgba(255,255,255,.8);
+ border-top:1px solid #ddd;
+ clear:both;
+ padding:14px;
+}
+#modalLogIn .ssa-buttons{
+ margin-bottom: 1em;
+}
+
+#modalLogIn .form-group {
+ margin-bottom: 10px;
+}
+
+
/* screen language */
#screen_language {
diff --git a/index.html b/index.html
index 7defa80..24a4836 100644
--- a/index.html
+++ b/index.html
@@ -42,7 +42,7 @@
<li style="display: none;" id="navigation-prolog"><a href="">Prolog</a></li>
</ul>
<ul class="nav navbar-nav navbar-right">
- <p class="navbar-text" id="signed-in-title">Signed in as Franc Jožef</p>
+ <p class="navbar-text" id="signed-in-title"></p>
<li class="dropdown lang-selection">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" aria-expanded="true">
<span class="lang-choice"></span>
@@ -112,7 +112,7 @@
</div>
<!-- login screen -->
- <div class="container" id="screen_login">
+ <!--div class="container" id="screen_login">
<form class="form-signin">
<h2 class="form-signin-heading">Please login</h2>
<div class="form-group">
@@ -123,10 +123,10 @@
<button class="btn btn-lg btn-default btn-block" type="button" id="submit">Login</button>
</div>
<div class="form-group">
- <a href="" data-dismiss="modal" data-toggle="modal" role="button" data-target="#modalSignIn">New User? Sign-in..</a>
+ <a href="" data-dismiss="modal" data-toggle="modal" role="button" data-target="#modalSignUp">New User? Sign-up..</a>
</div>
</form>
- </div>
+ </div-->
<!-- main screen: programming language selection, settings, etc. -->
@@ -297,63 +297,106 @@
</div><!--container-->
<!-- Modals -->
- <div id="modalSignIn" class="modal fade in" tabindex="-1" role="dialog" aria-hidden="false" style="display: none;">
- <div class="modal-dialog">
+
+ <div id="modalLogIn" class="modal fade in" tabindex="-1" role="dialog" aria-hidden="false" data-keyboard="false" data-backdrop="static" style="display: none;">
+ <div class="modal-dialog modal-sm">
+ <div class="modal-content">
+ <div class="modal-header">
+ <h3 class="text-center">Please sign in</h3>
+ </div>
+ <div class="modal-body">
+ <div class="row">
+ <div class="col-md-12">
+ Login via
+ <div class="ssa-buttons">
+ <img src="res/gumb_aaiprijava.png" style="width: 49%">
+ </div>
+ or
+ <form class="form" role="form" method="post" action="login" accept-charset="UTF-8" id="login-nav">
+ <div class="form-group">
+ <label class="sr-only" for="username">Username</label>
+ <input type="text" class="form-control" id="username" placeholder="Username" required>
+ </div>
+ <div class="form-group">
+ <label class="sr-only" for="password">Password</label>
+ <input type="password" class="form-control" id="password" placeholder="Password" required>
+ <div class="help-block text-right"><a href="#">Forgot the password?</a></div>
+ </div>
+ <div class="form-group">
+ <button class="btn btn-primary btn-block" data-dismiss="modal" type="button" id="submit">Sign in</button>
+ </div>
+ <div class="checkbox">
+ <label>
+ <input type="checkbox"> keep me logged-in
+ </label>
+ </div>
+ </form>
+ </div>
+ </div>
+ </div><!--/modal-body-->
+ <div class="modal-footer">
+ <div class="text-center">
+ New here ? <a href="#" data-dismiss="modal" data-toggle="modal" role="button" data-target="#modalSignUp"><b>Sign Up</b></a>
+ </div>
+ </div><!--/modal-footer-->
+ </div>
+ </div>
+ </div>
+
+
+ <div id="modalSignUp" class="modal fade in" tabindex="-1" role="dialog" aria-hidden="false" style="display: none;">
+ <div class="modal-dialog modal-sm">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
- <h2 class="text-center">Sign-in</h2>
+ <h3 class="text-center">Sign up</h3>
</div>
<div class="modal-body">
<form class="form" method="post">
- <div class="form-group">
- <label class="control-label">Email</label>
- <input class="form-control" name="email" id="inputEmail" type="email" data-ng-model="newuser.email" placeholder="email@you.com (kept private)" required="">
- </div>
<div class="form-group" bs-has-error="">
- <label class="control-label">Username</label>
- <input class="form-control" name="username" id="inputUsername" type="text" data-ng-model="newuser.username" placeholder="desired username" pattern="^[a-z,A-Z,0-9,_]{5,15}$" data-valid-min="5" title="Choose a alpha-numeric username of 5-15 characters" required="">
+ <label class="control-label small">Username</label>
+ <input class="form-control" name="username" id="modalSignUpUsername" type="text" placeholder="desired username" pattern="^[a-z,A-Z,0-9,_]{5,15}$" data-valid-min="5" title="Choose a alpha-numeric username of 5-15 characters" required="">
</div>
<div class="form-group">
- <label class="control-label">Password</label>
- <input class="form-control" name="password" id="inputpassword" type="password" data-ng-model="newuser.password" placeholder="password" pattern="^[a-z,A-Z,0-9,_]{6,15}$" data-valid-min="6" title="Choose a alpha-numeric password of a least 6 characters" required="">
+ <label class="control-label small">Password</label>
+ <input class="form-control" name="password" id="modalSignUpPassword" type="password" placeholder="password" pattern="^[a-z,A-Z,0-9,_]{6,15}$" data-valid-min="6" title="Choose a alpha-numeric password of a least 6 characters" required="">
</div>
<div class="form-group">
- <label class="control-label">Verify (repeat password)</label>
- <input class="form-control" name="verify" id="inputVerify" type="password" data-ng-model="newuser.verify" placeholder="password (again)" pattern="^[a-z,A-Z,0-9,_]{6,15}$" data-valid-min="6" title="Choose a alpha-numeric password of a least 6 characters" required="">
+ <label class="control-label small">Verify (repeat password)</label>
+ <input class="form-control" name="verify" id="modalSignUpVerify" type="password" placeholder="password (again)" pattern="^[a-z,A-Z,0-9,_]{6,15}$" data-valid-min="6" title="Choose a alpha-numeric password of a least 6 characters" required="">
</div>
</form><!--/row-->
</div><!--/modal-body-->
<div class="modal-footer">
- <button class="btn btn-default" data-dismiss="modal" aria-hidden="true">Cancel</button>
- <button class="btn btn-lg btn-primary" id="btnRegister" type="submit">Sign</button>
+ <button class="btn btn-default" data-dismiss="modal" aria-hidden="true" data-toggle="modal" data-target="#modalLogIn">Cancel</button>
+ <button class="btn btn-primary" data-dismiss="modal" data-toggle="modal" data-target="#modalLogIn" id="btnSignUp" type="submit">Sign up</button>
</div><!--/modal-footer-->
</div>
</div>
</div>
<div id="modalChangePassword" class="modal fade in" tabindex="-1" role="dialog" aria-hidden="false" style="display: none;">
- <div class="modal-dialog">
+ <div class="modal-dialog modal-sm">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
- <h2 class="text-center">Password Change</h2>
+ <h3 class="text-center">Change password </h3>
</div>
<div class="modal-body">
<form class="form" method="post">
<div class="form-group">
- <label>New Password</label>
- <input class="form-control input-lg" placeholder="Enter a new password" name="new" type="password">
+ <label class="control-label small">New Password</label>
+ <input class="form-control" placeholder="Enter a new password" name="new" type="password">
</div>
<div class="form-group">
- <label>Verify Password</label>
- <input class="form-control input-lg" placeholder="Repeat the password again" name="verify" type="password">
+ <label class="control-label small">Verify Password</label>
+ <input class="form-control" placeholder="Repeat the password again" name="verify" type="password">
</div>
</form><!--/row-->
</div><!--/modal-body-->
<div class="modal-footer">
<button class="btn btn-default" data-dismiss="modal" aria-hidden="true">Cancel</button>
- <button class="btn btn-lg btn-primary" id="btnPasswdChange" type="submit">Change</button>
+ <button class="btn btn-primary" id="btnPasswdChange" type="submit">Change</button>
</div><!--/modal-footer-->
</div>
</div>
diff --git a/js/codeq/hint.js b/js/codeq/hint.js
index 1b97afc..d30f934 100644
--- a/js/codeq/hint.js
+++ b/js/codeq/hint.js
@@ -7,7 +7,7 @@
var firstCharacterPos = {'line': 0, 'ch': 0},
sel_no_scroll = {'scroll': false};
- codeq.makeHinter = function (jqHints, jqEditor, editor, trNamespace, hintDefsA, commonHintDefsA, planDef) {
+ codeq.makeHinter = function (jqHints, jqEditor, editor, trNamespace, problemDef, commonDef) {
var hintCounter = 0, // for generating unique class-names
hintCleaners = [],
planIdx = 0,
@@ -133,25 +133,15 @@
codeq.tr.registerDictionary(trNamespace, dictionary);
- // TODO: below is a temporary code to bridge the old implementation with the new data format
- if (planDef.sl) planDef = planDef.sl;
- else planDef = planDef.en || [];
- var hintDefs = {}, t1, t2, k;
- if (hintDefsA.sl) t1 = hintDefsA.sl;
- else t1 = hintDefsA.en || {};
- if (commonHintDefsA.sl) t2 = commonHintDefsA.sl;
- else t2 = commonHintDefsA.en || {};
- for (k in t2) {
- if (!t2.hasOwnProperty(k)) continue;
- hintDefs[k] = t2[k];
- }
- for (k in t1) {
- if (!t1.hasOwnProperty(k)) continue;
- hintDefs[k] = t1[k];
- }
+ var hintProblemDefs = problemDef.hint_type,
+ hintCommonDefs = commonDef.hint_type,
+ hintProblemTr = problemDef.hint,
+ hintCommonTr = commonDef.hint,
+ planDef = problemDef.plan.sl;
return {
- /** Display the next "planning" hint and return whether there are
+ /**
+ * Display the next "planning" hint and return whether there are
* any more available.
*/
'planNext': function () {
@@ -170,46 +160,50 @@
*/
'handle': function (serverHints) {
var n = serverHints.length,
- /** number */ i,
- /** ServerHint */ serverHint,
- /** HintDefinition */ hintDef,
- hintType, hintTemplate, t, fn, indices;
+ i, serverHint, hintId, hintDef, hintContent, hintType, hintTemplate, t, fn, indices;
clearHints();
mainLoop:
for (i = 0; i < n; i++) {
serverHint = serverHints[i];
- hintDef = hintDefs[serverHint.id];
+ hintId = serverHint.id;
+ hintDef = hintProblemDefs[hintId];
+ if (hintDef) {
+ hintContent = hintProblemTr[hintId];
+ }
+ else {
+ hintDef = hintCommonDefs[hintId];
+ hintContent = hintCommonTr[hintId];
+ }
if (!hintDef) {
- codeq.log.error('Undefined hint ' + serverHint.id);
+ codeq.log.error('Undefined hint: ' + hintId);
+ continue;
+ }
+ if (!hintContent) {
+ codeq.log.error('Hint without content: ' + hintId);
continue;
}
if (serverHint.indices) {
indices = serverHint.indices;
for (i = 0; i < indices.length; i++) {
- hintDef = hintDef[indices[i]];
- if (!hintDef) {
- codeq.log.error('Undefined hint ' + serverHint.id + ' with indices ' + serverHint.indices);
+ hintContent = hintContent[indices[i]];
+ if (!hintContent) {
+ codeq.log.error('Cannot reference hint ' + hintId + ' with indices ' + serverHint.indices);
continue mainLoop;
}
}
}
+
t = typeof hintDef;
- if ((t === 'string') || (hintDef instanceof Array)) {
- hintType = 'static';
- hintTemplate = hintDef;
- }
- else if (t === 'object') {
- hintType = hintDef.type;
- hintTemplate = hintDef.message;
- }
+ if (t === 'string') hintType = hintDef;
+ else if ((t === 'object') && (hintDef !== null)) hintType = hintDef.type;
else {
- codeq.log.error('Unsupported hint definition: ' + t);
+ codeq.log.error('Cannot determine type of hint ' + hintId + ' from: ' + hintDef);
continue;
}
fn = typeHandlers[hintType];
if (!fn) codeq.log.error('Unsupported hint type: ' + hintType);
- else fn(hintType, hintTemplate, serverHint);
+ else fn(hintType, hintContent.sl, serverHint);
}
},
diff --git a/js/codeq/login.js b/js/codeq/login.js
index e3204d3..e5a446b 100644
--- a/js/codeq/login.js
+++ b/js/codeq/login.js
@@ -36,8 +36,9 @@
};
codeq.globalStateMachine.register('login',{
'enter': function(){
+ $('#signed-in-title').html('');
$("#submit").on('click', loginFun);
- //$('#modalLogin').modal();
+ $('#modalLogIn').modal();
$("#screen_login").css('display', '');
$('#disabled').css('display', 'none');
@@ -45,6 +46,7 @@
'exit' : function(){
$("#submit").off('click', loginFun);
$("#screen_login").css('display', 'none');
+ $('#signed-in-title').html('Signed in as '+$('#username').val());
$("#password").val('');
}
});
diff --git a/js/codeq/problem.js b/js/codeq/problem.js
index 7ae54d8..d07e5fa 100644
--- a/js/codeq/problem.js
+++ b/js/codeq/problem.js
@@ -10,13 +10,23 @@
// processed form, hint key -> translation language -> value
// ================================================================================
+ defaultHintCondition = function (translation) {
+ // must contain at least one translation
+ var key;
+ if (!translation || typeof translation !== 'object') return false;
+ for (key in translation) {
+ if (!translation.hasOwnProperty(key)) continue;
+ return true;
+ }
+ return false;
+ },
processHints = function (rawTranslations) {
var defaultHint = {}, // here we put all the hints with their default translations
allHints = {}, // the result
allHintKeys = [],
tr, key, i, lang, hint, h, j;
// find the default hint translations, they will form the basis of default hints
- tr = chooseDefaultTranslation(rawTranslations, 'hint') || {};
+ tr = chooseDefaultTranslation(rawTranslations, 'hint', defaultHintCondition) || {};
for (key in tr) { // copy the hints
if (!tr.hasOwnProperty(key)) continue;
defaultHint[key] = tr[key];
@@ -26,7 +36,7 @@
for (i = langs.length - 1; i >= 0; i--) {
lang = langs[i];
tr = rawTranslations[lang];
- if (!tr || !tr.hint) continue; // skip unavailable translations or translations with no hints
+ if (!tr || !defaultHintCondition(tr.hint)) continue; // skip unavailable translations or translations with no hints
hint = tr.hint;
for (key in hint) {
if (!hint.hasOwnProperty(key) || !hint[key]) continue;
@@ -37,22 +47,26 @@
}
}
// create all translations for hints
+ for (i = allHintKeys.length - 1; i >= 0; i--) {
+ allHints[allHintKeys[i]] = {}; // create keys with no translations, we'll fill them in the next loop
+ }
for (i = langs.length - 1; i >= 0; i--) {
lang = langs[i];
tr = rawTranslations[lang];
// set up hints
- if (!tr || !tr.hint) {
+ if (!tr || !defaultHintCondition(tr.hint)) {
// there's no hint in the current language, copy the default in its entirety
- allHints[lang] = defaultHint;
+ for (j = allHintKeys.length - 1; j >= 0; j--) {
+ key = allHintKeys[j];
+ allHints[key][lang] = defaultHint[key];
+ }
}
else {
// make a copy of all hints, using the default hint value where a hint value is missing
- hint = {};
- allHints[lang] = hint;
h = tr.hint;
- for (j = allHintKeys.length; j >= 0; j--) {
+ for (j = allHintKeys.length - 1; j >= 0; j--) {
key = allHintKeys[j];
- hint[key] = h[key] || defaultHint[key];
+ allHints[key][lang] = h[key] || defaultHint[key];
}
}
}
@@ -64,9 +78,14 @@
// processed form, hint key -> translation language -> value
// ================================================================================
+ defaultPlanCondition = function (translation) {
+ // default plan must be non-empty
+ if (!translation || !(translation instanceof Array)) return false;
+ return translation.length > 0;
+ },
processPlans = function (rawTranslations) {
// find the default plan translation
- var defaultPlan = chooseDefaultTranslation(rawTranslations, 'plan') || [],
+ var defaultPlan = chooseDefaultTranslation(rawTranslations, 'plan', defaultPlanCondition) || [],
allPlans = {}, // the result
i, lang, tr;
// create all translations for plan
@@ -74,12 +93,12 @@
lang = langs[i];
tr = rawTranslations[lang];
// set up plan
- if (!tr || !tr.plan) {
- // there's no plan in the current language, copy the default plan
- allPlans[lang] = defaultPlan;
+ if (tr && defaultPlanCondition(tr.plan)) {
+ allPlans[lang] = tr.plan;
}
else {
- allPlans[lang] = tr.plan;
+ // there's no plan in the current language, copy the default plan
+ allPlans[lang] = defaultPlan;
}
}
return allPlans;
@@ -111,7 +130,7 @@
/**
* convert the input translations (arg0) for given keys (arg1..argN)
- * so each keys holds all its translations for ever language
+ * so each keys holds all its translations for every language
*/
convertTranslations = function () {
var translations = arguments[0] || {},
@@ -187,7 +206,10 @@
'language': languageIdentifier, // 'prolog', 'python', ...
'html': html.join(''), // the DOM structure (without textual content), as HTML text
'refs': problemReferences, // array of problem info {g: group, p: problem, id: problem_id}, referenced from DOM <a> elements
- 'hints': processHints(rawTranslations) // hint translations: keyword -> lang -> value
+ 'commonDef': {
+ 'hint': processHints(rawTranslations), // hint translations: keyword -> lang -> value
+ 'hint_type': data.hint_type || {}
+ }
};
},
@@ -218,7 +240,7 @@
.spread(function (userProblemData, generalProblemData) {
if (userProblemData.code !== 0) throw new Error('Failed to obtain user problem data, code: ' + userProblemData.code + ', message: ' + userProblemData.message);
if (!generalProblemData) throw new Error('General problem data is not defined');
- codeq.globalStateMachine.transition(language, generalProblemData, data.hints, userProblemData.solution);
+ codeq.globalStateMachine.transition(language, generalProblemData, data.commonDef, userProblemData.solution);
})
)
.fail(function (reason) {
@@ -233,14 +255,15 @@
// Problem definition processing
// ================================================================================
- chooseDefaultTranslation = function (rawTranslations, translationKey) {
+ chooseDefaultTranslation = function (rawTranslations, translationKey, condition) {
var tr = rawTranslations.en, // try English as the default
- lang;
- if (tr && tr[translationKey]) return tr[translationKey];
- for (lang in rawTranslations) { // find a translation with hints
- if (!rawTranslations.hasOwnProperty(lang) || rawTranslations[lang]) continue;
+ lang, value;
+ if (typeof condition !== 'function') condition = function (x) { return !!x; };
+ if (tr && condition(tr[translationKey])) return tr[translationKey];
+ for (lang in rawTranslations) { // find a translation with content
+ if (!rawTranslations.hasOwnProperty(lang)) continue;
tr = rawTranslations[lang];
- if (tr[translationKey]) return tr[translationKey];
+ if (tr && condition(tr[translationKey])) return tr[translationKey];
}
return null; // default must be chosen by the caller
},
@@ -254,7 +277,8 @@
'id': rawData.id,
'translations': convertTranslations(rawTranslations, 'title', 'name', 'slug', 'description'), // GUI translations: keyword -> lang -> value
'hint': processHints(rawTranslations), // hint translations: keyword -> lang -> value
- 'plan': processPlans(rawTranslations) // plan translations: keyword -> lang -> value
+ 'plan': processPlans(rawTranslations), // plan translations: keyword -> lang -> value
+ 'hint_type': rawData.hint_type || {}
};
},
diff --git a/js/codeq/prolog.js b/js/codeq/prolog.js
index 87ac353..bcced1c 100644
--- a/js/codeq/prolog.js
+++ b/js/codeq/prolog.js
@@ -66,14 +66,14 @@
};
var prologHandler; //created when we enter the prolog state and destroyed once we leave it
codeq.globalStateMachine.register('prolog', {
- 'enter': function (problemDef, commonHints, currentSolution) {
+ 'enter': function (problemDef, commonDef, currentSolution) {
$('#navigation-language').css('display', '');
$('#navigation-problem').css('display', '');
$("#navigation-prolog").addClass("active");
$('#navigation-prolog').css('display', '');
jqScreen.css('display', '');//we have to show the screen now so the code editor shows its initial values correctly
- prologHandler = createPrologHandler(problemDef, commonHints, currentSolution);
+ prologHandler = createPrologHandler(problemDef, commonDef, currentSolution);
subScreens = codeq.makeStateMachine(substates);
subScreens.transition(jqDescription.data(stateNameTag));
/* Q.delay(100).then(function(){
@@ -253,7 +253,7 @@
* @param {PrologTaskDef} info
* @returns {{destroy: Function, processServerHints: Function}}
*/
- createPrologHandler = function (problemDef, commonHints, currentSolution) {
+ createPrologHandler = function (problemDef, commonDef, currentSolution) {
var //problem = info.problem,
jqDescriptionContent = jqDescription.find('.description'),
jqEditor = jqCode.find('.code_editor'),
@@ -264,7 +264,7 @@
}),
activityHandler = makeActivityHandler(editor, problemDef.id),
terminal = makePrologTerminalHandler(jqTerminal, editor, problemDef.id, activityHandler),
- hinter = codeq.makeHinter(jqHints, jqEditor, editor, 'prolog_hints', problemDef.hint, commonHints, problemDef.plan),
+ hinter = codeq.makeHinter(jqHints, jqEditor, editor, 'prolog_hints', problemDef, commonDef),
commError = function (error) {
alert(error);
};
diff --git a/js/codeq/python.js b/js/codeq/python.js
index e20fe06..8a9e92f 100644
--- a/js/codeq/python.js
+++ b/js/codeq/python.js
@@ -71,14 +71,14 @@
};
var pythonHandler; //created when we enter the python state and destroyed once we leave it
codeq.globalStateMachine.register('python', {
- 'enter': function (problemDef, commonHints, currentSolution) {
+ 'enter': function (problemDef, commonDef, currentSolution) {
$('#navigation-language').css('display', '');
$('#navigation-problem').css('display', '');
$("#navigation-python").addClass("active");
$('#navigation-python').css('display', '');
jqScreen.css('display', '');//we have to show the screen now so the code editor shows its initial values correctly
- pythonHandler = createPythonHandler(problemDef, commonHints, currentSolution);
+ pythonHandler = createPythonHandler(problemDef, commonDef, currentSolution);
subScreens = codeq.makeStateMachine(substates);
subScreens.transition(jqDescription.data(stateNameTag));
/* Q.delay(100).then(function(){
@@ -211,7 +211,7 @@
* @param {PrologTaskDef} info
* @returns {{destroy: Function, processServerHints: Function}}
*/
- var createPythonHandler = function (problemDef, commonHints, currentSolution) {
+ var createPythonHandler = function (problemDef, commonDef, currentSolution) {
var //problem = info.problem,
jqDescriptionContent = jqDescription.find('.description'),
jqEditor = jqCode.find('.code_editor'),
@@ -223,7 +223,7 @@
}),
activityHandler = makeActivityHandler(editor, problemDef.id),
terminal = makePythonTerminalHandler(jqTerminal, editor, problemDef.id, activityHandler),
- hinter = codeq.makeHinter(jqHints, jqEditor, editor, 'python_hints', problemDef.hint, commonHints, problemDef.plan),
+ hinter = codeq.makeHinter(jqHints, jqEditor, editor, 'python_hints', problemDef, commonDef),
commError = function (error) {
alert(error);
};