From 7dab4d3640b7b37c407eea111eda1fc0b71adbda Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ale=C5=A1=20Smodi=C5=A1?= Date: Mon, 28 Sep 2015 18:44:48 +0200 Subject: Implement in-structure GUI translation for python and problem editing screens. Hints are not yet covered. --- js/codeq/problem.js | 173 ++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 161 insertions(+), 12 deletions(-) (limited to 'js/codeq/problem.js') diff --git a/js/codeq/problem.js b/js/codeq/problem.js index 3e218d8..35b45af 100644 --- a/js/codeq/problem.js +++ b/js/codeq/problem.js @@ -2,8 +2,93 @@ var jqScreen = $('#screen_problem'), languageCache = {}, // keyed by language identifier: processed data about languages translationCache = [], // keys are autogenerated in ta(), a value is a dictionary of translations of a translation key for every language + problemCache = {}, // problem data cache, 3-level, keyed by: language, problem group, and problem identifier langs, Nlangs, // constants, set on init + // ================================================================================ + // Hint processing: extract hints from the translations and return them in the + // processed form, hint key -> translation language -> value + // ================================================================================ + + 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') || {}; + for (key in tr) { // copy the hints + if (!tr.hasOwnProperty(key)) continue; + defaultHint[key] = tr[key]; + allHintKeys.push(key); + } + // copy any hints not in the default hints to the default hints + 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 + hint = tr.hint; + for (key in hint) { + if (!hint.hasOwnProperty(key) || !hint[key]) continue; + if (!key in defaultHint) { + defaultHint[key] = hint[key]; + allHintKeys.push(key); + } + } + } + // create all translations for hints + for (i = langs.length - 1; i >= 0; i--) { + lang = langs[i]; + tr = rawTranslations[lang]; + // set up hints + if (!tr || !tr.hint) { + // there's no hint in the current language, copy the default in its entirety + allHints[lang] = defaultHint; + } + 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--) { + key = allHintKeys[j]; + hint[key] = h[key] || defaultHint[key]; + } + } + } + return allHints; + }, + + // ================================================================================ + // Plan processing: extract plans from the translations and return them in the + // processed form, hint key -> translation language -> value + // ================================================================================ + + processPlans = function (rawTranslations) { + // find the default plan translation + var defaultPlan = chooseDefaultTranslation(rawTranslations, 'plan') || [], + allPlans = {}, // the result + i, lang, tr; + // create all translations for plan + for (i = langs.length - 1; i >= 0; i--) { + 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; + } + else { + allPlans[lang] = tr.plan; + } + } + return allPlans; + }, + + // ================================================================================ + // Group + problems directory processing + // ================================================================================ + chooseTranslation = function (keyword, lang, currentDict, enDict, translations) { var tr = currentDict[keyword], otherLang; @@ -65,11 +150,12 @@ */ createLanguageData = function (data, languageIdentifier) { // data is the content of language.json var li = languageIdentifier, // a shorthand + rawTranslations = data.translations || {}, groups = data.groups || {}, html = [], problemReferences = [], groupIdentifier, group, problems, problemIdentifier, problem; - var langDict = convertTranslations(data.translations, 'name', 'description'), // this will be the resulting dictionary: multi-level keys that lead up to the lang-dict + var langDict = convertTranslations(rawTranslations, 'name', 'description'), // this will be the resulting dictionary: multi-level keys that lead up to the lang-dict groupDict, problemDict; // title: HTML structure for "name" and "desc" html.push('


'); @@ -91,24 +177,29 @@ problem = problems[problemIdentifier] || {}; problemDict = convertTranslations(problem.translations, 'name'); html.push('
  • '); - problemReferences.push({'g': groupIdentifier, 'p': problemIdentifier}); + problemReferences.push({'g': groupIdentifier, 'p': problemIdentifier, 'id': problem.id}); } html.push(''); } html.push(''); return { - 'language': languageIdentifier, - 'html': html.join(''), - 'refs': problemReferences, - 'hints': {} // TODO: prepare common hints for the language + '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 elements + 'hints': processHints(rawTranslations) // hint translations: keyword -> lang -> value }; }, + // ================================================================================ + // DOM instantiation. + // The transition to problem solving takes place here, after the user clicks on a + // problem and all the required data is loaded. + // ================================================================================ /** * Instantiates the screen from the given processed data. */ - createDom = function (data) { + createDom = function (data) { // data is the (cached) result of createLanguageData() var language = data.language; jqScreen.html(data.html); codeq.tr.translateDom(jqScreen); @@ -119,12 +210,15 @@ codeq.log.error('Clicked on a problem link having erroneous index: ' + index); return; } - // transition codeq.wait( - codeq.comms.getProblem(language, ref.g, ref.p) - .then(function (data) { - if (data.code !== 0) throw new Error('Failed to obtain problem data, code: ' + data.code + ', message: ' + data.message); - codeq.globalStateMachine.transition(language, data); + Q.all([ + codeq.comms.getProblem(language, ref.g, ref.p), // TODO: use ref.id instead // the current solution + getProblemData(language, ref.g, ref.p) // the (cached) result of processProblemData() + ]) + .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); }) ) .fail(function (reason) { @@ -134,6 +228,61 @@ .done(); }); }, + + // ================================================================================ + // Problem definition processing + // ================================================================================ + + chooseDefaultTranslation = function (rawTranslations, translationKey) { + 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; + tr = rawTranslations[lang]; + if (tr[translationKey]) return tr[translationKey]; + } + return null; // default must be chosen by the caller + }, + + processProblemData = function (rawData, language, group, problem) { + var rawTranslations = rawData.translations || {}; + return { + 'language': language, + 'group': group, + 'problem': problem, + '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 + }; + }, + + getProblemData = function (language, group, problem) { + var langCache = problemCache[language], + groupCache, cachedProblem, promise; + if (langCache) { + groupCache = langCache[group]; + if (!groupCache) { + groupCache = {}; + langCache[group] = groupCache; + } + } + else { + langCache = {}; + problemCache[language] = langCache; + groupCache = {}; + langCache[group] = groupCache; + } + cachedProblem = groupCache[problem]; + if (cachedProblem) return Q(cachedProblem); + return codeq.comms.getProblemDef(language, group, problem).then(function (rawData) { + var data = processProblemData(rawData); + groupCache[problem] = data; + return data; + }); + }, + currentLanguage; // the currently active language // ================================================================================ -- cgit v1.2.1 From 10de7241f22a10d65f53c891a8b07fe8650b4878 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20Pu=C5=A1nik?= Date: Tue, 29 Sep 2015 08:32:59 +0200 Subject: login removed from navbar --- js/codeq/problem.js | 2 -- 1 file changed, 2 deletions(-) (limited to 'js/codeq/problem.js') diff --git a/js/codeq/problem.js b/js/codeq/problem.js index 35b45af..464dc12 100644 --- a/js/codeq/problem.js +++ b/js/codeq/problem.js @@ -303,7 +303,6 @@ 'enter': function(language){ var data = null; // language data - $('#navigation-login').css('display', ''); $('#navigation-language').css('display', ''); $("#navigation-problem").addClass("active").css('display', ''); @@ -329,7 +328,6 @@ }, 'exit' : function(){ jqScreen.css('display', 'none'); - $('#navigation-login').css('display', 'none'); $('#navigation-language').css('display', 'none'); $('#navigation-problem').css('display', 'none').removeClass("active"); } -- cgit v1.2.1 From 22cb497f9ed19548e30a4c86dd99aaa91fd4b344 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ale=C5=A1=20Smodi=C5=A1?= Date: Tue, 29 Sep 2015 14:13:38 +0200 Subject: Changes to process language.js files with ordered problems (arrays instead of dictionaries). --- js/codeq/problem.js | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'js/codeq/problem.js') diff --git a/js/codeq/problem.js b/js/codeq/problem.js index 464dc12..7ae54d8 100644 --- a/js/codeq/problem.js +++ b/js/codeq/problem.js @@ -151,10 +151,11 @@ createLanguageData = function (data, languageIdentifier) { // data is the content of language.json var li = languageIdentifier, // a shorthand rawTranslations = data.translations || {}, - groups = data.groups || {}, + groups = data.groups || [], + Ngroups = groups.length, html = [], problemReferences = [], - groupIdentifier, group, problems, problemIdentifier, problem; + group, problems, Nproblems, problem, i, j; var langDict = convertTranslations(rawTranslations, 'name', 'description'), // this will be the resulting dictionary: multi-level keys that lead up to the lang-dict groupDict, problemDict; // title: HTML structure for "name" and "desc" @@ -162,22 +163,21 @@ html.push('
    '); // content: problem directory html.push('