@pie-element/image-cloze-association 10.2.0-next.19 → 10.2.0-next.21

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.
@@ -1,7 +1,7 @@
1
1
  import { g as e, i as t, l as n, s as r, x as i } from "../dist-oxliJ767.js";
2
2
  import { t as a } from "../humps-vcapGabG.js";
3
3
  //#region ../../shared/controller-utils/dist/index.js
4
- var o = /* @__PURE__ */ i(e(), 1), s = a(), c = Object.defineProperty, l = /* @__PURE__ */ ((e, t) => {
4
+ var o = /* @__PURE__ */ i(e(), 1), s = /* @__PURE__ */ i(a(), 1), c = Object.defineProperty, l = /* @__PURE__ */ ((e, t) => {
5
5
  let n = {};
6
6
  for (var r in e) c(n, r, {
7
7
  get: e[r],
@@ -52,17 +52,17 @@ var d = {
52
52
  possibleResponses: s,
53
53
  hasUnplacedChoices: l
54
54
  };
55
- }, g = (0, o.default)("pie-elements:image-cloze-association:controller"), _ = (e) => ({
55
+ }, { camelizeKeys: g } = s.default, _ = (0, o.default)("pie-elements:image-cloze-association:controller"), v = (e) => ({
56
56
  ...d,
57
57
  ...e
58
- }), v = (e, t, n) => {
59
- let i = _(e), a = (0, s.camelizeKeys)(i);
58
+ }), y = (e, t, n) => {
59
+ let i = v(e), a = g(i);
60
60
  return new Promise((e) => {
61
61
  let o = n.mode === "evaluate", { responseAreasToBeFilled: s, possibleResponses: c, hasUnplacedChoices: l } = h(a.validation, a.possibleResponses), u = {
62
62
  disabled: n.mode !== "gather",
63
63
  mode: n.mode,
64
64
  ...a,
65
- responseCorrect: o ? w(a, t) === 1 : void 0,
65
+ responseCorrect: o ? T(a, t) === 1 : void 0,
66
66
  validation: o ? a.validation : void 0,
67
67
  responseAreasToBeFilled: s,
68
68
  completeResponses: c,
@@ -70,32 +70,32 @@ var d = {
70
70
  };
71
71
  i.shuffle && (u.possibleResponses = r(i.possible_responses)), n.role === "instructor" && (n.mode === "view" || n.mode === "evaluate") ? (u.teacherInstructions = a.teacherInstructionsEnabled ? a.teacherInstructions : null, u.rationale = a.rationale ? a.rationale : null) : (u.teacherInstructions = null, u.rationale = null), e(u);
72
72
  });
73
- }, y = (e, r) => {
73
+ }, b = (e, r) => {
74
74
  let i = n(e), a = !0, o = 0;
75
75
  return !r || t(r) ? !1 : (i.forEach((e) => o += (e.images || []).length), r.answers && o === r.answers.length ? r.answers.forEach((e) => {
76
76
  let t = (i[e.containerIndex]?.images || []).indexOf(e.value);
77
77
  t >= 0 ? i[e.containerIndex].images.splice(t, 1) : a = !1;
78
78
  }) : a = !1, a);
79
- }, b = (e) => n(e.filter((e) => e.images && e.images.length)), x = (e, t) => {
80
- let { validation: { altResponses: n } } = e, { validation: { validResponse: { value: r } } } = e, i = y(r, t);
79
+ }, x = (e) => n(e.filter((e) => e.images && e.images.length)), S = (e, t) => {
80
+ let { validation: { altResponses: n } } = e, { validation: { validResponse: { value: r } } } = e, i = b(r, t);
81
81
  return !i && n && n.length && n.forEach((e) => {
82
- y(e.value, t) && (i = !0);
82
+ b(e.value, t) && (i = !0);
83
83
  }), i;
84
- }, S = (e, t, n) => {
84
+ }, C = (e, t, n) => {
85
85
  let r = t.filter((t) => t.containerIndex === e), i = r.filter((e) => !e.isCorrect), a = (n.value[e].images || []).length;
86
86
  if (r.length > a) {
87
87
  let e = r.length - a;
88
88
  return i.slice(-e);
89
89
  }
90
90
  return [];
91
- }, C = (e, n) => {
91
+ }, w = (e, n) => {
92
92
  let { validation: { validResponse: r }, maxResponsePerZone: i } = e, a = 0, o = 0, s = 0;
93
93
  if (!n || t(n)) return 0;
94
94
  if (r.value.forEach((e) => s += (e.images || []).length), n.answers && n.answers.length) {
95
95
  let e = m(n.answers, r.value);
96
96
  a = e.filter((e) => e.isCorrect).length, o = e.filter((e) => !e.isCorrect).length, n.answers.forEach((t) => {
97
97
  if (i > 1) {
98
- let n = S(t.containerIndex, e, r);
98
+ let n = C(t.containerIndex, e, r);
99
99
  n.length && n.forEach((e) => {
100
100
  e.id === t.id && --a;
101
101
  });
@@ -103,12 +103,12 @@ var d = {
103
103
  }), (!i || i <= 1) && (a -= o);
104
104
  } else a = 0;
105
105
  a = a < 0 ? 0 : a;
106
- let c = b(r.value), l = i > 1 ? s : (c || []).length, u = (a / l).toFixed(2);
106
+ let c = x(r.value), l = i > 1 ? s : (c || []).length, u = (a / l).toFixed(2);
107
107
  return parseFloat(u);
108
- }, w = (e, t, n = {}) => {
109
- let r = l.enabled(e, n), i = x(e, t);
110
- return r ? C(e, t) : +!!i;
111
- }, T = (e, t, n) => {
108
+ }, T = (e, t, n = {}) => {
109
+ let r = l.enabled(e, n), i = S(e, t);
110
+ return r ? w(e, t) : +!!i;
111
+ }, E = (e, t, n) => {
112
112
  let r = [], { answers: i } = t || {}, a = e.validation?.validResponse?.value || [], o = a.length;
113
113
  if (r.push(`${o} placement container(s) defined in this question.`), i && i.length > 0) {
114
114
  r.push(`Student placed ${i.length} image(s) into placement containers.`);
@@ -128,23 +128,23 @@ var d = {
128
128
  s.length > 0 && r.push(`${s.length} alternate response combination(s) are accepted for this question.`);
129
129
  let c = l.enabled(e, n) ? "partial scoring" : "all-or-nothing scoring";
130
130
  r.push(`Score calculated using ${c}.`);
131
- let u = w(e, t, n);
131
+ let u = T(e, t, n);
132
132
  return r.push(`Final score: ${u}.`), r;
133
- }, E = (e, n, r = {}) => new Promise((i) => {
134
- if (g("outcome..."), !n || t(n)) i({
133
+ }, D = (e, n, r = {}) => new Promise((i) => {
134
+ if (_("outcome..."), !n || t(n)) i({
135
135
  score: 0,
136
136
  empty: !0,
137
137
  traceLog: ["Student did not place any images into placement containers. Score is 0."]
138
138
  });
139
139
  else {
140
- let t = (0, s.camelizeKeys)(e), a = T(t, n, r);
140
+ let t = g(e), a = E(t, n, r);
141
141
  i({
142
- score: w(t, n, r),
142
+ score: T(t, n, r),
143
143
  empty: !1,
144
144
  traceLog: a
145
145
  });
146
146
  }
147
- }), D = (e, t) => new Promise((n) => {
147
+ }), O = (e, t) => new Promise((n) => {
148
148
  if (t.mode !== "evaluate" && t.role === "instructor") {
149
149
  let { validation: { valid_response: { value: t } } } = e, r = [];
150
150
  t && t.forEach((e, t) => {
@@ -159,13 +159,13 @@ var d = {
159
159
  id: "1"
160
160
  });
161
161
  } else n(null);
162
- }), O = (e) => (e || "").replace(/(<(?!img|iframe|source)([^>]+)>)/gi, ""), k = (e = {}, t = {}) => {
162
+ }), k = (e) => (e || "").replace(/(<(?!img|iframe|source)([^>]+)>)/gi, ""), A = (e = {}, t = {}) => {
163
163
  let n = {};
164
164
  return ["teacherInstructions"].forEach((r) => {
165
- t[r]?.required && !O(e[r]) && (n[r] = "This field is required.");
165
+ t[r]?.required && !k(e[r]) && (n[r] = "This field is required.");
166
166
  }), n;
167
167
  };
168
168
  //#endregion
169
- export { D as createCorrectResponseSession, T as getLogTrace, C as getPartialScore, y as isResponseCorrect, v as model, _ as normalize, E as outcome, k as validate };
169
+ export { O as createCorrectResponseSession, E as getLogTrace, w as getPartialScore, b as isResponseCorrect, y as model, v as normalize, D as outcome, A as validate };
170
170
 
171
171
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../../../../../shared/controller-utils/dist/index.js","../../../../src/controller/defaults.ts","../../../../src/controller/utils.ts","../../../../src/controller/index.ts"],"sourcesContent":["//#region \\0rolldown/runtime.js\nvar e = Object.defineProperty, t = (t, n) => {\n\tlet r = {};\n\tfor (var i in t) e(r, i, {\n\t\tget: t[i],\n\t\tenumerable: !0\n\t});\n\treturn n || e(r, Symbol.toStringTag, { value: \"Module\" }), r;\n};\n//#endregion\n//#region src/persistence.ts\nfunction n(e) {\n\treturn Array.isArray(e) ? e.filter((e) => e != null) : [];\n}\nfunction r(e) {\n\tlet t = [...e];\n\tfor (let e = t.length - 1; e > 0; e--) {\n\t\tlet n = Math.floor(Math.random() * (e + 1));\n\t\t[t[e], t[n]] = [t[n], t[e]];\n\t}\n\treturn t;\n}\nfunction i(e) {\n\treturn e == null ? !0 : Array.isArray(e) ? e.length === 0 : typeof e == \"object\" && Object.keys(e).length === 0;\n}\nasync function a(e, t, a, o = \"value\") {\n\tlet s = n(t?.data?.shuffledValues ?? t?.shuffledValues ?? []);\n\tif (!t) {\n\t\tconsole.warn(\"Unable to save shuffled choices because there's no session.\");\n\t\treturn;\n\t}\n\tif (!i(s)) return n(s.map((t) => e.find((e) => e[o] === t)));\n\tlet c = r(e);\n\tif (a && typeof a == \"function\") try {\n\t\tlet e = n(c.map((e) => e[o]));\n\t\ti(e) ? console.error(`shuffledValues is an empty array - refusing to call updateSession. shuffledChoices: ${JSON.stringify(c)}, key: ${o}`) : t.id && t.element && await a(t.id, t.element, { shuffledValues: e });\n\t} catch (e) {\n\t\tconsole.warn(\"Unable to save shuffled order for choices\"), console.error(e);\n\t}\n\telse console.warn(\"Unable to save shuffled choices, shuffle will happen every time.\");\n\treturn c;\n}\nfunction o(e, t, n) {\n\treturn !!(e.lockChoiceOrder || n[\"@pie-element\"]?.lockChoiceOrder || (n.role ?? \"student\") === \"instructor\");\n}\n//#endregion\n//#region src/partial-scoring.ts\nvar s = /* @__PURE__ */ t({ enabled: () => c });\nfunction c(e, t, n) {\n\treturn e?.partialScoring === !1 || t?.partialScoring === !1 ? !1 : typeof n != \"boolean\" || n;\n}\n//#endregion\nexport { a as getShuffledChoices, o as lockChoices, s as partialScoring };\n","// @ts-nocheck\n/**\n * @synced-from pie-elements/packages/image-cloze-association/controller/src/defaults.js\n * @auto-generated\n *\n * This file is automatically synced from pie-elements and converted to TypeScript.\n * Manual edits will be overwritten on next sync.\n * To make changes, edit the upstream JavaScript file and run sync again.\n */\n\nexport default {\n rationale: '',\n rationaleEnabled: true,\n studentInstructionsEnabled: true,\n teacherInstructions: '',\n teacherInstructionsEnabled: true,\n};\n","// @ts-nocheck\n/**\n * @synced-from pie-elements/packages/image-cloze-association/controller/src/utils.js\n * @auto-generated\n *\n * This file is automatically synced from pie-elements and converted to TypeScript.\n * Manual edits will be overwritten on next sync.\n * To make changes, edit the upstream JavaScript file and run sync again.\n */\n\n// functions also used in src/utils-correctness.js\n\nconst getAllCorrectness = (answers, responses) =>\n (answers || []).map((answer) => ({\n ...answer,\n isCorrect: ((responses[answer.containerIndex] && responses[answer.containerIndex].images) || []).includes(\n answer.value,\n ),\n }));\n\nconst getValidAnswer = (answer, response) =>\n ((response[answer.containerIndex] && response[answer.containerIndex].images) || []).filter(\n (res) => res === answer.value,\n );\n\nexport const getAllUniqueCorrectness = (answers, validResponses) => {\n let allCorrectness = getAllCorrectness(answers, validResponses);\n\n answers.forEach((answer1) => {\n const valuesToParse = answers.filter(\n (answer2) => answer2.value === answer1.value && answer2.containerIndex === answer1.containerIndex,\n );\n\n if (valuesToParse.length > 1) {\n // point only to duplicates but first\n valuesToParse.shift();\n // mark duplicates as incorrect\n valuesToParse.forEach((value, index) => {\n allCorrectness = (allCorrectness || []).map((finalAnswer) => {\n if (finalAnswer.id === value.id) {\n let valid = getValidAnswer(finalAnswer, validResponses);\n return {\n ...finalAnswer,\n isCorrect: valid.length > index + 1,\n };\n }\n return finalAnswer;\n });\n });\n }\n });\n return allCorrectness;\n};\n\n// calculate the minimum number of populated response areas (categories) in the correct answer or alternates\n// and create an array with the possible responses ids\nexport const getCompleteResponseDetails = (validation, allChoices) => {\n const extractImages = (response) => (response?.value || []).map((container) => container.images);\n const countFilledResponseAreas = (container) => (container || []).filter((images) => images.length).length;\n\n const { validResponse, altResponses } = validation || {};\n const imagesPerContainer = extractImages(validResponse);\n const possibleResponses = [imagesPerContainer.flat()];\n let responseAreasToBeFilled = countFilledResponseAreas(imagesPerContainer);\n\n (altResponses || []).forEach((altResponse) => {\n const altImagesPerContainer = extractImages(altResponse);\n const filledResponseAreas = countFilledResponseAreas(altImagesPerContainer);\n possibleResponses.push(altImagesPerContainer.flat());\n\n if (filledResponseAreas < responseAreasToBeFilled) {\n responseAreasToBeFilled = filledResponseAreas;\n }\n });\n\n // check if any correct answer have any unplaced answer choices\n const hasUnplacedChoices = possibleResponses.some(\n (response) => !allChoices.every((val) => response.includes(val)),\n );\n\n return { responseAreasToBeFilled, possibleResponses, hasUnplacedChoices };\n};\n","// @ts-nocheck\n/**\n * @synced-from pie-elements/packages/image-cloze-association/controller/src/index.js\n * @auto-generated\n *\n * This file is automatically synced from pie-elements and converted to TypeScript.\n * Manual edits will be overwritten on next sync.\n * To make changes, edit the upstream JavaScript file and run sync again.\n */\n\nimport debug from 'debug';\nimport { camelizeKeys } from 'humps';\nimport { partialScoring } from '@pie-element/shared-controller-utils';\nimport { cloneDeep, isEmpty, shuffle } from '@pie-element/shared-lodash';\n\nimport defaults from './defaults.js';\nimport { getAllUniqueCorrectness, getCompleteResponseDetails } from './utils.js';\n\nconst log = debug('pie-elements:image-cloze-association:controller');\n\nexport const normalize = (question) => ({ ...defaults, ...question });\n\nexport const model = (question, session, env) => {\n const questionNormalized = normalize(question);\n const questionCamelized = camelizeKeys(questionNormalized);\n\n return new Promise((resolve) => {\n const shouldIncludeCorrectResponse = env.mode === 'evaluate';\n\n const {\n responseAreasToBeFilled,\n possibleResponses: completeResponses,\n hasUnplacedChoices,\n } = getCompleteResponseDetails(questionCamelized.validation, questionCamelized.possibleResponses);\n\n const out = {\n disabled: env.mode !== 'gather',\n mode: env.mode,\n ...questionCamelized,\n responseCorrect: shouldIncludeCorrectResponse ? getScore(questionCamelized, session) === 1 : undefined,\n validation: shouldIncludeCorrectResponse ? questionCamelized.validation : undefined,\n responseAreasToBeFilled,\n completeResponses,\n hasUnplacedChoices,\n };\n\n if (questionNormalized.shuffle) {\n out.possibleResponses = shuffle(questionNormalized.possible_responses);\n }\n\n if (env.role === 'instructor' && (env.mode === 'view' || env.mode === 'evaluate')) {\n out.teacherInstructions = questionCamelized.teacherInstructionsEnabled\n ? questionCamelized.teacherInstructions\n : null;\n out.rationale = questionCamelized.rationale ? questionCamelized.rationale : null;\n } else {\n out.teacherInstructions = null;\n out.rationale = null;\n }\n\n resolve(out);\n });\n};\n\nexport const isResponseCorrect = (correctResponses, session) => {\n const responses = cloneDeep(correctResponses);\n let isCorrect = true;\n let totalValidResponses = 0;\n\n if (!session || isEmpty(session)) {\n return false;\n }\n\n responses.forEach((value) => (totalValidResponses += (value.images || []).length));\n\n if (session.answers && totalValidResponses === session.answers.length) {\n session.answers.forEach((answer) => {\n const index = (responses[answer.containerIndex]?.images || []).indexOf(answer.value);\n\n if (index >= 0) {\n // remove response from correct responses array to ensure that duplicates are evaluated correctly\n responses[answer.containerIndex].images.splice(index, 1);\n } else {\n isCorrect = false;\n }\n });\n } else {\n isCorrect = false;\n }\n\n return isCorrect;\n};\n\n// This applies for correct responses that have empty values\nconst keepNonEmptyResponses = (responses) => {\n const filtered = responses.filter((response) => response.images && response.images.length);\n return cloneDeep(filtered);\n};\n\n// This applies for items that don't support partial scoring.\nconst isDefaultOrAltResponseCorrect = (question, session) => {\n const {\n validation: { altResponses },\n } = question;\n let {\n validation: {\n validResponse: { value },\n },\n } = question;\n\n let isCorrect = isResponseCorrect(value, session);\n\n // Look for correct answers in alternate responses.\n if (!isCorrect && altResponses && altResponses.length) {\n altResponses.forEach((altResponse) => {\n if (isResponseCorrect(altResponse.value, session)) {\n isCorrect = true;\n }\n });\n }\n return isCorrect;\n};\n\n// Deduct only the items that exceeded the maximum valid response per container.\nconst getDeductionPerContainer = (containerIndex, answers, valid) => {\n const totalStack = answers.filter((item) => item.containerIndex === containerIndex);\n const incorrectStack = totalStack.filter((item) => !item.isCorrect);\n const maxValid = (valid.value[containerIndex].images || []).length;\n\n if (totalStack.length > maxValid) {\n const ignored = totalStack.length - maxValid;\n return incorrectStack.slice(-ignored);\n }\n return [];\n};\n\nexport const getPartialScore = (question, session) => {\n const {\n validation: { validResponse },\n maxResponsePerZone,\n } = question;\n let correctAnswers = 0;\n let incorrectAnswers = 0;\n let possibleResponses = 0;\n\n if (!session || isEmpty(session)) {\n return 0;\n }\n\n validResponse.value.forEach((value) => (possibleResponses += (value.images || []).length));\n\n if (session.answers && session.answers.length) {\n const all = getAllUniqueCorrectness(session.answers, validResponse.value);\n correctAnswers = all.filter((item) => item.isCorrect).length;\n incorrectAnswers = all.filter((item) => !item.isCorrect).length;\n\n // deduction rules: https://docs.google.com/document/d/1Oprm8Qs5fg_Dwoj2pNpsfu4D63QgCZgvcqTgeaVel7I/edit\n session.answers.forEach((answer) => {\n if (maxResponsePerZone > 1) {\n const deductionList = getDeductionPerContainer(answer.containerIndex, all, validResponse);\n\n if (deductionList.length) {\n deductionList.forEach((item) => {\n if (item.id === answer.id) {\n correctAnswers -= 1;\n }\n });\n }\n }\n });\n\n if (!maxResponsePerZone || maxResponsePerZone <= 1) {\n correctAnswers -= incorrectAnswers;\n }\n } else {\n correctAnswers = 0;\n }\n // negative values will implicitly make the score equal to zero\n correctAnswers = correctAnswers < 0 ? 0 : correctAnswers;\n\n // use length of validResponse since some containers can be left empty\n const nonEmptyResponses = keepNonEmptyResponses(validResponse.value);\n const denominator = maxResponsePerZone > 1 ? possibleResponses : (nonEmptyResponses || []).length;\n const str = (correctAnswers / denominator).toFixed(2);\n\n return parseFloat(str);\n};\n\nconst getScore = (config, session, env = {}) => {\n const isPartialScoring = partialScoring.enabled(config, env);\n const correct = isDefaultOrAltResponseCorrect(config, session);\n\n return isPartialScoring ? getPartialScore(config, session) : correct ? 1 : 0;\n};\n\n/**\n * Generates detailed trace log for scoring evaluation\n * @param {Object} model - the question model\n * @param {Object} session - the student session\n * @param {Object} env - the environment\n * @returns {Array} traceLog - array of trace messages\n */\nexport const getLogTrace = (model, session, env) => {\n const traceLog = [];\n const { answers } = session || {};\n \n const validResponse = model.validation?.validResponse?.value || [];\n const totalContainers = validResponse.length;\n traceLog.push(`${totalContainers} placement container(s) defined in this question.`);\n\n if (answers && answers.length > 0) {\n traceLog.push(`Student placed ${answers.length} image(s) into placement containers.`);\n \n const answersByContainer = {};\n answers.forEach((answer) => {\n if (!answersByContainer[answer.containerIndex]) {\n answersByContainer[answer.containerIndex] = [];\n }\n answersByContainer[answer.containerIndex].push(answer.value);\n });\n \n validResponse.forEach((container, containerIndex) => {\n const correctImages = container.images || [];\n const studentImages = answersByContainer[containerIndex] || [];\n \n if (correctImages.length > 0) {\n if (studentImages.length === 0) {\n traceLog.push(`Container ${containerIndex + 1}: student left empty (should contain ${correctImages.length} image(s)).`);\n } else {\n const correctCount = studentImages.filter(img => correctImages.includes(img)).length;\n const incorrectCount = studentImages.length - correctCount;\n \n if (correctCount > 0 && incorrectCount === 0) {\n traceLog.push(`Container ${containerIndex + 1}: student placed ${correctCount} correct image(s).`);\n } else if (correctCount === 0 && incorrectCount > 0) {\n traceLog.push(`Container ${containerIndex + 1}: student placed ${incorrectCount} incorrect image(s).`);\n } else {\n traceLog.push(`Container ${containerIndex + 1}: student placed ${correctCount} correct and ${incorrectCount} incorrect image(s).`);\n }\n }\n }\n });\n } else {\n traceLog.push('Student did not place any images into placement containers.');\n }\n\n const altResponses = model.validation?.altResponses || [];\n if (altResponses.length > 0) {\n traceLog.push(`${altResponses.length} alternate response combination(s) are accepted for this question.`);\n }\n\n const partialScoringEnabled = partialScoring.enabled(model, env);\n const scoringMethod = partialScoringEnabled ? 'partial scoring' : 'all-or-nothing scoring';\n traceLog.push(`Score calculated using ${scoringMethod}.`);\n\n const score = getScore(model, session, env);\n traceLog.push(`Final score: ${score}.`);\n\n return traceLog;\n}\n\nexport const outcome = (config, session, env = {}) => {\n return new Promise((resolve) => {\n log('outcome...');\n if (!session || isEmpty(session)) {\n resolve({ \n score: 0, \n empty: true, \n traceLog: ['Student did not place any images into placement containers. Score is 0.'] \n });\n } else {\n const configCamelized = camelizeKeys(config);\n const traceLog = getLogTrace(configCamelized, session, env);\n const score = getScore(configCamelized, session, env);\n \n resolve({ \n score, \n empty: false,\n traceLog \n });\n }\n });\n};\n\nexport const createCorrectResponseSession = (question, env) => {\n return new Promise((resolve) => {\n if (env.mode !== 'evaluate' && env.role === 'instructor') {\n const {\n validation: {\n valid_response: { value },\n },\n } = question;\n const answers = [];\n\n if (value) {\n value.forEach((container, i) => {\n (container.images || []).forEach((v) => {\n answers.push({\n value: v,\n containerIndex: i,\n });\n });\n });\n }\n\n resolve({\n answers,\n id: '1',\n });\n } else {\n resolve(null);\n }\n });\n};\n\n// remove all html tags\nconst getInnerText = (html) => (html || '').replaceAll(/<[^>]*>/g, '');\n\n// remove all html tags except img, iframe and source tag for audio\nconst getContent = (html) => (html || '').replace(/(<(?!img|iframe|source)([^>]+)>)/gi, '');\n\nexport const validate = (model = {}, config = {}) => {\n const errors = {};\n\n ['teacherInstructions'].forEach((field) => {\n if (config[field]?.required && !getContent(model[field])) {\n errors[field] = 'This field is required.';\n }\n });\n\n return errors;\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../../../../../shared/controller-utils/dist/index.js","../../../../src/controller/defaults.ts","../../../../src/controller/utils.ts","../../../../src/controller/index.ts"],"sourcesContent":["//#region \\0rolldown/runtime.js\nvar e = Object.defineProperty, t = (t, n) => {\n\tlet r = {};\n\tfor (var i in t) e(r, i, {\n\t\tget: t[i],\n\t\tenumerable: !0\n\t});\n\treturn n || e(r, Symbol.toStringTag, { value: \"Module\" }), r;\n};\n//#endregion\n//#region src/persistence.ts\nfunction n(e) {\n\treturn Array.isArray(e) ? e.filter((e) => e != null) : [];\n}\nfunction r(e) {\n\tlet t = [...e];\n\tfor (let e = t.length - 1; e > 0; e--) {\n\t\tlet n = Math.floor(Math.random() * (e + 1));\n\t\t[t[e], t[n]] = [t[n], t[e]];\n\t}\n\treturn t;\n}\nfunction i(e) {\n\treturn e == null ? !0 : Array.isArray(e) ? e.length === 0 : typeof e == \"object\" && Object.keys(e).length === 0;\n}\nasync function a(e, t, a, o = \"value\") {\n\tlet s = n(t?.data?.shuffledValues ?? t?.shuffledValues ?? []);\n\tif (!t) {\n\t\tconsole.warn(\"Unable to save shuffled choices because there's no session.\");\n\t\treturn;\n\t}\n\tif (!i(s)) return n(s.map((t) => e.find((e) => e[o] === t)));\n\tlet c = r(e);\n\tif (a && typeof a == \"function\") try {\n\t\tlet e = n(c.map((e) => e[o]));\n\t\ti(e) ? console.error(`shuffledValues is an empty array - refusing to call updateSession. shuffledChoices: ${JSON.stringify(c)}, key: ${o}`) : await a(t.id, t.element, { shuffledValues: e });\n\t} catch (e) {\n\t\tconsole.warn(\"Unable to save shuffled order for choices\"), console.error(e);\n\t}\n\telse console.warn(\"Unable to save shuffled choices, shuffle will happen every time.\");\n\treturn c;\n}\nfunction o(e, t, n) {\n\treturn !!(e.lockChoiceOrder || n?.[\"@pie-element\"]?.lockChoiceOrder);\n}\n//#endregion\n//#region src/partial-scoring.ts\nvar s = /* @__PURE__ */ t({ enabled: () => c });\nfunction c(e, t, n) {\n\treturn e?.partialScoring === !1 || t?.partialScoring === !1 ? !1 : typeof n != \"boolean\" || n;\n}\n//#endregion\nexport { a as getShuffledChoices, o as lockChoices, s as partialScoring };\n","// @ts-nocheck\n/**\n * @synced-from pie-elements/packages/image-cloze-association/controller/src/defaults.js\n * @auto-generated\n *\n * This file is automatically synced from pie-elements and converted to TypeScript.\n * Manual edits will be overwritten on next sync.\n * To make changes, edit the upstream JavaScript file and run sync again.\n */\n\nexport default {\n rationale: '',\n rationaleEnabled: true,\n studentInstructionsEnabled: true,\n teacherInstructions: '',\n teacherInstructionsEnabled: true,\n};\n","// @ts-nocheck\n/**\n * @synced-from pie-elements/packages/image-cloze-association/controller/src/utils.js\n * @auto-generated\n *\n * This file is automatically synced from pie-elements and converted to TypeScript.\n * Manual edits will be overwritten on next sync.\n * To make changes, edit the upstream JavaScript file and run sync again.\n */\n\n// functions also used in src/utils-correctness.js\n\nconst getAllCorrectness = (answers, responses) =>\n (answers || []).map((answer) => ({\n ...answer,\n isCorrect: ((responses[answer.containerIndex] && responses[answer.containerIndex].images) || []).includes(\n answer.value,\n ),\n }));\n\nconst getValidAnswer = (answer, response) =>\n ((response[answer.containerIndex] && response[answer.containerIndex].images) || []).filter(\n (res) => res === answer.value,\n );\n\nexport const getAllUniqueCorrectness = (answers, validResponses) => {\n let allCorrectness = getAllCorrectness(answers, validResponses);\n\n answers.forEach((answer1) => {\n const valuesToParse = answers.filter(\n (answer2) => answer2.value === answer1.value && answer2.containerIndex === answer1.containerIndex,\n );\n\n if (valuesToParse.length > 1) {\n // point only to duplicates but first\n valuesToParse.shift();\n // mark duplicates as incorrect\n valuesToParse.forEach((value, index) => {\n allCorrectness = (allCorrectness || []).map((finalAnswer) => {\n if (finalAnswer.id === value.id) {\n let valid = getValidAnswer(finalAnswer, validResponses);\n return {\n ...finalAnswer,\n isCorrect: valid.length > index + 1,\n };\n }\n return finalAnswer;\n });\n });\n }\n });\n return allCorrectness;\n};\n\n// calculate the minimum number of populated response areas (categories) in the correct answer or alternates\n// and create an array with the possible responses ids\nexport const getCompleteResponseDetails = (validation, allChoices) => {\n const extractImages = (response) => (response?.value || []).map((container) => container.images);\n const countFilledResponseAreas = (container) => (container || []).filter((images) => images.length).length;\n\n const { validResponse, altResponses } = validation || {};\n const imagesPerContainer = extractImages(validResponse);\n const possibleResponses = [imagesPerContainer.flat()];\n let responseAreasToBeFilled = countFilledResponseAreas(imagesPerContainer);\n\n (altResponses || []).forEach((altResponse) => {\n const altImagesPerContainer = extractImages(altResponse);\n const filledResponseAreas = countFilledResponseAreas(altImagesPerContainer);\n possibleResponses.push(altImagesPerContainer.flat());\n\n if (filledResponseAreas < responseAreasToBeFilled) {\n responseAreasToBeFilled = filledResponseAreas;\n }\n });\n\n // check if any correct answer have any unplaced answer choices\n const hasUnplacedChoices = possibleResponses.some(\n (response) => !allChoices.every((val) => response.includes(val)),\n );\n\n return { responseAreasToBeFilled, possibleResponses, hasUnplacedChoices };\n};\n","// @ts-nocheck\n/**\n * @synced-from pie-elements/packages/image-cloze-association/controller/src/index.js\n * @auto-generated\n *\n * This file is automatically synced from pie-elements and converted to TypeScript.\n * Manual edits will be overwritten on next sync.\n * To make changes, edit the upstream JavaScript file and run sync again.\n */\n\nimport debug from 'debug';\nimport humps from 'humps';\nconst { camelizeKeys } = humps;\nimport { partialScoring } from '@pie-element/shared-controller-utils';\nimport { cloneDeep, isEmpty, shuffle } from '@pie-element/shared-lodash';\n\nimport defaults from './defaults.js';\nimport { getAllUniqueCorrectness, getCompleteResponseDetails } from './utils.js';\n\nconst log = debug('pie-elements:image-cloze-association:controller');\n\nexport const normalize = (question) => ({ ...defaults, ...question });\n\nexport const model = (question, session, env) => {\n const questionNormalized = normalize(question);\n const questionCamelized = camelizeKeys(questionNormalized);\n\n return new Promise((resolve) => {\n const shouldIncludeCorrectResponse = env.mode === 'evaluate';\n\n const {\n responseAreasToBeFilled,\n possibleResponses: completeResponses,\n hasUnplacedChoices,\n } = getCompleteResponseDetails(questionCamelized.validation, questionCamelized.possibleResponses);\n\n const out = {\n disabled: env.mode !== 'gather',\n mode: env.mode,\n ...questionCamelized,\n responseCorrect: shouldIncludeCorrectResponse ? getScore(questionCamelized, session) === 1 : undefined,\n validation: shouldIncludeCorrectResponse ? questionCamelized.validation : undefined,\n responseAreasToBeFilled,\n completeResponses,\n hasUnplacedChoices,\n };\n\n if (questionNormalized.shuffle) {\n out.possibleResponses = shuffle(questionNormalized.possible_responses);\n }\n\n if (env.role === 'instructor' && (env.mode === 'view' || env.mode === 'evaluate')) {\n out.teacherInstructions = questionCamelized.teacherInstructionsEnabled\n ? questionCamelized.teacherInstructions\n : null;\n out.rationale = questionCamelized.rationale ? questionCamelized.rationale : null;\n } else {\n out.teacherInstructions = null;\n out.rationale = null;\n }\n\n resolve(out);\n });\n};\n\nexport const isResponseCorrect = (correctResponses, session) => {\n const responses = cloneDeep(correctResponses);\n let isCorrect = true;\n let totalValidResponses = 0;\n\n if (!session || isEmpty(session)) {\n return false;\n }\n\n responses.forEach((value) => (totalValidResponses += (value.images || []).length));\n\n if (session.answers && totalValidResponses === session.answers.length) {\n session.answers.forEach((answer) => {\n const index = (responses[answer.containerIndex]?.images || []).indexOf(answer.value);\n\n if (index >= 0) {\n // remove response from correct responses array to ensure that duplicates are evaluated correctly\n responses[answer.containerIndex].images.splice(index, 1);\n } else {\n isCorrect = false;\n }\n });\n } else {\n isCorrect = false;\n }\n\n return isCorrect;\n};\n\n// This applies for correct responses that have empty values\nconst keepNonEmptyResponses = (responses) => {\n const filtered = responses.filter((response) => response.images && response.images.length);\n return cloneDeep(filtered);\n};\n\n// This applies for items that don't support partial scoring.\nconst isDefaultOrAltResponseCorrect = (question, session) => {\n const {\n validation: { altResponses },\n } = question;\n let {\n validation: {\n validResponse: { value },\n },\n } = question;\n\n let isCorrect = isResponseCorrect(value, session);\n\n // Look for correct answers in alternate responses.\n if (!isCorrect && altResponses && altResponses.length) {\n altResponses.forEach((altResponse) => {\n if (isResponseCorrect(altResponse.value, session)) {\n isCorrect = true;\n }\n });\n }\n return isCorrect;\n};\n\n// Deduct only the items that exceeded the maximum valid response per container.\nconst getDeductionPerContainer = (containerIndex, answers, valid) => {\n const totalStack = answers.filter((item) => item.containerIndex === containerIndex);\n const incorrectStack = totalStack.filter((item) => !item.isCorrect);\n const maxValid = (valid.value[containerIndex].images || []).length;\n\n if (totalStack.length > maxValid) {\n const ignored = totalStack.length - maxValid;\n return incorrectStack.slice(-ignored);\n }\n return [];\n};\n\nexport const getPartialScore = (question, session) => {\n const {\n validation: { validResponse },\n maxResponsePerZone,\n } = question;\n let correctAnswers = 0;\n let incorrectAnswers = 0;\n let possibleResponses = 0;\n\n if (!session || isEmpty(session)) {\n return 0;\n }\n\n validResponse.value.forEach((value) => (possibleResponses += (value.images || []).length));\n\n if (session.answers && session.answers.length) {\n const all = getAllUniqueCorrectness(session.answers, validResponse.value);\n correctAnswers = all.filter((item) => item.isCorrect).length;\n incorrectAnswers = all.filter((item) => !item.isCorrect).length;\n\n // deduction rules: https://docs.google.com/document/d/1Oprm8Qs5fg_Dwoj2pNpsfu4D63QgCZgvcqTgeaVel7I/edit\n session.answers.forEach((answer) => {\n if (maxResponsePerZone > 1) {\n const deductionList = getDeductionPerContainer(answer.containerIndex, all, validResponse);\n\n if (deductionList.length) {\n deductionList.forEach((item) => {\n if (item.id === answer.id) {\n correctAnswers -= 1;\n }\n });\n }\n }\n });\n\n if (!maxResponsePerZone || maxResponsePerZone <= 1) {\n correctAnswers -= incorrectAnswers;\n }\n } else {\n correctAnswers = 0;\n }\n // negative values will implicitly make the score equal to zero\n correctAnswers = correctAnswers < 0 ? 0 : correctAnswers;\n\n // use length of validResponse since some containers can be left empty\n const nonEmptyResponses = keepNonEmptyResponses(validResponse.value);\n const denominator = maxResponsePerZone > 1 ? possibleResponses : (nonEmptyResponses || []).length;\n const str = (correctAnswers / denominator).toFixed(2);\n\n return parseFloat(str);\n};\n\nconst getScore = (config, session, env = {}) => {\n const isPartialScoring = partialScoring.enabled(config, env);\n const correct = isDefaultOrAltResponseCorrect(config, session);\n\n return isPartialScoring ? getPartialScore(config, session) : correct ? 1 : 0;\n};\n\n/**\n * Generates detailed trace log for scoring evaluation\n * @param {Object} model - the question model\n * @param {Object} session - the student session\n * @param {Object} env - the environment\n * @returns {Array} traceLog - array of trace messages\n */\nexport const getLogTrace = (model, session, env) => {\n const traceLog = [];\n const { answers } = session || {};\n \n const validResponse = model.validation?.validResponse?.value || [];\n const totalContainers = validResponse.length;\n traceLog.push(`${totalContainers} placement container(s) defined in this question.`);\n\n if (answers && answers.length > 0) {\n traceLog.push(`Student placed ${answers.length} image(s) into placement containers.`);\n \n const answersByContainer = {};\n answers.forEach((answer) => {\n if (!answersByContainer[answer.containerIndex]) {\n answersByContainer[answer.containerIndex] = [];\n }\n answersByContainer[answer.containerIndex].push(answer.value);\n });\n \n validResponse.forEach((container, containerIndex) => {\n const correctImages = container.images || [];\n const studentImages = answersByContainer[containerIndex] || [];\n \n if (correctImages.length > 0) {\n if (studentImages.length === 0) {\n traceLog.push(`Container ${containerIndex + 1}: student left empty (should contain ${correctImages.length} image(s)).`);\n } else {\n const correctCount = studentImages.filter(img => correctImages.includes(img)).length;\n const incorrectCount = studentImages.length - correctCount;\n \n if (correctCount > 0 && incorrectCount === 0) {\n traceLog.push(`Container ${containerIndex + 1}: student placed ${correctCount} correct image(s).`);\n } else if (correctCount === 0 && incorrectCount > 0) {\n traceLog.push(`Container ${containerIndex + 1}: student placed ${incorrectCount} incorrect image(s).`);\n } else {\n traceLog.push(`Container ${containerIndex + 1}: student placed ${correctCount} correct and ${incorrectCount} incorrect image(s).`);\n }\n }\n }\n });\n } else {\n traceLog.push('Student did not place any images into placement containers.');\n }\n\n const altResponses = model.validation?.altResponses || [];\n if (altResponses.length > 0) {\n traceLog.push(`${altResponses.length} alternate response combination(s) are accepted for this question.`);\n }\n\n const partialScoringEnabled = partialScoring.enabled(model, env);\n const scoringMethod = partialScoringEnabled ? 'partial scoring' : 'all-or-nothing scoring';\n traceLog.push(`Score calculated using ${scoringMethod}.`);\n\n const score = getScore(model, session, env);\n traceLog.push(`Final score: ${score}.`);\n\n return traceLog;\n}\n\nexport const outcome = (config, session, env = {}) => {\n return new Promise((resolve) => {\n log('outcome...');\n if (!session || isEmpty(session)) {\n resolve({ \n score: 0, \n empty: true, \n traceLog: ['Student did not place any images into placement containers. Score is 0.'] \n });\n } else {\n const configCamelized = camelizeKeys(config);\n const traceLog = getLogTrace(configCamelized, session, env);\n const score = getScore(configCamelized, session, env);\n \n resolve({ \n score, \n empty: false,\n traceLog \n });\n }\n });\n};\n\nexport const createCorrectResponseSession = (question, env) => {\n return new Promise((resolve) => {\n if (env.mode !== 'evaluate' && env.role === 'instructor') {\n const {\n validation: {\n valid_response: { value },\n },\n } = question;\n const answers = [];\n\n if (value) {\n value.forEach((container, i) => {\n (container.images || []).forEach((v) => {\n answers.push({\n value: v,\n containerIndex: i,\n });\n });\n });\n }\n\n resolve({\n answers,\n id: '1',\n });\n } else {\n resolve(null);\n }\n });\n};\n\n// remove all html tags\nconst getInnerText = (html) => (html || '').replaceAll(/<[^>]*>/g, '');\n\n// remove all html tags except img, iframe and source tag for audio\nconst getContent = (html) => (html || '').replace(/(<(?!img|iframe|source)([^>]+)>)/gi, '');\n\nexport const validate = (model = {}, config = {}) => {\n const errors = {};\n\n ['teacherInstructions'].forEach((field) => {\n if (config[field]?.required && !getContent(model[field])) {\n errors[field] = 'This field is required.';\n }\n });\n\n return errors;\n};\n"],"mappings":";;;kEACI,IAAI,OAAO,gBA8CX,IAAoB,kBA9CY,GAAG,MAAM;CAC5C,IAAI,IAAI,CAAC;CACT,KAAK,IAAI,KAAK,GAAG,EAAE,GAAG,GAAG;EACxB,KAAK,EAAE;EACP,YAAY,CAAC;CACd,CAAC;CACD,OAAO,KAAK,EAAE,GAAG,OAAO,aAAa,EAAE,OAAO,SAAS,CAAC,GAAG;AAC5D,EAuCwB,CAAE,EAAE,eAAe,EAAE,CAAC;AAC9C,SAAS,EAAE,GAAG,GAAG,GAAG;CACnB,OAAO,GAAG,mBAAmB,CAAC,KAAK,GAAG,mBAAmB,CAAC,IAAI,CAAC,IAAI,OAAO,KAAK,aAAa;AAC7F;;;ACxCA,IAAA,IAAe;CACb,WAAW;CACX,kBAAkB;CAClB,4BAA4B;CAC5B,qBAAqB;CACrB,4BAA4B;AAC9B,GCJM,KAAqB,GAAS,OACjC,KAAW,CAAC,EAAA,CAAG,KAAK,OAAY;CAC/B,GAAG;CACH,YAAa,EAAU,EAAO,mBAAmB,EAAU,EAAO,eAAe,CAAC,UAAW,CAAC,EAAA,CAAG,SAC/F,EAAO,KACT;AACF,EAAE,GAEE,KAAkB,GAAQ,OAC5B,EAAS,EAAO,mBAAmB,EAAS,EAAO,eAAe,CAAC,UAAW,CAAC,EAAA,CAAG,QACjF,MAAQ,MAAQ,EAAO,KAC1B,GAEW,KAA2B,GAAS,MAAmB;CAClE,IAAI,IAAiB,EAAkB,GAAS,CAAc;CAyB9D,OAvBA,EAAQ,SAAS,MAAY;EAC3B,IAAM,IAAgB,EAAQ,QAC3B,MAAY,EAAQ,UAAU,EAAQ,SAAS,EAAQ,mBAAmB,EAAQ,cACrF;EAEA,AAAI,EAAc,SAAS,MAEzB,EAAc,MAAM,GAEpB,EAAc,SAAS,GAAO,MAAU;GACtC,KAAkB,KAAkB,CAAC,EAAA,CAAG,KAAK,MAAgB;IAC3D,IAAI,EAAY,OAAO,EAAM,IAAI;KAC/B,IAAI,IAAQ,EAAe,GAAa,CAAc;KACtD,OAAO;MACL,GAAG;MACH,WAAW,EAAM,SAAS,IAAQ;KACpC;IACF;IACA,OAAO;GACT,CAAC;EACH,CAAC;CAEL,CAAC,GACM;AACT,GAIa,KAA8B,GAAY,MAAe;CACpE,IAAM,KAAiB,OAAc,GAAU,SAAS,CAAC,EAAA,CAAG,KAAK,MAAc,EAAU,MAAM,GACzF,KAA4B,OAAe,KAAa,CAAC,EAAA,CAAG,QAAQ,MAAW,EAAO,MAAM,CAAC,CAAC,QAE9F,EAAE,kBAAe,oBAAiB,KAAc,CAAC,GACjD,IAAqB,EAAc,CAAa,GAChD,IAAoB,CAAC,EAAmB,KAAK,CAAC,GAChD,IAA0B,EAAyB,CAAkB;CAEzE,CAAC,KAAgB,CAAC,EAAA,CAAG,SAAS,MAAgB;EAC5C,IAAM,IAAwB,EAAc,CAAW,GACjD,IAAsB,EAAyB,CAAqB;EAG1E,AAFA,EAAkB,KAAK,EAAsB,KAAK,CAAC,GAE/C,IAAsB,MACxB,IAA0B;CAE9B,CAAC;CAGD,IAAM,IAAqB,EAAkB,MAC1C,MAAa,CAAC,EAAW,OAAO,MAAQ,EAAS,SAAS,CAAG,CAAC,CACjE;CAEA,OAAO;EAAE;EAAyB;EAAmB;CAAmB;AAC1E,GCrEM,EAAE,oBAAiB,EAAA,SAOnB,KAAA,GAAA,EAAA,QAAA,CAAY,iDAAiD,GAEtD,KAAa,OAAc;CAAE,GAAG;CAAU,GAAG;AAAS,IAEtD,KAAS,GAAU,GAAS,MAAQ;CAC/C,IAAM,IAAqB,EAAU,CAAQ,GACvC,IAAoB,EAAa,CAAkB;CAEzD,OAAO,IAAI,SAAS,MAAY;EAC9B,IAAM,IAA+B,EAAI,SAAS,YAE5C,EACJ,4BACA,mBAAmB,GACnB,0BACE,EAA2B,EAAkB,YAAY,EAAkB,iBAAiB,GAE1F,IAAM;GACV,UAAU,EAAI,SAAS;GACvB,MAAM,EAAI;GACV,GAAG;GACH,iBAAiB,IAA+B,EAAS,GAAmB,CAAO,MAAM,IAAI,KAAA;GAC7F,YAAY,IAA+B,EAAkB,aAAa,KAAA;GAC1E;GACA;GACA;EACF;EAgBA,AAdI,EAAmB,YACrB,EAAI,oBAAoB,EAAQ,EAAmB,kBAAkB,IAGnE,EAAI,SAAS,iBAAiB,EAAI,SAAS,UAAU,EAAI,SAAS,eACpE,EAAI,sBAAsB,EAAkB,6BACxC,EAAkB,sBAClB,MACJ,EAAI,YAAY,EAAkB,YAAY,EAAkB,YAAY,SAE5E,EAAI,sBAAsB,MAC1B,EAAI,YAAY,OAGlB,EAAQ,CAAG;CACb,CAAC;AACH,GAEa,KAAqB,GAAkB,MAAY;CAC9D,IAAM,IAAY,EAAU,CAAgB,GACxC,IAAY,IACZ,IAAsB;CAuB1B,OArBI,CAAC,KAAW,EAAQ,CAAO,IACtB,MAGT,EAAU,SAAS,MAAW,MAAwB,EAAM,UAAU,CAAC,EAAA,CAAG,MAAO,GAE7E,EAAQ,WAAW,MAAwB,EAAQ,QAAQ,SAC7D,EAAQ,QAAQ,SAAS,MAAW;EAClC,IAAM,KAAS,EAAU,EAAO,eAAe,EAAE,UAAU,CAAC,EAAA,CAAG,QAAQ,EAAO,KAAK;EAEnF,AAAI,KAAS,IAEX,EAAU,EAAO,eAAe,CAAC,OAAO,OAAO,GAAO,CAAC,IAEvD,IAAY;CAEhB,CAAC,IAED,IAAY,IAGP;AACT,GAGM,KAAyB,MAEtB,EADU,EAAU,QAAQ,MAAa,EAAS,UAAU,EAAS,OAAO,MAClE,CAAQ,GAIrB,KAAiC,GAAU,MAAY;CAC3D,IAAM,EACJ,YAAY,EAAE,sBACZ,GACA,EACF,YAAY,EACV,eAAe,EAAE,iBAEjB,GAEA,IAAY,EAAkB,GAAO,CAAO;CAUhD,OAPI,CAAC,KAAa,KAAgB,EAAa,UAC7C,EAAa,SAAS,MAAgB;EACpC,AAAI,EAAkB,EAAY,OAAO,CAAO,MAC9C,IAAY;CAEhB,CAAC,GAEI;AACT,GAGM,KAA4B,GAAgB,GAAS,MAAU;CACnE,IAAM,IAAa,EAAQ,QAAQ,MAAS,EAAK,mBAAmB,CAAc,GAC5E,IAAiB,EAAW,QAAQ,MAAS,CAAC,EAAK,SAAS,GAC5D,KAAY,EAAM,MAAM,EAAe,CAAC,UAAU,CAAC,EAAA,CAAG;CAE5D,IAAI,EAAW,SAAS,GAAU;EAChC,IAAM,IAAU,EAAW,SAAS;EACpC,OAAO,EAAe,MAAM,CAAC,CAAO;CACtC;CACA,OAAO,CAAC;AACV,GAEa,KAAmB,GAAU,MAAY;CACpD,IAAM,EACJ,YAAY,EAAE,oBACd,0BACE,GACA,IAAiB,GACjB,IAAmB,GACnB,IAAoB;CAExB,IAAI,CAAC,KAAW,EAAQ,CAAO,GAC7B,OAAO;CAKT,IAFA,EAAc,MAAM,SAAS,MAAW,MAAsB,EAAM,UAAU,CAAC,EAAA,CAAG,MAAO,GAErF,EAAQ,WAAW,EAAQ,QAAQ,QAAQ;EAC7C,IAAM,IAAM,EAAwB,EAAQ,SAAS,EAAc,KAAK;EAmBxE,AAlBA,IAAiB,EAAI,QAAQ,MAAS,EAAK,SAAS,CAAC,CAAC,QACtD,IAAmB,EAAI,QAAQ,MAAS,CAAC,EAAK,SAAS,CAAC,CAAC,QAGzD,EAAQ,QAAQ,SAAS,MAAW;GAClC,IAAI,IAAqB,GAAG;IAC1B,IAAM,IAAgB,EAAyB,EAAO,gBAAgB,GAAK,CAAa;IAExF,AAAI,EAAc,UAChB,EAAc,SAAS,MAAS;KAC9B,AAAI,EAAK,OAAO,EAAO,MACrB;IAEJ,CAAC;GAEL;EACF,CAAC,IAEG,CAAC,KAAsB,KAAsB,OAC/C,KAAkB;CAEtB,OACE,IAAiB;CAGnB,IAAiB,IAAiB,IAAI,IAAI;CAG1C,IAAM,IAAoB,EAAsB,EAAc,KAAK,GAC7D,IAAc,IAAqB,IAAI,KAAqB,KAAqB,CAAC,EAAA,CAAG,QACrF,KAAO,IAAiB,EAAA,CAAa,QAAQ,CAAC;CAEpD,OAAO,WAAW,CAAG;AACvB,GAEM,KAAY,GAAQ,GAAS,IAAM,CAAC,MAAM;CAC9C,IAAM,IAAmB,EAAe,QAAQ,GAAQ,CAAG,GACrD,IAAU,EAA8B,GAAQ,CAAO;CAE7D,OAAO,IAAmB,EAAgB,GAAQ,CAAO,IAAI;AAC/D,GASa,KAAe,GAAO,GAAS,MAAQ;CAClD,IAAM,IAAW,CAAC,GACZ,EAAE,eAAY,KAAW,CAAC,GAE1B,IAAgB,EAAM,YAAY,eAAe,SAAS,CAAC,GAC3D,IAAkB,EAAc;CAGtC,IAFA,EAAS,KAAK,GAAG,EAAgB,kDAAkD,GAE/E,KAAW,EAAQ,SAAS,GAAG;EACjC,EAAS,KAAK,kBAAkB,EAAQ,OAAO,qCAAqC;EAEpF,IAAM,IAAqB,CAAC;EAQ5B,AAPA,EAAQ,SAAS,MAAW;GAI1B,AAHK,EAAmB,EAAO,oBAC7B,EAAmB,EAAO,kBAAkB,CAAC,IAE/C,EAAmB,EAAO,eAAe,CAAC,KAAK,EAAO,KAAK;EAC7D,CAAC,GAED,EAAc,SAAS,GAAW,MAAmB;GACnD,IAAM,IAAgB,EAAU,UAAU,CAAC,GACrC,IAAgB,EAAmB,MAAmB,CAAC;GAE7D,IAAI,EAAc,SAAS,GACzB,IAAI,EAAc,WAAW,GAC3B,EAAS,KAAK,aAAa,IAAiB,EAAE,uCAAuC,EAAc,OAAO,YAAY;QACjH;IACL,IAAM,IAAe,EAAc,QAAO,MAAO,EAAc,SAAS,CAAG,CAAC,CAAC,CAAC,QACxE,IAAiB,EAAc,SAAS;IAE9C,AAAI,IAAe,KAAK,MAAmB,IACzC,EAAS,KAAK,aAAa,IAAiB,EAAE,mBAAmB,EAAa,mBAAmB,IACxF,MAAiB,KAAK,IAAiB,IAChD,EAAS,KAAK,aAAa,IAAiB,EAAE,mBAAmB,EAAe,qBAAqB,IAErG,EAAS,KAAK,aAAa,IAAiB,EAAE,mBAAmB,EAAa,eAAe,EAAe,qBAAqB;GAErI;EAEJ,CAAC;CACH,OACE,EAAS,KAAK,6DAA6D;CAG7E,IAAM,IAAe,EAAM,YAAY,gBAAgB,CAAC;CACxD,AAAI,EAAa,SAAS,KACxB,EAAS,KAAK,GAAG,EAAa,OAAO,mEAAmE;CAI1G,IAAM,IADwB,EAAe,QAAQ,GAAO,CACtC,IAAwB,oBAAoB;CAClE,EAAS,KAAK,0BAA0B,EAAc,EAAE;CAExD,IAAM,IAAQ,EAAS,GAAO,GAAS,CAAG;CAG1C,OAFA,EAAS,KAAK,gBAAgB,EAAM,EAAE,GAE/B;AACT,GAEa,KAAW,GAAQ,GAAS,IAAM,CAAC,MACvC,IAAI,SAAS,MAAY;CAE9B,IADA,EAAI,YAAY,GACZ,CAAC,KAAW,EAAQ,CAAO,GAC7B,EAAQ;EACN,OAAO;EACP,OAAO;EACP,UAAU,CAAC,yEAAyE;CACtF,CAAC;MACI;EACL,IAAM,IAAkB,EAAa,CAAM,GACrC,IAAW,EAAY,GAAiB,GAAS,CAAG;EAG1D,EAAQ;GACN,OAHY,EAAS,GAAiB,GAAS,CAG/C;GACA,OAAO;GACP;EACF,CAAC;CACH;AACF,CAAC,GAGU,KAAgC,GAAU,MAC9C,IAAI,SAAS,MAAY;CAC9B,IAAI,EAAI,SAAS,cAAc,EAAI,SAAS,cAAc;EACxD,IAAM,EACJ,YAAY,EACV,gBAAgB,EAAE,iBAElB,GACE,IAAU,CAAC;EAajB,AAXI,KACF,EAAM,SAAS,GAAW,MAAM;GAC9B,CAAC,EAAU,UAAU,CAAC,EAAA,CAAG,SAAS,MAAM;IACtC,EAAQ,KAAK;KACX,OAAO;KACP,gBAAgB;IAClB,CAAC;GACH,CAAC;EACH,CAAC,GAGH,EAAQ;GACN;GACA,IAAI;EACN,CAAC;CACH,OACE,EAAQ,IAAI;AAEhB,CAAC,GAOG,KAAc,OAAU,KAAQ,GAAA,CAAI,QAAQ,sCAAsC,EAAE,GAE7E,KAAY,IAAQ,CAAC,GAAG,IAAS,CAAC,MAAM;CACnD,IAAM,IAAS,CAAC;CAQhB,OANA,CAAC,qBAAqB,CAAC,CAAC,SAAS,MAAU;EACzC,AAAI,EAAO,EAAM,EAAE,YAAY,CAAC,EAAW,EAAM,EAAM,MACrD,EAAO,KAAS;CAEpB,CAAC,GAEM;AACT"}
@@ -1,11 +1,11 @@
1
1
  import { a as e, f as t, x as n } from "../dist-oxliJ767.js";
2
- import { Bt as r, Dt as i, F as a, H as o, Lt as s, Rt as c, a as l, b as u, c as d, d as f, f as p, ft as m, ht as h, i as g, k as _, l as v, n as y, o as b, pt as x, r as S, s as C, t as w, u as T, v as E, x as D, y as O } from "../Check-DrKXQGXL.js";
2
+ import { Dt as r, F as i, H as a, Lt as o, Rt as s, Vt as c, a as l, b as u, c as d, d as f, f as p, ft as m, ht as h, i as g, k as _, l as v, n as y, o as b, pt as x, r as S, s as C, t as w, u as T, v as E, x as D, y as O } from "../Check-BzY2qRmU.js";
3
3
  import { t as ee } from "../humps-vcapGabG.js";
4
4
  import k, { Component as A, useEffect as te, useRef as j, useState as M } from "react";
5
5
  import { createRoot as N } from "react-dom/client";
6
6
  import { jsx as P, jsxs as F } from "react/jsx-runtime";
7
7
  //#region ../../lib-react/icons/dist/correct-response-icon.js
8
- var I = /* @__PURE__ */ n(s(), 1), L = ({ bgFill: e, fgFill: t }) => /* @__PURE__ */ F("svg", {
8
+ var I = /* @__PURE__ */ n(o(), 1), L = ({ bgFill: e, fgFill: t }) => /* @__PURE__ */ F("svg", {
9
9
  preserveAspectRatio: "xMinYMin meet",
10
10
  version: "1.1",
11
11
  viewBox: "-283 359 34 35",
@@ -163,22 +163,22 @@ var le = h("div")(({ theme: e }) => ({
163
163
  userSelect: "none",
164
164
  width: "100%",
165
165
  height: "100%",
166
- background: c.white(),
166
+ background: s.white(),
167
167
  transition: "background-color 200ms linear, border-color 200ms linear",
168
168
  boxSizing: "border-box",
169
169
  display: "grid",
170
170
  gridRowGap: e.spacing(1),
171
171
  gridColumnGap: e.spacing(1),
172
172
  padding: e.spacing(1),
173
- border: `2px dashed ${c.black()}`
173
+ border: `2px dashed ${s.black()}`
174
174
  },
175
175
  "&.placeholderDisabled": {
176
176
  boxShadow: "none",
177
- background: c.white()
177
+ background: s.white()
178
178
  },
179
179
  "&.over": {
180
- border: `1px solid ${c.border()}`,
181
- backgroundColor: c.backgroundDark()
180
+ border: `1px solid ${s.border()}`,
181
+ backgroundColor: s.backgroundDark()
182
182
  },
183
183
  "&.board": {
184
184
  padding: e.spacing(1),
@@ -189,7 +189,7 @@ var le = h("div")(({ theme: e }) => ({
189
189
  justifyContent: "center",
190
190
  overflow: "hidden",
191
191
  touchAction: "none",
192
- backgroundColor: c.surface()
192
+ backgroundColor: s.surface()
193
193
  },
194
194
  "&.categorizeBoard": {
195
195
  padding: e.spacing(.5),
@@ -200,19 +200,19 @@ var le = h("div")(({ theme: e }) => ({
200
200
  justifyContent: "center",
201
201
  overflow: "hidden",
202
202
  touchAction: "none",
203
- backgroundColor: c.surface()
203
+ backgroundColor: s.surface()
204
204
  },
205
205
  "&.verticalPool": {
206
206
  display: "flex",
207
207
  flexFlow: "column wrap"
208
208
  }
209
209
  })), ue = (e) => {
210
- let { children: t, className: n, isOver: r, type: i, grid: a, disabled: o, choiceBoard: s, isCategorize: l, isVerticalPool: u, minHeight: d, extraStyles: f } = e, p = ce("placeholder", o && "placeholderDisabled", r && "over", i, n), m = {};
210
+ let { children: t, className: n, isOver: r, type: i, grid: a, disabled: o, choiceBoard: c, isCategorize: l, isVerticalPool: u, minHeight: d, extraStyles: f } = e, p = ce("placeholder", o && "placeholderDisabled", r && "over", i, n), m = {};
211
211
  if (a && a.columns && (m.gridTemplateColumns = `repeat(${a.columns}, 1fr)`), a && a.rows) {
212
212
  let e = a.rowsRepeatValue || "1fr";
213
213
  m.gridTemplateRows = `repeat(${a.rows}, ${e})`;
214
214
  }
215
- i === "choice" && (m.border = `1px solid ${c.borderLight()}`, m.background = c.surface());
215
+ i === "choice" && (m.border = `1px solid ${s.borderLight()}`, m.background = s.surface());
216
216
  let h = l ? "categorizeBoard" : "board";
217
217
  return /* @__PURE__ */ P(le, {
218
218
  style: {
@@ -220,7 +220,7 @@ var le = h("div")(({ theme: e }) => ({
220
220
  minHeight: d,
221
221
  ...f
222
222
  },
223
- className: ce(s ? h : p, u && "verticalPool"),
223
+ className: ce(c ? h : p, u && "verticalPool"),
224
224
  children: t
225
225
  });
226
226
  };
@@ -329,7 +329,7 @@ me.propTypes = {
329
329
  };
330
330
  //#endregion
331
331
  //#region ../../../node_modules/.bun/@mui+icons-material@7.3.11+44ccb211c00abd9d/node_modules/@mui/icons-material/esm/NotInterested.js
332
- var he = o(/*#__PURE__*/ P("path", { d: "M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2m0 18c-4.42 0-8-3.58-8-8 0-1.85.63-3.55 1.69-4.9L16.9 18.31C15.55 19.37 13.85 20 12 20m6.31-3.1L7.1 5.69C8.45 4.63 10.15 4 12 4c4.42 0 8 3.58 8 8 0 1.85-.63 3.55-1.69 4.9" }), "NotInterested"), ge = "height ease-in 300ms, opacity ease-in 300ms", _e = h("div")(() => ({
332
+ var he = a(/*#__PURE__*/ P("path", { d: "M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2m0 18c-4.42 0-8-3.58-8-8 0-1.85.63-3.55 1.69-4.9L16.9 18.31C15.55 19.37 13.85 20 12 20m6.31-3.1L7.1 5.69C8.45 4.63 10.15 4 12 4c4.42 0 8 3.58 8 8 0 1.85-.63 3.55-1.69 4.9" }), "NotInterested"), ge = "height ease-in 300ms, opacity ease-in 300ms", _e = h("div")(() => ({
333
333
  position: "relative",
334
334
  height: 0,
335
335
  overflow: "hidden",
@@ -1941,7 +1941,7 @@ var mt = pt(u, "Readable") || pt(_t.Readable, "Readable"), ht = p, gt = ht.defau
1941
1941
  minWidth: "140px",
1942
1942
  alignSelf: "center",
1943
1943
  verticalAlign: "middle",
1944
- color: `var(--correct-answer-toggle-label-color, ${c.text()})`,
1944
+ color: `var(--correct-answer-toggle-label-color, ${s.text()})`,
1945
1945
  fontWeight: "normal",
1946
1946
  ...yt
1947
1947
  })), Ct = h("div")(() => ({
@@ -2048,16 +2048,16 @@ var mt = pt(u, "Readable") || pt(_t.Readable, "Readable"), ht = p, gt = ht.defau
2048
2048
  })
2049
2049
  });
2050
2050
  }
2051
- }, Et = o(/*#__PURE__*/ P("path", { d: "M19 6.41 17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z" }), "Close"), Dt = h("svg")(() => ({
2052
- "&.correctEmpty": { color: c.correct() },
2051
+ }, Et = a(/*#__PURE__*/ P("path", { d: "M19 6.41 17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z" }), "Close"), Dt = h("svg")(() => ({
2052
+ "&.correctEmpty": { color: s.correct() },
2053
2053
  "&.correctFilled": {
2054
- color: c.background(),
2055
- backgroundColor: c.correct()
2054
+ color: s.background(),
2055
+ backgroundColor: s.correct()
2056
2056
  },
2057
- "&.incorrectEmpty": { color: c.incorrect() },
2057
+ "&.incorrectEmpty": { color: s.incorrect() },
2058
2058
  "&.incorrectFilled": {
2059
- color: c.background(),
2060
- backgroundColor: c.incorrect()
2059
+ color: s.background(),
2060
+ backgroundColor: s.incorrect()
2061
2061
  }
2062
2062
  })), Ot = (e, t) => `${e ? "correct" : "incorrect"}${t ? "Filled" : "Empty"}`, kt = ({ containerStyle: e, isCorrect: t, filled: n }) => {
2063
2063
  let r = t ? w : Et, i = t !== void 0, a = i ? Ot(t, n) : "";
@@ -2098,8 +2098,8 @@ At.propTypes = {
2098
2098
  //#region src/delivery/possible-response.tsx
2099
2099
  var jt = h("div")(() => ({
2100
2100
  position: "relative",
2101
- backgroundColor: c.white(),
2102
- border: `1px solid ${c.borderDark()}`,
2101
+ backgroundColor: s.white(),
2102
+ border: `1px solid ${s.borderDark()}`,
2103
2103
  display: "flex",
2104
2104
  alignItems: "center",
2105
2105
  justifyContent: "center",
@@ -2112,20 +2112,20 @@ var jt = h("div")(() => ({
2112
2112
  },
2113
2113
  "&.answerChoiceTransparency": {
2114
2114
  border: "none",
2115
- backgroundColor: `${c.transparent()}`,
2116
- "&:hover": { border: `1px solid ${c.borderDark()}` }
2115
+ backgroundColor: `${s.transparent()}`,
2116
+ "&:hover": { border: `1px solid ${s.borderDark()}` }
2117
2117
  },
2118
- "&.baseCorrect": { border: `2px solid ${c.correct()} !important` },
2119
- "&.baseIncorrect": { border: `2px solid ${c.incorrect()} !important` },
2118
+ "&.baseCorrect": { border: `2px solid ${s.correct()} !important` },
2119
+ "&.baseIncorrect": { border: `2px solid ${s.incorrect()} !important` },
2120
2120
  "&.selected": {
2121
- border: `2px solid ${c.buttonFocusOutline()}`,
2121
+ border: `2px solid ${s.buttonFocusOutline()}`,
2122
2122
  "& > *": { opacity: .7 }
2123
2123
  }
2124
2124
  })), Mt = h(At)(() => ({
2125
2125
  cursor: "grab",
2126
- backgroundColor: c.background(),
2126
+ backgroundColor: s.background(),
2127
2127
  "&.hiddenSpan": { visibility: "hidden" }
2128
- })), Z = ({ canDrag: e, containerStyle: t, data: n, onDragBegin: r, answerChoiceTransparency: a, isOverlay: o, selectedResponse: s, onSelectClick: c, onPlacementClick: l }) => {
2128
+ })), Z = ({ canDrag: e, containerStyle: t, data: n, onDragBegin: i, answerChoiceTransparency: a, isOverlay: o, selectedResponse: s, onSelectClick: c, onPlacementClick: l }) => {
2129
2129
  let u = j(null), f = j(null), { setNodeRef: p, attributes: m, listeners: h, isDragging: g } = d({
2130
2130
  id: `possible-response-${n.id}`,
2131
2131
  data: {
@@ -2145,7 +2145,7 @@ var jt = h("div")(() => ({
2145
2145
  clearTimeout(f.current);
2146
2146
  }, x = (t) => {
2147
2147
  t.preventDefault(), f.current = setTimeout(() => {
2148
- e && u.current && r(n);
2148
+ e && u.current && i(n);
2149
2149
  }, 500);
2150
2150
  };
2151
2151
  te(() => {
@@ -2159,12 +2159,12 @@ var jt = h("div")(() => ({
2159
2159
  position: "absolute",
2160
2160
  bottom: "3px",
2161
2161
  right: "3px"
2162
- }, w = S === !0 ? "baseCorrect" : S === !1 ? "baseIncorrect" : void 0, T = /<img[^>]+src="([^">]+)"/.test(n.value), E = i({
2162
+ }, w = S === !0 ? "baseCorrect" : S === !1 ? "baseIncorrect" : void 0, T = /<img[^>]+src="([^">]+)"/.test(n.value), E = r({
2163
2163
  answerChoiceTransparency: a && !g,
2164
2164
  [w]: !!w,
2165
2165
  textAnswerChoiceStyle: !T && !o,
2166
2166
  selected: _ && !g
2167
- }), D = i({ hiddenSpan: n.hidden });
2167
+ }), D = r({ hiddenSpan: n.hidden });
2168
2168
  return /* @__PURE__ */ F(jt, {
2169
2169
  className: E,
2170
2170
  style: t,
@@ -2208,15 +2208,15 @@ var Nt = h("div")(() => ({
2208
2208
  position: "absolute",
2209
2209
  boxSizing: "border-box",
2210
2210
  "&.active": {
2211
- border: `2px solid ${c.text()}`,
2211
+ border: `2px solid ${s.text()}`,
2212
2212
  backgroundColor: "rgba(230, 242, 252, .8)"
2213
2213
  },
2214
- "&.dashed": { border: `2px dashed ${c.text()}` },
2214
+ "&.dashed": { border: `2px dashed ${s.text()}` },
2215
2215
  "&.is-over": {
2216
2216
  border: "1px solid rgb(158, 158, 158)",
2217
2217
  backgroundColor: "rgb(224, 224, 224)"
2218
2218
  }
2219
- })), Ft = ({ answers: e, canDrag: t, containerStyle: n, draggingElement: r, onDragAnswerBegin: a, onDragAnswerEnd: o, showDashedBorder: s, responseAreaFill: c, responseContainerPadding: l = "10px", imageDropTargetPadding: u, answerChoiceTransparency: d, maxResponsePerZone: f, onDrop: p, index: m, selectedResponse: h, onSelectClick: g, onPlacementClick: _ }) => {
2219
+ })), Ft = ({ answers: e, canDrag: t, containerStyle: n, draggingElement: i, onDragAnswerBegin: a, onDragAnswerEnd: o, showDashedBorder: s, responseAreaFill: c, responseContainerPadding: l = "10px", imageDropTargetPadding: u, answerChoiceTransparency: d, maxResponsePerZone: f, onDrop: p, index: m, selectedResponse: h, onSelectClick: g, onPlacementClick: _ }) => {
2220
2220
  let [y, b] = M(!1), [x, S] = M(!1), C = j(null), w = j(null), { setNodeRef: T, isOver: E } = v({
2221
2221
  id: `response-container-${m}`,
2222
2222
  data: {
@@ -2234,7 +2234,7 @@ var Nt = h("div")(() => ({
2234
2234
  e.removeEventListener("touchstart", t);
2235
2235
  };
2236
2236
  }, []);
2237
- let D = !!r.id, O = !!h, ee = i({
2237
+ let D = !!i.id, O = !!h, ee = r({
2238
2238
  "is-over": E || O && y && t,
2239
2239
  dashed: s && !D,
2240
2240
  active: D
@@ -2372,9 +2372,9 @@ var Rt = h("div")(({ theme: e }) => ({
2372
2372
  display: "flex",
2373
2373
  width: "fit-content",
2374
2374
  maxWidth: "100%",
2375
- "&.default": { border: `1px solid ${c.disabled()}` },
2376
- "&.correct": { border: `2px solid ${c.correct()}` },
2377
- "&.incorrect": { border: `2px solid ${c.incorrect()}` }
2375
+ "&.default": { border: `1px solid ${s.disabled()}` },
2376
+ "&.correct": { border: `2px solid ${s.correct()}` },
2377
+ "&.incorrect": { border: `2px solid ${s.incorrect()}` }
2378
2378
  })), zt = class extends k.Component {
2379
2379
  getClassname() {
2380
2380
  let { responseCorrect: e } = this.props, t;
@@ -2434,7 +2434,7 @@ zt.propTypes = {
2434
2434
  //#endregion
2435
2435
  //#region src/delivery/possible-responses.tsx
2436
2436
  var Bt = h("div")(({ theme: e }) => ({
2437
- backgroundColor: c.background(),
2437
+ backgroundColor: s.background(),
2438
2438
  margin: e.spacing(2),
2439
2439
  display: "flex",
2440
2440
  alignItems: "center",
@@ -2473,9 +2473,7 @@ Vt.propTypes = {
2473
2473
  onSelectClick: I.default.func,
2474
2474
  onPlacementClick: I.default.func
2475
2475
  };
2476
- //#endregion
2477
- //#region src/delivery/utils-correctness.ts
2478
- var Ht = ee(), Ut = (e, t) => (e || []).map((e) => ({
2476
+ var { camelizeKeys: Ht } = (/* @__PURE__ */ n(ee(), 1)).default, Ut = (e, t) => (e || []).map((e) => ({
2479
2477
  ...e,
2480
2478
  isCorrect: (t[e.containerIndex] && t[e.containerIndex].images || []).includes(e.value)
2481
2479
  })), Wt = (e, t) => (t[e.containerIndex].images || []).filter((t) => t === e.value), Gt = (e, t) => {
@@ -2496,7 +2494,7 @@ var Ht = ee(), Ut = (e, t) => (e || []).map((e) => ({
2496
2494
  }));
2497
2495
  }), n;
2498
2496
  }, Kt = (e, t) => {
2499
- let { validResponse: { value: n } = {} } = (0, Ht.camelizeKeys)(t);
2497
+ let { validResponse: { value: n } = {} } = Ht(t);
2500
2498
  return (n || []).reduce((t, n, r) => {
2501
2499
  let i = !!e.find((e) => e.containerIndex === r);
2502
2500
  return n.images = n.images || [], i ? t : [...t, {
@@ -2508,7 +2506,7 @@ var Ht = ee(), Ut = (e, t) => (e || []).map((e) => ({
2508
2506
  }];
2509
2507
  }, []);
2510
2508
  }, qt = (e, t) => {
2511
- let { validResponse: { value: n }, altResponses: r } = (0, Ht.camelizeKeys)(t), i = Gt(Ut(e, n), n);
2509
+ let { validResponse: { value: n }, altResponses: r } = Ht(t), i = Gt(Ut(e, n), n);
2512
2510
  return i.filter((e) => e.isCorrect).length < i.length && r && r.length ? (r || []).map((t) => {
2513
2511
  let n = t.value;
2514
2512
  return Gt(Ut(e, n), n);
@@ -2566,9 +2564,9 @@ function Q(e) {
2566
2564
  function $(e, t) {
2567
2565
  return !e || Q(e) ? e : Q(e.default) ? e.default : t && Q(e[t]) ? e[t] : t && Q(e[t]?.default) ? e[t].default : e;
2568
2566
  }
2569
- var Xt = $(_, "UiLayout") || $(tn.UiLayout, "UiLayout"), Zt = $(D, "PreviewPrompt") || $(tn.PreviewPrompt, "PreviewPrompt"), Qt = $(a, "Collapsible") || $(tn.Collapsible, "Collapsible"), $t = p, en = $t.default, tn = en && typeof en == "object" ? en : $t, { translator: nn } = dt, rn = () => Math.random().toString(36).substring(2) + (/* @__PURE__ */ new Date()).getTime().toString(36), an = 250, on = h(Xt)({
2570
- color: c.text(),
2571
- backgroundColor: c.background(),
2567
+ var Xt = $(_, "UiLayout") || $(tn.UiLayout, "UiLayout"), Zt = $(D, "PreviewPrompt") || $(tn.PreviewPrompt, "PreviewPrompt"), Qt = $(i, "Collapsible") || $(tn.Collapsible, "Collapsible"), $t = p, en = $t.default, tn = en && typeof en == "object" ? en : $t, { translator: nn } = dt, rn = () => Math.random().toString(36).substring(2) + (/* @__PURE__ */ new Date()).getTime().toString(36), an = 250, on = h(Xt)({
2568
+ color: s.text(),
2569
+ backgroundColor: s.background(),
2572
2570
  position: "relative",
2573
2571
  "& img": {
2574
2572
  maxWidth: "100%",
@@ -2963,7 +2961,7 @@ var hn = mn("data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAMCAgICAgMC
2963
2961
  updateAnswer: this.updateAnswer.bind(this)
2964
2962
  });
2965
2963
  this._root ||= N(this), this._root.render(e), queueMicrotask(() => {
2966
- r(this);
2964
+ c(this);
2967
2965
  });
2968
2966
  }
2969
2967
  }