changeset 607:328f24798462 multiple-tests-concatenation

working, hacked together.
author Giulio Moro <giuliomoro@yahoo.it>
date Fri, 11 Mar 2016 16:49:47 +0000
parents 6833d8c2b52e
children 0256f3748b27
files .hgignore assets/images/arrow-checkbox-unchecked.png assets/images/checkbox-checked.png assets/images/checkbox-unchecked-disabled.png assets/images/ok.png core.js example_eval/ABshort.xml example_eval/labelling.xml example_eval/post_survey.xml example_eval/pre_survey.xml index.html save.php test_base.php test_list.php
diffstat 14 files changed, 407 insertions(+), 17 deletions(-) [+]
line wrap: on
line diff
--- a/.hgignore	Sun Mar 06 20:55:00 2016 +0000
+++ b/.hgignore	Fri Mar 11 16:49:47 2016 +0000
@@ -50,4 +50,6 @@
 re:^docs/DMRN+10/img/\._APE\.png$
 re:^docs/DMRN+10/img/\._MUSHRA\.png$
 example_eval/samples/*
-	
+.hgrc
+*.orig	
+
Binary file assets/images/arrow-checkbox-unchecked.png has changed
Binary file assets/images/checkbox-checked.png has changed
Binary file assets/images/checkbox-unchecked-disabled.png has changed
Binary file assets/images/ok.png has changed
--- a/core.js	Sun Mar 06 20:55:00 2016 +0000
+++ b/core.js	Fri Mar 11 16:49:47 2016 +0000
@@ -15,9 +15,9 @@
 var popup; // Hold the interfacePopup object
 var testState;
 var currentTrackOrder = []; // Hold the current XML tracks in their (randomised) order
-var audioEngineContext; // The custome AudioEngine object
-var projectReturn; // Hold the URL for the return
-
+var audioEngineContext; // The custom AudioEngine object
+var projectReturn; 
+var returnUrl; // Holds the url to be redirected to at the end of the test
 
 // Add a prototype to the bufferSourceNode to reference to the audioObject holding it
 AudioBufferSourceNode.prototype.owner = undefined;
@@ -338,11 +338,28 @@
 		a.textContent = "Save File";
 		
 		popup.showPopup();
-		popup.popupContent.innerHTML = "</span>Please save the file below to give to your test supervisor</span><br>";
+		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;
-		xmlhttp.open("POST",destURL,true);
+		destUrlFull = destURL;
+		var saveFilenamePrefix;
+		// parse the querystring of destUrl, get the "id" (if any) and append it to destUrl
+		var qs = returnUrl.split("?");
+		if(qs.length == 2){
+			qs = qs[1];
+			qs = qs.split("&");
+			for(var n = 0; n < qs.length; n++){
+				var pair = qs[n].split("=");
+	      if (pair[0] == "id") {
+	      	saveFilenamePrefix = pair[1];
+	      }
+			}
+		}
+		if(typeof(saveFilenamePrefix) !== "undefined"){
+			destUrlFull+="?saveFilenamePrefix="+saveFilenamePrefix;
+		}
+		xmlhttp.open("POST",destUrlFull,true);
 		xmlhttp.setRequestHeader('Content-Type', 'text/xml');
 		xmlhttp.onerror = function(){
 			console.log('Error saving file to server! Presenting download locally');
@@ -368,6 +385,9 @@
 					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);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/example_eval/ABshort.xml	Fri Mar 11 16:49:47 2016 +0000
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<waet xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="test-schema.xsd">
+	<setup interface="AB" projectReturn="save.php" randomiseOrder='true' testPages="1" loudness="-23" sampleRate="44100">
+		<metric>
+			<metricenable>testTimer</metricenable>
+			<metricenable>elementTimer</metricenable>
+			<metricenable>elementInitialPosition</metricenable>
+			<metricenable>elementTracker</metricenable>
+			<metricenable>elementFlagListenedTo</metricenable>
+			<metricenable>elementFlagMoved</metricenable>
+			<metricenable>elementListenTracker</metricenable>
+		</metric>
+		<interface>
+			<interfaceoption type="check" name="fragmentMoved"/>
+			<interfaceoption type="check" name="scalerange" min="25" max="75"/>
+            <interfaceoption type="check" name="fragmentPlayed" />
+			<interfaceoption type="show" name='playhead'/>
+			<interfaceoption type="show" name="page-count"/>
+            <interfaceoption type="show" name='volume'/>
+		</interface>
+	</setup>
+    <page id="test-0" hostURL="example_eval/" randomiseOrder="true" repeatCount="0" loop="false" showElementComments="true" loudness="-12">
+        <commentboxprefix>Comment on fragment</commentboxprefix>
+        <interface>
+            <title>Which of these do you prefer</title>
+        </interface>
+        <audioelement url="3.wav" id="track-0"/>
+        <audioelement url="5.wav" id="track-1"/>
+    </page>
+</waet>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/example_eval/labelling.xml	Fri Mar 11 16:49:47 2016 +0000
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<waet xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="test-schema.xsd">
+	<setup interface="likert" projectReturn="save.php">
+		<metric>
+			<metricenable>testTimer</metricenable>
+			<metricenable>elementTimer</metricenable>
+			<metricenable>elementInitialPosition</metricenable>
+			<metricenable>elementTracker</metricenable>
+			<metricenable>elementFlagListenedTo</metricenable>
+			<metricenable>elementFlagMoved</metricenable>
+			<metricenable>elementListenTracker</metricenable>
+		</metric>
+		<interface>
+			<interfaceoption type="check" name="fragmentMoved"/>
+			<interfaceoption type="check" name="scalerange" min="25" max="75"/>
+            <interfaceoption type="show" name="volume"/>
+			<interfaceoption type="show" name='playhead'/>
+			<interfaceoption type="show" name="page-count"/>
+		</interface>
+	</setup>
+	<page id='test-0' hostURL="example_eval/" randomiseOrder='true' repeatCount='0' loop='true' showElementComments='true' loudness="-23">
+		<interface>
+			<scales>
+				<scalelabel position="0">(1) Very Annoying</scalelabel>
+				<scalelabel position="25">(2) Annoying</scalelabel>
+				<scalelabel position="50">(3) Slightly Annoying</scalelabel>
+				<scalelabel position="75">(4) Audible but not Annoying</scalelabel>
+				<scalelabel position="100">(5) Inaudible</scalelabel>
+			</scales>
+		</interface>
+		<audioelement url="0.wav" id="track-1"/>
+        <audioelement url="2.wav" id="track-3" type="outside-reference"/>
+	</page>
+</waet>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/example_eval/post_survey.xml	Fri Mar 11 16:49:47 2016 +0000
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="utf-8"?>
+<waet xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="test-schema.xsd">
+	<setup interface="AB" projectReturn="save.php" randomiseOrder='true' testPages="1" loudness="-23" sampleRate="44100">
+        <survey location="after">
+            <surveyentry type="question" id="location" mandatory="true" boxsize="large">
+                <statement>Please enter your location. (example mandatory text question)</statement>
+            </surveyentry>
+            <surveyentry type="number" id="age" min="0">
+                <statement>Please enter your age (example non-mandatory number question)</statement>
+            </surveyentry>
+            <surveyentry type="radio" id="rating">
+                <statement>Please rate this interface (example radio button question)</statement>
+                <option name="bad">Bad</option>
+                <option name="poor">Poor</option>
+                <option name="good">Good</option>
+                <option name="great">Great</option>
+            </surveyentry>
+            <surveyentry type="statement">
+                <statement>Thank you for taking this listening test. May God be with you.</statement>
+            </surveyentry>
+        </survey>
+		<metric>
+			<metricenable>testTimer</metricenable>
+			<metricenable>elementTimer</metricenable>
+			<metricenable>elementInitialPosition</metricenable>
+			<metricenable>elementTracker</metricenable>
+			<metricenable>elementFlagListenedTo</metricenable>
+			<metricenable>elementFlagMoved</metricenable>
+			<metricenable>elementListenTracker</metricenable>
+		</metric>
+		<interface>
+			<interfaceoption type="show" name='playhead'/>
+			<interfaceoption type="show" name="page-count"/>
+            <interfaceoption type="show" name='volume'/>
+            <!--interfaceoption type="submit" name="post-submit-dialog">
+                <a href="javascript:document.referrer">Click here to continue with the next test</a>
+            </interfaceoption-->
+		</interface>
+	</setup>
+    <page id="test-0" hostURL="example_eval/" randomiseOrder="true" repeatCount="0" loop="false" showElementComments="true" loudness="-12">
+        <commentboxprefix>Comment on fragment</commentboxprefix>
+        <interface>
+            <title>SKIP THIS PAGE. I WANT 0 PAGES!!!!</title>
+        </interface>
+        <audioelement url="2.wav" id="track-0"/>
+        <audioelement url="1.wav" id="track-1"/>
+    </page>
+</waet>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/example_eval/pre_survey.xml	Fri Mar 11 16:49:47 2016 +0000
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="utf-8"?>
+<waet xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="test-schema.xsd">
+	<setup interface="AB" projectReturn="save.php" randomiseOrder='true' testPages="1" loudness="-23" sampleRate="44100">
+		<survey location="before">
+			<surveyentry type="question" id="sessionId" mandatory="true">
+				<statement>Please enter your name.</statement>
+			</surveyentry>
+			<surveyentry type="checkbox" id="checkboxtest" mandatory="true">
+				<statement>Please select with which activities you have any experience (example checkbox question)</statement>
+				<option name="musician">Playing a musical instrument</option>
+				<option name="soundengineer">Recording or mixing audio</option>
+				<option name="developer">Developing audio software</option>
+				<option name="hwdesigner">Designing or building audio hardware</option>
+				<option name="researcher">Research in the field of audio</option>
+			</surveyentry>
+			<surveyentry type="statement">
+				<statement>This is a preliminary test for a study on the Hammond organ. You will be presented with pairs of stimuli. For each pair you will be asked to single out the one note that was produced by a heavier touch.
+                    
+                    Feel free to add any comments on the stimuli in the boxes at the bottom of each page of the test.	</statement>
+			</surveyentry>
+		</survey>
+		<metric>
+			<metricenable>testTimer</metricenable>
+			<metricenable>elementTimer</metricenable>
+			<metricenable>elementInitialPosition</metricenable>
+			<metricenable>elementTracker</metricenable>
+			<metricenable>elementFlagListenedTo</metricenable>
+			<metricenable>elementFlagMoved</metricenable>
+			<metricenable>elementListenTracker</metricenable>
+		</metric>
+		<interface>
+			<interfaceoption type="check" name="fragmentMoved"/>
+			<interfaceoption type="check" name="scalerange" min="25" max="75"/>
+            <interfaceoption type="check" name="fragmentPlayed" />
+			<interfaceoption type="show" name='playhead'/>
+			<interfaceoption type="show" name="page-count"/>
+            <interfaceoption type="show" name='volume'/>
+            <!--interfaceoption type="submit" name="post-submit-dialog">
+                <a href="javascript:document.referrer">Click here to continue with the next test</a>
+            </interfaceoption-->
+		</interface>
+	</setup>
+    <page id="test-0" hostURL="example_eval/" randomiseOrder="true" repeatCount="0" loop="false" showElementComments="true" loudness="-12">
+        <commentboxprefix>Comment on fragment</commentboxprefix>
+        <interface>
+            <title>SKIP OVER THIS, I WANT ZERO PAGES!!!</title>
+        </interface>
+        <audioelement url="1.wav" id="track-0"/>
+        <audioelement url="1.wav" id="track-1"/>
+    </page>
+</waet>
\ No newline at end of file
--- a/index.html	Sun Mar 06 20:55:00 2016 +0000
+++ b/index.html	Fri Mar 11 16:49:47 2016 +0000
@@ -32,12 +32,17 @@
 				{
 					// Split each request into
 					searchQueries[i] = searchQueries[i].split('=');
-					if (searchQueries[i][0] == "url")
+					var key = searchQueries[i][0];
+					var string = searchQueries[i][1];
+					if (key === "url")
 					{
-						url = searchQueries[i][1];
+						url = string;
+					}
+					if (key === "returnUrl"){
+						returnUrl = decodeURIComponent(string);
 					}
 				}
-				loadProjectSpec(url);
+				loadProjectSpec(url+"?"+Math.random()); // force resource reload, in case the server is lazy
 				window.onbeforeunload = function() {
 					return "Please only leave this page once you have completed the tests. Are you sure you have completed all testing?";
 				};
@@ -49,7 +54,8 @@
 		<!-- Load up the default page interface allowing for project setting loads, even if hard-coded-->
 		<!-- Actual test interface design should be contained in the .js for ease of dynamic content-->
 		<div id='topLevelBody'>
-            <span>Web Audio Evaluation Toolbox</span>
+            <span>Loading Web Audio Evaluation Toolbox ...</span>
+            <noscript>Javascript must be enabled in your browsers in order to be able to view this website</noscript>
 		</div>
         <div id="popupHolder" class="popupHolder" style="visibility: hidden; z-index: -1">
             <div id="popupContent">
--- a/save.php	Sun Mar 06 20:55:00 2016 +0000
+++ b/save.php	Fri Mar 11 16:49:47 2016 +0000
@@ -1,17 +1,18 @@
 <?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
-    }
+	try{
+	    date_default_timezone_get();
+	}
+	catch(Exception $e){
+	    date_default_timezone_set('UTC'); // Sets to UTC if not specified anywhere in .ini
+	}
+	$saveFilenamePrefix = isset($_GET['saveFilenamePrefix']) ? $_GET['saveFilenamePrefix'].'-' : '';
 	header('Access-Control-Allow-Origin: *');
 	header("Content-type: text/xml");
 	$postText = file_get_contents('php://input');
 	$sha1_hash = sha1($postText);
 	$datetime = date('ymdHis');
-	$xmlfile = "save".$datetime."-".$sha1_hash.".xml";
+	$xmlfile = $saveFilenamePrefix."save".$datetime."-".$sha1_hash.".xml";
 	$fileHandle = fopen("saves/".$xmlfile, 'w');
 	if ($fileHandle == FALSE)
 	{
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test_base.php	Fri Mar 11 16:49:47 2016 +0000
@@ -0,0 +1,169 @@
+<?php
+function fisherYatesShuffle(&$items, $seed) // http://stackoverflow.com/questions/6557805/randomize-a-php-array-with-a-seed
+{
+  @mt_srand($seed);
+  for ($i = count($items) - 1; $i > 0; $i--)
+  {
+    $j = @mt_rand(0, $i);
+    $tmp = $items[$i];
+    $items[$i] = $items[$j];
+    $items[$j] = $tmp;
+  }
+}
+function url_origin( $s, $use_forwarded_host = false ) //http://stackoverflow.com/questions/6768793/get-the-full-url-in-php
+{
+  $ssl      = ( ! empty( $s['HTTPS'] ) && $s['HTTPS'] == 'on' );
+  $sp       = strtolower( $s['SERVER_PROTOCOL'] );
+  $protocol = substr( $sp, 0, strpos( $sp, '/' ) ) . ( ( $ssl ) ? 's' : '' );
+  $port     = $s['SERVER_PORT'];
+  $port     = ( ( ! $ssl && $port=='80' ) || ( $ssl && $port=='443' ) ) ? '' : ':'.$port;
+  $host     = ( $use_forwarded_host && isset( $s['HTTP_X_FORWARDED_HOST'] ) ) ? $s['HTTP_X_FORWARDED_HOST'] : ( isset( $s['HTTP_HOST'] ) ? $s['HTTP_HOST'] : null );
+  $host     = isset( $host ) ? $host : $s['SERVER_NAME'] . $port;
+  return $protocol . '://' . $host;
+}
+
+function full_url( $s, $use_forwarded_host = false )
+{
+  return url_origin( $s, $use_forwarded_host ) . $s['REQUEST_URI'];
+}
+  $toAppendToUrl = '';
+  if(isset($_GET["id"])){
+    $id = $_GET["id"];
+  } else {
+    $max = pow(2, 24);
+    $rand = openssl_random_pseudo_bytes($max);
+    $id = sha1($rand);
+    if(sizeof($_GET) == 0){ // if the query string is empty
+      $toAppendToUrl = '?';  // start the query string
+    } else {
+      $toAppendToUrl = '&'; // otherwise, append to it
+    }
+    $toAppendToUrl .= 'id='.$id;
+  }
+  if(isset($_GET["next"])){
+    $next = $_GET["next"];
+  } else {
+    $next = 0;
+  }
+
+  $absoluteUrl = full_url($_SERVER).$toAppendToUrl;
+  // echo "<br \>".$absoluteUrl."<br \>";
+  // if there is a "next" in the query string, create a version of $absoluteUrl with
+  // next:=next+1
+  $absoluteUrlSplit = explode('?', $absoluteUrl);
+  $absoluteUrlNextPlusOne = $absoluteUrl;
+  if(sizeof($absoluteUrlSplit) === 2){
+    $queryString = $absoluteUrlSplit[1];
+    parse_str($queryString, $queryStringParsed);
+    $queryStringParsed['next'] += 1;
+    $queryString = http_build_query($queryStringParsed);
+    $absoluteUrlNextPlusOne = $absoluteUrlSplit[0]."?".$queryString;
+  }
+  $defaultTestEntry = Array('url' => null, 'string' => null, 'class' => 'disabled', 'a' => false, 'editable' => false);
+
+  require_once('test_list.php'); //this returns $tests
+
+  if($next == sizeof($tests)){
+    // we are done 
+    $bottomBox = 'The test is complete, thank you for your participation.';
+  } else {
+    $bottomBox = 'If you want to have a break, come back to this page and continue from where you left, just come back to this URL:<br /><div id="currentUrl">'.$absoluteUrl.'</div>';
+  }
+  // until this point, the content of $tests will always be the same for a given $id,
+  // regardless of how many times we visited this page.
+  for($n = 0; $n < sizeof($tests); $n++ ){
+    //TODO: check if the corresponding file exists
+    // meantime, let us just rely on the GET variable 'next'
+    if($n <= $next){
+      $tests[$n]['a'] = true;
+      $tests[$n]['class'] = 'enabled done';
+  // if we are going to re-run a test, return to the same page
+      $tests[$n]['returnUrl'] = urlencode($absoluteUrl);
+    }
+    if($n == $next){
+      $tests[$n]['editable'] = true;
+      $tests[$n]['class'] = 'enabled editable';
+  // if we are going to run a new test, return to the same page with next:=next+1
+      $tests[$n]['returnUrl'] = urlencode($absoluteUrlNextPlusOne);
+    }
+  }
+?>
+<html>
+<head>
+  <style>
+ul.tests-list li{
+  margin: 10px 0 5px 0;
+
+}
+.done {
+  list-style-image: url('assets/images/checkbox-checked.png');
+}
+.done a {
+  color: green;
+}
+.editable{
+  list-style-image: url('assets/images/arrow-checkbox-unchecked.png');
+  list-style-position: inside;
+  margin-left: -30px;
+}
+.disabled{
+  color: grey;
+  text-decoration: line-through;
+  list-style-image: url('assets/images/checkbox-unchecked-disabled.png');
+}
+#currentUrl{
+  font-weight: bold;
+  padding-left: 20px;
+  padding-top: 5px;
+}
+
+  </style>
+  <script src="jquery-2.1.4.js"></script>
+  <script>
+  function confirmEditing(e){
+    var message = 'Are you sure you want to edit this item? All previous changes will be lost';
+    return window.confirm(message);
+  }
+  var elements;
+  $(document).ready(function(){
+    lis = $('ul');
+    elements = $('li.done:not(.editable)', lis);
+    for(var n = 0; n < elements.length; n++){
+      elements[n].onclick = confirmEditing;
+    }
+    history.pushState({}, null,  location.pathname+location.search+'<?php echo $toAppendToUrl; ?>');
+
+    // elements = $('li:not(.editable.done)', lis);
+    // for(var element in elements){
+    //   element.onclick = confirmEditing;
+    // }
+  });
+  </script>
+</head>
+<body>
+
+<ul class = "tests-list">
+<?php foreach($tests as $n => $test) : ?> 
+  <li class="test-element <?php echo $test['class'] ?>">
+<?php 
+if($test['a'] === true) {
+  // parameters passed to the test are used to keep track of the state and should be returned back to
+  // this page when it is called again.
+  // These parameters are:
+  // id= keeps track of the user and of the sorting of the tests in this page
+  // next= keeps track of the first test not yet undertaken
+  
+  echo '<a href="'.$test['url'].'&returnUrl='.$test['returnUrl'].'">'.$n.' - '.$test['string'].'</a>';
+} else {
+  echo $n.' - '.$test['string'];
+}
+?>
+  </li>
+<?php endforeach; ?>
+</ul>
+
+  <div id="bottomBox">
+  <?php if($bottomBox!=='') echo $bottomBox ?>
+  </div>
+</body>
+</html>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test_list.php	Fri Mar 11 16:49:47 2016 +0000
@@ -0,0 +1,29 @@
+<?php
+// need to generate an array $tests containing the tests in the order they shuold be executed
+  $preSurvey = $defaultTestEntry;
+  $preSurvey['url'] = 'index.html?url=example_eval/pre_survey.xml';
+  $preSurvey['string'] = 'Pre-survey';
+  
+  $postSurvey = $defaultTestEntry;
+  $postSurvey['url'] = 'index.html?url=example_eval/post_survey.xml';
+  $postSurvey['string'] = 'Post-survey';
+
+  $abTests = Array($defaultTestEntry, $defaultTestEntry, $defaultTestEntry, $defaultTestEntry);
+  $abTests[0]['url'] = 'index.html?url=example_eval/ABshort.xml';
+  $abTests[0]['string'] = 'AB0';
+  $abTests[1]['url'] = 'index.html?url=example_eval/ABshort.xml';
+  $abTests[1]['string'] = 'AB1';
+  $abTests[2]['url'] = 'index.html?url=example_eval/ABshort.xml';
+  $abTests[2]['string'] = 'AB2';
+  $abTests[3]['url'] = 'index.html?url=example_eval/ABshort.xml';
+  $abTests[3]['string'] = 'AB3';
+
+  $likertTest = $defaultTestEntry;
+  $likertTest['url'] = 'index.html?url=example_eval/labelling.xml';
+  $likertTest['string'] = 'Labelling';
+  // the shuffling of the elements is bound to the last 8 characters of $id
+  $seed = hexdec(substr($id, -8)); 
+  //shuffling only the order of the ABtests
+  fisherYatesShuffle($abTests, $seed);
+  $tests = array_merge(Array($preSurvey), $abTests, Array($likertTest), Array($postSurvey));
+  
\ No newline at end of file