@pie-element/hotspot 4.10.9 → 4.10.11-beta.1443
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +360 -0
- package/configure/CHANGELOG.md +319 -0
- package/configure/lib/button.js.map +1 -1
- package/configure/lib/defaults.js +23 -2
- package/configure/lib/defaults.js.map +1 -1
- package/configure/lib/hotspot-container.js +28 -19
- package/configure/lib/hotspot-container.js.map +1 -1
- package/configure/lib/hotspot-drawable.js +3 -3
- package/configure/lib/hotspot-drawable.js.map +1 -1
- package/configure/lib/hotspot-palette.js.map +1 -1
- package/configure/lib/hotspot-polygon.js.map +1 -1
- package/configure/lib/hotspot-rectangle.js.map +1 -1
- package/configure/lib/index.js +16 -2
- package/configure/lib/index.js.map +1 -1
- package/configure/lib/root.js +129 -38
- package/configure/lib/root.js.map +1 -1
- package/configure/lib/upload-control.js.map +1 -1
- package/configure/lib/utils.js +15 -3
- package/configure/lib/utils.js.map +1 -1
- package/configure/package.json +4 -4
- package/configure/src/__tests__/__snapshots__/hotspot-container.test.js.snap +1 -1
- package/configure/src/__tests__/__snapshots__/root.test.js.snap +56 -4
- package/configure/src/__tests__/hotspot-container.test.js +98 -71
- package/configure/src/__tests__/hotspot-drawable.test.js +48 -49
- package/configure/src/__tests__/index.test.js +28 -51
- package/configure/src/__tests__/root.test.js +162 -82
- package/configure/src/__tests__/utils.test.js +112 -98
- package/configure/src/button.jsx +4 -4
- package/configure/src/defaults.js +35 -18
- package/configure/src/hotspot-container.jsx +99 -98
- package/configure/src/hotspot-drawable.jsx +56 -56
- package/configure/src/hotspot-palette.jsx +12 -25
- package/configure/src/hotspot-polygon.jsx +20 -22
- package/configure/src/hotspot-rectangle.jsx +5 -15
- package/configure/src/index.js +32 -18
- package/configure/src/root.jsx +116 -60
- package/configure/src/upload-control.jsx +9 -20
- package/configure/src/utils.js +51 -22
- package/controller/CHANGELOG.md +23 -0
- package/controller/lib/defaults.js +2 -2
- package/controller/lib/defaults.js.map +1 -1
- package/controller/lib/index.js +39 -3
- package/controller/lib/index.js.map +1 -1
- package/controller/lib/utils.js.map +1 -1
- package/controller/package.json +2 -2
- package/controller/src/__tests__/index.test.js +29 -50
- package/controller/src/defaults.js +5 -9
- package/controller/src/index.js +47 -33
- package/controller/src/utils.js +9 -6
- package/docs/config-schema.json +217 -0
- package/docs/config-schema.json.md +169 -0
- package/docs/demo/config.js +2 -2
- package/docs/demo/generate.js +53 -35
- package/docs/demo/session.js +2 -2
- package/docs/pie-schema.json +49 -0
- package/docs/pie-schema.json.md +36 -0
- package/lib/hotspot/container.js +24 -6
- package/lib/hotspot/container.js.map +1 -1
- package/lib/hotspot/icons.js.map +1 -1
- package/lib/hotspot/image.js.map +1 -1
- package/lib/hotspot/index.js +65 -5
- package/lib/hotspot/index.js.map +1 -1
- package/lib/hotspot/polygon.js +45 -19
- package/lib/hotspot/polygon.js.map +1 -1
- package/lib/hotspot/rectangle.js +45 -19
- package/lib/hotspot/rectangle.js.map +1 -1
- package/lib/index.js +3 -0
- package/lib/index.js.map +1 -1
- package/lib/session-updater.js.map +1 -1
- package/package.json +6 -4
- package/src/__tests__/__snapshots__/{container-test.jsx.snap → container.test.jsx.snap} +8 -0
- package/src/__tests__/__snapshots__/image.test.jsx.snap +43 -0
- package/src/__tests__/__snapshots__/{polygon-test.jsx.snap → polygon.test.jsx.snap} +11 -0
- package/src/__tests__/__snapshots__/{rectangle-test.jsx.snap → rectangle.test.jsx.snap} +11 -0
- package/src/__tests__/container.test.jsx +214 -0
- package/src/__tests__/{image-test.jsx → image.test.jsx} +2 -2
- package/src/__tests__/polygon.test.jsx +235 -0
- package/src/__tests__/rectangle.test.jsx +237 -0
- package/src/__tests__/{session-updater-test.jsx → session-updater.test.jsx} +22 -31
- package/src/hotspot/container.jsx +40 -23
- package/src/hotspot/icons.js +4 -2
- package/src/hotspot/image.jsx +4 -8
- package/src/hotspot/index.jsx +73 -33
- package/src/hotspot/polygon.jsx +48 -30
- package/src/hotspot/rectangle.jsx +48 -30
- package/src/index.js +10 -18
- package/src/session-updater.js +1 -1
- package/src/__tests__/__snapshots__/image-test.jsx.snap +0 -21
- package/src/__tests__/container-test.jsx +0 -143
- package/src/__tests__/polygon-test.jsx +0 -77
- package/src/__tests__/rectangle-test.jsx +0 -78
|
@@ -4,36 +4,25 @@ import { withStyles } from '@material-ui/core/styles/index';
|
|
|
4
4
|
|
|
5
5
|
import Button from './button';
|
|
6
6
|
|
|
7
|
-
const UploadControl = ({
|
|
8
|
-
classNameButton,
|
|
9
|
-
classNameSection,
|
|
10
|
-
classes,
|
|
11
|
-
label,
|
|
12
|
-
onInputClick,
|
|
13
|
-
onUploadImage,
|
|
14
|
-
setRef
|
|
15
|
-
}) => (
|
|
7
|
+
const UploadControl = ({ classNameButton, classNameSection, classes, label, onInputClick, onUploadImage, setRef }) => (
|
|
16
8
|
<div className={classNameSection}>
|
|
17
|
-
<Button
|
|
18
|
-
className={classNameButton}
|
|
19
|
-
label={label}
|
|
20
|
-
onClick={onInputClick}
|
|
21
|
-
/>
|
|
9
|
+
<Button className={classNameButton} label={label} onClick={onInputClick} />
|
|
22
10
|
<input
|
|
23
11
|
accept="image/*"
|
|
24
12
|
className={classes.input}
|
|
25
13
|
onChange={onUploadImage}
|
|
26
|
-
ref={ref => {
|
|
14
|
+
ref={(ref) => {
|
|
15
|
+
setRef(ref);
|
|
16
|
+
}}
|
|
27
17
|
type="file"
|
|
28
18
|
/>
|
|
29
19
|
</div>
|
|
30
20
|
);
|
|
31
21
|
|
|
32
|
-
|
|
33
22
|
const styles = () => ({
|
|
34
23
|
input: {
|
|
35
|
-
display: 'none'
|
|
36
|
-
}
|
|
24
|
+
display: 'none',
|
|
25
|
+
},
|
|
37
26
|
});
|
|
38
27
|
|
|
39
28
|
UploadControl.propTypes = {
|
|
@@ -43,12 +32,12 @@ UploadControl.propTypes = {
|
|
|
43
32
|
label: PropTypes.string.isRequired,
|
|
44
33
|
onInputClick: PropTypes.func.isRequired,
|
|
45
34
|
onUploadImage: PropTypes.func.isRequired,
|
|
46
|
-
setRef: PropTypes.func.isRequired
|
|
35
|
+
setRef: PropTypes.func.isRequired,
|
|
47
36
|
};
|
|
48
37
|
|
|
49
38
|
UploadControl.defaultProps = {
|
|
50
39
|
classNameButton: '',
|
|
51
|
-
classNameSection: ''
|
|
40
|
+
classNameSection: '',
|
|
52
41
|
};
|
|
53
42
|
|
|
54
43
|
export default withStyles(styles)(UploadControl);
|
package/configure/src/utils.js
CHANGED
|
@@ -9,28 +9,29 @@ const updateImageDimensions = (initialDim, nextDim, keepAspectRatio, resizeType)
|
|
|
9
9
|
// if we want to change image height => we update the width accordingly
|
|
10
10
|
return {
|
|
11
11
|
width: nextDim.height * imageAspectRatio,
|
|
12
|
-
height: nextDim.height
|
|
13
|
-
}
|
|
12
|
+
height: nextDim.height,
|
|
13
|
+
};
|
|
14
14
|
}
|
|
15
15
|
|
|
16
16
|
// if we want to change image width => we update the height accordingly
|
|
17
17
|
return {
|
|
18
18
|
width: nextDim.width,
|
|
19
|
-
height: nextDim.width / imageAspectRatio
|
|
20
|
-
}
|
|
19
|
+
height: nextDim.width / imageAspectRatio,
|
|
20
|
+
};
|
|
21
21
|
}
|
|
22
22
|
|
|
23
23
|
// if we don't want to keep aspect ratio, we just update both values
|
|
24
24
|
return {
|
|
25
25
|
width: nextDim.width,
|
|
26
|
-
height: nextDim.height
|
|
27
|
-
}
|
|
26
|
+
height: nextDim.height,
|
|
27
|
+
};
|
|
28
28
|
};
|
|
29
29
|
|
|
30
30
|
// referenceInitialValue = the initial value of the Stage
|
|
31
31
|
// referenceNextValue = the next value of the Stage
|
|
32
32
|
// currentValue = the value that has to be re-sized influenced by the changes that were made on the Stage
|
|
33
|
-
const getDelta = (referenceInitialValue, referenceNextValue, currentValue) =>
|
|
33
|
+
const getDelta = (referenceInitialValue, referenceNextValue, currentValue) =>
|
|
34
|
+
(referenceNextValue / referenceInitialValue) * currentValue;
|
|
34
35
|
|
|
35
36
|
const getUpdatedRectangle = (initialDim, nextDim, shape) => ({
|
|
36
37
|
...shape,
|
|
@@ -42,17 +43,17 @@ const getUpdatedRectangle = (initialDim, nextDim, shape) => ({
|
|
|
42
43
|
|
|
43
44
|
const getUpdatedPlygon = (initialDim, nextDim, shape) => ({
|
|
44
45
|
...shape,
|
|
45
|
-
points: shape.points.map(point => ({
|
|
46
|
+
points: shape.points.map((point) => ({
|
|
46
47
|
x: getDelta(initialDim.width, nextDim.width, point.x),
|
|
47
48
|
y: getDelta(initialDim.height, nextDim.height, point.y),
|
|
48
|
-
}))
|
|
49
|
+
})),
|
|
49
50
|
});
|
|
50
51
|
|
|
51
52
|
// initialDim = the initial dimensions: { width, height } of the Stage
|
|
52
53
|
// nextDim = the next dimensions: { width, height } of the Stage
|
|
53
54
|
// shapes = array of shapes that have to be re-sized and re-positioned
|
|
54
55
|
const getUpdatedShapes = (initialDim, nextDim, shapes) => {
|
|
55
|
-
return shapes.map(shape => {
|
|
56
|
+
return shapes.map((shape) => {
|
|
56
57
|
if (shape.group === 'rectangles') {
|
|
57
58
|
return getUpdatedRectangle(initialDim, nextDim, shape);
|
|
58
59
|
}
|
|
@@ -75,16 +76,19 @@ const getAllShapes = (shapesMap) => {
|
|
|
75
76
|
const shapesKeys = Object.keys(shapesMap);
|
|
76
77
|
|
|
77
78
|
return shapesKeys.length
|
|
78
|
-
? shapesKeys.reduce(
|
|
79
|
-
acc
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
79
|
+
? shapesKeys.reduce(
|
|
80
|
+
(acc, currentShapeKey) =>
|
|
81
|
+
acc.concat(
|
|
82
|
+
shapesMap[currentShapeKey]
|
|
83
|
+
? shapesMap[currentShapeKey].map((shape, index) => ({
|
|
84
|
+
...shape,
|
|
85
|
+
group: currentShapeKey,
|
|
86
|
+
index: shape.index || acc.length + index,
|
|
87
|
+
}))
|
|
88
|
+
: [],
|
|
89
|
+
),
|
|
90
|
+
shapesArray,
|
|
91
|
+
)
|
|
88
92
|
: shapesArray;
|
|
89
93
|
};
|
|
90
94
|
|
|
@@ -97,7 +101,7 @@ const groupShapes = (shapesArray) => {
|
|
|
97
101
|
shapesArray = shapesArray || [];
|
|
98
102
|
const shapesMap = {
|
|
99
103
|
rectangles: [],
|
|
100
|
-
polygons: []
|
|
104
|
+
polygons: [],
|
|
101
105
|
};
|
|
102
106
|
|
|
103
107
|
if (shapesArray.length) {
|
|
@@ -110,5 +114,30 @@ const groupShapes = (shapesArray) => {
|
|
|
110
114
|
return cloneDeep(shapesMap);
|
|
111
115
|
};
|
|
112
116
|
|
|
117
|
+
const generateValidationMessage = (config) => {
|
|
118
|
+
const { minShapes, maxShapes, maxSelections } = config;
|
|
119
|
+
|
|
120
|
+
const shapesMessage =
|
|
121
|
+
`\nThere should be at least ${minShapes} ` + (maxShapes ? `and at most ${maxShapes} ` : '') + 'shapes defined.';
|
|
122
|
+
|
|
123
|
+
const selectionsMessage =
|
|
124
|
+
`\nThere should be at least 1 ` +
|
|
125
|
+
(maxSelections ? `and at most ${maxSelections} ` : '') +
|
|
126
|
+
'shape' +
|
|
127
|
+
(maxSelections ? 's' : '') +
|
|
128
|
+
' selected.';
|
|
113
129
|
|
|
114
|
-
|
|
130
|
+
const message = 'Validation requirements:' + shapesMessage + selectionsMessage;
|
|
131
|
+
|
|
132
|
+
return message;
|
|
133
|
+
};
|
|
134
|
+
|
|
135
|
+
export {
|
|
136
|
+
updateImageDimensions,
|
|
137
|
+
generateValidationMessage,
|
|
138
|
+
getUpdatedShapes,
|
|
139
|
+
getAllShapes,
|
|
140
|
+
groupShapes,
|
|
141
|
+
getUpdatedRectangle,
|
|
142
|
+
getUpdatedPlygon,
|
|
143
|
+
};
|
package/controller/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,29 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
5
|
|
|
6
|
+
## [3.5.1](https://github.com/pie-framework/pie-elements/compare/@pie-element/hotspot-controller@3.5.0...@pie-element/hotspot-controller@3.5.1) (2022-12-07)
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
### Bug Fixes
|
|
10
|
+
|
|
11
|
+
* update libs ([441f403](https://github.com/pie-framework/pie-elements/commit/441f403870b7bec0d61fab58b8d93dbe0ead4c32))
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
# [3.5.0](https://github.com/pie-framework/pie-elements/compare/@pie-element/hotspot-controller@3.4.8...@pie-element/hotspot-controller@3.5.0) (2022-05-03)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
### Features
|
|
21
|
+
|
|
22
|
+
* **hotspot:** added configurable validation PD-1702 ([18eb985](https://github.com/pie-framework/pie-elements/commit/18eb98568adf9248dc616a9ae71d9f8394b62fc1))
|
|
23
|
+
* **hotspot:** PD-1703 implement ui/ux for item validation ([a962183](https://github.com/pie-framework/pie-elements/commit/a962183d0941936b69a95b32002135507d769170))
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
|
|
6
29
|
## [3.4.5](https://github.com/pie-framework/pie-elements/compare/@pie-element/hotspot-controller@3.4.3...@pie-element/hotspot-controller@3.4.5) (2021-11-11)
|
|
7
30
|
|
|
8
31
|
**Note:** Version bump only for package @pie-element/hotspot-controller
|
|
@@ -17,8 +17,8 @@ var _default = {
|
|
|
17
17
|
height: 0,
|
|
18
18
|
width: 0
|
|
19
19
|
},
|
|
20
|
-
hotspotColor: 'rgba(137, 183, 244, 0.
|
|
21
|
-
hotspotList: ['rgba(137, 183, 244, 0.
|
|
20
|
+
hotspotColor: 'rgba(137, 183, 244, 0.25)',
|
|
21
|
+
hotspotList: ['rgba(137, 183, 244, 0.25)'],
|
|
22
22
|
outlineColor: 'blue',
|
|
23
23
|
outlineList: ['blue']
|
|
24
24
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/defaults.js"],"names":["prompt","imageUrl","shapes","rectangles","polygons","multipleCorrect","partialScoring","dimensions","height","width","hotspotColor","hotspotList","outlineColor","outlineList"],"mappings":";;;;;;eAAe;AACbA,EAAAA,MAAM,EAAE,6BADK;AAEbC,EAAAA,QAAQ,EAAE,EAFG;AAGbC,EAAAA,MAAM,EAAE;AACNC,IAAAA,UAAU,EAAE,EADN;AAENC,IAAAA,QAAQ,EAAE;AAFJ,GAHK;AAObC,EAAAA,eAAe,EAAE,IAPJ;AAQbC,EAAAA,cAAc,EAAE,KARH;AASbC,EAAAA,UAAU,EAAE;AACVC,IAAAA,MAAM,EAAE,CADE;AAEVC,IAAAA,KAAK,EAAE;AAFG,GATC;AAabC,EAAAA,YAAY,EAAE,2BAbD;AAcbC,EAAAA,WAAW,EAAE,
|
|
1
|
+
{"version":3,"sources":["../src/defaults.js"],"names":["prompt","imageUrl","shapes","rectangles","polygons","multipleCorrect","partialScoring","dimensions","height","width","hotspotColor","hotspotList","outlineColor","outlineList"],"mappings":";;;;;;eAAe;AACbA,EAAAA,MAAM,EAAE,6BADK;AAEbC,EAAAA,QAAQ,EAAE,EAFG;AAGbC,EAAAA,MAAM,EAAE;AACNC,IAAAA,UAAU,EAAE,EADN;AAENC,IAAAA,QAAQ,EAAE;AAFJ,GAHK;AAObC,EAAAA,eAAe,EAAE,IAPJ;AAQbC,EAAAA,cAAc,EAAE,KARH;AASbC,EAAAA,UAAU,EAAE;AACVC,IAAAA,MAAM,EAAE,CADE;AAEVC,IAAAA,KAAK,EAAE;AAFG,GATC;AAabC,EAAAA,YAAY,EAAE,2BAbD;AAcbC,EAAAA,WAAW,EAAE,CAAC,2BAAD,CAdA;AAebC,EAAAA,YAAY,EAAE,MAfD;AAgBbC,EAAAA,WAAW,EAAE,CAAC,MAAD;AAhBA,C","sourcesContent":["export default {\n prompt: 'This is the question prompt',\n imageUrl: '',\n shapes: {\n rectangles: [],\n polygons: [],\n },\n multipleCorrect: true,\n partialScoring: false,\n dimensions: {\n height: 0,\n width: 0,\n },\n hotspotColor: 'rgba(137, 183, 244, 0.25)',\n hotspotList: ['rgba(137, 183, 244, 0.25)'],\n outlineColor: 'blue',\n outlineList: ['blue'],\n};\n"],"file":"defaults.js"}
|
package/controller/lib/index.js
CHANGED
|
@@ -5,9 +5,11 @@ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefau
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", {
|
|
6
6
|
value: true
|
|
7
7
|
});
|
|
8
|
+
exports.createDefaultModel = exports.createCorrectResponseSession = void 0;
|
|
8
9
|
exports.model = model;
|
|
10
|
+
exports.normalize = void 0;
|
|
9
11
|
exports.outcome = outcome;
|
|
10
|
-
exports.
|
|
12
|
+
exports.validate = void 0;
|
|
11
13
|
|
|
12
14
|
var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
|
|
13
15
|
|
|
@@ -28,9 +30,9 @@ var _defaults = _interopRequireDefault(require("./defaults"));
|
|
|
28
30
|
var _excluded = ["index"],
|
|
29
31
|
_excluded2 = ["index"];
|
|
30
32
|
|
|
31
|
-
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object);
|
|
33
|
+
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
|
|
32
34
|
|
|
33
|
-
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]
|
|
35
|
+
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { (0, _defineProperty2["default"])(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
|
|
34
36
|
|
|
35
37
|
var log = (0, _debug["default"])('pie-elements:hotspot:controller');
|
|
36
38
|
|
|
@@ -224,4 +226,38 @@ var createCorrectResponseSession = function createCorrectResponseSession(questio
|
|
|
224
226
|
};
|
|
225
227
|
|
|
226
228
|
exports.createCorrectResponseSession = createCorrectResponseSession;
|
|
229
|
+
|
|
230
|
+
var validate = function validate() {
|
|
231
|
+
var model = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
|
232
|
+
var config = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
233
|
+
var shapes = model.shapes;
|
|
234
|
+
var _config$minShapes = config.minShapes,
|
|
235
|
+
minShapes = _config$minShapes === void 0 ? 2 : _config$minShapes,
|
|
236
|
+
maxShapes = config.maxShapes,
|
|
237
|
+
maxSelections = config.maxSelections;
|
|
238
|
+
var errors = {};
|
|
239
|
+
var allShapes = Object.values(shapes || {}).reduce(function (acc, shape) {
|
|
240
|
+
return [].concat((0, _toConsumableArray2["default"])(acc), (0, _toConsumableArray2["default"])(shape));
|
|
241
|
+
}, []);
|
|
242
|
+
var nbOfSelections = (allShapes || []).reduce(function (acc, shape) {
|
|
243
|
+
return shape.correct ? acc + 1 : acc;
|
|
244
|
+
}, 0);
|
|
245
|
+
var nbOfShapes = (allShapes || []).length;
|
|
246
|
+
|
|
247
|
+
if (nbOfShapes < minShapes) {
|
|
248
|
+
errors.shapesError = "There should be at least ".concat(minShapes, " shapes defined.");
|
|
249
|
+
} else if (nbOfShapes > maxShapes) {
|
|
250
|
+
errors.shapesError = "No more than ".concat(maxShapes, " shapes should be defined.");
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
if (nbOfSelections < 1) {
|
|
254
|
+
errors.selectionsError = 'There should be at least 1 shape selected.';
|
|
255
|
+
} else if (nbOfSelections > maxSelections) {
|
|
256
|
+
errors.selectionsError = "No more than ".concat(maxSelections, " shapes should be selected.");
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
return errors;
|
|
260
|
+
};
|
|
261
|
+
|
|
262
|
+
exports.validate = validate;
|
|
227
263
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.js"],"names":["log","normalize","question","promptEnabled","rationaleEnabled","teacherInstructionsEnabled","studentInstructionsEnabled","strokeWidth","model","session","env","normalizedQuestion","imageUrl","dimensions","hotspotColor","multipleCorrect","outlineColor","partialScoring","prompt","shapes","rectangles","polygons","Promise","resolve","out","disabled","mode","map","index","rectProps","polyProps","responseCorrect","undefined","role","rationale","teacherInstructions","createDefaultModel","defaults","getScore","config","answers","partialScoringEnabled","enabled","correctAnswers","selectedChoices","choices","correctChoices","filter","choice","correct","forEach","shape","selected","answer","id","correctlySelected","extraAnswers","length","total","str","toFixed","parseFloat","outcome","score","empty","returnShapesCorrect","i","push","createCorrectResponseSession","rectangleCorrect","polygonsCorrect"],"mappings":"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","sourcesContent":["import debug from 'debug';\nimport isEmpty from 'lodash/isEmpty';\nimport { partialScoring } from '@pie-lib/controller-utils';\n\nimport { isResponseCorrect } from './utils';\n\nimport defaults from './defaults';\n\nconst log = debug('pie-elements:hotspot:controller');\n\nexport const normalize = question => ({\n promptEnabled: true,\n rationaleEnabled: true,\n teacherInstructionsEnabled: true,\n studentInstructionsEnabled: true,\n strokeWidth: 5,\n ...question,\n});\n\nexport function model(question, session, env) {\n const normalizedQuestion = normalize(question);\n const {\n imageUrl,\n dimensions,\n hotspotColor,\n multipleCorrect,\n outlineColor,\n partialScoring,\n prompt,\n shapes\n } = normalizedQuestion;\n const { rectangles, polygons } = shapes || {};\n\n return new Promise(resolve => {\n const out = {\n disabled: env.mode !== 'gather',\n mode: env.mode,\n dimensions,\n imageUrl,\n outlineColor,\n hotspotColor,\n multipleCorrect,\n partialScoring,\n shapes: {\n ...shapes,\n // eslint-disable-next-line no-unused-vars\n rectangles: (rectangles || []).map(({ index, ...rectProps }) => ({ ...rectProps })),\n // eslint-disable-next-line no-unused-vars\n polygons: (polygons || []).map(({ index, ...polyProps }) => ({ ...polyProps }))\n },\n responseCorrect:\n env.mode === 'evaluate'\n ? isResponseCorrect(normalizedQuestion, session)\n : undefined\n };\n\n if (env.role === 'instructor' && (env.mode === 'view' || env.mode === 'evaluate')) {\n out.rationale = normalizedQuestion.rationaleEnabled ? normalizedQuestion.rationale : null;\n out.teacherInstructions = normalizedQuestion.teacherInstructionsEnabled ? normalizedQuestion.teacherInstructions : null;\n } else {\n out.rationale = null;\n out.teacherInstructions = null;\n }\n\n out.prompt = normalizedQuestion.promptEnabled ? prompt : null;\n out.strokeWidth = normalizedQuestion.strokeWidth;\n\n // console.log(out);\n resolve(out);\n });\n}\n\nexport const createDefaultModel = (model = {}) =>\n new Promise(resolve => {\n resolve({\n ...defaults,\n ...model,\n });\n });\n\nconst getScore = (config, session, env = {}) => {\n const { answers } = session || {};\n\n if (!config.shapes || (!config.shapes.rectangles && !config.shapes.polygons)) {\n return 0;\n }\n\n const { shapes: { rectangles = [], polygons = [] } = {} } = config;\n const partialScoringEnabled = partialScoring.enabled(config, env);\n\n if (!partialScoringEnabled) {\n return isResponseCorrect(config, session) ? 1 : 0;\n }\n\n let correctAnswers = 0;\n let selectedChoices = 0;\n\n const choices = [...rectangles, ...polygons];\n\n const correctChoices = choices.filter(choice => choice.correct);\n\n choices.forEach(shape => {\n const selected = answers && answers.filter(answer => answer.id === shape.id)[0];\n const correctlySelected = shape.correct && selected;\n\n if(selected) {\n selectedChoices +=1;\n }\n\n if (correctlySelected) {\n correctAnswers += 1;\n }\n });\n\n const extraAnswers = selectedChoices > correctChoices.length ? selectedChoices - correctChoices.length : 0;\n\n const total = correctChoices.length === 0 ? 1 : correctChoices.length;\n const str = ((correctAnswers - extraAnswers) / total).toFixed(2);\n\n return str < 0 ? 0 : parseFloat(str);\n};\n\nexport function outcome(config, session, env = {}) {\n return new Promise(resolve => {\n log('outcome...');\n\n if (!session || isEmpty(session)) {\n resolve({ score: 0, empty: true });\n }\n\n if (session.answers) {\n const score = getScore(config, session, env);\n resolve({ score });\n } else {\n resolve({score: 0, empty: true})\n }\n });\n}\n\nconst returnShapesCorrect = (shapes) => {\n let answers = [];\n\n shapes.forEach(i => {\n const { correct, id } = i;\n if (correct) {\n answers.push({ id });\n }\n });\n return answers;\n};\n\nexport const createCorrectResponseSession = (question, env) => {\n return new Promise(resolve => {\n if (env.mode !== 'evaluate' && env.role === 'instructor') {\n const { shapes: { rectangles = [], polygons = {} } = {} } = question;\n\n const rectangleCorrect = returnShapesCorrect(rectangles);\n const polygonsCorrect = returnShapesCorrect(polygons);\n\n resolve({\n answers: [\n ...rectangleCorrect,\n ...polygonsCorrect\n ],\n id: '1'\n });\n } else {\n resolve(null);\n }\n });\n};\n"],"file":"index.js"}
|
|
1
|
+
{"version":3,"sources":["../src/index.js"],"names":["log","normalize","question","promptEnabled","rationaleEnabled","teacherInstructionsEnabled","studentInstructionsEnabled","strokeWidth","model","session","env","normalizedQuestion","imageUrl","dimensions","hotspotColor","multipleCorrect","outlineColor","partialScoring","prompt","shapes","rectangles","polygons","Promise","resolve","out","disabled","mode","map","index","rectProps","polyProps","responseCorrect","undefined","role","rationale","teacherInstructions","createDefaultModel","defaults","getScore","config","answers","partialScoringEnabled","enabled","correctAnswers","selectedChoices","choices","correctChoices","filter","choice","correct","forEach","shape","selected","answer","id","correctlySelected","extraAnswers","length","total","str","toFixed","parseFloat","outcome","score","empty","returnShapesCorrect","i","push","createCorrectResponseSession","rectangleCorrect","polygonsCorrect","validate","minShapes","maxShapes","maxSelections","errors","allShapes","Object","values","reduce","acc","nbOfSelections","nbOfShapes","shapesError","selectionsError"],"mappings":"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","sourcesContent":["import debug from 'debug';\nimport isEmpty from 'lodash/isEmpty';\nimport { partialScoring } from '@pie-lib/controller-utils';\n\nimport { isResponseCorrect } from './utils';\n\nimport defaults from './defaults';\n\nconst log = debug('pie-elements:hotspot:controller');\n\nexport const normalize = (question) => ({\n promptEnabled: true,\n rationaleEnabled: true,\n teacherInstructionsEnabled: true,\n studentInstructionsEnabled: true,\n strokeWidth: 5,\n ...question,\n});\n\nexport function model(question, session, env) {\n const normalizedQuestion = normalize(question);\n const { imageUrl, dimensions, hotspotColor, multipleCorrect, outlineColor, partialScoring, prompt, shapes } =\n normalizedQuestion;\n const { rectangles, polygons } = shapes || {};\n\n return new Promise((resolve) => {\n const out = {\n disabled: env.mode !== 'gather',\n mode: env.mode,\n dimensions,\n imageUrl,\n outlineColor,\n hotspotColor,\n multipleCorrect,\n partialScoring,\n shapes: {\n ...shapes,\n // eslint-disable-next-line no-unused-vars\n rectangles: (rectangles || []).map(({ index, ...rectProps }) => ({ ...rectProps })),\n // eslint-disable-next-line no-unused-vars\n polygons: (polygons || []).map(({ index, ...polyProps }) => ({ ...polyProps })),\n },\n responseCorrect: env.mode === 'evaluate' ? isResponseCorrect(normalizedQuestion, session) : undefined,\n };\n\n if (env.role === 'instructor' && (env.mode === 'view' || env.mode === 'evaluate')) {\n out.rationale = normalizedQuestion.rationaleEnabled ? normalizedQuestion.rationale : null;\n out.teacherInstructions = normalizedQuestion.teacherInstructionsEnabled\n ? normalizedQuestion.teacherInstructions\n : null;\n } else {\n out.rationale = null;\n out.teacherInstructions = null;\n }\n\n out.prompt = normalizedQuestion.promptEnabled ? prompt : null;\n out.strokeWidth = normalizedQuestion.strokeWidth;\n\n // console.log(out);\n resolve(out);\n });\n}\n\nexport const createDefaultModel = (model = {}) =>\n new Promise((resolve) => {\n resolve({\n ...defaults,\n ...model,\n });\n });\n\nconst getScore = (config, session, env = {}) => {\n const { answers } = session || {};\n\n if (!config.shapes || (!config.shapes.rectangles && !config.shapes.polygons)) {\n return 0;\n }\n\n const { shapes: { rectangles = [], polygons = [] } = {} } = config;\n const partialScoringEnabled = partialScoring.enabled(config, env);\n\n if (!partialScoringEnabled) {\n return isResponseCorrect(config, session) ? 1 : 0;\n }\n\n let correctAnswers = 0;\n let selectedChoices = 0;\n\n const choices = [...rectangles, ...polygons];\n\n const correctChoices = choices.filter((choice) => choice.correct);\n\n choices.forEach((shape) => {\n const selected = answers && answers.filter((answer) => answer.id === shape.id)[0];\n const correctlySelected = shape.correct && selected;\n\n if (selected) {\n selectedChoices += 1;\n }\n\n if (correctlySelected) {\n correctAnswers += 1;\n }\n });\n\n const extraAnswers = selectedChoices > correctChoices.length ? selectedChoices - correctChoices.length : 0;\n\n const total = correctChoices.length === 0 ? 1 : correctChoices.length;\n const str = ((correctAnswers - extraAnswers) / total).toFixed(2);\n\n return str < 0 ? 0 : parseFloat(str);\n};\n\nexport function outcome(config, session, env = {}) {\n return new Promise((resolve) => {\n log('outcome...');\n\n if (!session || isEmpty(session)) {\n resolve({ score: 0, empty: true });\n }\n\n if (session.answers) {\n const score = getScore(config, session, env);\n resolve({ score });\n } else {\n resolve({ score: 0, empty: true });\n }\n });\n}\n\nconst returnShapesCorrect = (shapes) => {\n let answers = [];\n\n shapes.forEach((i) => {\n const { correct, id } = i;\n if (correct) {\n answers.push({ id });\n }\n });\n return answers;\n};\n\nexport const createCorrectResponseSession = (question, env) => {\n return new Promise((resolve) => {\n if (env.mode !== 'evaluate' && env.role === 'instructor') {\n const { shapes: { rectangles = [], polygons = {} } = {} } = question;\n\n const rectangleCorrect = returnShapesCorrect(rectangles);\n const polygonsCorrect = returnShapesCorrect(polygons);\n\n resolve({\n answers: [...rectangleCorrect, ...polygonsCorrect],\n id: '1',\n });\n } else {\n resolve(null);\n }\n });\n};\n\nexport const validate = (model = {}, config = {}) => {\n const { shapes } = model;\n const { minShapes = 2, maxShapes, maxSelections } = config;\n const errors = {};\n\n const allShapes = Object.values(shapes || {}).reduce((acc, shape) => [...acc, ...shape], []);\n\n const nbOfSelections = (allShapes || []).reduce((acc, shape) => (shape.correct ? acc + 1 : acc), 0);\n\n const nbOfShapes = (allShapes || []).length;\n\n if (nbOfShapes < minShapes) {\n errors.shapesError = `There should be at least ${minShapes} shapes defined.`;\n } else if (nbOfShapes > maxShapes) {\n errors.shapesError = `No more than ${maxShapes} shapes should be defined.`;\n }\n\n if (nbOfSelections < 1) {\n errors.selectionsError = 'There should be at least 1 shape selected.';\n } else if (nbOfSelections > maxSelections) {\n errors.selectionsError = `No more than ${maxSelections} shapes should be selected.`;\n }\n\n return errors;\n};\n"],"file":"index.js"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/utils.js"],"names":["getCorrectResponse","choices","filter","c","correct","map","id","sort","isResponseCorrect","question","session","shapes","rectangles","polygons","correctResponseIds","answers","length","answerIds","a"],"mappings":";;;;;;;;;;;AAAA;;AACA;;AAEO,IAAMA,kBAAkB,GAAG,SAArBA,kBAAqB,CAACC,OAAD;AAAA,
|
|
1
|
+
{"version":3,"sources":["../src/utils.js"],"names":["getCorrectResponse","choices","filter","c","correct","map","id","sort","isResponseCorrect","question","session","shapes","rectangles","polygons","correctResponseIds","answers","length","answerIds","a"],"mappings":";;;;;;;;;;;AAAA;;AACA;;AAEO,IAAMA,kBAAkB,GAAG,SAArBA,kBAAqB,CAACC,OAAD;AAAA,SAChCA,OAAO,CACJC,MADH,CACU,UAACC,CAAD;AAAA,WAAOA,CAAC,CAACC,OAAT;AAAA,GADV,EAEGC,GAFH,CAEO,UAACF,CAAD;AAAA,WAAOA,CAAC,CAACG,EAAT;AAAA,GAFP,EAGGC,IAHH,EADgC;AAAA,CAA3B;;;;AAMA,IAAMC,iBAAiB,GAAG,SAApBA,iBAAoB,CAACC,QAAD,EAAWC,OAAX,EAAuB;AACtD,yBAEID,QAFJ,CACEE,MADF;AAAA,MACYC,UADZ,oBACYA,UADZ;AAAA,MACwBC,QADxB,oBACwBA,QADxB;AAGA,MAAMZ,OAAO,iDAAOW,UAAP,uCAAsBC,QAAtB,EAAb;AACA,MAAIC,kBAAkB,GAAGd,kBAAkB,CAACC,OAAD,CAA3C;;AAEA,MAAI,CAACS,OAAD,IAAY,yBAAQA,OAAR,CAAhB,EAAkC;AAChC,WAAO,KAAP;AACD;;AAED,MAAIA,OAAO,CAACK,OAAR,IAAmBL,OAAO,CAACK,OAAR,CAAgBC,MAAvC,EAA+C;AAC7C,QAAIC,SAAS,GAAG,CAACP,OAAO,CAACK,OAAR,IAAmB,EAApB,EAAwBV,GAAxB,CAA4B,UAACa,CAAD;AAAA,aAAOA,CAAC,CAACZ,EAAT;AAAA,KAA5B,CAAhB;AAEA,WAAO,yBAAQW,SAAS,CAACV,IAAV,EAAR,EAA0BO,kBAA1B,CAAP;AACD,GAJD,MAIO,IAAI,EAAEA,kBAAkB,IAAIA,kBAAkB,CAACE,MAA3C,CAAJ,EAAwD;AAC7D,WAAO,IAAP;AACD;;AAED,SAAO,KAAP;AACD,CApBM","sourcesContent":["import isEqual from 'lodash/isEqual';\nimport isEmpty from 'lodash/isEmpty';\n\nexport const getCorrectResponse = (choices) =>\n choices\n .filter((c) => c.correct)\n .map((c) => c.id)\n .sort();\n\nexport const isResponseCorrect = (question, session) => {\n const {\n shapes: { rectangles, polygons },\n } = question;\n const choices = [...rectangles, ...polygons];\n let correctResponseIds = getCorrectResponse(choices);\n\n if (!session || isEmpty(session)) {\n return false;\n }\n\n if (session.answers && session.answers.length) {\n let answerIds = (session.answers || []).map((a) => a.id);\n\n return isEqual(answerIds.sort(), correctResponseIds);\n } else if (!(correctResponseIds && correctResponseIds.length)) {\n return true;\n }\n\n return false;\n};\n"],"file":"utils.js"}
|
package/controller/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pie-element/hotspot-controller",
|
|
3
3
|
"private": true,
|
|
4
|
-
"version": "3.
|
|
4
|
+
"version": "3.5.1",
|
|
5
5
|
"description": "",
|
|
6
6
|
"scripts": {
|
|
7
7
|
"test": "echo \"Error: no test specified\" && exit 1"
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
"main": "lib/index.js",
|
|
12
12
|
"module": "src/index.js",
|
|
13
13
|
"dependencies": {
|
|
14
|
-
"@pie-lib/controller-utils": "^0.2.
|
|
14
|
+
"@pie-lib/controller-utils": "^0.2.42",
|
|
15
15
|
"debug": "^4.1.1",
|
|
16
16
|
"lodash": "^4.17.15"
|
|
17
17
|
}
|
|
@@ -41,20 +41,17 @@ describe('controller', () => {
|
|
|
41
41
|
});
|
|
42
42
|
|
|
43
43
|
describe('outcome partialScoring test', () => {
|
|
44
|
-
|
|
45
|
-
describe('hanging controller', ()=> {
|
|
46
|
-
|
|
44
|
+
describe('hanging controller', () => {
|
|
47
45
|
it('doesnt hang if answers is missing', async () => {
|
|
48
|
-
const response = await outcome({}, {id:
|
|
49
|
-
expect(response).toEqual({score: 0, empty: true});
|
|
46
|
+
const response = await outcome({}, { id: '1' }, {});
|
|
47
|
+
expect(response).toEqual({ score: 0, empty: true });
|
|
50
48
|
});
|
|
51
49
|
|
|
52
50
|
it('doesnt hang if the rest is missing', async () => {
|
|
53
|
-
const response = await outcome({}, {id:
|
|
54
|
-
expect(response).toEqual({score: 0 });
|
|
51
|
+
const response = await outcome({}, { id: '1', answers: {} }, {});
|
|
52
|
+
expect(response).toEqual({ score: 0 });
|
|
55
53
|
});
|
|
56
|
-
|
|
57
|
-
})
|
|
54
|
+
});
|
|
58
55
|
|
|
59
56
|
beforeEach(() => {
|
|
60
57
|
const rectangles = question.shapes.rectangles.concat({
|
|
@@ -72,11 +69,7 @@ describe('controller', () => {
|
|
|
72
69
|
|
|
73
70
|
const assertOutcome = (message, extra, sessionValue, env, expected) => {
|
|
74
71
|
it(message, async () => {
|
|
75
|
-
const result = await outcome(
|
|
76
|
-
{ ...question, ...extra },
|
|
77
|
-
sessionValue,
|
|
78
|
-
env
|
|
79
|
-
);
|
|
72
|
+
const result = await outcome({ ...question, ...extra }, sessionValue, env);
|
|
80
73
|
expect(result).toEqual(expect.objectContaining(expected));
|
|
81
74
|
});
|
|
82
75
|
};
|
|
@@ -86,7 +79,7 @@ describe('controller', () => {
|
|
|
86
79
|
{ partialScoring: true },
|
|
87
80
|
{ answers: [{ id: '2' }] },
|
|
88
81
|
{ mode: 'evaluate' },
|
|
89
|
-
{ score: 0 }
|
|
82
|
+
{ score: 0 },
|
|
90
83
|
);
|
|
91
84
|
|
|
92
85
|
assertOutcome(
|
|
@@ -94,7 +87,7 @@ describe('controller', () => {
|
|
|
94
87
|
{ partialScoring: false },
|
|
95
88
|
{ answers: [{ id: '2' }] },
|
|
96
89
|
{ mode: 'evaluate' },
|
|
97
|
-
{ score: 0 }
|
|
90
|
+
{ score: 0 },
|
|
98
91
|
);
|
|
99
92
|
|
|
100
93
|
assertOutcome(
|
|
@@ -102,7 +95,7 @@ describe('controller', () => {
|
|
|
102
95
|
{ partialScoring: false },
|
|
103
96
|
{ answers: [{ id: '2' }] },
|
|
104
97
|
{ mode: 'evaluate', partialScoring: true },
|
|
105
|
-
{ score: 0 }
|
|
98
|
+
{ score: 0 },
|
|
106
99
|
);
|
|
107
100
|
|
|
108
101
|
assertOutcome(
|
|
@@ -110,7 +103,7 @@ describe('controller', () => {
|
|
|
110
103
|
{ partialScoring: true },
|
|
111
104
|
{ answers: [{ id: '2' }] },
|
|
112
105
|
{ mode: 'evaluate', partialScoring: false },
|
|
113
|
-
{ score: 0 }
|
|
106
|
+
{ score: 0 },
|
|
114
107
|
);
|
|
115
108
|
});
|
|
116
109
|
|
|
@@ -136,13 +129,16 @@ describe('controller', () => {
|
|
|
136
129
|
|
|
137
130
|
describe('partial scoring', () => {
|
|
138
131
|
beforeEach(() => {
|
|
139
|
-
const rectangles = question.shapes.rectangles.concat(
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
132
|
+
const rectangles = question.shapes.rectangles.concat(
|
|
133
|
+
{
|
|
134
|
+
id: '5',
|
|
135
|
+
correct: true,
|
|
136
|
+
},
|
|
137
|
+
{
|
|
138
|
+
id: '6',
|
|
139
|
+
correct: true,
|
|
140
|
+
},
|
|
141
|
+
);
|
|
146
142
|
question = {
|
|
147
143
|
...question,
|
|
148
144
|
partialScoring: true,
|
|
@@ -172,13 +168,12 @@ describe('controller', () => {
|
|
|
172
168
|
});
|
|
173
169
|
|
|
174
170
|
it('returns a score of 0.5 for 2/4 correct answers and 0 incorrect answers', async () => {
|
|
175
|
-
const result = await outcome(question, { answers: [{ id: '5' }, { id: '4'}] });
|
|
171
|
+
const result = await outcome(question, { answers: [{ id: '5' }, { id: '4' }] });
|
|
176
172
|
expect(result.score).toEqual(0.5);
|
|
177
173
|
});
|
|
178
174
|
|
|
179
|
-
|
|
180
175
|
it('returns a score of 0.75 for 3/4 correct answers and 0 incorrect answers', async () => {
|
|
181
|
-
const result = await outcome(question, { answers: [{ id: '1' }, { id: '5' }, { id: '4'}] });
|
|
176
|
+
const result = await outcome(question, { answers: [{ id: '1' }, { id: '5' }, { id: '4' }] });
|
|
182
177
|
expect(result.score).toEqual(0.75);
|
|
183
178
|
});
|
|
184
179
|
|
|
@@ -247,9 +242,7 @@ describe('controller', () => {
|
|
|
247
242
|
});
|
|
248
243
|
|
|
249
244
|
const returnOutcome = (session) => {
|
|
250
|
-
it(`returns empty: true when session is ${JSON.stringify(
|
|
251
|
-
session
|
|
252
|
-
)}`, async () => {
|
|
245
|
+
it(`returns empty: true when session is ${JSON.stringify(session)}`, async () => {
|
|
253
246
|
const result = await outcome(question, session);
|
|
254
247
|
expect(result).toEqual({ score: 0, empty: true });
|
|
255
248
|
});
|
|
@@ -298,15 +291,9 @@ describe('controller', () => {
|
|
|
298
291
|
|
|
299
292
|
it('returns shapes', () => {
|
|
300
293
|
expect(result.shapes.rectangles).toEqual(
|
|
301
|
-
expect.arrayContaining([
|
|
302
|
-
{ id: '1', correct: true },
|
|
303
|
-
{ id: '2' },
|
|
304
|
-
{ id: '3' },
|
|
305
|
-
])
|
|
306
|
-
);
|
|
307
|
-
expect(result.shapes.polygons).toEqual(
|
|
308
|
-
expect.arrayContaining([{ id: '4', correct: true }])
|
|
294
|
+
expect.arrayContaining([{ id: '1', correct: true }, { id: '2' }, { id: '3' }]),
|
|
309
295
|
);
|
|
296
|
+
expect(result.shapes.polygons).toEqual(expect.arrayContaining([{ id: '4', correct: true }]));
|
|
310
297
|
});
|
|
311
298
|
|
|
312
299
|
it('does not return responseCorrect', () => {
|
|
@@ -336,15 +323,9 @@ describe('controller', () => {
|
|
|
336
323
|
|
|
337
324
|
it('returns choices w/ correct', () => {
|
|
338
325
|
expect(result.shapes.rectangles).toEqual(
|
|
339
|
-
expect.arrayContaining([
|
|
340
|
-
{ id: '1', correct: true },
|
|
341
|
-
{ id: '2' },
|
|
342
|
-
{ id: '3' },
|
|
343
|
-
])
|
|
344
|
-
);
|
|
345
|
-
expect(result.shapes.polygons).toEqual(
|
|
346
|
-
expect.arrayContaining([{ id: '4', correct: true }])
|
|
326
|
+
expect.arrayContaining([{ id: '1', correct: true }, { id: '2' }, { id: '3' }]),
|
|
347
327
|
);
|
|
328
|
+
expect(result.shapes.polygons).toEqual(expect.arrayContaining([{ id: '4', correct: true }]));
|
|
348
329
|
});
|
|
349
330
|
|
|
350
331
|
it('returns is response correct', () => {
|
|
@@ -355,9 +336,7 @@ describe('controller', () => {
|
|
|
355
336
|
|
|
356
337
|
describe('isResponseCorrect', () => {
|
|
357
338
|
const returnIsResponseCorect = (session) => {
|
|
358
|
-
it(`response is not correct if session is ${JSON.stringify(
|
|
359
|
-
session
|
|
360
|
-
)}`, () => {
|
|
339
|
+
it(`response is not correct if session is ${JSON.stringify(session)}`, () => {
|
|
361
340
|
expect(isResponseCorrect(question, session)).toEqual(false);
|
|
362
341
|
});
|
|
363
342
|
};
|
|
@@ -3,20 +3,16 @@ export default {
|
|
|
3
3
|
imageUrl: '',
|
|
4
4
|
shapes: {
|
|
5
5
|
rectangles: [],
|
|
6
|
-
polygons: []
|
|
6
|
+
polygons: [],
|
|
7
7
|
},
|
|
8
8
|
multipleCorrect: true,
|
|
9
9
|
partialScoring: false,
|
|
10
10
|
dimensions: {
|
|
11
11
|
height: 0,
|
|
12
|
-
width: 0
|
|
12
|
+
width: 0,
|
|
13
13
|
},
|
|
14
|
-
hotspotColor: 'rgba(137, 183, 244, 0.
|
|
15
|
-
hotspotList: [
|
|
16
|
-
'rgba(137, 183, 244, 0.65)'
|
|
17
|
-
],
|
|
14
|
+
hotspotColor: 'rgba(137, 183, 244, 0.25)',
|
|
15
|
+
hotspotList: ['rgba(137, 183, 244, 0.25)'],
|
|
18
16
|
outlineColor: 'blue',
|
|
19
|
-
outlineList: [
|
|
20
|
-
'blue'
|
|
21
|
-
]
|
|
17
|
+
outlineList: ['blue'],
|
|
22
18
|
};
|