Mercurial > hg > webaudioevaluationtool
changeset 1249:ba6b9e1aaef5
Merge
line wrap: on
line diff
--- a/core.js Wed Mar 09 15:00:19 2016 +0000 +++ b/core.js Thu Mar 10 17:08:10 2016 +0000 @@ -220,12 +220,51 @@ } else if (responseDocument.children[0].nodeName == "waetresult") { // document is a result - projectXML = responseDocument.getElementsByTagName('waet')[0]; + 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 session-key - var sessionKey = responseDocument.children[0].getAttribute(key); - storage.initialise(sessionKey); + // Use the original + storage.initialise(responseDocument); } /// CHECK FOR SAMPLE RATE COMPATIBILITY if (specification.sampleRate != undefined) { @@ -334,16 +373,17 @@ popup.popupContent.appendChild(a); } else { var xmlhttp = new XMLHttpRequest; - xmlhttp.open("POST",destURL,true); + xmlhttp.open("POST","\save.php?key="+storage.SessionKey.key,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.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"); @@ -716,6 +756,7 @@ { this.store.postResult(node); } + this.store.complete(); advanceState(); } }; @@ -922,6 +963,7 @@ element.exportXMLDOM(storePoint); } pageXMLSave(storePoint.XMLDOM, this.currentStateMap); + storePoint.complete(); }; } @@ -1175,7 +1217,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; @@ -2138,6 +2180,7 @@ this.showElementComments = undefined; this.outsideReference = null; this.loudness = null; + this.label = null; this.preTest = null; this.postTest = null; this.interfaces = []; @@ -3002,8 +3045,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) @@ -3102,25 +3145,29 @@ 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(sessionKey) + this.initialise = function(existingStore) { - if (sessionKey == undefined) { + 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.SessionKey.key = sessionKey; + 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);} + if (specification.postTest != undefined){this.globalPostTest = new this.surveyNode(this,this.root,specification.postTest);} }; this.SessionKey = { @@ -3186,14 +3233,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); } @@ -3205,7 +3254,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": @@ -3231,6 +3287,10 @@ break; } }; + this.complete = function() { + this.state = "complete"; + this.XMLDOM.setAttribute("state",this.state); + } }; this.pageNode = function(parent,specification) @@ -3238,9 +3298,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);} @@ -3252,7 +3314,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); @@ -3269,6 +3332,11 @@ } this.parent.root.appendChild(this.XMLDOM); + + this.complete = function() { + this.state = "complete"; + this.XMLDOM.setAttribute("state","complete"); + } }; this.update = function() { this.SessionKey.update();
--- a/example_eval/AB_example.xml Wed Mar 09 15:00:19 2016 +0000 +++ b/example_eval/AB_example.xml Thu Mar 10 17:08:10 2016 +0000 @@ -13,7 +13,7 @@ <option name="hwdesigner">Designing or building audio hardware</option> <option name="researcher">Research in the field of audio</option> </surveyentry> - <surveyentry type="statement"> + <surveyentry type="statement" id="test-intro"> <statement>This is an example of an 'AB'-style test, with two pages, using the test stimuli in 'example_eval/'.</statement> </surveyentry> </survey> @@ -31,7 +31,7 @@ <option name="good">Good</option> <option name="great">Great</option> </surveyentry> - <surveyentry type="statement"> + <surveyentry type="statement" id="test-thank-you"> <statement>Thank you for taking this listening test. Please click 'submit' and your results will appear in the 'saves/' folder.</statement> </surveyentry> </survey> @@ -60,7 +60,7 @@ <audioelement url="0.wav" id="track-0"/> <audioelement url="1.wav" id="track-1"/> <survey location="before"> - <surveyentry type="statement"> + <surveyentry type="statement" id="test-0-intro"> <statement>A two way comparison using randomised element order, automatic loudness and synchronised looping.</statement> </surveyentry> </survey> @@ -83,7 +83,7 @@ <audioelement url="5.wav" id="track-7"/> <audioelement url="6.wav" id="track-8"/> <survey location="before"> - <surveyentry type="statement"> + <surveyentry type="statement" id="test-1-intro"> <statement>A 7 way comparison using randomised element order and synchronised looping.</statement> </surveyentry> </survey>
--- a/example_eval/mushra_example.xml Wed Mar 09 15:00:19 2016 +0000 +++ b/example_eval/mushra_example.xml Thu Mar 10 17:08:10 2016 +0000 @@ -13,7 +13,7 @@ <option name="hwdesigner">Designing or building audio hardware</option> <option name="researcher">Research in the field of audio</option> </surveyentry> - <surveyentry type="statement"> + <surveyentry type="statement" id="test-intro"> <statement>This is an example of an 'APE'-style test, with two pages, using the test stimuli in 'example_eval/'.</statement> </surveyentry> </survey> @@ -31,7 +31,7 @@ <option name="good">Good</option> <option name="great">Great</option> </surveyentry> - <surveyentry type="statement"> + <surveyentry type="statement" id="thankyou"> <statement>Thank you for taking this listening test. Please click 'submit' and your results will appear in the 'saves/' folder.</statement> </surveyentry> </survey> @@ -71,7 +71,7 @@ <audioelement url="3.wav" id="track-3"/> <audioelement url="4.wav" id="track-4"/> <survey location="before"> - <surveyentry type="statement"> + <surveyentry type="statement" id="test-0-intro"> <statement>Example of a 'MUSHRA' style interface with hidden anchor 'zero' (which needs to be below 20%), looping of the samples, randomisation of marker labels, mandatory moving of every sample, and a forced scale usage of at least 25%-75% using a Comparison Category Rating Scale.</statement> </surveyentry> </survey> @@ -118,7 +118,7 @@ <option name="heavy">Heavy</option> </commentquestion> <survey location="before"> - <surveyentry type="statement"> + <surveyentry type="statement" id="test-1-intro"> <statement>Example of a 'MUSHRA' style interface with hidden anchor 'zero' (which needs to be below 20%), looping of the samples, randomisation of marker labels, mandatory moving of every sample, and a forced scale usage of at least 25%-75%.</statement> </surveyentry> </survey>
--- a/example_eval/project.xml Wed Mar 09 15:00:19 2016 +0000 +++ b/example_eval/project.xml Thu Mar 10 17:08:10 2016 +0000 @@ -13,7 +13,7 @@ <option name="hwdesigner">Designing or building audio hardware</option> <option name="researcher">Research in the field of audio</option> </surveyentry> - <surveyentry type="statement"> + <surveyentry type="statement" id="test-intro"> <statement>This is an example of an 'APE'-style test, with two pages, using the test stimuli in 'example_eval/'.</statement> </surveyentry> </survey> @@ -31,7 +31,7 @@ <option name="good">Good</option> <option name="great">Great</option> </surveyentry> - <surveyentry type="statement"> + <surveyentry type="statement" id="thankyou"> <statement>Thank you for taking this listening test. Please click 'submit' and your results will appear in the 'saves/' folder.</statement> </surveyentry> </survey> @@ -76,7 +76,7 @@ <audioelement url="3.wav" id="track-3"/> <audioelement url="4.wav" id="track-4"/> <survey location="before"> - <surveyentry type="statement"> + <surveyentry type="statement" id="test-0-intro"> <statement>Example of an 'APE' style interface with hidden anchor 'zero' (which needs to be below 20%), looping of the samples, randomisation of marker labels, mandatory moving of every sample, and a forced scale usage of at least 25%-75%.</statement> </surveyentry> </survey> @@ -86,7 +86,7 @@ </surveyentry> </survey> </page> - <page id='test-1' hostURL="example_eval/" randomiseOrder='true' repeatCount='0' loop='false' showElementComments='true'> + <page id='test-1' hostURL="example_eval/" randomiseOrder='true' repeatCount='0' loop='false' showElementComments='true' label="none"> <commentboxprefix>Comment on fragment</commentboxprefix> <interface name="preference"> <title>Example Test Question</title> @@ -123,7 +123,7 @@ <option name="heavy">Heavy</option> </commentquestion> <survey location="before"> - <surveyentry type="statement"> + <surveyentry type="statement" id="test-1-intro"> <statement>Example of an 'APE' style interface with hidden anchor 'zero' (which needs to be below 20%), looping of the samples, randomisation of marker labels, mandatory moving of every sample, and a forced scale usage of at least 25%-75%.</statement> </surveyentry> </survey>
--- a/interfaces/AB.js Wed Mar 09 15:00:19 2016 +0000 +++ b/interfaces/AB.js Thu Mar 10 17:08:10 2016 +0000 @@ -308,7 +308,22 @@ console.log("WARNING - AB cannot have fixed reference"); } var audioObject = audioEngineContext.newTrack(element); - var node = new this.comparatorBox(audioObject,index,String.fromCharCode(65 + index)); + var label; + switch(audioObject.specification.parent.label) { + case "none": + label = ""; + break; + case "number": + label = ""+index; + break; + case "letter": + label = String.fromCharCode(97 + index); + break; + default: + label = String.fromCharCode(65 + index); + break; + } + var node = new this.comparatorBox(audioObject,index,label); audioObject.bindInterface(node); this.comparators.push(node); this.boxHolders.appendChild(node.box);
--- a/interfaces/ape.css Wed Mar 09 15:00:19 2016 +0000 +++ b/interfaces/ape.css Thu Mar 10 17:08:10 2016 +0000 @@ -64,6 +64,7 @@ -moz-user-select: -moz-none; -khtml-user-select: none; -webkit-user-select: none; + border: 1px solid black; } div.outside-reference {
--- a/interfaces/ape.js Wed Mar 09 15:00:19 2016 +0000 +++ b/interfaces/ape.js Thu Mar 10 17:08:10 2016 +0000 @@ -239,7 +239,7 @@ }; // Create Submit (save) button var submit = document.createElement("button"); - submit.innerHTML = 'Submit'; + submit.innerHTML = 'Next'; submit.onclick = buttonSubmitClick; submit.id = 'submit-button'; // Append the interface buttons into the interfaceButtons object. @@ -535,7 +535,22 @@ this.canvas.appendChild(trackObj); this.sliders.push(trackObj); this.metrics.push(new metricTracker(this)); - trackObj.innerHTML = '<span>'+(this.metrics.length-1)+'</span>'; + var label = document.createElement("label"); + switch(audioObject.specification.parent.label) { + case "letter": + label.textContent = String.fromCharCode(97 + this.metrics.length-1); + break; + case "capital": + label.textContent = String.fromCharCode(65 + this.metrics.length-1); + break; + case "none": + label.textContent = ""; + break; + default: + label.textContent = ""+this.metrics.length; + break; + } + trackObj.appendChild(label); this.metrics[this.metrics.length-1].initialise(convSliderPosToRate(trackObj)); return trackObj; };
--- a/interfaces/discrete.js Wed Mar 09 15:00:19 2016 +0000 +++ b/interfaces/discrete.js Thu Mar 10 17:08:10 2016 +0000 @@ -55,7 +55,7 @@ }; // Create Submit (save) button var submit = document.createElement("button"); - submit.innerHTML = 'Submit'; + submit.innerHTML = 'Next'; submit.onclick = buttonSubmitClick; submit.id = 'submit-button'; submit.style.float = 'left'; @@ -184,7 +184,7 @@ }); // Find all the audioElements from the audioHolder - var label = 0; + var index = 0; var interfaceScales = testState.currentStateMap.interfaces[0].scales; $(page.audioElements).each(function(index,element){ // Find URL of track @@ -198,11 +198,25 @@ audioObject.bindInterface(orNode); } else { // Create a slider per track + switch(audioObject.specification.parent.label) { + case "none": + label = ""; + break; + case "letter": + label = String.fromCharCode(97 + index); + break; + case "capital": + label = String.fromCharCode(65 + index); + break; + default: + label = ""+index; + break; + } var sliderObj = new discreteObject(audioObject,label,interfaceScales); sliderBox.appendChild(sliderObj.holder); audioObject.bindInterface(sliderObj); interfaceContext.commentBoxes.createCommentBox(audioObject); - label += 1; + index += 1; } });
--- a/interfaces/horizontal-sliders.js Wed Mar 09 15:00:19 2016 +0000 +++ b/interfaces/horizontal-sliders.js Thu Mar 10 17:08:10 2016 +0000 @@ -55,7 +55,7 @@ }; // Create Submit (save) button var submit = document.createElement("button"); - submit.innerHTML = 'Submit'; + submit.innerHTML = 'Next'; submit.onclick = buttonSubmitClick; submit.id = 'submit-button'; submit.style.float = 'left'; @@ -185,7 +185,7 @@ }); // Find all the audioElements from the audioHolder - var label = 0; + var index = 0; $(page.audioElements).each(function(index,element){ // Find URL of track // In this jQuery loop, variable 'this' holds the current audioElement. @@ -198,6 +198,20 @@ audioObject.bindInterface(orNode); } else { // Create a slider per track + switch(audioObject.specification.parent.label) { + case "none": + label = ""; + break; + case "letter": + label = String.fromCharCode(97 + index); + break; + case "capital": + label = String.fromCharCode(65 + index); + break; + default: + label = ""+index; + break; + } var sliderObj = new sliderObject(audioObject,label); if (typeof page.initialPosition === "number") @@ -211,7 +225,7 @@ sliderBox.appendChild(sliderObj.holder); audioObject.bindInterface(sliderObj); interfaceContext.commentBoxes.createCommentBox(audioObject); - label += 1; + index += 1; } });
--- a/interfaces/mushra.js Wed Mar 09 15:00:19 2016 +0000 +++ b/interfaces/mushra.js Thu Mar 10 17:08:10 2016 +0000 @@ -61,7 +61,7 @@ }; // Create Submit (save) button var submit = document.createElement("button"); - submit.innerHTML = 'Submit'; + submit.innerHTML = 'Next'; submit.onclick = buttonSubmitClick; submit.id = 'submit-button'; submit.style.float = 'left'; @@ -183,7 +183,7 @@ currentTestHolder.repeatCount = audioHolderObject.repeatCount; // Find all the audioElements from the audioHolder - var label = 0; + var index = 0; $(audioHolderObject.audioElements).each(function(index,element){ // Find URL of track // In this jQuery loop, variable 'this' holds the current audioElement. @@ -196,6 +196,20 @@ audioObject.bindInterface(orNode); } else { // Create a slider per track + switch(audioObject.specification.parent.label) { + case "none": + label = ""; + break; + case "letter": + label = String.fromCharCode(97 + index); + break; + case "capital": + label = String.fromCharCode(65 + index); + break; + default: + label = ""+index; + break; + } var sliderObj = new sliderObject(audioObject,label); if (typeof audioHolderObject.initialPosition === "number") @@ -209,7 +223,7 @@ sliderBox.appendChild(sliderObj.holder); audioObject.bindInterface(sliderObj); interfaceContext.commentBoxes.createCommentBox(audioObject); - label += 1; + index += 1; } });
--- a/save.php Wed Mar 09 15:00:19 2016 +0000 +++ b/save.php Thu Mar 10 17:08:10 2016 +0000 @@ -1,11 +1,5 @@ <?php error_reporting(0); - try{ - date_default_timezone_get(); - } - catch(Exception $e){ - date_default_timezone_set('UTC'); // Sets to UTC if not specified anywhere in .ini - } header('Access-Control-Allow-Origin: *'); header("Content-type: text/xml"); $postText = file_get_contents('php://input'); @@ -23,13 +17,13 @@ if ($wbytes === FALSE) { // FileWrite failed - $xml = '<response state="error"><message>Could not write file "saves/'.$xmlfile.'"</message></response>'; + $xml = '<response state="error"><message>Could not write file "'.$filename.'"</message></response>'; echo $xml; return; } fclose($fileHandle); - // Return JSON confirmation data - $xml = '<response state="OK"><message>OK</message><file bytes="'.$wbytes.'">"saves/'.$xmlfile.'"</file></response>'; + // Return XML confirmation data + $xml = '<response state="OK"><message>OK</message><file bytes="'.$wbytes.'">"'.$filename.'"</file></response>'; echo $xml; -?> +?> \ No newline at end of file
--- a/test-schema.xsd Wed Mar 09 15:00:19 2016 +0000 +++ b/test-schema.xsd Thu Mar 10 17:08:10 2016 +0000 @@ -9,6 +9,21 @@ <xs:attribute name="id" type="xs:ID"/> <xs:attribute name="mandatory" type="xs:boolean"/> <xs:attribute name="name" type="xs:string"/> + + <xs:attribute name="preSilence" default="0"> + <xs:simpleType> + <xs:restriction base="xs:decimal"> + <xs:minInclusive value="0.0"/> + </xs:restriction> + </xs:simpleType> + </xs:attribute> + <xs:attribute name="postSilence" default="0"> + <xs:simpleType> + <xs:restriction base="xs:decimal"> + <xs:minInclusive value="0.0"/> + </xs:restriction> + </xs:simpleType> + </xs:attribute> <!-- define complex elements--> <xs:element name="waet"> @@ -23,6 +38,7 @@ <xs:element name="setup"> <xs:complexType> <xs:sequence> + <xs:element name="exitText" type="xs:string" minOccurs="0" maxOccurs="1"/> <xs:element ref="survey" minOccurs="0" maxOccurs="2"/> <xs:element ref="metric" maxOccurs="1"/> <xs:element ref="interface" maxOccurs="1"/> @@ -33,6 +49,9 @@ <xs:attribute name="testPages" type="xs:nonNegativeInteger" default="0"/> <xs:attribute name="loudness" type="xs:nonPositiveInteger" use="optional"/> <xs:attribute name="sampleRate" type="xs:positiveInteger" use="optional"/> + <xs:attribute name="calibration" type="xs:boolean" default="false"/> + <xs:attribute ref="preSilence"/> + <xs:attribute ref="postSilence"/> </xs:complexType> </xs:element> @@ -51,8 +70,22 @@ <xs:attribute name="randomiseOrder" type="xs:boolean" default="false"/> <xs:attribute name="repeatCount" type="xs:nonNegativeInteger" default="0"/> <xs:attribute name="loop" type="xs:boolean" default="false"/> + <xs:attribute name="synchronous" type="xs:boolean" default="false"/> <xs:attribute name="showElementComments" type="xs:boolean" default="false"/> <xs:attribute name="loudness" type="xs:nonPositiveInteger" use="optional"/> + <xs:attribute name="label" use="optional" default="default"> + <xs:simpleType> + <xs:restriction base="xs:string"> + <xs:enumeration value="default"/> + <xs:enumeration value="none"/> + <xs:enumeration value="number"/> + <xs:enumeration value="letter"/> + <xs:enumeration value="capital"/> + </xs:restriction> + </xs:simpleType> + </xs:attribute> + <xs:attribute ref="preSilence"/> + <xs:attribute ref="postSilence"/> </xs:complexType> </xs:element> @@ -136,6 +169,8 @@ </xs:simpleType> </xs:attribute> <xs:attribute name="loudness" type="xs:nonPositiveInteger" use="optional"/> + <xs:attribute ref="preSilence"/> + <xs:attribute ref="postSilence"/> </xs:complexType> </xs:element>