/** * Created by robert on 9/15/15. */ codeq.makeStateMachine = function(def){ var currState = null; return { 'transition': function(name){ if(currState !== null) currState.exit(); currState = def[name]; currState.enter(); }, '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(); } } }); /* 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(); } } };