Mercurial > hg > webaudioevaluationtool
comparison analysis/analysis.js @ 1284:6c819878ac85
Major updates. Specification Nodes now own file (specification.js). Updating Analysis to allow filtering based on survey responses.
author | Nicholas Jillings <n.g.r.jillings@se14.qmul.ac.uk> |
---|---|
date | Thu, 31 Mar 2016 13:31:42 +0100 |
parents | b4a0244bf5ed |
children | ae57d9f618cb |
comparison
equal
deleted
inserted
replaced
1283:b24d861c96b3 | 1284:6c819878ac85 |
---|---|
1 /* | 1 /* |
2 * Analysis script for WAET | 2 * Analysis script for WAET |
3 */ | 3 */ |
4 | 4 |
5 var chartContext; | 5 // Firefox does not have an XMLDocument.prototype.getElementsByName |
6 // and there is no searchAll style command, this custom function will | |
7 // search all children recusrively for the name. Used for XSD where all | |
8 // element nodes must have a name and therefore can pull the schema node | |
9 XMLDocument.prototype.getAllElementsByName = function(name) | |
10 { | |
11 name = String(name); | |
12 var selected = this.documentElement.getAllElementsByName(name); | |
13 return selected; | |
14 } | |
15 | |
16 Element.prototype.getAllElementsByName = function(name) | |
17 { | |
18 name = String(name); | |
19 var selected = []; | |
20 var node = this.firstElementChild; | |
21 while(node != null) | |
22 { | |
23 if (node.getAttribute('name') == name) | |
24 { | |
25 selected.push(node); | |
26 } | |
27 if (node.childElementCount > 0) | |
28 { | |
29 selected = selected.concat(node.getAllElementsByName(name)); | |
30 } | |
31 node = node.nextElementSibling; | |
32 } | |
33 return selected; | |
34 } | |
35 | |
36 XMLDocument.prototype.getAllElementsByTagName = function(name) | |
37 { | |
38 name = String(name); | |
39 var selected = this.documentElement.getAllElementsByTagName(name); | |
40 return selected; | |
41 } | |
42 | |
43 Element.prototype.getAllElementsByTagName = function(name) | |
44 { | |
45 name = String(name); | |
46 var selected = []; | |
47 var node = this.firstElementChild; | |
48 while(node != null) | |
49 { | |
50 if (node.nodeName == name) | |
51 { | |
52 selected.push(node); | |
53 } | |
54 if (node.childElementCount > 0) | |
55 { | |
56 selected = selected.concat(node.getAllElementsByTagName(name)); | |
57 } | |
58 node = node.nextElementSibling; | |
59 } | |
60 return selected; | |
61 } | |
62 | |
63 // Firefox does not have an XMLDocument.prototype.getElementsByName | |
64 if (typeof XMLDocument.prototype.getElementsByName != "function") { | |
65 XMLDocument.prototype.getElementsByName = function(name) | |
66 { | |
67 name = String(name); | |
68 var node = this.documentElement.firstElementChild; | |
69 var selected = []; | |
70 while(node != null) | |
71 { | |
72 if (node.getAttribute('name') == name) | |
73 { | |
74 selected.push(node); | |
75 } | |
76 node = node.nextElementSibling; | |
77 } | |
78 return selected; | |
79 } | |
80 } | |
81 | |
82 var chartContext, testData; | |
6 window.onload = function() { | 83 window.onload = function() { |
7 // Load the Visualization API and the corechart package. | 84 // Load the Visualization API and the corechart package. |
8 google.charts.load('current', {'packages':['corechart']}); | 85 google.charts.load('current', {'packages':['corechart']}); |
9 chartContext = new Chart(); | 86 chartContext = new Chart(); |
87 testData = new Data(); | |
88 } | |
89 | |
90 function get(url) { | |
91 // Return a new promise. | |
92 return new Promise(function(resolve, reject) { | |
93 // Do the usual XHR stuff | |
94 var req = new XMLHttpRequest(); | |
95 req.open('GET', url); | |
96 req.onload = function() { | |
97 // This is called even on 404 etc | |
98 // so check the status | |
99 if (req.status == 200) { | |
100 // Resolve the promise with the response text | |
101 resolve(req.response); | |
102 } | |
103 else { | |
104 // Otherwise reject with the status text | |
105 // which will hopefully be a meaningful error | |
106 reject(Error(req.statusText)); | |
107 } | |
108 }; | |
109 | |
110 // Handle network errors | |
111 req.onerror = function() { | |
112 reject(Error("Network Error")); | |
113 }; | |
114 | |
115 // Make the request | |
116 req.send(); | |
117 }); | |
10 } | 118 } |
11 | 119 |
12 function arrayMean(values) { | 120 function arrayMean(values) { |
13 var mean = 0; | 121 var mean = 0; |
14 for (var value of values) { | 122 for (var value of values) { |
113 } | 221 } |
114 return histogram; | 222 return histogram; |
115 } | 223 } |
116 | 224 |
117 function Chart() { | 225 function Chart() { |
118 this.valueData = null; | 226 this.valueData; |
119 this.commentData = null; | |
120 this.loadStatus = 0; | |
121 this.charts = []; | 227 this.charts = []; |
122 | |
123 var XMLHttp = new XMLHttpRequest(); | |
124 XMLHttp.parent = this; | |
125 XMLHttp.open("GET","../scripts/score_parser.php?format=JSON",true); | |
126 XMLHttp.onload = function() { | |
127 // Now we have the JSON data, extract | |
128 this.parent.valueData = JSON.parse(this.responseText); | |
129 this.parent.loadStatus++; | |
130 } | |
131 XMLHttp.send(); | |
132 var XMLHttp2 = new XMLHttpRequest(); | |
133 XMLHttp2.parent = this; | |
134 XMLHttp2.open("GET","../scripts/comment_parser.php?format=JSON",true); | |
135 XMLHttp2.onload = function() { | |
136 // Now we have the JSON data, extract | |
137 this.parent.commentData = JSON.parse(this.responseText); | |
138 this.parent.loadStatus++; | |
139 } | |
140 XMLHttp2.send(); | |
141 | 228 |
142 this.chartObject = function(name) { | 229 this.chartObject = function(name) { |
143 // Create the charting object | 230 // Create the charting object |
144 this.name = name; | 231 this.name = name; |
145 this.root = document.createElement("div"); | 232 this.root = document.createElement("div"); |
490 this.charts.push(chart); | 577 this.charts.push(chart); |
491 } | 578 } |
492 } | 579 } |
493 } | 580 } |
494 } | 581 } |
582 | |
583 function Data() { | |
584 // This holds the link between the server side calculations and the client side visualisation of the data | |
585 | |
586 // Dynamically generate the test filtering / page filterting tools | |
587 var self = this; | |
588 // Collect the test types and counts | |
589 this.testSavedDiv = document.getElementById("test-saved"); | |
590 this.testSaves = null; | |
591 this.selectURL = null; | |
592 | |
593 this.specification = new Specification(); | |
594 get("../test-schema.xsd").then(function(response){ | |
595 var parse = new DOMParser(); | |
596 self.specification.schema = parse.parseFromString(response,'text/xml'); | |
597 },function(error){ | |
598 console.log("ERROR: Could not get Test Schema"); | |
599 }); | |
600 this.update = function(url) { | |
601 var self = this; | |
602 get(url).then(function(response){ | |
603 var parse = new DOMParser(); | |
604 self.specification.decode(parse.parseFromString(response,'text/xml')); | |
605 interfaceContext.generateFilters(self.specification); | |
606 return true; | |
607 },function(error){ | |
608 console.log("ERROR: Could not get"+url); | |
609 return false; | |
610 }); | |
611 } | |
612 var get_test = new XMLHttpRequest(); | |
613 get_test.parent = this; | |
614 get_test.open("GET","../scripts/get_tests.php?format=JSON",true); | |
615 get_test.onload = function() { | |
616 this.parent.testSavedDiv.innerHTML = null; | |
617 var table = document.createElement("table"); | |
618 table.innerHTML = "<tr><td>Test Filename</td><td>Count</td><td>Include</td></tr>"; | |
619 this.parent.testSaves = JSON.parse(this.responseText); | |
620 for (var test of this.parent.testSaves.tests) { | |
621 var tableRow = document.createElement("tr"); | |
622 var tableRowFilename = document.createElement("td"); | |
623 tableRowFilename.textContent = test.testName; | |
624 var tableRowCount = document.createElement("td"); | |
625 tableRowCount.textContent = test.files.length; | |
626 tableRow.appendChild(tableRowFilename); | |
627 tableRow.appendChild(tableRowCount); | |
628 var tableRowInclude = document.createElement("td"); | |
629 var tableRowIncludeInput = document.createElement("input"); | |
630 tableRowIncludeInput.type = "radio"; | |
631 tableRowIncludeInput.name = "test-include"; | |
632 tableRowIncludeInput.setAttribute("source",test.testName); | |
633 tableRowIncludeInput.addEventListener("change",this.parent); | |
634 tableRowInclude.appendChild(tableRowIncludeInput); | |
635 tableRow.appendChild(tableRowInclude); | |
636 table.appendChild(tableRow); | |
637 } | |
638 this.parent.testSavedDiv.appendChild(table); | |
639 } | |
640 get_test.send(); | |
641 this.handleEvent = function(event) { | |
642 if (event.currentTarget.nodeName == "INPUT" && event.currentTarget.name == "test-include") { | |
643 // Changed the test specification | |
644 this.selectURL = event.currentTarget.getAttribute("source"); | |
645 this.update(this.selectURL); | |
646 } | |
647 } | |
648 } | |
649 | |
650 var interfaceContext = new function() { | |
651 // This creates the interface for the user to connect with the dynamic back-end to retrieve data | |
652 this.rootDOM = document.createElement("div"); | |
653 this.filterDOM = document.createElement("div"); | |
654 this.filterDOM.innerHTML = "<p>PreTest Filters</p><div id='filter-count'></div>"; | |
655 this.filterObjects = []; | |
656 this.generateFilters = function(specification) { | |
657 // Filters are based on the pre and post global surverys | |
658 var FilterObject = function(parent,specification) { | |
659 this.parent = parent; | |
660 this.specification = specification; | |
661 this.rootDOM = document.createElement("div"); | |
662 this.rootDOM.innerHTML = "<span>ID: "+specification.id+", Type: "+specification.type+"</span>"; | |
663 this.rootDOM.className = "filter-entry"; | |
664 this.handleEvent = function(event) { | |
665 switch(this.specification.type) { | |
666 case "number": | |
667 var name = event.currentTarget.name; | |
668 eval("this."+name+" = event.currentTarget.value"); | |
669 break; | |
670 case "checkbox": | |
671 break; | |
672 case "radio": | |
673 break; | |
674 } | |
675 this.parent.getFileCount(); | |
676 } | |
677 this.getFilterPairs = function() { | |
678 var pairs = []; | |
679 switch(this.specification.type) { | |
680 case "number": | |
681 if (this.min != "") { | |
682 pairs.push([specification.id+"-min",this.min]); | |
683 } | |
684 if (this.max != "") { | |
685 pairs.push([specification.id+"-max",this.max]); | |
686 } | |
687 break; | |
688 case "radio": | |
689 case "checkbox": | |
690 for (var i=0; i<this.options.length; i++) { | |
691 if (!this.options[i].checked) { | |
692 pairs.push([specification.id+"-exclude-"+i,specification.options[i].name]); | |
693 } | |
694 } | |
695 break; | |
696 } | |
697 return pairs; | |
698 } | |
699 switch(specification.type) { | |
700 case "number": | |
701 // Number can be ranged by min/max levels | |
702 this.min = ""; | |
703 this.max = ""; | |
704 this.minDOM = document.createElement("input"); | |
705 this.minDOM.type = "number"; | |
706 this.minDOM.name = "min"; | |
707 this.minDOM.addEventListener("change",this); | |
708 this.minDOMText = document.createElement("span"); | |
709 this.minDOMText.textContent = "Minimum: "; | |
710 var pairHolder = document.createElement("div"); | |
711 pairHolder.appendChild(this.minDOMText); | |
712 pairHolder.appendChild(this.minDOM); | |
713 this.rootDOM.appendChild(pairHolder); | |
714 | |
715 this.maxDOM = document.createElement("input"); | |
716 this.maxDOM.type = "number"; | |
717 this.maxDOM.name = "max"; | |
718 this.maxDOM.addEventListener("change",this); | |
719 this.maxDOMText = document.createElement("span"); | |
720 this.maxDOMText.textContent = "Maximum: "; | |
721 var pairHolder = document.createElement("div"); | |
722 pairHolder.appendChild(this.maxDOMText); | |
723 pairHolder.appendChild(this.maxDOM); | |
724 this.rootDOM.appendChild(pairHolder); | |
725 break; | |
726 case "radio": | |
727 case "checkbox": | |
728 this.options = []; | |
729 for (var i=0; i<specification.options.length; i++) { | |
730 var option = specification.options[i]; | |
731 var pairHolder = document.createElement("div"); | |
732 var text = document.createElement("span"); | |
733 text.textContent = option.text; | |
734 var check = document.createElement("input"); | |
735 check.type = "checkbox"; | |
736 check.setAttribute("option-index",i); | |
737 check.checked = true; | |
738 check.addEventListener("click",this); | |
739 this.options.push(check); | |
740 pairHolder.appendChild(text); | |
741 pairHolder.appendChild(check); | |
742 this.rootDOM.appendChild(pairHolder); | |
743 } | |
744 break; | |
745 default: | |
746 break; | |
747 } | |
748 } | |
749 for (var survey_entry of specification.preTest.options) { | |
750 switch(survey_entry.type) { | |
751 case "number": | |
752 case "radio": | |
753 case "checkbox": | |
754 var node = new FilterObject(this,survey_entry); | |
755 this.filterObjects.push(node); | |
756 this.filterDOM.appendChild(node.rootDOM); | |
757 break; | |
758 default: | |
759 break; | |
760 } | |
761 } | |
762 for (var survey_entry of specification.postTest.options) { | |
763 switch(survey_entry.type) { | |
764 case "number": | |
765 case "radio": | |
766 case "checkbox": | |
767 var node = new FilterObject(this,survey_entry); | |
768 this.filterObjects.push(node); | |
769 this.filterDOM.appendChild(node.rootDOM); | |
770 break; | |
771 default: | |
772 break; | |
773 } | |
774 } | |
775 document.getElementById("test-saved").appendChild(this.filterDOM); | |
776 } | |
777 this.getFileCount = function() { | |
778 // First we must get the filter pairs | |
779 var pairs = []; | |
780 for (var obj of this.filterObjects) { | |
781 pairs = pairs.concat(obj.getFilterPairs()); | |
782 } | |
783 var req_str = "../scripts/get_filtered_count.php?url="+testData.selectURL; | |
784 var index = 0; | |
785 while(pairs[index] != undefined) { | |
786 req_str += '&'; | |
787 req_str += pairs[index][0]+"="+pairs[index][1]; | |
788 index++; | |
789 } | |
790 get(req_str).then(function(response){ | |
791 var urls = JSON.parse(response); | |
792 var str = "Filtered to "+urls.urls.length+" file"; | |
793 if (urls.urls.length != 1) { | |
794 str += "s."; | |
795 } else { | |
796 str += "."; | |
797 } | |
798 document.getElementById("filter-count").textContent = str; | |
799 },function(error){ | |
800 console.error(error); | |
801 }); | |
802 } | |
803 } |