diff options
-rw-r--r-- | js/codeq/mainScreen.js | 126 | ||||
-rw-r--r-- | js/codeq/prolog.js | 5 | ||||
-rw-r--r-- | js/codeq/prologPythonLib.js | 341 | ||||
-rw-r--r-- | js/prolog.js | 5 | ||||
-rw-r--r-- | js/python.js | 3 |
5 files changed, 9 insertions, 471 deletions
diff --git a/js/codeq/mainScreen.js b/js/codeq/mainScreen.js deleted file mode 100644 index e842ee3..0000000 --- a/js/codeq/mainScreen.js +++ /dev/null @@ -1,126 +0,0 @@ -/** - * Created by robert on 9/17/15. - */ - -(function() { - var problems,//this will the actual (sub)state machine - stateNameTag = 'stateName'; - - var divs = {}; - divs['description'] = $('div.col-lg-3.col-md-6.col-sm-12:has(#description)');//lets actually find the needed divs for later use - divs['code'] = $('div.col-lg-3.col-md-6.col-sm-12:has(#code_editor)'); - divs['console'] = $('div.col-lg-3.col-md-6.col-sm-12:has(#console)');//named 'consoleDiv', because 'console' is already in use - divs['info'] = $('div.col-lg-3.col-md-6.col-sm-12:has(#info)'); - - divs['description'].data(stateNameTag, 'description'); - divs['code'].data(stateNameTag, 'code'); - divs['console'].data(stateNameTag, 'console'); - divs['info'].data(stateNameTag, 'info'); - - var eventName = 'mousedown',//event name of the event which will trigger the transition between these substates - mouseDownEventFunction = function () { - problems.transition($(this).data(stateNameTag)); - }, - removeListenersFromDivs = function () { - $.each(divs, function (i, value) { - value.off(eventName, mouseDownEventFunction); - }); - }, - removeBlockClassesFromDivs = function () { - $.each(divs, function (i, value) { - value.removeClass('block'); - }); - }, - removeChangedClassesFromDivs = function () { - $.each(divs, function (i, value) { - value.removeClass('block-focus block-less-width block-less-height block-less-everything').addClass('block');//these class names were chosen for the view where the screen is partitioned in 4 quarters (2 by 2) - }); - }, - setTransitionsBetweenDivs = function (current) { - $.each(divs, function (key, value) { - if (current !== key) value.on(eventName, mouseDownEventFunction); - }); - }, - addClassesToDivs = function (divsWithClasses) { - $.each(divsWithClasses, function (divName, className) { - divs[divName].addClass(className); - }); - }, - substates = { - 'description': { - 'enter': function () { - removeBlockClassesFromDivs(); - addClassesToDivs({ - 'description': 'block-focus', - 'code': 'block-less-width', - 'console': 'block-less-height', - 'info': 'block-less-everything' - }); - setTransitionsBetweenDivs('description'); - }, - 'exit': function () { - removeChangedClassesFromDivs(); - removeListenersFromDivs(); - } - }, - 'code': { - 'enter': function () { - removeBlockClassesFromDivs(); - addClassesToDivs({ - 'description': 'block-less-width', - 'code': 'block-focus', - 'console': 'block-less-everything', - 'info': 'block-less-height' - }); - setTransitionsBetweenDivs('code'); - }, - 'exit': function () { - removeChangedClassesFromDivs(); - removeListenersFromDivs(); - } - }, - 'info': { - 'enter': function () { - removeBlockClassesFromDivs(); - addClassesToDivs({ - 'description': 'block-less-everything', - 'code': 'block-less-height', - 'console': 'block-less-width', - 'info': 'block-focus' - }); - setTransitionsBetweenDivs('info'); - }, - 'exit': function () { - removeChangedClassesFromDivs(); - removeListenersFromDivs(); - } - }, - 'console': { - 'enter': function () { - removeBlockClassesFromDivs(); - addClassesToDivs({ - 'description': 'block-less-height', - 'code': 'block-less-everything', - 'console': 'block-focus', - 'info': 'block-less-width' - }); - setTransitionsBetweenDivs('console'); - }, - 'exit': function () { - removeChangedClassesFromDivs(); - removeListenersFromDivs(); - } - } - }; - codeq.globalStateMachine.register('main', { - 'enter': function () { - $('#screen_prolog').css('display', ''); - problems = codeq.makeStateMachine(substates); - problems.transition(divs['description'].data(stateNameTag)); - }, - 'exit': function () { - $('#screen_prolog').css('display', 'none'); - problems.destroy(); - } - }); -})();
\ No newline at end of file diff --git a/js/codeq/prolog.js b/js/codeq/prolog.js index 1978ba4..e411895 100644 --- a/js/codeq/prolog.js +++ b/js/codeq/prolog.js @@ -220,6 +220,7 @@ var makePrologTerminalHandler = function (jqConsole, editor, problem_id, activityHandler) { var promptMode = true, // default: query composition; alternative: query result browsing + manualStop = false,// if the user stopped showing next answers (false) or if there are no more answers (true) terminal = codeq.makeConsole(jqConsole, { 'greeting': 'CodeQ Prolog terminal proxy' }), @@ -236,7 +237,7 @@ } if (promptMode) { terminal.setLineBuffered(); - terminal.append('.\n?- ', 'output'); + terminal.append(manualStop ? '?- ' : '.\n?- ', 'output'); } }, tcf = function terminalCommandFailed (error) { @@ -261,6 +262,7 @@ terminal.onInput = function (command) { if (promptMode) { promptMode = false; + manualStop = false; terminal.setNotBuffered(); return codeq.comms.sendQuery({ 'problem_id': problem_id, @@ -282,6 +284,7 @@ } else { // stop searching for answers + manualStop = true; return codeq.comms.sendQuery({ 'problem_id': problem_id, 'step': 'end', diff --git a/js/codeq/prologPythonLib.js b/js/codeq/prologPythonLib.js deleted file mode 100644 index 400a56e..0000000 --- a/js/codeq/prologPythonLib.js +++ /dev/null @@ -1,341 +0,0 @@ -/** - * Created by robert on 9/15/15. - */ - -/** - * this is currently not used - I made this common python/prolog library a bit to early, but I don't want to delete everything, so I'll leave it for now in case it can be used later without to many changes - * - * - * - * @param editor - * @param problem_id - * @returns {{queueTrace: Function, flush: Function, addAndPurge: Function}} - */ - -codeq.makeActivityHandler = function (editor, problem_id) { - var lastActivityMillis = Date.now(), - deltaActivityMillis = function deltaActivityMillisFunc () { - var now = Date.now(), - dt = now - lastActivityMillis; - lastActivityMillis = now; - return dt; - }, - queue = [], - ts = null, - timer = function () { - var promise; - ts = null; - if (queue.length === 0) return Q(true); - promise = codeq.comms.sendActivity(queue, editor.getDoc().getValue(), problem_id); - queue.length = 0; - return promise; - }, - flush = function () { - clearTimeout(ts); - return timer(); - }; - - return { - 'queueTrace': function (trace) { - trace['dt'] = deltaActivityMillis(); - queue.push(trace); - if (ts === null) setTimeout(timer, 10000); // flush every 10 seconds - }, - 'flush': flush, - 'addAndPurge': function (trace) { - var accumulatedTrace = queue; - queue = []; - trace['dt'] = deltaActivityMillis(); - accumulatedTrace.push(trace); - if (ts !== null) { - clearTimeout(ts); - ts = null; - } - return accumulatedTrace; - } - }; -}; - -/** - * Creates a new handler for the given Programming language assignment definition. - * - * @param {string} language - either 'prolog' or 'python' - * @param {PrologTaskDef} info - * @param {function} makeTerminalHandlerFun - either the makePythonTerminalHandler or makePrologTerminalHandler function - * @returns {{destroy: Function, processServerHints: Function}} - */ -codeq.createProgrammingLanguageHandler = function (language,info,makeTerminalHandlerFun) { - var firstCharacterPos = {'line': 0, 'ch': 0}; - - var problem = info.problem, - jqDescription = $('#description'), - jqEditor = $('#code_editor'), - jqConsole = $('#console'), - jqHints = $('#info'), - editor = CodeMirror(jqEditor[0], { cursorHeight: 0.85, lineNumbers: true, matchBrackets: true }), - activityHandler = codeq.makeActivityHandler(editor, problem.id), - terminal = makeTerminalHandlerFun(jqConsole, editor, problem.id, activityHandler), - hintDefs = problem.hint, - hintCounter = 0, // for generating unique class-names - hintCleaners = [], - clearHints = function () { - var i; - for (i = hintCleaners.length - 1; i >= 0; i--) { - hintCleaners[i](); - } - hintCleaners.length = 0; - hintCounter = 0; - }, - addMark = function (start, end) { - var posStart = editor.posFromIndex(start), - posEnd = editor.posFromIndex(end), - doc = editor.getDoc(), - mark = doc.markText(posStart, posEnd, {className: 'editor-mark _emark_' + hintCounter}), - result = {start: posStart, end: posEnd, mark: mark, className: '_emark_' + hintCounter}; - hintCleaners.push(function () { mark.clear(); mark = null; doc = null; result.mark = null; }); - hintCounter++; - return result; - }, - processTemplate = function (template, args) { - if (!args) - return template; - return template.replace(/\[%=(\w+)%\]/g, function(match, name) { - return args[name]; - }); - }, - hintHandlers = { - 'static': function (type, template, serverHint) { - codeq.log.debug('Processing static hint'); - var message = processTemplate(template, serverHint.args); - jqHints.append('<div class="hint-static">' + message + '</div>'); - // no hint cleaner here, a static hint remains on the screen - }, - 'popup': function (type, template, serverHint) { - codeq.log.debug('Processing popup hint'); - var message = processTemplate(template, serverHint.args), - mark = addMark(serverHint.start, serverHint.end), // add the mark - jqMark = jqEditor.find('.' + mark.className); - /* jqPopup = null, - onBlur = function () { - codeq.log.debug('Removing popup'); - if (jqPopup) { - jqPopup.off('blur', onBlur); - jqPopup.remove(); - jqPopup = null; - } - }; - - window.jqMark = jqMark; // TODO: DEBUG - - jqMark.on('click', function () { - if (jqPopup) return; - codeq.log.debug('Showing popup'); - var pos = mark.mark.find(), // results in {from: {line: number, ch: number}, to: {line: number, ch: number}} - left = pos.from.ch < pos.to.ch ? pos.from.ch : pos.to.ch, - down = pos.from.line < pos.to.line ? pos.to.line : pos.from.line; - jqPopup = $('<div style="position: absolute;" class="editor-popup ' + mark.className + '"></div>').html(template); - editor.addWidget({line: down, ch: left}, jqPopup[0], true); - jqPopup = jqEditor.find('.editor-popup.' + mark.className); - setTimeout(function () {jqPopup.trigger('focus'); jqPopup.on('click', onBlur);}, 50); // event handlers can be registered only when the DOM elements is part of the document - window.jqPopup = jqPopup; // TODO: DEBUG - }); - - hintCleaners.push(function () { - if (jqPopup) { - jqPopup.off('blur', onBlur); - jqPopup.remove(); - jqPopup = null; - } - if (jqMark) { - jqMark = null; - } - mark = null; - });*/ - - jqMark.popover({content: message, html: true, placement: 'auto bottom', trigger: 'hover focus click', container: 'body'}); - hintCleaners.push(function () { if (jqMark) { jqMark.popover('destroy'); jqMark = null; } }); - - mark.mark.on('', function () {}); - }, - 'dropdown': function (type, template, serverHint) { - codeq.log.debug('Processing dropdown hint'); - var completion = null, // the completion object, created in showHint() - close = function () { - if (completion) { - completion.close(); - completion = null; - } - }; - - if ((editor.listSelections().length > 1) || editor.somethingSelected()) { - // showHint() doesn't work if a selection is activeparts - } - - editor.showHint({ - hint: function () { - var hints = { - list: serverHint.choices, - from: editor.posFromIndex(serverHint.start), - to: editor.posFromIndex(serverHint.end) - }; - completion = editor.state.completionActive; - return hints; - }, - completeOnSingleClick: true, - completeSingle: false - }); - - hintCleaners.push(close); - } - }; - - editor.setValue(info.solution); - $('#title').text(problem.slug); - jqDescription.html(problem.description); - - editor.on('change', function (instance, changeObj) { - var doc = editor.getDoc(), - pos = codeq.codePointCount(doc.getRange(firstCharacterPos, changeObj.from)); - - if (changeObj.removed) { - activityHandler.queueTrace({'typ': 'rm', 'off': pos, 'len': codeq.codePointCount(changeObj.removed)}); - } - - if (changeObj.text) { - activityHandler.queueTrace({'typ': 'ins', 'off': pos, 'txt': changeObj.text}); - } - }); - - var handler = { - destroy: function () { - terminal.destroy(); - jqDescription.empty(); - jqEditor.empty(); // TODO: perhaps you do not want to "free" the editor, just empty it - jqConsole.empty(); // TODO: the same with the console - jqHints.empty(); // TODO: just make static references to these - jqDescription = null; - jqEditor = null; - jqConsole = null; - jqHints = null; - }, - - /** - * Processes and display appropriately the server hints. - * TODO: sort hints so static and popup hints come first, and a (single) drop-down hint last - * - * @param {ServerHint[]} serverHints an array of hints from the server - */ - processServerHints: function (serverHints) { - var n = serverHints.length, - /** number */ i, - /** ServerHint */ serverHint, - /** HintDefinition */ hintDef, - hintType, hintTemplate, t, fn; - clearHints(); - for (i = 0; i < n; i++) { - serverHint = serverHints[i]; - hintDef = hintDefs[serverHint.id]; - if (serverHint.indices) { - indices = serverHint.indices - for (i = 0; i < indices.length; i++) { - hintDef = hintDef[indices[i]]; - if (!hintDef) - break; - } - } - if (!hintDef) { - codeq.log.error('Undefined hint ' + serverHint.id + ' with indices ' + serverHint.indices); - continue; - } - t = typeof hintDef; - if (t === 'object') { - hintType = hintDef.type; - hintTemplate = hintDef.message; - } - else if (t === 'string') { - hintType = 'static'; - hintTemplate = hintDef; - } - else { - codeq.log.error('Unsupported hint definition: ' + t); - continue; - } - - fn = hintHandlers[hintType]; - if (!fn) codeq.log.error('Unsupported hint type: ' + hintType); - else fn(hintType, hintTemplate, serverHint); - } - } - }; - - var jqButtons = $('#block-toolbar button'); -// $(jqButtons.get(0)).on('click', function () { handler.processServerHints([{id:'x_must_be_female'}]); }); -// $(jqButtons.get(1)).on('click', function () { handler.processServerHints([{id:'popup_unknown', start: 20, end: 26}]); }); -// $(jqButtons.get(2)).on('click', function () { handler.processServerHints([{id:'drop_down', start: 20, end: 26, choices:['ena', 'dva', 'tri']}]); }); - - $('#btn_code_hint').on('click', function () { - if (language === 'prolog') { - terminal.append('hint.\n', 'input'); - terminal.inputDisable(); - } - var doc = editor.getDoc(); - codeq.comms.sendHint({ - 'language': 'prolog', - 'program': editor.getDoc().getValue(), - 'problem_id': problem.id - }).then( - function hintSuccess(data) { - if (data.code === 0) - handler.processServerHints(data.hints); - else - terminal.append(data.message + '\n', 'error'); - }, - function hintFailed (error) { - terminal.append(error + '\n', 'error'); - } - ).fin(function () { - if(language === 'prolog'){ - terminal.inputEnable(); - terminal.append('?- ', 'output'); - } - } - ).done(); - }); - $('#btn_code_test').on('click', function () { - if(language === 'prolog'){ - terminal.append('test.\n', 'input'); - terminal.inputDisable(); - } - var doc = editor.getDoc(); - codeq.comms.sendTest({ - 'language': language, - 'program': editor.getDoc().getValue(), - 'problem_id': problem.id - }).then( - function testSuccess(data) { - if (data.code === 0) - handler.processServerHints(data.hints); - else - terminal.append(data.message + '\n', 'error'); - }, - function testFailed (error) { - terminal.append(error + '\n', 'error'); - } - ).fin(function () { - if(language === 'prolog'){ - terminal.inputEnable(); - terminal.append('?- ', 'output'); - } - } - ).done(); - }); - - if(language === 'python'){ - // TODO first line of interpreter output is buffered without this, why? - codeq.comms.sendPush({ - 'text': '' - }); - } - - return handler; -}; diff --git a/js/prolog.js b/js/prolog.js index 29ceb3d..fad1dd4 100644 --- a/js/prolog.js +++ b/js/prolog.js @@ -8,6 +8,7 @@ var makePrologTerminalHandler = function (jqConsole, editor, problem_id, activityHandler) { var promptMode = true, // default: query composition; alternative: query result browsing + manualStop = false, // if the user stopped showing next answers (false) or if there are no more answers (true) terminal = codeq.makeConsole(jqConsole, { 'greeting': 'CodeQ Prolog terminal proxy' }), @@ -24,7 +25,7 @@ } if (promptMode) { terminal.setLineBuffered(); - terminal.append('.\n?- ', 'output'); + terminal.append(manualStop ? '?- ' : '.\n?- ', 'output'); } }, tcf = function terminalCommandFailed (error) { @@ -49,6 +50,7 @@ terminal.onInput = function (command) { if (promptMode) { promptMode = false; + manualStop = false; terminal.setNotBuffered(); return codeq.comms.sendQuery({ 'problem_id': problem_id, @@ -70,6 +72,7 @@ } else { // stop searching for answers + manualStop = true; return codeq.comms.sendQuery({ 'problem_id': problem_id, 'step': 'end', diff --git a/js/python.js b/js/python.js index fa4943b..1f2b5cb 100644 --- a/js/python.js +++ b/js/python.js @@ -6,7 +6,6 @@ // a constant var firstCharacterPos = {'line': 0, 'ch': 0}; - //codeq.makePythonTerminalHandler = function (jqConsole, editor, problem_id, activityHandler) { var makePythonTerminalHandler = function (jqConsole, editor, problem_id, activityHandler) { var terminal = codeq.makeConsole(jqConsole, { 'greeting': 'CodeQ Python terminal proxy' @@ -38,7 +37,7 @@ return terminal; }; - var makeActivityHandler = function (editor, problem_id) { + var makeActivityHandler = function (editor, problem_id) { var lastActivityMillis = Date.now(), deltaActivityMillis = function deltaActivityMillisFunc () { var now = Date.now(), |