@pie-element/hotspot 4.10.10 → 4.10.11-beta.1445

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.
Files changed (91) hide show
  1. package/CHANGELOG.md +349 -0
  2. package/configure/CHANGELOG.md +311 -0
  3. package/configure/lib/button.js.map +1 -1
  4. package/configure/lib/defaults.js +23 -2
  5. package/configure/lib/defaults.js.map +1 -1
  6. package/configure/lib/hotspot-container.js +28 -19
  7. package/configure/lib/hotspot-container.js.map +1 -1
  8. package/configure/lib/hotspot-drawable.js +3 -3
  9. package/configure/lib/hotspot-drawable.js.map +1 -1
  10. package/configure/lib/hotspot-palette.js.map +1 -1
  11. package/configure/lib/hotspot-polygon.js.map +1 -1
  12. package/configure/lib/hotspot-rectangle.js.map +1 -1
  13. package/configure/lib/index.js +16 -2
  14. package/configure/lib/index.js.map +1 -1
  15. package/configure/lib/root.js +129 -38
  16. package/configure/lib/root.js.map +1 -1
  17. package/configure/lib/upload-control.js.map +1 -1
  18. package/configure/lib/utils.js +15 -3
  19. package/configure/lib/utils.js.map +1 -1
  20. package/configure/package.json +4 -4
  21. package/configure/src/__tests__/__snapshots__/hotspot-container.test.js.snap +1 -1
  22. package/configure/src/__tests__/__snapshots__/root.test.js.snap +56 -4
  23. package/configure/src/__tests__/hotspot-container.test.js +98 -71
  24. package/configure/src/__tests__/hotspot-drawable.test.js +48 -49
  25. package/configure/src/__tests__/index.test.js +28 -51
  26. package/configure/src/__tests__/root.test.js +162 -82
  27. package/configure/src/__tests__/utils.test.js +112 -98
  28. package/configure/src/button.jsx +4 -4
  29. package/configure/src/defaults.js +35 -18
  30. package/configure/src/hotspot-container.jsx +99 -98
  31. package/configure/src/hotspot-drawable.jsx +56 -56
  32. package/configure/src/hotspot-palette.jsx +12 -25
  33. package/configure/src/hotspot-polygon.jsx +20 -22
  34. package/configure/src/hotspot-rectangle.jsx +5 -15
  35. package/configure/src/index.js +32 -18
  36. package/configure/src/root.jsx +116 -60
  37. package/configure/src/upload-control.jsx +9 -20
  38. package/configure/src/utils.js +51 -22
  39. package/controller/CHANGELOG.md +23 -0
  40. package/controller/lib/defaults.js +2 -2
  41. package/controller/lib/defaults.js.map +1 -1
  42. package/controller/lib/index.js +39 -3
  43. package/controller/lib/index.js.map +1 -1
  44. package/controller/lib/utils.js.map +1 -1
  45. package/controller/package.json +2 -2
  46. package/controller/src/__tests__/index.test.js +29 -50
  47. package/controller/src/defaults.js +5 -9
  48. package/controller/src/index.js +47 -33
  49. package/controller/src/utils.js +9 -6
  50. package/docs/config-schema.json +217 -0
  51. package/docs/config-schema.json.md +169 -0
  52. package/docs/demo/config.js +2 -2
  53. package/docs/demo/generate.js +53 -35
  54. package/docs/demo/session.js +2 -2
  55. package/docs/pie-schema.json +49 -0
  56. package/docs/pie-schema.json.md +36 -0
  57. package/lib/hotspot/container.js +24 -6
  58. package/lib/hotspot/container.js.map +1 -1
  59. package/lib/hotspot/icons.js.map +1 -1
  60. package/lib/hotspot/image.js.map +1 -1
  61. package/lib/hotspot/index.js +65 -5
  62. package/lib/hotspot/index.js.map +1 -1
  63. package/lib/hotspot/polygon.js +45 -19
  64. package/lib/hotspot/polygon.js.map +1 -1
  65. package/lib/hotspot/rectangle.js +45 -19
  66. package/lib/hotspot/rectangle.js.map +1 -1
  67. package/lib/index.js +3 -0
  68. package/lib/index.js.map +1 -1
  69. package/lib/session-updater.js.map +1 -1
  70. package/package.json +7 -4
  71. package/src/__tests__/__snapshots__/{container-test.jsx.snap → container.test.jsx.snap} +8 -0
  72. package/src/__tests__/__snapshots__/image.test.jsx.snap +43 -0
  73. package/src/__tests__/__snapshots__/{polygon-test.jsx.snap → polygon.test.jsx.snap} +11 -0
  74. package/src/__tests__/__snapshots__/{rectangle-test.jsx.snap → rectangle.test.jsx.snap} +11 -0
  75. package/src/__tests__/container.test.jsx +214 -0
  76. package/src/__tests__/{image-test.jsx → image.test.jsx} +2 -2
  77. package/src/__tests__/polygon.test.jsx +235 -0
  78. package/src/__tests__/rectangle.test.jsx +237 -0
  79. package/src/__tests__/{session-updater-test.jsx → session-updater.test.jsx} +22 -31
  80. package/src/hotspot/container.jsx +40 -23
  81. package/src/hotspot/icons.js +4 -2
  82. package/src/hotspot/image.jsx +4 -8
  83. package/src/hotspot/index.jsx +73 -33
  84. package/src/hotspot/polygon.jsx +48 -30
  85. package/src/hotspot/rectangle.jsx +48 -30
  86. package/src/index.js +10 -18
  87. package/src/session-updater.js +1 -1
  88. package/src/__tests__/__snapshots__/image-test.jsx.snap +0 -21
  89. package/src/__tests__/container-test.jsx +0 -143
  90. package/src/__tests__/polygon-test.jsx +0 -77
  91. 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 => { setRef(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);
@@ -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) => (referenceNextValue / referenceInitialValue) * 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((acc, currentShapeKey) =>
79
- acc.concat(
80
- shapesMap[currentShapeKey]
81
- ? shapesMap[currentShapeKey].map((shape, index) => ({
82
- ...shape,
83
- group: currentShapeKey,
84
- index: shape.index || acc.length + index
85
- }))
86
- : []),
87
- shapesArray)
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
- export { updateImageDimensions, getUpdatedShapes, getAllShapes, groupShapes, getUpdatedRectangle, getUpdatedPlygon };
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
+ };
@@ -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.65)',
21
- hotspotList: ['rgba(137, 183, 244, 0.65)'],
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,CACX,2BADW,CAdA;AAiBbC,EAAAA,YAAY,EAAE,MAjBD;AAkBbC,EAAAA,WAAW,EAAE,CACX,MADW;AAlBA,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.65)',\n hotspotList: [\n 'rgba(137, 183, 244, 0.65)'\n ],\n outlineColor: 'blue',\n outlineList: [\n 'blue'\n ]\n};\n"],"file":"defaults.js"}
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"}
@@ -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.createCorrectResponseSession = exports.createDefaultModel = exports.normalize = void 0;
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); if (enumerableOnly) { symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); } keys.push.apply(keys, symbols); } return keys; }
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] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { (0, _defineProperty2["default"])(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
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,SAAaA,OAAO,CACnDC,MAD4C,CACrC,UAAAC,CAAC;AAAA,WAAIA,CAAC,CAACC,OAAN;AAAA,GADoC,EAE5CC,GAF4C,CAExC,UAAAF,CAAC;AAAA,WAAIA,CAAC,CAACG,EAAN;AAAA,GAFuC,EAG5CC,IAH4C,EAAb;AAAA,CAA3B;;;;AAKA,IAAMC,iBAAiB,GAAG,SAApBA,iBAAoB,CAACC,QAAD,EAAWC,OAAX,EAAuB;AACtD,yBAA6CD,QAA7C,CAAQE,MAAR;AAAA,MAAkBC,UAAlB,oBAAkBA,UAAlB;AAAA,MAA8BC,QAA9B,oBAA8BA,QAA9B;AACA,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,UAAAa,CAAC;AAAA,aAAIA,CAAC,CAACZ,EAAN;AAAA,KAA7B,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,CAlBM","sourcesContent":["import isEqual from 'lodash/isEqual';\nimport isEmpty from 'lodash/isEmpty';\n\nexport const getCorrectResponse = (choices) => choices\n .filter(c => c.correct)\n .map(c => c.id)\n .sort();\n\nexport const isResponseCorrect = (question, session) => {\n const { shapes: { rectangles, polygons } } = 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"}
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"}
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@pie-element/hotspot-controller",
3
3
  "private": true,
4
- "version": "3.4.8",
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.26",
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: "1"}, {});
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: "1", answers: {}}, {});
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
- id: '5',
141
- correct: true,
142
- }, {
143
- id: '6',
144
- correct: true,
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.65)',
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
  };