@pie-element/venn-classification 0.1.1-next.6 → 0.1.1-next.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/author.js +2 -0
- package/dist/author/index.d.ts +6 -0
- package/dist/author/index.js +3881 -888
- package/dist/author/index.js.map +1 -1
- package/dist/browser/VennClassification-DtbNF8RE.js +3696 -0
- package/dist/browser/VennClassification-DtbNF8RE.js.map +1 -0
- package/dist/browser/author/index.js +3428 -3353
- package/dist/browser/author/index.js.map +1 -1
- package/dist/browser/controller/index.js +2 -2
- package/dist/browser/controller-jTPoghNQ.js +1776 -0
- package/dist/browser/controller-jTPoghNQ.js.map +1 -0
- package/dist/browser/delivery/index.js +6 -4
- package/dist/browser/delivery/index.js.map +1 -1
- package/dist/controller/index.d.ts +21 -7
- package/dist/controller/index.js +2396 -49
- package/dist/controller/index.js.map +1 -1
- package/dist/controller/region.d.ts +2 -2
- package/dist/delivery/dnd.d.ts +9 -0
- package/dist/delivery/index.d.ts +12 -0
- package/dist/delivery/index.js +3712 -727
- package/dist/delivery/index.js.map +1 -1
- package/dist/delivery/layout.d.ts +104 -34
- package/dist/delivery/tile-accessible-name.d.ts +13 -1
- package/dist/i18n.d.ts +9 -0
- package/dist/index.iife.js +14 -17
- package/dist/index.js +3712 -727
- package/dist/index.js.map +1 -1
- package/dist/types.d.ts +7 -0
- package/package.json +2 -1
- package/dist/browser/VennClassification-DCPzzIcj.js +0 -3386
- package/dist/browser/VennClassification-DCPzzIcj.js.map +0 -1
- package/dist/browser/controller-DGuLVZuv.js +0 -249
- package/dist/browser/controller-DGuLVZuv.js.map +0 -1
|
@@ -1,249 +0,0 @@
|
|
|
1
|
-
//#region src/controller/region.ts
|
|
2
|
-
function e(e) {
|
|
3
|
-
return !e || e.length === 0 ? "" : [...e].sort((e, t) => e - t).join(",");
|
|
4
|
-
}
|
|
5
|
-
function t(e) {
|
|
6
|
-
return !e || e.length === 0 ? [] : [...e].sort((e, t) => e - t);
|
|
7
|
-
}
|
|
8
|
-
function n(e, n) {
|
|
9
|
-
if (!e || !n) return !e == !n && (e?.length ?? 0) === (n?.length ?? 0);
|
|
10
|
-
if (e.length !== n.length) return !1;
|
|
11
|
-
let r = t(e), i = t(n);
|
|
12
|
-
for (let e = 0; e < r.length; e++) if (r[e] !== i[e]) return !1;
|
|
13
|
-
return !0;
|
|
14
|
-
}
|
|
15
|
-
function r(e) {
|
|
16
|
-
let t = [], n = 1 << e;
|
|
17
|
-
for (let r = 0; r < n; r++) {
|
|
18
|
-
let n = [];
|
|
19
|
-
for (let t = 0; t < e; t++) r & 1 << t && n.push(t);
|
|
20
|
-
t.push(n);
|
|
21
|
-
}
|
|
22
|
-
return t;
|
|
23
|
-
}
|
|
24
|
-
function i(e, n) {
|
|
25
|
-
let r = t(n), i = r.map((t) => e[t]?.label ?? `Set ${t + 1}`), a = e.length;
|
|
26
|
-
return r.length === 0 ? a === 2 ? `Neither ${e[0]?.label ?? "Set 1"} nor ${e[1]?.label ?? "Set 2"}` : `None of ${e.map((e, t) => e?.label ?? `Set ${t + 1}`).join(", ")}` : r.length === 1 ? `${i[0]} only` : i.join(" and ");
|
|
27
|
-
}
|
|
28
|
-
function a(t, n) {
|
|
29
|
-
let r = e(n), a = t.regionLabels?.[r];
|
|
30
|
-
return typeof a == "string" && a.trim().length > 0 ? a : i(t.circles ?? [], n);
|
|
31
|
-
}
|
|
32
|
-
var o = {
|
|
33
|
-
model: {
|
|
34
|
-
id: "1",
|
|
35
|
-
element: "venn-classification",
|
|
36
|
-
prompt: "<p>Sort each tile into the correct region of the Venn diagram.</p>",
|
|
37
|
-
promptEnabled: !0,
|
|
38
|
-
circles: [{ label: "Set A" }, { label: "Set B" }],
|
|
39
|
-
tiles: [],
|
|
40
|
-
regionLabels: {},
|
|
41
|
-
scoringPolicy: "partialPerTile"
|
|
42
|
-
},
|
|
43
|
-
configuration: {
|
|
44
|
-
prompt: {
|
|
45
|
-
label: "Prompt",
|
|
46
|
-
settings: !0
|
|
47
|
-
},
|
|
48
|
-
scoringPolicy: {
|
|
49
|
-
label: "Scoring policy",
|
|
50
|
-
settings: !0
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
}, s = /* @__PURE__ */ new Set([2]), c = (e) => !!e && typeof e == "object" && !Array.isArray(e) && Object.keys(e).length === 0;
|
|
54
|
-
function l(e) {
|
|
55
|
-
return String(e ?? "").replace(/<[^>]+>/g, " ").replace(/\s+/g, " ").trim();
|
|
56
|
-
}
|
|
57
|
-
function u(e = {}) {
|
|
58
|
-
let t = {
|
|
59
|
-
...o.model,
|
|
60
|
-
...e
|
|
61
|
-
};
|
|
62
|
-
return (!Array.isArray(t.circles) || t.circles.length === 0) && (t.circles = o.model.circles.map((e) => ({ ...e }))), Array.isArray(t.tiles) || (t.tiles = []), (!t.regionLabels || typeof t.regionLabels != "object") && (t.regionLabels = {}), t.scoringPolicy !== "allOrNothing" && t.scoringPolicy !== "partialPerTile" && (t.scoringPolicy = "partialPerTile"), t;
|
|
63
|
-
}
|
|
64
|
-
function d(e, n) {
|
|
65
|
-
let r = { ...e || {} }, i = e?.placements ?? {}, a = {};
|
|
66
|
-
for (let [e, n] of Object.entries(i)) n == null ? a[e] = null : Array.isArray(n) ? a[e] = t(n) : a[e] = null;
|
|
67
|
-
if (n?.tiles) for (let e of n.tiles) e.id in a || (a[e.id] = null);
|
|
68
|
-
return r.placements = a, r.completed = f(n, {
|
|
69
|
-
...r,
|
|
70
|
-
placements: a
|
|
71
|
-
}), r;
|
|
72
|
-
}
|
|
73
|
-
function f(e, t) {
|
|
74
|
-
if (!e || !Array.isArray(e.tiles) || e.tiles.length === 0) return !1;
|
|
75
|
-
let n = t?.placements ?? {};
|
|
76
|
-
for (let t of e.tiles) if (n[t.id] == null) return !1;
|
|
77
|
-
return !0;
|
|
78
|
-
}
|
|
79
|
-
function p(e, t) {
|
|
80
|
-
return t == null ? "unanswered" : n(e.correctRegion, t) ? "correct" : "incorrect";
|
|
81
|
-
}
|
|
82
|
-
function m(e, t) {
|
|
83
|
-
let n = {}, r = t?.placements ?? {};
|
|
84
|
-
for (let t of e.tiles ?? []) n[t.id] = p(t, r[t.id] ?? null);
|
|
85
|
-
return n;
|
|
86
|
-
}
|
|
87
|
-
function h(e, t, r = {}) {
|
|
88
|
-
return new Promise((i) => {
|
|
89
|
-
if (!t || c(t) || !t.placements || Object.keys(t.placements).length === 0) {
|
|
90
|
-
i({
|
|
91
|
-
score: 0,
|
|
92
|
-
empty: !0
|
|
93
|
-
});
|
|
94
|
-
return;
|
|
95
|
-
}
|
|
96
|
-
if (r.mode !== "evaluate") {
|
|
97
|
-
i({
|
|
98
|
-
score: void 0,
|
|
99
|
-
completed: void 0
|
|
100
|
-
});
|
|
101
|
-
return;
|
|
102
|
-
}
|
|
103
|
-
let a = u(e || void 0), o = a.tiles || [];
|
|
104
|
-
if (o.length === 0) {
|
|
105
|
-
i({
|
|
106
|
-
score: 0,
|
|
107
|
-
empty: !0
|
|
108
|
-
});
|
|
109
|
-
return;
|
|
110
|
-
}
|
|
111
|
-
let s = t.placements || {}, l = 0, d = 0;
|
|
112
|
-
for (let e of o) {
|
|
113
|
-
let t = s[e.id];
|
|
114
|
-
t != null && (d += 1, n(e.correctRegion, t) && (l += 1));
|
|
115
|
-
}
|
|
116
|
-
if (d === 0) {
|
|
117
|
-
i({
|
|
118
|
-
score: 0,
|
|
119
|
-
empty: !0
|
|
120
|
-
});
|
|
121
|
-
return;
|
|
122
|
-
}
|
|
123
|
-
if ((a.scoringPolicy === "allOrNothing" ? "allOrNothing" : "partialPerTile") == "allOrNothing") {
|
|
124
|
-
i({ score: +(l === o.length) });
|
|
125
|
-
return;
|
|
126
|
-
}
|
|
127
|
-
i({ score: l / o.length });
|
|
128
|
-
});
|
|
129
|
-
}
|
|
130
|
-
function g(e, n, r = {}) {
|
|
131
|
-
return new Promise((i) => {
|
|
132
|
-
let a = u(e || void 0), o = r || {}, s = {
|
|
133
|
-
prompt: a.promptEnabled === !1 ? null : a.prompt ?? null,
|
|
134
|
-
circles: a.circles.map((e) => ({ label: e?.label ?? "" })),
|
|
135
|
-
tiles: a.tiles.map((e) => {
|
|
136
|
-
let n = String(e.imageUrl ?? "").trim(), r = n.length > 0 ? {
|
|
137
|
-
imageUrl: n,
|
|
138
|
-
imageAlt: String(e.imageAlt ?? "").trim()
|
|
139
|
-
} : {};
|
|
140
|
-
return {
|
|
141
|
-
id: e.id,
|
|
142
|
-
label: e.label ?? "",
|
|
143
|
-
...r,
|
|
144
|
-
...o.mode === "evaluate" ? { correctRegion: t(e.correctRegion) } : {}
|
|
145
|
-
};
|
|
146
|
-
}),
|
|
147
|
-
regionLabels: { ...a.regionLabels || {} },
|
|
148
|
-
scoringPolicy: a.scoringPolicy ?? "partialPerTile",
|
|
149
|
-
disabled: o.mode !== "gather",
|
|
150
|
-
mode: o.mode,
|
|
151
|
-
env: o
|
|
152
|
-
};
|
|
153
|
-
if (o.mode === "evaluate") {
|
|
154
|
-
let e = {};
|
|
155
|
-
for (let n of a.tiles) e[n.id] = t(n.correctRegion);
|
|
156
|
-
s.correctRegionsById = e, s.correctness = m(a, n);
|
|
157
|
-
}
|
|
158
|
-
if (o.role === "instructor" && (o.mode === "view" || o.mode === "evaluate")) {
|
|
159
|
-
let e = a;
|
|
160
|
-
s.teacherInstructions = e.teacherInstructionsEnabled ? e.teacherInstructions ?? null : null;
|
|
161
|
-
} else s.teacherInstructions = null;
|
|
162
|
-
i(s);
|
|
163
|
-
});
|
|
164
|
-
}
|
|
165
|
-
function _(e, n = {}) {
|
|
166
|
-
return new Promise((r) => {
|
|
167
|
-
if (n.mode === "evaluate" || n.role !== "instructor") {
|
|
168
|
-
r(null);
|
|
169
|
-
return;
|
|
170
|
-
}
|
|
171
|
-
let i = u(e || void 0), a = {};
|
|
172
|
-
for (let e of i.tiles) a[e.id] = t(e.correctRegion);
|
|
173
|
-
r({
|
|
174
|
-
id: "1",
|
|
175
|
-
element: "venn-classification",
|
|
176
|
-
placements: a,
|
|
177
|
-
completed: !0
|
|
178
|
-
});
|
|
179
|
-
});
|
|
180
|
-
}
|
|
181
|
-
function v(e, n = {}) {
|
|
182
|
-
let r = {}, i = e || {};
|
|
183
|
-
if (i.promptEnabled) {
|
|
184
|
-
let e = (i.prompt ?? "").trim();
|
|
185
|
-
(!e || e === "<p></p>") && (r.prompt = "Prompt is required when prompt is enabled");
|
|
186
|
-
}
|
|
187
|
-
let a = Array.isArray(i.circles) ? i.circles : [];
|
|
188
|
-
if (!s.has(a.length)) r.circles = `Venn classification currently supports ${[...s].sort((e, t) => e - t).join(" or ")} circles (got ${a.length})`;
|
|
189
|
-
else for (let e = 0; e < a.length; e++) if (!(a[e]?.label ?? "").trim()) {
|
|
190
|
-
r.circles = `Circle ${e + 1} needs a label`;
|
|
191
|
-
break;
|
|
192
|
-
}
|
|
193
|
-
let o = Array.isArray(i.tiles) ? i.tiles : [];
|
|
194
|
-
if (o.length < 1) r.tiles = "At least one tile is required";
|
|
195
|
-
else {
|
|
196
|
-
let e = /* @__PURE__ */ new Set();
|
|
197
|
-
for (let n = 0; n < o.length; n++) {
|
|
198
|
-
let i = o[n];
|
|
199
|
-
if (!i?.id) {
|
|
200
|
-
r.tiles = `Tile ${n + 1} is missing an id`;
|
|
201
|
-
break;
|
|
202
|
-
}
|
|
203
|
-
if (e.has(i.id)) {
|
|
204
|
-
r.tiles = `Tile id "${i.id}" appears more than once`;
|
|
205
|
-
break;
|
|
206
|
-
}
|
|
207
|
-
e.add(i.id);
|
|
208
|
-
let s = l(i.label), c = String(i.imageUrl ?? "").trim(), u = String(i.imageAlt ?? "").trim();
|
|
209
|
-
if (!s && !c) {
|
|
210
|
-
r.tiles = `Tile "${i.id}" needs a label or an image URL`;
|
|
211
|
-
break;
|
|
212
|
-
}
|
|
213
|
-
if (c && !u) {
|
|
214
|
-
r.tiles = `Tile "${i.id}": when an image URL is set, short alt text is required for accessibility`;
|
|
215
|
-
break;
|
|
216
|
-
}
|
|
217
|
-
let d = i.correctRegion;
|
|
218
|
-
if (!Array.isArray(d)) {
|
|
219
|
-
r.tiles = `Tile "${i.id}" is missing correctRegion`;
|
|
220
|
-
break;
|
|
221
|
-
}
|
|
222
|
-
let f = t(d);
|
|
223
|
-
if (new Set(f).size !== f.length) {
|
|
224
|
-
r.tiles = `Tile "${i.id}" correctRegion has duplicate indexes`;
|
|
225
|
-
break;
|
|
226
|
-
}
|
|
227
|
-
let p = f.find((e) => !Number.isInteger(e) || e < 0 || e >= a.length);
|
|
228
|
-
if (p !== void 0) {
|
|
229
|
-
r.tiles = `Tile "${i.id}" correctRegion index ${p} is out of range for ${a.length} circles`;
|
|
230
|
-
break;
|
|
231
|
-
}
|
|
232
|
-
}
|
|
233
|
-
}
|
|
234
|
-
return i.scoringPolicy !== void 0 && i.scoringPolicy !== "allOrNothing" && i.scoringPolicy !== "partialPerTile" && (r.scoringPolicy = "Scoring policy must be \"allOrNothing\" or \"partialPerTile\""), r;
|
|
235
|
-
}
|
|
236
|
-
function y(e) {
|
|
237
|
-
let n = u(e || void 0), r = {};
|
|
238
|
-
for (let e of n.tiles) r[e.id] = t(e.correctRegion);
|
|
239
|
-
return {
|
|
240
|
-
id: "preview",
|
|
241
|
-
element: "venn-classification",
|
|
242
|
-
placements: r,
|
|
243
|
-
completed: !0
|
|
244
|
-
};
|
|
245
|
-
}
|
|
246
|
-
//#endregion
|
|
247
|
-
export { n as _, m as a, g as c, v as d, i as f, e as g, t as h, u as i, d as l, a as m, y as n, p as o, r as p, _ as r, f as s, s as t, h as u };
|
|
248
|
-
|
|
249
|
-
//# sourceMappingURL=controller-DGuLVZuv.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"controller-DGuLVZuv.js","names":[],"sources":["../../src/controller/region.ts","../../src/controller/defaults.ts","../../src/controller/index.ts"],"sourcesContent":["/**\n * Region helpers for the venn-classification controller.\n *\n * A region is a sorted-ascending array of circle indexes. These helpers deal\n * with keying, labelling, and equality in a layout-agnostic way so that both\n * the controller (for scoring / validation) and delivery (for rendering)\n * can share them.\n */\n\nimport type { Region, VennCircle, VennModel } from '../types.js';\n\n/**\n * Returns the canonical region key: sorted-ascending indexes joined by commas.\n * Outside / \"neither\" region is the empty string.\n */\nexport function regionKey(region: Region | null | undefined): string {\n if (!region || region.length === 0) return '';\n return [...region].sort((a, b) => a - b).join(',');\n}\n\n/** Return a fresh sorted-ascending copy of a region. */\nexport function normalizeRegion(region: Region | null | undefined): Region {\n if (!region || region.length === 0) return [];\n return [...region].sort((a, b) => a - b);\n}\n\nexport function regionsEqual(a: Region | null | undefined, b: Region | null | undefined): boolean {\n if (!a || !b) return !a === !b && (a?.length ?? 0) === (b?.length ?? 0);\n if (a.length !== b.length) return false;\n const sa = normalizeRegion(a);\n const sb = normalizeRegion(b);\n for (let i = 0; i < sa.length; i++) {\n if (sa[i] !== sb[i]) return false;\n }\n return true;\n}\n\n/**\n * Enumerate every valid region for a given number of circles.\n * Returns an array of `Region` covering the powerset of `[0..n)`, starting\n * with the outside region (`[]`). Order:\n * 2-set: [], [0], [1], [0,1] (4 regions)\n * 3-set: [], [0], [1], [2], [0,1], [0,2], [1,2], [0,1,2] (8 regions)\n */\nexport function enumerateRegions(circleCount: number): Region[] {\n const regions: Region[] = [];\n const total = 1 << circleCount;\n for (let mask = 0; mask < total; mask++) {\n const r: Region = [];\n for (let i = 0; i < circleCount; i++) {\n if (mask & (1 << i)) r.push(i);\n }\n regions.push(r);\n }\n return regions;\n}\n\n/**\n * Auto-compose the accessible/visible label for a region from the circle labels.\n *\n * 2-set:\n * [] -> \"Neither X nor Y\"\n * [i] -> \"<label(i)> only\"\n * [0,1] -> \"<X> and <Y>\"\n *\n * 3-set (data shape supported; delivery layout ships in v2):\n * [] -> \"None of X, Y, Z\"\n * [i] -> \"<label(i)> only\"\n * [0,1] -> \"<X> and <Y>\"\n * [0,1,2] -> \"<X> and <Y> and <Z>\"\n */\nexport function composeRegionLabel(circles: VennCircle[], region: Region): string {\n const norm = normalizeRegion(region);\n const labels = norm.map((i) => circles[i]?.label ?? `Set ${i + 1}`);\n const circleCount = circles.length;\n\n if (norm.length === 0) {\n if (circleCount === 2) {\n const a = circles[0]?.label ?? 'Set 1';\n const b = circles[1]?.label ?? 'Set 2';\n return `Neither ${a} nor ${b}`;\n }\n const all = circles.map((c, i) => c?.label ?? `Set ${i + 1}`).join(', ');\n return `None of ${all}`;\n }\n\n if (norm.length === 1) {\n return `${labels[0]} only`;\n }\n\n return labels.join(' and ');\n}\n\n/**\n * Resolve the label for a region, preferring an author-supplied override from\n * `model.regionLabels` keyed by region-key, falling back to the auto-composed\n * label.\n */\nexport function getRegionLabel(\n model: Pick<VennModel, 'circles' | 'regionLabels'>,\n region: Region\n): string {\n const key = regionKey(region);\n const override = model.regionLabels?.[key];\n if (typeof override === 'string' && override.trim().length > 0) {\n return override;\n }\n return composeRegionLabel(model.circles ?? [], region);\n}\n","import type { VennModel } from '../types.js';\n\nconst model: VennModel = {\n id: '1',\n element: 'venn-classification',\n prompt: '<p>Sort each tile into the correct region of the Venn diagram.</p>',\n promptEnabled: true,\n circles: [{ label: 'Set A' }, { label: 'Set B' }],\n tiles: [],\n regionLabels: {},\n scoringPolicy: 'partialPerTile',\n};\n\nexport default {\n model,\n configuration: {\n prompt: {\n label: 'Prompt',\n settings: true,\n },\n scoringPolicy: {\n label: 'Scoring policy',\n settings: true,\n },\n },\n};\n","import defaults from './defaults.js';\nimport { normalizeRegion, regionsEqual } from './region.js';\nimport type {\n Region,\n ScoringPolicy,\n VennModel,\n VennSession,\n VennTile,\n VennViewModel,\n} from '../types.js';\n\nexport {\n composeRegionLabel,\n enumerateRegions,\n getRegionLabel,\n normalizeRegion,\n regionKey,\n regionsEqual,\n} from './region.js';\nexport type {\n Region,\n ScoringPolicy,\n VennCircle,\n VennModel,\n VennSession,\n VennTile,\n VennViewModel,\n} from '../types.js';\n\n/**\n * Circle counts that the v1 delivery surface will actually lay out.\n * The data model is N-generic; widening to 3-set delivery is a one-line change\n * plus the 3-set layout/picker once that work ships.\n */\nexport const SUPPORTED_CIRCLE_COUNTS = new Set<number>([2]);\n\nconst isEmptyObject = (value: unknown): boolean =>\n !!value &&\n typeof value === 'object' &&\n !Array.isArray(value) &&\n Object.keys(value as Record<string, unknown>).length === 0;\n\nfunction tilePlainLabel(label: unknown): string {\n return String(label ?? '')\n .replace(/<[^>]+>/g, ' ')\n .replace(/\\s+/g, ' ')\n .trim();\n}\n\nexport function createDefaultModel(model: Partial<VennModel> = {}): VennModel {\n const merged: VennModel = {\n ...(defaults.model as VennModel),\n ...model,\n };\n if (!Array.isArray(merged.circles) || merged.circles.length === 0) {\n merged.circles = (defaults.model as VennModel).circles.map((c) => ({ ...c }));\n }\n if (!Array.isArray(merged.tiles)) {\n merged.tiles = [];\n }\n if (!merged.regionLabels || typeof merged.regionLabels !== 'object') {\n merged.regionLabels = {};\n }\n if (merged.scoringPolicy !== 'allOrNothing' && merged.scoringPolicy !== 'partialPerTile') {\n merged.scoringPolicy = 'partialPerTile';\n }\n return merged;\n}\n\n/**\n * Return a session whose `placements` map has an entry for every authored tile.\n * Unknown placement keys are preserved (so hosts that round-trip extra keys\n * don't lose them), and arrays are normalized to sorted-ascending.\n */\nexport function normalizeSession(\n session: VennSession | null | undefined,\n model?: VennModel\n): VennSession {\n const base: VennSession = { ...(session || {}) };\n const inputPlacements = (session?.placements ?? {}) as Record<string, Region | null>;\n const placements: Record<string, Region | null> = {};\n\n for (const [k, v] of Object.entries(inputPlacements)) {\n if (v === null || v === undefined) {\n placements[k] = null;\n } else if (Array.isArray(v)) {\n placements[k] = normalizeRegion(v);\n } else {\n placements[k] = null;\n }\n }\n\n if (model?.tiles) {\n for (const tile of model.tiles) {\n if (!(tile.id in placements)) {\n placements[tile.id] = null;\n }\n }\n }\n\n base.placements = placements;\n base.completed = isComplete(model, { ...base, placements });\n return base;\n}\n\n/**\n * True iff every authored tile has a non-null placement.\n * Intentionally permissive about unauthored placement keys: they don't\n * contribute to completeness.\n */\nexport function isComplete(\n model: VennModel | null | undefined,\n session: VennSession | null | undefined\n): boolean {\n if (!model || !Array.isArray(model.tiles) || model.tiles.length === 0) return false;\n const placements = session?.placements ?? {};\n for (const tile of model.tiles) {\n const p = placements[tile.id];\n if (p === null || p === undefined) return false;\n }\n return true;\n}\n\nexport type Correctness = 'correct' | 'incorrect' | 'unanswered';\n\n/** Per-tile correctness verdict. */\nexport function getTileCorrectness(\n tile: VennTile,\n placement: Region | null | undefined\n): Correctness {\n if (placement === null || placement === undefined) return 'unanswered';\n return regionsEqual(tile.correctRegion, placement) ? 'correct' : 'incorrect';\n}\n\n/** Map tile id -> correctness, for convenience in delivery `evaluate` mode. */\nexport function getCorrectnessMap(\n model: VennModel,\n session: VennSession | null | undefined\n): Record<string, Correctness> {\n const out: Record<string, Correctness> = {};\n const placements = session?.placements ?? {};\n for (const tile of model.tiles ?? []) {\n out[tile.id] = getTileCorrectness(tile, placements[tile.id] ?? null);\n }\n return out;\n}\n\nexport function outcome(\n question: VennModel | null | undefined,\n session: VennSession | null | undefined,\n env: { mode?: string } = {}\n): Promise<{ score?: number; empty?: boolean; completed?: boolean }> {\n return new Promise((resolve) => {\n if (\n !session ||\n isEmptyObject(session) ||\n !session.placements ||\n Object.keys(session.placements).length === 0\n ) {\n resolve({ score: 0, empty: true });\n return;\n }\n\n if (env.mode !== 'evaluate') {\n resolve({ score: undefined, completed: undefined });\n return;\n }\n\n const model = createDefaultModel((question as VennModel) || undefined);\n const tiles = model.tiles || [];\n if (tiles.length === 0) {\n resolve({ score: 0, empty: true });\n return;\n }\n\n const placements = session.placements || {};\n let correct = 0;\n let answered = 0;\n for (const tile of tiles) {\n const p = placements[tile.id];\n if (p === null || p === undefined) continue;\n answered += 1;\n if (regionsEqual(tile.correctRegion, p)) correct += 1;\n }\n\n if (answered === 0) {\n resolve({ score: 0, empty: true });\n return;\n }\n\n const policy: ScoringPolicy =\n model.scoringPolicy === 'allOrNothing' ? 'allOrNothing' : 'partialPerTile';\n if (policy === 'allOrNothing') {\n resolve({ score: correct === tiles.length ? 1 : 0 });\n return;\n }\n\n resolve({ score: correct / tiles.length });\n });\n}\n\n/**\n * Build the view model consumed by the delivery Svelte component.\n * Strips `correctRegion` from `tiles` unless the host is in `evaluate` mode so\n * authored answers don't leak in `gather`.\n */\nexport function model(\n question: VennModel | null | undefined,\n session: VennSession | null | undefined,\n env: { mode?: string; role?: string; [key: string]: unknown } = {}\n): Promise<VennViewModel> {\n return new Promise((resolve) => {\n const normalizedQuestion = createDefaultModel((question as VennModel) || undefined);\n const safeEnv = env || {};\n\n const out: VennViewModel = {\n prompt:\n normalizedQuestion.promptEnabled === false ? null : (normalizedQuestion.prompt ?? null),\n circles: normalizedQuestion.circles.map((c) => ({ label: c?.label ?? '' })),\n tiles: normalizedQuestion.tiles.map((t) => {\n const imageUrl = String(t.imageUrl ?? '').trim();\n const imageFields =\n imageUrl.length > 0 ? { imageUrl, imageAlt: String(t.imageAlt ?? '').trim() } : {};\n return {\n id: t.id,\n label: t.label ?? '',\n ...imageFields,\n ...(safeEnv.mode === 'evaluate'\n ? { correctRegion: normalizeRegion(t.correctRegion) }\n : {}),\n };\n }),\n regionLabels: { ...(normalizedQuestion.regionLabels || {}) },\n scoringPolicy: normalizedQuestion.scoringPolicy ?? 'partialPerTile',\n disabled: safeEnv.mode !== 'gather',\n mode: safeEnv.mode,\n env: safeEnv,\n };\n\n if (safeEnv.mode === 'evaluate') {\n const correctRegionsById: Record<string, Region> = {};\n for (const tile of normalizedQuestion.tiles) {\n correctRegionsById[tile.id] = normalizeRegion(tile.correctRegion);\n }\n out.correctRegionsById = correctRegionsById;\n out.correctness = getCorrectnessMap(normalizedQuestion, session);\n }\n\n const isInstructor = safeEnv.role === 'instructor';\n if (isInstructor && (safeEnv.mode === 'view' || safeEnv.mode === 'evaluate')) {\n const anyQ = normalizedQuestion as unknown as {\n teacherInstructionsEnabled?: boolean;\n teacherInstructions?: string;\n };\n out.teacherInstructions = anyQ.teacherInstructionsEnabled\n ? (anyQ.teacherInstructions ?? null)\n : null;\n } else {\n out.teacherInstructions = null;\n }\n\n resolve(out);\n });\n}\n\nexport function createCorrectResponseSession(\n question: VennModel | null | undefined,\n env: { mode?: string; role?: string } = {}\n): Promise<VennSession | null> {\n return new Promise((resolve) => {\n if (env.mode === 'evaluate' || env.role !== 'instructor') {\n resolve(null);\n return;\n }\n const model = createDefaultModel((question as VennModel) || undefined);\n const placements: Record<string, Region> = {};\n for (const tile of model.tiles) {\n placements[tile.id] = normalizeRegion(tile.correctRegion);\n }\n resolve({\n id: '1',\n element: 'venn-classification',\n placements,\n completed: true,\n });\n });\n}\n\n/**\n * Shallow model validation for authoring surfaces. Returns a map of\n * `{field: message}`; an empty map means \"valid enough to save\".\n */\nexport function validate(\n model: VennModel | null | undefined,\n _config: unknown = {}\n): Record<string, string> {\n const errors: Record<string, string> = {};\n const m = (model || {}) as VennModel;\n\n if (m.promptEnabled) {\n const p = (m.prompt ?? '').trim();\n if (!p || p === '<p></p>') {\n errors.prompt = 'Prompt is required when prompt is enabled';\n }\n }\n\n const circles = Array.isArray(m.circles) ? m.circles : [];\n if (!SUPPORTED_CIRCLE_COUNTS.has(circles.length)) {\n const supported = [...SUPPORTED_CIRCLE_COUNTS].sort((a, b) => a - b).join(' or ');\n errors.circles = `Venn classification currently supports ${supported} circles (got ${circles.length})`;\n } else {\n for (let i = 0; i < circles.length; i++) {\n const label = (circles[i]?.label ?? '').trim();\n if (!label) {\n errors.circles = `Circle ${i + 1} needs a label`;\n break;\n }\n }\n }\n\n const tiles = Array.isArray(m.tiles) ? m.tiles : [];\n if (tiles.length < 1) {\n errors.tiles = 'At least one tile is required';\n } else {\n const seen = new Set<string>();\n for (let i = 0; i < tiles.length; i++) {\n const tile = tiles[i];\n if (!tile?.id) {\n errors.tiles = `Tile ${i + 1} is missing an id`;\n break;\n }\n if (seen.has(tile.id)) {\n errors.tiles = `Tile id \"${tile.id}\" appears more than once`;\n break;\n }\n seen.add(tile.id);\n\n const labelPlain = tilePlainLabel(tile.label);\n const imageUrl = String(tile.imageUrl ?? '').trim();\n const imageAlt = String(tile.imageAlt ?? '').trim();\n if (!labelPlain && !imageUrl) {\n errors.tiles = `Tile \"${tile.id}\" needs a label or an image URL`;\n break;\n }\n if (imageUrl && !imageAlt) {\n errors.tiles = `Tile \"${tile.id}\": when an image URL is set, short alt text is required for accessibility`;\n break;\n }\n\n const region = tile.correctRegion;\n if (!Array.isArray(region)) {\n errors.tiles = `Tile \"${tile.id}\" is missing correctRegion`;\n break;\n }\n\n const sorted = normalizeRegion(region);\n // Must be sorted ascending by convention, with unique in-range indexes.\n const unique = new Set(sorted);\n if (unique.size !== sorted.length) {\n errors.tiles = `Tile \"${tile.id}\" correctRegion has duplicate indexes`;\n break;\n }\n const outOfRange = sorted.find(\n (idx) => !Number.isInteger(idx) || idx < 0 || idx >= circles.length\n );\n if (outOfRange !== undefined) {\n errors.tiles = `Tile \"${tile.id}\" correctRegion index ${outOfRange} is out of range for ${circles.length} circles`;\n break;\n }\n }\n }\n\n if (\n m.scoringPolicy !== undefined &&\n m.scoringPolicy !== 'allOrNothing' &&\n m.scoringPolicy !== 'partialPerTile'\n ) {\n errors.scoringPolicy = 'Scoring policy must be \"allOrNothing\" or \"partialPerTile\"';\n }\n\n return errors;\n}\n\n/**\n * Helper for authoring-time previews: build a session that places each tile in\n * its authored correct region. Used by the authoring live preview so authors\n * see the intended final state of the diagram.\n */\nexport function buildPreviewSession(model: VennModel | null | undefined): VennSession {\n const m = createDefaultModel(model || undefined);\n const placements: Record<string, Region> = {};\n for (const tile of m.tiles) {\n placements[tile.id] = normalizeRegion(tile.correctRegion);\n }\n return {\n id: 'preview',\n element: 'venn-classification',\n placements,\n completed: true,\n };\n}\n"],"mappings":"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"}
|