import * as helper from "./helpers.js"; import * as config from "./config.js"; /** * Submits answers */ export function submitAnswers(exam_details, db, URLS) { if (!exam_details || !exam_details.exam_mode) { alert("Answers can only be submitted when the exam is in exam mode."); return; } getJsonAnswers(exam_details, db) .then((a) => { let json = { eid: exam_details.eid, cid: exam_details.cid, start_time: exam_details.start_time, answers: JSON.stringify(a), }; postAnswers(json, URLS, exam_details); }) .catch((e) => { console.debug(e) alert("No answers to submit"); }); } /** * Gets a json representation of answers * @return {JSON} - answers */ export function getJsonAnswers(exam_details, db) { console.debug(exam_details) console.debug({ aid: exam_details.aid, cid: exam_details.cid, eid: exam_details.eid, }) return db.answers .where({ aid: exam_details.aid, cid: exam_details.cid, eid: exam_details.eid, }) .toArray(); } /** * Posts answers to url * @param {*} ans - json representation of answers */ export function postAnswers(ans, URLS, exam_details) { $("#progress").html("Submitting answers..."); console.debug("postAnswers", ans, URLS, exam_details) console.debug("posturl", URLS.exam_submit_url) $.post(URLS.exam_submit_url, ans, null, "json") .done((data) => { console.debug("returned data", data); if (data.success) { $("#submit-error-overlay").remove(); if (data.question_count == exam_details.number_of_questions) { let ret = confirm( // `${data.question_count} answers successfully submitted. Click OK to finish the exam.` `Answers successfully submitted. Click OK to finish the exam.` ); if (ret) { $(document).trigger("saveSessionEvent", [true]); if (URLS.exam_results_url != "") { let url = URLS.exam_results_url; if (exam_details.cid != "") { url = `${url}${exam_details.cid}`; if (localStorage.getItem("cid.passcode") != null) { url = `${url}/${localStorage.getItem("cid.passcode")}`; } if (exam_details.cid.startsWith("u-")) { url = URLS.exam_user_results_url; } } $("#options-link") .empty() .append( `
Results and answers
` ); } $("#options-panel").show(); } else {} } else { //alert(`${data.question_count} answers sucessfully submitted.`); alert(`Answers sucessfully submitted.`); } } else { submissionError(data, ans, exam_details, URLS); } }) .fail((e) => { // Will occur with server error such as 500 console.debug("error", e); submissionError(e, ans, exam_details, URLS); }); // $.post( "http://localhost:8000/submit_answers", JSON.stringify(ans)); } export function submissionError(data, answer_json, exam_details, URLS) { // Clear any existing overlay $("#submit-error-overlay").remove(); let answers = JSON.parse(answer_json.answers); let answer_map = {}; answers.forEach((ans) => { if (!answer_map.hasOwnProperty(ans.qid)) { answer_map[ans.qid] = []; } answer_map[ans.qid].push(ans); }); let $list = $("
    "); exam_details.question_order.forEach((qid, idx) => { if (qid in answer_map) { let ans_array = answer_map[qid]; ans_array.forEach((ans_obj, sub_idx) => { $list.append(`
  1. Question ${idx + 1}.${sub_idx + 1}: ${ans_obj.ans}
  2. `); }); } }); let rawJsonStr = JSON.stringify(answer_json, null, 2); let errorMsg = "An error occurred while submitting your answers."; if (data && data.error) { errorMsg = `Server returned error: ${data.error}`; } else if (data && data.statusText) { errorMsg = `Network error: ${data.statusText} (${data.status})`; } let $overlay = $(`

    Submission Failed

    ${errorMsg}

    Your answers are saved locally in the browser's database and will not be lost unless you clear your local data. Please try to submit again, or save a backup file of your answers and contact support.

    Submitted Answers:

    ${$list.prop("outerHTML")}
    View Raw Submission JSON
    ${rawJsonStr}
    `); $("body").append($overlay); // Setup download backup link let fileBlob = new Blob([JSON.stringify(answer_json)], {type: "application/json"}); let backupUrl = URL.createObjectURL(fileBlob); $overlay.find("#btn-err-backup").attr("href", backupUrl).attr("download", `answers_backup_${exam_details.eid.replace(/\//g, "_")}.json`); // Close handler $overlay.find("#btn-err-close").on("click", function() { $("#submit-error-overlay").remove(); }); // Retry handler $overlay.find("#btn-err-retry").on("click", function() { postAnswers(answer_json, URLS, exam_details); }); } export function getQuestion(url, question_number, question_total) { console.debug("Downloading question ", url, question_number, question_total); return $.ajax({ dataType: "json", url: url, progress: function(e) { if (e.lengthComputable) { var completedPercentage = Math.round((e.loaded * 100) / e.total); $("#progress").html( `Downloading question [${question_number}/${question_total}]
    ${completedPercentage}%
    ${helper.formatBytes( e.total )}` ); } else { $("#progress").html( `Downloading question [${question_number}/${question_total}]
    This file is compressed (downloaded ${helper.humanFileSize(e.loaded)})` ); } }, error: (jqXHR, textStatus, errorThrown) => { console.debug("error downlading", jqXHR, textStatus, errorThrown); }, //success: function (data) { // strReturn = data; //}, //async: false, }); } export function postSavedAnswer(type, qid, answer, e, db_object, db, submit_url) { console.debug("post", type, qid, answer, e) return $.ajax({ type: "POST", url: submit_url, data: JSON.stringify({ qid: `${type}/${qid}`, answer: answer, status: 2 }), contentType: "application/json; charset=utf-8", dataType: "json", success: function(data) { db_object.submitted = true; db.user_answers.put(db_object); e.target.remove() console.debug(data); }, error: function(errMsg) { alert(errMsg); } }); }