Mercurial > hg > webaudioevaluationtool
diff core.js @ 608:0256f3748b27 multiple-tests-concatenation
Merge
author | Giulio Moro <giuliomoro@yahoo.it> |
---|---|
date | Sat, 12 Mar 2016 15:32:30 +0000 |
parents | 328f24798462 640ffb822da1 |
children | 34d8bca65edc |
line wrap: on
line diff
--- a/core.js Fri Mar 11 16:49:47 2016 +0000 +++ b/core.js Sat Mar 12 15:32:30 2016 +0000 @@ -166,38 +166,10 @@ //var decode = $.parseXML(response); //projectXML = $(decode); - // First perform XML schema validation - var Module = { - xml: response, - schema: schemaXSD, - arguments:["--noout", "--schema", 'test-schema.xsd','document.xml'] - }; - - var xmllint = validateXML(Module); - console.log(xmllint); - if(xmllint != 'document.xml validates\n') - { - document.getElementsByTagName('body')[0].innerHTML = null; - var msg = document.createElement("h3"); - msg.textContent = "FATAL ERROR"; - var span = document.createElement("h4"); - span.textContent = "The XML validator returned the following errors when decoding your XML file"; - document.getElementsByTagName('body')[0].appendChild(msg); - document.getElementsByTagName('body')[0].appendChild(span); - xmllint = xmllint.split('\n'); - for (var i in xmllint) - { - document.getElementsByTagName('body')[0].appendChild(document.createElement('br')); - var span = document.createElement("span"); - span.textContent = xmllint[i]; - document.getElementsByTagName('body')[0].appendChild(span); - } - return; - } - - var parse = new DOMParser(); - projectXML = parse.parseFromString(response,'text/xml'); - var errorNode = projectXML.getElementsByTagName('parsererror'); + // Check if XML is new or a resumption + var parse = new DOMParser(); + var responseDocument = parse.parseFromString(response,'text/xml'); + var errorNode = responseDocument.getElementsByTagName('parsererror'); if (errorNode.length >= 1) { var msg = document.createElement("h3"); @@ -210,10 +182,90 @@ document.getElementsByTagName('body')[0].appendChild(errorNode[0]); return; } - - // Build the specification - specification.decode(projectXML); - storage.initialise(); + if (responseDocument.children[0].nodeName == "waet") { + // document is a specification + + // Perform XML schema validation + var Module = { + xml: response, + schema: schemaXSD, + arguments:["--noout", "--schema", 'test-schema.xsd','document.xml'] + }; + projectXML = responseDocument; + var xmllint = validateXML(Module); + console.log(xmllint); + if(xmllint != 'document.xml validates\n') + { + document.getElementsByTagName('body')[0].innerHTML = null; + var msg = document.createElement("h3"); + msg.textContent = "FATAL ERROR"; + var span = document.createElement("h4"); + span.textContent = "The XML validator returned the following errors when decoding your XML file"; + document.getElementsByTagName('body')[0].appendChild(msg); + document.getElementsByTagName('body')[0].appendChild(span); + xmllint = xmllint.split('\n'); + for (var i in xmllint) + { + document.getElementsByTagName('body')[0].appendChild(document.createElement('br')); + var span = document.createElement("span"); + span.textContent = xmllint[i]; + document.getElementsByTagName('body')[0].appendChild(span); + } + return; + } + // Build the specification + specification.decode(projectXML); + // Generate the session-key + storage.initialise(); + + } else if (responseDocument.children[0].nodeName == "waetresult") { + // document is a result + projectXML = document.implementation.createDocument(null,"waet"); + projectXML.children[0].appendChild(responseDocument.getElementsByTagName('waet')[0].getElementsByTagName("setup")[0].cloneNode(true)); + var child = responseDocument.children[0].children[0]; + while (child != null) { + if (child.nodeName == "survey") { + // One of the global survey elements + if (child.getAttribute("state") == "complete") { + // We need to remove this survey from <setup> + var location = child.getAttribute("location"); + var globalSurveys = projectXML.getElementsByTagName("setup")[0].getElementsByTagName("survey")[0]; + while(globalSurveys != null) { + if (location == "pre" || location == "before") { + if (globalSurveys.getAttribute("location") == "pre" || globalSurveys.getAttribute("location") == "before") { + projectXML.getElementsByTagName("setup")[0].removeChild(globalSurveys); + break; + } + } else { + if (globalSurveys.getAttribute("location") == "post" || globalSurveys.getAttribute("location") == "after") { + projectXML.getElementsByTagName("setup")[0].removeChild(globalSurveys); + break; + } + } + globalSurveys = globalSurveys.nextElementSibling; + } + } else { + // We need to complete this, so it must be regenerated by store + var copy = child; + child = child.previousElementSibling; + responseDocument.children[0].removeChild(copy); + } + } else if (child.nodeName == "page") { + if (child.getAttribute("state") == "empty") { + // We need to complete this page + projectXML.children[0].appendChild(responseDocument.getElementById(child.getAttribute("ref")).cloneNode(true)); + var copy = child; + child = child.previousElementSibling; + responseDocument.children[0].removeChild(copy); + } + } + child = child.nextElementSibling; + } + // Build the specification + specification.decode(projectXML); + // Use the original + storage.initialise(responseDocument); + } /// CHECK FOR SAMPLE RATE COMPATIBILITY if (specification.sampleRate != undefined) { if (Number(specification.sampleRate) != audioContext.sampleRate) { @@ -297,27 +349,6 @@ // Create the audio engine object audioEngineContext = new AudioEngine(specification); - - $(specification.pages).each(function(index,elem){ - $(elem.audioElements).each(function(i,audioElem){ - var URL = elem.hostURL + audioElem.url; - var buffer = null; - for (var i=0; i<audioEngineContext.buffers.length; i++) - { - if (URL == audioEngineContext.buffers[i].url) - { - buffer = audioEngineContext.buffers[i]; - break; - } - } - if (buffer == null) - { - buffer = new audioEngineContext.bufferObj(); - buffer.getMedia(URL); - audioEngineContext.buffers.push(buffer); - } - }); - }); } function createProjectSave(destURL) { @@ -328,7 +359,7 @@ var parent = document.createElement("div"); parent.appendChild(xmlDoc); var file = [parent.innerHTML]; - if (destURL == "null" || destURL == undefined) { + if (destURL == "local") { var bb = new Blob(file,{type : 'application/xml'}); var dnlk = window.URL.createObjectURL(bb); var a = document.createElement("a"); @@ -341,8 +372,7 @@ popup.popupContent.innerHTML = "<span>Please save the file below to give to your test supervisor</span><br>"; popup.popupContent.appendChild(a); } else { - var xmlhttp = new XMLHttpRequest; - destUrlFull = destURL; + destUrlFull = destURL+"?key="+storage.SessionKey.key; var saveFilenamePrefix; // parse the querystring of destUrl, get the "id" (if any) and append it to destUrl var qs = returnUrl.split("?"); @@ -357,43 +387,39 @@ } } if(typeof(saveFilenamePrefix) !== "undefined"){ - destUrlFull+="?saveFilenamePrefix="+saveFilenamePrefix; + destUrlFull+="&saveFilenamePrefix="+saveFilenamePrefix; } + var xmlhttp = new XMLHttpRequest; xmlhttp.open("POST",destUrlFull,true); xmlhttp.setRequestHeader('Content-Type', 'text/xml'); xmlhttp.onerror = function(){ console.log('Error saving file to server! Presenting download locally'); - createProjectSave(null); + createProjectSave("local"); }; - xmlhttp.onreadystatechange = function() { - console.log(xmlhttp.status); - if (xmlhttp.status != 200 && xmlhttp.readyState == 4) { - createProjectSave(null); - } else { - var parser = new DOMParser(); - var xmlDoc = parser.parseFromString(xmlhttp.responseText, "application/xml"); - if (xmlDoc == null) - { - createProjectSave('null'); - } - var response = xmlDoc.childNodes[0]; - if (response.getAttribute('state') == "OK") - { - var file = response.getElementsByTagName('file')[0]; - console.log('Save OK: Filename '+file.textContent+','+file.getAttribute('bytes')+'B'); - popup.showPopup(); - popup.popupContent.innerHTML = null; - popup.popupContent.textContent = "Thank you!"; - window.onbeforeunload=null; - if(typeof(returnUrl) !== "undefined"){ - window.location = returnUrl; - } - } else { - var message = response.getElementsByTagName('message')[0]; - errorSessionDump(message.textContent); - } - } - }; + xmlhttp.onload = function() { + console.log(xmlhttp); + if (this.status >= 300) { + console.log("WARNING - Could not update at this time"); + createProjectSave("local"); + } else { + var parser = new DOMParser(); + var xmlDoc = parser.parseFromString(xmlhttp.responseText, "application/xml"); + var response = xmlDoc.getElementsByTagName('response')[0]; + window.onbeforeunload=null; + if (response.getAttribute("state") == "OK") { + var file = response.getElementsByTagName("file")[0]; + if(typeof(returnUrl) !== "undefined"){ + window.location = returnUrl; + } + console.log("Save: OK, written "+file.getAttribute("bytes")+"B"); + popup.popupContent.textContent = "Thank you. Your session has been saved."; + } else { + var message = response.getElementsByTagName("message"); + console.log("Save: Error! "+message.textContent); + createProjectSave("local"); + } + } + }; xmlhttp.send(file); popup.showPopup(); popup.popupContent.innerHTML = null; @@ -452,6 +478,10 @@ return Math.pow(10,gain/20.0); } +function randomString(length) { + return Math.round((Math.pow(36, length + 1) - Math.random() * Math.pow(36, length))).toString(36).slice(1); +} + function interfacePopup() { // Creates an object to manage the popup this.popup = null; @@ -747,6 +777,7 @@ { this.store.postResult(node); } + this.store.complete(); advanceState(); } }; @@ -825,6 +856,22 @@ { if (specification.testPages <= i && specification.testPages != 0) {break;} this.stateMap.push(pageHolder[i]); + storage.createTestPageStore(pageHolder[i]); + for (var element of pageHolder[i].audioElements) { + var URL = pageHolder[i].hostURL + element.url; + var buffer = null; + for (var buffObj of audioEngineContext.buffers) { + if (URL == buffObj.url) { + buffer = buffObj; + break; + } + } + if (buffer == null) { + buffer = new audioEngineContext.bufferObj(); + buffer.getMedia(URL); + audioEngineContext.buffers.push(buffer); + } + } } if (specification.preTest != null) {this.preTestSurvey = specification.preTest;} @@ -843,6 +890,7 @@ if (this.stateIndex == null) { this.initialise(); } + storage.update(); if (this.stateIndex == -1) { this.stateIndex++; console.log('Starting test...'); @@ -875,7 +923,7 @@ { this.currentStateMap.audioElements = randomiseOrder(this.currentStateMap.audioElements); } - this.currentStore = storage.createTestPageStore(this.currentStateMap); + this.currentStore = storage.testPages[this.stateIndex]; if (this.currentStateMap.preTest != null) { this.currentStatePosition = 'pre'; @@ -936,6 +984,7 @@ element.exportXMLDOM(storePoint); } pageXMLSave(storePoint.XMLDOM, this.currentStateMap); + storePoint.complete(); }; } @@ -1189,7 +1238,7 @@ var aeNodes = this.pageStore.XMLDOM.getElementsByTagName('audioelement'); for (var i=0; i<aeNodes.length; i++) { - if(aeNodes[i].id == element.id) + if(aeNodes[i].getAttribute("ref") == element.id) { this.audioObjects[audioObjectId].storeDOM = aeNodes[i]; break; @@ -1931,6 +1980,7 @@ this.type = undefined; this.schema = specification.schema.getAllElementsByName('surveyentry')[0]; this.id = undefined; + this.name = undefined; this.mandatory = undefined; this.statement = undefined; this.boxsize = undefined; @@ -1986,34 +2036,32 @@ var statement = doc.createElement('statement'); statement.textContent = this.statement; node.appendChild(statement); - switch(this.type) - { - case "statement": - break; - case "question": + if (this.type != "statement") { node.id = this.id; + if (this.name != undefined) { node.setAttribute("name",this.name);} if (this.mandatory != undefined) { node.setAttribute("mandatory",this.mandatory);} - if (this.boxsize != undefined) {node.setAttribute("boxsize",this.boxsize);} - break; - case "number": - node.id = this.id; - if (this.mandatory != undefined) { node.setAttribute("mandatory",this.mandatory);} - if (this.min != undefined) {node.setAttribute("min", this.min);} - if (this.max != undefined) {node.setAttribute("max", this.max);} - break; - case "checkbox": - case "radio": - node.id = this.id; - for (var i=0; i<this.options.length; i++) - { - var option = this.options[i]; - var optionNode = doc.createElement("option"); - optionNode.setAttribute("name",option.name); - optionNode.textContent = option.text; - node.appendChild(optionNode); - } - break; - } + switch(this.type) + { + case "question": + if (this.boxsize != undefined) {node.setAttribute("boxsize",this.boxsize);} + break; + case "number": + if (this.min != undefined) {node.setAttribute("min", this.min);} + if (this.max != undefined) {node.setAttribute("max", this.max);} + break; + case "checkbox": + case "radio": + for (var i=0; i<this.options.length; i++) + { + var option = this.options[i]; + var optionNode = doc.createElement("option"); + optionNode.setAttribute("name",option.name); + optionNode.textContent = option.text; + node.appendChild(optionNode); + } + break; + } + } return node; }; }; @@ -2153,6 +2201,7 @@ this.showElementComments = undefined; this.outsideReference = null; this.loudness = null; + this.label = null; this.preTest = null; this.postTest = null; this.interfaces = []; @@ -2280,6 +2329,7 @@ this.commentQuestionNode = function() { this.id = null; + this.name = undefined; this.type = undefined; this.options = []; this.statement = undefined; @@ -2287,6 +2337,7 @@ this.decode = function(parent,xml) { this.id = xml.id; + this.name = xml.getAttribute('name'); this.type = xml.getAttribute('type'); this.statement = xml.getElementsByTagName('statement')[0].textContent; var optNodes = xml.getElementsByTagName('option'); @@ -2305,6 +2356,7 @@ var node = root.createElement("commentquestion"); node.id = this.id; node.setAttribute("type",this.type); + if (this.name != undefined){node.setAttribute("name",this.name);} var statement = root.createElement("statement"); statement.textContent = this.statement; node.appendChild(statement); @@ -2322,6 +2374,7 @@ this.audioElementNode = function() { this.url = null; this.id = null; + this.name = null; this.parent = null; this.type = null; this.marker = null; @@ -3013,8 +3066,8 @@ if (passed == false) { check_pass = false; - console.log("Continue listening to track-"+audioEngineContext.audioObjects.interfaceDOM.getPresentedId()); - error_obj.push(audioEngineContext.audioObjects.interfaceDOM.getPresentedId()); + console.log("Continue listening to track-"+object.interfaceDOM.getPresentedId()); + error_obj.push(object.interfaceDOM.getPresentedId()); } } if (check_pass == false) @@ -3113,15 +3166,82 @@ this.globalPreTest = null; this.globalPostTest = null; this.testPages = []; - this.document = document.implementation.createDocument(null,"waetresult"); - this.root = this.document.childNodes[0]; + this.document = null; + this.root = null; this.state = 0; - this.initialise = function() + this.initialise = function(existingStore) { - if (specification.preTest != undefined){this.globalPreTest = new this.surveyNode(this,this.root,specification.preTest);} - if (specification.postTest != undefined){this.globalPostTest = new this.surveyNode(this,this.root,specification.postTest);} + if (existingStore == undefined) { + // We need to get the sessionKey + this.SessionKey.generateKey(); + this.document = document.implementation.createDocument(null,"waetresult"); + this.root = this.document.childNodes[0]; + var projectDocument = specification.projectXML; + projectDocument.setAttribute('file-name',url); + this.root.appendChild(projectDocument); + this.root.appendChild(returnDateNode()); + this.root.appendChild(interfaceContext.returnNavigator()); + } else { + this.document = existingStore; + this.root = existingStore.children[0]; + this.SessionKey.key = this.root.getAttribute("key"); + } + if (specification.preTest != undefined){this.globalPreTest = new this.surveyNode(this,this.root,specification.preTest);} + if (specification.postTest != undefined){this.globalPostTest = new this.surveyNode(this,this.root,specification.postTest);} }; + + this.SessionKey = { + key: null, + request: new XMLHttpRequest(), + parent: this, + handleEvent: function() { + var parse = new DOMParser(); + var xml = parse.parseFromString(this.request.response,"text/xml"); + if (xml.getAllElementsByTagName("state")[0].textContent == "OK") { + this.key = xml.getAllElementsByTagName("key")[0].textContent; + this.parent.root.setAttribute("key",this.key); + this.parent.root.setAttribute("state","empty"); + } else { + this.generateKey(); + } + }, + generateKey: function() { + var temp_key = randomString(32); + this.request.open("GET","keygen.php?key="+temp_key,true); + this.request.addEventListener("load",this); + this.request.send(); + }, + update: function() { + this.parent.root.setAttribute("state","update"); + var xmlhttp = new XMLHttpRequest(); + xmlhttp.open("POST",specification.projectReturn+"?key="+this.key); + xmlhttp.setRequestHeader('Content-Type', 'text/xml'); + xmlhttp.onerror = function(){ + console.log('Error updating file to server!'); + }; + var hold = document.createElement("div"); + var clone = this.parent.root.cloneNode(true); + hold.appendChild(clone); + xmlhttp.onload = function() { + if (this.status >= 300) { + console.log("WARNING - Could not update at this time"); + } else { + var parser = new DOMParser(); + var xmlDoc = parser.parseFromString(xmlhttp.responseText, "application/xml"); + var response = xmlDoc.getElementsByTagName('response')[0]; + if (response.getAttribute("state") == "OK") { + var file = response.getElementsByTagName("file")[0]; + console.log("Intermediate save: OK, written "+file.getAttribute("bytes")+"B"); + } else { + var message = response.getElementsByTagName("message"); + console.log("Intermediate save: Error! "+message.textContent); + } + } + } + xmlhttp.send([hold.innerHTML]); + } + } this.createTestPageStore = function(specification) { @@ -3134,14 +3254,16 @@ { this.specification = specification; this.parent = parent; + this.state = "empty"; this.XMLDOM = this.parent.document.createElement('survey'); this.XMLDOM.setAttribute('location',this.specification.location); + this.XMLDOM.setAttribute("state",this.state); for (var optNode of this.specification.options) { if (optNode.type != 'statement') { var node = this.parent.document.createElement('surveyresult'); - node.id = optNode.id; + node.setAttribute("ref",optNode.id); node.setAttribute('type',optNode.type); this.XMLDOM.appendChild(node); } @@ -3153,7 +3275,14 @@ // From popup: node is the popupOption node containing both spec. and results // ID is the position if (node.specification.type == 'statement'){return;} - var surveyresult = this.parent.document.getElementById(node.specification.id); + var surveyresult = this.XMLDOM.children[0]; + while(surveyresult != null) { + if (surveyresult.getAttribute("ref") == node.specification.id) + { + break; + } + surveyresult = surveyresult.nextElementSibling; + } switch(node.specification.type) { case "number": @@ -3179,6 +3308,10 @@ break; } }; + this.complete = function() { + this.state = "complete"; + this.XMLDOM.setAttribute("state",this.state); + } }; this.pageNode = function(parent,specification) @@ -3186,9 +3319,11 @@ // Create one store per test page this.specification = specification; this.parent = parent; + this.state = "empty"; this.XMLDOM = this.parent.document.createElement('page'); - this.XMLDOM.setAttribute('id',specification.id); + this.XMLDOM.setAttribute('ref',specification.id); this.XMLDOM.setAttribute('presentedId',specification.presentedId); + this.XMLDOM.setAttribute("state",this.state); if (specification.preTest != undefined){this.preTest = new this.parent.surveyNode(this.parent,this.XMLDOM,this.specification.preTest);} if (specification.postTest != undefined){this.postTest = new this.parent.surveyNode(this.parent,this.XMLDOM,this.specification.postTest);} @@ -3200,7 +3335,8 @@ for (var element of this.specification.audioElements) { var aeNode = this.parent.document.createElement('audioelement'); - aeNode.id = element.id; + aeNode.setAttribute('ref',element.id); + if (element.name != undefined){aeNode.setAttribute('name',element.name)}; aeNode.setAttribute('type',element.type); aeNode.setAttribute('url', element.url); aeNode.setAttribute('gain', element.gain); @@ -3217,16 +3353,20 @@ } this.parent.root.appendChild(this.XMLDOM); + + this.complete = function() { + this.state = "complete"; + this.XMLDOM.setAttribute("state","complete"); + } }; + this.update = function() { + this.SessionKey.update(); + } this.finish = function() { if (this.state == 0) { - var projectDocument = specification.projectXML; - projectDocument.setAttribute('file-name',url); - this.root.appendChild(projectDocument); - this.root.appendChild(returnDateNode()); - this.root.appendChild(interfaceContext.returnNavigator()); + this.update(); } this.state = 1; return this.root;