alexsys-exam-renderer 0.1.0

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 (43) hide show
  1. package/dist/exam-session/examScoring.d.ts +39 -0
  2. package/dist/exam-session/examScoring.d.ts.map +1 -0
  3. package/dist/exam-session/examSessionTypes.d.ts +344 -0
  4. package/dist/exam-session/examSessionTypes.d.ts.map +1 -0
  5. package/dist/exam-session/interactions/CoinTableResponse.d.ts +9 -0
  6. package/dist/exam-session/interactions/CoinTableResponse.d.ts.map +1 -0
  7. package/dist/exam-session/interactions/ColorPenPicker.d.ts +13 -0
  8. package/dist/exam-session/interactions/ColorPenPicker.d.ts.map +1 -0
  9. package/dist/exam-session/interactions/DraftSheet.d.ts +9 -0
  10. package/dist/exam-session/interactions/DraftSheet.d.ts.map +1 -0
  11. package/dist/exam-session/interactions/DragMatch.d.ts +10 -0
  12. package/dist/exam-session/interactions/DragMatch.d.ts.map +1 -0
  13. package/dist/exam-session/interactions/GeometryCanvas.d.ts +20 -0
  14. package/dist/exam-session/interactions/GeometryCanvas.d.ts.map +1 -0
  15. package/dist/exam-session/interactions/HandwrittenNumberAnswer.d.ts +11 -0
  16. package/dist/exam-session/interactions/HandwrittenNumberAnswer.d.ts.map +1 -0
  17. package/dist/exam-session/interactions/KonvaDrawingGrid.d.ts +10 -0
  18. package/dist/exam-session/interactions/KonvaDrawingGrid.d.ts.map +1 -0
  19. package/dist/exam-session/interactions/LabelPlacement.d.ts +10 -0
  20. package/dist/exam-session/interactions/LabelPlacement.d.ts.map +1 -0
  21. package/dist/exam-session/interactions/NumberLineAnswer.d.ts +12 -0
  22. package/dist/exam-session/interactions/NumberLineAnswer.d.ts.map +1 -0
  23. package/dist/exam-session/interactions/PronunciationRecorder.d.ts +17 -0
  24. package/dist/exam-session/interactions/PronunciationRecorder.d.ts.map +1 -0
  25. package/dist/exam-session/interactions/SingleChoice.d.ts +10 -0
  26. package/dist/exam-session/interactions/SingleChoice.d.ts.map +1 -0
  27. package/dist/exam-session/interactions/SortableAnswer.d.ts +10 -0
  28. package/dist/exam-session/interactions/SortableAnswer.d.ts.map +1 -0
  29. package/dist/exam-session/interactions/TextAnswer.d.ts +11 -0
  30. package/dist/exam-session/interactions/TextAnswer.d.ts.map +1 -0
  31. package/dist/exam-session/interactions/geometryColors.d.ts +6 -0
  32. package/dist/exam-session/interactions/geometryColors.d.ts.map +1 -0
  33. package/dist/index.d.ts +21 -0
  34. package/dist/index.d.ts.map +1 -0
  35. package/dist/index.js +2593 -0
  36. package/dist/renderer/QuestionPreviewPanel.d.ts +7 -0
  37. package/dist/renderer/QuestionPreviewPanel.d.ts.map +1 -0
  38. package/dist/renderer/QuestionRenderer.d.ts +21 -0
  39. package/dist/renderer/QuestionRenderer.d.ts.map +1 -0
  40. package/dist/styles.css +2 -0
  41. package/dist/voice/evaluateVoiceAiResult.d.ts +19 -0
  42. package/dist/voice/evaluateVoiceAiResult.d.ts.map +1 -0
  43. package/package.json +56 -0
package/dist/index.js ADDED
@@ -0,0 +1,2593 @@
1
+ import { useEffect as e, useMemo as t, useRef as n, useState as r } from "react";
2
+ import { Fragment as i, jsx as a, jsxs as o } from "react/jsx-runtime";
3
+ import { DragDropProvider as s, useDraggable as c, useDroppable as l } from "@dnd-kit/react";
4
+ import { CheckCircle2 as u, Eraser as d, Mic as f, PencilRuler as p, RotateCcw as m, Square as h, VolumeX as g, XCircle as _ } from "lucide-react";
5
+ import { Arc as v, Circle as y, Group as b, Layer as x, Line as S, Rect as C, Stage as w, Text as T } from "react-konva";
6
+ import { move as E } from "@dnd-kit/helpers";
7
+ import { useSortable as D } from "@dnd-kit/react/sortable";
8
+ //#region src/exam-session/examScoring.ts
9
+ var O = 1e3, k = 500, A = 70;
10
+ function j(e, t) {
11
+ let n = e.sections.filter((e) => e.isScored !== !1).map((e) => M(e, t)), r = H(n, (e) => e.correctCount), i = H(n, (e) => e.incorrectCount), a = H(n, (e) => e.unansweredCount), o = i + a, s = H(n, (e) => e.totalUnits), c = U(H(n, (e) => e.maxScore)), l = U(H(n, (e) => e.score));
12
+ return {
13
+ correctCount: r,
14
+ generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
15
+ incorrectCount: i,
16
+ maxScore: c,
17
+ notCorrectCount: o,
18
+ percentage: c > 0 ? U(l / c * 100) : 0,
19
+ score: l,
20
+ sections: n,
21
+ subject: e.subject,
22
+ title: e.title,
23
+ totalUnits: s,
24
+ unansweredCount: a
25
+ };
26
+ }
27
+ function M(e, t) {
28
+ let n = e.questions.flatMap((e) => N(e, t)).map((t) => ({
29
+ ...t,
30
+ sectionId: e.id
31
+ })), r = Number.parseFloat(e.points) || 0, i = V(n, "correct"), a = V(n, "incorrect"), o = V(n, "unanswered"), s = a + o, c = n.length > 0 ? r / n.length : 0;
32
+ return {
33
+ badge: e.badge,
34
+ correctCount: i,
35
+ id: e.id,
36
+ incorrectCount: a,
37
+ maxScore: r,
38
+ notCorrectCount: s,
39
+ score: U(i * c),
40
+ title: e.title,
41
+ tone: e.tone,
42
+ totalUnits: n.length,
43
+ unansweredCount: o,
44
+ units: n
45
+ };
46
+ }
47
+ function N(e, t) {
48
+ switch (e.type) {
49
+ case "inline-inputs":
50
+ case "equation-inputs": return e.items.flatMap((n) => {
51
+ if (!n.correctAnswer) return [];
52
+ let r = `${e.id}:${n.id}`;
53
+ return [P(r, e.id, n.before, n.correctAnswer, t[r])];
54
+ });
55
+ case "number-line": return [P(e.id, e.id, e.expression, e.correctAnswer, t[e.id])];
56
+ case "visual-choice": return te(e.id, e.id, e.grading.pairs, t[e.id]);
57
+ case "length-estimation": return ne(e, t);
58
+ case "shape-choice": return te(e.id, e.id, e.grading.pairs, t[e.id]);
59
+ case "drag-match": return te(e.id, e.id, e.grading?.pairs, t[e.id]);
60
+ case "drawing-grid": return [L(e, t[e.id])];
61
+ case "table-response": return I(e, t[e.id]);
62
+ case "text-input": return e.correctAnswer ? [P(e.id, e.id, e.prompt, e.correctAnswer, t[e.id])] : [];
63
+ case "sortable-answer": return [];
64
+ case "label-placement": return re(e.id, e.grading?.targetsByLabelId, t[e.id]);
65
+ case "audio-recording": return [ee(e, t[e.id])];
66
+ }
67
+ }
68
+ function ee(e, t) {
69
+ return t?.kind === "audio-recording" ? z(e.id, e.id, e.expectedAnswer, t.evaluation.isCorrect ? "correct" : "incorrect") : z(e.id, e.id, e.expectedAnswer, "unanswered");
70
+ }
71
+ function P(e, t, n, r, i) {
72
+ return r ? i?.kind === "handwritten-number" ? i.strokes.length === 0 ? z(e, t, n, "unanswered") : z(e, t, n, i.recognizedValue && le(i.recognizedValue, r) ? "correct" : "incorrect") : i?.kind !== "text" || B(i.value) === "" ? z(e, t, n, "unanswered") : z(e, t, n, le(i.value, r) ? "correct" : "incorrect") : z(e, t, n, "incorrect");
73
+ }
74
+ function te(e, t, n, r) {
75
+ return n ? Object.entries(n).map(([n, i]) => {
76
+ let a = r?.kind === "matches" ? r.pairs[n] : void 0, o = a ? a === i ? "correct" : "incorrect" : "unanswered";
77
+ return z(`${e}:${n}`, t, n, o);
78
+ }) : [];
79
+ }
80
+ function ne(e, t) {
81
+ let n = e.items.map((n) => {
82
+ let r = `${e.id}:squares:${n.id}`;
83
+ return P(r, e.id, n.label, n.squareLength.toString(), t[r]);
84
+ }), r = e.items.flatMap((n) => {
85
+ if (!n.correctColorId) return [];
86
+ let r = `${e.id}:color:${n.id}`;
87
+ return [F(r, e.id, n.label, n.correctColorId, t[r])];
88
+ });
89
+ return n.concat(r);
90
+ }
91
+ function F(e, t, n, r, i) {
92
+ return i?.kind !== "choice" || !i.choiceId ? z(e, t, n, "unanswered") : z(e, t, n, i.choiceId === r ? "correct" : "incorrect");
93
+ }
94
+ function I(e, t) {
95
+ return e.columns.flatMap((n) => {
96
+ if (typeof n.correctCount != "number") return [];
97
+ let r = t?.kind === "coin-table" ? t.counts[n.id] : void 0, i = r === void 0 ? "unanswered" : r === n.correctCount ? "correct" : "incorrect";
98
+ return z(`${e.id}:${n.id}`, e.id, n.title, i);
99
+ });
100
+ }
101
+ function re(e, t, n) {
102
+ return t ? Object.entries(t).map(([t, r]) => {
103
+ let i = n?.kind === "placements" ? n.placements[t]?.targetId : void 0, a = i ? i === r ? "correct" : "incorrect" : "unanswered";
104
+ return z(`${e}:${t}`, e, t, a);
105
+ }) : [];
106
+ }
107
+ function L(e, t) {
108
+ let n = e.grading.expectedSegments, r = t?.kind === "drawing" && ((t.elements?.length ?? 0) > 0 || (t.strokes?.length ?? 0) > 0);
109
+ if (t?.kind !== "drawing" || !r) return z(e.id, e.id, e.prompt, "unanswered");
110
+ let i = n.every((n) => ie(t, e, n));
111
+ return z(e.id, e.id, e.prompt, i ? "correct" : "incorrect");
112
+ }
113
+ function ie(e, t, n) {
114
+ let r = R(t, n.from), i = R(t, n.to);
115
+ return !r || !i ? !1 : ae(e).some((e) => oe(e, r, i));
116
+ }
117
+ function ae(e) {
118
+ let t = e.elements.flatMap((e) => e.type === "line" ? [{
119
+ end: {
120
+ x: e.points[2],
121
+ y: e.points[3]
122
+ },
123
+ points: e.points,
124
+ start: {
125
+ x: e.points[0],
126
+ y: e.points[1]
127
+ }
128
+ }] : e.type === "freehand" && e.points.length >= 4 ? [{
129
+ end: {
130
+ x: e.points[e.points.length - 2],
131
+ y: e.points[e.points.length - 1]
132
+ },
133
+ points: e.points,
134
+ start: {
135
+ x: e.points[0],
136
+ y: e.points[1]
137
+ }
138
+ }] : []), n = e.strokes?.flatMap((e) => e.points.length < 4 ? [] : [{
139
+ end: {
140
+ x: e.points[e.points.length - 2],
141
+ y: e.points[e.points.length - 1]
142
+ },
143
+ points: e.points,
144
+ start: {
145
+ x: e.points[0],
146
+ y: e.points[1]
147
+ }
148
+ }]) ?? [];
149
+ return t.concat(n);
150
+ }
151
+ function oe(e, t, n) {
152
+ let r = W(e.start, t) <= A && W(e.end, n) <= A, i = W(e.start, n) <= A && W(e.end, t) <= A;
153
+ return !r && !i ? !1 : se(e.points, t, n, A);
154
+ }
155
+ function se(e, t, n, r) {
156
+ for (let i = 0; i < e.length - 1; i += 4) if (ue({
157
+ x: e[i],
158
+ y: e[i + 1]
159
+ }, t, n) > r) return !1;
160
+ return !0;
161
+ }
162
+ function R(e, t) {
163
+ if ("pointId" in t) {
164
+ let n = e.points.find((e) => e.id === t.pointId);
165
+ return n ? ce(n.x, n.y) : null;
166
+ }
167
+ return ce(t.percentX, t.percentY);
168
+ }
169
+ function ce(e, t) {
170
+ return {
171
+ x: e / 100 * O,
172
+ y: t / 100 * k
173
+ };
174
+ }
175
+ function z(e, t, n, r) {
176
+ return {
177
+ id: e,
178
+ label: n,
179
+ questionId: t,
180
+ status: r
181
+ };
182
+ }
183
+ function le(e, t) {
184
+ let n = B(e), r = B(t), i = Number(n), a = Number(r);
185
+ return Number.isFinite(i) && Number.isFinite(a) ? i === a : n === r;
186
+ }
187
+ function B(e) {
188
+ return e.trim().replace(/[٠-٩]/g, (e) => `${e.charCodeAt(0) - 1632}`).replace(/[۰-۹]/g, (e) => `${e.charCodeAt(0) - 1776}`);
189
+ }
190
+ function V(e, t) {
191
+ return e.filter((e) => e.status === t).length;
192
+ }
193
+ function H(e, t) {
194
+ return e.reduce((e, n) => e + t(n), 0);
195
+ }
196
+ function U(e) {
197
+ return Math.round(e * 100) / 100;
198
+ }
199
+ function W(e, t) {
200
+ return Math.hypot(e.x - t.x, e.y - t.y);
201
+ }
202
+ function ue(e, t, n) {
203
+ let r = n.x - t.x, i = n.y - t.y, a = r * r + i * i;
204
+ if (a === 0) return W(e, t);
205
+ let o = Math.max(0, Math.min(1, ((e.x - t.x) * r + (e.y - t.y) * i) / a));
206
+ return W(e, {
207
+ x: t.x + o * r,
208
+ y: t.y + o * i
209
+ });
210
+ }
211
+ //#endregion
212
+ //#region src/exam-session/interactions/CoinTableResponse.tsx
213
+ var de = 0, fe = 12;
214
+ function pe({ columns: e, value: t, onChange: n }) {
215
+ let r = t?.counts ?? {};
216
+ function i(e, t) {
217
+ let i = e.maxCoins ?? fe, a = Math.max(de, Math.min(i, t));
218
+ n({
219
+ kind: "coin-table",
220
+ counts: {
221
+ ...r,
222
+ [e.id]: a
223
+ }
224
+ });
225
+ }
226
+ return /* @__PURE__ */ a("div", {
227
+ className: "response-table",
228
+ children: e.map((e) => {
229
+ let t = r[e.id] ?? 0, n = e.maxCoins ?? fe;
230
+ return /* @__PURE__ */ o("div", {
231
+ className: "response-column",
232
+ children: [
233
+ /* @__PURE__ */ a("h4", { children: e.title }),
234
+ /* @__PURE__ */ o("div", {
235
+ className: "coin-table-area",
236
+ "aria-label": e.answerLabel,
237
+ children: [/* @__PURE__ */ a("div", {
238
+ className: "coin-list",
239
+ "aria-hidden": "true",
240
+ children: Array.from({ length: t }, (t, n) => /* @__PURE__ */ a("span", {
241
+ className: "coin-shape",
242
+ children: "د"
243
+ }, `${e.id}-coin-${n}`))
244
+ }), /* @__PURE__ */ o("div", {
245
+ className: "coin-controls",
246
+ children: [/* @__PURE__ */ a("button", {
247
+ className: "coin-action",
248
+ disabled: t >= n,
249
+ onClick: () => i(e, t + 1),
250
+ type: "button",
251
+ children: "إِضافَةٌ"
252
+ }), /* @__PURE__ */ a("button", {
253
+ className: "coin-action coin-action--secondary",
254
+ disabled: t <= de,
255
+ onClick: () => i(e, t - 1),
256
+ type: "button",
257
+ children: "حَذْفٌ"
258
+ })]
259
+ })]
260
+ }),
261
+ /* @__PURE__ */ o("label", {
262
+ className: "coin-count-answer",
263
+ children: [
264
+ /* @__PURE__ */ a("span", { children: e.answerLabel }),
265
+ /* @__PURE__ */ a("input", {
266
+ "aria-label": e.answerLabel,
267
+ inputMode: "numeric",
268
+ onChange: (t) => i(e, Number(t.target.value) || 0),
269
+ value: t
270
+ }),
271
+ /* @__PURE__ */ a("span", { children: "دَراهِمُ" })
272
+ ]
273
+ })
274
+ ]
275
+ }, e.id);
276
+ })
277
+ });
278
+ }
279
+ //#endregion
280
+ //#region src/exam-session/interactions/DragMatch.tsx
281
+ function me({ items: e, targets: t, value: n, onChange: r }) {
282
+ let i = n?.pairs ?? {}, c = new Set(Object.values(i));
283
+ return /* @__PURE__ */ a(s, {
284
+ onDragEnd: (e) => {
285
+ if (e.canceled) return;
286
+ let t = e.operation.source?.id?.toString(), n = e.operation.target?.id?.toString();
287
+ !t || !n || r({
288
+ kind: "matches",
289
+ pairs: {
290
+ ...Object.fromEntries(Object.entries(i).filter(([e, r]) => e !== n && r !== t)),
291
+ [n]: t
292
+ }
293
+ });
294
+ },
295
+ children: /* @__PURE__ */ o("div", {
296
+ className: "drag-match",
297
+ children: [/* @__PURE__ */ a("div", {
298
+ className: "drag-match__items",
299
+ children: e.filter((e) => !c.has(e.id)).map((e) => /* @__PURE__ */ a(he, { item: e }, e.id))
300
+ }), /* @__PURE__ */ a("div", {
301
+ className: "drag-match__targets",
302
+ children: t.map((t) => /* @__PURE__ */ a(ge, {
303
+ assignedItem: e.find((e) => e.id === i[t.id]),
304
+ target: t
305
+ }, t.id))
306
+ })]
307
+ })
308
+ });
309
+ }
310
+ function he({ item: e }) {
311
+ let { ref: t, isDragging: n } = c({ id: e.id });
312
+ return /* @__PURE__ */ a("button", {
313
+ className: n ? "drag-pill drag-pill--dragging" : "drag-pill",
314
+ ref: t,
315
+ type: "button",
316
+ children: e.label
317
+ });
318
+ }
319
+ function ge({ assignedItem: e, target: t }) {
320
+ let { ref: n, isDropTarget: r } = l({ id: t.id });
321
+ return /* @__PURE__ */ o("div", {
322
+ className: r ? "drop-slot drop-slot--active" : "drop-slot",
323
+ ref: n,
324
+ children: [/* @__PURE__ */ a("span", {
325
+ className: "drop-slot__visual",
326
+ children: t.label
327
+ }), e ? /* @__PURE__ */ a(he, { item: e }) : /* @__PURE__ */ a("span", { children: "ضَعِ الإِجابَةَ هُنا" })]
328
+ });
329
+ }
330
+ //#endregion
331
+ //#region src/exam-session/interactions/HandwrittenNumberAnswer.tsx
332
+ var G = 132, K = 88, _e = 650;
333
+ function q({ ariaLabel: t, value: i, onChange: s, onClear: c, recognizer: l }) {
334
+ let u = i?.strokes ?? [], f = u.length === 0, p = n(s), [m, h] = r(!1), [g, _] = r(!1), v = !!l?.isAvailable(), y = f || m ? "idle" : i?.recognizedValue === void 0 ? v ? g ? "unrecognized" : "recognizing" : "unavailable" : "recognized";
335
+ e(() => {
336
+ p.current = s;
337
+ }, [s]), e(() => {
338
+ if (f || m || !i || !l || i.recognizedValue !== void 0 || !v) return;
339
+ let e = !1, t = window.setTimeout(() => {
340
+ l.recognize(i).then((t) => {
341
+ if (!e) {
342
+ if (t.recognizedValue === void 0) {
343
+ _(!0);
344
+ return;
345
+ }
346
+ p.current(t);
347
+ }
348
+ }).catch(() => {
349
+ e || _(!0);
350
+ });
351
+ }, _e);
352
+ return () => {
353
+ e = !0, window.clearTimeout(t);
354
+ };
355
+ }, [
356
+ m,
357
+ f,
358
+ v,
359
+ l,
360
+ i
361
+ ]);
362
+ function b(e) {
363
+ _(!1), s({
364
+ canvasHeight: K,
365
+ canvasWidth: G,
366
+ kind: "handwritten-number",
367
+ strokes: e
368
+ });
369
+ }
370
+ function E(e) {
371
+ let t = e.target.getStage()?.getPointerPosition();
372
+ t && (e.evt.preventDefault(), h(!0), b([...u, {
373
+ id: `stroke-${Date.now()}-${Math.round(t.x)}-${Math.round(t.y)}`,
374
+ points: [t.x, t.y],
375
+ timestamps: [Date.now()]
376
+ }]));
377
+ }
378
+ function D(e) {
379
+ if (f || !e.evt.buttons && e.evt.pointerType === "mouse") return;
380
+ let t = e.target.getStage()?.getPointerPosition();
381
+ t && (e.evt.preventDefault(), b(u.map((e, n) => n === u.length - 1 ? {
382
+ ...e,
383
+ points: [
384
+ ...e.points,
385
+ t.x,
386
+ t.y
387
+ ],
388
+ timestamps: [...e.timestamps ?? [], Date.now()]
389
+ } : e)));
390
+ }
391
+ function O(e) {
392
+ e.evt.preventDefault(), h(!1);
393
+ }
394
+ function k() {
395
+ h(!1), b([]), c?.();
396
+ }
397
+ return /* @__PURE__ */ o("div", {
398
+ className: "handwritten-number-answer",
399
+ "aria-label": t,
400
+ children: [
401
+ /* @__PURE__ */ o(w, {
402
+ className: "handwritten-number-stage",
403
+ height: K,
404
+ onPointerCancel: O,
405
+ onPointerDown: E,
406
+ onPointerMove: D,
407
+ onPointerUp: O,
408
+ role: "img",
409
+ width: G,
410
+ children: [/* @__PURE__ */ o(x, {
411
+ listening: !1,
412
+ children: [
413
+ /* @__PURE__ */ a(C, {
414
+ cornerRadius: 14,
415
+ fill: "#fff",
416
+ height: K,
417
+ stroke: "#cfe3d9",
418
+ strokeWidth: 2,
419
+ width: G,
420
+ x: 0,
421
+ y: 0
422
+ }),
423
+ /* @__PURE__ */ a(S, {
424
+ dash: [6, 8],
425
+ points: [
426
+ 16,
427
+ K - 18,
428
+ G - 16,
429
+ K - 18
430
+ ],
431
+ stroke: "#dbe9e2",
432
+ strokeWidth: 2
433
+ }),
434
+ f ? /* @__PURE__ */ a(T, {
435
+ align: "center",
436
+ fill: "#9aaca3",
437
+ fontFamily: "Arial, sans-serif",
438
+ fontSize: 15,
439
+ fontStyle: "bold",
440
+ height: K,
441
+ text: "ارسم هنا",
442
+ verticalAlign: "middle",
443
+ width: G,
444
+ x: 0,
445
+ y: 0
446
+ }) : null
447
+ ]
448
+ }), /* @__PURE__ */ a(x, { children: u.map((e) => /* @__PURE__ */ a(S, {
449
+ globalCompositeOperation: "source-over",
450
+ lineCap: "round",
451
+ lineJoin: "round",
452
+ points: e.points,
453
+ stroke: "#061013",
454
+ strokeWidth: 7,
455
+ tension: .28
456
+ }, e.id)) })]
457
+ }),
458
+ /* @__PURE__ */ a("button", {
459
+ "aria-label": "مسح الجواب المرسوم",
460
+ className: "handwritten-number-clear",
461
+ disabled: f,
462
+ onClick: k,
463
+ type: "button",
464
+ children: /* @__PURE__ */ a(d, { "aria-hidden": "true" })
465
+ }),
466
+ y !== "idle" && y !== "unavailable" ? /* @__PURE__ */ a("span", {
467
+ "aria-live": "polite",
468
+ className: "handwritten-number-status",
469
+ "data-state": y,
470
+ children: ve(y, i?.recognizedValue)
471
+ }) : null
472
+ ]
473
+ });
474
+ }
475
+ function ve(e, t) {
476
+ switch (e) {
477
+ case "recognizing": return "جارٍ التعرّف على الرقم…";
478
+ case "recognized": return `تمّ التعرّف: ${t ?? ""}`;
479
+ case "unrecognized": return "أَعِدْ كتابةَ الرقم بوضوح";
480
+ case "idle":
481
+ case "unavailable": return "";
482
+ }
483
+ }
484
+ //#endregion
485
+ //#region src/exam-session/interactions/ColorPenPicker.tsx
486
+ function ye({ ariaLabel: e, className: t = "", colors: n, disabled: r = !1, onChange: i, selectedColorId: s }) {
487
+ return /* @__PURE__ */ a("div", {
488
+ "aria-label": e,
489
+ className: ["color-pen-picker", t].filter(Boolean).join(" "),
490
+ role: "group",
491
+ children: n.map((e) => /* @__PURE__ */ o("button", {
492
+ "aria-pressed": s === e.id,
493
+ className: s === e.id ? "color-pen-button color-pen-button--selected" : "color-pen-button",
494
+ disabled: r,
495
+ onClick: () => i(e.id),
496
+ style: { "--pen-color": e.value },
497
+ type: "button",
498
+ children: [/* @__PURE__ */ a("span", {
499
+ className: "color-pen-button__indicator",
500
+ "aria-hidden": "true"
501
+ }), /* @__PURE__ */ a("span", {
502
+ className: "color-pen-button__label",
503
+ children: e.label
504
+ })]
505
+ }, e.id))
506
+ });
507
+ }
508
+ //#endregion
509
+ //#region src/exam-session/interactions/geometryColors.ts
510
+ var J = [
511
+ {
512
+ id: "green",
513
+ label: "أَخْضَرُ",
514
+ value: "#0b7f45"
515
+ },
516
+ {
517
+ id: "red",
518
+ label: "أَحْمَرُ",
519
+ value: "#e34a58"
520
+ },
521
+ {
522
+ id: "blue",
523
+ label: "أَزْرَقُ",
524
+ value: "#256fd2"
525
+ },
526
+ {
527
+ id: "black",
528
+ label: "أَسْوَدُ",
529
+ value: "#17212b"
530
+ }
531
+ ], be = {
532
+ black: "#17212b",
533
+ blue: "#256fd2",
534
+ green: "#0b7f45",
535
+ red: "#e34a58"
536
+ };
537
+ function xe(e, t) {
538
+ return t ? e.find((e) => e.id === t || e.value === t)?.id ?? e[0]?.id ?? "green" : e[0]?.id ?? "green";
539
+ }
540
+ function Se(e, t) {
541
+ return e.find((e) => e.id === t)?.value ?? e[0]?.value ?? J[0].value;
542
+ }
543
+ function Ce(e) {
544
+ return e.map((e) => ({
545
+ id: e.id,
546
+ label: e.label,
547
+ value: be[e.id] ?? J[0].value
548
+ }));
549
+ }
550
+ //#endregion
551
+ //#region src/exam-session/interactions/GeometryCanvas.tsx
552
+ var we = 1e3, Te = 600, Y = 30, Ee = 240, De = 12, Oe = J[0].value, X = "#0a8f55", ke = [
553
+ {
554
+ id: "pen",
555
+ icon: "✎",
556
+ label: "قَلَمٌ"
557
+ },
558
+ {
559
+ id: "eraser",
560
+ icon: "⌫",
561
+ label: "مِمْحاةٌ"
562
+ },
563
+ {
564
+ id: "line",
565
+ icon: "╱",
566
+ label: "خَطٌّ"
567
+ },
568
+ {
569
+ id: "ruler",
570
+ icon: "▰",
571
+ label: "مِسْطَرَةٌ"
572
+ },
573
+ {
574
+ id: "protractor",
575
+ icon: "◠",
576
+ label: "مِنْقَلَةٌ"
577
+ },
578
+ {
579
+ id: "compass",
580
+ icon: "⌖",
581
+ label: "بَرْكارٌ"
582
+ }
583
+ ], Ae = /* @__PURE__ */ new Set([
584
+ "ruler",
585
+ "protractor",
586
+ "compass"
587
+ ]);
588
+ function je({ actionLabel: e, canvasHeight: t = Te, canvasWidth: i = we, className: s = "", colorOptions: c = J, defaultColor: l, disabled: u = !1, minStageWidth: d = Ee, onChange: f, points: p = [], showColorPalette: m = !0, value: h, variant: g = "question" }) {
589
+ let _ = c.length > 0 ? c : J, [v, y] = r(null), [b, S] = r([]), [T, E] = r(() => xe(_, l ?? "black")), [D, O] = r(() => Be(h)), [k, A] = r(() => h?.guides ?? ze(i, t)), [j, M] = r(null), [N, ee] = r({
590
+ height: t,
591
+ scale: 1,
592
+ width: i
593
+ }), [P, te] = r({
594
+ canRedo: !1,
595
+ canUndo: !1
596
+ }), ne = n(null), F = n([Z(D)]), I = n(0), re = n(0), L = n(null);
597
+ Me(ne, i, t, d, ee);
598
+ let ie = He(p, i, t), ae = [
599
+ "geometry-canvas",
600
+ `geometry-canvas--${g}`,
601
+ s
602
+ ].filter(Boolean).join(" "), oe = _.some((e) => e.id === T) ? T : xe(_, "black"), se = Se(_, oe), R = Ge(v);
603
+ function ce(e) {
604
+ return Ae.has(e) ? !R && b.includes(e) : v === e || b.includes(e);
605
+ }
606
+ function z(e) {
607
+ S((t) => t.includes(e) ? t.filter((t) => t !== e) : t.concat(e));
608
+ }
609
+ function le(e) {
610
+ if (e === "ruler" || e === "protractor") {
611
+ if (R) {
612
+ y(null), S((t) => t.includes(e) ? t : t.concat(e));
613
+ return;
614
+ }
615
+ z(e);
616
+ return;
617
+ }
618
+ if (e === "compass") {
619
+ let e = v !== "compass" || !b.includes("compass");
620
+ y(e ? "compass" : null), S((t) => {
621
+ let n = t.filter((e) => e !== "compass");
622
+ return e ? [...n, "compass"] : n;
623
+ });
624
+ return;
625
+ }
626
+ y(e);
627
+ }
628
+ function B(e) {
629
+ return re.current += 1, `${e}-${Date.now()}-${re.current}`;
630
+ }
631
+ function V(e, t = k) {
632
+ f({
633
+ elements: Z(e),
634
+ guides: t,
635
+ kind: "drawing",
636
+ strokes: Ve(e)
637
+ });
638
+ }
639
+ function H() {
640
+ te({
641
+ canRedo: I.current < F.current.length - 1,
642
+ canUndo: I.current > 0
643
+ });
644
+ }
645
+ function U(e, t = k) {
646
+ let n = Z(e), r = F.current.slice(0, I.current + 1);
647
+ r.push(n), F.current = r, I.current = r.length - 1, O(n), V(n, t), H();
648
+ }
649
+ function W(e) {
650
+ A(e), V(D, e);
651
+ }
652
+ function ue() {
653
+ if (!P.canUndo || u) return;
654
+ --I.current;
655
+ let e = Z(F.current[I.current]);
656
+ O(e), V(e), H();
657
+ }
658
+ function de() {
659
+ if (!P.canRedo || u) return;
660
+ I.current += 1;
661
+ let e = Z(F.current[I.current]);
662
+ O(e), V(e), H();
663
+ }
664
+ function fe() {
665
+ u || D.length === 0 || U([]);
666
+ }
667
+ function pe(e) {
668
+ let n = e.target.getStage()?.getPointerPosition();
669
+ return n ? {
670
+ x: tt(n.x / N.scale, 0, i),
671
+ y: tt(n.y / N.scale, 0, t)
672
+ } : null;
673
+ }
674
+ function me(e) {
675
+ if (u || !R && We(e.target)) return;
676
+ let t = pe(e);
677
+ if (!t || !v) return;
678
+ if (v === "eraser") {
679
+ G(t);
680
+ return;
681
+ }
682
+ let n = Ue(t, ie);
683
+ if (v === "pen") {
684
+ L.current = n, M({
685
+ color: se,
686
+ id: B("freehand"),
687
+ points: [n.x, n.y],
688
+ strokeWidth: 4,
689
+ type: "freehand"
690
+ });
691
+ return;
692
+ }
693
+ if (v === "line") {
694
+ L.current = n, M({
695
+ color: se,
696
+ id: B("line"),
697
+ points: [
698
+ n.x,
699
+ n.y,
700
+ n.x,
701
+ n.y
702
+ ],
703
+ strokeWidth: 3,
704
+ type: "line"
705
+ });
706
+ return;
707
+ }
708
+ v === "compass" && (L.current = n, M({
709
+ center: n,
710
+ color: se,
711
+ id: B("circle"),
712
+ radius: 1,
713
+ strokeWidth: 3,
714
+ type: "circle"
715
+ }));
716
+ }
717
+ function he(e) {
718
+ let t = pe(e);
719
+ if (t) {
720
+ if (v === "eraser" && !u) {
721
+ G(t);
722
+ return;
723
+ }
724
+ if (!(!j || !L.current || u)) {
725
+ if (j.type === "freehand") {
726
+ M({
727
+ ...j,
728
+ points: j.points.concat([t.x, t.y])
729
+ });
730
+ return;
731
+ }
732
+ if (j.type === "line") {
733
+ let e = Ue(t, ie);
734
+ M({
735
+ ...j,
736
+ points: [
737
+ L.current.x,
738
+ L.current.y,
739
+ e.x,
740
+ e.y
741
+ ]
742
+ });
743
+ return;
744
+ }
745
+ j.type === "circle" && M({
746
+ ...j,
747
+ radius: Q(j.center, t)
748
+ });
749
+ }
750
+ }
751
+ }
752
+ function ge() {
753
+ if (!j || u) {
754
+ L.current = null, M(null);
755
+ return;
756
+ }
757
+ let e = j;
758
+ if (L.current = null, M(null), qe(e)) {
759
+ if (e.type === "circle") {
760
+ let t = {
761
+ ...k,
762
+ compass: {
763
+ center: e.center,
764
+ radius: e.radius
765
+ }
766
+ };
767
+ A(t), U(D.concat(e), t);
768
+ return;
769
+ }
770
+ U(D.concat(e));
771
+ }
772
+ }
773
+ function G(e) {
774
+ if (D.length === 0) return;
775
+ let t = Je(D, e);
776
+ t < 0 || U(D.filter((e, n) => n !== t));
777
+ }
778
+ return /* @__PURE__ */ o("div", {
779
+ className: ae,
780
+ "data-disabled": u ? "true" : "false",
781
+ dir: "rtl",
782
+ children: [
783
+ /* @__PURE__ */ a("div", {
784
+ className: "geometry-toolbar",
785
+ "aria-label": "أَدَواتُ الوَرَقَةِ المُسَوَّدَةِ",
786
+ children: ke.map((e) => /* @__PURE__ */ o("button", {
787
+ "aria-pressed": ce(e.id),
788
+ className: [
789
+ "geometry-tool-button",
790
+ ce(e.id) ? "geometry-tool-button--active" : "",
791
+ Ae.has(e.id) ? "geometry-tool-button--guide" : ""
792
+ ].filter(Boolean).join(" "),
793
+ disabled: u,
794
+ onClick: () => le(e.id),
795
+ type: "button",
796
+ children: [/* @__PURE__ */ a("span", {
797
+ "aria-hidden": "true",
798
+ children: e.icon
799
+ }), /* @__PURE__ */ a("span", { children: e.label })]
800
+ }, e.id))
801
+ }),
802
+ m ? /* @__PURE__ */ a(ye, {
803
+ ariaLabel: "أَلْوانُ الأَقْلامِ",
804
+ className: "geometry-color-picker",
805
+ colors: _,
806
+ disabled: u,
807
+ onChange: E,
808
+ selectedColorId: oe
809
+ }) : null,
810
+ /* @__PURE__ */ a("div", {
811
+ className: "geometry-stage-shell",
812
+ ref: ne,
813
+ children: /* @__PURE__ */ a(w, {
814
+ height: N.height,
815
+ onMouseDown: me,
816
+ onMouseLeave: ge,
817
+ onMouseMove: he,
818
+ onMouseUp: ge,
819
+ onTouchEnd: ge,
820
+ onTouchMove: he,
821
+ onTouchStart: me,
822
+ width: N.width,
823
+ children: /* @__PURE__ */ o(x, {
824
+ scaleX: N.scale,
825
+ scaleY: N.scale,
826
+ children: [
827
+ /* @__PURE__ */ a(C, {
828
+ fill: "#fff",
829
+ height: t,
830
+ stroke: "#bad3c8",
831
+ strokeWidth: 1,
832
+ width: i
833
+ }),
834
+ /* @__PURE__ */ a(Ne, {
835
+ canvasHeight: t,
836
+ canvasWidth: i
837
+ }),
838
+ p.map((e, n) => /* @__PURE__ */ a(Pe, {
839
+ label: n % 2 == 0 ? "1" : "2",
840
+ x: e.x / 100 * i,
841
+ y: e.y / 100 * t
842
+ }, e.id)),
843
+ D.map((e) => Re(e)),
844
+ j ? Re(j, !0) : null,
845
+ b.includes("ruler") ? /* @__PURE__ */ a(Fe, {
846
+ disabled: u,
847
+ guide: k.ruler,
848
+ locked: R,
849
+ onCommit: (e) => W({
850
+ ...k,
851
+ ruler: e
852
+ })
853
+ }) : null,
854
+ b.includes("protractor") ? /* @__PURE__ */ a(Ie, {
855
+ disabled: u,
856
+ guide: k.protractor,
857
+ locked: R,
858
+ onChange: (e) => W({
859
+ ...k,
860
+ protractor: e
861
+ })
862
+ }) : null,
863
+ b.includes("compass") ? /* @__PURE__ */ a(Le, {
864
+ disabled: u,
865
+ guide: k.compass,
866
+ locked: R,
867
+ onChange: (e) => W({
868
+ ...k,
869
+ compass: e
870
+ })
871
+ }) : null
872
+ ]
873
+ })
874
+ })
875
+ }),
876
+ /* @__PURE__ */ o("div", {
877
+ className: "geometry-actions",
878
+ children: [
879
+ e ? /* @__PURE__ */ a("span", { children: e }) : null,
880
+ /* @__PURE__ */ a("button", {
881
+ disabled: !P.canUndo || u,
882
+ onClick: ue,
883
+ type: "button",
884
+ children: "تَراجُعٌ"
885
+ }),
886
+ /* @__PURE__ */ a("button", {
887
+ disabled: !P.canRedo || u,
888
+ onClick: de,
889
+ type: "button",
890
+ children: "إِعادَةٌ"
891
+ }),
892
+ /* @__PURE__ */ a("button", {
893
+ disabled: D.length === 0 || u,
894
+ onClick: fe,
895
+ type: "button",
896
+ children: "مَسْحٌ"
897
+ })
898
+ ]
899
+ })
900
+ ]
901
+ });
902
+ }
903
+ function Me(t, n, r, i, a) {
904
+ e(() => {
905
+ let e = t.current;
906
+ if (!e) return;
907
+ let o = (e) => {
908
+ let t = Math.min(n, Math.max(1, e > 0 ? e : i)), o = t / n;
909
+ a({
910
+ height: r * o,
911
+ scale: o,
912
+ width: t
913
+ });
914
+ };
915
+ o(e.clientWidth);
916
+ let s = new ResizeObserver((e) => {
917
+ let t = e[0];
918
+ t && o(t.contentRect.width);
919
+ });
920
+ return s.observe(e), () => s.disconnect();
921
+ }, [
922
+ r,
923
+ t,
924
+ n,
925
+ i,
926
+ a
927
+ ]);
928
+ }
929
+ function Ne({ canvasHeight: e, canvasWidth: t }) {
930
+ let n = Math.floor(t / Y), r = Math.floor(e / Y);
931
+ return /* @__PURE__ */ o(i, { children: [Array.from({ length: n + 1 }, (t, n) => /* @__PURE__ */ a(S, {
932
+ points: [
933
+ n * Y,
934
+ 0,
935
+ n * Y,
936
+ e
937
+ ],
938
+ stroke: "#d2ded8",
939
+ strokeWidth: 1
940
+ }, `vertical-${n}`)), Array.from({ length: r + 1 }, (e, n) => /* @__PURE__ */ a(S, {
941
+ points: [
942
+ 0,
943
+ n * Y,
944
+ t,
945
+ n * Y
946
+ ],
947
+ stroke: "#d2ded8",
948
+ strokeWidth: 1
949
+ }, `horizontal-${n}`))] });
950
+ }
951
+ function Pe({ label: e, x: t, y: n }) {
952
+ return /* @__PURE__ */ o(i, { children: [/* @__PURE__ */ a(y, {
953
+ fill: "#e63542",
954
+ radius: 9,
955
+ shadowBlur: 8,
956
+ shadowColor: "rgba(230, 53, 66, 0.28)",
957
+ stroke: "#fff",
958
+ strokeWidth: 3,
959
+ x: t,
960
+ y: n
961
+ }), /* @__PURE__ */ a(T, {
962
+ fill: "#111",
963
+ fontSize: 18,
964
+ fontStyle: "bold",
965
+ text: e,
966
+ x: t + 11,
967
+ y: n - 22
968
+ })] });
969
+ }
970
+ function Fe({ disabled: t, guide: s, locked: c, onCommit: l }) {
971
+ let [u, d] = r(s), f = n(s);
972
+ e(() => {
973
+ f.current = s, d(s);
974
+ }, [s]);
975
+ let p = u.length / 2, m = p + 44, h = -p - 44, g = p + 8, _ = -p - 8, v = !t && !c;
976
+ function x(e) {
977
+ f.current = e, d(e);
978
+ }
979
+ function w(e) {
980
+ e.cancelBubble = !0;
981
+ let t = Ke(e);
982
+ t && (x({
983
+ ...f.current,
984
+ x: t.x,
985
+ y: t.y
986
+ }), e.currentTarget.position({
987
+ x: 0,
988
+ y: 0
989
+ }));
990
+ }
991
+ function T(e) {
992
+ e.cancelBubble = !0, e.currentTarget.position({
993
+ x: 0,
994
+ y: 0
995
+ }), l(f.current);
996
+ }
997
+ function E(e, t) {
998
+ e.cancelBubble = !0;
999
+ let n = Ke(e);
1000
+ n && (x($e(f.current, n, t)), e.currentTarget.position({
1001
+ x: 0,
1002
+ y: 0
1003
+ }));
1004
+ }
1005
+ function D() {
1006
+ let e = {
1007
+ ...f.current,
1008
+ rotation: nt(f.current.rotation + 90)
1009
+ };
1010
+ x(e), l(e);
1011
+ }
1012
+ return /* @__PURE__ */ a(i, { children: /* @__PURE__ */ o(b, {
1013
+ listening: v,
1014
+ name: "geometry-guide",
1015
+ onDblClick: D,
1016
+ onDblTap: D,
1017
+ rotation: u.rotation,
1018
+ x: u.x,
1019
+ y: u.y,
1020
+ children: [
1021
+ /* @__PURE__ */ a(C, {
1022
+ cornerRadius: 7,
1023
+ fill: "rgba(14, 173, 100, 0.13)",
1024
+ height: 38,
1025
+ listening: !1,
1026
+ offsetX: u.length / 2,
1027
+ offsetY: 38 / 2,
1028
+ stroke: X,
1029
+ strokeWidth: 2,
1030
+ width: u.length
1031
+ }),
1032
+ /* @__PURE__ */ a(S, {
1033
+ points: [
1034
+ -u.length / 2 + 12,
1035
+ 0,
1036
+ u.length / 2 - 12,
1037
+ 0
1038
+ ],
1039
+ listening: !1,
1040
+ stroke: X,
1041
+ strokeWidth: 2
1042
+ }),
1043
+ Array.from({ length: Math.floor(u.length / 20) + 1 }, (e, t) => {
1044
+ let n = -u.length / 2 + t * 20, r = t % 5 == 0;
1045
+ return /* @__PURE__ */ a(S, {
1046
+ listening: !1,
1047
+ points: [
1048
+ n,
1049
+ 19,
1050
+ n,
1051
+ r ? 4 : 10
1052
+ ],
1053
+ stroke: X,
1054
+ strokeWidth: r ? 1.5 : 1
1055
+ }, t);
1056
+ }),
1057
+ /* @__PURE__ */ a(S, {
1058
+ dash: [7, 7],
1059
+ listening: !1,
1060
+ opacity: .72,
1061
+ points: [
1062
+ g,
1063
+ 0,
1064
+ m,
1065
+ 0
1066
+ ],
1067
+ stroke: X,
1068
+ strokeWidth: 2
1069
+ }),
1070
+ /* @__PURE__ */ a(S, {
1071
+ dash: [7, 7],
1072
+ listening: !1,
1073
+ opacity: .72,
1074
+ points: [
1075
+ _,
1076
+ 0,
1077
+ h,
1078
+ 0
1079
+ ],
1080
+ stroke: X,
1081
+ strokeWidth: 2
1082
+ }),
1083
+ /* @__PURE__ */ a(b, {
1084
+ draggable: v,
1085
+ name: "geometry-guide",
1086
+ onDblClick: D,
1087
+ onDblTap: D,
1088
+ onDragEnd: T,
1089
+ onDragMove: (e) => E(e, "right"),
1090
+ children: /* @__PURE__ */ a(C, {
1091
+ fill: "rgba(255, 255, 255, 0.01)",
1092
+ height: 106,
1093
+ offsetY: 53,
1094
+ width: m + 24,
1095
+ x: 0
1096
+ })
1097
+ }),
1098
+ /* @__PURE__ */ a(b, {
1099
+ draggable: v,
1100
+ name: "geometry-guide",
1101
+ onDblClick: D,
1102
+ onDblTap: D,
1103
+ onDragEnd: T,
1104
+ onDragMove: (e) => E(e, "left"),
1105
+ children: /* @__PURE__ */ a(C, {
1106
+ fill: "rgba(255, 255, 255, 0.01)",
1107
+ height: 106,
1108
+ offsetY: 53,
1109
+ width: Math.abs(h) + 24,
1110
+ x: h - 24
1111
+ })
1112
+ }),
1113
+ /* @__PURE__ */ a(y, {
1114
+ fill: "#f7fffb",
1115
+ listening: !1,
1116
+ radius: 16,
1117
+ shadowBlur: 10,
1118
+ shadowColor: "rgba(10, 143, 85, 0.35)",
1119
+ stroke: X,
1120
+ strokeWidth: 4,
1121
+ x: m,
1122
+ y: 0
1123
+ }),
1124
+ /* @__PURE__ */ a(y, {
1125
+ fill: "#f7fffb",
1126
+ listening: !1,
1127
+ radius: 16,
1128
+ shadowBlur: 10,
1129
+ shadowColor: "rgba(10, 143, 85, 0.35)",
1130
+ stroke: X,
1131
+ strokeWidth: 4,
1132
+ x: h,
1133
+ y: 0
1134
+ }),
1135
+ /* @__PURE__ */ o(b, {
1136
+ draggable: v,
1137
+ name: "geometry-guide",
1138
+ onDragEnd: T,
1139
+ onDragMove: w,
1140
+ children: [/* @__PURE__ */ a(C, {
1141
+ cornerRadius: 13,
1142
+ fill: "#ffffff",
1143
+ height: 26,
1144
+ offsetX: 35,
1145
+ offsetY: 13,
1146
+ shadowBlur: 8,
1147
+ shadowColor: "rgba(10, 143, 85, 0.2)",
1148
+ stroke: X,
1149
+ strokeWidth: 2,
1150
+ width: 70
1151
+ }), [
1152
+ -14,
1153
+ 0,
1154
+ 14
1155
+ ].map((e) => /* @__PURE__ */ a(S, {
1156
+ lineCap: "round",
1157
+ points: [
1158
+ e,
1159
+ -7,
1160
+ e,
1161
+ 7
1162
+ ],
1163
+ stroke: X,
1164
+ strokeWidth: 2
1165
+ }, e))]
1166
+ })
1167
+ ]
1168
+ }) });
1169
+ }
1170
+ function Ie({ disabled: e, guide: t, locked: n, onChange: r }) {
1171
+ let s = !e && !n, c = Ze({
1172
+ x: 136,
1173
+ y: 0
1174
+ }, t.rotation, {
1175
+ x: t.x,
1176
+ y: t.y
1177
+ });
1178
+ return /* @__PURE__ */ o(i, { children: [/* @__PURE__ */ o(b, {
1179
+ draggable: s,
1180
+ listening: s,
1181
+ name: "geometry-guide",
1182
+ onDragMove: (e) => r({
1183
+ ...t,
1184
+ x: e.target.x(),
1185
+ y: e.target.y()
1186
+ }),
1187
+ rotation: t.rotation,
1188
+ x: t.x,
1189
+ y: t.y,
1190
+ children: [
1191
+ /* @__PURE__ */ a(v, {
1192
+ angle: 180,
1193
+ fill: "rgba(14, 173, 100, 0.11)",
1194
+ innerRadius: 0,
1195
+ outerRadius: 110,
1196
+ rotation: 180,
1197
+ stroke: X,
1198
+ strokeWidth: 2
1199
+ }),
1200
+ /* @__PURE__ */ a(S, {
1201
+ points: [
1202
+ -110,
1203
+ 0,
1204
+ 110,
1205
+ 0
1206
+ ],
1207
+ stroke: X,
1208
+ strokeWidth: 2
1209
+ }),
1210
+ Array.from({ length: 19 }, (e, t) => {
1211
+ let n = t * 10, r = (180 - n) * Math.PI / 180, i = {
1212
+ x: Math.cos(r) * 110,
1213
+ y: -Math.sin(r) * 110
1214
+ }, o = {
1215
+ x: Math.cos(r) * (t % 3 == 0 ? 92 : 100),
1216
+ y: -Math.sin(r) * (t % 3 == 0 ? 92 : 100)
1217
+ };
1218
+ return /* @__PURE__ */ a(S, {
1219
+ points: [
1220
+ o.x,
1221
+ o.y,
1222
+ i.x,
1223
+ i.y
1224
+ ],
1225
+ stroke: X,
1226
+ strokeWidth: t % 3 == 0 ? 1.4 : 1
1227
+ }, n);
1228
+ }),
1229
+ [
1230
+ 0,
1231
+ 90,
1232
+ 180
1233
+ ].map((e) => {
1234
+ let t = (180 - e) * Math.PI / 180;
1235
+ return /* @__PURE__ */ a(T, {
1236
+ fill: X,
1237
+ fontSize: 12,
1238
+ fontStyle: "bold",
1239
+ text: `${e}`,
1240
+ x: Math.cos(t) * 72 - 10,
1241
+ y: -Math.sin(t) * 72 - 7
1242
+ }, e);
1243
+ })
1244
+ ]
1245
+ }), /* @__PURE__ */ a(y, {
1246
+ draggable: s,
1247
+ fill: "#fff",
1248
+ listening: s,
1249
+ name: "geometry-guide",
1250
+ onDragMove: (e) => {
1251
+ let n = e.target.position();
1252
+ r({
1253
+ ...t,
1254
+ rotation: Math.atan2(n.y - t.y, n.x - t.x) * 180 / Math.PI
1255
+ });
1256
+ },
1257
+ radius: 10,
1258
+ stroke: X,
1259
+ strokeWidth: 3,
1260
+ x: c.x,
1261
+ y: c.y
1262
+ })] });
1263
+ }
1264
+ function Le({ disabled: e, guide: t, locked: n, onChange: r }) {
1265
+ let s = !e && !n, c = {
1266
+ x: t.center.x + t.radius,
1267
+ y: t.center.y
1268
+ }, l = {
1269
+ x: t.center.x + t.radius / 2,
1270
+ y: t.center.y - Math.min(90, Math.max(34, t.radius * .68))
1271
+ };
1272
+ return /* @__PURE__ */ o(i, { children: [
1273
+ /* @__PURE__ */ a(y, {
1274
+ dash: [8, 8],
1275
+ radius: t.radius,
1276
+ stroke: X,
1277
+ strokeWidth: 2,
1278
+ x: t.center.x,
1279
+ y: t.center.y
1280
+ }),
1281
+ /* @__PURE__ */ a(S, {
1282
+ dash: [8, 8],
1283
+ points: [
1284
+ t.center.x,
1285
+ t.center.y,
1286
+ c.x,
1287
+ c.y
1288
+ ],
1289
+ stroke: X,
1290
+ strokeWidth: 2
1291
+ }),
1292
+ /* @__PURE__ */ a(S, {
1293
+ lineCap: "round",
1294
+ lineJoin: "round",
1295
+ points: [
1296
+ t.center.x,
1297
+ t.center.y,
1298
+ l.x,
1299
+ l.y,
1300
+ c.x,
1301
+ c.y
1302
+ ],
1303
+ stroke: X,
1304
+ strokeWidth: 4
1305
+ }),
1306
+ /* @__PURE__ */ a(y, {
1307
+ fill: "#fff",
1308
+ radius: 8,
1309
+ stroke: X,
1310
+ strokeWidth: 3,
1311
+ x: l.x,
1312
+ y: l.y
1313
+ }),
1314
+ /* @__PURE__ */ a(y, {
1315
+ draggable: s,
1316
+ fill: "#fff",
1317
+ listening: s,
1318
+ name: "geometry-guide",
1319
+ onDragMove: (e) => r({
1320
+ ...t,
1321
+ center: e.target.position()
1322
+ }),
1323
+ radius: 11,
1324
+ stroke: X,
1325
+ strokeWidth: 3,
1326
+ x: t.center.x,
1327
+ y: t.center.y
1328
+ }),
1329
+ /* @__PURE__ */ a(y, {
1330
+ draggable: s,
1331
+ fill: "#fff",
1332
+ listening: s,
1333
+ name: "geometry-guide",
1334
+ onDragMove: (e) => {
1335
+ let n = e.target.position();
1336
+ r({
1337
+ ...t,
1338
+ radius: Math.max(14, Q(t.center, n))
1339
+ });
1340
+ },
1341
+ radius: 9,
1342
+ stroke: X,
1343
+ strokeWidth: 3,
1344
+ x: c.x,
1345
+ y: c.y
1346
+ })
1347
+ ] });
1348
+ }
1349
+ function Re(e, t = !1) {
1350
+ let n = t ? .58 : 1;
1351
+ return e.type === "freehand" ? /* @__PURE__ */ a(S, {
1352
+ lineCap: "round",
1353
+ lineJoin: "round",
1354
+ opacity: n,
1355
+ points: e.points,
1356
+ stroke: e.color,
1357
+ strokeWidth: e.strokeWidth,
1358
+ tension: .45
1359
+ }, e.id) : e.type === "line" ? /* @__PURE__ */ a(S, {
1360
+ lineCap: "round",
1361
+ opacity: n,
1362
+ points: e.points,
1363
+ stroke: e.color,
1364
+ strokeWidth: e.strokeWidth
1365
+ }, e.id) : /* @__PURE__ */ a(y, {
1366
+ opacity: n,
1367
+ radius: e.radius,
1368
+ stroke: e.color,
1369
+ strokeWidth: e.strokeWidth,
1370
+ x: e.center.x,
1371
+ y: e.center.y
1372
+ }, e.id);
1373
+ }
1374
+ function ze(e, t) {
1375
+ return {
1376
+ compass: {
1377
+ center: {
1378
+ x: e / 2,
1379
+ y: t / 2
1380
+ },
1381
+ radius: Math.min(e, t) * .22
1382
+ },
1383
+ protractor: {
1384
+ rotation: 0,
1385
+ x: e / 2,
1386
+ y: t * .72
1387
+ },
1388
+ ruler: {
1389
+ length: Math.min(e - 70, 430),
1390
+ rotation: 0,
1391
+ x: e / 2,
1392
+ y: t / 2
1393
+ }
1394
+ };
1395
+ }
1396
+ function Be(e) {
1397
+ return e?.elements?.length ? Z(e.elements) : (e?.strokes ?? []).filter((e) => e.tool === "pen" && e.points.length >= 4).map((e) => ({
1398
+ color: Oe,
1399
+ id: e.id,
1400
+ points: e.points.slice(),
1401
+ strokeWidth: 4,
1402
+ type: "freehand"
1403
+ }));
1404
+ }
1405
+ function Ve(e) {
1406
+ return e.flatMap((e) => e.type === "freehand" ? [{
1407
+ id: e.id,
1408
+ points: e.points.slice(),
1409
+ tool: "pen"
1410
+ }] : e.type === "line" ? [{
1411
+ id: e.id,
1412
+ points: [...e.points],
1413
+ tool: "pen"
1414
+ }] : []);
1415
+ }
1416
+ function Z(e) {
1417
+ return e.map((e) => e.type === "freehand" ? {
1418
+ ...e,
1419
+ points: e.points.slice()
1420
+ } : e.type === "line" ? {
1421
+ ...e,
1422
+ points: [
1423
+ e.points[0],
1424
+ e.points[1],
1425
+ e.points[2],
1426
+ e.points[3]
1427
+ ]
1428
+ } : {
1429
+ ...e,
1430
+ center: { ...e.center }
1431
+ });
1432
+ }
1433
+ function He(e, t, n) {
1434
+ let r = e.map((e) => ({
1435
+ x: e.x / 100 * t,
1436
+ y: e.y / 100 * n
1437
+ })), i = [];
1438
+ for (let e = 0; e <= t; e += Y) for (let t = 0; t <= n; t += Y) i.push({
1439
+ x: e,
1440
+ y: t
1441
+ });
1442
+ return r.concat(i);
1443
+ }
1444
+ function Ue(e, t) {
1445
+ let n = e, r = De;
1446
+ return t.forEach((t) => {
1447
+ let i = Q(e, t);
1448
+ i < r && (n = t, r = i);
1449
+ }), n;
1450
+ }
1451
+ function We(e) {
1452
+ let t = e;
1453
+ for (; t;) {
1454
+ if (t.name().split(" ").includes("geometry-guide")) return !0;
1455
+ t = t.getParent();
1456
+ }
1457
+ return !1;
1458
+ }
1459
+ function Ge(e) {
1460
+ return e === "pen" || e === "line" || e === "eraser";
1461
+ }
1462
+ function Ke(e) {
1463
+ let t = e.target.getStage()?.getPointerPosition();
1464
+ if (!t) return null;
1465
+ let n = e.target.getLayer(), r = n?.scaleX() || 1, i = n?.scaleY() || r;
1466
+ return {
1467
+ x: t.x / r,
1468
+ y: t.y / i
1469
+ };
1470
+ }
1471
+ function qe(e) {
1472
+ return e.type === "freehand" ? e.points.length >= 4 : e.type === "line" ? et(e.points) > 6 : e.radius > 6;
1473
+ }
1474
+ function Je(e, t) {
1475
+ for (let n = e.length - 1; n >= 0; --n) if (Ye(e[n], t)) return n;
1476
+ return -1;
1477
+ }
1478
+ function Ye(e, t) {
1479
+ if (e.type === "circle") return Math.abs(Q(e.center, t) - e.radius) <= 14;
1480
+ for (let n = 0; n < e.points.length - 2; n += 2) if (Xe(t, {
1481
+ x1: e.points[n],
1482
+ x2: e.points[n + 2],
1483
+ y1: e.points[n + 1],
1484
+ y2: e.points[n + 3]
1485
+ }) <= 14) return !0;
1486
+ return !1;
1487
+ }
1488
+ function Xe(e, t) {
1489
+ let n = t.x2 - t.x1, r = t.y2 - t.y1, i = n * n + r * r;
1490
+ if (i === 0) return Q(e, {
1491
+ x: t.x1,
1492
+ y: t.y1
1493
+ });
1494
+ let a = tt(((e.x - t.x1) * n + (e.y - t.y1) * r) / i, 0, 1);
1495
+ return Q(e, {
1496
+ x: t.x1 + a * n,
1497
+ y: t.y1 + a * r
1498
+ });
1499
+ }
1500
+ function Ze(e, t, n) {
1501
+ let r = t * Math.PI / 180, i = Math.cos(r), a = Math.sin(r);
1502
+ return {
1503
+ x: n.x + e.x * i - e.y * a,
1504
+ y: n.y + e.x * a + e.y * i
1505
+ };
1506
+ }
1507
+ function Qe(e, t) {
1508
+ return Ze({
1509
+ x: t === "left" ? -e.length / 2 : e.length / 2,
1510
+ y: 0
1511
+ }, e.rotation, {
1512
+ x: e.x,
1513
+ y: e.y
1514
+ });
1515
+ }
1516
+ function $e(e, t, n) {
1517
+ let r = n === "right" ? "left" : "right", i = Qe(e, r), a = Math.atan2(t.y - i.y, t.x - i.x) * 180 / Math.PI, o = nt(n === "right" ? a : a + 180), s = o * Math.PI / 180, c = e.length / 2, l = r === "left" ? 1 : -1;
1518
+ return {
1519
+ ...e,
1520
+ rotation: o,
1521
+ x: i.x + Math.cos(s) * c * l,
1522
+ y: i.y + Math.sin(s) * c * l
1523
+ };
1524
+ }
1525
+ function et(e) {
1526
+ return Q({
1527
+ x: e[0],
1528
+ y: e[1]
1529
+ }, {
1530
+ x: e[2],
1531
+ y: e[3]
1532
+ });
1533
+ }
1534
+ function Q(e, t) {
1535
+ return Math.hypot(e.x - t.x, e.y - t.y);
1536
+ }
1537
+ function tt(e, t, n) {
1538
+ return Math.min(Math.max(e, t), n);
1539
+ }
1540
+ function nt(e) {
1541
+ return (e % 360 + 360) % 360;
1542
+ }
1543
+ //#endregion
1544
+ //#region src/exam-session/interactions/KonvaDrawingGrid.tsx
1545
+ function rt({ actionLabel: e, points: t, value: n, onChange: r }) {
1546
+ return /* @__PURE__ */ a(je, {
1547
+ actionLabel: e,
1548
+ onChange: r,
1549
+ points: t,
1550
+ value: n,
1551
+ variant: "question"
1552
+ });
1553
+ }
1554
+ //#endregion
1555
+ //#region src/exam-session/interactions/LabelPlacement.tsx
1556
+ function it({ labels: e, targets: t, value: n, onChange: r }) {
1557
+ let i = n?.placements ?? {}, c = new Set(Object.keys(i));
1558
+ return /* @__PURE__ */ a(s, {
1559
+ onDragEnd: (e) => {
1560
+ if (e.canceled) return;
1561
+ let n = e.operation.source?.id?.toString(), a = e.operation.target?.id?.toString(), o = t.find((e) => e.id === a);
1562
+ !n || !o || r({
1563
+ kind: "placements",
1564
+ placements: {
1565
+ ...i,
1566
+ [n]: {
1567
+ labelId: n,
1568
+ targetId: o.id,
1569
+ x: o.x,
1570
+ y: o.y
1571
+ }
1572
+ }
1573
+ });
1574
+ },
1575
+ children: /* @__PURE__ */ o("div", {
1576
+ className: "label-placement",
1577
+ children: [/* @__PURE__ */ a("div", {
1578
+ className: "label-placement__bank",
1579
+ children: e.filter((e) => !c.has(e.id)).map((e) => /* @__PURE__ */ a(at, { label: e }, e.id))
1580
+ }), /* @__PURE__ */ a("div", {
1581
+ className: "label-placement__diagram",
1582
+ children: t.map((t) => /* @__PURE__ */ a(ot, {
1583
+ label: e.find((e) => i[e.id]?.targetId === t.id),
1584
+ target: t
1585
+ }, t.id))
1586
+ })]
1587
+ })
1588
+ });
1589
+ }
1590
+ function at({ label: e }) {
1591
+ let { ref: t, isDragging: n } = c({ id: e.id });
1592
+ return /* @__PURE__ */ a("button", {
1593
+ className: n ? "placement-label placement-label--dragging" : "placement-label",
1594
+ ref: t,
1595
+ type: "button",
1596
+ children: e.label
1597
+ });
1598
+ }
1599
+ function ot({ label: e, target: t }) {
1600
+ let { ref: n, isDropTarget: r } = l({ id: t.id });
1601
+ return /* @__PURE__ */ o("div", {
1602
+ className: r ? "placement-target placement-target--active" : "placement-target",
1603
+ ref: n,
1604
+ style: {
1605
+ left: `${t.x}%`,
1606
+ top: `${t.y}%`
1607
+ },
1608
+ children: [/* @__PURE__ */ a("span", {
1609
+ "aria-hidden": "true",
1610
+ children: t.label
1611
+ }), e ? /* @__PURE__ */ a(at, { label: e }) : null]
1612
+ });
1613
+ }
1614
+ //#endregion
1615
+ //#region src/exam-session/interactions/NumberLineAnswer.tsx
1616
+ function st({ answerId: e, expression: t, value: n, onChange: r, onClear: i, recognizer: s }) {
1617
+ return /* @__PURE__ */ o("div", {
1618
+ className: "number-line-layout",
1619
+ children: [/* @__PURE__ */ a(ct, {}), /* @__PURE__ */ o("div", {
1620
+ className: "compact-answer",
1621
+ children: [/* @__PURE__ */ a("span", { children: t }), /* @__PURE__ */ a(q, {
1622
+ ariaLabel: t,
1623
+ onChange: (t) => r(e, t),
1624
+ onClear: () => i(e),
1625
+ recognizer: s,
1626
+ value: n
1627
+ })]
1628
+ })]
1629
+ });
1630
+ }
1631
+ function ct() {
1632
+ return /* @__PURE__ */ o("svg", {
1633
+ className: "number-line",
1634
+ viewBox: "0 0 520 86",
1635
+ role: "img",
1636
+ "aria-label": "مُسْتَقِيمٌ عَدَدِيٌّ مِنْ 0 إِلَى 10",
1637
+ children: [/* @__PURE__ */ a("line", {
1638
+ x1: "32",
1639
+ x2: "488",
1640
+ y1: "36",
1641
+ y2: "36"
1642
+ }), Array.from({ length: 11 }, (e, t) => {
1643
+ let n = 32 + t * 45.6;
1644
+ return /* @__PURE__ */ o("g", { children: [/* @__PURE__ */ a("line", {
1645
+ x1: n,
1646
+ x2: n,
1647
+ y1: "28",
1648
+ y2: "44"
1649
+ }), /* @__PURE__ */ a("text", {
1650
+ x: n,
1651
+ y: "66",
1652
+ children: t
1653
+ })] }, t);
1654
+ })]
1655
+ });
1656
+ }
1657
+ //#endregion
1658
+ //#region src/voice/evaluateVoiceAiResult.ts
1659
+ var lt = {
1660
+ audioConfig: {
1661
+ bitDepth: 16,
1662
+ channels: 1,
1663
+ format: "wav",
1664
+ sampleRate: 16e3
1665
+ },
1666
+ lang: "fr",
1667
+ useModelAi: !0
1668
+ };
1669
+ function ut(e, t, n) {
1670
+ let r = mt([t, ...n.acceptedPronunciations ?? []]), i = r.map(dt), a = dt(e.transcript), o = i.map((e, t) => ({
1671
+ index: t,
1672
+ similarity: pt(a, e)
1673
+ })).reduce((e, t) => t.similarity > e.similarity ? t : e, {
1674
+ index: -1,
1675
+ similarity: 0
1676
+ }), s = o.index >= 0 ? r[o.index] : null, c = o.similarity === 1, l = ht(n.minimumSimilarity ?? ft(s), 0, 1), u = e.language === n.expectedLanguage, d = a.length > 0, f = d && u && o.similarity >= l, p = d ? u ? f ? "correct" : "incorrect" : "language-mismatch" : "no-speech";
1677
+ return {
1678
+ acceptedPronunciations: r,
1679
+ confidence: e.confidence,
1680
+ confidencePercent: Math.round(ht(e.confidence, 0, 1) * 100),
1681
+ detectedPronunciation: e.transcript,
1682
+ expectedLanguage: n.expectedLanguage,
1683
+ expectedText: t,
1684
+ isCorrect: f,
1685
+ isExactMatch: c,
1686
+ language: e.language,
1687
+ latencyMs: e.latencyMs,
1688
+ matchedPronunciation: f ? s : null,
1689
+ minimumSimilarity: l,
1690
+ modelVersion: e.modelVersion,
1691
+ normalizedDetectedPronunciation: a,
1692
+ normalizedPronunciations: i,
1693
+ similarity: o.similarity,
1694
+ similarityPercent: Math.round(o.similarity * 100),
1695
+ status: p,
1696
+ timestamps: e.timestamps ?? []
1697
+ };
1698
+ }
1699
+ function dt(e) {
1700
+ return e.toLocaleLowerCase().normalize("NFD").replace(/[\u0300-\u036f]/g, "").replace(/[\u064b-\u065f\u0670]/g, "").replace(/[|]+/g, " ").replace(/[^\p{Letter}\p{Number}\s]/gu, " ").replace(/\s+/g, " ").trim();
1701
+ }
1702
+ function ft(e) {
1703
+ return (e ? dt(e).length : 0) <= 4 ? 1 : .85;
1704
+ }
1705
+ function pt(e, t) {
1706
+ let n = Array.from(e), r = Array.from(t), i = Math.max(n.length, r.length);
1707
+ if (i === 0) return 0;
1708
+ let a = Array.from({ length: r.length + 1 }, (e, t) => t);
1709
+ for (let e = 0; e < n.length; e += 1) {
1710
+ let t = [e + 1];
1711
+ for (let i = 0; i < r.length; i += 1) {
1712
+ let o = n[e] === r[i] ? 0 : 1;
1713
+ t.push(Math.min(t[i] + 1, a[i + 1] + 1, a[i] + o));
1714
+ }
1715
+ a.splice(0, a.length, ...t);
1716
+ }
1717
+ return ht(1 - a[r.length] / i, 0, 1);
1718
+ }
1719
+ function mt(e) {
1720
+ let t = /* @__PURE__ */ new Set();
1721
+ return e.filter((e) => {
1722
+ let n = dt(e);
1723
+ return !n || t.has(n) ? !1 : (t.add(n), !0);
1724
+ });
1725
+ }
1726
+ function ht(e, t, n) {
1727
+ return Math.min(n, Math.max(t, e));
1728
+ }
1729
+ //#endregion
1730
+ //#region src/exam-session/interactions/PronunciationRecorder.tsx
1731
+ function gt({ acceptedPronunciations: i, expectedText: s, imageAlt: c, imageSrc: l, instruction: u, language: d, minimumSimilarity: p, onChange: g, onReset: _, recorder: v, value: y }) {
1732
+ let [b, x] = r("idle"), [S, C] = r(null), [w, T] = r(0), E = n(null), D = n(!1), O = t(() => y ? ut(y.result.modelAiResult, s, {
1733
+ acceptedPronunciations: i,
1734
+ expectedLanguage: d,
1735
+ minimumSimilarity: p
1736
+ }) : null, [
1737
+ i,
1738
+ s,
1739
+ d,
1740
+ p,
1741
+ y
1742
+ ]);
1743
+ e(() => {
1744
+ if (b !== "recording") return;
1745
+ let e = window.setInterval(() => {
1746
+ let e = E.current;
1747
+ e !== null && T(Date.now() - e);
1748
+ }, 200);
1749
+ return () => window.clearInterval(e);
1750
+ }, [b]), e(() => () => {
1751
+ D.current && v?.stopRecording().catch(() => void 0);
1752
+ }, [v]);
1753
+ async function k() {
1754
+ if (b !== "recording") {
1755
+ x("checking"), C(null), _();
1756
+ try {
1757
+ if (!v) throw Error("مُسجِّل الصَّوت غَير مُتاحٍ فِي هذا التَّطبِيق.");
1758
+ let e = {
1759
+ ...lt,
1760
+ lang: d,
1761
+ maxDuration: 10
1762
+ };
1763
+ if (!(await v.startRecording(e)).started) throw Error("تعذّر بدء التسجيل الصوتي.");
1764
+ D.current = !0, E.current = Date.now(), T(0), x("recording");
1765
+ } catch (e) {
1766
+ D.current = !1, E.current = null, C(bt(e)), x("error");
1767
+ }
1768
+ }
1769
+ }
1770
+ async function A() {
1771
+ if (b === "recording") {
1772
+ x("processing"), C(null);
1773
+ try {
1774
+ if (!v) throw Error("مُسجِّل الصَّوت غَير مُتاحٍ فِي هذا التَّطبِيق.");
1775
+ let e = await v.stopRecording(), t = ut(e.modelAiResult, s, {
1776
+ acceptedPronunciations: i,
1777
+ expectedLanguage: d,
1778
+ minimumSimilarity: p
1779
+ });
1780
+ D.current = !1, E.current = null, T(e.duration), g({
1781
+ evaluation: t,
1782
+ kind: "audio-recording",
1783
+ result: e
1784
+ }), x("idle");
1785
+ } catch (e) {
1786
+ D.current = !1, E.current = null, C(bt(e)), x("error");
1787
+ }
1788
+ }
1789
+ }
1790
+ function j() {
1791
+ C(null), T(0), x("idle"), _();
1792
+ }
1793
+ let M = b === "checking" || b === "processing", N = b === "recording" ? w : y?.result.duration ?? w;
1794
+ return /* @__PURE__ */ o("div", {
1795
+ className: "audio-debug-card",
1796
+ "data-status": b,
1797
+ children: [
1798
+ /* @__PURE__ */ o("div", {
1799
+ className: "audio-pronunciation-target",
1800
+ children: [/* @__PURE__ */ a("div", {
1801
+ className: "audio-pronunciation-image-frame",
1802
+ children: /* @__PURE__ */ a("img", {
1803
+ alt: c,
1804
+ src: l
1805
+ })
1806
+ }), /* @__PURE__ */ o("div", {
1807
+ className: "audio-pronunciation-copy",
1808
+ children: [
1809
+ /* @__PURE__ */ o("span", { children: [
1810
+ "اُنْطِقِ الكَلِمَةَ بِـ",
1811
+ yt(d),
1812
+ ":"
1813
+ ] }),
1814
+ /* @__PURE__ */ a("strong", {
1815
+ dir: d === "ar" ? "rtl" : "ltr",
1816
+ children: s
1817
+ }),
1818
+ /* @__PURE__ */ a("p", { children: u })
1819
+ ]
1820
+ })]
1821
+ }),
1822
+ /* @__PURE__ */ o("div", {
1823
+ className: "audio-debug-card__hero",
1824
+ "aria-live": "polite",
1825
+ children: [/* @__PURE__ */ a("span", {
1826
+ className: "audio-debug-card__icon",
1827
+ "aria-hidden": "true",
1828
+ children: /* @__PURE__ */ a(f, {})
1829
+ }), /* @__PURE__ */ o("div", { children: [/* @__PURE__ */ a("strong", { children: xt(b, !!y) }), /* @__PURE__ */ a("span", { children: vt(N) })] })]
1830
+ }),
1831
+ /* @__PURE__ */ o("div", {
1832
+ className: "audio-debug-actions",
1833
+ children: [
1834
+ /* @__PURE__ */ o("button", {
1835
+ className: "audio-debug-button audio-debug-button--record",
1836
+ disabled: b === "recording" || M,
1837
+ onClick: k,
1838
+ type: "button",
1839
+ children: [/* @__PURE__ */ a(f, { "aria-hidden": "true" }), /* @__PURE__ */ a("span", { children: y ? "سَجِّلْ مُحاوَلَةً جَدِيدَةً" : "اِبْدَأِ التَّسْجِيلَ" })]
1840
+ }),
1841
+ /* @__PURE__ */ o("button", {
1842
+ className: "audio-debug-button audio-debug-button--stop",
1843
+ disabled: b !== "recording",
1844
+ onClick: A,
1845
+ type: "button",
1846
+ children: [/* @__PURE__ */ a(h, { "aria-hidden": "true" }), /* @__PURE__ */ a("span", { children: "أَنْهِ التَّسْجِيلَ" })]
1847
+ }),
1848
+ /* @__PURE__ */ o("button", {
1849
+ className: "audio-debug-button audio-debug-button--reset",
1850
+ disabled: b === "recording" || M || !y && !S,
1851
+ onClick: j,
1852
+ type: "button",
1853
+ children: [/* @__PURE__ */ a(m, { "aria-hidden": "true" }), /* @__PURE__ */ a("span", { children: "إِعادَةُ المُحاوَلَةِ" })]
1854
+ })
1855
+ ]
1856
+ }),
1857
+ S ? /* @__PURE__ */ a("p", {
1858
+ className: "audio-debug-message",
1859
+ role: "alert",
1860
+ children: S
1861
+ }) : null,
1862
+ y && O ? /* @__PURE__ */ o("section", {
1863
+ className: "audio-pronunciation-feedback",
1864
+ "data-outcome": O.status,
1865
+ "data-testid": "pronunciation-feedback",
1866
+ role: "status",
1867
+ children: [/* @__PURE__ */ o("div", {
1868
+ className: "audio-pronunciation-feedback__headline",
1869
+ children: [/* @__PURE__ */ a(_t, { status: O.status }), /* @__PURE__ */ o("div", { children: [/* @__PURE__ */ a("strong", { children: St(O.status) }), /* @__PURE__ */ a("span", { children: Ct(O.status, s) })] })]
1870
+ }), /* @__PURE__ */ o("div", {
1871
+ className: "audio-debug-metadata",
1872
+ children: [
1873
+ /* @__PURE__ */ a($, {
1874
+ label: "ما تَعَرَّفَ عَلَيْهِ النَّمُوذَجُ",
1875
+ value: O.detectedPronunciation || "—"
1876
+ }),
1877
+ /* @__PURE__ */ a($, {
1878
+ label: "نِسْبَةُ التَّطابُقِ",
1879
+ value: `${O.similarityPercent}%`
1880
+ }),
1881
+ /* @__PURE__ */ a($, {
1882
+ label: "ثِقَةُ النَّمُوذَجِ",
1883
+ value: `${O.confidencePercent}%`
1884
+ }),
1885
+ /* @__PURE__ */ a($, {
1886
+ label: "اللُّغَةُ",
1887
+ value: O.language.toUpperCase()
1888
+ }),
1889
+ /* @__PURE__ */ a($, {
1890
+ label: "زَمَنُ التَّحْلِيلِ",
1891
+ value: `${O.latencyMs} ms`
1892
+ }),
1893
+ /* @__PURE__ */ a($, {
1894
+ label: "عَدَدُ الرُّمُوزِ الصَّوْتِيَّةِ",
1895
+ value: O.timestamps.length.toString()
1896
+ })
1897
+ ]
1898
+ })]
1899
+ }) : null
1900
+ ]
1901
+ });
1902
+ }
1903
+ function _t({ status: e }) {
1904
+ return a(e === "correct" ? u : e === "no-speech" ? g : _, { "aria-hidden": "true" });
1905
+ }
1906
+ function $({ label: e, value: t }) {
1907
+ return /* @__PURE__ */ o("span", {
1908
+ className: "audio-debug-meta-card",
1909
+ children: [/* @__PURE__ */ a("small", { children: e }), /* @__PURE__ */ a("strong", {
1910
+ dir: "ltr",
1911
+ children: t
1912
+ })]
1913
+ });
1914
+ }
1915
+ function vt(e) {
1916
+ let t = Math.max(0, Math.round(e / 1e3)), n = Math.floor(t / 60), r = t % 60;
1917
+ return `${n.toString().padStart(2, "0")}:${r.toString().padStart(2, "0")}`;
1918
+ }
1919
+ function yt(e) {
1920
+ return e === "fr" ? "الفَرَنْسِيَّةِ" : "العَرَبِيَّةِ";
1921
+ }
1922
+ function bt(e) {
1923
+ let t = e;
1924
+ return t.code === "MISSING_PERMISSION" ? "يَجِبُ السَّماحُ بِاسْتِعْمالِ المِيكْرُوفُونِ لِتَسْجِيلِ الإِجابَةِ." : t.code === "MODEL_VOCAB_MISMATCH" ? "مَلَفُّ نَمُوذَجِ اللُّغَةِ لا يُطابِقُ قامُوسَهُ. يُرْجى تَصْحِيحُ مَلَفِّ النَّمُوذَجِ." : t.message ? t.message : typeof e == "string" ? e : "حَدَثَ خَطَأٌ أَثْناءَ تَسْجِيلِ الإِجابَةِ الصَّوْتِيَّةِ.";
1925
+ }
1926
+ function xt(e, t) {
1927
+ return e === "checking" ? "جارِي تَجْهِيزُ المِيكْرُوفُونِ" : e === "recording" ? "جارِي التَّسْجِيلُ... تَكَلَّمِ الآنَ" : e === "processing" ? "جارِي تَحْلِيلُ النُّطْقِ" : e === "error" ? "تَعَذَّرَ تَحْلِيلُ التَّسْجِيلِ" : t ? "اِكْتَمَلَ تَحْلِيلُ الإِجابَةِ" : "المِيكْرُوفُونُ جاهِزٌ";
1928
+ }
1929
+ function St(e) {
1930
+ return e === "correct" ? "أَحْسَنْتَ! إِجابَةٌ صَحِيحَةٌ" : e === "no-speech" ? "لَمْ نَسْمَعْ كَلِمَةً واضِحَةً" : e === "language-mismatch" ? "اُسْتُعْمِلَ نَمُوذَجُ لُغَةٍ مُخْتَلِفَةٍ" : "حاوِلْ مَرَّةً أُخْرى";
1931
+ }
1932
+ function Ct(e, t) {
1933
+ return e === "correct" ? `نَطَقْتَ «${t}» بِشَكْلٍ صَحِيحٍ.` : e === "no-speech" ? `قَرِّبْ فَمَكَ مِنَ المِيكْرُوفُونِ وَقُلْ «${t}».` : `اِسْتَمِعْ إِلى نُطْقِ «${t}» ثُمَّ أَعِدِ المُحاوَلَةَ.`;
1934
+ }
1935
+ //#endregion
1936
+ //#region src/exam-session/interactions/SortableAnswer.tsx
1937
+ function wt({ answerId: e, items: t, value: n, onChange: r }) {
1938
+ let i = new Map(t.map((e) => [e.id, e])), o = n?.itemIds.length === t.length ? n.itemIds.filter((e) => i.has(e)) : t.map((e) => e.id);
1939
+ return /* @__PURE__ */ a(s, {
1940
+ onDragEnd: (e) => {
1941
+ e.canceled || r({
1942
+ kind: "order",
1943
+ itemIds: E(o, e).map((e) => e.toString())
1944
+ });
1945
+ },
1946
+ children: /* @__PURE__ */ a("div", {
1947
+ className: "sortable-answer",
1948
+ children: o.map((t, n) => {
1949
+ let r = i.get(t);
1950
+ return r ? /* @__PURE__ */ a(Tt, {
1951
+ group: e,
1952
+ index: n,
1953
+ item: r
1954
+ }, r.id) : null;
1955
+ })
1956
+ })
1957
+ });
1958
+ }
1959
+ function Tt({ group: e, index: t, item: n }) {
1960
+ let { ref: r, isDragging: i, isDropTarget: o } = D({
1961
+ id: n.id,
1962
+ index: t,
1963
+ group: e,
1964
+ type: "sortable-answer"
1965
+ });
1966
+ return /* @__PURE__ */ a("button", {
1967
+ className: [
1968
+ "sortable-token",
1969
+ i ? "sortable-token--dragging" : "",
1970
+ o ? "sortable-token--target" : ""
1971
+ ].filter(Boolean).join(" "),
1972
+ ref: r,
1973
+ type: "button",
1974
+ children: n.label
1975
+ });
1976
+ }
1977
+ //#endregion
1978
+ //#region src/exam-session/interactions/TextAnswer.tsx
1979
+ function Et({ ariaLabel: e, className: t, inputMode: n = "text", value: r, onChange: i }) {
1980
+ return /* @__PURE__ */ a("input", {
1981
+ "aria-label": e,
1982
+ className: t,
1983
+ inputMode: n,
1984
+ onChange: (e) => i({
1985
+ kind: "text",
1986
+ value: e.target.value
1987
+ }),
1988
+ value: r?.value ?? ""
1989
+ });
1990
+ }
1991
+ //#endregion
1992
+ //#region src/renderer/QuestionRenderer.tsx
1993
+ function Dt({ adapters: e, clearAnswer: t, question: n, getAnswer: r, updateAnswer: i }) {
1994
+ return /* @__PURE__ */ o("article", {
1995
+ className: `question-block question-block--${n.type}`,
1996
+ children: [/* @__PURE__ */ a(kt, {
1997
+ number: n.number,
1998
+ prompt: n.prompt
1999
+ }), At(n, r, i, t, e)]
2000
+ });
2001
+ }
2002
+ function Ot({ adapters: e, clearAnswer: t, section: n, getAnswer: r, updateAnswer: i }) {
2003
+ return /* @__PURE__ */ o("section", {
2004
+ className: `question-section question-section--${n.tone}`,
2005
+ children: [/* @__PURE__ */ o("header", {
2006
+ className: "section-heading",
2007
+ children: [
2008
+ /* @__PURE__ */ o("span", {
2009
+ className: "section-points",
2010
+ children: [/* @__PURE__ */ a("small", { children: "ن" }), n.points]
2011
+ }),
2012
+ /* @__PURE__ */ a("h3", { children: n.title }),
2013
+ /* @__PURE__ */ a("span", {
2014
+ className: "section-badge",
2015
+ children: n.badge
2016
+ })
2017
+ ]
2018
+ }), /* @__PURE__ */ a("div", {
2019
+ className: "section-body",
2020
+ children: n.questions.map((n) => /* @__PURE__ */ a(Dt, {
2021
+ adapters: e,
2022
+ clearAnswer: t,
2023
+ getAnswer: r,
2024
+ question: n,
2025
+ updateAnswer: i
2026
+ }, n.id))
2027
+ })]
2028
+ });
2029
+ }
2030
+ function kt({ number: e, prompt: t }) {
2031
+ return /* @__PURE__ */ o("div", {
2032
+ className: "question-prompt",
2033
+ children: [e > 0 ? /* @__PURE__ */ a("span", { children: e }) : null, /* @__PURE__ */ a("strong", { children: t })]
2034
+ });
2035
+ }
2036
+ function At(e, t, n, r, s) {
2037
+ switch (e.type) {
2038
+ case "inline-inputs": return /* @__PURE__ */ a("div", {
2039
+ className: "inline-equation-grid",
2040
+ children: e.items.map((i) => {
2041
+ let c = `${e.id}:${i.id}`;
2042
+ return /* @__PURE__ */ o("div", {
2043
+ className: "equation-card",
2044
+ children: [
2045
+ /* @__PURE__ */ a("span", { children: i.before }),
2046
+ /* @__PURE__ */ a(q, {
2047
+ ariaLabel: i.before,
2048
+ onChange: (e) => n(c, e),
2049
+ onClear: () => r(c),
2050
+ recognizer: s?.handwritingRecognizer,
2051
+ value: Mt(t(c))
2052
+ }),
2053
+ i.after ? /* @__PURE__ */ a("span", { children: i.after }) : null
2054
+ ]
2055
+ }, i.id);
2056
+ })
2057
+ });
2058
+ case "visual-choice": return /* @__PURE__ */ o(i, { children: [/* @__PURE__ */ a(Ut, {
2059
+ choices: e.choices,
2060
+ onChange: (t) => n(e.id, t),
2061
+ value: Pt(t(e.id)),
2062
+ visual: e.visual
2063
+ }), e.inputLabel ? /* @__PURE__ */ o("div", {
2064
+ className: "compact-answer",
2065
+ children: [/* @__PURE__ */ a("span", { children: e.inputLabel }), /* @__PURE__ */ a(q, {
2066
+ ariaLabel: e.inputLabel,
2067
+ onChange: (t) => n(`${e.id}:input`, t),
2068
+ onClear: () => r(`${e.id}:input`),
2069
+ recognizer: s?.handwritingRecognizer,
2070
+ value: Mt(t(`${e.id}:input`))
2071
+ })]
2072
+ }) : null] });
2073
+ case "number-line": return /* @__PURE__ */ a(st, {
2074
+ answerId: e.id,
2075
+ expression: e.expression,
2076
+ onClear: r,
2077
+ onChange: n,
2078
+ recognizer: s?.handwritingRecognizer,
2079
+ value: Mt(t(e.id))
2080
+ });
2081
+ case "equation-inputs": return /* @__PURE__ */ a("div", {
2082
+ className: "stacked-equations",
2083
+ children: e.items.map((i) => {
2084
+ let c = `${e.id}:${i.id}`;
2085
+ return /* @__PURE__ */ o("div", {
2086
+ className: "wide-equation-card",
2087
+ children: [
2088
+ /* @__PURE__ */ a("span", { children: i.before }),
2089
+ /* @__PURE__ */ a(q, {
2090
+ ariaLabel: `${e.prompt} ${i.before}`,
2091
+ onChange: (e) => n(c, e),
2092
+ onClear: () => r(c),
2093
+ recognizer: s?.handwritingRecognizer,
2094
+ value: Mt(t(c))
2095
+ }),
2096
+ i.after ? /* @__PURE__ */ a("span", { children: i.after }) : null
2097
+ ]
2098
+ }, i.id);
2099
+ })
2100
+ });
2101
+ case "length-estimation": return /* @__PURE__ */ a(Wt, {
2102
+ answerId: e.id,
2103
+ choices: e.choices,
2104
+ getAnswer: t,
2105
+ items: e.items,
2106
+ updateAnswer: n
2107
+ });
2108
+ case "shape-choice": return /* @__PURE__ */ o("div", {
2109
+ className: "shape-choice-layout",
2110
+ children: [/* @__PURE__ */ a(me, {
2111
+ items: e.choices.map((e) => ({
2112
+ id: `${e.id}-label`,
2113
+ label: e.label
2114
+ })),
2115
+ onChange: (t) => n(e.id, t),
2116
+ targets: e.choices.map((e) => ({
2117
+ id: `${e.id}-target`,
2118
+ label: Bt(e.id)
2119
+ })),
2120
+ value: Pt(t(e.id))
2121
+ }), /* @__PURE__ */ a("div", {
2122
+ className: "shape-row",
2123
+ "aria-hidden": "true",
2124
+ children: e.choices.map((e) => /* @__PURE__ */ a("span", { className: `shape-drawing shape-drawing--${e.id}` }, e.id))
2125
+ })]
2126
+ });
2127
+ case "drawing-grid": return /* @__PURE__ */ a(rt, {
2128
+ actionLabel: e.actionLabel,
2129
+ onChange: (t) => n(e.id, t),
2130
+ points: e.points,
2131
+ value: Lt(t(e.id))
2132
+ });
2133
+ case "table-response": return /* @__PURE__ */ a(pe, {
2134
+ columns: e.columns,
2135
+ onChange: (t) => n(e.id, t),
2136
+ value: Rt(t(e.id))
2137
+ });
2138
+ case "text-input": return e.before && !e.after && e.number === 0 ? /* @__PURE__ */ a("p", {
2139
+ className: "problem-statement",
2140
+ children: e.before
2141
+ }) : /* @__PURE__ */ o("div", {
2142
+ className: "sentence-answer",
2143
+ children: [
2144
+ e.before ? /* @__PURE__ */ a("span", { children: e.before }) : null,
2145
+ /* @__PURE__ */ a(q, {
2146
+ ariaLabel: e.prompt,
2147
+ onChange: (t) => n(e.id, t),
2148
+ onClear: () => r(e.id),
2149
+ recognizer: s?.handwritingRecognizer,
2150
+ value: Mt(t(e.id))
2151
+ }),
2152
+ e.after ? /* @__PURE__ */ a("span", { children: e.after }) : null
2153
+ ]
2154
+ });
2155
+ case "drag-match": return /* @__PURE__ */ a(me, {
2156
+ items: e.items,
2157
+ onChange: (t) => n(e.id, t),
2158
+ targets: e.targets,
2159
+ value: Pt(t(e.id))
2160
+ });
2161
+ case "sortable-answer": return /* @__PURE__ */ a(wt, {
2162
+ answerId: e.id,
2163
+ items: e.items,
2164
+ onChange: (t) => n(e.id, t),
2165
+ value: Ft(t(e.id))
2166
+ });
2167
+ case "label-placement": return /* @__PURE__ */ a(it, {
2168
+ labels: e.labels,
2169
+ onChange: (t) => n(e.id, t),
2170
+ targets: e.targets,
2171
+ value: It(t(e.id))
2172
+ });
2173
+ case "audio-recording": return /* @__PURE__ */ a(gt, {
2174
+ acceptedPronunciations: e.acceptedPronunciations,
2175
+ expectedText: e.expectedAnswer,
2176
+ imageAlt: e.imageAlt,
2177
+ imageSrc: e.imageSrc,
2178
+ instruction: e.instruction,
2179
+ language: e.language,
2180
+ minimumSimilarity: e.minimumSimilarity,
2181
+ onChange: (t) => n(e.id, t),
2182
+ onReset: () => r(e.id),
2183
+ recorder: s?.audioRecorder,
2184
+ value: zt(t(e.id))
2185
+ });
2186
+ }
2187
+ }
2188
+ function jt(e) {
2189
+ return e?.kind === "text" ? e : void 0;
2190
+ }
2191
+ function Mt(e) {
2192
+ return e?.kind === "handwritten-number" ? e : void 0;
2193
+ }
2194
+ function Nt(e) {
2195
+ return e?.kind === "choice" ? e : void 0;
2196
+ }
2197
+ function Pt(e) {
2198
+ return e?.kind === "matches" ? e : void 0;
2199
+ }
2200
+ function Ft(e) {
2201
+ return e?.kind === "order" ? e : void 0;
2202
+ }
2203
+ function It(e) {
2204
+ return e?.kind === "placements" ? e : void 0;
2205
+ }
2206
+ function Lt(e) {
2207
+ return e?.kind === "drawing" ? e : void 0;
2208
+ }
2209
+ function Rt(e) {
2210
+ return e?.kind === "coin-table" ? e : void 0;
2211
+ }
2212
+ function zt(e) {
2213
+ return e?.kind === "audio-recording" ? e : void 0;
2214
+ }
2215
+ function Bt(e) {
2216
+ return e === "triangle" ? "△" : e === "square" ? "□" : e === "rectangle" ? "▭" : e;
2217
+ }
2218
+ function Vt({ variant: e }) {
2219
+ return e === "counter-rows" ? /* @__PURE__ */ o("div", {
2220
+ className: "visual-panel visual-panel--counters",
2221
+ "aria-hidden": "true",
2222
+ children: [/* @__PURE__ */ a("div", { children: Array.from({ length: 5 }, (e, t) => /* @__PURE__ */ a("span", { className: "counter-dot" }, `top-${t}`)) }), /* @__PURE__ */ a("div", { children: Array.from({ length: 4 }, (e, t) => /* @__PURE__ */ a("span", { className: "counter-dot counter-dot--crossed" }, `bottom-${t}`)) })]
2223
+ }) : /* @__PURE__ */ o("div", {
2224
+ className: "visual-panel visual-panel--suns",
2225
+ "aria-hidden": "true",
2226
+ children: [/* @__PURE__ */ a("div", { children: Array.from({ length: 4 }, (e, t) => /* @__PURE__ */ a("span", {
2227
+ className: "sun-icon",
2228
+ children: "☀"
2229
+ }, `sun-${t}`)) }), /* @__PURE__ */ a("div", { children: Array.from({ length: 2 }, (e, t) => /* @__PURE__ */ a("span", {
2230
+ className: "star-outline",
2231
+ children: "✩"
2232
+ }, `star-${t}`)) })]
2233
+ });
2234
+ }
2235
+ var Ht = "picture";
2236
+ function Ut({ choices: t, onChange: i, value: s, visual: c }) {
2237
+ let l = n(null), u = n(null), d = n({}), f = n(null), p = s?.pairs[Ht], [m, h] = r(null), [g, _] = r(null);
2238
+ function v(e, t) {
2239
+ let n = l.current;
2240
+ if (!n) return null;
2241
+ let r = n.getBoundingClientRect();
2242
+ return {
2243
+ x: e - r.left,
2244
+ y: t - r.top
2245
+ };
2246
+ }
2247
+ function y(e) {
2248
+ if (!e) return null;
2249
+ let t = e.getBoundingClientRect();
2250
+ return v(t.left + t.width / 2, t.top + t.height / 2);
2251
+ }
2252
+ e(() => {
2253
+ function e(e) {
2254
+ let t = l.current;
2255
+ if (!t || !e) return null;
2256
+ let n = t.getBoundingClientRect(), r = e.getBoundingClientRect();
2257
+ return {
2258
+ x: r.left + r.width / 2 - n.left,
2259
+ y: r.top + r.height / 2 - n.top
2260
+ };
2261
+ }
2262
+ function t() {
2263
+ if (!p) {
2264
+ h(null);
2265
+ return;
2266
+ }
2267
+ let t = e(d.current[p]), n = e(u.current);
2268
+ if (!t || !n) {
2269
+ h(null);
2270
+ return;
2271
+ }
2272
+ h({
2273
+ x1: t.x,
2274
+ x2: n.x,
2275
+ y1: t.y,
2276
+ y2: n.y
2277
+ });
2278
+ }
2279
+ let n = window.setTimeout(t, 0), r = () => t();
2280
+ return window.addEventListener("resize", r), () => {
2281
+ window.clearTimeout(n), window.removeEventListener("resize", r);
2282
+ };
2283
+ }, [p]);
2284
+ function b(e, t) {
2285
+ let n = y(t.currentTarget), r = v(t.clientX, t.clientY);
2286
+ !n || !r || (t.preventDefault(), t.currentTarget.setPointerCapture(t.pointerId), f.current = {
2287
+ choiceId: e,
2288
+ origin: "answer",
2289
+ pointerId: t.pointerId
2290
+ }, _({
2291
+ x1: n.x,
2292
+ x2: r.x,
2293
+ y1: n.y,
2294
+ y2: r.y
2295
+ }));
2296
+ }
2297
+ function x(e) {
2298
+ let t = y(u.current), n = v(e.clientX, e.clientY);
2299
+ !t || !n || (e.preventDefault(), e.currentTarget.setPointerCapture(e.pointerId), f.current = {
2300
+ origin: "target",
2301
+ pointerId: e.pointerId
2302
+ }, _({
2303
+ x1: t.x,
2304
+ x2: n.x,
2305
+ y1: t.y,
2306
+ y2: n.y
2307
+ }));
2308
+ }
2309
+ function S(e) {
2310
+ let t = f.current;
2311
+ if (!t || t.pointerId !== e.pointerId) return;
2312
+ let n = v(e.clientX, e.clientY), r = y(t.origin === "answer" && t.choiceId ? d.current[t.choiceId] : u.current);
2313
+ !r || !n || _({
2314
+ x1: r.x,
2315
+ x2: n.x,
2316
+ y1: r.y,
2317
+ y2: n.y
2318
+ });
2319
+ }
2320
+ function C(e) {
2321
+ let t = f.current;
2322
+ if (!(!t || t.pointerId !== e.pointerId)) {
2323
+ if (e.currentTarget.hasPointerCapture(e.pointerId) && e.currentTarget.releasePointerCapture(e.pointerId), t.origin === "answer" && t.choiceId && w(u.current, e.clientX, e.clientY) && i({
2324
+ kind: "matches",
2325
+ pairs: { [Ht]: t.choiceId }
2326
+ }), t.origin === "target") {
2327
+ let t = T(e.clientX, e.clientY);
2328
+ t && i({
2329
+ kind: "matches",
2330
+ pairs: { [Ht]: t }
2331
+ });
2332
+ }
2333
+ f.current = null, _(null);
2334
+ }
2335
+ }
2336
+ function w(e, t, n) {
2337
+ if (!e) return !1;
2338
+ let r = e.getBoundingClientRect(), i = r.left + r.width / 2, a = r.top + r.height / 2;
2339
+ return Math.hypot(t - i, n - a) <= Math.max(r.width, r.height) * 1.5;
2340
+ }
2341
+ function T(e, n) {
2342
+ return t.find((t) => w(d.current[t.id], e, n))?.id;
2343
+ }
2344
+ return /* @__PURE__ */ o("div", {
2345
+ className: "visual-line-match",
2346
+ ref: l,
2347
+ children: [
2348
+ /* @__PURE__ */ o("svg", {
2349
+ className: "visual-line-match__lines",
2350
+ "aria-hidden": "true",
2351
+ children: [m ? /* @__PURE__ */ a("line", {
2352
+ className: "visual-line-match__line visual-line-match__line--settled",
2353
+ x1: m.x1,
2354
+ x2: m.x2,
2355
+ y1: m.y1,
2356
+ y2: m.y2
2357
+ }) : null, g ? /* @__PURE__ */ a("line", {
2358
+ className: "visual-line-match__line visual-line-match__line--draft",
2359
+ x1: g.x1,
2360
+ x2: g.x2,
2361
+ y1: g.y1,
2362
+ y2: g.y2
2363
+ }) : null]
2364
+ }),
2365
+ /* @__PURE__ */ o("div", {
2366
+ className: "visual-match-picture",
2367
+ children: [/* @__PURE__ */ a(Vt, { variant: c }), /* @__PURE__ */ a("button", {
2368
+ "aria-label": "اربط الصورة بالإجابة",
2369
+ className: p ? "visual-match-point visual-match-point--target visual-match-point--target-active" : "visual-match-point visual-match-point--target",
2370
+ onPointerCancel: C,
2371
+ onPointerDown: x,
2372
+ onPointerMove: S,
2373
+ onPointerUp: C,
2374
+ ref: u,
2375
+ type: "button"
2376
+ })]
2377
+ }),
2378
+ /* @__PURE__ */ a("div", {
2379
+ className: "visual-line-match__answers",
2380
+ children: t.map((e) => /* @__PURE__ */ o("div", {
2381
+ className: p === e.id ? "visual-match-answer visual-match-answer--matched" : "visual-match-answer",
2382
+ children: [/* @__PURE__ */ a("span", {
2383
+ className: "answer-chip__label answer-chip__label--math",
2384
+ children: e.label
2385
+ }), /* @__PURE__ */ a("button", {
2386
+ "aria-label": `اربط ${e.label} بالصورة`,
2387
+ className: "visual-match-point visual-match-point--answer",
2388
+ onPointerCancel: C,
2389
+ onPointerDown: (t) => b(e.id, t),
2390
+ onPointerMove: S,
2391
+ onPointerUp: C,
2392
+ ref: (t) => {
2393
+ d.current[e.id] = t;
2394
+ },
2395
+ type: "button"
2396
+ })]
2397
+ }, e.id))
2398
+ })
2399
+ ]
2400
+ });
2401
+ }
2402
+ function Wt({ answerId: e, choices: t, getAnswer: i, items: s, updateAnswer: c }) {
2403
+ let l = Math.max(...s.map((e) => e.squareLength)) + 2, u = Ce(t), [d, f] = r(null), [p, m] = r(!1), [h, g] = r({}), _ = n(null);
2404
+ function v(e, t, n) {
2405
+ let r = d;
2406
+ r && g((i) => {
2407
+ let a = i[e], o = a?.colorId === r ? a.fill : 0, s = Math.min(1, o + n);
2408
+ return s >= .92 && c(t, {
2409
+ choiceId: r,
2410
+ kind: "choice"
2411
+ }), {
2412
+ ...i,
2413
+ [e]: {
2414
+ colorId: r,
2415
+ fill: s
2416
+ }
2417
+ };
2418
+ });
2419
+ }
2420
+ function y(e, t, n) {
2421
+ n.preventDefault(), n.currentTarget.setPointerCapture(n.pointerId), _.current = {
2422
+ colorAnswerId: t,
2423
+ itemId: e,
2424
+ lastClientX: n.clientX
2425
+ }, m(!0), v(e, t, .08);
2426
+ }
2427
+ function b(e, t, n) {
2428
+ let r = _.current;
2429
+ if (!r || r.itemId !== e) return;
2430
+ let i = Math.max(n.currentTarget.getBoundingClientRect().width, 1), a = Math.abs(n.clientX - r.lastClientX) / i;
2431
+ _.current = {
2432
+ colorAnswerId: t,
2433
+ itemId: e,
2434
+ lastClientX: n.clientX
2435
+ }, a > 0 && v(e, t, a * 1.25);
2436
+ }
2437
+ function x(e) {
2438
+ e?.currentTarget.hasPointerCapture(e.pointerId) && e.currentTarget.releasePointerCapture(e.pointerId), _.current = null, m(!1);
2439
+ }
2440
+ return /* @__PURE__ */ o("div", {
2441
+ className: "length-estimation-task",
2442
+ "data-coloring": p ? "true" : "false",
2443
+ onPointerCancel: () => x(),
2444
+ onPointerUp: () => x(),
2445
+ children: [/* @__PURE__ */ a(ye, {
2446
+ ariaLabel: "ألوان الأقلام",
2447
+ className: "length-color-picker",
2448
+ colors: u,
2449
+ onChange: f,
2450
+ selectedColorId: d
2451
+ }), /* @__PURE__ */ a("div", {
2452
+ className: "length-card-row",
2453
+ children: s.map((t) => {
2454
+ let n = `${e}:squares:${t.id}`, r = `${e}:color:${t.id}`, s = Nt(i(r)), d = h[t.id], f = d?.colorId ?? s?.choiceId, p = d?.fill ?? +!!s?.choiceId, m = f ? Se(u, f) : "#9aa3a8", g = `${16 + Math.min(p, 1) * 68}%`;
2455
+ return /* @__PURE__ */ o("div", {
2456
+ className: "length-card",
2457
+ children: [/* @__PURE__ */ a("div", {
2458
+ className: "square-measure-strip",
2459
+ style: { "--measure-squares": l },
2460
+ children: /* @__PURE__ */ a("button", {
2461
+ "aria-label": `تلوين ${t.label}`,
2462
+ className: [
2463
+ "pencil-pencil",
2464
+ "pencil-pencil--paint-target",
2465
+ p > 0 ? "pencil-pencil--colored" : ""
2466
+ ].filter(Boolean).join(" "),
2467
+ onKeyDown: (e) => {
2468
+ (e.key === "Enter" || e.key === " ") && (e.preventDefault(), v(t.id, r, .22));
2469
+ },
2470
+ onPointerDown: (e) => {
2471
+ y(t.id, r, e);
2472
+ },
2473
+ onPointerMove: (e) => {
2474
+ b(t.id, r, e);
2475
+ },
2476
+ onPointerUp: x,
2477
+ style: {
2478
+ "--pencil-color": m,
2479
+ "--pencil-fill-end": g,
2480
+ "--pencil-squares": t.squareLength,
2481
+ "--pencil-start-square": 1
2482
+ },
2483
+ type: "button"
2484
+ })
2485
+ }), /* @__PURE__ */ o("label", {
2486
+ className: "length-value-row",
2487
+ children: [
2488
+ /* @__PURE__ */ a("span", { children: t.label }),
2489
+ /* @__PURE__ */ a(Et, {
2490
+ ariaLabel: `طول ${t.label} بالمربعات`,
2491
+ inputMode: "numeric",
2492
+ onChange: (e) => c(n, e),
2493
+ value: jt(i(n))
2494
+ }),
2495
+ /* @__PURE__ */ a("span", { children: "مربعات" })
2496
+ ]
2497
+ })]
2498
+ }, t.id);
2499
+ })
2500
+ })]
2501
+ });
2502
+ }
2503
+ //#endregion
2504
+ //#region src/renderer/QuestionPreviewPanel.tsx
2505
+ function Gt({ adapters: e, question: t }) {
2506
+ let [n, i] = r({});
2507
+ function o(e, t) {
2508
+ i((n) => ({
2509
+ ...n,
2510
+ [e]: t
2511
+ }));
2512
+ }
2513
+ function s(e) {
2514
+ i((t) => {
2515
+ let n = { ...t };
2516
+ return delete n[e], n;
2517
+ });
2518
+ }
2519
+ return /* @__PURE__ */ a("div", {
2520
+ className: "exam-renderer-preview",
2521
+ children: /* @__PURE__ */ a(Dt, {
2522
+ adapters: e,
2523
+ clearAnswer: s,
2524
+ getAnswer: (e) => n[e],
2525
+ question: t,
2526
+ updateAnswer: o
2527
+ })
2528
+ });
2529
+ }
2530
+ //#endregion
2531
+ //#region src/exam-session/interactions/DraftSheet.tsx
2532
+ function Kt({ disabled: e, onChange: t, value: n }) {
2533
+ let [i, s] = r(!1);
2534
+ return /* @__PURE__ */ a("aside", {
2535
+ className: "draft-sheet",
2536
+ "data-disabled": e ? "true" : "false",
2537
+ "data-open": i ? "true" : "false",
2538
+ dir: "rtl",
2539
+ children: i ? /* @__PURE__ */ o("div", {
2540
+ className: "draft-sheet__panel",
2541
+ "aria-label": "ورقة وساخ",
2542
+ children: [/* @__PURE__ */ o("header", {
2543
+ className: "draft-sheet__header",
2544
+ children: [/* @__PURE__ */ a("strong", { children: "ورقة وساخ" }), /* @__PURE__ */ a("button", {
2545
+ onClick: () => s(!1),
2546
+ type: "button",
2547
+ children: "إِغْلاقٌ"
2548
+ })]
2549
+ }), /* @__PURE__ */ a(je, {
2550
+ actionLabel: "مساحة ورقة وساخ",
2551
+ canvasHeight: 430,
2552
+ disabled: e,
2553
+ onChange: t,
2554
+ value: n,
2555
+ variant: "draft"
2556
+ })]
2557
+ }) : /* @__PURE__ */ o("button", {
2558
+ className: "draft-sheet__toggle",
2559
+ disabled: e,
2560
+ onClick: () => s(!0),
2561
+ type: "button",
2562
+ children: [/* @__PURE__ */ a(p, { "aria-hidden": "true" }), /* @__PURE__ */ a("span", { children: "ورقة وساخ" })]
2563
+ })
2564
+ });
2565
+ }
2566
+ //#endregion
2567
+ //#region src/exam-session/interactions/SingleChoice.tsx
2568
+ function qt({ answerId: e, choices: t, value: n, onChange: r }) {
2569
+ return /* @__PURE__ */ a("div", {
2570
+ className: "choice-group",
2571
+ role: "radiogroup",
2572
+ "aria-label": `اِخْتِياراتُ الإِجابَةِ ${e}`,
2573
+ children: t.map((e) => {
2574
+ let t = /[0-9+\-=]/.test(e.label);
2575
+ return /* @__PURE__ */ a("button", {
2576
+ "aria-checked": n?.choiceId === e.id,
2577
+ className: n?.choiceId === e.id ? "answer-chip answer-chip--selected" : "answer-chip",
2578
+ onClick: () => r({
2579
+ kind: "choice",
2580
+ choiceId: e.id
2581
+ }),
2582
+ role: "radio",
2583
+ type: "button",
2584
+ children: /* @__PURE__ */ a("span", {
2585
+ className: t ? "answer-chip__label answer-chip__label--math" : "answer-chip__label",
2586
+ children: e.label
2587
+ })
2588
+ }, e.id);
2589
+ })
2590
+ });
2591
+ }
2592
+ //#endregion
2593
+ export { pe as CoinTableResponse, ye as ColorPenPicker, J as DEFAULT_GEOMETRY_COLORS, lt as DEFAULT_NATIVE_VOICE_AI_CONFIG, Kt as DraftSheet, me as DragMatch, Ot as ExamSectionRenderer, je as GeometryCanvas, q as HandwrittenNumberAnswer, rt as KonvaDrawingGrid, it as LabelPlacement, st as NumberLineAnswer, gt as PronunciationRecorder, Gt as QuestionPreviewPanel, Dt as QuestionRenderer, qt as SingleChoice, wt as SortableAnswer, Et as TextAnswer, j as calculateExamResult, ut as evaluateVoiceAiResult, Se as getColorValue, xe as getDefaultColorId, Ce as mapChoicesToGeometryColors, dt as normalizeVoiceText };