annotate analyse.html @ 329:5f27d3eb93fe WAC2016

Paper: edits in various sections; Added preliminary analysis page
author Brecht De Man <b.deman@qmul.ac.uk>
date Wed, 14 Oct 2015 20:12:52 +0100
parents
children 378726f0ac91 9da8a3e65a78
rev   line source
b@329 1 <!DOCTYPE html>
b@329 2 <html lang="en">
b@329 3 <head>
b@329 4 <meta charset="utf-8">
b@329 5
b@329 6 <!-- Always force latest IE rendering engine (even in intranet) & Chrome Frame
b@329 7 Remove this if you use the .htaccess -->
b@329 8 <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
b@329 9
b@329 10 <title>Analysis</title>
b@329 11 <meta name="description" content="Show results from subjective evaluation">
b@329 12 <meta name="author" content="Brecht De Man">
b@329 13
b@329 14 <script type="text/javascript" src="https://www.google.com/jsapi"></script>
b@329 15 <script type="text/javascript">
b@329 16 // To aid 'one-page set-up' all scripts and CSS must be included directly in this file!
b@329 17
b@329 18 google.load("visualization", "1", {packages:["corechart"]});
b@329 19
b@329 20 /*************
b@329 21 * SETUP *
b@329 22 *************/
b@329 23 // folder where to find the XML files
b@329 24 xmlFileFolder = "saves";
b@329 25 // array of XML files
b@329 26 var xmlFiles = ['McG-A-2014-03.xml','McG-B-2014-03.xml','McG-C-2014-03.xml'];
b@329 27
b@329 28 //TODO: make retrieval of file names automatic / drag files on here
b@329 29
b@329 30 /****************
b@329 31 * VARIABLES *
b@329 32 ****************/
b@329 33
b@329 34 // Counters
b@329 35 // How many files, audioHolders, audioElementes and statements annotated (don't count current one)
b@329 36 var numberOfFiles = -1;
b@329 37 var numberOfaudioHolders = -1;
b@329 38 var numberOfaudioElementes = -1;
b@329 39 var numberOfStatements = -1;
b@329 40 var numberOfSkippedComments = 0;
b@329 41
b@329 42 // Object arrays
b@329 43 var fileNameArray = [];
b@329 44 var subjectArray = [];
b@329 45 var audioHolderArray = [];
b@329 46 var audioElementArray = [];
b@329 47
b@329 48 // End of (file, audioholder, audioelement) flags
b@329 49 var newFile = true;
b@329 50 var newAudioHolder = true;
b@329 51 var newAudioElement = true;
b@329 52
b@329 53 var fileCounter = 0; // file index
b@329 54 var audioHolderCounter=0; // audioholder index (current XML file)
b@329 55 var audioElementCounter=0; // audioelement index (current audioholder)
b@329 56 var statementNumber=0; // total number of statements
b@329 57
b@329 58 var root; // root of XML file
b@329 59 var commentInFull = ''; // full comment
b@329 60
b@329 61 var playAudio = true; // whether corresponding audio should be played back
b@329 62
b@329 63 // // Measuring time
b@329 64 // var lastTimeMeasured = -1; //
b@329 65 // var durationLastAnnotation = -1; // duration of last annotation
b@329 66 // var timeArray = [];
b@329 67 // var MIN_TIME = 1.0; // minimum time counted as significant
b@329 68 // var measurementPaused = false; // whether time measurement is paused
b@329 69 // var timeInBuffer = 0; //
b@329 70
b@329 71 var topLevel;
b@329 72 window.onload = function() {
b@329 73 // Initialise page
b@329 74 topLevel = document.getElementById('topLevelBody');
b@329 75 var setup = document.createElement('div');
b@329 76 setup.id = 'setupTagDiv';
b@329 77 loadAllFiles();
b@329 78
b@329 79 makePlots();
b@329 80 // measure time at this point:
b@329 81 lastTimeMeasured = new Date().getTime(); // in milliseconds
b@329 82 };
b@329 83
b@329 84 // Assert function
b@329 85 function assert(condition, message) {
b@329 86 if (!condition) {
b@329 87 message = message || "Assertion failed";
b@329 88 if (typeof Error !== "undefined") {
b@329 89 throw new Error(message);
b@329 90 }
b@329 91 throw message; // Fallback
b@329 92 }
b@329 93 }
b@329 94
b@329 95 function median(values) {
b@329 96 values.sort( function(a,b) {return a - b;} );
b@329 97 var half = Math.floor(values.length/2);
b@329 98 if(values.length % 2)
b@329 99 return values[half];
b@329 100 else
b@329 101 return (values[half-1] + values[half]) / 2.0;
b@329 102 }
b@329 103
b@329 104 /***********************
b@329 105 * TIME MEASUREMENT *
b@329 106 ************************/
b@329 107
b@329 108 // measure time since last time this function was called
b@329 109 function timeSinceLastCall() {
b@329 110 // current time
b@329 111 var currentTime = new Date().getTime();
b@329 112 // calculate time difference
b@329 113 var timeDifference = currentTime - lastTimeMeasured + timeInBuffer;
b@329 114 // clear buffer (for pausing)
b@329 115 timeInBuffer = 0;
b@329 116 // remember last measured time
b@329 117 lastTimeMeasured = currentTime;
b@329 118 return timeDifference;
b@329 119 }
b@329 120
b@329 121 // pause time measurement
b@329 122 function pauseTimeMeasurement() {
b@329 123 // UN-PAUSE
b@329 124 if (measurementPaused) { // already paused
b@329 125 // button shows 'pause' again
b@329 126 document.getElementById('pauseButton').innerHTML = 'Pause';
b@329 127 // toggle state
b@329 128 measurementPaused = false;
b@329 129 // resume time measurement
b@329 130 lastTimeMeasured = new Date().getTime(); // reset time, discard time while paused
b@329 131 } else { // PAUSE
b@329 132 // button shows 'resume'
b@329 133 document.getElementById('pauseButton').innerHTML = 'Resume';
b@329 134 // toggle state
b@329 135 measurementPaused = true;
b@329 136 // pause time measurement
b@329 137 timeInBuffer = timeSinceLastCall();
b@329 138 }
b@329 139 }
b@329 140
b@329 141 // show elapsed time on interface
b@329 142 function showTimeElapsedInSeconds() {
b@329 143 // if paused: un-pause
b@329 144 if (measurementPaused) {
b@329 145 pauseTimeMeasurement();
b@329 146 }
b@329 147
b@329 148 // time of last annotation
b@329 149 var lastAnnotationTime = timeSinceLastCall()/1000;
b@329 150 document.getElementById('timeDisplay').innerHTML = lastAnnotationTime.toFixed(2);
b@329 151 // average time over last ... annotations
b@329 152 var avgAnnotationTime;
b@329 153 var numberOfElementsToAverage =
b@329 154 document.getElementById('numberOfTimeAverages').value;
b@329 155 if (isPositiveInteger(numberOfElementsToAverage)) {
b@329 156 avgAnnotationTime =
b@329 157 calculateAverageTime(lastAnnotationTime,
b@329 158 Number(numberOfElementsToAverage));
b@329 159 } else {
b@329 160 // change text field content to 'ALL'
b@329 161 document.getElementById('numberOfTimeAverages').value = 'ALL';
b@329 162 avgAnnotationTime = calculateAverageTime(lastAnnotationTime, -1);
b@329 163 }
b@329 164 document.getElementById('timeAverageDisplay').innerHTML = avgAnnotationTime.toFixed(2);
b@329 165 }
b@329 166
b@329 167 // auxiliary function: is string a positive integer?
b@329 168 // http://stackoverflow.com/questions/10834796/...
b@329 169 // validate-that-a-string-is-a-positive-integer
b@329 170 function isPositiveInteger(str) {
b@329 171 var n = ~~Number(str);
b@329 172 return String(n) === str && n >= 0;
b@329 173 }
b@329 174
b@329 175 // calculate average time
b@329 176 function calculateAverageTime(newTimeMeasurementInSeconds,numberOfPoints) {
b@329 177 // append last measurement time to time array, if significant
b@329 178 if (newTimeMeasurementInSeconds > MIN_TIME) {
b@329 179 timeArray.push(newTimeMeasurementInSeconds);
b@329 180 }
b@329 181 // average over last N elements of this array
b@329 182 if (numberOfPoints < 0 || numberOfPoints>=timeArray.length) { // calculate average over all
b@329 183 var sum = 0;
b@329 184 for (var i = 0; i < timeArray.length; i++) {
b@329 185 sum += timeArray[i];
b@329 186 }
b@329 187 averageOfTimes = sum/timeArray.length;
b@329 188 } else { // calculate average over specified number of times measured last
b@329 189 var sum = 0;
b@329 190 for (var i = timeArray.length-numberOfPoints; i < timeArray.length; i++) {
b@329 191 sum += timeArray[i];
b@329 192 }
b@329 193 averageOfTimes = sum/numberOfPoints;
b@329 194 }
b@329 195 return averageOfTimes;
b@329 196 }
b@329 197
b@329 198
b@329 199 /********************************
b@329 200 * PLAYBACK OF AUDIO *
b@329 201 ********************************/
b@329 202
b@329 203 //PLAYaudioElement
b@329 204 // Keep track of whether audio should be played
b@329 205 function playFlagChanged(){
b@329 206 playAudio = playFlag.checked; // global variable
b@329 207
b@329 208 if (!playAudio){ // if audio needs to stop
b@329 209 audio.pause(); // stop audio - if anything is playing
b@329 210 currently_playing = ''; // back to empty string so playaudioElement knows nothing's playing
b@329 211 }
b@329 212 }
b@329 213
b@329 214 // audioHolder that's currently playing
b@329 215 var currently_playing_audioHolder = ''; // at first: empty string
b@329 216 var currently_playing_audioElement = '';
b@329 217 var audio;
b@329 218
b@329 219 // Play audioElement of audioHolder if available, from start or from same position
b@329 220 function playaudioElement(audioHolderName, audioElementerName){
b@329 221 if (playAudio) { // if enabled
b@329 222 // get corresponding file from folder
b@329 223 var file_location = 'audio/'+audioHolderName + '/' + audioElementerName + '.mp3'; // fixed path and file name format
b@329 224
b@329 225 // if not available, show error/warning message
b@329 226 //TODO ...
b@329 227
b@329 228 // if nothing playing yet, start playing
b@329 229 if (currently_playing_audioHolder == ''){ // signal that nothing is playing
b@329 230 //playSound(audioBuffer);
b@329 231 audio = new Audio(file_location);
b@329 232 audio.loop = true; // loop when end is reached
b@329 233 audio.play();
b@329 234 currently_playing_audioHolder = audioHolderName;
b@329 235 currently_playing_audioElement = audioElementerName;
b@329 236 } else if (currently_playing_audioHolder != audioHolderName) {
b@329 237 // if different audioHolder playing, stop that and start playing
b@329 238 audio.pause(); // stop audio
b@329 239 audio = new Audio(file_location); // load new file
b@329 240 audio.loop = true; // loop when end is reached
b@329 241 audio.play(); // play audio from the start
b@329 242 currently_playing_audioHolder = audioHolderName;
b@329 243 currently_playing_audioElement = audioElementerName;
b@329 244 } else if (currently_playing_audioElement != audioElementerName) {
b@329 245 // if same audioHolder playing, start playing from where it left off
b@329 246 skipTime = audio.currentTime; // time to skip to
b@329 247 audio.pause(); // stop audio
b@329 248 audio = new Audio(file_location);
b@329 249 audio.addEventListener('loadedmetadata', function() {
b@329 250 this.currentTime = skipTime;
b@329 251 console.log('Loaded '+audioHolderName+'-'+audioElementerName+', playing from '+skipTime);
b@329 252 }, false); // skip to same time when audio is loaded!
b@329 253 audio.loop = true; // loop when end is reached
b@329 254 audio.play(); // play from that time
b@329 255 audio.currentTime = skipTime;
b@329 256 currently_playing_audioHolder = audioHolderName;
b@329 257 currently_playing_audioElement = audioElementerName;
b@329 258 }
b@329 259 // if same audioElement playing: keep on playing (i.e. do nothing)
b@329 260 }
b@329 261 }
b@329 262
b@329 263 /********************
b@329 264 * READING FILES *
b@329 265 ********************/
b@329 266
b@329 267 // Read necessary data from XML file
b@329 268 function readXML(xmlFileName){
b@329 269 if (window.XMLHttpRequest)
b@329 270 {// code for IE7+, Firefox, Chrome, Opera, Safari
b@329 271 xmlhttp=new XMLHttpRequest();
b@329 272 }
b@329 273 else
b@329 274 {// code for IE6, IE5
b@329 275 xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
b@329 276 }
b@329 277 xmlhttp.open("GET",xmlFileName,false);
b@329 278 xmlhttp.send();
b@329 279 return xmlhttp.responseXML;
b@329 280 }
b@329 281
b@329 282 // go over all files and compute relevant statistics
b@329 283 function loadAllFiles() {
b@329 284 // retrieve information from XMLs
b@329 285
b@329 286 for (fileIndex = 0; fileIndex < xmlFiles.length; fileIndex++) {
b@329 287 xmlFileName = xmlFileFolder+"/"+xmlFiles[fileIndex];
b@329 288 xml = readXML(xmlFileName);
b@329 289 if (xml != null) { // if file exists
b@329 290 // append file name to array of file names
b@329 291 fileNameArray.push(xmlFiles[fileIndex]);
b@329 292
b@329 293 // get root of XML file
b@329 294 root = xml.getElementsByTagName('browserevaluationresult')[0];
b@329 295
b@329 296 // get subject ID, add to array if not already there
b@329 297 pretest = root.getElementsByTagName('pretest')[0];
b@329 298 subjectID = pretest.getElementsByTagName('comment')[0];
b@329 299 if (subjectID.getAttribute('id')!='sessionId') { // warning in console when not available
b@329 300 console.log(xmlFiles[fileIndex]+': no SessionID available');
b@329 301 }
b@329 302 if (subjectArray.indexOf(subjectID.textContent) == -1) { // if not already in array
b@329 303 subjectArray.push(subjectID.textContent); // append to array
b@329 304 }
b@329 305
b@329 306 // go over all audioHolders, add to array if not already there
b@329 307 audioHolderNodes = root.getElementsByTagName('audioholder');
b@329 308 // go over audioHolderNodes and append audioHolder name when not present yet
b@329 309 for (audioHolderIndex = 0; audioHolderIndex < audioHolderNodes.length; audioHolderIndex++) {
b@329 310 audioHolderName = audioHolderNodes[audioHolderIndex].getAttribute('id');
b@329 311 if (audioHolderArray.indexOf(audioHolderName) == -1) { // if not already in array
b@329 312 audioHolderArray.push(audioHolderName); // append to array
b@329 313 }
b@329 314 // within each audioHolder, go over all audioElement IDs, add to array if not already there
b@329 315 audioElementNodes = audioHolderNodes[audioHolderIndex].getElementsByTagName('audioelement');
b@329 316 for (audioElementIndex = 0; audioElementIndex < audioElementNodes.length; audioElementIndex++) {
b@329 317 audioElementName = audioElementNodes[audioElementIndex].getAttribute('id');
b@329 318 if (audioElementArray.indexOf(audioElementName) == -1) { // if not already in array
b@329 319 audioElementArray.push(audioElementName); // append to array
b@329 320 }
b@329 321 }
b@329 322 }
b@329 323 // count occurrences of each audioHolder
b@329 324 // ...
b@329 325 }
b@329 326 else {
b@329 327 console.log('XML file '+xmlFileName+' not found.');
b@329 328 }
b@329 329 }
b@329 330
b@329 331 // sort alphabetically
b@329 332 fileNameArray.sort();
b@329 333 subjectArray.sort();
b@329 334 audioHolderArray.sort();
b@329 335 audioElementArray.sort();
b@329 336
b@329 337 // display all information in HTML
b@329 338 // show XML file folder
b@329 339 document.getElementById('xmlFileFolder_span').innerHTML = "\""+xmlFileFolder+"/\"";
b@329 340 // show number of files
b@329 341 document.getElementById('numberOfFiles_span').innerHTML = fileNameArray.length;
b@329 342 // show list of subject names
b@329 343 document.getElementById('subjectArray_span').innerHTML = subjectArray.toString();
b@329 344 // show list of audioHolders
b@329 345 document.getElementById('audioHolderArray_span').innerHTML = audioHolderArray.toString();
b@329 346 // show list of audioElementes
b@329 347 document.getElementById('audioElementArray_span').innerHTML = audioElementArray.toString();
b@329 348 }
b@329 349
b@329 350 function makePlots() {
b@329 351 // create value array
b@329 352 var ratings = []; // 3D matrix of ratings (audioHolder, audioElement, subject)
b@329 353 for (audioHolderIndex = 0; audioHolderIndex < audioHolderNodes.length; audioHolderIndex++) {
b@329 354 ratings.push([]);
b@329 355 for (audioElementIndex = 0; audioElementIndex < audioElementNodes.length; audioElementIndex++) {
b@329 356 ratings[audioHolderIndex].push([]);
b@329 357 }
b@329 358 }
b@329 359
b@329 360 // go over all XML files
b@329 361 for (fileIndex = 0; fileIndex < xmlFiles.length; fileIndex++) {
b@329 362 xmlFileName = xmlFileFolder+"/"+xmlFiles[fileIndex];
b@329 363 xml = readXML(xmlFileName);
b@329 364 if (xml != null) { // if file exists
b@329 365 // get root of XML file
b@329 366 root = xml.getElementsByTagName('browserevaluationresult')[0];
b@329 367 // go over all audioHolders
b@329 368 audioHolderNodes = root.getElementsByTagName('audioholder');
b@329 369 for (audioHolderIndex = 0; audioHolderIndex < audioHolderNodes.length; audioHolderIndex++) {
b@329 370 audioHolderName = audioHolderNodes[audioHolderIndex].getAttribute('id');
b@329 371 audioElementNodes = audioHolderNodes[audioHolderIndex].getElementsByTagName('audioelement');
b@329 372 // go over all audioelements
b@329 373 for (audioElementIndex = 0; audioElementIndex < audioElementNodes.length; audioElementIndex++) {
b@329 374 audioElementName = audioElementNodes[audioElementIndex].getAttribute('id');
b@329 375 // get value
b@329 376 var value = audioElementNodes[audioElementIndex].getElementsByTagName("value")[0].textContent;
b@329 377 if (value) { // if not empty, null, undefined...
b@329 378 ratingValue = parseFloat(value);
b@329 379 // add to matrix
b@329 380 ratings[audioHolderIndex][audioElementIndex].push(ratingValue)
b@329 381 }
b@329 382 }
b@329 383 }
b@329 384
b@329 385 // go over all audioHolders
b@329 386
b@329 387 // go over all audioElements within audioHolder, see if present in idMatrix, add if not
b@329 388 // add corresponding rating to 'ratings', at position corresponding with position in idMatrix
b@329 389 }
b@329 390 }
b@329 391
b@329 392 for (audioHolderIndex = 0; audioHolderIndex < audioHolderArray.length; audioHolderIndex++) {
b@329 393 audioHolderName = audioHolderArray[audioHolderIndex]; // for this song
b@329 394 tickArray = []
b@329 395 medianOfAudioElement = []
b@329 396
b@329 397 raw_data = [['SubjectID', 'Rating']];
b@329 398 audioElIdx = 0;
b@329 399 for (audioElementIndex = 0; audioElementIndex<ratings[audioHolderIndex].length; audioElementIndex++){
b@329 400 if (ratings[audioHolderIndex][audioElementIndex].length>0) {
b@329 401 audioElIdx++; // increase if not empty
b@329 402 // make tick label
b@329 403 tickArray.push({v:audioElIdx, f: audioElementArray[audioElementIndex]});
b@329 404 // add median
b@329 405 medianOfAudioElement.push(median(ratings[audioHolderIndex][audioElementIndex]));
b@329 406 }
b@329 407 for (subject = 0; subject<ratings[audioHolderIndex][audioElementIndex].length; subject++){
b@329 408 // add subject-value pair for each subject
b@329 409 raw_data.push([audioElIdx, ratings[audioHolderIndex][audioElementIndex][subject]]);
b@329 410 }
b@329 411 }
b@329 412
b@329 413 // create plot (one per song)
b@329 414 var data = google.visualization.arrayToDataTable(raw_data);
b@329 415
b@329 416 var options = {
b@329 417 title: audioHolderName,
b@329 418 hAxis: {title: 'Subject', minValue: 0, maxValue: audioElIdx+1,
b@329 419 ticks: tickArray},
b@329 420 vAxis: {title: 'Rating', minValue: 0, maxValue: 1},
b@329 421 seriesType: 'scatter',
b@329 422 legend: 'none'
b@329 423 };
b@329 424 var div = document.createElement('div');
b@329 425 document.body.appendChild(div);
b@329 426 div.id = 'div_'+audioHolderName;
b@329 427 div.style.width = '1100px';
b@329 428 div.style.height = '350px';
b@329 429 var chart = new google.visualization.ComboChart(document.getElementById('div_'+audioHolderName));
b@329 430 chart.draw(data, options);
b@329 431
b@329 432 // box plots
b@329 433 // function drawVisualization() {
b@329 434 // // Create and populate the data table.
b@329 435 // var data = google.visualization.arrayToDataTable([
b@329 436 // ['ID', 'IQR', '', '', '', 'Median', 'Average'],
b@329 437 // ['Serie1', 20, 28, 38, 45, 20, 25],
b@329 438 // ['Serie2', 31, 38, 55, 66, 30, 35],
b@329 439 // ['Serie3', 50, 55, 77, 80, 10, 15],
b@329 440 // ['Serie4', 77, 77, 66, 50, 20, 25],
b@329 441 // ['Serie5', 68, 66, 22, 15, 30, 35]
b@329 442 // // Treat first row as data as well.
b@329 443 // ]);
b@329 444 // // Create and draw the visualization.
b@329 445 // var ac = new google.visualization.ComboChart(document.getElementById('visualization'));
b@329 446 // ac.draw(data, {
b@329 447 // title : 'Box Plot with Median and Average',
b@329 448 // width: 600,
b@329 449 // height: 400,
b@329 450 // vAxis: {title: "Value"},
b@329 451 // hAxis: {title: "Serie ID"},
b@329 452 // series: { 0: {type: "candlesticks"}, 1: {type: "line", pointSize: 10, lineWidth:
b@329 453 // 0 }, 2: {type: "line", pointSize: 10, lineWidth: 0, color: 'black' } }
b@329 454 // });
b@329 455 // }
b@329 456 }
b@329 457 }
b@329 458
b@329 459 </script>
b@329 460
b@329 461
b@329 462
b@329 463 <style>
b@329 464 div {
b@329 465 padding: 2px;
b@329 466 margin-top: 2px;
b@329 467 margin-bottom: 2px;
b@329 468 }
b@329 469 div.head{
b@329 470 margin-left: 10px;
b@329 471 border: black;
b@329 472 border-width: 2px;
b@329 473 border-style: solid;
b@329 474 }
b@329 475 div.attrib{
b@329 476 margin-left:25px;
b@329 477 border: black;
b@329 478 border-width: 2px;
b@329 479 border-style: dashed;
b@329 480 margin-bottom: 10px;
b@329 481 }
b@329 482 div#headerMatter{
b@329 483 background-color: #FFFFCC;
b@329 484 }
b@329 485 div#currentStatement{
b@329 486 font-size:3.0em;
b@329 487 font-weight: bold;
b@329 488
b@329 489 }
b@329 490 div#debugDisplay {
b@329 491 color: #CCCCCC;
b@329 492 font-size:0.3em;
b@329 493 }
b@329 494 span#scoreDisplay {
b@329 495 font-weight: bold;
b@329 496 }
b@329 497 div#wrapper {
b@329 498 width: 780px;
b@329 499 border: 1px solid black;
b@329 500 overflow: hidden; /* add this to contain floated children */
b@329 501 }
b@329 502 div#instrumentSection {
b@329 503 width: 250px;
b@329 504 border: 1px solid red;
b@329 505 display: inline-block;
b@329 506 }
b@329 507 div#featureSection {
b@329 508 width: 250px;
b@329 509 border: 1px solid green;
b@329 510 display: inline-block;
b@329 511 }
b@329 512 div#valenceSection {
b@329 513 width: 250px;
b@329 514 border: 1px solid blue;
b@329 515 display: inline-block;
b@329 516 }
b@329 517 button#previousComment{
b@329 518 width: 120px;
b@329 519 height: 150px;
b@329 520 font-size:1.5em;
b@329 521 }
b@329 522 button#nextComment{
b@329 523 width: 666px;
b@329 524 height: 150px;
b@329 525 font-size:1.5em;
b@329 526 }
b@329 527 ul
b@329 528 {
b@329 529 list-style-type: none; /* no bullet points */
b@329 530 margin-left: -20px; /* less indent */
b@329 531 margin-top: 0px;
b@329 532 margin-bottom: 5px;
b@329 533 }
b@329 534 </style>
b@329 535
b@329 536 </head>
b@329 537
b@329 538 <body>
b@329 539 <h1>Subjective evaluation results</h1>
b@329 540
b@329 541 <div id="debugDisplay">
b@329 542 XML file folder: <span id="xmlFileFolder_span"></span>
b@329 543 </div>
b@329 544
b@329 545 <div id="headerMatter">
b@329 546 <div>
b@329 547 <strong>Result XML files:</strong> <span id="numberOfFiles_span"></span>
b@329 548 </div>
b@329 549 <div>
b@329 550 <strong>Audioholders in dataset:</strong> <span id="audioHolderArray_span"></span>
b@329 551 </div>
b@329 552 <div>
b@329 553 <strong>Subjects in dataset:</strong> <span id="subjectArray_span"></span>
b@329 554 </div>
b@329 555 <div>
b@329 556 <strong>Audioelements in dataset:</strong> <span id="audioElementArray_span"></span>
b@329 557 </div>
b@329 558 <br>
b@329 559 </div>
b@329 560 <br>
b@329 561
b@329 562 <!-- Show time elapsed
b@329 563 The last annotation took <strong><span id="timeDisplay">(N/A)</span></strong> seconds.
b@329 564 <br>-->
b@329 565
b@329 566 </body>
b@329 567 </html>