@pie-element/ebsr 7.0.13 → 7.0.15-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.
Files changed (39) hide show
  1. package/CHANGELOG.md +328 -0
  2. package/configure/CHANGELOG.md +312 -0
  3. package/configure/lib/defaults.js +23 -4
  4. package/configure/lib/defaults.js.map +1 -1
  5. package/configure/lib/index.js +5 -5
  6. package/configure/lib/index.js.map +1 -1
  7. package/configure/lib/main.js +62 -50
  8. package/configure/lib/main.js.map +1 -1
  9. package/configure/package.json +3 -3
  10. package/configure/src/__tests__/__snapshots__/index.test.js.snap +4 -2
  11. package/configure/src/__tests__/index.test.js +164 -211
  12. package/configure/src/defaults.js +38 -19
  13. package/configure/src/index.js +8 -7
  14. package/configure/src/main.jsx +134 -147
  15. package/controller/CHANGELOG.md +20 -0
  16. package/controller/lib/defaults.js.map +1 -1
  17. package/controller/lib/index.js +91 -12
  18. package/controller/lib/index.js.map +1 -1
  19. package/controller/lib/utils.js.map +1 -1
  20. package/controller/package.json +2 -2
  21. package/controller/src/__tests__/index.test.js +113 -141
  22. package/controller/src/__tests__/utils.test.js +6 -9
  23. package/controller/src/defaults.js +1 -1
  24. package/controller/src/index.js +104 -69
  25. package/controller/src/utils.js +6 -4
  26. package/docs/config-schema.json +280 -0
  27. package/docs/config-schema.json.md +217 -1
  28. package/docs/demo/config.js +2 -2
  29. package/docs/demo/generate.js +3 -3
  30. package/docs/pie-schema.json +127 -0
  31. package/docs/pie-schema.json.md +96 -0
  32. package/lib/index.js +11 -8
  33. package/lib/index.js.map +1 -1
  34. package/lib/print.js +243 -0
  35. package/lib/print.js.map +1 -0
  36. package/package.json +8 -4
  37. package/src/__tests__/index.test.js +2 -7
  38. package/src/index.js +7 -5
  39. package/src/print.js +179 -0
@@ -1,19 +1,16 @@
1
1
  import defaults from './defaults';
2
- import { lockChoices, getShuffledChoices } from '@pie-lib/controller-utils';
2
+ import { lockChoices, getShuffledChoices, partialScoring } from '@pie-lib/controller-utils';
3
3
  import { isResponseCorrect } from './utils';
4
4
  import get from 'lodash/get';
5
5
  import isEmpty from 'lodash/isEmpty';
6
6
 
7
- const prepareChoice = (model, env, defaultFeedback) => choice => {
7
+ const prepareChoice = (model, env, defaultFeedback) => (choice) => {
8
8
  const out = {
9
9
  label: choice.label,
10
- value: choice.value
10
+ value: choice.value,
11
11
  };
12
12
 
13
- if (
14
- env.role === 'instructor' &&
15
- (env.mode === 'view' || env.mode === 'evaluate')
16
- ) {
13
+ if (env.role === 'instructor' && (env.mode === 'view' || env.mode === 'evaluate')) {
17
14
  out.rationale = model.rationaleEnabled ? choice.rationale : null;
18
15
  } else {
19
16
  out.rationale = null;
@@ -37,26 +34,18 @@ const prepareChoice = (model, env, defaultFeedback) => choice => {
37
34
  };
38
35
 
39
36
  const parsePart = (part, key, session, env) => {
40
- const defaultFeedback = Object.assign(
41
- { correct: 'Correct', incorrect: 'Incorrect' },
42
- part.defaultFeedback
43
- );
37
+ const defaultFeedback = Object.assign({ correct: 'Correct', incorrect: 'Incorrect' }, part.defaultFeedback);
44
38
 
45
- let choices = part.choices
46
- ? part.choices.map(prepareChoice(part, env, defaultFeedback))
47
- : [];
39
+ let choices = part.choices ? part.choices.map(prepareChoice(part, env, defaultFeedback)) : [];
48
40
 
49
41
  return {
50
42
  ...part,
51
43
  choices,
52
44
  disabled: env.mode !== 'gather',
53
45
  complete: {
54
- min: part.choices.filter(c => c.correct).length
46
+ min: part.choices.filter((c) => c.correct).length,
55
47
  },
56
- responseCorrect:
57
- env.mode === 'evaluate'
58
- ? isResponseCorrect(part, key, session)
59
- : undefined
48
+ responseCorrect: env.mode === 'evaluate' ? isResponseCorrect(part, key, session) : undefined,
60
49
  };
61
50
  };
62
51
 
@@ -73,7 +62,7 @@ export const normalize = ({ partA = {}, partB = {}, ...question }) => ({
73
62
  studentInstructionsEnabled: true,
74
63
  gridColumns: '2',
75
64
  ...partA,
76
- choicesLayout: partA.choicesLayout || (partA.verticalMode === false && 'horizontal') || 'vertical'
65
+ choicesLayout: partA.choicesLayout || (partA.verticalMode === false && 'horizontal') || 'vertical',
77
66
  },
78
67
  partB: {
79
68
  ...defaults.partB,
@@ -84,8 +73,8 @@ export const normalize = ({ partA = {}, partB = {}, ...question }) => ({
84
73
  studentInstructionsEnabled: true,
85
74
  gridColumns: '2',
86
75
  ...partB,
87
- choicesLayout: partB.choicesLayout || (partB.verticalMode === false && 'horizontal') || 'vertical'
88
- }
76
+ choicesLayout: partB.choicesLayout || (partB.verticalMode === false && 'horizontal') || 'vertical',
77
+ },
89
78
  });
90
79
 
91
80
  /**
@@ -102,8 +91,8 @@ export async function model(question, session, env, updateSession) {
102
91
 
103
92
  const shuffledValues = {};
104
93
 
105
- const us = part => (id, element, update) =>
106
- new Promise(resolve => {
94
+ const us = (part) => (id, element, update) =>
95
+ new Promise((resolve) => {
107
96
  shuffledValues[part] = update.shuffledValues;
108
97
  resolve();
109
98
  });
@@ -119,7 +108,7 @@ export async function model(question, session, env, updateSession) {
119
108
  partAChoices,
120
109
  { shuffledValues: (session.shuffledValues || {}).partA },
121
110
  us('partA'),
122
- 'value'
111
+ 'value',
123
112
  );
124
113
  }
125
114
 
@@ -131,40 +120,33 @@ export async function model(question, session, env, updateSession) {
131
120
  partBChoices,
132
121
  { shuffledValues: (session.shuffledValues || {}).partB },
133
122
  us('partB'),
134
- 'value'
123
+ 'value',
135
124
  );
136
125
  }
137
126
 
138
127
  if (!isEmpty(shuffledValues)) {
139
128
  if (updateSession && typeof updateSession === 'function') {
140
129
  updateSession(session.id, session.element, {
141
- shuffledValues
142
- }).catch(e => {
130
+ shuffledValues,
131
+ }).catch((e) => {
143
132
  console.error('update session failed', e);
144
133
  });
145
134
  }
146
135
  }
147
136
 
148
137
  if (normalizedQuestion.partLabels) {
149
- partA.partLabel =
150
- normalizedQuestion.partLabelType === 'Letters' ? 'Part A' : 'Part 1';
151
- partB.partLabel =
152
- normalizedQuestion.partLabelType === 'Letters' ? 'Part B' : 'Part 2';
138
+ partA.partLabel = normalizedQuestion.partLabelType === 'Letters' ? 'Part A' : 'Part 1';
139
+ partB.partLabel = normalizedQuestion.partLabelType === 'Letters' ? 'Part B' : 'Part 2';
153
140
  } else {
154
141
  partA.partLabel = undefined;
155
142
  partB.partLabel = undefined;
156
143
  }
157
144
 
158
- if (
159
- env.role === 'instructor' &&
160
- (env.mode === 'view' || env.mode === 'evaluate')
161
- ) {
162
- partA.teacherInstructions = normalizedQuestion.partA
163
- .teacherInstructionsEnabled
145
+ if (env.role === 'instructor' && (env.mode === 'view' || env.mode === 'evaluate')) {
146
+ partA.teacherInstructions = normalizedQuestion.partA.teacherInstructionsEnabled
164
147
  ? normalizedQuestion.partA.teacherInstructions
165
148
  : null;
166
- partB.teacherInstructions = normalizedQuestion.partB
167
- .teacherInstructionsEnabled
149
+ partB.teacherInstructions = normalizedQuestion.partB.teacherInstructionsEnabled
168
150
  ? normalizedQuestion.partB.teacherInstructions
169
151
  : null;
170
152
  } else {
@@ -172,41 +154,37 @@ export async function model(question, session, env, updateSession) {
172
154
  partB.teacherInstructions = null;
173
155
  }
174
156
 
175
- partA.prompt = normalizedQuestion.partA.promptEnabled
176
- ? normalizedQuestion.partA.prompt
177
- : null;
178
- partB.prompt = normalizedQuestion.partB.promptEnabled
179
- ? normalizedQuestion.partB.prompt
180
- : null;
157
+ partA.prompt = normalizedQuestion.partA.promptEnabled ? normalizedQuestion.partA.prompt : null;
158
+ partB.prompt = normalizedQuestion.partB.promptEnabled ? normalizedQuestion.partB.prompt : null;
181
159
 
182
- return new Promise(resolve => {
160
+ return new Promise((resolve) => {
183
161
  resolve({
184
162
  disabled: env.mode !== 'gather',
185
163
  mode: env.mode,
186
164
  partA,
187
- partB
165
+ partB,
188
166
  });
189
167
  });
190
168
  }
191
169
 
192
170
  export const createDefaultModel = (model = {}) =>
193
- new Promise(resolve => {
171
+ new Promise((resolve) => {
194
172
  resolve({
195
173
  ...defaults,
196
- ...model
174
+ ...model,
197
175
  });
198
176
  });
199
177
 
200
- const isCorrect = c => c.correct === true;
178
+ const isCorrect = (c) => c.correct === true;
201
179
 
202
- const getScore = (config, sessionPart, key) => {
180
+ const getScore = (config, sessionPart, key, partialScoringEnabled) => {
203
181
  const { choices = [] } = (config && config[key]) || {};
204
182
  const maxScore = choices.length;
205
183
  const { value: sessionPartValue } = sessionPart || {};
206
184
 
207
- const chosen = c => !!(sessionPartValue || []).find(v => v === c.value);
208
- const correctAndNotChosen = c => isCorrect(c) && !chosen(c);
209
- const incorrectAndChosen = c => !isCorrect(c) && chosen(c);
185
+ const chosen = (c) => !!(sessionPartValue || []).find((v) => v === c.value);
186
+ const correctAndNotChosen = (c) => isCorrect(c) && !chosen(c);
187
+ const incorrectAndChosen = (c) => !isCorrect(c) && chosen(c);
210
188
  const correctChoices = choices.reduce((total, choice) => {
211
189
  if (correctAndNotChosen(choice) || incorrectAndChosen(choice)) {
212
190
  return total - 1;
@@ -216,15 +194,15 @@ const getScore = (config, sessionPart, key) => {
216
194
  }, choices.length);
217
195
 
218
196
  // determine score for a part
219
- if (!config.partialScoring && correctChoices < maxScore) {
197
+ if (!partialScoringEnabled && correctChoices < maxScore) {
220
198
  return 0;
221
199
  }
222
200
 
223
201
  return parseFloat(maxScore ? (correctChoices / maxScore).toFixed(2) : 0);
224
202
  };
225
203
 
226
- export function outcome(config, session) {
227
- return new Promise(resolve => {
204
+ export function outcome(config, session, env) {
205
+ return new Promise((resolve) => {
228
206
  const { value } = session || {};
229
207
 
230
208
  if (!session || !value) {
@@ -234,13 +212,15 @@ export function outcome(config, session) {
234
212
  if (value) {
235
213
  const { partA, partB } = value || {};
236
214
 
237
- const scoreA = getScore(config, partA, 'partA');
238
- const scoreB = getScore(config, partB, 'partB');
215
+ const partialScoringEnabled = partialScoring.enabled(config, env);
239
216
 
240
- if (!config.partialScoring) {
217
+ const scoreA = getScore(config, partA, 'partA', partialScoringEnabled);
218
+ const scoreB = getScore(config, partB, 'partB', partialScoringEnabled);
219
+
220
+ if (!partialScoringEnabled) {
241
221
  // The EBSR item is worth 1 point
242
222
  // That point is awarded if and only if both parts are fully correct, otherwise no points are awarded
243
- resolve({ score: (scoreA === 1 && scoreB === 1) ? 1 : 0, scoreA, scoreB, max: 1 });
223
+ resolve({ score: scoreA === 1 && scoreB === 1 ? 1 : 0, scoreA, scoreB, max: 1 });
244
224
  } else {
245
225
  // The EBSR item is worth 2 points
246
226
  if (scoreA === 1) {
@@ -260,10 +240,10 @@ export function outcome(config, session) {
260
240
  });
261
241
  }
262
242
 
263
- const returnPartCorrect = choices => {
243
+ const returnPartCorrect = (choices) => {
264
244
  let answers = [];
265
245
 
266
- choices.forEach(i => {
246
+ choices.forEach((i) => {
267
247
  const { correct, value } = i;
268
248
  if (correct) {
269
249
  answers.push(value);
@@ -273,7 +253,7 @@ const returnPartCorrect = choices => {
273
253
  };
274
254
 
275
255
  export const createCorrectResponseSession = (question, env) => {
276
- return new Promise(resolve => {
256
+ return new Promise((resolve) => {
277
257
  if (env.mode !== 'evaluate' && env.role === 'instructor') {
278
258
  const { partA, partB } = question;
279
259
 
@@ -284,17 +264,72 @@ export const createCorrectResponseSession = (question, env) => {
284
264
  value: {
285
265
  partA: {
286
266
  id: 'partA',
287
- value: partACorrect
267
+ value: partACorrect,
288
268
  },
289
269
  partB: {
290
270
  id: 'partB',
291
- value: partBCorrect
292
- }
271
+ value: partBCorrect,
272
+ },
293
273
  },
294
- id: '1'
274
+ id: '1',
295
275
  });
296
276
  } else {
297
277
  resolve(null);
298
278
  }
299
279
  });
300
280
  };
281
+
282
+ const validatePart = (model = {}, config = {}) => {
283
+ const { choices } = model;
284
+ const { minAnswerChoices = 2, maxAnswerChoices } = config;
285
+ const reversedChoices = [...(choices || [])].reverse();
286
+ const choicesErrors = {};
287
+ let hasCorrectResponse = false;
288
+
289
+ reversedChoices.forEach((choice, index) => {
290
+ const { correct, value, label } = choice;
291
+
292
+ if (correct) {
293
+ hasCorrectResponse = true;
294
+ }
295
+
296
+ if (label === '' || label === '<div></div>') {
297
+ choicesErrors[value] = 'Content should not be empty.';
298
+ } else {
299
+ const identicalAnswer = reversedChoices.slice(index + 1).some((c) => c.label === label);
300
+
301
+ if (identicalAnswer) {
302
+ choicesErrors[value] = 'Content should be unique.';
303
+ }
304
+ }
305
+ });
306
+
307
+ const errors = {};
308
+ const nbOfChoices = (choices || []).length;
309
+
310
+ if (nbOfChoices < minAnswerChoices) {
311
+ errors.answerChoicesError = `There should be at least ${minAnswerChoices} choices defined.`;
312
+ } else if (nbOfChoices > maxAnswerChoices) {
313
+ errors.answerChoicesError = `No more than ${maxAnswerChoices} choices should be defined.`;
314
+ }
315
+
316
+ if (!hasCorrectResponse) {
317
+ errors.correctResponseError = 'No correct response defined.';
318
+ }
319
+
320
+ if (!isEmpty(choicesErrors)) {
321
+ errors.choicesErrors = choicesErrors;
322
+ }
323
+
324
+ return errors;
325
+ };
326
+
327
+ export const validate = (model = {}, config = {}) => {
328
+ const { partA, partB } = model || {};
329
+ const { partA: partAConfig, partB: partBConfig } = config || {};
330
+
331
+ const partAErrors = validatePart(partA, partAConfig);
332
+ const partBErrors = validatePart(partB, partBConfig);
333
+
334
+ return { partA: partAErrors, partB: partBErrors };
335
+ };
@@ -1,9 +1,11 @@
1
1
  import isEqual from 'lodash/isEqual';
2
2
 
3
- export const getCorrectResponse = (choices) => choices && choices
4
- .filter(c => c.correct)
5
- .map(c => c.value)
6
- .sort();
3
+ export const getCorrectResponse = (choices) =>
4
+ choices &&
5
+ choices
6
+ .filter((c) => c.correct)
7
+ .map((c) => c.value)
8
+ .sort();
7
9
 
8
10
  export const isResponseCorrect = (question, key, session) => {
9
11
  let correctResponse = getCorrectResponse(question.choices);
@@ -119,6 +119,27 @@
119
119
  }
120
120
  }
121
121
  },
122
+ "settingsPanelDisabled": {
123
+ "description": "Indicates if the settings panel is not available",
124
+ "type": "boolean",
125
+ "title": "settingsPanelDisabled"
126
+ },
127
+ "spellCheck": {
128
+ "title": "ConfigureProp",
129
+ "type": "object",
130
+ "properties": {
131
+ "settings": {
132
+ "description": "Indicates if the item has to be displayed in the Settings Panel",
133
+ "type": "boolean",
134
+ "title": "settings"
135
+ },
136
+ "label": {
137
+ "description": "Indicates the label for the item that has to be displayed in the Settings Panel",
138
+ "type": "string",
139
+ "title": "label"
140
+ }
141
+ }
142
+ },
122
143
  "rationale": {
123
144
  "title": "ConfigureProp",
124
145
  "type": "object",
@@ -198,6 +219,68 @@
198
219
  "title": "label"
199
220
  }
200
221
  }
222
+ },
223
+ "minAnswerChoices": {
224
+ "description": "Minimum number of answer choices",
225
+ "type": "number",
226
+ "title": "minAnswerChoices"
227
+ },
228
+ "maxAnswerChoices": {
229
+ "description": "Maximum number of answer choices",
230
+ "type": "number",
231
+ "title": "maxAnswerChoices"
232
+ },
233
+ "maxImageWidth": {
234
+ "title": "ConfigureMaxImageDimensionsProp",
235
+ "type": "object",
236
+ "properties": {
237
+ "teacherInstructions": {
238
+ "description": "Indicates the max dimension for images in teacher instructions",
239
+ "type": "number",
240
+ "title": "teacherInstructions"
241
+ },
242
+ "prompt": {
243
+ "description": "Indicates the max dimension for images in prompt - this is also the default dimension for all other input fields if it's not specified",
244
+ "type": "number",
245
+ "title": "prompt"
246
+ },
247
+ "rationale": {
248
+ "description": "Indicates the max dimension for images in rationale",
249
+ "type": "number",
250
+ "title": "rationale"
251
+ },
252
+ "choices": {
253
+ "description": "Indicates the max dimension for images in choices",
254
+ "type": "number",
255
+ "title": "choices"
256
+ }
257
+ }
258
+ },
259
+ "maxImageHeight": {
260
+ "title": "ConfigureMaxImageDimensionsProp",
261
+ "type": "object",
262
+ "properties": {
263
+ "teacherInstructions": {
264
+ "description": "Indicates the max dimension for images in teacher instructions",
265
+ "type": "number",
266
+ "title": "teacherInstructions"
267
+ },
268
+ "prompt": {
269
+ "description": "Indicates the max dimension for images in prompt - this is also the default dimension for all other input fields if it's not specified",
270
+ "type": "number",
271
+ "title": "prompt"
272
+ },
273
+ "rationale": {
274
+ "description": "Indicates the max dimension for images in rationale",
275
+ "type": "number",
276
+ "title": "rationale"
277
+ },
278
+ "choices": {
279
+ "description": "Indicates the max dimension for images in choices",
280
+ "type": "number",
281
+ "title": "choices"
282
+ }
283
+ }
201
284
  }
202
285
  }
203
286
  },
@@ -317,6 +400,27 @@
317
400
  }
318
401
  }
319
402
  },
403
+ "settingsPanelDisabled": {
404
+ "description": "Indicates if the settings panel is not available",
405
+ "type": "boolean",
406
+ "title": "settingsPanelDisabled"
407
+ },
408
+ "spellCheck": {
409
+ "title": "ConfigureProp",
410
+ "type": "object",
411
+ "properties": {
412
+ "settings": {
413
+ "description": "Indicates if the item has to be displayed in the Settings Panel",
414
+ "type": "boolean",
415
+ "title": "settings"
416
+ },
417
+ "label": {
418
+ "description": "Indicates the label for the item that has to be displayed in the Settings Panel",
419
+ "type": "string",
420
+ "title": "label"
421
+ }
422
+ }
423
+ },
320
424
  "rationale": {
321
425
  "title": "ConfigureProp",
322
426
  "type": "object",
@@ -396,6 +500,68 @@
396
500
  "title": "label"
397
501
  }
398
502
  }
503
+ },
504
+ "minAnswerChoices": {
505
+ "description": "Minimum number of answer choices",
506
+ "type": "number",
507
+ "title": "minAnswerChoices"
508
+ },
509
+ "maxAnswerChoices": {
510
+ "description": "Maximum number of answer choices",
511
+ "type": "number",
512
+ "title": "maxAnswerChoices"
513
+ },
514
+ "maxImageWidth": {
515
+ "title": "ConfigureMaxImageDimensionsProp",
516
+ "type": "object",
517
+ "properties": {
518
+ "teacherInstructions": {
519
+ "description": "Indicates the max dimension for images in teacher instructions",
520
+ "type": "number",
521
+ "title": "teacherInstructions"
522
+ },
523
+ "prompt": {
524
+ "description": "Indicates the max dimension for images in prompt - this is also the default dimension for all other input fields if it's not specified",
525
+ "type": "number",
526
+ "title": "prompt"
527
+ },
528
+ "rationale": {
529
+ "description": "Indicates the max dimension for images in rationale",
530
+ "type": "number",
531
+ "title": "rationale"
532
+ },
533
+ "choices": {
534
+ "description": "Indicates the max dimension for images in choices",
535
+ "type": "number",
536
+ "title": "choices"
537
+ }
538
+ }
539
+ },
540
+ "maxImageHeight": {
541
+ "title": "ConfigureMaxImageDimensionsProp",
542
+ "type": "object",
543
+ "properties": {
544
+ "teacherInstructions": {
545
+ "description": "Indicates the max dimension for images in teacher instructions",
546
+ "type": "number",
547
+ "title": "teacherInstructions"
548
+ },
549
+ "prompt": {
550
+ "description": "Indicates the max dimension for images in prompt - this is also the default dimension for all other input fields if it's not specified",
551
+ "type": "number",
552
+ "title": "prompt"
553
+ },
554
+ "rationale": {
555
+ "description": "Indicates the max dimension for images in rationale",
556
+ "type": "number",
557
+ "title": "rationale"
558
+ },
559
+ "choices": {
560
+ "description": "Indicates the max dimension for images in choices",
561
+ "type": "number",
562
+ "title": "choices"
563
+ }
564
+ }
399
565
  }
400
566
  }
401
567
  },
@@ -431,6 +597,11 @@
431
597
  }
432
598
  }
433
599
  },
600
+ "settingsPanelDisabled": {
601
+ "description": "Indicates if the settings panel is not available",
602
+ "type": "boolean",
603
+ "title": "settingsPanelDisabled"
604
+ },
434
605
  "scoringType": {
435
606
  "title": "ConfigureProp",
436
607
  "type": "object",
@@ -581,6 +752,27 @@
581
752
  }
582
753
  }
583
754
  },
755
+ "settingsPanelDisabled": {
756
+ "description": "Indicates if the settings panel is not available",
757
+ "type": "boolean",
758
+ "title": "settingsPanelDisabled"
759
+ },
760
+ "spellCheck": {
761
+ "title": "ConfigureProp",
762
+ "type": "object",
763
+ "properties": {
764
+ "settings": {
765
+ "description": "Indicates if the item has to be displayed in the Settings Panel",
766
+ "type": "boolean",
767
+ "title": "settings"
768
+ },
769
+ "label": {
770
+ "description": "Indicates the label for the item that has to be displayed in the Settings Panel",
771
+ "type": "string",
772
+ "title": "label"
773
+ }
774
+ }
775
+ },
584
776
  "rationale": {
585
777
  "title": "ConfigureProp",
586
778
  "type": "object",
@@ -660,6 +852,68 @@
660
852
  "title": "label"
661
853
  }
662
854
  }
855
+ },
856
+ "minAnswerChoices": {
857
+ "description": "Minimum number of answer choices",
858
+ "type": "number",
859
+ "title": "minAnswerChoices"
860
+ },
861
+ "maxAnswerChoices": {
862
+ "description": "Maximum number of answer choices",
863
+ "type": "number",
864
+ "title": "maxAnswerChoices"
865
+ },
866
+ "maxImageWidth": {
867
+ "title": "ConfigureMaxImageDimensionsProp",
868
+ "type": "object",
869
+ "properties": {
870
+ "teacherInstructions": {
871
+ "description": "Indicates the max dimension for images in teacher instructions",
872
+ "type": "number",
873
+ "title": "teacherInstructions"
874
+ },
875
+ "prompt": {
876
+ "description": "Indicates the max dimension for images in prompt - this is also the default dimension for all other input fields if it's not specified",
877
+ "type": "number",
878
+ "title": "prompt"
879
+ },
880
+ "rationale": {
881
+ "description": "Indicates the max dimension for images in rationale",
882
+ "type": "number",
883
+ "title": "rationale"
884
+ },
885
+ "choices": {
886
+ "description": "Indicates the max dimension for images in choices",
887
+ "type": "number",
888
+ "title": "choices"
889
+ }
890
+ }
891
+ },
892
+ "maxImageHeight": {
893
+ "title": "ConfigureMaxImageDimensionsProp",
894
+ "type": "object",
895
+ "properties": {
896
+ "teacherInstructions": {
897
+ "description": "Indicates the max dimension for images in teacher instructions",
898
+ "type": "number",
899
+ "title": "teacherInstructions"
900
+ },
901
+ "prompt": {
902
+ "description": "Indicates the max dimension for images in prompt - this is also the default dimension for all other input fields if it's not specified",
903
+ "type": "number",
904
+ "title": "prompt"
905
+ },
906
+ "rationale": {
907
+ "description": "Indicates the max dimension for images in rationale",
908
+ "type": "number",
909
+ "title": "rationale"
910
+ },
911
+ "choices": {
912
+ "description": "Indicates the max dimension for images in choices",
913
+ "type": "number",
914
+ "title": "choices"
915
+ }
916
+ }
663
917
  }
664
918
  }
665
919
  },
@@ -678,6 +932,32 @@
678
932
  "title": "label"
679
933
  }
680
934
  }
935
+ },
936
+ "ConfigureMaxImageDimensionsProp": {
937
+ "title": "ConfigureMaxImageDimensionsProp",
938
+ "type": "object",
939
+ "properties": {
940
+ "teacherInstructions": {
941
+ "description": "Indicates the max dimension for images in teacher instructions",
942
+ "type": "number",
943
+ "title": "teacherInstructions"
944
+ },
945
+ "prompt": {
946
+ "description": "Indicates the max dimension for images in prompt - this is also the default dimension for all other input fields if it's not specified",
947
+ "type": "number",
948
+ "title": "prompt"
949
+ },
950
+ "rationale": {
951
+ "description": "Indicates the max dimension for images in rationale",
952
+ "type": "number",
953
+ "title": "rationale"
954
+ },
955
+ "choices": {
956
+ "description": "Indicates the max dimension for images in choices",
957
+ "type": "number",
958
+ "title": "choices"
959
+ }
960
+ }
681
961
  }
682
962
  },
683
963
  "$schema": "http://json-schema.org/draft-07/schema#"