comparison core.js @ 1634:90c5e3c53066

Major Update. All new state machine to track the session state and hold session data. Will enable new interfaces to be built on top and have the same common structures.
author Nicholas Jillings <nickjillings@users.noreply.github.com>
date Wed, 27 May 2015 16:45:48 +0100
parents 29fafd5c2f92
children 2dc61bd6494e
comparison
equal deleted inserted replaced
1633:29fafd5c2f92 1634:90c5e3c53066
7 7
8 /* create the web audio API context and store in audioContext*/ 8 /* create the web audio API context and store in audioContext*/
9 var audioContext; // Hold the browser web audio API 9 var audioContext; // Hold the browser web audio API
10 var projectXML; // Hold the parsed setup XML 10 var projectXML; // Hold the parsed setup XML
11 var popup; // Hold the interfacePopup object 11 var popup; // Hold the interfacePopup object
12 var testState;
12 var currentState; // Keep track of the current state (pre/post test, which test, final test? first test?) 13 var currentState; // Keep track of the current state (pre/post test, which test, final test? first test?)
13 var testXMLSetups = []; // Hold the parsed test instances 14 //var testXMLSetups = []; // Hold the parsed test instances
14 var testResultsHolders =[]; // Hold the results from each test for publishing to XML 15 //var testResultsHolders =[]; // Hold the results from each test for publishing to XML
15 var currentTrackOrder = []; // Hold the current XML tracks in their (randomised) order 16 var currentTrackOrder = []; // Hold the current XML tracks in their (randomised) order
16 var currentTestHolder; // Hold any intermediate results during test - metrics 17 //var currentTestHolder; // Hold any intermediate results during test - metrics
17 var audioEngineContext; // The custome AudioEngine object 18 var audioEngineContext; // The custome AudioEngine object
18 var projectReturn; // Hold the URL for the return 19 var projectReturn; // Hold the URL for the return
19 var preTestQuestions = document.createElement('PreTest'); // Store any pre-test question response 20 //var preTestQuestions = document.createElement('PreTest'); // Store any pre-test question response
20 var postTestQuestions = document.createElement('PostTest'); // Store any post-test question response 21 //var postTestQuestions = document.createElement('PostTest'); // Store any post-test question response
21 22
22 // Add a prototype to the bufferSourceNode to reference to the audioObject holding it 23 // Add a prototype to the bufferSourceNode to reference to the audioObject holding it
23 AudioBufferSourceNode.prototype.owner = undefined; 24 AudioBufferSourceNode.prototype.owner = undefined;
24 25
25 window.onload = function() { 26 window.onload = function() {
28 29
29 // Create a web audio API context 30 // Create a web audio API context
30 // Fixed for cross-browser support 31 // Fixed for cross-browser support
31 var AudioContext = window.AudioContext || window.webkitAudioContext; 32 var AudioContext = window.AudioContext || window.webkitAudioContext;
32 audioContext = new AudioContext; 33 audioContext = new AudioContext;
34
35 // Create test state
36 testState = new stateMachine();
33 37
34 // Create the audio engine object 38 // Create the audio engine object
35 audioEngineContext = new AudioEngine(); 39 audioEngineContext = new AudioEngine();
36 40
37 // Create the popup interface object 41 // Create the popup interface object
161 if (this.currentIndex < this.popupOptions.length) { 165 if (this.currentIndex < this.popupOptions.length) {
162 this.postNode(); 166 this.postNode();
163 } else { 167 } else {
164 // Reached the end of the popupOptions 168 // Reached the end of the popupOptions
165 this.hidePopup(); 169 this.hidePopup();
170 if (this.responses.nodeName == testState.stateResults[testState.stateIndex].nodeName) {
171 testState.stateResults[testState.stateIndex] = this.responses;
172 } else {
173 testState.stateResults[testState.stateIndex].appendChild(this.responses);
174 }
166 advanceState(); 175 advanceState();
167 } 176 }
168 } 177 }
169 } 178 }
170 179
171 function advanceState() 180 function advanceState()
172 { 181 {
173 console.log(currentState); 182 // Just for complete clarity
174 if (currentState == 'preTest') 183 testState.advanceState();
175 { 184 }
176 // End of pre-test, begin the test 185
177 preTestQuestions = popup.responses; 186 function stateMachine()
178 loadTest(0); 187 {
179 } else if (currentState == 'postTest') { 188 // Object prototype for tracking and managing the test state
180 postTestQuestions = popup.responses; 189 this.stateMap = [];
181 console.log('ALL COLLECTED!'); 190 this.stateIndex = null;
182 createProjectSave(projectReturn); 191 this.currentStateMap = [];
183 }else if (currentState.substr(0,10) == 'testRunPre') 192 this.currentIndex = null;
184 { 193 this.currentTestId = 0;
185 // Start the test 194 this.stateResults = [];
186 var testId = currentState.substr(11,currentState.length-10); 195 this.initialise = function(){
187 currentState = 'testRun-'+testId; 196 if (this.stateMap.length > 0) {
188 currentTestHolder.appendChild(popup.responses); 197 if(this.stateIndex != null) {
189 //audioEngineContext.timer.startTest(); 198 console.log('NOTE - State already initialise');
190 //audioEngineContext.play(); 199 }
191 } else if (currentState.substr(0,11) == 'testRunPost') 200 this.stateIndex = -1;
192 { 201 var that = this;
193 var testId = currentState.substr(12,currentState.length-11); 202 for (var id=0; id<this.stateMap.length; id++){
194 currentTestHolder.appendChild(popup.responses); 203 var name = this.stateMap[id].nodeName;
195 testEnded(testId); 204 var obj = document.createElement(name);
196 } else if (currentState.substr(0,7) == 'testRun') 205 this.stateResults.push(obj);
197 { 206 }
198 var testId = currentState.substr(8,currentState.length-7); 207 } else {
199 // Check if we have any post tests to perform 208 conolse.log('FATAL - StateMap not correctly constructed. EMPTY_STATE_MAP');
200 var postXML = $(testXMLSetups[testId]).find('PostTest')[0]; 209 }
201 if (postXML == undefined || postXML.childElementCount == 0) { 210 };
202 testEnded(testId); 211 this.advanceState = function(){
203 } 212 if (this.stateIndex == null) {
204 else if (postXML.childElementCount > 0) 213 this.initialise();
205 { 214 }
206 currentState = 'testRunPost-'+testId; 215 if (this.stateIndex == -1) {
207 popup.initState(postXML); 216 console.log('Starting test...');
208 } 217 }
209 } 218 if (this.currentIndex == null){
210 console.log(currentState); 219 if (this.currentStateMap.nodeName == "audioHolder") {
220 // Save current page
221 this.testPageCompleted(this.stateResults[this.stateIndex],this.currentStateMap,this.currentTestId);
222 this.currentTestId++;
223 }
224 this.stateIndex++;
225 if (this.stateIndex >= this.stateMap.length) {
226 console.log('Test Completed');
227 createProjectSave(projectReturn);
228 } else {
229 this.currentStateMap = this.stateMap[this.stateIndex];
230 if (this.currentStateMap.nodeName == "audioHolder") {
231 console.log('Loading test page');
232 loadTest(this.currentStateMap);
233 this.initialiseInnerState(this.currentStateMap);
234 } else if (this.currentStateMap.nodeName == "PreTest" || this.currentStateMap.nodeName == "PostTest") {
235 if (this.currentStateMap.childElementCount >= 1) {
236 popup.initState(this.currentStateMap);
237 } else {
238 this.advanceState();
239 }
240 } else {
241 this.advanceState();
242 }
243 }
244 } else {
245 this.advanceInnerState();
246 }
247 };
248
249 this.testPageCompleted = function(store, testXML, testId) {
250 // Function called each time a test page has been completed
251 // Can be used to over-rule default behaviour
252
253 pageXMLSave(store, testXML, testId);
254 }
255
256 this.initialiseInnerState = function(testXML) {
257 // Parses the received testXML for pre and post test options
258 this.currentStateMap = [];
259 var preTest = $(testXML).find('PreTest')[0];
260 var postTest = $(testXML).find('PostTest')[0];
261 if (preTest == undefined) {preTest = document.createElement("preTest");}
262 if (postTest == undefined){postTest= document.createElement("postTest");}
263 this.currentStateMap.push(preTest);
264 this.currentStateMap.push(testXML);
265 this.currentStateMap.push(postTest);
266 this.currentIndex = -1;
267 this.advanceInnerState();
268 }
269
270 this.advanceInnerState = function() {
271 this.currentIndex++;
272 if (this.currentIndex >= this.currentStateMap.length) {
273 this.currentIndex = null;
274 this.currentStateMap = this.stateMap[this.stateIndex];
275 this.advanceState();
276 } else {
277 if (this.currentStateMap[this.currentIndex].nodeName == "audioHolder") {
278 console.log("Loading test page"+this.currentTestId);
279 } else if (this.currentStateMap[this.currentIndex].nodeName == "PreTest") {
280 popup.initState(this.currentStateMap[this.currentIndex]);
281 } else if (this.currentStateMap[this.currentIndex].nodeName == "PostTest") {
282 popup.initState(this.currentStateMap[this.currentIndex]);
283 } else {
284 this.advanceInnerState();
285 }
286 }
287 }
288
289 this.previousState = function(){};
211 } 290 }
212 291
213 function testEnded(testId) 292 function testEnded(testId)
214 { 293 {
215 pageXMLSave(testId); 294 pageXMLSave(testId);
301 xmlhttp.send(file); 380 xmlhttp.send(file);
302 } 381 }
303 return submitDiv; 382 return submitDiv;
304 } 383 }
305 384
385 // Only other global function which must be defined in the interface class. Determines how to create the XML document.
386 function interfaceXMLSave(){
387 // Create the XML string to be exported with results
388 var xmlDoc = document.createElement("BrowserEvaluationResult");
389 xmlDoc.appendChild(returnDateNode());
390 for (var i=0; i<testState.stateResults.length; i++)
391 {
392 xmlDoc.appendChild(testState.stateResults[i]);
393 }
394
395 return xmlDoc;
396 }
397
306 function AudioEngine() { 398 function AudioEngine() {
307 399
308 // Create two output paths, the main outputGain and fooGain. 400 // Create two output paths, the main outputGain and fooGain.
309 // Output gain is default to 1 and any items for playback route here 401 // Output gain is default to 1 and any items for playback route here
310 // Foo gain is used for analysis to ensure paths get processed, but are not heard 402 // Foo gain is used for analysis to ensure paths get processed, but are not heard