comparison analyse.html @ 1116:c44fbf72f7f2

All interfaces support comment boxes. Comment box identification matches presented tag (for instance, AB will be Comment on fragment A, rather than 1). Tighter buffer loading protocol, audioObjects register with the buffer rather than checking for buffer existence (which can be buggy depending on the buffer state). Buffers now have a state to ensure exact location in loading chain (downloading, decoding, LUFS, ready).
author Nicholas Jillings <n.g.r.jillings@se14.qmul.ac.uk>
date Fri, 29 Jan 2016 11:11:57 +0000
parents
children b5bf2f57187c 9ee921c8cdd3 eef2d4ea18fb
comparison
equal deleted inserted replaced
-1:000000000000 1116:c44fbf72f7f2
1 <!DOCTYPE html>
2 <html lang="en">
3 <head>
4 <meta charset="utf-8">
5
6 <!-- Always force latest IE rendering engine (even in intranet) & Chrome Frame
7 Remove this if you use the .htaccess -->
8 <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
9
10 <title>Analysis</title>
11 <meta name="description" content="Show results from subjective evaluation">
12 <meta name="author" content="Brecht De Man">
13
14 <script type="text/javascript" src="https://www.google.com/jsapi"></script>
15 <script type="text/javascript">
16 // To aid 'one-page set-up' all scripts and CSS must be included directly in this file!
17
18 google.load("visualization", "1", {packages:["corechart"]});
19
20 /*************
21 * SETUP *
22 *************/
23 // folder where to find the XML files
24 xmlFileFolder = "saves";
25 // array of XML files
26 // THIS IS WHERE YOU SPECIFY RESULT XML FILES TO ANALYSE
27 var xmlFiles = ['test-0.xml','test-1.xml','test-2.xml','test-3.xml'];
28
29
30 //TODO: make retrieval of file names automatic / drag files on here
31
32 /****************
33 * VARIABLES *
34 ****************/
35
36 // Counters
37 // How many files, audioholders, audioelementes and statements annotated (don't count current one)
38 var numberOfFiles = -1;
39 var numberOfaudioholders = -1;
40 var numberOfaudioelementes = -1;
41 var numberOfStatements = -1;
42 var numberOfSkippedComments = 0;
43
44 // Object arrays
45 var fileNameArray = [];
46 var subjectArray = [];
47 var audioholderArray = [];
48 var audioelementArray = [];
49
50 // End of (file, audioholder, audioelement) flags
51 var newFile = true;
52 var newAudioHolder = true;
53 var newAudioElement = true;
54
55 var fileCounter = 0; // file index
56 var audioholderCounter=0; // audioholder index (current XML file)
57 var audioelementCounter=0; // audioelement index (current audioholder)
58 var statementNumber=0; // total number of statements
59
60 var root; // root of XML file
61 var commentInFull = ''; // full comment
62
63 var playAudio = true; // whether corresponding audio should be played back
64
65 // // Measuring time
66 // var lastTimeMeasured = -1; //
67 // var durationLastAnnotation = -1; // duration of last annotation
68 // var timeArray = [];
69 // var MIN_TIME = 1.0; // minimum time counted as significant
70 // var measurementPaused = false; // whether time measurement is paused
71 // var timeInBuffer = 0; //
72
73 var topLevel;
74 window.onload = function() {
75 // Initialise page
76 topLevel = document.getElementById('topLevelBody');
77 var setup = document.createElement('div');
78 setup.id = 'setupTagDiv';
79 loadAllFiles();
80 makePlots();
81 printSurveyData()
82 // measure time at this point:
83 lastTimeMeasured = new Date().getTime(); // in milliseconds
84 };
85
86 // Assert function
87 function assert(condition, message) {
88 if (!condition) {
89 message = message || "Assertion failed";
90 if (typeof Error !== "undefined") {
91 throw new Error(message);
92 }
93 throw message; // Fallback
94 }
95 }
96
97 function median(values) { // TODO: replace code by '50th percentile' - should be the same?
98 values.sort( function(a,b) {return a - b;} );
99 var half = Math.floor(values.length/2);
100 if(values.length % 2)
101 return values[half];
102 else
103 return (values[half-1] + values[half]) / 2.0;
104 }
105
106 function percentile(values, n) {
107 values.sort( function(a,b) {return a - b;} );
108 // get ordinal rank
109 var rank = Math.min(Math.floor(values.length*n/100), values.length-1);
110 return values[rank];
111 }
112
113 /***********************
114 * TIME MEASUREMENT *
115 ************************/
116
117 // measure time since last time this function was called
118 function timeSinceLastCall() {
119 // current time
120 var currentTime = new Date().getTime();
121 // calculate time difference
122 var timeDifference = currentTime - lastTimeMeasured + timeInBuffer;
123 // clear buffer (for pausing)
124 timeInBuffer = 0;
125 // remember last measured time
126 lastTimeMeasured = currentTime;
127 return timeDifference;
128 }
129
130 // pause time measurement
131 function pauseTimeMeasurement() {
132 // UN-PAUSE
133 if (measurementPaused) { // already paused
134 // button shows 'pause' again
135 document.getElementById('pauseButton').innerHTML = 'Pause';
136 // toggle state
137 measurementPaused = false;
138 // resume time measurement
139 lastTimeMeasured = new Date().getTime(); // reset time, discard time while paused
140 } else { // PAUSE
141 // button shows 'resume'
142 document.getElementById('pauseButton').innerHTML = 'Resume';
143 // toggle state
144 measurementPaused = true;
145 // pause time measurement
146 timeInBuffer = timeSinceLastCall();
147 }
148 }
149
150 // show elapsed time on interface
151 function showTimeElapsedInSeconds() {
152 // if paused: un-pause
153 if (measurementPaused) {
154 pauseTimeMeasurement();
155 }
156
157 // time of last annotation
158 var lastAnnotationTime = timeSinceLastCall()/1000;
159 document.getElementById('timeDisplay').innerHTML = lastAnnotationTime.toFixed(2);
160 // average time over last ... annotations
161 var avgAnnotationTime;
162 var numberOfElementsToAverage =
163 document.getElementById('numberOfTimeAverages').value;
164 if (isPositiveInteger(numberOfElementsToAverage)) {
165 avgAnnotationTime =
166 calculateAverageTime(lastAnnotationTime,
167 Number(numberOfElementsToAverage));
168 } else {
169 // change text field content to 'ALL'
170 document.getElementById('numberOfTimeAverages').value = 'ALL';
171 avgAnnotationTime = calculateAverageTime(lastAnnotationTime, -1);
172 }
173 document.getElementById('timeAverageDisplay').innerHTML = avgAnnotationTime.toFixed(2);
174 }
175
176 // auxiliary function: is string a positive integer?
177 // http://stackoverflow.com/questions/10834796/...
178 // validate-that-a-string-is-a-positive-integer
179 function isPositiveInteger(str) {
180 var n = ~~Number(str);
181 return String(n) === str && n >= 0;
182 }
183
184 // calculate average time
185 function calculateAverageTime(newTimeMeasurementInSeconds,numberOfPoints) {
186 // append last measurement time to time array, if significant
187 if (newTimeMeasurementInSeconds > MIN_TIME) {
188 timeArray.push(newTimeMeasurementInSeconds);
189 }
190 // average over last N elements of this array
191 if (numberOfPoints < 0 || numberOfPoints>=timeArray.length) { // calculate average over all
192 var sum = 0;
193 for (var i = 0; i < timeArray.length; i++) {
194 sum += timeArray[i];
195 }
196 averageOfTimes = sum/timeArray.length;
197 } else { // calculate average over specified number of times measured last
198 var sum = 0;
199 for (var i = timeArray.length-numberOfPoints; i < timeArray.length; i++) {
200 sum += timeArray[i];
201 }
202 averageOfTimes = sum/numberOfPoints;
203 }
204 return averageOfTimes;
205 }
206
207
208 /********************************
209 * PLAYBACK OF AUDIO *
210 ********************************/
211
212 //PLAYaudioelement
213 // Keep track of whether audio should be played
214 function playFlagChanged(){
215 playAudio = playFlag.checked; // global variable
216
217 if (!playAudio){ // if audio needs to stop
218 audio.pause(); // stop audio - if anything is playing
219 currently_playing = ''; // back to empty string so playaudioelement knows nothing's playing
220 }
221 }
222
223 // audioholder that's currently playing
224 var currently_playing_audioholder = ''; // at first: empty string
225 var currently_playing_audioelement = '';
226 var audio;
227
228 // Play audioelement of audioholder if available, from start or from same position
229 function playaudioelement(audioholderName, audioelementerName){
230 if (playAudio) { // if enabled
231 // get corresponding file from folder
232 var file_location = 'audio/'+audioholderName + '/' + audioelementerName + '.mp3'; // fixed path and file name format
233
234 // if not available, show error/warning message
235 //TODO ...
236
237 // if nothing playing yet, start playing
238 if (currently_playing_audioholder == ''){ // signal that nothing is playing
239 //playSound(audioBuffer);
240 audio = new Audio(file_location);
241 audio.loop = true; // loop when end is reached
242 audio.play();
243 currently_playing_audioholder = audioholderName;
244 currently_playing_audioelement = audioelementerName;
245 } else if (currently_playing_audioholder != audioholderName) {
246 // if different audioholder playing, stop that and start playing
247 audio.pause(); // stop audio
248 audio = new Audio(file_location); // load new file
249 audio.loop = true; // loop when end is reached
250 audio.play(); // play audio from the start
251 currently_playing_audioholder = audioholderName;
252 currently_playing_audioelement = audioelementerName;
253 } else if (currently_playing_audioelement != audioelementerName) {
254 // if same audioholder playing, start playing from where it left off
255 skipTime = audio.currentTime; // time to skip to
256 audio.pause(); // stop audio
257 audio = new Audio(file_location);
258 audio.addEventListener('loadedmetadata', function() {
259 this.currentTime = skipTime;
260 console.log('Loaded '+audioholderName+'-'+audioelementerName+', playing from '+skipTime);
261 }, false); // skip to same time when audio is loaded!
262 audio.loop = true; // loop when end is reached
263 audio.play(); // play from that time
264 audio.currentTime = skipTime;
265 currently_playing_audioholder = audioholderName;
266 currently_playing_audioelement = audioelementerName;
267 }
268 // if same audioelement playing: keep on playing (i.e. do nothing)
269 }
270 }
271
272 /********************
273 * READING FILES *
274 ********************/
275
276 // Read necessary data from XML file
277 function readXML(xmlFileName){
278 if (window.XMLHttpRequest)
279 {// code for IE7+, Firefox, Chrome, Opera, Safari
280 xmlhttp=new XMLHttpRequest();
281 }
282 else
283 {// code for IE6, IE5
284 xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
285 }
286 xmlhttp.open("GET",xmlFileName,false);
287 xmlhttp.send();
288 return xmlhttp.responseXML;
289 }
290
291 // go over all files and compute relevant statistics
292 function loadAllFiles() {
293 // retrieve information from XMLs
294
295 for (fileIndex = 0; fileIndex < xmlFiles.length; fileIndex++) {
296 xmlFileName = xmlFileFolder+"/"+xmlFiles[fileIndex];
297 xml = readXML(xmlFileName);
298 if (xml != null) { // if file exists
299 // append file name to array of file names
300 fileNameArray.push(xmlFiles[fileIndex]);
301
302 // get root of XML file
303 root = xml.getElementsByTagName('browserevaluationresult')[0];
304
305 // get subject ID, add to array if not already there
306 pretest = root.getElementsByTagName('pretest')[0];
307 subjectID = pretest.getElementsByTagName('comment')[0];
308 if (subjectID){
309 if (subjectID.getAttribute('id')!='sessionId') { // warning in console when not available
310 console.log(xmlFiles[fileIndex]+': no SessionID available');
311 }
312 if (subjectArray.indexOf(subjectID.textContent) == -1) { // if not already in array
313 subjectArray.push(subjectID.textContent); // append to array
314 }
315 }
316
317 // go over all audioholders, add to array if not already there
318 audioholderNodes = root.getElementsByTagName('audioholder');
319 // go over audioholderNodes and append audioholder name when not present yet
320 for (audioholderIndex = 0; audioholderIndex < audioholderNodes.length; audioholderIndex++) {
321 audioholderName = audioholderNodes[audioholderIndex].getAttribute('id');
322 if (audioholderArray.indexOf(audioholderName) == -1) { // if not already in array
323 audioholderArray.push(audioholderName); // append to array
324 }
325 // within each audioholder, go over all audioelement IDs, add to array if not already there
326 audioelementNodes = audioholderNodes[audioholderIndex].getElementsByTagName('audioelement');
327 for (audioelementIndex = 0; audioelementIndex < audioelementNodes.length; audioelementIndex++) {
328 audioelementName = audioelementNodes[audioelementIndex].getAttribute('id');
329 if (audioelementArray.indexOf(audioelementName) == -1) { // if not already in array
330 audioelementArray.push(audioelementName); // append to array
331 }
332 }
333 }
334 // count occurrences of each audioholder
335 // ...
336 }
337 else {
338 console.log('XML file '+xmlFileName+' not found.');
339 }
340 }
341
342 // sort alphabetically
343 fileNameArray.sort();
344 subjectArray.sort();
345 audioholderArray.sort();
346 audioelementArray.sort();
347
348 // display all information in HTML
349 // show XML file folder
350 document.getElementById('xmlFileFolder_span').innerHTML = "\""+xmlFileFolder+"/\"";
351 // show number of files
352 document.getElementById('numberOfFiles_span').innerHTML = fileNameArray.length;
353 // show list of subject names
354 document.getElementById('subjectArray_span').innerHTML = subjectArray.toString();
355 // show list of audioholders
356 document.getElementById('audioholderArray_span').innerHTML = audioholderArray.toString();
357 // show list of audioelementes
358 document.getElementById('audioelementArray_span').innerHTML = audioelementArray.toString();
359 }
360
361 function printSurveyData() {
362 // print some fields from the survey for different people
363
364 // go over all XML files
365 for (fileIndex = 0; fileIndex < xmlFiles.length; fileIndex++) {
366 xmlFileName = xmlFileFolder+"/"+xmlFiles[fileIndex];
367 xml = readXML(xmlFileName);
368 // make a div
369 var div = document.createElement('div');
370 document.body.appendChild(div);
371 div.id = 'div_survey_'+xmlFileName;
372 div.style.width = '1100px';
373 //div.style.height = '350px';
374
375 // title for that div (subject id)
376 document.getElementById('div_survey_'+xmlFileName).innerHTML = '<h2>'+xmlFileName+'</h2>';
377
378 // which songs did they do
379 if (xml != null) { // if file exists
380 // get root of XML file
381 root = xml.getElementsByTagName('browserevaluationresult')[0];
382 // go over all audioholders
383 // document.getElementById('div_survey_'+xmlFileName).innerHTML += '<strong>Audioholders: </strong>';
384 // audioholderNodes = root.getElementsByTagName('audioholder');
385 // for (audioholderIndex = 0; audioholderIndex < audioholderNodes.length-1; audioholderIndex++) {
386 // document.getElementById('div_survey_'+xmlFileName).innerHTML += audioholderNodes[audioholderIndex].getAttribute('id')+', ';
387 // }
388 // document.getElementById('div_survey_'+xmlFileName).innerHTML += audioholderNodes[audioholderNodes.length-1].getAttribute('id');
389
390 // survey responses (each if available)
391 // get posttest node for total test
392 childNodes = root.childNodes;
393 posttestnode = null;
394 for (idx = 0; idx < childNodes.length; idx++){
395 if (childNodes[childNodes.length-idx-1].tagName == 'posttest') {
396 posttestnode = childNodes[childNodes.length-idx-1];
397 break;
398 }
399 }
400
401 // post-test info
402 if (posttestnode) {
403 posttestcomments = posttestnode.getElementsByTagName('comment');
404 for (idx=0; idx < posttestcomments.length; idx++){
405 commentsToPrint = ['age', 'location']; // CHANGE WHAT TO PRINT
406 idAttribute = posttestcomments[idx].getAttribute('id');
407 if (commentsToPrint.indexOf(idAttribute) >= 0) { // if exists?
408 document.getElementById('div_survey_'+xmlFileName).innerHTML += '<br><strong>'+idAttribute+': </strong>'+posttestcomments[idx].textContent;
409 }
410 }
411 }
412 }
413 }
414 }
415
416 function makePlots() { //TODO: split into different functions
417 // TEMPORARY
418 makeTimeline(xmlFileFolder+"/"+xmlFiles[7]);
419
420 // create value array
421 var ratings = []; // 3D matrix of ratings (audioholder, audioelement, subject)
422 for (audioholderIndex = 0; audioholderIndex < audioholderArray.length; audioholderIndex++) {
423 ratings.push([]);
424 for (audioelementIndex = 0; audioelementIndex < audioelementArray.length; audioelementIndex++) {
425 ratings[audioholderIndex].push([]);
426 }
427 }
428
429 // go over all XML files
430 for (fileIndex = 0; fileIndex < xmlFiles.length; fileIndex++) {
431 xmlFileName = xmlFileFolder+"/"+xmlFiles[fileIndex];
432 xml = readXML(xmlFileName);
433 if (xml != null) { // if file exists
434 // get root of XML file
435 root = xml.getElementsByTagName('browserevaluationresult')[0];
436 // go over all audioholders
437 audioholderNodes = root.getElementsByTagName('audioholder');
438 for (audioholderIndex = 0; audioholderIndex < audioholderNodes.length; audioholderIndex++) {
439 audioholderName = audioholderNodes[audioholderIndex].getAttribute('id');
440 audioelementNodes = audioholderNodes[audioholderIndex].getElementsByTagName('audioelement');
441 // go over all audioelements
442 for (audioelementIndex = 0; audioelementIndex < audioelementNodes.length; audioelementIndex++) {
443 audioelementName = audioelementNodes[audioelementIndex].getAttribute('id');
444 // get value
445 var value = audioelementNodes[audioelementIndex].getElementsByTagName("value")[0].textContent;
446 if (value) { // if not empty, null, undefined...
447 ratingValue = parseFloat(value);
448 // add to matrix at proper position
449 aHidx = audioholderArray.indexOf(audioholderName);
450 aEidx = audioelementArray.indexOf(audioelementName);
451 ratings[aHidx][aEidx].push(ratingValue);
452 }
453 }
454 }
455
456 // go over all audioholders
457
458 // go over all audioelements within audioholder, see if present in idMatrix, add if not
459 // add corresponding rating to 'ratings', at position corresponding with position in idMatrix
460 }
461 }
462
463 for (audioholderIndex = 0; audioholderIndex < audioholderArray.length; audioholderIndex++) {
464 audioholderName = audioholderArray[audioholderIndex]; // for this song
465 tickArray = []
466
467 raw_data = [['SubjectID', 'Rating']];
468 audioElIdx = 0;
469 for (audioelementIndex = 0; audioelementIndex<ratings[audioholderIndex].length; audioelementIndex++){
470 if (ratings[audioholderIndex][audioelementIndex].length>0) {
471 audioElIdx++; // increase if not empty
472 // make tick label
473 tickArray.push({v:audioElIdx, f: audioelementArray[audioelementIndex]});
474 }
475 for (subject = 0; subject<ratings[audioholderIndex][audioelementIndex].length; subject++){
476 // add subject-value pair for each subject
477 raw_data.push([audioElIdx, ratings[audioholderIndex][audioelementIndex][subject]]);
478 }
479 }
480
481 // create plot (one per song)
482 var data = google.visualization.arrayToDataTable(raw_data);
483
484 var options = {
485 title: audioholderName,
486 hAxis: {title: 'audioelement ID', minValue: 0, maxValue: audioElIdx+1,
487 ticks: tickArray},
488 vAxis: {title: 'Rating', minValue: 0, maxValue: 1},
489 seriesType: 'scatter',
490 legend: 'none'
491 };
492 var div = document.createElement('div');
493 document.body.appendChild(div);
494 div.id = 'div_'+audioholderName;
495 div.style.width = '1100px';
496 div.style.height = '350px';
497 var chart = new google.visualization.ComboChart(document.getElementById('div_'+audioholderName));
498 chart.draw(data, options);
499
500 // box plots
501 var div = document.createElement('div');
502 document.body.appendChild(div);
503 div.id = 'div_box_'+audioholderName;
504 div.style.width = '1100px';
505 div.style.height = '350px';
506 // Get median, percentiles, maximum and minimum; outliers.
507 pctl25 = [];
508 pctl75 = [];
509 med = [];
510 min = [];
511 max = [];
512 outlierArray = [];
513 max_n_outliers = 0; // maximum number of outliers for one audioelement
514 for (audioelementIndex = 0; audioelementIndex<ratings[audioholderIndex].length; audioelementIndex++){
515 med.push(median(ratings[audioholderIndex][audioelementIndex])); // median
516 pctl25.push(percentile(ratings[audioholderIndex][audioelementIndex], 25)); // 25th percentile
517 pctl75.push(percentile(ratings[audioholderIndex][audioelementIndex], 75)); // 75th percentile
518 IQR = pctl75[pctl75.length-1]-pctl25[pctl25.length-1];
519 // outliers: range of values which is above pctl75+1.5*IQR or below pctl25-1.5*IQR
520 outliers = [];
521 rest = [];
522 for (idx = 0; idx<ratings[audioholderIndex][audioelementIndex].length; idx++){
523 if (ratings[audioholderIndex][audioelementIndex][idx] > pctl75[pctl75.length-1]+1.5*IQR ||
524 ratings[audioholderIndex][audioelementIndex][idx] < pctl25[pctl25.length-1]-1.5*IQR){
525 outliers.push(ratings[audioholderIndex][audioelementIndex][idx]);
526 }
527 else {
528 rest.push(ratings[audioholderIndex][audioelementIndex][idx]);
529 }
530 }
531 outlierArray.push(outliers);
532 max_n_outliers = Math.max(max_n_outliers, outliers.length); // update max mber
533 // max: maximum value which is not outlier
534 max.push(Math.max.apply(null, rest));
535 // min: minimum value which is not outlier
536 min.push(Math.min.apply(null, rest));
537 }
538
539 // Build data array
540 boxplot_data = [['ID', 'Span', '', '', '', 'Median']];
541 for (idx = 0; idx < max_n_outliers; idx++) {
542 boxplot_data[0].push('Outlier');
543 }
544 for (audioelementIndex = 0; audioelementIndex<ratings[audioholderIndex].length; audioelementIndex++){
545 if (ratings[audioholderIndex][audioelementIndex].length>0) { // if rating array not empty for this audioelement
546 data_array = [
547 audioelementArray[audioelementIndex], // name
548 min[audioelementIndex], // minimum
549 pctl75[audioelementIndex],
550 pctl25[audioelementIndex],
551 max[audioelementIndex], // maximum
552 med[audioelementIndex]
553 ];
554 for (idx = 0; idx < max_n_outliers; idx++) {
555 if (idx<outlierArray[audioelementIndex].length){
556 data_array.push(outlierArray[audioelementIndex][idx]);
557 }
558 else {
559 data_array.push(null);
560 }
561 }
562 boxplot_data.push(data_array);
563 }
564 }
565
566 // Create and populate the data table.
567 var data = google.visualization.arrayToDataTable(boxplot_data);
568 // Create and draw the visualization.
569 var ac = new google.visualization.ComboChart(document.getElementById('div_box_'+audioholderName));
570 ac.draw(data, {
571 title : audioholderName,
572 //width: 600,
573 //height: 400,
574 vAxis: {title: "Rating"},
575 hAxis: {title: "audioelement ID"},
576 seriesType: "line",
577 pointSize: 5,
578 lineWidth: 0,
579 colors: ['black'],
580 series: { 0: {type: "candlesticks", color: 'blue'}, // box plot shape
581 1: {type: "line", pointSize: 10, lineWidth: 0, color: 'red' } }, // median
582 legend: 'none'
583 });
584 }
585 }
586
587 function makeTimeline(xmlFileName){ // WIP
588 // Based on the XML file name, take time data and plot playback and marker movements
589
590 // read XML file and check if exists
591 xml = readXML(xmlFileName);
592 if (!xml) { // if file does not exist
593 console.log('XML file '+xml+'does not exist. ('+xmlFileName+')')
594 return; // do nothing; exit function
595 }
596 // get root of XML file
597 root = xml.getElementsByTagName('browserevaluationresult')[0];
598
599 audioholder_time = 0;
600 previous_audioholder_time = 0; // time spent before current audioholder
601 time_offset = 0; // test starts at zero
602
603 // go over all audioholders
604 audioholderNodes = root.getElementsByTagName('audioholder');
605 for (audioholderIndex = 0; audioholderIndex < audioholderNodes.length; audioholderIndex++) {
606 audioholderName = audioholderNodes[audioholderIndex].getAttribute('id');
607 if (!audioholderName) {
608 console.log('audioholder name is empty; go to next one. ('+xmlFileName+')');
609 break;
610 }
611
612 // subtract total audioholder length from subsequent audioholder event times
613 audioholder_children = audioholderNodes[audioholderIndex].childNodes;
614 foundIt = false;
615 console.log(audioholder_children[2].getElementsByTagName("metricResult")) // not working!
616 for (idx = 0; idx<audioholder_children.length; idx++) { // go over children
617
618 if (audioholder_children[idx].getElementsByTagName('metricResult').length) {
619 console.log(audioholder_children[idx].getElementsByTagName('metricResult')[0]);
620 if (audioholder_children[idx].getElementsByTagName('metricResult')[0].getAttribute('id') == "testTime"){
621 audioholder_time = parseFloat(audioholder_children[idx].getElementsByTagName('metricResult')[0].textContent);
622 console.log(audioholder_time);
623 foundIt = true;
624 }
625 }
626 }
627 if (!foundIt) {
628 console.log("Skipping audioholder without total time specified from "+xmlFileName+"."); // always hitting this
629 break;
630 }
631
632 audioelementNodes = audioholderNodes[audioholderIndex].getElementsByTagName('audioelement');
633
634 // make div
635
636 // draw chart
637
638 // legend with audioelement names
639 }
640 }
641
642 </script>
643
644
645
646 <style>
647 div {
648 padding: 2px;
649 margin-top: 2px;
650 margin-bottom: 2px;
651 }
652 div.head{
653 margin-left: 10px;
654 border: black;
655 border-width: 2px;
656 border-style: solid;
657 }
658 div.attrib{
659 margin-left:25px;
660 border: black;
661 border-width: 2px;
662 border-style: dashed;
663 margin-bottom: 10px;
664 }
665 div#headerMatter{
666 background-color: #FFFFCC;
667 }
668 div#currentStatement{
669 font-size:3.0em;
670 font-weight: bold;
671
672 }
673 div#debugDisplay {
674 color: #CCCCCC;
675 font-size:0.3em;
676 }
677 span#scoreDisplay {
678 font-weight: bold;
679 }
680 div#wrapper {
681 width: 780px;
682 border: 1px solid black;
683 overflow: hidden; /* add this to contain floated children */
684 }
685 div#instrumentSection {
686 width: 250px;
687 border: 1px solid red;
688 display: inline-block;
689 }
690 div#featureSection {
691 width: 250px;
692 border: 1px solid green;
693 display: inline-block;
694 }
695 div#valenceSection {
696 width: 250px;
697 border: 1px solid blue;
698 display: inline-block;
699 }
700 button#previousComment{
701 width: 120px;
702 height: 150px;
703 font-size:1.5em;
704 }
705 button#nextComment{
706 width: 666px;
707 height: 150px;
708 font-size:1.5em;
709 }
710 ul
711 {
712 list-style-type: none; /* no bullet points */
713 margin-left: -20px; /* less indent */
714 margin-top: 0px;
715 margin-bottom: 5px;
716 }
717 </style>
718
719 </head>
720
721 <body>
722 <h1>Subjective evaluation results</h1>
723
724 <div id="debugDisplay">
725 XML file folder: <span id="xmlFileFolder_span"></span>
726 </div>
727
728 <div id="headerMatter">
729 <div>
730 <strong>Result XML files:</strong> <span id="numberOfFiles_span"></span>
731 </div>
732 <div>
733 <strong>Audioholders in dataset:</strong> <span id="audioholderArray_span"></span>
734 </div>
735 <div>
736 <strong>Subjects in dataset:</strong> <span id="subjectArray_span"></span>
737 </div>
738 <div>
739 <strong>Audioelements in dataset:</strong> <span id="audioelementArray_span"></span>
740 </div>
741 <br>
742 </div>
743 <br>
744
745 <!-- Show time elapsed
746 The last annotation took <strong><span id="timeDisplay">(N/A)</span></strong> seconds.
747 <br>-->
748
749 </body>
750 </html>