-
Notifications
You must be signed in to change notification settings - Fork 0
/
proso-apps-services.min.js.map
1 lines (1 loc) · 91.8 KB
/
proso-apps-services.min.js.map
1
{"version":3,"file":"proso-apps-services.min.js","sources":["proso-apps-services.js"],"names":["obj2get","obj","prefix","ignore_prefix_keys","str","key","hasOwnProperty","indexOf","encodeURIComponent","angular","module","value","window","gettext","x","filter","msgid","configServiceLoaded","m","factory","$http","$window","$cookieStore","configService","self","this","config","getConfig","appName","defaultValue","variable","overridden","isDebug","console","log","error","path","split","i","length","debug","loadConfig","get","success","response","processConfig","data","copy","override","$","isNumeric","parseFloat","put","removeOverridden","resetOverridden","getOverridden","$httpProvider","interceptors","push","$injector","request","has","url","match","loggingServiceLoaded","loggingService","debugLog","debugLogListeners","getDebugLog","extendDebugLog","events","forEach","e","listener","addDebugLogListener","processing","message","info","warn","level","jsonEvent","undefined","eventKey","toJson","ajax","type","beforeSend","setRequestHeader","cookie","contentType","always","name","cookieValue","document","cookies","trim","substring","decodeURIComponent","$provide","decorator","serverLogger","$delegate","exception","cause","stack","map","line","Object","debug_log","service","$q","concepts","conceptsPromise","userStats","userStatsPromise","_getConcepts","concept","tags_raw","tags","tag","_getUserStats","getConcepts","resolve","reject","getUserStats","getFromServer","getConceptsWithTags","then","filtered_concepts","isIn","msg","getConceptByParam","param","found_concept","getConceptByName","getConceptByIdentifier","identifier","getConceptByQuery","query","getUserStatsBulk","users","params","JSON","stringify","$cookies","queue","deferredQuestion","promiseResolvedTmp","currentQuestion","answerQueue","current","setId","summary","contexts","loadingQuestions","initSet","configName","flushAnswerQueue","set_length","question_queue_size_max","question_queue_size_min","save_answer_immediately","cache_context","setFilter","clearQueue","questions","answers","correct","count","extend","getCurrent","saveAnswer","answer","forceSave","time","Date","now","flashcard_id","flashcard_answered_id","time_gap","Math","round","defaults","headers","post","csrftoken","_getFilter","saveAnswerToCurrentQuestion","answeredId","responseTime","meta","extra","response_time","answer_class","payload","id","question_type","task_instance_id","client_meta","practice_meta","options","option_ids","o","getQuestion","defer","_resolvePromise","promise","preloadQuestions","_loadQuestions","getQuestionQueue","getAnswerQueue","getSummary","s","min","question","limit","avoid","item_id","request_in_set","concat","_loadContexts","context_id","context","cache","shift","ignore","Array","without_contexts","filters","addGroup","language","addGroupParams","getToPracticeCounts","getStats","mastered","username","getStatsPost","clean","getGroups","status","logged","loading","user","update","sessionUpdated","init","signup","_resetError","_processUser","signupParams","email","pass","pass2","firstName","lastName","password","password_check","first_name","last_name","getUserProfile","stats","loadUser","processUser","profile","send_emails","public","updateSession","login","logout","clearObj","prop","loadUserFromJS","scope","$apply","loadSession","session","locale","navigator","userLanguage","browserLanguage","display_height","innerHeight","display_width","innerWidth","time_zone","jstz","determine","err","updateProfile","loginGoogle","_openPopup","loginFacebook","loginEdookit","next","settings","open","updateClasses","classes","cls","owner","owner_of","createClass","code","joinClass","member_of","createStudent","members","loginStudent","student","controller","$scope","$timeout","date","opened","maximized","loggingOpened","abTestingOpened","flashcardsLimit","unshift","$watch","n","addToOverride","keys","k","openABTesting","abExperiment","filter_column","filter_value","learning_curve_length","setups","setup","values","variables","variable_id","drawABTestingBar","getFlashcardFilterParams","flashcardsCategories","categories","flashcardsContexts","flashcardsTypes","types","showFlashcardsPractice","flashcardsAnswers","getElementById","innerHTML","showFlashcardsAnswers","column","google","visualization","DataTable","addColumn","role","addRows","number_of_answers","confidence_interval","max","number_of_users","returning_chance","view","title","columns","DataView","setColumns","chart","ColumnChart","legend","position","vAxis","format","width","height","intervals","styel","pointSize","barWidth","lineWidth","chartArea","draw","drawABTestingLearning","all_users","learning_curve_accessor","rows","row","LineChart","hAxis","style","fillOpacity","curveType","showAuditChart","auditLimit","auditUser","auditPrimary","auditSecondary","auditKey","reverse","record","formatter","NumberFormat","fractionDigits","pattern","recommendUser","recommendationRegisterMin","register_min","recommendationRegisterMax","register_max","recommendationAnswersMin","number_of_answers_min","recommendationAnswersMax","number_of_answers_max","recommendationSuccessMin","success_min","recommendationSuccessMax","success_max","recommendationVariableName","variable_name","recommendationVariableMin","variable_min","recommendationVariableMax","variable_max","recommendationOutput","directive","restrict","templateUrl","run","$templateCache","$$csp","element","find","prepend"],"mappings":"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","sourcesContent":["/*\n * proso-apps-js\n * Version: 1.0.0 - 2016-07-08\n * License: MIT\n */\nangular.module(\"proso.apps\", [\"proso.apps.tpls\", \"proso.apps.common-config\",\"proso.apps.common-logging\",\"proso.apps.concept-concept\",\"proso.apps.models-practice\",\"proso.apps.models-userStats\",\"proso.apps.user-user\", \"proso.apps.common-toolbar\"])\nangular.module(\"proso.apps.tpls\", [\"templates/common-toolbar/toolbar.html\"]);\nangular.module(\"proso.apps.gettext\", [])\n.value(\"gettext\", window.gettext || function(x){return x;})\n.filter(\"trans\", [\"gettext\", function(gettext) {\n return function(msgid) {\n return gettext(msgid);\n };\n}]);\nvar configServiceLoaded;\nif (configServiceLoaded){\n throw \"ConfigService already loaded\";\n}\nconfigServiceLoaded = true;\n\nfunction obj2get(obj, prefix, ignore_prefix_keys){\n var str = \"\";\n for (var key in obj) {\n if (obj.hasOwnProperty(key)) {\n if (str !== \"\") {\n str += \"&\";\n }\n if (ignore_prefix_keys.indexOf(key) === -1){\n str += prefix;\n }\n str += key + \"=\" + encodeURIComponent(obj[key]);\n }\n }\n return str;\n}\n\nvar m = angular.module('proso.apps.common-config', ['ngCookies']);\n\nm.factory(\"configService\", [\"$http\", \"$window\", \"$cookieStore\", function($http, $window, $cookieStore){\n if (!!$window.configService){\n return $window.configService;\n }\n\n var self = this;\n var config = null;\n\n self.getConfig = function (appName, key, defaultValue) {\n var variable = null;\n if (typeof overridden[appName + \".\" + key] !== 'undefined') {\n variable = overridden[appName + \".\" + key];\n if (self.isDebug()) {\n console.log(appName + \".\" + key, \"overridden\", variable);\n }\n return variable;\n }\n\n if (config === null) {\n console.error(\"Config not loaded\");\n return;\n }\n\n variable = config[appName];\n var path = key.split(\".\");\n for (var i = 0; i < path.length; i++) {\n if (typeof variable === 'undefined') {\n if (self.isDebug()) {\n console.log(appName + \".\" + key, \"use default\", defaultValue);\n }\n return defaultValue;\n }\n variable = variable[path[i]];\n }\n if (typeof variable === 'undefined') {\n if (self.isDebug()) {\n console.log(appName + \".\" + key, \"use default\", defaultValue);\n }\n return defaultValue;\n }\n if (self.isDebug()) {\n console.log(appName + \".\" + key, \"from config\", variable);\n }\n return variable;\n };\n\n self.isDebug = function() {\n return overridden.debug === true;\n };\n\n self.loadConfig = function () {\n return $http.get(\"/common/config/\")\n .success(function (response) {\n self.processConfig(response.data);\n })\n .error(function () {\n console.error(\"Problem while loading config from server\");\n });\n };\n\n self.processConfig = function (data) {\n config = angular.copy(data);\n };\n\n self.override = function (key, value) {\n if (value === 'true') {\n value = true;\n } else if (value === 'false') {\n value = false;\n } else if ($.isNumeric(value)) {\n value = parseFloat(value);\n }\n overridden[key] = value;\n $cookieStore.put(\"configService:overridden\", overridden);\n };\n\n self.removeOverridden = function (key) {\n delete overridden[key];\n $cookieStore.put(\"configService:overridden\", overridden);\n };\n\n self.resetOverridden = function () {\n overridden = {};\n $cookieStore.put(\"configService:overridden\", overridden);\n };\n\n self.getOverridden = function () {\n return angular.copy(overridden);\n };\n\n var overridden = $cookieStore.get(\"configService:overridden\") || {};\n $window.configService = self;\n return self;\n}]);\n\nm.config(['$httpProvider', function($httpProvider) {\n var configService;\n $httpProvider.interceptors.push(function($injector){\n return {\n request: function(config){\n if (!$injector.has('configService')) {\n console.log('There is no configuration service available.');\n return config;\n }\n configService = configService || $injector.get(\"configService\");\n if (config.url.split(\"?\")[0].match(/\\.\\w+$/) !== null){\n return config;\n }\n var overridden = obj2get(configService.getOverridden(), \"config.\", [\"user\", \"time\", \"debug\"]);\n if (overridden === \"\"){\n return config;\n }\n config.url += config.url.indexOf(\"?\") === -1 ? \"?\" : \"&\";\n config.url += overridden;\n return config;\n }\n };\n });\n}]);\n\n\nvar loggingServiceLoaded;\nif (loggingServiceLoaded){\n throw \"LoggingService already loaded\";\n}\nloggingServiceLoaded = true;\n\nvar m = angular.module('proso.apps.common-logging', ['proso.apps.common-config']);\n\nm.factory(\"loggingService\", [\"$window\", function($window) {\n if (!!$window.loggingService){\n return $window.loggingService;\n }\n\n var self = this;\n var debugLog = [];\n var debugLogListeners = [];\n\n self.getDebugLog = function() {\n return debugLog;\n };\n\n self.extendDebugLog = function(url, events) {\n events.forEach(function(e) {\n e.url = url;\n debugLog.push(e);\n });\n debugLogListeners.forEach(function(listener) {\n listener(events);\n });\n };\n\n self.addDebugLogListener = function(listener) {\n debugLogListeners.push(listener);\n };\n\n $window.loggingService = self;\n return self;\n}]);\n\nm.factory(\"serverLogger\", [function() {\n\n var self = this;\n var processing = {};\n\n self.debug = function(message, data) {\n self.log(message, data, \"debug\");\n };\n\n self.info = function(message, data) {\n self.log(message, data, \"info\");\n };\n\n self.warn = function(message, data) {\n self.log(message, data, \"warn\");\n };\n\n self.error = function(message, data) {\n self.log(message, data, \"error\");\n };\n\n self.log = function(message, data, level) {\n var jsonEvent = {\n message: message,\n level: level\n };\n if (data !== undefined) {\n jsonEvent['data'] = data;\n }\n var eventKey = angular.toJson(jsonEvent);\n if (processing[eventKey]) {\n return;\n }\n processing[eventKey] = true;\n $.ajax({\n type: \"POST\",\n url: \"/common/log/\",\n beforeSend: function (request) {\n request.setRequestHeader(\"X-CSRFToken\", self.cookie('csrftoken'));\n },\n contentType: \"application/json\",\n data: angular.toJson(jsonEvent)\n }).always(function() {\n delete processing[eventKey];\n });\n };\n\n self.cookie = function(name) {\n var cookieValue = null;\n if (document.cookie && document.cookie !== '') {\n var cookies = document.cookie.split(';');\n for (var i = 0; i < cookies.length; i++) {\n var cookie = $.trim(cookies[i]);\n // Does this cookie string begin with the name we want?\n if (cookie.substring(0, name.length + 1) === (name + '=')) {\n cookieValue = decodeURIComponent(cookie.substring(name.length + 1));\n break;\n }\n }\n }\n return cookieValue;\n };\n\n return self;\n}]);\n\nm.config([\"$provide\", function($provide) {\n var configService;\n $provide.decorator(\"$exceptionHandler\", [\"serverLogger\", \"$injector\", \"$delegate\", function(serverLogger, $injector, $delegate) {\n return function(exception, cause) {\n configService = configService || $injector.get(\"configService\");\n $delegate(exception, cause);\n if (configService.getConfig(\"proso_common\", \"logging.js_errors\", false)) {\n serverLogger.error(exception.message, {'stack': exception.stack.split('\\n').map(function (line) { return line.trim(); })});\n }\n };\n }]);\n}]);\n\nm.config(['$httpProvider', function($httpProvider) {\n var loggingService;\n $httpProvider.interceptors.push(function($injector) {\n return {\n response: function(response) {\n loggingService = loggingService || $injector.get(\"loggingService\");\n if (response.data instanceof Object && 'debug_log' in response.data) {\n loggingService.extendDebugLog(response.config.url, response.data.debug_log);\n }\n return response;\n }\n };\n });\n}]);\n\nvar m = angular.module('proso.apps.concept-concept', []);\nm.service(\"conceptService\", [\"$http\", \"$q\", function($http, $q) {\n var self = this;\n var concepts = null;\n var conceptsPromise = null;\n var userStats = null;\n var userStatsPromise = null;\n\n var _getConcepts = function () {\n if (conceptsPromise){\n return conceptsPromise;\n }\n conceptsPromise = $http.get(\"/concepts/concepts?all=True\")\n .success(function(response){\n concepts = response.data;\n angular.forEach(concepts, function (concept) {\n concept.tags_raw = [];\n angular.forEach(concept.tags, function (tag) {\n concept.tags_raw.push(tag.type + ':' + tag.value);\n });\n });\n }).error(function(){\n console.error(\"Error while loading concepts from backend\");\n });\n return conceptsPromise;\n };\n\n var _getUserStats = function () {\n if (userStatsPromise){\n return userStatsPromise;\n }\n userStatsPromise = $http.get(\"/concepts/user_stats\")\n .success(function(response){\n userStats = response.data;\n }).error(function(){\n console.error(\"Error while loading user stats from backend\");\n });\n return userStatsPromise;\n };\n\n // get all concepts\n self.getConcepts = function () {\n return $q(function(resolve, reject) {\n if (concepts !== null) {\n resolve(angular.copy(concepts));\n } else {\n _getConcepts()\n .success(function(){\n resolve(angular.copy(concepts));\n }).error(function(){\n reject(\"Error while loading concepts from backend\");\n });\n }\n });\n };\n\n self.getUserStats = function (getFromServer) {\n return $q(function(resolve, reject) {\n if (userStats !== null && !getFromServer ) {\n resolve(angular.copy(userStats));\n } else {\n userStatsPromise = null;\n _getUserStats()\n .success(function(){\n resolve(angular.copy(userStats));\n }).error(function(){\n reject(\"Error while loading userStats from backend\");\n });\n }\n });\n };\n\n // get all concepts containing all provided tags (form 'type:value')\n self.getConceptsWithTags = function (tags) {\n if (typeof tags !== 'object'){\n tags = tags ? [tags] : [];\n }\n return $q(function(resolve, reject) {\n self.getConcepts().then(\n function (concepts) {\n var filtered_concepts = [];\n angular.forEach(concepts, function (concept) {\n var isIn = true;\n angular.forEach(tags, function (tag) {\n if (concept.tags_raw.indexOf(tag) === -1){\n isIn = false;\n }\n });\n if (isIn){\n filtered_concepts.push(concept);\n }\n });\n resolve(filtered_concepts);\n }, function (msg) {\n reject(msg);\n });\n });\n };\n\n var getConceptByParam = function (param, value) {\n return $q(function(resolve, reject) {\n self.getConcepts().then(\n function (concepts) {\n var found_concept = {};\n angular.forEach(concepts, function (concept) {\n if (concept[param] === value){\n found_concept = concept;\n }\n });\n resolve(found_concept);\n }, function (msg) {\n reject(msg);\n });\n });\n };\n\n self.getConceptByName = function (name) {\n return getConceptByParam('name', name);\n };\n\n self.getConceptByIdentifier = function (identifier) {\n return getConceptByParam('identifier', identifier);\n };\n\n self.getConceptByQuery = function (query) {\n return getConceptByParam('identifier', query);\n };\n\n self.getUserStatsBulk = function (users) {\n return $http.get(\"/concepts/user_stats_bulk\", {params: {users: JSON.stringify(users)}});\n };\n}]);\nvar m = angular.module('proso.apps.models-practice', ['ngCookies', 'proso.apps.common-config']);\nm.service(\"practiceService\", [\"$http\", \"$q\", \"configService\", \"$cookies\", function($http, $q, configService, $cookies){\n var self = this;\n\n var queue = [];\n var deferredQuestion = null;\n var promiseResolvedTmp = false;\n var currentQuestion = null;\n var answerQueue = [];\n\n var config = {};\n var current = 0;\n var setId = 0;\n var summary = {};\n\n var contexts = {};\n\n var loadingQuestions = false;\n\n // called on create and set reset\n self.initSet = function(configName){\n self.flushAnswerQueue();\n var key = \"practice.\" + configName + \".\";\n config.set_length = configService.getConfig(\"proso_models\", key + \"set_length\", 10);\n config.question_queue_size_max = configService.getConfig(\"proso_models\", key + \"question_queue_size_max\", 1);\n config.question_queue_size_min = configService.getConfig(\"proso_models\", key + \"question_queue_size_min\", 1);\n config.save_answer_immediately = configService.getConfig(\"proso_models\", key + \"save_answer_immediately\", false);\n config.cache_context = configService.getConfig(\"proso_models\", key + \"cache_context\", false);\n\n self.setFilter({});\n current = 0;\n currentQuestion = null;\n self.clearQueue();\n deferredQuestion = null;\n setId++;\n summary = {\n questions: [],\n answers: [],\n correct: 0,\n count: 0\n };\n };\n\n self.setFilter = function(filter){\n config.filter = {\n filter: [],\n };\n angular.extend(config.filter, filter);\n };\n\n self.getCurrent = function(){\n return current;\n };\n\n self.getConfig = function(){\n return angular.copy(config);\n };\n\n // add answer to queue and upload queued answers if necessary\n self.saveAnswer = function(answer, forceSave){\n if (answer) {\n answer.time = Date.now();\n answerQueue.push(answer);\n summary.answers.push(answer);\n summary.count++;\n if (answer.flashcard_id === answer.flashcard_answered_id) {\n summary.correct++;\n }\n }\n\n if (config.save_answer_immediately || forceSave || current >= config.set_length) {\n if (answerQueue.length > 0) {\n answerQueue.forEach(function(answer){\n answer.time_gap = Math.round((Date.now() - answer.time) / 1000);\n delete answer.time;\n });\n $http.defaults.headers.post['X-CSRFToken'] = $cookies.csrftoken;\n $http.post(\"/models/answer/\", {answers: answerQueue}, {params: _getFilter(['avoid', 'limit'])})\n .error(function (response) {\n console.error(\"Problem while uploading answer\", response);\n });\n answerQueue = [];\n }\n }\n };\n\n self.flushAnswerQueue = function(){\n self.saveAnswer(null, true);\n };\n\n // build answer from current question and save\n self.saveAnswerToCurrentQuestion = function(answeredId, responseTime, meta, extra){\n if (!currentQuestion) {\n console.error(\"There is no current flashcard\");\n return;\n }\n var answer = {\n response_time: responseTime,\n answer_class: currentQuestion.answer_class\n };\n if (currentQuestion.answer_class === \"flashcard_answer\"){\n answer.flashcard_id = currentQuestion.payload.id;\n answer.flashcard_answered_id = answeredId;\n answer.question_type = currentQuestion.question_type;\n }\n if (currentQuestion.answer_class === \"task_answer\"){\n answer.task_instance_id = currentQuestion.payload.id;\n answer.correct = answeredId === currentQuestion.payload.id;\n }\n if (meta) {\n answer.meta = {client_meta: meta};\n }\n if (currentQuestion.practice_meta) {\n if (answer.meta) {\n answer.meta = angular.extend(answer.meta, currentQuestion.practice_meta);\n } else {\n answer.meta = currentQuestion.practice_meta;\n }\n }\n if (currentQuestion.payload.options && currentQuestion.payload.options.length){\n answer.option_ids = [];\n currentQuestion.payload.options.forEach(function(o){\n if (o.id !== currentQuestion.payload.id) {\n answer.option_ids.push(o.id);\n }\n });\n }\n if (extra){\n answer = angular.extend(answer, extra);\n }\n self.saveAnswer(answer);\n };\n\n // return promise of question\n self.getQuestion = function(){\n if(deferredQuestion){\n return $q(function(resolve, reject){\n reject(\"Already one question promised\");\n });\n }\n deferredQuestion = $q.defer();\n promiseResolvedTmp = false;\n _resolvePromise();\n deferredQuestion.promise.then(function(){ deferredQuestion = null;}, function(){ deferredQuestion = null;});\n return deferredQuestion.promise;\n };\n\n self.clearQueue = function(){\n queue = [];\n };\n\n // preload questions\n self.preloadQuestions = function(){\n _loadQuestions();\n };\n\n self.getQuestionQueue = function(){\n return queue;\n };\n\n self.getAnswerQueue = function(){\n return answerQueue;\n };\n\n self.getSummary = function(){\n var s = angular.copy(summary);\n for (var i = 0; i < Math.min(s.questions.length, s.answers.length); i++){\n var answer = s.answers[i];\n var question = s.questions[i];\n if (question.id === answer.flashcard_id){\n question.answer = answer;\n }\n answer.correct = answer.flashcard_id === answer.flashcard_answered_id;\n }\n return s;\n };\n\n\n var _loadQuestions = function(){\n if (loadingQuestions){\n return; // loading request is already running\n }\n\n if (queue.length >= config.question_queue_size_min) { return; } // if there are some questions queued\n config.filter.limit = config.question_queue_size_max - queue.length;\n if (deferredQuestion && !promiseResolvedTmp) { config.filter.limit ++; } // if we promised one question\n config.filter.limit = Math.min(config.filter.limit, config.set_length - current - queue.length); // check size of set\n if (config.filter.limit === 0) {return;} // nothing to do\n config.filter.avoid = currentQuestion && currentQuestion.payload ? [currentQuestion.payload.item_id] : []; // avoid current question\n queue.forEach(function(question){\n config.filter.avoid.push(question.payload.item_id);\n });\n\n var filter = _getFilter();\n var request;\n if (answerQueue.length === 0) {\n request = $http.get(\"/models/practice/\", {params: filter});\n }else{\n $http.defaults.headers.post['X-CSRFToken'] = $cookies.csrftoken;\n request = $http.post(\"/models/practice/\", {answers: answerQueue}, {params: filter});\n answerQueue = [];\n }\n var request_in_set = setId;\n loadingQuestions = true;\n request\n .success(function(response){\n loadingQuestions = false;\n if (request_in_set !== setId) {\n return;\n }\n queue = queue.concat(response.data);\n _loadContexts();\n if (queue.length > 0) {\n _resolvePromise();\n }\n else{\n console.error(\"No Questions to practice\");\n }\n })\n .error(function (response) {\n loadingQuestions = false;\n if (deferredQuestion !== null){\n deferredQuestion.reject(\"Something went wrong while loading questions from backend.\");\n }\n console.error(\"Something went wrong while loading questions from backend.\");\n });\n };\n\n var _loadContexts = function(){\n if (config.cache_context){\n queue.forEach(function(question){\n if (question.payload.context_id in contexts){\n if (contexts[question.payload.context_id] !== \"loading\"){\n question.payload.context = contexts[question.payload.context_id];\n }\n }else{\n contexts[question.payload.context_id] = \"loading\";\n $http.get(\"/flashcards/context/\" + question.payload.context_id, {cache: true})\n .success(function(response){\n contexts[question.payload.context_id] = response.data;\n _resolvePromise();\n }).error(function(){\n delete contexts[question.payload.context_id];\n console.error(\"Error while loading context from backend\");\n });\n }\n });\n }\n };\n\n var _resolvePromise = function(){\n if (deferredQuestion === null){\n return;\n }\n if (config.set_length === current){\n deferredQuestion.reject(\"Set was completed\");\n return;\n }\n if (queue.length > 0) {\n if (config.cache_context){\n if (typeof contexts[queue[0].payload.context_id] === 'object'){\n queue[0].payload.context = contexts[queue[0].payload.context_id];\n }else{\n return;\n }\n }\n currentQuestion = queue.shift();\n current++;\n promiseResolvedTmp = true;\n summary.questions.push(currentQuestion);\n deferredQuestion.resolve(currentQuestion);\n }\n _loadQuestions();\n };\n\n var _getFilter = function(ignore) {\n if (!ignore) {\n ignore = [];\n }\n var filter = {};\n for (var key in config.filter){\n if (ignore.indexOf(key) !== -1) {\n continue;\n }\n if (config.filter[key] instanceof Array) {\n filter[key] = JSON.stringify(config.filter[key]);\n }else{\n filter[key] = config.filter[key];\n }\n }\n if (config.cache_context){\n filter.without_contexts = 1;\n }\n return filter;\n };\n}]);\n\nvar m = angular.module('proso.apps.models-userStats', ['ngCookies']);\nm.service(\"userStatsService\", [\"$http\", \"$cookies\", function($http, $cookies){\n var self = this;\n\n var filters = {\n filters: {},\n };\n\n self.addGroup = function (id, data) {\n if (!data.language){\n delete data.language;\n }\n filters.filters[id] = data;\n };\n\n self.addGroupParams = function (id, filter, language) {\n filters.filters[id] = filter;\n if (typeof language !== \"undefined\"){\n filters.language = language;\n }\n };\n\n self.getToPracticeCounts = function(){\n $http.defaults.headers.post['X-CSRFToken'] = $cookies.csrftoken;\n return $http.post(\"/models/to_practice_counts/\", filters, {cache: true});\n };\n\n self.getStats = function(mastered, username){\n $http.defaults.headers.post['X-CSRFToken'] = $cookies.csrftoken;\n var params = {filters: JSON.stringify(filters.filters)};\n if (mastered){\n params.mastered = true;\n }\n if (username){\n params.username = username;\n }\n return $http.get(\"/models/user_stats/\", {params: params});\n };\n\n self.getStatsPost = function(mastered, username){\n $http.defaults.headers.post['X-CSRFToken'] = $cookies.csrftoken;\n var params = \"?\";\n params += mastered ? \"&mastered=true\" : \"\";\n params += username ? \"&username=\"+username : \"\";\n return $http.post(\"/models/user_stats/\" + params, filters);\n };\n\n self.clean = function(){\n filters = {\n filters: {},\n };\n };\n\n self.getGroups = function (){\n return angular.copy(filters);\n };\n\n}]);\n\nvar m = angular.module('proso.apps.user-user', ['ngCookies']);\nm.service(\"userService\", [\"$http\", function($http){\n var self = this;\n self.status = {\n \"logged\": false,\n \"loading\": false\n };\n self.user = {};\n var update = this.update = {};\n var sessionUpdated = false;\n self.error = {};\n\n // called on create\n self.init = function (){\n };\n\n self.signup = function(data){\n self.status.loading = true;\n _resetError();\n var promise = $http.post(\"/user/signup/\", data);\n promise.success(function(response){\n _processUser(response.data);\n })\n .error(function(response){\n self.error = response;\n })\n .finally(function(response){\n self.status.loading = false;\n });\n return promise;\n };\n\n self.signupParams = function(name, email, pass, pass2, firstName, lastName){\n return self.signup({\n \"username\": name,\n \"email\": email,\n \"password\": pass,\n \"password_check\": pass2,\n \"first_name\": firstName,\n \"last_name\": lastName\n });\n };\n\n // get public user profile from backend\n self.getUserProfile = function(username, stats){\n var params = {username: username};\n if (stats){\n params.stats = true;\n }\n return $http.get(\"/user/profile/\", {params: params});\n };\n\n // get user profile from backend\n self.loadUser = function(stats){\n self.status.loading = true;\n var params = {};\n if (stats){\n params.stats = true;\n }\n return $http.get(\"/user/profile/\", {params: params})\n .success(function(response){\n _processUser(response.data);\n })\n .finally(function(response){\n self.status.loading = false;\n });\n };\n\n self.processUser = function(data){\n _processUser(angular.copy(data));\n };\n\n // process user data\n var _processUser = function(data){\n if (!data) {\n self.status.logged = false;\n return;\n }\n self.status.logged = data.user && data.user.email !== undefined;\n self.user.profile = data;\n angular.extend(self.user, data.user);\n angular.extend(update, {\n user: {\n first_name: self.user.first_name,\n last_name: self.user.last_name\n },\n send_emails: self.user.profile.send_emails,\n public: self.user.profile.public\n });\n delete self.user.profile.user;\n if (!sessionUpdated){\n self.updateSession();\n sessionUpdated = true;\n }\n };\n\n self.login = function(username, pass){\n self.status.loading = true;\n _resetError();\n var promise = $http.post(\"/user/login/\", {\n username: username,\n password: pass\n });\n promise.success(function(response){\n _processUser(response.data);\n })\n .error(function(response){\n self.error = response;\n })\n .finally(function(response){\n self.status.loading = false;\n });\n return promise;\n };\n\n self.logout = function(){\n self.status.loading = true;\n $http.get(\"/user/logout/\")\n .success(function(response){\n clearObj(self.user);\n self.status.logged = false;\n })\n .finally(function(response){\n self.status.loading = false;\n });\n };\n\n\n var _resetError = function(){\n clearObj(self.error);\n };\n\n var clearObj = function(obj){\n for (var prop in obj) {\n if (obj.hasOwnProperty(prop)){ delete obj[prop]; }\n }\n };\n\n\n self.loadUserFromJS = function (scope, stats) {\n scope.$apply(self.loadUser(stats));\n };\n\n self.loadSession = function(){\n self.status.loading = true;\n $http.get(\"/user/session/\")\n .success(function(response){\n self.user.session = response.data;\n })\n .finally(function(response){\n self.status.loading = false;\n });\n };\n\n self.updateSession = function(){\n var data = {\n locale: window.navigator.language || window.navigator.userLanguage || window.navigator.browserLanguage,\n display_height: window.innerHeight,\n display_width: window.innerWidth\n };\n try{\n data.time_zone = jstz.determine().name();\n }catch (err){ console.log(\"JSTimeZone lib not loaded\");}\n $http.post(\"/user/session/\", data).error(function(){\n console.error(\"Error while updating session\");\n });\n };\n\n self.updateProfile = function(user){\n var data = {\n user: {},\n };\n if (user.profile) {\n angular.extend(data, user.profile);\n }\n angular.extend(data.user, user);\n delete data.user.profile;\n delete data.user.username;\n\n self.status.loading = true;\n _resetError();\n var promise = $http.post(\"/user/profile/\", data);\n promise.success(function(response){\n _processUser(response.data);\n })\n .error(function(response){\n self.error = response;\n }).finally(function(response){\n self.status.loading = false;\n });\n return promise;\n };\n\n self.loginGoogle = function() {\n _openPopup('/login/google-oauth2/', '/user/close_popup/');\n };\n\n self.loginFacebook = function() {\n _openPopup('/login/facebook/', '/user/close_popup/');\n };\n\n self.loginEdookit = function() {\n _openPopup('/login/edookit/', '/user/close_popup/');\n };\n\n var _openPopup = function(url, next){\n var settings = 'height=700,width=700,left=100,top=100,resizable=yes,scrollbars=yes,toolbar=no,menubar=no,location=yes,directories=no,status=yes';\n url += \"?next=\" + next;\n window.open(url, \"popup\", settings);\n };\n\n self.init();\n\n self.updateClasses = function(){\n self.status.loading = true;\n _resetError();\n var promise = $http.get(\"/user/classes/\");\n promise.success(function(response){\n var classes = response.data;\n angular.forEach(classes, function (cls) {\n delete cls.owner;\n });\n self.user.profile.owner_of = classes;\n })\n .error(function(response){\n self.error = response;\n })\n .finally(function(response){\n self.status.loading = false;\n });\n return promise;\n };\n\n self.createClass = function(name, code){\n self.status.loading = true;\n _resetError();\n var promise = $http.post(\"/user/create_class/\", {\n name: name,\n code: code\n });\n promise.success(function(response){\n var cls = response.data;\n delete cls.owner;\n self.user.profile.owner_of.push(cls);\n })\n .error(function(response){\n self.error = response;\n })\n .finally(function(response){\n self.status.loading = false;\n });\n return promise;\n };\n\n self.joinClass = function (code) {\n self.status.loading = true;\n _resetError();\n var promise = $http.post(\"/user/join_class/\", {\n code: code\n });\n promise.success(function(response){\n self.user.profile.member_of.push(response.data);\n })\n .error(function(response){\n self.error = response;\n })\n .finally(function(response){\n self.status.loading = false;\n });\n return promise;\n };\n\n self.createStudent = function(data){\n self.status.loading = true;\n _resetError();\n var promise = $http.post(\"/user/create_student/\", data);\n promise.success(function(response){\n angular.forEach(self.user.profile.owner_of, function (cls) {\n if (cls.id === data.class){\n cls.members.push(response.data);\n }\n });\n })\n .error(function(response){\n self.error = response;\n })\n .finally(function(response){\n self.status.loading = false;\n });\n return promise;\n };\n\n self.loginStudent = function (id) {\n self.status.loading = true;\n _resetError();\n var promise = $http.post(\"/user/login_student/\", {\n student: id\n });\n promise.success(function(response){\n _processUser(response.data);\n })\n .error(function(response){\n self.error = response;\n })\n .finally(function(response){\n self.status.loading = false;\n });\n return promise;\n };\n\n}]);\n\nvar m = angular.module('proso.apps.common-toolbar', ['ngCookies', 'proso.apps.common-config']);\n\nm.controller(\"ToolbarController\", ['$scope', '$cookies', 'configService', 'loggingService', '$timeout', '$http', function($scope, $cookies, configService, loggingService, $timeout, $http) {\n $scope.override = configService.override;\n $scope.removeOverridden = configService.removeOverridden;\n $scope.date = new Date();\n $scope.debugLog = [];\n $scope.opened = $cookies[\"toolbar:opened\"] === \"true\";\n $scope.maximized = $cookies[\"toolbar:maximized\"] === \"true\";\n $scope.loggingOpened = true;\n $scope.abTestingOpened = false;\n $scope.flashcardsLimit = 10;\n $scope.override('debug', true);\n $scope.overridden = configService.getOverridden();\n loggingService.addDebugLogListener(function(events) {\n $timeout(function(){\n events.forEach(function (e) {\n $scope.debugLog.unshift(e);\n });\n });\n });\n\n $scope.$watch(\"opened\", function(n, o){\n $cookies[\"toolbar:opened\"] = n;\n });\n\n $scope.$watch(\"maximized\", function(n, o){\n $cookies[\"toolbar:maximized\"] = n;\n });\n\n $scope.addToOverride = function(name) {\n if (!name) {\n return;\n }\n configService.override(name, '');\n };\n\n $scope.getOverridden = function() {\n var overridden = configService.getOverridden();\n Object.keys(overridden).filter(function(k) {\n return (k === 'user' || k === 'debug' || k === 'time');\n }).forEach(function (k) {\n delete overridden[k];\n });\n return overridden;\n };\n\n $scope.openABTesting = function() {\n $scope.abTestingOpened = ! $scope.abTestingOpened;\n if ($scope.abTestingOpened && !$scope.abExperiment) {\n $http.get('/configab/experiments', {params: {filter_column: 'is_enabled', filter_value: true, stats: true, learning_curve_length: 5}})\n .success(function(response) {\n var data = response.data;\n if (data.length === 0) {\n return;\n }\n $scope.abExperiment = data[0];\n $scope.abExperiment.setups.forEach(function(setup) {\n setup.values.forEach(function(value) {\n $scope.abExperiment.variables.forEach(function(variable) {\n if (variable.id = value.variable_id) {\n value.variable = variable;\n }\n });\n });\n });\n $scope.drawABTestingBar();\n });\n }\n $scope.drawABTestingBar();\n };\n \n var getFlashcardFilterParams = function(){\n var params = {\n limit: $scope.flashcardsLimit\n };\n if ($scope.flashcardsCategories) {\n params.categories = JSON.stringify(\n $scope.flashcardsCategories.split(',').map(function(x) { return x.trim(); })\n );\n }\n if ($scope.flashcardsContexts) {\n params.contexts = JSON.stringify(\n $scope.flashcardsContexts.split(',').map(function(x) { return x.trim(); })\n );\n }\n if ($scope.flashcardsTypes) {\n params.types = JSON.stringify(\n $scope.flashcardsTypes.split(',').map(function(x) { return x.trim(); })\n );\n }\n return params;\n };\n\n $scope.showFlashcardsPractice = function() {\n $scope.flashcardsAnswers = [];\n var params = getFlashcardFilterParams();\n\n $http.get('/flashcards/practice_image', {params: params}).success(function(response) {\n document.getElementById(\"flashcardsChart\").innerHTML = response;\n });\n };\n\n $scope.showFlashcardsAnswers = function() {\n var params = getFlashcardFilterParams();\n\n document.getElementById(\"flashcardsChart\").innerHTML = '';\n $http.get('/flashcards/answers', {params: params}).success(function(response) {\n $scope.flashcardsAnswers = response.data;\n });\n };\n\n $scope.drawABTestingBar = function(column) {\n if (!$scope.abExperiment) {\n return;\n }\n var data = new google.visualization.DataTable();\n data.addColumn('string', 'Experiment Setup');\n data.addColumn('number', 'Number of Answers');\n data.addColumn({type: 'number', role: 'interval'});\n data.addColumn({type: 'number', role: 'interval'});\n data.addColumn('number', 'Number of Users');\n data.addColumn('number', 'Returning Chance');\n data.addColumn({type: 'number', role: 'interval'});\n data.addColumn({type: 'number', role: 'interval'});\n data.addRows($scope.abExperiment.setups.map(function(setup) {\n return [\n 'Setup #' + setup.id,\n setup.stats.number_of_answers.value,\n setup.stats.number_of_answers.confidence_interval.min,\n setup.stats.number_of_answers.confidence_interval.max,\n setup.stats.number_of_users,\n setup.stats.returning_chance.value,\n setup.stats.returning_chance.confidence_interval.min,\n setup.stats.returning_chance.confidence_interval.max,\n ];\n }));\n var view = data;\n var title = 'All';\n if (column) {\n var columns = {\n number_of_answers: [0, 1, 2, 3],\n number_of_users: [0, 4],\n returning_chance: [0, 5, 6, 7],\n };\n title = column;\n view = new google.visualization.DataView(data);\n view.setColumns(columns[column]);\n }\n var chart = new google.visualization.ColumnChart(document.getElementById(\"abChart\"));\n var options = {\n title: title,\n legend: {\n position: 'none'\n },\n vAxis: {\n format: '#.###'\n },\n width: 480,\n height: 300,\n intervals: {\n styel: 'bars',\n pointSize: 10,\n barWidth: 0,\n lineWidth: 4,\n },\n chartArea: {'width': '80%', 'height': '80%'}\n };\n chart.draw(view, options);\n };\n\n $scope.drawABTestingLearning = function(all_users) {\n if (!$scope.abExperiment) {\n return;\n }\n var learning_curve_accessor = 'learning_curve';\n if (all_users) {\n learning_curve_accessor = 'learning_curve_all_users';\n }\n var data = new google.visualization.DataTable();\n data.addColumn({type: 'number', role: 'domain'});\n var length = 0;\n $scope.abExperiment.setups.forEach(function(setup) {\n data.addColumn('number', 'Setup #' + setup.id);\n data.addColumn({type: 'number', role: 'interval'});\n data.addColumn({type: 'number', role: 'interval'});\n length = Math.max(setup.stats[learning_curve_accessor].success.length);\n });\n var rows = [];\n for (var i = 0; i < length; i++) {\n var row = [i];\n /*jshint -W083 */\n $scope.abExperiment.setups.forEach(function(setup) {\n row.push(setup.stats[learning_curve_accessor].success[i].value);\n row.push(setup.stats[learning_curve_accessor].success[i].confidence_interval.min);\n row.push(setup.stats[learning_curve_accessor].success[i].confidence_interval.max);\n });\n rows.push(row);\n }\n data.addRows(rows);\n var chart = new google.visualization.LineChart(document.getElementById(\"abChart\"));\n var options = {\n title: 'Learning',\n legend: {\n position: 'none'\n },\n vAxis: {\n format: '#.###'\n },\n hAxis: {\n title: 'Attempt',\n position: 'center'\n },\n intervals: {\n style: 'area',\n fillOpacity: 0.2\n },\n lineWidth: 4,\n pointSize: 10,\n curveType: 'function',\n width: 480,\n height: 300,\n 'chartArea': {'width': '80%', 'height': '80%'}\n };\n chart.draw(data, options);\n };\n\n $scope.showAuditChart = function() {\n var params = {};\n if ($scope.auditLimit) {\n params['limit'] = $scope.auditLimit;\n }\n if ($scope.auditUser) {\n params['user'] = $scope.auditUser;\n }\n if ($scope.auditPrimary) {\n params['item'] = $scope.auditPrimary;\n }\n if ($scope.auditSecondary) {\n params['item_secondary'] = $scope.auditSecondary;\n }\n $http.get(\"/models/audit/\" + $scope.auditKey, {params: params})\n .success(function(response) {\n var data = new google.visualization.DataTable();\n data.addColumn('number', 'Update');\n data.addColumn('number', 'Value');\n data.addColumn({type: 'datetime', role: 'tooltip'});\n response.data.reverse();\n var rows = [];\n for (var i = 0; i < response.data.length; i++) {\n var record = response.data[i];\n rows.push([i, record.value, new Date(record.time)]);\n }\n data.addRows(rows);\n var options = {\n title: $scope.auditKey,\n legend: {\n position: 'none'\n },\n vAxis: {\n format: '#.###'\n },\n hAxis: {\n title: 'Update',\n position: 'center'\n },\n width: 480,\n height: 300,\n 'chartArea': {'width': '80%', 'height': '80%'}\n };\n var formatter = new google.visualization.NumberFormat({\n fractionDigits: 3, pattern: '#.###'\n });\n formatter.format(data, 1);\n var chart = new google.visualization.LineChart(document.getElementById('auditChart'));\n chart.draw(data, options);\n });\n };\n\n $scope.recommendUser = function() {\n var filter = {};\n if ($scope.recommendationRegisterMin) {\n filter.register_min = $scope.recommendationRegisterMin;\n }\n if ($scope.recommendationRegisterMax) {\n filter.register_max = $scope.recommendationRegisterMax;\n }\n if ($scope.recommendationAnswersMin) {\n filter.number_of_answers_min = $scope.recommendationAnswersMin;\n }\n if ($scope.recommendationAnswersMax) {\n filter.number_of_answers_max = $scope.recommendationAnswersMax;\n }\n if ($scope.recommendationSuccessMin) {\n filter.success_min = $scope.recommendationSuccessMin;\n }\n if ($scope.recommendationSuccessMax) {\n filter.success_max = $scope.recommendationSuccessMax;\n }\n if ($scope.recommendationVariableName) {\n filter.variable_name = $scope.recommendationVariableName;\n }\n if ($scope.recommendationVariableMin) {\n filter.variable_min = $scope.recommendationVariableMin;\n }\n if ($scope.recommendationVariableMax) {\n filter.variable_max = $scope.recommendationVariableMax;\n }\n $scope.recommendationOutput = 'Loading...';\n $http.get('/models/recommend_users', {params: filter})\n .success(function (response) {\n if (response.data.length > 0) {\n $scope.recommendationOutput = response.data[0];\n } else {\n $scope.recommendationOutput = 'Not Found';\n }\n });\n };\n\n}]);\n\nm.directive('toolbar', [function () {\n return {\n restrict: 'E',\n controller: 'ToolbarController',\n templateUrl: 'templates/common-toolbar/toolbar.html'\n };\n}]);\n\nangular.module(\"templates/common-toolbar/toolbar.html\", []).run([\"$templateCache\", function($templateCache) {\n $templateCache.put(\"templates/common-toolbar/toolbar.html\",\n \"<div id=\\\"proso-toolbar\\\">\\n\" +\n \" <div id=\\\"config-bar-show-button\\\" ng-click=\\\"opened = !opened\\\" ng-hide=\\\"opened\\\"> proso bar </div>\\n\" +\n \"\\n\" +\n \" <div id=\\\"config-bar\\\" ng-cloak ng-show=\\\"opened\\\" ng-class=\\\"{'maximized' : maximized}\\\">\\n\" +\n \" <div id=\\\"config-bar-header\\\">\\n\" +\n \" <span id=\\\"config-bar-maximize\\\" ng-click=\\\"maximized = !maximized\\\">Maximize</span>\\n\" +\n \" <span id=\\\"config-bar-hide\\\" ng-click=\\\"opened = !opened\\\">Close</span>\\n\" +\n \" </div>\\n\" +\n \" <ul id=\\\"config-bar-content\\\">\\n\" +\n \" <li>\\n\" +\n \" <span ng-click=\\\"addToOverride(propertyToOverride)\\\" class=\\\"add-to-override\\\">+</span>\\n\" +\n \" <input type=\\\"text\\\" ng-model=\\\"propertyToOverride\\\" id=\\\"config-bar-property-name\\\" placeholder=\\\"Property Name\\\" />\\n\" +\n \" </li>\\n\" +\n \" <li>\\n\" +\n \" <span ng-click=\\\"removeOverridden('user'); overridden.user = null;\\\" class=\\\"reset\\\">X</span>\\n\" +\n \" <input type=\\\"number\\\" ng-model=\\\"overridden.user\\\" placeholder=\\\"User\\\" ng-change=\\\"override('user', overridden.user)\\\" />\\n\" +\n \" </li>\\n\" +\n \" <li style=\\\"display: none\\\">\\n\" +\n \" <span ng-click=\\\"removeOverridden('time'); overridden.time= null;\\\" class=\\\"reset\\\">X</span>\\n\" +\n \" <input type=\\\"text\\\" ng-model=\\\"overridden.time\\\" placeholder=\\\"Time\\\" ng-change=\\\"override('time', overridden.time)\\\" />\\n\" +\n \" <i>{{date | date:'yyyy-MM-dd_HH:mm:ss'}}</i>\\n\" +\n \" </li>\\n\" +\n \" <li ng-repeat=\\\"(name, value) in getOverridden() track by name\\\">\\n\" +\n \" <span class=\\\"reset\\\" ng-click=\\\"removeOverridden(name)\\\">X</span>\\n\" +\n \" <input type=\\\"text\\\" disabled class=\\\"property-name\\\" ng-model=\\\"name\\\" />\\n\" +\n \" <input type=\\\"text\\\" class=\\\"property-value\\\" placeholder=\\\"Value\\\" ng-model=\\\"value\\\" ng-change=\\\"override(name, value)\\\" />\\n\" +\n \" </li>\\n\" +\n \" <div class='section' ng-click=\\\"openABTesting()\\\">AB Testing <span id=\\\"abExperimentName\\\">{{abExperiment.identifier }}</span></div>\\n\" +\n \" <ul id=\\\"config-bar-ab\\\" ng-cloak ng-show=\\\"abTestingOpened\\\">\\n\" +\n \" <li>\\n\" +\n \" <ul id=\\\"abSetupInfo\\\">\\n\" +\n \" <li ng-repeat=\\\"setup in abExperiment.setups\\\">\\n\" +\n \" <strong class=\\\"setup-id\\\">#{{ setup.id }}</strong>\\n\" +\n \" <ul>\\n\" +\n \" <li ng-repeat=\\\"value in setup.values\\\">\\n\" +\n \" <span class=\\\"variable-name\\\" title=\\\"{{ value.variable.app_name }}.{{ value.variable.name }} \\\">\\n\" +\n \" {{ value.variable.name.split('.').slice(-1)[0] | limitTo: 12 }}{{ value.variable.name.split('.').slice(-1)[0].length > 12 ? '...' : '' }}\\n\" +\n \" </span>\\n\" +\n \" <span class=\\\"variable-value\\\" title=\\\"{{ value.value }}\\\">{{ value.value.split('.').slice(-1)[0] | limitTo: 12 }} {{ value.value.split('.').slice(-1)[0].length > 12 ? '...' : '' }}</span>\\n\" +\n \" <span class=\\\"comma\\\" ng-if=\\\"!$last\\\">,</a>\\n\" +\n \" </li>\\n\" +\n \" </ul>\\n\" +\n \" </li>\\n\" +\n \" </ul>\\n\" +\n \" <li>\\n\" +\n \" <div id=\\\"abChart\\\"></div>\\n\" +\n \" <li>\\n\" +\n \" <button ng-click=\\\"drawABTestingBar()\\\" class=\\\"ab-experiment-chart-button\\\">All</button>\\n\" +\n \" <button ng-click=\\\"drawABTestingBar('number_of_users')\\\" class=\\\"ab-experiment-chart-button\\\">Users</button>\\n\" +\n \" <button ng-click=\\\"drawABTestingBar('number_of_answers')\\\" class=\\\"ab-experiment-chart-button\\\">Answers</button>\\n\" +\n \" <button ng-click=\\\"drawABTestingBar('returning_chance')\\\" class=\\\"ab-experiment-chart-button\\\">Return</button>\\n\" +\n \" <button ng-click=\\\"drawABTestingLearning(false)\\\" class=\\\"ab-experiment-chart-button\\\" title=\\\"Learning curve containing only users with at least the given number of testing answers\\\">Learn</button>\\n\" +\n \" <button ng-click=\\\"drawABTestingLearning(true)\\\" class=\\\"ab-experiment-chart-button\\\" title=\\\"Learning curve containing all users with at least one testing answer\\\">Learn (A)</button>\\n\" +\n \" </li>\\n\" +\n \" </ul>\\n\" +\n \" <div class='section' ng-click=\\\"flashcardsOpened = !flashcardsOpened\\\">Flashcards</div>\\n\" +\n \" <ul id=\\\"config-bar-flashcards\\\" ng-cloak ng-show=\\\"flashcardsOpened\\\">\\n\" +\n \" <li>\\n\" +\n \" <input type=\\\"text\\\" ng-model=\\\"flashcardsCategories\\\" placeholder=\\\"Categories\\\" />\\n\" +\n \" <input type=\\\"text\\\" ng-model=\\\"flashcardsContexts\\\" placeholder=\\\"Contexts\\\" />\\n\" +\n \" <input type=\\\"text\\\" ng-model=\\\"flashcardsTypes\\\" placeholder=\\\"Types\\\" />\\n\" +\n \" </li>\\n\" +\n \" <li>\\n\" +\n \" <input type=\\\"text\\\" ng-model=\\\"flashcardsLimit\\\" placeholder=\\\"Limit\\\" />\\n\" +\n \" <button ng-click=\\\"showFlashcardsPractice()\\\">Show Practice</button>\\n\" +\n \" <button ng-click=\\\"showFlashcardsAnswers()\\\">Show Answers</button>\\n\" +\n \" </li>\\n\" +\n \" <div style=\\\"overflow: auto; width: 100%; height: 300px;\\\">\\n\" +\n \" <table ng-show=\\\"flashcardsAnswers.length > 0\\\" id=\\\"flashcardsAnswers\\\">\\n\" +\n \" <thead>\\n\" +\n \" <tr>\\n\" +\n \" <th>#</th>\\n\" +\n \" <th>User</th>\\n\" +\n \" <th>Item</th>\\n\" +\n \" <th>Asked</th>\\n\" +\n \" <th>Answered</th>\\n\" +\n \" <th>Opt.</th>\\n\" +\n \" </tr>\\n\" +\n \" </thead>\\n\" +\n \" <tbody>\\n\" +\n \" <tr ng-repeat=\\\"answer in flashcardsAnswers\\\">\\n\" +\n \" <td>\\n\" +\n \" <a href=\\\"/flashcards/answer/{{ answer.id }}?html\\\" title=\\\"{{answer.time | date:'yyyy-MM-dd_HH:mm:ss'}}, direction: {{ answer.direction }}\\\">\\n\" +\n \" {{ answer.id }}\\n\" +\n \" </a>\\n\" +\n \" </td>\\n\" +\n \" <td>{{ answer.user_id }}</td>\\n\" +\n \" <td>{{ answer.item_asked_id }}</td>\\n\" +\n \" <td>{{ answer.flashcard_asked.identifier | limitTo:12 }} {{ answer.flashcard_answered.identifier.length > 12 ? '...' : '' }}</td>\\n\" +\n \" <td ng-class=\\\"{true: 'correct', false: 'wrong'}[answer.item_asked_id == answer.item_answered_id]\\\">\\n\" +\n \" {{ answer.flashcard_answered.identifier | limitTo:12 }}{{ answer.flashcard_answered.identifier.length > 12 ? '...' : '' }}\\n\" +\n \" </td>\\n\" +\n \" <td class=\\\"direction-{{ answer.direction }}\\\">{{ answer.options.length }}</td>\\n\" +\n \" </tr>\\n\" +\n \" </tbody>\\n\" +\n \" </table>\\n\" +\n \" <div id=\\\"flashcardsChart\\\"></div>\\n\" +\n \" </div>\\n\" +\n \" </ul>\\n\" +\n \" <div class='section' ng-click=\\\"auditOpened = !auditOpened\\\">Models Audit</div>\\n\" +\n \" <ul id=\\\"config-bar-audit\\\" ng-cloak ng-show=\\\"auditOpened\\\">\\n\" +\n \" <li>\\n\" +\n \" <input type=\\\"text\\\" ng-model=\\\"auditLimit\\\" placeholder=\\\"Limit\\\" />\\n\" +\n \" <input type=\\\"text\\\" ng-model=\\\"auditKey\\\" placeholder=\\\"Key\\\" id=\\\"config-bar-audit-key\\\" />\\n\" +\n \" <input type=\\\"text\\\" ng-model=\\\"auditUser\\\" placeholder=\\\"User\\\" />\\n\" +\n \" </li>\\n\" +\n \" <li>\\n\" +\n \" <input type=\\\"text\\\" ng-model=\\\"auditPrimary\\\" placeholder=\\\"Item Primary\\\" />\\n\" +\n \" <input type=\\\"text\\\" ng-model=\\\"auditSecondary\\\" placeholder=\\\"Item Secondary\\\" />\\n\" +\n \" <button ng-click=\\\"showAuditChart()\\\">Show Chart</button>\\n\" +\n \" </li>\\n\" +\n \" <div id=\\\"auditChart\\\"></div>\\n\" +\n \" </ul>\\n\" +\n \" <div class='section' ng-click=\\\"recommendationOpened = !recommendationOpened\\\">Recommend User</div>\\n\" +\n \" <ul id=\\\"config-bar-recommendation\\\" ng-cloak ng-show=\\\"recommendationOpened\\\">\\n\" +\n \" <li>\\n\" +\n \" <input type=\\\"text\\\" placeholder=\\\"Register Time\\\" disabled/>\\n\" +\n \" <input type=\\\"text\\\" placeholder=\\\"Min\\\" ng-model=\\\"recommendationRegisterMin\\\" />\\n\" +\n \" <input type=\\\"text\\\" placeholder=\\\"Max\\\" ng-model=\\\"recommendationRegisterMax\\\" />\\n\" +\n \" </li>\\n\" +\n \" <li>\\n\" +\n \" <input type=\\\"text\\\" placeholder=\\\"Number of Answers\\\" disabled/>\\n\" +\n \" <input type=\\\"text\\\" placeholder=\\\"Min\\\" ng-model=\\\"recommendationAnswersMin\\\" />\\n\" +\n \" <input type=\\\"text\\\" placeholder=\\\"Max\\\" ng-model=\\\"recommendationAnswersMax\\\" />\\n\" +\n \" </li>\\n\" +\n \" <li>\\n\" +\n \" <input type=\\\"text\\\" placeholder=\\\"Success\\\" disabled/>\\n\" +\n \" <input type=\\\"text\\\" placeholder=\\\"Min\\\" ng-model=\\\"recommendationSuccessMin\\\" />\\n\" +\n \" <input type=\\\"text\\\" placeholder=\\\"Max\\\" ng-model=\\\"recommendationSuccessMax\\\" />\\n\" +\n \" </li>\\n\" +\n \" <li>\\n\" +\n \" <input type=\\\"text\\\" placeholder=\\\"Variable Name\\\" ng-model=\\\"recommendationVariableName\\\" />\\n\" +\n \" <input type=\\\"text\\\" placeholder=\\\"Min\\\" ng-model=\\\"recommendationVariableMin\\\" />\\n\" +\n \" <input type=\\\"text\\\" placeholder=\\\"Max\\\" ng-model=\\\"recommendationVariableMax\\\" />\\n\" +\n \" </li>\\n\" +\n \" <li>\\n\" +\n \" <input type=\\\"text\\\" ng-model=\\\"recommendationOutput\\\" disabled />\\n\" +\n \" <button ng-click=\\\"recommendUser()\\\">Recommend</button>\\n\" +\n \" </li>\\n\" +\n \" </ul>\\n\" +\n \" <div class='section' ng-click=\\\"loggingOpened = !loggingOpened\\\">Logging</div>\\n\" +\n \" <ul id=\\\"config-bar-logging\\\" ng-cloak ng-show=\\\"loggingOpened\\\">\\n\" +\n \" <li ng-repeat=\\\"event in debugLog|limitTo:100\\\" class=\\\"logging-event\\\">\\n\" +\n \" <span class=\\\"level\\\">{{ event.level }}</span>\\n\" +\n \" <span class=\\\"url\\\">{{ event.url }}</span>\\n\" +\n \" <span class=\\\"filename\\\">{{ event.filename }}:{{ event.line_number }}</span>\\n\" +\n \" <span class=\\\"message\\\">{{ event.message }}</span>\\n\" +\n \" </li>\\n\" +\n \" </ul>\\n\" +\n \" </ul>\\n\" +\n \" </div>\\n\" +\n \"</div>\\n\" +\n \"\");\n}]);\n!angular.$$csp() && angular.element(document).find('head').prepend('<style type=\"text/css\">#config-bar-show-button{position:fixed;right:-40px;top:250px;width:100px;transform:rotate(-90deg);-webkit-transform:rotate(-90deg);border:solid #808080 1px;margin:0;padding:10px;text-transform:capitalize;font-weight:bold;background-color:rgba(255,255,255,0.8);transition:all 0.2s;cursor:pointer;text-align:center;z-index:1000;}#config-bar-show-button:hover{background-color:#1f8dd6;color:white;}#config-bar{position:fixed;right:0;top:0;bottom:0;width:500px;border-left:solid #808080 1px;background-color:rgba(255,255,255,0.8);z-index:1000;}#config-bar.maximized{width:100%;}#config-bar-header{background-color:rgba(31,141,214,0.8);margin:0;padding:5px 10px;text-align:right;color:white;}#config-bar-content .section{background-color:rgba(31,141,214,0.8);margin:5px 0;padding:5px 10px;color:white;text-transform:uppercase;cursor:pointer;}#config-bar-maximize{text-align:right;cursor:pointer;margin-right:20px;}#config-bar-hide{text-align:right;width:100%;cursor:pointer;}#config-bar-content{margin:0;list-style:none;padding:0;}#config-bar-content > li{border-bottom:1px dashed #E9F4FB;padding:5px 10px;margin:0;}#config-bar-content > li:hover{background:#E9F4FB;}#config-bar-content .reset,#config-bar-content .add-to-override{cursor:pointer;font-weight:bolder;}#config-bar-content input{padding:5px 10px;}#config-bar-content label{margin-left:10px;cursor:pointer;}#config-bar-content .link{text-transform:uppercase;cursor:pointer;font-weight:bold;}#config-bar-logging{list-style:none;margin:0;padding:0;max-height:500px;overflow-y:scroll;font-size:12px;}#config-bar-logging > li{margin:0;padding:5px 10px;border-bottom:1px solid #E9F4FB;}#config-bar-logging > li:hover{background-color:#E9F4FB;}#config-bar-logging .level{display:block;float:left;width:10%;font-weight:bold;}#config-bar-logging .url{font-weight:bold;margin-left:10px;display:block;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;width:50%;float:left;}#config-bar-logging .filename{display:block;float:right;text-align:right;width:30%;font-weight:bold;}#config-bar-logging .message{display:block;clear:both;margin-top:20px;margin-bottom:5px;}#config-bar-content .property-name{width:70%;}#config-bar-content .property-value{width:10%;text-align:center;}#config-bar-property-name{width:70%;}#config-bar-audit,#config-bar-ab,#config-bar-flashcards,#config-bar-recommendation{padding-left:5px;}#config-bar-audit li,#config-bar-ab li,#config-bar-flashcards li,#config-bar-recommendation li{padding-left:0;margin-left:0;list-style:none;margin-bottom:5px;}#config-bar-ab ul{padding-left:0;margin-left:0;}.ab-experiment-chart-button{font-size:13px;width:15%;}#config-bar-audit input,#config-bar-flashcards input,#config-bar-recommendation input{width:27%;}#config-bar-audit button,#config-bar-flashcards button,#config-bar-recommendation button{width:27%;}#auditChart{margin:10px auto;width:480px;}#abChart{margin:0 auto;width:480px;}#flashcardsChart{margin:0 auto;width:100%;height:1000px;}#abExperimentName{margin-left:20px;font-weight:bold;}#abSetupInfo > li > ul,#abSetupInfo > li > ul > li{display:inline;}#flashcardsAnswers{width:100%;}#flashcardsAnswers thead{color:#fff;background-color:rgba(31,141,214,0.8);}#flashcardsAnswers th,#flashcardsAnswers td{text-align:center;}#flashcardsAnswers tbody tr:nth-child(even){background-color:#E9F4FB;}#flashcardsAnswers tbody tr:nth-child(odd){background-color:#fff;}#flashcardsAnswers td.correct{background-color:#009933;color:white;}#flashcardsAnswers td.wrong{background-color:#cc0000;color:white;}#flashcardsAnswers td.direction-t2d{background-color:#ff9900;color:white;}#flashcardsAnswers td.direction-d2t{background-color:#ffff00;}</style>');\n!angular.$$csp() && angular.element(document).find('head').prepend('<style type=\"text/css\">.rating .btn{margin:20px;}</style>');"]}