From 9fde9cb6cbb628fb882101385009d3b9387dc33d Mon Sep 17 00:00:00 2001 From: Robert Zorko Date: Thu, 17 Sep 2015 10:01:28 +0200 Subject: improvments to the state machine (states can now be registered) and those improvments are now used for the existing two states (plus some code general code cleanup) --- index.html | 2 + js/codeq/login.js | 112 +++++++++++++++++++++ js/codeq/mainScreen.js | 126 +++++++++++++++++++++++ js/codeq/stateMachine.js | 254 +---------------------------------------------- 4 files changed, 244 insertions(+), 250 deletions(-) create mode 100644 js/codeq/login.js create mode 100644 js/codeq/mainScreen.js diff --git a/index.html b/index.html index 036641f..ad38b69 100644 --- a/index.html +++ b/index.html @@ -135,6 +135,8 @@ + + diff --git a/js/codeq/login.js b/js/codeq/login.js new file mode 100644 index 0000000..808d1b3 --- /dev/null +++ b/js/codeq/login.js @@ -0,0 +1,112 @@ +/** + * Created by robert on 9/17/15. + */ + +(function(){ + var loginFun = function(){ + var identifier = $('#problem_group').val().split('/'), + problem = $('#problems').val(); + if (identifier.length < 2) alert('Choose a problem group'); + else if (!problem) alert('Choose a problem'); + else { + $('#disabled').css('display', ''); + codeq.comms.login($('#username').val(), $('#password').val()) + .then(function (data) { + $('#disabled').css('display', 'none'); + if (data.code !== 0) throw new Error('Login failed, code: ' + data.code + ', message: ' + data.message); + }) + .then(function () { + return codeq.comms.getProblem(identifier[0], identifier[1], problem); + }) + .then(function (data) { + if (data.code !== 0) throw new Error('Failed to obtain problem data, code: ' + data.code + ', message: ' + data.message); + $('#disabled').css('display', 'none'); + switch (identifier[0]) { + case 'prolog': + // TODO: assignment to window for debug only + //$('#screen_login').css('display', 'none'); + //$('#screen_prolog').css('display', ''); + codeq.globalStateMachine.transition('prolog'); + window.phandler = codeq.createPrologHandler(data.data); + break; + case 'python': + // TODO: assignment to window for debug only + //$('#screen_login').css('display', 'none'); + //$('#screen_prolog').css('display', ''); + codeq.globalStateMachine.transition('prolog'); + window.phandler = codeq.createPythonHandler(data.data); + break; + default: + alert('Unknown language: ' + identifier[0]); + break; + } + }) + .fail(function (reason) { + $('#disabled').css('display', 'none'); + alert('Login request failed: ' + reason); + }) + .done(); + } + }; + codeq.globalStateMachine.register('login',{ + 'enter': function(){ + codeq.comms.connect().then(function () { + return codeq.comms.send({'action': 'list_problems'});//currently problem list and the actual login are still in the same state + }).then( + function success(data) { + var i, groups, group, problems, problem, first_group, + jqGroup = $('#problem_group'), + jqProblems = $('#problems'), + html = [], + mapping = {}, + onGroupChange = function () { + var problems = mapping[jqGroup.val()], + html = [], + i, p; + if (problems) { + for (i = 0; i < problems.length; i++) { + p = problems[i]; + html.push('\n') + } + } + jqProblems.html(html.join('')); + }; + + if (data && (data.code === 0)) { + $('#disabled').css('display', 'none'); + groups = data.problems; + for (i = 0; i < groups.length; i++) { + group = groups[i]; + var identifier = group.identifier.language + '/' + group.identifier.group; + var name = group.name.language + ': ' + group.name.group; + html.push('\n'); + mapping[identifier] = group.problems; + } + jqGroup.html(html.join('')); + first_group = html[1]; + html = null; + + jqGroup.on('click', onGroupChange); + jqGroup.val(first_group); + onGroupChange(); + + $("#submit").on('click', loginFun); + } + else { + $('#disabled').css('cursor', ''); + alert('Obtaining list of problems failed: code=' + data.code + ', reason=' + data.message); + } + }, + + function failure(reason) { + $('#disabled').css('cursor', ''); + alert('Request to obtain list of problems failed: ' + reason); + } + ).done(); + }, + 'exit' : function(){ + $("#submit").off('click', loginFun); + $("#screen_login").css('display', 'none'); + } + }); +})(); \ No newline at end of file diff --git a/js/codeq/mainScreen.js b/js/codeq/mainScreen.js new file mode 100644 index 0000000..8752cbe --- /dev/null +++ b/js/codeq/mainScreen.js @@ -0,0 +1,126 @@ +/** + * 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('prolog', { + '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/stateMachine.js b/js/codeq/stateMachine.js index 229c8ff..12332c4 100644 --- a/js/codeq/stateMachine.js +++ b/js/codeq/stateMachine.js @@ -13,256 +13,10 @@ codeq.makeStateMachine = function(def){ 'destroy': function(){ if(currState !== null) currState.exit(); currState = null; - } - } -} - - - - -var loginFun = function(){ - var identifier = $('#problem_group').val().split('/'), - problem = $('#problems').val(); - if (identifier.length < 2) alert('Choose a problem group'); - else if (!problem) alert('Choose a problem'); - else { - $('#disabled').css('display', ''); - codeq.comms.login($('#username').val(), $('#password').val()) - .then(function (data) { - $('#disabled').css('display', 'none'); - if (data.code !== 0) throw new Error('Login failed, code: ' + data.code + ', message: ' + data.message); - }) - .then(function () { - return codeq.comms.getProblem(identifier[0], identifier[1], problem); - }) - .then(function (data) { - if (data.code !== 0) throw new Error('Failed to obtain problem data, code: ' + data.code + ', message: ' + data.message); - $('#disabled').css('display', 'none'); - switch (identifier[0]) { - case 'prolog': - // TODO: assignment to window for debug only - //$('#screen_login').css('display', 'none'); - //$('#screen_prolog').css('display', ''); - codeq.globalStateMachine.transition('prolog'); - window.phandler = codeq.createPrologHandler(data.data); - break; - case 'python': - // TODO: assignment to window for debug only - //$('#screen_login').css('display', 'none'); - //$('#screen_prolog').css('display', ''); - codeq.globalStateMachine.transition('prolog'); - window.phandler = codeq.createPythonHandler(data.data); - break; - default: - alert('Unknown language: ' + identifier[0]); - break; - } - }) - .fail(function (reason) { - $('#disabled').css('display', 'none'); - alert('Login request failed: ' + reason); - }) - .done(); - } -}; - -codeq.globalStateMachine = codeq.makeStateMachine({ - 'login':{ - 'enter': function(){ - codeq.comms.connect().then(function () { - return codeq.comms.send({'action': 'list_problems'});//currently problem list and the actual login are still in the same state - }).then( - function success(data) { - var i, groups, group, problems, problem, first_group, - jqGroup = $('#problem_group'), - jqProblems = $('#problems'), - html = [], - mapping = {}, - onGroupChange = function () { - var problems = mapping[jqGroup.val()], - html = [], - i, p; - if (problems) { - for (i = 0; i < problems.length; i++) { - p = problems[i]; - html.push('\n') - } - } - jqProblems.html(html.join('')); - }; - - if (data && (data.code === 0)) { - $('#disabled').css('display', 'none'); - groups = data.problems; - for (i = 0; i < groups.length; i++) { - group = groups[i]; - var identifier = group.identifier.language + '/' + group.identifier.group; - var name = group.name.language + ': ' + group.name.group; - html.push('\n'); - mapping[identifier] = group.problems; - } - jqGroup.html(html.join('')); - first_group = html[1]; - html = null; - - jqGroup.on('click', onGroupChange); - jqGroup.val(first_group); - onGroupChange(); - - $("#submit").on('click', loginFun); - } - else { - $('#disabled').css('cursor', ''); - alert('Obtaining list of problems failed: code=' + data.code + ', reason=' + data.message); - } - }, - - function failure(reason) { - $('#disabled').css('cursor', ''); - alert('Request to obtain list of problems failed: ' + reason); - } - ).done(); }, - 'exit' : function(){ - $("#submit").off('click', loginFun); - $("#screen_login").css('display', 'none'); - } - }, - - 'prolog':{ - 'enter': function(){ - $('#screen_prolog').css('display', ''); - removeFocusFromElements(); - problems = codeq.makeStateMachine(substates); - //problems.transition('instructions'); - problems.transition('instructions'); - }, - 'exit': function(){ - $('#screen_prolog').css('display', 'none'); - problems.destroy(); + 'register': function(name,state){ + def[name] = state; } } -}); - -/* -the following variables are used in the sub-state machine representing the 4 different panels in the codeq app - */ -var problems,//this will the actual state machine - description = $('div.col-lg-3.col-md-6.col-sm-12:has(#description)'),//lets actually find the needed divs for later use - code = $('div.col-lg-3.col-md-6.col-sm-12:has(#code_editor)'), - consoleDiv = $('div.col-lg-3.col-md-6.col-sm-12:has(#console)'),//named 'consoleDiv', because 'console' is already in use - info = $('div.col-lg-3.col-md-6.col-sm-12:has(#info)'), - - //some functions used inside the enter and exit functions of the state machine - eventName = 'mousedown',//event name of the event which will trigger the transition between these substates - mouseDownEventFunctionDescription = function(){ - problems.transition('instructions'); - }, - mouseDownEventFunctionCode = function(){ - problems.transition('code'); - }, - mouseDownEventFunctionConsole = function(){ - problems.transition('console'); - }, - mouseDownEventFunctionInfo = function(){ - problems.transition('info'); - }, - removeListenersFromDivs = function(){ - description.off(eventName,mouseDownEventFunctionDescription); - code.off(eventName,mouseDownEventFunctionCode); - consoleDiv.off(eventName,mouseDownEventFunctionConsole); - info.off(eventName,mouseDownEventFunctionInfo); - }, - removeBlockClassesFromDivs = function(){ - description.removeClass('block'); - code.removeClass('block'); - consoleDiv.removeClass('block'); - info.removeClass('block'); - }, - removeChangedClassesFromDivs = function(){ - description.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) - code.removeClass('block-focus block-less-width block-less-height block-less-everything').addClass('block'); - consoleDiv.removeClass('block-focus block-less-width block-less-height block-less-everything').addClass('block'); - info.removeClass('block-focus block-less-width block-less-height block-less-everything').addClass('block'); - }, - setTransitionsBetweenDivs = function(current){ - if(current !== description)description.on(eventName,mouseDownEventFunctionDescription); - if(current !== code)code.on( eventName,mouseDownEventFunctionCode); - if(current !== info)info.on( eventName,mouseDownEventFunctionInfo); - if(current !== consoleDiv)consoleDiv.on( eventName,mouseDownEventFunctionConsole); - }, - removeFocusFromElements = function(){ - - }, - - //the states of the sub-state machine - substates = { - 'instructions':{ - 'enter': function(){ - removeBlockClassesFromDivs(); - - description.addClass('block-focus'); - code.addClass('block-less-width'); - consoleDiv.addClass('block-less-height'); - info.addClass('block-less-everything'); - - setTransitionsBetweenDivs(description); - }, - 'exit': function(){ - removeFocusFromElements(); - removeChangedClassesFromDivs(); - removeListenersFromDivs(); - } - }, - 'code':{ - 'enter': function(){ - removeBlockClassesFromDivs(); - - description.addClass('block-less-width'); - code.addClass('block-focus'); - consoleDiv.addClass('block-less-everything'); - info.addClass('block-less-height'); - - setTransitionsBetweenDivs(code); - }, - 'exit': function(){ - removeFocusFromElements(); - removeChangedClassesFromDivs(); - removeListenersFromDivs(); - } - }, - 'info':{ - 'enter': function(){ - removeBlockClassesFromDivs(); - - description.addClass('block-less-everything'); - code.addClass('block-less-height'); - consoleDiv.addClass('block-less-width'); - info.addClass('block-focus'); - - setTransitionsBetweenDivs(info); - }, - 'exit': function(){ - removeFocusFromElements(); - removeChangedClassesFromDivs(); - removeListenersFromDivs(); - } - }, - 'console':{ - 'enter': function(){ - removeBlockClassesFromDivs(); - - description.addClass('block-less-height'); - code.addClass('block-less-everything'); - consoleDiv.addClass('block-focus'); - info.addClass('block-less-width'); - - setTransitionsBetweenDivs(consoleDiv); - }, - 'exit': function(){ - removeFocusFromElements(); - removeChangedClassesFromDivs(); - removeListenersFromDivs(); - } - } - }; \ No newline at end of file +}; +codeq.globalStateMachine = codeq.makeStateMachine({}); -- cgit v1.2.1