/* data_services_post.js */ var xBookUtils = {}; var noopDSApi = { initializeClass : function(){ var dfd = jQuery.Deferred(); setTimeout(function(){ dfd.resolve(null); }, Math.floor(100 + Math.random() * 500)); return dfd.promise(); }, initializeUser: function(){ var dfd = jQuery.Deferred(); setTimeout(function(){ dfd.resolve(null); }, Math.floor(100 + Math.random() * 500)); return dfd.promise();}, loadClassData: function(){ var dfd = jQuery.Deferred(); setTimeout(function(){ dfd.resolve([]); }, Math.floor(100 + Math.random() * 500)); return dfd.promise();}, loadGlobalClassData: function(){ var dfd = jQuery.Deferred(); setTimeout(function(){ dfd.resolve(null); }, Math.floor(100 + Math.random() * 500)); return dfd.promise();}, setData: function(){}, setGlobalData: function(){ var dfd = jQuery.Deferred(); setTimeout(function(){ dfd.resolve(null); }, Math.floor(100 + Math.random() * 500)); return dfd.promise();}, }; var Player_ds = Player_gore.extend({ //current_topic:"Total", ds : { isInitialized : false, measure_count: { "grammar": { "Total": 34, "Average total score": 34, "Fragments": 3, "Pronouns": 9, "Run-Ons and Comma Splices": 5, "Subject-Verb Agreement": 5, "Verbs": 9, "Verbs Multilingual": 3}, "skills": { "Total": 20, "Average total score": 20, "Building Vocabulary": 5, "Patterns of Organization": 5, "Recognizing Supporting Details": 5, "Recognizing Topics and Main Ideas": 5}, "strategies": { "Total": 25, "Average total score": 25, "Active Reading": 10, "Argument": 5, "Critical Reading": 5, "Interpretive Reading": 5}, "style": { "Total": 34, "Average total score": 34, "Apostrophes": 3, "Capitalization": 2, "Commas": 7, "Modifiers": 4, "Parallelism": 3, "Quotation Marks": 3, "Semicolons and Colons": 3, "Sentence Structure": 4, "Sentence Structure Multilingual": 2, "Word Choice": 3} }, api : ( typeof ((((window.parent || {}).PX || {}).API || {}).DataService) != "undefined") ? window.parent.PX.API.DataService : noopDSApi, userData: {}, classData: {}, quizData: {}, studentNames: {}, initialize: function(callback){ // Instructors won't have a user entry in DS so we don't need to call // it for them if (!xBookUtils.isInstructor()) { this.initializeUser(callback); } // We only want to call this if viewing as an instructor since // the stored quiz data has user names in it because getClassRoster // has not been implemented yet if (xBookUtils.isInstructor()) { this.initializeClass(callback); } }, initializeUser: function(callback){ safe_log("initializeUser: retrieving DS data for " + player.md.quiz_name); this.api.initializeUser(player.md.quiz_name).then(function(a){ safe_log("received data from initializeUser"); safe_log(a); if (a !== null && a!== undefined){ safe_log("initializeUser: data is not null"); safe_log(a); } else { safe_log("initializeUser: data is empty for " + player.md.quiz_name); } if (callback !== undefined) { callback(); } }); }, // If user_id has completed both the pre/post test then return true, // otherwise false completedPrePostQuizzes: function(user_id, ds_array) { var pre = false; var post = false; for(var i = 0; i < ds_array.length; i++){ // If we know that the student has completed both quizzes // then return true if (pre && post) { return true; } if (ds_array[i].UserId == user_id) { var valueObject = player.ds.parseHelper(ds_array[i].Value.v); if (valueObject.complete === true) { if (ds_array[i].Key === "pre") { pre = true; } else if (ds_array[i].Key === "post") { post = true; } } } } if (!pre || !post) { return false; } return true; }, // display is boolean: true = show buttons, // false = no comparison data, show message setComparisonButtons: function(display) { if (display) { $('#vcr_waiting').replaceWith("View Class Comparison Report"); $('#vrr_waiting').replaceWith("View Roster Comparison Report"); } else { $('#vcr_waiting').replaceWith("
Report Unavailable
"); $('#vrr_waiting').replaceWith("Report Unavailable
"); } }, initializeClass: function(callback){ player.ds.studentNames["0000"] = "Total"; safe_log("initializeClass: retrieving DS data for " + player.md.quiz_name); this.api.initializeClass(player.md.quiz_name).then(function(ds_array){ // ds_array is array of objects returned by DS if (ds_array !== null && ds_array !== undefined){ safe_log("initializeClass"); safe_log(ds_array); // go through each object in DS array (each object represents // one student's scores for a particular quiz) for(var i = 0; i < ds_array.length; i++){ safe_log("ds_array[" + i +"]"); safe_log(ds_array[i]); var user_id = ds_array[i].UserId; var key = ds_array[i].Key; safe_log("UserId: " + user_id + ", Key: " + key); // key must be either "pre" or "post" if (ds_array[i].Key !== "pre" && ds_array[i].Key !== "post") { continue; } // make sure student has completed both pre and post quiz if (!player.ds.completedPrePostQuizzes(user_id, ds_array)) { safe_log("UserID " + user_id + " has not completed both pre and post quizzes"); continue; } // Make sure we have scores if (ds_array[i].Value.v === undefined) { continue; } var valueObject = player.ds.parseHelper(ds_array[i].Value.v); safe_log("valueObject"); safe_log(valueObject); if (valueObject.scores === undefined) { continue; } // Make sure student has completed the quiz if (valueObject.complete !== true) { safe_log(user_id + " has not completed quiz"); continue; } // player.ds.classData.USERID.KEY.SCORES // USERID = string // KEY = string // SCORES = if (player.ds.classData[user_id] === undefined) { player.ds.classData[user_id] = {}; } // total up all the scores for the student var student_total = {attempts: 0, score: 0}; for (var measure in valueObject.scores) { if (valueObject.scores.hasOwnProperty(measure)) { student_total.attempts += valueObject.scores[measure].attempts; student_total.score += valueObject.scores[measure].score; } } valueObject.scores['Total'] = student_total; player.ds.classData[user_id][key] = valueObject.scores; // save off student name if (player.ds.studentNames[user_id] === undefined || player.ds.studentNames[user_id] === "Unknown") { if (valueObject.name !== undefined) { player.ds.studentNames[user_id] = decodeURIComponent(valueObject.name); } else { player.ds.studentNames[user_id] = "Unknown"; } } // While we are at it, let's calculate totals for key. We need // to go through each measure and add the score to the total. // Totals will have the UserId '0000'. total_id = "0000"; if (player.ds.classData[total_id] === undefined) { player.ds.classData[total_id] = {}; } if (player.ds.classData[total_id][key] === undefined) { player.ds.classData[total_id][key] = {}; } // valueObject now includes the "All" measure we calculated // above for the user for (var measure in valueObject.scores) { if (valueObject.scores.hasOwnProperty(measure)) { //safe_log("measure: " + measure); if (player.ds.classData[total_id][key][measure] === undefined) { //safe_log("creating measure for " + key); player.ds.classData[total_id][key][measure] = {}; } // get Total attempts for this measure var t_attempts = player.ds.classData[total_id][key][measure].attempts; if (t_attempts === undefined) { t_attempts = 0; } // get Total score for this measure var t_score = player.ds.classData[total_id][key][measure].score; if (t_score === undefined) { t_score = 0; } if (valueObject.scores[measure].attempts !== undefined) { //safe_log("adding attempts " + valueObject.scores[measure].attempts + " to Total attempts for [" + key + "][" + measure + "].attempts"); player.ds.classData[total_id][key][measure].attempts = t_attempts + valueObject.scores[measure].attempts; } if (valueObject.scores[measure].score !== undefined) { //safe_log("adding score " + valueObject.scores[measure].score + " to Total score for [" + key + "][" + measure + "].score"); player.ds.classData[total_id][key][measure].score = t_score + valueObject.scores[measure].score; } } } // end for // increment students by 1 for this quiz if (player.ds.quizData[key] === undefined) { player.ds.quizData[key] = {}; player.ds.quizData[key].students = 0; } player.ds.quizData[key].students++; } // end for safe_log("classData"); safe_log(player.ds.classData); safe_log("studentNames"); safe_log(player.ds.studentNames); safe_log("quizData"); safe_log(player.ds.quizData); // do we have comparisons for the class comparison report? if (player.ds.quizData.pre === undefined || player.ds.quizData.post === undefined) { player.ds.setComparisonButtons(false); } else { $("#manuscript").addClass("ds_init"); player.ds.setComparisonButtons(true); } player.ds.initialize_comp_instructor_report_data(); } else { safe_log("initializeClass: data is empty for " + player.md.quiz_name); player.ds.setComparisonButtons(false); } if (callback !== undefined) { callback(); } }); }, // end initializeClass initialize_comp_instructor_report_data: function(){ //first order of business is to calculate the overall scores for each student //while we're at it, tally up for class totals too. //we'll populate the topic dropdown too... var topic_dropdown = $("#comp_class_data_topic_dropdown"); for (var i = 0; i < player.measure_names.length; i++){ topic_dropdown.append(""); } //player.class_data["Total"].scores["Total"] = {attempts:0, score:0}; var student_dropdown = $("#comp_class_data_student_dropdown"); for (var key in player.ds.classData){ // loop over each student if (player.ds.classData.hasOwnProperty(key)) { //add to the dropdown if (key !== "0000"){ var student_name = this.getClassDataName(key); student_dropdown.append(""); } } } student_dropdown.select2(); //player.comp_instructor_report_data_is_initialized = true; }, // end initialize_comp_instructor_report_data // value is a JS object generateDataRecord: function(datasetID, key, value, loadOnUserInit, loadOnClassInit, loadOnSchoolInit){ var r = { CourseId: parent.PxPage.Context.Course.EntityId, InstitutionId: null, // DS is using the "RAId" instead of the "CurrentUserId" UserId: parent.PxPage.Context.User.RAId, Key: key, Value: {v: this.stringifyHelper(value)}, // this must be an object DataSetId: datasetID, LoadOnUserInit: loadOnUserInit, LoadOnClassInit: loadOnClassInit, LoadOnSchoolInit: loadOnSchoolInit }; return r; }, // end generateDataRecord // This is a workaround for the current bug in Activity Tracker which // is stripping escaped double quotes from values stringifyHelper: function(obj) { var string = JSON.stringify(obj); string = string.replace(/\"/g, "_DQ_"); return string; }, // This is a workaround for the current bug in Activity Tracker which // is stripping escaped double quotes from values parseHelper: function(str) { str = str.replace(/_DQ_/g, "\""); return JSON.parse(str); }, getClassData: function(userid, quizname, measure, value) { if (this.classData[userid] === undefined) { return undefined; } if (this.classData[userid][quizname] === undefined) { return undefined; } if (this.classData[userid][quizname][measure] === undefined) { return undefined; } return this.classData[userid][quizname][measure][value]; }, getClassDataName: function (userid) { return this.studentNames[userid]; } }, // end player.ds // Class Comparison Report generate_comp_instructor_report: function() { safe_log("generate_comp_instructor_report"); safe_log("player.current_student_for_report = " + player.current_student_for_report); var container_element = $("[data-block_type='comp_class_results_summary']")[0]; $(container_element).empty(); var rowOrder = []; var rowCollection = []; var quiz_names = ["pre", "post"]; var create_progress_bar = function(barClass, percentage, details) { var html = "" + player.diag_quiz_title + "
"; h += "Class Report for " + title_name + "
"; for(var i = 0; i < rowCollection.length; i++){ var row = rowCollection[i]; h = h + row.html; } $(container_element).append(h); }, // end generate_comp_instructor_report show_comp_instructor_class_report: function(roster_link) { safe_log("show_comp_instructor_class_report"); safe_log("roster_link = " + roster_link); var s = player.get_section_by_title("Comparison Results"); if (roster_link !== true) { $("[data-section-index=" + s.index + "]").removeClass("show_roster_link"); } else { $("[data-section-index=" + s.index + "]").addClass("show_roster_link"); } player.show_section(s.index); }, // end show_instructor_class_report show_section: function(section_to_show) { this._super(section_to_show); /* safe_log("show_section"); var $sec = this.get_current_section_jq(); safe_log($sec); safe_log($sec.attr("data-block_type")); */ if (this.get_current_section_jq().attr("data-block_type") === "instructor_report"){ $("#next_button").hide(); } }, save_student_data: function(){ var scoreObject = {}; for (var i = 0; i < player.measure_names.length; i++){ var score = 0; if(player.measure_names[i].attempts > 0){ score = ((player.measure_names[i].score / player.measure_names[i].attempts) * 100).toFixed(0) + "%"; } scoreObject[player.measure_names[i].value] = {}; scoreObject[player.measure_names[i].value].attempts = player.measure_names[i].attempts; //total_attempts += player.measure_names[i].attempts; scoreObject[player.measure_names[i].value].score = player.measure_names[i].score; //total_score += player.measure_names[i].score; } safe_log("save_student_data: scoreObject") safe_log(scoreObject); this.send_student_data_to_ARGA(scoreObject); }, // end save_student_data send_student_data_to_ARGA: function(data){ var dataObject = {}; if(player.ARGA_running){ Set_ARGA_Data("scores", JSON.stringify(data)); Save_ARGA_Data(); dataObject.name = Get_ARGA_Data("learner_name"); dataObject.scores = data; // JS object dataObject.complete = this.allQuestionsAnswered(); var key = player.md.quiz_type; // "pre" or "post" var record = player.ds.generateDataRecord(player.md.quiz_name, key, dataObject, "true", "true", "false"); safe_log("record"); safe_log([record]); player.ds.api.setData([record]); } }, // end send_student_data_to_ARGA // Return true if all answers in the quiz have been answered, otherwise false allQuestionsAnswered: function() { //safe_log("allQuestionsAnswered"); //safe_log(player.activity.questions); //safe_log(player.activity.questions.length); // make sure every question in the quiz has been answered for (var q_index=1; q_index" + player.diag_quiz_title + "
"; h += "Roster Report for " + topic_name + "
"; for(var i = 0; i < rowCollection.length; i++){ var row = rowCollection[i]; h = h + row.html; } $(container_element).append(h); }, // end generate_comp_instructor_roster_report show_comp_instructor_roster_report: function(){ safe_log("show_comp_instructor_roster_report"); var s = player.get_section_by_title("Roster Comparison Results"); player.show_section(s.index); }, initialize: function(id, panel) { this._super(id, panel); $("#comp_class_data_sort_order_buttons > label").click(function(){ var $this = $(this); var $radio = $this.children("input"); if ($radio.length > 0) { player.class_results_sort_order= $radio.val(); player.generate_comp_instructor_report(); } }); $("#comp_roster_data_sort_order_buttons > label").click(function(){ var $this = $(this); var $radio = $this.children("input"); if ($radio.length > 0) { player.roster_data_sort_order= $radio.val(); player.generate_comp_instructor_roster_report(); } }); $("#comp_class_data_sort_order").change(function(){ player.class_results_sort_order= $("#comp_class_data_sort_order").val(); player.generate_comp_instructor_report(); }); $("#comp_roster_data_sort_order").change(function(){ player.roster_data_sort_order = $("#comp_roster_data_sort_order").val(); player.generate_comp_instructor_roster_report(); }); $("#comp_class_data_student_dropdown").change(function(){ player.current_student_for_report = $("#comp_class_data_student_dropdown").val(); player.generate_comp_instructor_report(); }); $("#comp_class_data_topic_dropdown").change(function(){ player.current_topic = $("#comp_class_data_topic_dropdown").val(); player.generate_comp_instructor_roster_report(); }); this.ds.initialize(function(){ //safe_log("data services initialized"); }); } }); // end Player_ds player = new Player_ds(); xBookUtils.isInstructor = function() { if (xBookUtils.inPXFrame()){ try { if (top.PxPage.Context.User.IsInstructor === "true") { return true; } return false; } catch(e) { safe_log("xBookUtils.isInstructor: error referencing top.PxPage: " + e.message); return false; } } if (xBookUtils.inDFWrapper()) { try { var $wrapper_body = $('body', top.window.document); if ($wrapper_body.hasClass('wrapper_student_view')) { return false; } return true; } catch(e) { safe_log("xBookUtils.isInstructor: error referencing top.window: " + e.message); return false; } } return false; } /* inPXFrame: Return true if the page is being viewed in the main PX content frame, otherwise return false. */ xBookUtils.inPXFrame = function() { try { if (top.PxPage) { return true; } } catch(err) { } return false; } /* inDFWrapper: Return true if we are viewing the page in the DF wrapper, otherwise return false; */ xBookUtils.inDFWrapper = function() { try { if (top.DFwrapper) { return true; } } catch(err) { } return false; } // Redo the getQueryTextForARGA function for MC questions so that html tags // are removed from the question text sent to the gradebook. var MC_Query = MC_Query.extend({ // Remove html tags from query text so they don't show up in the gradebook getQueryTextForARGA: function() { if (this.query_text_for_ARGA != null && this.query_text_for_ARGA != "") { var q_text = this.query_text_for_ARGA; safe_log("getQueryTextForARGA: initial query text: " + q_text); q_text = q_text.replace(/<(\/)?[^>]+>/gi, ''); safe_log("getQueryTextForARGA: " + q_text); return q_text; } else if (this.query_text != null && this.query_text != "") { var q_text = this.query_text; safe_log("getQueryTextForARGA: initial query text: " + q_text); q_text = q_text.replace(/<(\/)?[^>]+>/gi, ''); safe_log("getQueryTextForARGA: " + q_text); return q_text; } else { return "see page for question context"; } } });