changeset 462:0db687b660f1 Dev_main

Updated AB files. One comparison per page node, all elements in the page compared against each other.
author Nicholas Jillings <n.g.r.jillings@se14.qmul.ac.uk>
date Tue, 12 Jan 2016 11:18:01 +0000
parents f5b148187b72
children 32757cefeee0
files AB.css AB.js example_eval/AB_example.xml
diffstat 3 files changed, 181 insertions(+), 165 deletions(-) [+]
line wrap: on
line diff
--- a/AB.css	Tue Jan 12 09:16:39 2016 +0000
+++ b/AB.css	Tue Jan 12 11:18:01 2016 +0000
@@ -53,6 +53,10 @@
 	background-color: #FF0000;
 }
 
+div.disabled {
+	background-color: #AAA;
+}
+
 div.selected {
 	background-color: #008000;
 }
--- a/AB.js	Tue Jan 12 09:16:39 2016 +0000
+++ b/AB.js	Tue Jan 12 11:18:01 2016 +0000
@@ -68,35 +68,11 @@
 	// Construct the AB Boxes
 	var boxes = document.createElement('div');
 	boxes.align = "center";
-	var boxA = document.createElement('div');
-	boxA.className = 'comparitor-holder';
-	boxA.id = 'comparitor-A';
-	var selector = document.createElement('div');
-	selector.className = 'comparitor-selector';
-	selector.innerHTML = '<span>A</span>';
-	var playback = document.createElement('button');
-	playback.className = 'comparitor-button';
-	playback.textContent = "Listen";
-	boxA.appendChild(selector);
-	boxA.appendChild(playback); 
-	boxes.appendChild(boxA);
-	
-	var boxB = document.createElement('div');
-	boxB.className = 'comparitor-holder';
-	boxB.id = 'comparitor-B';
-	var selector = document.createElement('div');
-	selector.className = 'comparitor-selector';
-	selector.innerHTML = '<span>B</span>';
-	var playback = document.createElement('button');
-	playback.className = 'comparitor-button';
-	playback.textContent = "Listen";
-	boxB.appendChild(selector);
-	boxB.appendChild(playback); 
-	boxes.appendChild(boxB);
+	boxes.id = "box-holders";
 	
 	var submit = document.createElement('button');
 	submit.id = "submit";
-	submit.onclick = function() {interfaceContext.comparitor.submitButton();};
+	submit.onclick = buttonSubmitClick;
 	submit.className = "big-button";
 	submit.textContent = "submit";
 	submit.style.position = "absolute";
@@ -115,7 +91,6 @@
 	// Load the full interface
 	testState.initialise();
 	testState.advanceState();
-	resizeWindow(null);
 }
 
 function loadTest(audioHolderObject)
@@ -135,146 +110,133 @@
 	
 	// Populate the comparitor object
 	interfaceContext.comparitor = new Comparitor(audioHolderObject);
-	interfaceContext.comparitor.progress();
+	resizeWindow(null);
 }
 
 function Comparitor(audioHolderObject)
-{
-	this.pairs = [];
-	this.listened = [false, false];
-	this.selected = null;
-	this.index = -1;
-	this.currentPair = null;
-	this.progress = function()
+{	
+	this.comparitorBox = function(audioElement,id,text)
 	{
-		this.index++;
-		if (this.index >= this.pairs.length)
+		this.parent = audioElement;
+		this.id = id;
+		this.value = 0;
+		this.disabled = true;
+		this.box = document.createElement('div');
+		this.box.className = 'comparitor-holder';
+		this.box.setAttribute('track-id',audioElement.id);
+		this.box.id = 'comparitor-'+text;
+		this.selector = document.createElement('div');
+		this.selector.className = 'comparitor-selector disabled';
+		var selectorText = document.createElement('span');
+		selectorText.textContent = text;
+		this.selector.appendChild(selectorText);
+		this.playback = document.createElement('button');
+		this.playback.className = 'comparitor-button';
+		this.playback.disabled = true;
+		this.playback.textContent = "Listen";
+		this.box.appendChild(this.selector);
+		this.box.appendChild(this.playback);
+		this.selector.onclick = function()
 		{
-			buttonSubmitClick();
-			return;
-		}
-		$(".comparitor-selector").removeClass('selected');
-		this.listened = [false, false];
-		this.selected = null;
-		this.currentPair = this.pairs[this.index];
+			if ($(event.currentTarget).hasClass('disabled'))
+			{
+				console.log("Please wait until sample has loaded");
+				return;
+			}
+			$(".comparitor-selector").removeClass('selected');
+			var id = event.currentTarget.parentElement.getAttribute('track-id');
+			interfaceContext.comparitor.selected = id;
+			$(event.currentTarget).addClass('selected');
+			for (var i=0; i<interfaceContext.comparitor.comparitors.length; i++)
+			{
+				var obj = interfaceContext.comparitor.comparitors[i];
+				if (i == id) {
+					obj.value = 1;
+				} else {
+					obj.value = 0;
+				}
+				obj.parent.metric.moved(audioEngineContext.timer.getTestTime(),obj.value);
+			}
+		};
+		this.playback.onclick = function()
+		{
+			$('.comparitor-button').text('Listen');
+			var id = event.currentTarget.parentElement.getAttribute('track-id');
+			audioEngineContext.play(id);
+			$(event.currentTarget).text('Playing');
+		};
+		
+		this.enable = function()
+		{
+			if (this.parent.state == 1)
+			{
+				$(this.selector).removeClass('disabled');
+				this.playback.disabled = false;
+			}
+		};
+		this.updateLoading = function(progress)
+		{
+			if (progress != 100)
+			{
+				progress = String(progress);
+				progress = progress.split('.')[0];
+				this.playback.textContent = progress+'%';
+			} else {
+				this.playback.textContent = "Listen";
+			}
+		};
+		this.exportXMLDOM = function(audioObject)
+		{
+			var node = storage.document.createElement('value');
+			node.textContent = this.value;
+			return node;
+		};
+		this.getValue = function() {
+			return this.value;	
+		};
 	};
 	
+	this.boxHolders = document.getElementById('box-holders');
+	this.boxHolders.innerHTML = null;
+	this.comparitors = [];
+	this.selected = null;
+	
 	// First generate the Audio Objects for the Audio Engine
-	$(audioHolderObject.audioElements).each(function(index,element){
+	for (var index=0; index<audioHolderObject.audioElements.length; index++)
+	{
+		var element = audioHolderObject.audioElements[index];
 		if (index == audioHolderObject.outsideReference || element.type == 'outside-reference')
 		{
 			console.log("WARNING - AB cannot have fixed reference");
 		}
 		var audioObject = audioEngineContext.newTrack(element);
-		audioObject.interfaceDOM = new comparitorElementObject(audioObject);
-	});
-	
-	// Now generate the pairings
-	this.pairs = [];
-	var num_elems = audioEngineContext.audioObjects.length;
-	for (var i=0; i<num_elems; i++)
-	{
-		for (var j=i+1; j<num_elems; j++)
-		{
-			var pair = {
-				A: audioEngineContext.audioObjects[i],
-				B: audioEngineContext.audioObjects[j]
-			};
-			this.pairs.push(pair);
-		}
+		var node = new this.comparitorBox(audioObject,index,String.fromCharCode(65 + index));
+		audioObject.bindInterface(node);
+		this.comparitors.push(node);
+		this.boxHolders.appendChild(node.box);
 	}
-	
-	// Generate Interface Bindings
-	$('.comparitor-selector').click(function(){
-		$(".comparitor-selector").removeClass('selected');
-		if (interfaceContext.comparitor.currentPair != null)
-		{
-			var side = this.parentElement.id.split('-')[1];
-			var pair = interfaceContext.comparitor.currentPair;
-			var selected = eval('interfaceContext.comparitor.currentPair.'+side);
-			interfaceContext.comparitor.selected = selected;
-			$(this).addClass('selected');
-		}
-	});
-	
-	$('.comparitor-button').click(function(){
-		$('.comparitor-button').text('Listen');
-		if (interfaceContext.comparitor.currentPair != null)
-		{
-			var side = this.parentElement.id.split('-')[1];
-			var pair = interfaceContext.comparitor.currentPair;
-			var selected = eval('interfaceContext.comparitor.currentPair.'+side);
-			audioEngineContext.play(selected.id);
-			$(this).text('Playing');
-			if (side == 'A') {interfaceContext.comparitor.listened[0] = true;}
-			else if (side == 'B') {interfaceContext.comparitor.listened[1] = true;}
-		}
-	});
-	
-	this.submitButton = function()
-	{
-		audioEngineContext.stop();
-		$('.comparitor-button').text('Listen');
-		// Check both A and B have been listened to
-		if (this.listened[0] == false || this.listened[1] == false)
-		{
-			console.log("Listen to both A and B before submitting");
-			alert("Listen to both A and B before submitting");
-			return;
-		}
-		if (this.selected == null)
-		{
-			console.log("Select either A or B before submitting");
-			alert("Select either A or B before submitting");
-			return;
-		}
-		this.pairs[this.index].A.interfaceDOM.results.push({
-			compair: this.pairs[this.index].B.specification.id,
-			choice: this.selected
-		});
-		this.pairs[this.index].B.interfaceDOM.results.push({
-			compair: this.pairs[this.index].A.specification.id,
-			choice: this.selected
-		});
-		this.progress();
-	};
 	return this;
 }
 
-function comparitorElementObject(audioObject)
-{
-	// The Interface Object for the comparitor
-	this.parent = audioObject;
-	this.results = [];
-	this.state = 0;
-	this.enable = function()
-	{
-		this.state = 1;
-	};
-	this.exportXMLDOM = function(audioObject) {
-		var obj = [];
-		for (var result of this.results)
-		{
-			var node = storage.document.createElement('value');
-			node.setAttribute('comparitorId',result.compair);
-			node.setAttribute('selectedId',result.choice.specification.id);
-			node.textContent = result.choice.specification.id;
-			obj.push(node);
-		}
-		return obj;
-	};
-	this.getValue = function() {
-		return 0;
-	};
-}
-
 function resizeWindow(event)
 {
-	var totalWidth = 620;
-	var diff = (window.innerWidth - totalWidth)/2;
-	document.getElementById('comparitor-A').style.left = diff +'px';
-	document.getElementById('comparitor-B').style.left = diff +360 +'px';
 	document.getElementById('submit').style.left = (window.innerWidth-250)/2 + 'px';
+	var numObj = interfaceContext.comparitor.comparitors.length;
+	var boxW = numObj*260;
+	var spaces = numObj-1;
+	var spaceSize = 50;
+	var remainder = window.innerWidth - boxW;
+	if (remainder < spaces*spaceSize)
+	{
+		spaceSize = Math.floor(spaces/remainder);
+	}
+	var totalW = boxW + spaces*spaceSize;
+	var diff = (window.innerWidth - totalW)/2;
+	for (var i=0; i<interfaceContext.comparitor.comparitors.length; i++)
+	{
+		var obj = interfaceContext.comparitor.comparitors[i];
+		obj.box.style.left = diff + (260+spaceSize)*i + 'px';
+	}
 }
 
 function buttonSubmitClick()
@@ -282,31 +244,56 @@
 	var checks = [];
 	checks = checks.concat(testState.currentStateMap.interfaces[0].options);
 	checks = checks.concat(specification.interfaces.options);
+	var canContinue = true;
 	
 	for (var i=0; i<checks.length; i++) {
 		if (checks[i].type == 'check')
 		{
 			switch(checks[i].name) {
+			case 'fragmentPlayed':
+				// Check if all fragments have been played
+				var checkState = interfaceContext.checkAllPlayed();
+				if (checkState == false) {canContinue = false;}
+				break;
+			case  'fragmentFullPlayback':
+				// Check all fragments have been played to their full length
+				var checkState = interfaceContext.checkFragmentsFullyPlayed();
+				if (checkState == false) {canContinue = false;}
+				break;
+			case 'fragmentMoved':
+				// Check all fragment sliders have been moved.
+				var checkState = interfaceContext.checkAllMoved();
+				if (checkState == false) {canContinue = false;}
+				break;
+			case 'fragmentComments':
+				// Check all fragment sliders have been moved.
+				var checkState = interfaceContext.checkAllCommented();
+				if (checkState == false) {canContinue = false;}
+				break;
 			default:
 				console.log("WARNING - Check option "+checks[i].check+" is not supported on this interface");
 				break;
 			}
 
 		}
+		if (!canContinue) {break;}
 	}
-    if (audioEngineContext.status == 1) {
-        var playback = document.getElementById('playback-button');
-        playback.click();
-    // This function is called when the submit button is clicked. Will check for any further tests to perform, or any post-test options
-    } else
-    {
-        if (audioEngineContext.timer.testStarted == false)
-        {
-            alert('You have not started the test! Please press start to begin the test!');
-            return;
-        }
-    }
-    testState.advanceState();
+	if (canContinue)
+	{
+	    if (audioEngineContext.status == 1) {
+	        var playback = document.getElementById('playback-button');
+	        playback.click();
+	    // This function is called when the submit button is clicked. Will check for any further tests to perform, or any post-test options
+	    } else
+	    {
+	        if (audioEngineContext.timer.testStarted == false)
+	        {
+	            alert('You have not started the test! Please press start to begin the test!');
+	            return;
+	        }
+	    }
+	    testState.advanceState();
+	}
 }
 
 function pageXMLSave(store, pageSpecification)
--- a/example_eval/AB_example.xml	Tue Jan 12 09:16:39 2016 +0000
+++ b/example_eval/AB_example.xml	Tue Jan 12 11:18:01 2016 +0000
@@ -1,6 +1,6 @@
 <?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="2" loudness="-23" sampleRate="44100">
+	<setup interface="AB" projectReturn="save.php" randomiseOrder='false' testPages="2" loudness="-23" sampleRate="44100">
 		<survey location="before">
 			<surveyentry type="question" id="sessionId" mandatory="true">
 				<statement>Please enter your name.</statement>
@@ -14,7 +14,7 @@
 				<option name="researcher">Research in the field of audio</option>
 			</surveyentry>
 			<surveyentry type="statement">
-				<statement>This is an example of an 'APE'-style test, with two pages, using the test stimuli in 'example_eval/'.</statement>
+				<statement>This is an example of an 'AB'-style test, with two pages, using the test stimuli in 'example_eval/'.</statement>
 			</surveyentry>
 		</survey>
 		<survey location="after">
@@ -38,7 +38,10 @@
 		<metric>
 			<metricenable>testTimer</metricenable>
 			<metricenable>elementTimer</metricenable>
+			<metricenable>elementInitialPosition</metricenable>
+			<metricenable>elementTracker</metricenable>
 			<metricenable>elementFlagListenedTo</metricenable>
+			<metricenable>elementFlagMoved</metricenable>
 			<metricenable>elementListenTracker</metricenable>
 		</metric>
 		<interface>
@@ -53,12 +56,11 @@
 		<interface>
 			<title>Depth</title>
 		</interface>
-		<audioelement url="0.wav" id="track-0" type="anchor"/>
+		<audioelement url="0.wav" id="track-0"/>
 		<audioelement url="1.wav" id="track-1"/>
-		<audioelement url="2.wav" id="track-2"/>
 		<survey location="before">
 			<surveyentry type="statement">
-				<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>
+				<statement>A two way comparison using randomised element order, automatic loudness and synchronised looping.</statement>
 			</surveyentry>
 		</survey>
 		<survey location="after">
@@ -67,4 +69,27 @@
 			</surveyentry>
 		</survey>
 	</page>
+	<page id='test-1' hostURL="example_eval/" randomiseOrder='true' repeatCount='0' loop='false' showElementComments='true' loudness="-12">
+		<commentboxprefix>Comment on fragment</commentboxprefix>
+		<interface>
+			<title>Depth</title>
+		</interface>
+		<audioelement url="0.wav" id="track-2"/>
+		<audioelement url="1.wav" id="track-3"/>
+		<audioelement url="2.wav" id="track-4"/>
+		<audioelement url="3.wav" id="track-5"/>
+		<audioelement url="4.wav" id="track-6"/>
+		<audioelement url="5.wav" id="track-7"/>
+		<audioelement url="6.wav" id="track-8"/>
+		<survey location="before">
+			<surveyentry type="statement">
+				<statement>A 7 way comparison using randomised element order and synchronised looping.</statement>
+			</surveyentry>
+		</survey>
+		<survey location="after">
+			<surveyentry type="question" id="genre-1" mandatory="true">
+				<statement>Please enter the genre.</statement>
+			</surveyentry>
+		</survey>
+	</page>
 </waet>
\ No newline at end of file