changeset 2886:c70036f28226

Fixes for #76 and #97
author Nicholas Jillings <nicholas.jillings@mail.bcu.ac.uk>
date Tue, 27 Jun 2017 13:07:41 +0100
parents 98209bb0fe87
children cedaf7ee1b81
files test_create.html test_create/interfaces/specifications.json test_create/test_core.js
diffstat 3 files changed, 359 insertions(+), 16 deletions(-) [+]
line wrap: on
line diff
--- a/test_create.html	Mon Jun 26 12:52:42 2017 +0100
+++ b/test_create.html	Tue Jun 27 13:07:41 2017 +0100
@@ -849,17 +849,17 @@
                     <h3>Axis Image</h3>
                     <textarea ng-model="interface.image"></textarea>
                 </div>
-                <div class="node">
+                <div class="node" name="scale-selection">
                     <h3>Axis Scales</h3>
                     <button type="button" class="btn btn-success" ng-click="addScale();">Add</button>
                     <button type="button" class="btn btn-danger" ng-click="clearScales()" ng-show="interface.scales.length > 0">Clear Scales</button>
                     <div class="dropdown" style="display: inline-block;">
                         <button class="btn btn-default dropdown-toggle" type="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="true">
-                            {{selectedScale}}
+                            Scales: {{selectedScale}}
                             <span class="caret"></span>
                         </button>
                         <ul class="dropdown-menu" aria-labelledby="dropdownMenu1">
-                            <li ng-repeat="scale in testSpecifications.scales" ng-click="useScales(scale)"><a href="#">{{scale.name}}</a></li>
+                            <li ng-repeat="scale in scales" ng-click="useScales(scale)"><a href="#">{{scale.name}}</a></li>
                         </ul>
                     </div>
                     <div class="node" ng-repeat="scale in interface.scales">
--- a/test_create/interfaces/specifications.json	Mon Jun 26 12:52:42 2017 +0100
+++ b/test_create/interfaces/specifications.json	Tue Jun 27 13:07:41 2017 +0100
@@ -5,14 +5,60 @@
             "interface": "APE",
             "description": {
                 "en": "Audio Perceptual Evaluation. A multi-stimulus test where each audio fragment is shown on one continuous slider. Fragments are randomnly positioned along the slider. The user clicks a fragment to play and drags to move."
-            }
+            },
+            "checks": [],
+            "show": [],
+            "elements": []
         }, {
             "name": "MUSHRA",
             "interface": "MUSHRA",
             "description": {
                 "en": "Multi-stimulus with hidden reference and anchor. Each fragment is shown on its own vertical slider. One fragment must be labelled as a reference and another labelled as an anchor. One external reference must also be shown."
             },
-            "scale": "ACR"
+            "scales": ["ACR"],
+            "checks": [{
+                "name": "fragmentMoved",
+                "support": "none"
+            }, {
+                "name": "fragmentPlayed",
+                "support": "none"
+            }, {
+                "name": "fragmentFullPlayback",
+                "support": "none"
+            }, {
+                "name": "fragmentComments",
+                "support": "none"
+            }, {
+                "name": "scalerange",
+                "support": "none"
+            }],
+            "show": [{
+                "name": "volume",
+                "support": "none"
+            }, {
+                "name": "page-count",
+                "support": "none"
+            }, {
+                "name": "playhead",
+                "support": "none"
+            }, {
+                "name": "comments",
+                "support": "none"
+            }],
+            "elements": [{
+                "anchor": {
+                    "min": 1,
+                    "max": "undefined"
+                },
+                "reference": {
+                    "min": 1,
+                    "max": "undefined"
+                },
+                "outsidereference": {
+                    "min": 1,
+                    "max": "undefined"
+                }
+            }]
         }, {
             "name": "Vertical Sliders",
             "interface": "MUSHRA",
@@ -43,60 +89,291 @@
             "description": {
                 "en": "Each stimulus is placed on a discrete scale. The scale is fixed to the Likert scale options of 'Strongly Disagree', 'Disagree', 'Neutral', 'Agree' and 'Strongly Agree'"
             },
-            "scale": "Likert"
+            "scales": ["Likert"],
+            "checks": [{
+                "name": "fragmentPlayed",
+                "support": "none"
+            }, {
+                "name": "fragmentFullPlayback",
+                "support": "none"
+            }, {
+                "name": "fragmentComments",
+                "support": "none"
+            }],
+            "show": [{
+                "name": "volume",
+                "support": "none"
+            }, {
+                "name": "page-count",
+                "support": "none"
+            }, {
+                "name": "playhead",
+                "support": "none"
+            }, {
+                "name": "comments",
+                "support": "none"
+            }]
         }, {
             "name": "ABC/HR",
             "interface": "MUSHRA",
             "description": {
                 "en": "Each stimulus is placed on a vertical slider. The scale is fixed with the labels 'Imperceptible' to 'Very Annoying'"
             },
-            "scale": "ABC"
+            "scales": ["ABC"],
+            "checks": [{
+                "name": "fragmentMoved",
+                "support": "none"
+            }, {
+                "name": "fragmentPlayed",
+                "support": "none"
+            }, {
+                "name": "fragmentFullPlayback",
+                "support": "none"
+            }, {
+                "name": "fragmentComments",
+                "support": "none"
+            }],
+            "show": [{
+                "name": "volume",
+                "support": "none"
+            }, {
+                "name": "page-count",
+                "support": "none"
+            }, {
+                "name": "playhead",
+                "support": "none"
+            }, {
+                "name": "comments",
+                "support": "none"
+            }]
         }, {
             "name": "Bipolar",
             "interface": "horizontal",
             "description": {
                 "en": "Each stimulus is placed on a horizontal slider and initialised to the value '0'. The scale operates from -50 to +5-. In the results this is normalised, like all other interfaces, from 0 (-50) to 1 (+50)"
             },
-            "scale": "Bipolar"
+            "scales": ["Bipolar"],
+            "checks": [{
+                "name": "fragmentMoved",
+                "support": "none"
+            }, {
+                "name": "fragmentPlayed",
+                "support": "none"
+            }, {
+                "name": "fragmentFullPlayback",
+                "support": "none"
+            }, {
+                "name": "fragmentComments",
+                "support": "none"
+            }],
+            "show": [{
+                "name": "volume",
+                "support": "none"
+            }, {
+                "name": "page-count",
+                "support": "none"
+            }, {
+                "name": "playhead",
+                "support": "none"
+            }, {
+                "name": "comments",
+                "support": "none"
+            }]
         }, {
             "name": "Absolute Category Rating",
             "interface": "discrete",
             "description": {
                 "en": "Each element is on a discrete scale of 'Bad', 'Poor', 'Fair', 'Good' and 'Excellent'. Each element must be given a rating."
             },
-            "scale": "ACR"
+            "scales": ["ACR"],
+            "checks": [{
+                "name": "fragmentMoved",
+                "support": "mandatory"
+            }, {
+                "name": "fragmentPlayed",
+                "support": "none"
+            }, {
+                "name": "fragmentFullPlayback",
+                "support": "none"
+            }, {
+                "name": "fragmentComments",
+                "support": "none"
+            }],
+            "show": [{
+                "name": "volume",
+                "support": "none"
+            }, {
+                "name": "page-count",
+                "support": "none"
+            }, {
+                "name": "playhead",
+                "support": "none"
+            }, {
+                "name": "comments",
+                "support": "none"
+            }]
         }, {
             "name": "Discrete Category Rating",
             "interface": "discrete",
             "description": {
                 "en": ""
             },
-            "scale": "DCR"
+            "scales": ["DCR"],
+            "checks": [{
+                "name": "fragmentPlayed",
+                "support": "none"
+            }, {
+                "name": "fragmentFullPlayback",
+                "support": "none"
+            }, {
+                "name": "fragmentComments",
+                "support": "none"
+            }],
+            "show": [{
+                "name": "volume",
+                "support": "none"
+            }, {
+                "name": "page-count",
+                "support": "none"
+            }, {
+                "name": "playhead",
+                "support": "none"
+            }, {
+                "name": "comments",
+                "support": "none"
+            }]
         }, {
-            "name": "HCRS",
+            "name": "Hedonic Cat. Rating",
             "interface": "MUSHRA",
             "description": {
                 "en": ""
             },
-            "scale": "Hedonic Category Rating Scale"
+            "scales": ["Hedonic Category Rating Scale"],
+            "checks": [{
+                "name": "fragmentMoved",
+                "support": "mandatory"
+            }, {
+                "name": "fragmentPlayed",
+                "support": "none"
+            }, {
+                "name": "fragmentFullPlayback",
+                "support": "none"
+            }, {
+                "name": "fragmentComments",
+                "support": "none"
+            }],
+            "show": [{
+                "name": "volume",
+                "support": "none"
+            }, {
+                "name": "page-count",
+                "support": "none"
+            }, {
+                "name": "playhead",
+                "support": "none"
+            }, {
+                "name": "comments",
+                "support": "none"
+            }],
+            "elements": {
+                "outsidereference": {
+                    "min": 1,
+                    "max": 1
+                }
+            }
         }, {
             "name": "ITUR5PCIS",
             "interface": "MUSHRA",
             "description": {
                 "en": ""
             },
-            "scale": "ACR"
+            "scales": ["ABC"],
+            "checks": [{
+                "name": "fragmentMoved",
+                "support": "none"
+            }, {
+                "name": "fragmentPlayed",
+                "support": "none"
+            }, {
+                "name": "fragmentFullPlayback",
+                "support": "none"
+            }, {
+                "name": "fragmentComments",
+                "support": "none"
+            }],
+            "show": [{
+                "name": "volume",
+                "support": "none"
+            }, {
+                "name": "page-count",
+                "support": "none"
+            }, {
+                "name": "playhead",
+                "support": "none"
+            }, {
+                "name": "comments",
+                "support": "none"
+            }],
+            "elements": {
+                "outsidereference": {
+                    "min": 1,
+                    "max": 1
+                }
+            }
+        }, {
+            "name": "Pairwise",
+            "interface": "AB",
+            "description": {
+                "en": "A discrete interface where each page holds each fragment. The user must select one fragment. All other fragments are not selected"
+            },
+            "hasScales": "false",
+            "elements": {
+                "number": {
+                    "min": 2,
+                    "max": "undefined"
+                }
+            }
         }, {
             "name": "AB",
             "interface": "AB",
             "description": {
                 "en": "Each page contains two audio fragments. The user must select one of the fragments to proceed. There can be an outside reference."
+            },
+            "hasScales": "false",
+            "checks": [{
+                "name": "fragmentPlayed",
+                "support": "mandatory"
+            }],
+            "elements": {
+                "number": {
+                    "min": 2,
+                    "max": 2
+                },
+                "outsidereference": {
+                    "min": 0,
+                    "max": 1
+                }
             }
         }, {
             "name": "ABX",
             "interface": "ABX",
             "description": {
                 "en": "Each page has two audio fragments presented as A and B. The test duplicates one of the fragments and presents it as X. The user must choose which, out of A or B, is closest to X."
+            },
+            "hasScales": "false",
+            "checks": [{
+                "name": "fragmentPlayed",
+                "support": "mandatory"
+            }],
+            "elements": {
+                "number": {
+                    "min": 2,
+                    "max": 2
+                },
+                "outsidereference": {
+                    "min": 0,
+                    "max": 1
+                }
             }
         }, {
             "name": "Timeline",
--- a/test_create/test_core.js	Mon Jun 26 12:52:42 2017 +0100
+++ b/test_create/test_core.js	Tue Jun 27 13:07:41 2017 +0100
@@ -83,6 +83,11 @@
         $s.globalSchema = specification.getSchema();
     });
     $s.specification = specification;
+    $s.selectedTestPrototype = undefined;
+    $s.setTestPrototype = function (obj) {
+        $s.selectedTestPrototype = obj;
+        $w.specification.interface = obj.interface;
+    }
 
     $s.addPage = function () {
         $s.specification.createNewPage();
@@ -132,7 +137,10 @@
         var obj = $s.testSpecifications.interfaces.find(function (i) {
             return i.name == name;
         });
-        specification.interface = obj.interface;
+        if (obj === undefined) {
+            throw ("Cannot find specification");
+        }
+        $s.setTestPrototype(obj);
     };
     // Get the test interface specifications
     $s.file = undefined;
@@ -191,6 +199,10 @@
             }
         }
     };
+
+    $s.configure = function () {}
+
+    $s.$watch("selectedTestPrototype", $s.configure);
 }]);
 
 AngularInterface.controller("survey", ['$scope', '$element', '$window', function ($s, $e, $w) {
@@ -283,6 +295,7 @@
             $s.interface.options.splice(index, 1);
         }
     };
+    $s.scales = [];
     $s.removeScale = function (scale) {
         var index = $s.interface.scales.findIndex(function (s) {
             return s == scale;
@@ -305,9 +318,62 @@
         scale.scales.forEach(function (s) {
             $s.interface.scales.push(s);
         });
-        $s.selectedScale = "Scale: " + scale.name;
+        $s.selectedScale = scale.name;
     };
-    $s.selectedScale = "Scale: Custom";
+    $s.selectedScale = undefined;
+
+    $s.configure = function () {
+        if ($s.selectedTestPrototype === undefined) {
+            return;
+        }
+        if ($s.selectedTestPrototype.checks && $s.selectedTestPrototype.checks.length >= 1) {
+            $s.selectedTestPrototype.checks.forEach(function (entry) {
+                var dom = $e[0].querySelector("[name=\"" + entry.name + "\"] input");
+                if (entry.support == "none") {
+                    dom.checked = false;
+                    dom.disabled = true;
+                }
+            });
+        }
+        if ($s.selectedTestPrototype.show && $s.selectedTestPrototype.show.length >= 1) {
+            $s.selectedTestPrototype.show.forEach(function (entry) {
+                var dom = $e[0].querySelector("[name=\"" + entry.name + "\"] input");
+                if (entry.support == "none") {
+                    dom.checked = false;
+                    dom.disabled = true;
+                }
+            });
+        }
+        if ($s.interface !== specification.interfaces) {
+            // Page specific interface nodes
+            if ($s.selectedTestPrototype.hasScales !== undefined && ($s.selectedTestPrototype.hasScales == "false" || $s.selectedTestPrototype.hasScales == false)) {
+                var elem = $e[0].querySelector("[name=\"scale-selection\"]")
+                elem.style.visibility = "hidden";
+                elem.style.height = "0px";
+            }
+            if ($s.selectedTestPrototype.scales && $s.selectedTestPrototype.show.length >= 1) {
+                $s.scales = [];
+                $s.selectedTestPrototype.scales.forEach(function (scalename) {
+                    var obj = $s.testSpecifications.scales.find(function (a) {
+                        return a.name == scalename;
+                    });
+                    $s.scales.push(obj);
+                });
+                if ($s.selectedTestPrototype.scales.includes($s.selectedScale) == false) {
+                    $s.clearScales();
+                }
+                if ($s.scales.length == 1) {
+                    $s.clearScales();
+                    $s.useScales($s.scales[0]);
+                }
+            } else {
+                $s.scales = $s.testSpecifications.scales;
+            }
+        }
+    };
+
+    $s.$watch("selectedTestPrototype", $s.configure);
+    $s.configure();
 }]);
 AngularInterface.controller("page", ['$scope', '$element', '$window', function ($s, $e, $w) {
     $s.addInterface = function () {