Mercurial > hg > webaudioevaluationtool
changeset 538:6d652a6c80ed Dev_main
Merge into dev_main
author | Nicholas Jillings <n.g.r.jillings@se14.qmul.ac.uk> |
---|---|
date | Mon, 22 Feb 2016 12:33:56 +0000 |
parents | 2a723261ee3e (diff) 16bf7d5fa618 (current diff) |
children | 4a69b3ba474d |
files | core.js |
diffstat | 15 files changed, 484 insertions(+), 23 deletions(-) [+] |
line wrap: on
line diff
--- a/.hgignore Sun Feb 21 11:18:08 2016 +0000 +++ b/.hgignore Mon Feb 22 12:33:56 2016 +0000 @@ -49,3 +49,5 @@ re:^docs/DMRN+10/img/\._TestCreate\.png$ re:^docs/DMRN+10/img/\._APE\.png$ re:^docs/DMRN+10/img/\._MUSHRA\.png$ +example_eval/samples/* +
--- a/analyse.html Sun Feb 21 11:18:08 2016 +0000 +++ b/analyse.html Mon Feb 22 12:33:56 2016 +0000 @@ -24,7 +24,7 @@ xmlFileFolder = "saves"; // array of XML files // THIS IS WHERE YOU SPECIFY RESULT XML FILES TO ANALYSE - var xmlFiles = ['test-0.xml','test-1.xml','test-2.xml','test-3.xml']; + var xmlFiles = ['test-2.xml']; //TODO: make retrieval of file names automatic / drag files on here @@ -284,6 +284,7 @@ xmlhttp=new ActiveXObject("Microsoft.XMLHTTP"); } xmlhttp.open("GET",xmlFileName,false); + xmlhttp.overrideMimeType('text/xml'); xmlhttp.send(); return xmlhttp.responseXML; } @@ -300,11 +301,11 @@ fileNameArray.push(xmlFiles[fileIndex]); // get root of XML file - root = xml.getElementsByTagName('browserevaluationresult')[0]; + root = xml.getElementsByTagName('waetresult')[0]; // get subject ID, add to array if not already there - pretest = root.getElementsByTagName('pretest')[0]; - subjectID = pretest.getElementsByTagName('comment')[0]; + pretestSurveyResult = root.getElementsByTagName('surveyresult')[0]; + subjectID = pretestSurveyResult.getElementsByTagName('comment')[0]; if (subjectID){ if (subjectID.getAttribute('id')!='sessionId') { // warning in console when not available console.log(xmlFiles[fileIndex]+': no SessionID available'); @@ -378,7 +379,7 @@ // which songs did they do if (xml != null) { // if file exists // get root of XML file - root = xml.getElementsByTagName('browserevaluationresult')[0]; + root = xml.getElementsByTagName('waetresult')[0]; // go over all audioholders // document.getElementById('div_survey_'+xmlFileName).innerHTML += '<strong>Audioholders: </strong>'; // audioholderNodes = root.getElementsByTagName('audioholder'); @@ -415,7 +416,7 @@ function makePlots() { //TODO: split into different functions // TEMPORARY - makeTimeline(xmlFileFolder+"/"+xmlFiles[7]); + makeTimeline(xmlFileFolder+"/"+xmlFiles[0]); // create value array var ratings = []; // 3D matrix of ratings (audioholder, audioelement, subject) @@ -432,7 +433,7 @@ xml = readXML(xmlFileName); if (xml != null) { // if file exists // get root of XML file - root = xml.getElementsByTagName('browserevaluationresult')[0]; + root = xml.getElementsByTagName('waetresult')[0]; // go over all audioholders audioholderNodes = root.getElementsByTagName('audioholder'); for (audioholderIndex = 0; audioholderIndex < audioholderNodes.length; audioholderIndex++) { @@ -594,7 +595,7 @@ return; // do nothing; exit function } // get root of XML file - root = xml.getElementsByTagName('browserevaluationresult')[0]; + root = xml.getElementsByTagName('waetresult')[0]; audioholder_time = 0; previous_audioholder_time = 0; // time spent before current audioholder
--- a/core.js Sun Feb 21 11:18:08 2016 +0000 +++ b/core.js Mon Feb 22 12:33:56 2016 +0000 @@ -344,11 +344,13 @@ if (xmlhttp.status != 200 && xmlhttp.readyState == 4) { createProjectSave(null); } else { - if (xmlhttp.responseXML == null) + var parser = new DOMParser(); + var xmlDoc = parser.parseFromString(xmlhttp.responseText, "application/xml"); + if (xmlDoc == null) { createProjectSave('null'); } - var response = xmlhttp.responseXML.childNodes[0]; + var response = xmlDoc.childNodes[0]; if (response.getAttribute('state') == "OK") { var file = response.getElementsByTagName('file')[0]; @@ -2254,7 +2256,7 @@ this.id = null; this.parent = null; this.type = null; - this.marker = false; + this.marker = null; this.enforce = false; this.gain = 1.0; this.schema = specification.schema.getAllElementsByName('audioelement')[0];;
--- a/save.php Sun Feb 21 11:18:08 2016 +0000 +++ b/save.php Mon Feb 22 12:33:56 2016 +0000 @@ -1,6 +1,7 @@ <?php header('Access-Control-Allow-Origin: *'); header("Content-type: text/xml"); + error_reporting(0); $postText = file_get_contents('php://input'); $sha1_hash = sha1($postText); $datetime = date('ymdHis');
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/comment_parser.html Mon Feb 22 12:33:56 2016 +0000 @@ -0,0 +1,72 @@ +<html lang="en"> + <head> + <meta charset="utf-8" /> + <script type="text/javascript"> + function getXML() + { + var XMLHttp = new XMLHttpRequest(); + XMLHttp.open("GET","comment_parser.php?format=XML",true); + XMLHttp.onload = function() { + // Now we have the XML data, extract + var parse = new DOMParser(); + var ajax = parse.parseFromString(XMLHttp.response,'text/xml'); + + var parent = document.createElement("div"); + parent.appendChild(ajax.children[0]); + var file = [parent.innerHTML]; + var bb = new Blob(file,{type : 'application/xml'}); + generateLink(bb,".xml"); + } + XMLHttp.send(); + } + + function getJSON() + { + var XMLHttp = new XMLHttpRequest(); + XMLHttp.open("GET","comment_parser.php?format=JSON",true); + XMLHttp.onload = function() { + // Now we have the XML data, extract + var file = [XMLHttp.response]; + var bb = new Blob(file,{type : 'application/json'}); + generateLink(bb,".json"); + } + XMLHttp.send(); + } + + function getCSV() + { + var XMLHttp = new XMLHttpRequest(); + XMLHttp.open("GET","comment_parser.php?format=CSV",true); + XMLHttp.onload = function() { + // Now we have the XML data, extract + var file = [XMLHttp.response]; + var bb = new Blob(file,{type : 'text/csv'}); + generateLink(bb,".csv"); + } + XMLHttp.send(); + } + + function generateLink(blobfile,fmt) + { + var dnlk = window.URL.createObjectURL(blobfile); + var a = document.createElement("a"); + a.hidden = ''; + a.href = dnlk; + a.download = "save"+fmt; + a.textContent = "Save File"; + document.getElementById("download").appendChild(a); + } + </script> + </head> + <body> + <h1>WAET Test Results Analysis</h1> + <h2>Comment Extraction</h2> + <p>All of the XMLs in the server 'saves/' directory are automatically parsed and downloaded, extracting only the comments. Simply select the comments you wish to extract below and your desired data format.</p> + <div id="download"></div> + <div> + <button onclick="getXML();">XML</button> + <button onclick="getJSON();">JSON</button> + <button onclick="getCSV();">CSV</button> + </div> + </body> +</html> \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/comment_parser.php Mon Feb 22 12:33:56 2016 +0000 @@ -0,0 +1,146 @@ +<?php +// Comment Parser for PHP +class audioElement { + function __construct($id) { + $this->id = $id; + $this->comments = array(); + } + function addComment($str) { + array_push($this->comments,$str); + } +} + +class testPage { + function __construct($id) { + $this->id = $id; + $this->elements = array(); + } +} +// XML Saves location - assumes it will be saves/ +$saves = glob("../saves/*.xml"); +$comment_struct = array(); +if (is_array($saves)) +{ + foreach($saves as $filename) { + $xml_string = file_get_contents($filename, FILE_TEXT); + $xml_object = simplexml_load_string($xml_string); + if ($xml_object == false) { + echo "<h1>FATAL</h1> <span>could not parse file ".$filename.": </span>"; + foreach(libxml_get_errors() as $error) { + echo "<br>", $error->message; + } + } else { + // Iterate over each audioHolder node + foreach($xml_object->page as $pageInstance) + { + // Find the page in the comment_struct + $page_struct = null; + foreach($comment_struct as $comment_struct_page) + { + if ($pageInstance['id'] == $comment_struct_page->id) + { + $page_struct = $comment_struct_page; + break; + } + } + if ($page_struct == null) { + array_push($comment_struct,new testPage($pageInstance['id'])); + $page_struct = $comment_struct[count($comment_struct)-1]; + } + // Get the audioelements of the page + foreach($pageInstance->audioelement as $fragment) + { + // Find the page in the comment_struct + $element_struct = null; + foreach($page_struct->elements as $page_struct_element) + { + if ($fragment['id'] == $page_struct_element->id) + { + $element_struct = $page_struct_element; + break; + } + } + if ($element_struct == null) { + array_push($page_struct->elements,new audioElement($fragment['id'])); + $element_struct = $page_struct->elements[count($page_struct->elements)-1]; + } + $element_struct->addComment($fragment->comment->response); + } + } + } + } + // Now we have a sub <xml> containing all comment data + switch($_GET['format']) { + case "XML": + // Convert to an XML + $doc_struct = new SimpleXMLElement('<waetprocess/>'); + foreach($comment_struct as $page_struct) + { + $doc_page = $doc_struct->addChild("page"); + $doc_page->addAttribute("id",$page_struct->id); + foreach($page_struct->elements as $element_struct) + { + $doc_element = $doc_page->addChild("audioelement"); + $doc_element->addAttribute("id",$element_struct->id); + foreach($element_struct->comments as $comment) + { + $doc_comment = $doc_element->addChild("comment",$comment); + } + } + } + echo $doc_struct->asXML(); + break; + case "JSON": + // Convert to JSON + $doc_string = '{ "pages": ['; + for($page_index = 0; $page_index < count($comment_struct); $page_index++ ) + { + $page_struct = $comment_struct[$page_index]; + $doc_page = '{"id": "'.$page_struct->id.'", "elements": ['; + for($element_index = 0; $element_index < count($page_struct->elements); $element_index++ ) + { + $element_struct = $page_struct->elements[$element_index]; + $doc_element = '{"id": "'.$element_struct->id.'", "comments": ['; + for($comment_index = 0; $comment_index < count($element_struct->comments); $comment_index++ ) + { + $doc_comment = '"'.$element_struct->comments[$comment_index].'"'; + if ($comment_index < count($element_struct->comments)-1) { + $doc_comment = $doc_comment.','; + } + $doc_element = $doc_element.$doc_comment; + } + $doc_element = $doc_element.']}'; + if ($element_index < count($page_struct->elements)-1) { + $doc_element = $doc_element.','; + } + $doc_page = $doc_page.$doc_element; + } + $doc_page = $doc_page.']}'; + if ($page_index < count($comment_struct)-1) { + $doc_page = $doc_page.','; + } + $doc_string = $doc_string.$doc_page; + } + $doc_string = $doc_string."]}"; + echo $doc_string; + break; + case "CSV": + // Conver to CSV + // The CSV has three columns: page, element, comment + $doc_string = "page,element,comment"."\r\n"; + foreach($comment_struct as $page_struct) + { + foreach($page_struct->elements as $element_struct) + { + foreach($element_struct->comments as $comment) + { + $doc_string = $doc_string.$page_struct->id.",".$element_struct->id.",".$comment."\r\n"; + } + } + } + echo $doc_string; + } +} else { + echo "FATAL - No saved XML files discovered"; +} +?> \ No newline at end of file
--- a/scripts/comment_parser.py Sun Feb 21 11:18:08 2016 +0000 +++ b/scripts/comment_parser.py Mon Feb 22 12:33:56 2016 +0000 @@ -41,11 +41,11 @@ root = tree.getroot() # get list of all page names - for audioholder in root.findall("./audioholder"): # iterate over pages + for audioholder in root.findall("./page"): # iterate over pages page_name = audioholder.get('id') # get page name if page_name is None: # ignore 'empty' audio_holders - print "WARNING: " + file + " contains empty audio holder. (comment_parser.py)" + print "WARNING: " + file + " contains empty page. (comment_parser.py)" break # create folder [page_name] if not yet created
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/score_parser.php Mon Feb 22 12:33:56 2016 +0000 @@ -0,0 +1,192 @@ +<?php +// Value parser for WAET XML +// testPage --> axis --> element --> value +class nestedObject { + function __construct($id) { + $this->id = $id; + $this->nest = array(); + $this->type = null; + $this->num = 0; + } + function addNewChild($id) { + if ($this->type == null) { + $this->type = "nest"; + } + if ($this->type == "nest") { + $obj = new nestedObject($id); + array_push($this->nest,$obj); + $this->num = count($this->nest); + return $this->nest[$this->num-1]; + } + return null; + } + function findChild($checkId) { + if ($this->type == "nest"){ + foreach($this->nest as $child) + { + if (strcmp($checkId,$child->id) == 0) { + return $child; + } + } + } + return null; + } + function addValue($val) { + if ($this->type == null) { + $this->type = "value"; + } + if ($this->type == "value") { + array_push($this->nest,$val); + $this->num = count($this->nest); + return $this->nest[$this->num-1]; + } + return null; + } +} + +// Build the root nest object to hold the testPages +$root = new nestedObject("root"); + +// XML Saves location - assumes it will be saves/ +$saves = glob("../saves/*.xml"); +if (is_array($saves)) +{ + foreach($saves as $filename) { + $xml_string = file_get_contents($filename, FILE_TEXT); + $xml_object = simplexml_load_string($xml_string); + if ($xml_object == false) { + echo "<h1>FATAL</h1> <span>could not parse file ".$filename.": </span>"; + foreach(libxml_get_errors() as $error) { + echo "<br>", $error->message; + } + } else { + // Iterate over each $page node + foreach($xml_object->page as $pageInstance) + { + // Find in the nest + $pageInstanceId = $pageInstance['id']; + $page_nest = $root->findChild($pageInstanceId); + if ($page_nest == null) { + $page_nest = $root->addNewChild($pageInstanceId); + } + + // Iterate over each $element node + foreach($pageInstance->audioelement as $element) { + + // Now get the <value> tags + foreach($element->value as $value) { + $axis_nest = null; + $axisName = "default"; + if (isset($value['interface-name'])) + { + // Find the axis nest + $axisName = $value['interface-name']; + } + + $axis_nest = $page_nest->findChild($axisName); + if ($axis_nest == null) { + $axis_nest = $page_nest->addNewChild($axisName); + } + + // Find our specific element tag + $elementId = $element['id']; + $element_nest = $axis_nest->findChild($elementId); + if ($element_nest == null) { + $element_nest = $axis_nest->addNewChild($elementId); + } + // Now push our value + $element_nest->addValue($value); + } + } + } + } + } + // We now have a structure in $root. EXPORT IT + switch($_GET['format']) { + case "XML": + // Convert to XML + $doc_root = new SimpleXMLElement('<waetprocess/>'); + foreach($root->nest as $page) { + $doc_page = $doc_root->addChild("page"); + $doc_page->addAttribute("id",$page->id); + foreach($page->nest as $axis) { + $doc_axis = $doc_page->addChild("interface"); + $doc_axis->addAttribute("name",$axis->id); + foreach($axis->nest as $element) { + $doc_element = $doc_axis->addChild("audioelement"); + $doc_element->addAttribute("id",$element->id); + foreach($element->nest as $value) { + $doc_value = $doc_element->addChild("value",$value); + } + } + } + } + echo $doc_root->asXML(); + break; + case "JSON": + // Convert to JSON + $doc_root = '{ "pages": ['; + for ($pageIndex = 0; $pageIndex < $root->num; $pageIndex++) + { + $page = $root->nest[$pageIndex]; + $doc_page = '{ "id": "'.$page->id.'", "axis": ['; + for($axisIndex = 0; $axisIndex < $page->num; $axisIndex++) + { + $axis = $page->nest[$axisIndex]; + $doc_axis = '{ "name": "'.$axis->id.'", "elements": ['; + for($elementIndex = 0; $elementIndex < $axis->num; $elementIndex++) + { + $element = $axis->nest[$elementIndex]; + $doc_element = '{ "id": "'.$element->id.'", "values": ['; + for ($valueIndex = 0; $valueIndex < $element->num; $valueIndex++) + { + $doc_element = $doc_element."".strval($element->nest[$valueIndex]); + if ($valueIndex < $element->num-1) { + $doc_element = $doc_element.', '; + } + } + $doc_element = $doc_element.']}'; + if ($elementIndex < $axis->num-1) { + $doc_element = $doc_element.', '; + } + $doc_axis = $doc_axis.$doc_element; + } + $doc_axis = $doc_axis.']}'; + if ($axisIndex < $page->num-1) { + $doc_axis = $doc_axis.', '; + } + $doc_page = $doc_page.$doc_axis; + } + $doc_page = $doc_page.']}'; + if ($pageIndex < $root->num-1) { + $doc_page = $doc_page.', '; + } + $doc_root = $doc_root.$doc_page; + } + $doc_root = $doc_root.']}'; + echo $doc_root; + break; + case "CSV": + // Convert to CSV + // CSV Columts: page, axis, element, value + $doc_string = "page,axis,element,value"."\r\n"; + foreach($root->nest as $page){ + foreach($page->nest as $axis) { + foreach($axis->nest as $element) { + foreach($element->nest as $value) { + $doc_string = $doc_string.$page->id; + $doc_string = $doc_string.$axis->id; + $doc_string = $doc_string.$element->id; + $doc_string = $doc_string.$value; + $doc_string = $doc_string."\r\n"; + } + } + } + } + echo $doc_string; + } +} else { + echo "FATAL - No saved XML files discovered"; +} + +?> \ No newline at end of file
--- a/scripts/score_parser.py Sun Feb 21 11:18:08 2016 +0000 +++ b/scripts/score_parser.py Mon Feb 22 12:33:56 2016 +0000 @@ -43,7 +43,7 @@ subject_id = file_name[:-4] # file name (without extension) as subject ID # get list of all pages this subject evaluated - for audioholder in root.findall("./audioholder"): # iterate over pages + for audioholder in root.findall("./page"): # iterate over pages page_name = audioholder.get('id') # get page name if page_name is None: # ignore 'empty' audio_holders
--- a/test-schema.xsd Sun Feb 21 11:18:08 2016 +0000 +++ b/test-schema.xsd Mon Feb 22 12:33:56 2016 +0000 @@ -168,7 +168,7 @@ <xs:element name="survey"> <xs:complexType> <xs:sequence> - <xs:element name="surveyentry" maxOccurs="unbounded"> + <xs:element name="surveyentry" minOccurs="0" maxOccurs="unbounded"> <xs:complexType> <xs:sequence> <xs:element ref="statement" minOccurs="1" maxOccurs="1"/>
--- a/test_create/attributes.json Sun Feb 21 11:18:08 2016 +0000 +++ b/test_create/attributes.json Mon Feb 22 12:33:56 2016 +0000 @@ -6,7 +6,7 @@ "projectReturn": "Results Return URL", "randomiseOrder": "Randomise Order", "testPages": "Test Pages", - "loudness": "Target Loudess (LUFS)", + "loudness": "Target Loudness (LUFS)", "sampleRate": "Required Sample Rate", "hostURL": "Element URL Prefix", "repeatCount": "Repeat Count", @@ -20,4 +20,4 @@ "gain": "Gain (dB)", "marker": "Marker", "boxsize": "Box Size" -} \ No newline at end of file +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test_create/custom.css Mon Feb 22 12:33:56 2016 +0000 @@ -0,0 +1,23 @@ + +div#content > div.node{ + background-color: rgb(200,228,151); +} + +div#content > div#setup{ + background-color: coral; +} + +input:disabled+span{ + text-decoration: line-through; +} + +div.attribute{ + float: none; +} +div.attribute input{ + max-width: 100%; + width: 300px; +} +div.attribute input[type=radio], div.attribute input[type=checkbox]{ + width: 10px; +} \ No newline at end of file
--- a/test_create/style.css Sun Feb 21 11:18:08 2016 +0000 +++ b/test_create/style.css Mon Feb 22 12:33:56 2016 +0000 @@ -70,6 +70,16 @@ color: rgb(100,100,100); } + +div#content > div.node{ + background-color: rgb(200,228,151); +} + +div#content > div#setup{ + background-color: coral; +} + + div.node { float: left; padding: 10px; @@ -87,7 +97,7 @@ } div.node-attributes { min-width: 92%; - float: left; + float: none; padding: 10px; } div.attribute { @@ -103,9 +113,16 @@ min-width: 92%; } div.attribute input { - max-width: 100px; + max-width: 100%; + width: 300px; margin-right: 10px; } div.attribute input[type=number] { width: 80px; +} +div.attribute input[type=radio], div.attribute input[type=checkbox]{ + width: 10px; +} +input:disabled+span{ + text-decoration: line-through; } \ No newline at end of file
--- a/test_create/test_core.js Sun Feb 21 11:18:08 2016 +0000 +++ b/test_create/test_core.js Mon Feb 22 12:33:56 2016 +0000 @@ -1182,9 +1182,9 @@ obj.text.textContent = checkText.children[i].textContent; metric.children.push(obj); metric.childrenDOM.appendChild(obj.root); - for (var i=0; i<specification.metrics.enabled.length; i++) + for (var j=0; j<specification.metrics.enabled.length; j++) { - if (specification.metrics.enabled[i] == obj.name) + if (specification.metrics.enabled[j] == obj.name) { obj.input.checked = true; break; @@ -1872,6 +1872,9 @@ } // Build the components + if (this.specification.interfaces.length == 0) { + this.specification.interfaces.push(new specification.interfaceNode()); + } for (var interfaceObj of this.specification.interfaces) { var newInterface = new this.parent.interfaceNode(this.parent,interfaceObj);
--- a/test_create/test_create.html Sun Feb 21 11:18:08 2016 +0000 +++ b/test_create/test_create.html Mon Feb 22 12:33:56 2016 +0000 @@ -2,7 +2,9 @@ <head> <!-- This defines the test creator tool for the Web Audio Evaluation Toolbox --> <link rel='stylesheet' type="text/css" href="style.css"/> + <link rel='stylesheet' type="text/css" href="custom.css"/> <script type="text/javascript"> + window.onbeforeunload = function (e) {var message = 'If you leave the page now, any unsaved changes will be lost', e = e || window.event; if (e) { e.returnValue = message;}return message;}; // Copy of Specifiation node from Core.js function Specification() { // Handles the decoding of the project specification XML into a simple JavaScript Object. @@ -572,7 +574,7 @@ this.id = null; this.parent = null; this.type = null; - this.marker = false; + this.marker = null; this.enforce = false; this.gain = 1.0; this.schema = specification.schema.getAllElementsByName('audioelement')[0];; @@ -632,4 +634,4 @@ <div id="blanket"></div> <div id="content"></div> </body> -</html> \ No newline at end of file +</html>