changeset 459:f6c9f9e5400e Dev_main

Added AB test interface
author Nicholas Jillings <n.g.r.jillings@se14.qmul.ac.uk>
date Mon, 11 Jan 2016 16:32:26 +0000
parents 46b4af266cdf
children fd941017792b
files AB.css AB.js ape.js core.js example_eval/AB_example.xml index.html mushra.js
diffstat 7 files changed, 208 insertions(+), 37 deletions(-) [+]
line wrap: on
line diff
--- a/AB.css	Mon Jan 11 13:56:30 2016 +0000
+++ b/AB.css	Mon Jan 11 16:32:26 2016 +0000
@@ -31,23 +31,39 @@
 	background-color: #ddd
 }
 
+button.big-button {
+	width: 250px;
+	height: 40px;
+	font-size: 1.2em;
+}
+
 div.comparitor-holder {
 	width: 260px;
 	height: 300px;
 	border:  black 1px solid;
 	position: absolute;
+	padding-top: 5px;
 }
 
 div.comparitor-selector {
-	width: 250px;
+	width: 248px;
 	height: 250px;
 	border: black 1px solid;
 	position: relative;
+	background-color: #FF0000;
 }
 
-div.comparitor-button {
+div.selected {
+	background-color: #008000;
+}
+
+div.comparitor-selector span {
+	font-size: 4em;
+}
+
+button.comparitor-button {
 	width: 250px;
-	height: 50px;
+	height: 38px;
 	position: relative;
-	background-color: #FF0000;
+	margin-top: 5px;
 }
--- a/AB.js	Mon Jan 11 13:56:30 2016 +0000
+++ b/AB.js	Mon Jan 11 16:32:26 2016 +0000
@@ -65,6 +65,46 @@
 	var feedbackHolder = document.createElement('div');
 	feedbackHolder.id = 'feedbackHolder';
 	
+	// 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);
+	
+	var submit = document.createElement('button');
+	submit.id = "submit";
+	submit.onclick = function() {interfaceContext.comparitor.submitButton();};
+	submit.className = "big-button";
+	submit.textContent = "submit";
+	submit.style.position = "absolute";
+	submit.style.top = '466px';
+		
+	feedbackHolder.appendChild(boxes);
+	feedbackHolder.appendChild(submit);
+	
 	// Inject into HTML
 	testContent.appendChild(title); // Insert the title
 	testContent.appendChild(pagetitle);
@@ -75,6 +115,7 @@
 	// Load the full interface
 	testState.initialise();
 	testState.advanceState();
+	resizeWindow(null);
 }
 
 function loadTest(audioHolderObject)
@@ -94,6 +135,7 @@
 	
 	// Populate the comparitor object
 	interfaceContext.comparitor = new Comparitor(audioHolderObject);
+	interfaceContext.comparitor.progress();
 }
 
 function Comparitor(audioHolderObject)
@@ -101,23 +143,20 @@
 	this.pairs = [];
 	this.listened = [false, false];
 	this.selected = null;
-	this.index = 0;
-	this.feedbackHolder = document.getElementById('feedbackHolder');
-	this.injectA = document.createElement('div');
-	this.injectA.id = 'inject-A';
-	this.injectB = document.createElement('div');
-	this.injectB.id = 'inject-B';
-	this.submitButton = document.createElement('button');
+	this.index = -1;
+	this.currentPair = null;
 	this.progress = function()
 	{
+		this.index++;
 		if (this.index >= this.pairs.length)
 		{
 			buttonSubmitClick();
 			return;
 		}
+		$(".comparitor-selector").removeClass('selected');
 		this.listened = [false, false];
 		this.selected = null;
-		var pair = this.pairs[this.index];
+		this.currentPair = this.pairs[this.index];
 	};
 	
 	// First generate the Audio Objects for the Audio Engine
@@ -144,14 +183,38 @@
 			this.pairs.push(pair);
 		}
 	}
-	this.feedbackHolder.innerHTML = null;
-	this.feedbackHolder.appendChild(this.injectA);
-	this.feedbackHolder.appendChild(this.injectB);
-	this.feedbackHolder.appendChild(this.submitButton);
 	
-	this.submitButton.id = 'submit';
-	this.submitButton.onclick = function()
+	// 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)
 		{
@@ -165,7 +228,15 @@
 			alert("Select either A or B before submitting");
 			return;
 		}
-		this.pairs[this.index].A
+		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;
 }
@@ -174,25 +245,36 @@
 {
 	// The Interface Object for the comparitor
 	this.parent = audioObject;
-	this.holder = document.createElement('div');
-	this.play = document.createElement('button');
-	this.select = document.createElement('div');
-	
-	this.holder.className = "comparitor-holder";
-	this.holder.appendChild(this.select);
-	this.holder.appendChild(this.play);
-	this.holder.align = "center";
-	this.holder.setAttribute('trackIndex',audioObject.id);
-	
-	this.play.className = "comparitor-button";
-	this.play.textContent = "Listen";
-	
-	this.select.className = "comparitor-selector";
+	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';
 }
 
 function buttonSubmitClick() // TODO: Only when all songs have been played!
--- a/ape.js	Mon Jan 11 13:56:30 2016 +0000
+++ b/ape.js	Mon Jan 11 16:32:26 2016 +0000
@@ -636,7 +636,7 @@
 		// Called by the audioObject holding this element. Must be present
 		var obj = [];
 		$(this.trackSliderObjects).each(function(i,trackObj){
-			var node = document.createElement('value');
+			var node = storage.document.createElement('value');
 			node.setAttribute("interface-name",trackObj.getAttribute("interface-name"));
 			node.textContent = convSliderPosToRate(trackObj);
 			obj.push(node);
--- a/core.js	Mon Jan 11 13:56:30 2016 +0000
+++ b/core.js	Mon Jan 11 16:32:26 2016 +0000
@@ -1232,7 +1232,9 @@
 					this.storeDOM.appendChild(interfaceXML[i]);
 				}
 			}
-			this.storeDOM.appendChild(this.commentDOM.exportXMLDOM(this));
+			if (this.commentDOM != null) {
+				this.storeDOM.appendChild(this.commentDOM.exportXMLDOM(this));
+			}
 		}
 		var nodes = this.metric.exportXMLDOM();
 		var mroot = this.storeDOM.getElementsByTagName('metric')[0];
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/example_eval/AB_example.xml	Mon Jan 11 16:32:26 2016 +0000
@@ -0,0 +1,70 @@
+<?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">
+		<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 an example of an 'APE'-style test, with two pages, using the test stimuli in 'example_eval/'.</statement>
+			</surveyentry>
+		</survey>
+		<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. Please click 'submit' and your results will appear in the 'saves/' folder.</statement>
+			</surveyentry>
+		</survey>
+		<metric>
+			<metricenable>testTimer</metricenable>
+			<metricenable>elementTimer</metricenable>
+			<metricenable>elementFlagListenedTo</metricenable>
+			<metricenable>elementListenTracker</metricenable>
+		</metric>
+		<interface>
+			<interfaceoption type="check" name="fragmentMoved"/>
+			<interfaceoption type="check" name="scalerange" min="25" max="75"/>
+			<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="-12">
+		<commentboxprefix>Comment on fragment</commentboxprefix>
+		<interface>
+			<title>Depth</title>
+		</interface>
+		<audioelement url="0.wav" id="track-0" type="anchor"/>
+		<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>
+			</surveyentry>
+		</survey>
+		<survey location="after">
+			<surveyentry type="question" id="genre-0" mandatory="true">
+				<statement>Please enter the genre.</statement>
+			</surveyentry>
+		</survey>
+	</page>
+</waet>
\ No newline at end of file
--- a/index.html	Mon Jan 11 13:56:30 2016 +0000
+++ b/index.html	Mon Jan 11 16:32:26 2016 +0000
@@ -53,6 +53,7 @@
 			<ul>
 				<li><a href="index.html?url=example_eval/project.xml" target="_blank">APE interface test example</a></li>
 				<li><a href="index.html?url=example_eval/mushra_example.xml" target="_blank">MUSHRA interface test example</a></li>
+				<li><a href="index.html?url=example_eval/AB_example.xml" target="_blank">AB interface test example</a></li>
 				<li><a href="test_create/test_create.html" target="_blank">Test creator</a></li>
 				<li><a href="analyse.html" target="_blank">Analysis and diagnostics of results</a></li>
 			</ul>
--- a/mushra.js	Mon Jan 11 13:56:30 2016 +0000
+++ b/mushra.js	Mon Jan 11 16:32:26 2016 +0000
@@ -279,7 +279,7 @@
 	
 	this.exportXMLDOM = function(audioObject) {
 		// Called by the audioObject holding this element. Must be present
-		var node = document.createElement('value');
+		var node = storage.document.createElement('value');
 		node.textContent = this.slider.value;
 		return node;
 	};