@almadar/ui 5.35.0 → 5.36.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.
- package/dist/avl/index.cjs +224 -202
- package/dist/avl/index.js +224 -202
- package/dist/components/game/organisms/puzzles/builder/BuilderBoard.d.ts +18 -5
- package/dist/components/game/organisms/puzzles/classifier/ClassifierBoard.d.ts +21 -3
- package/dist/components/game/organisms/puzzles/debugger/DebuggerBoard.d.ts +12 -2
- package/dist/components/game/organisms/puzzles/negotiator/NegotiatorBoard.d.ts +13 -3
- package/dist/components/game/organisms/puzzles/simulator/SimulatorBoard.d.ts +22 -7
- package/dist/components/index.cjs +224 -202
- package/dist/components/index.js +224 -202
- package/dist/providers/index.cjs +224 -202
- package/dist/providers/index.js +224 -202
- package/dist/runtime/index.cjs +224 -202
- package/dist/runtime/index.js +224 -202
- package/package.json +1 -1
package/dist/avl/index.cjs
CHANGED
|
@@ -19898,61 +19898,53 @@ var init_Breadcrumb = __esm({
|
|
|
19898
19898
|
function BuilderBoard({
|
|
19899
19899
|
entity,
|
|
19900
19900
|
completeEvent = "PUZZLE_COMPLETE",
|
|
19901
|
+
placeEvent,
|
|
19902
|
+
checkEvent,
|
|
19903
|
+
playAgainEvent,
|
|
19901
19904
|
className
|
|
19902
19905
|
}) {
|
|
19903
19906
|
const { emit } = useEventBus();
|
|
19904
19907
|
const { t } = hooks.useTranslate();
|
|
19905
19908
|
const resolved = boardEntity(entity);
|
|
19906
|
-
const [placements, setPlacements] = React91.useState({});
|
|
19907
19909
|
const [headerError, setHeaderError] = React91.useState(false);
|
|
19908
|
-
const [
|
|
19909
|
-
const [attempts, setAttempts] = React91.useState(0);
|
|
19910
|
-
const [showHint, setShowHint] = React91.useState(false);
|
|
19910
|
+
const [selectedComponent, setSelectedComponent] = React91.useState(null);
|
|
19911
19911
|
const components = Array.isArray(resolved?.components) ? resolved.components : [];
|
|
19912
19912
|
const slots = Array.isArray(resolved?.slots) ? resolved.slots : [];
|
|
19913
|
+
const placements = {};
|
|
19914
|
+
for (const slot of slots) {
|
|
19915
|
+
if (slot.placedComponentId) placements[slot.id] = slot.placedComponentId;
|
|
19916
|
+
}
|
|
19917
|
+
const attempts = num(resolved?.attempts);
|
|
19918
|
+
const result = str(resolved?.result) || "none";
|
|
19919
|
+
const submitted = result === "win";
|
|
19913
19920
|
const usedComponentIds = new Set(Object.values(placements));
|
|
19914
19921
|
const availableComponents = components.filter((c) => !usedComponentIds.has(c.id));
|
|
19915
|
-
const
|
|
19916
|
-
const allPlaced = Object.keys(placements).length === slots.length;
|
|
19922
|
+
const allPlaced = slots.length > 0 && slots.every((s) => Boolean(placements[s.id]));
|
|
19917
19923
|
const results = submitted ? slots.map((slot) => ({
|
|
19918
19924
|
slot,
|
|
19919
19925
|
placed: placements[slot.id],
|
|
19920
|
-
correct: placements[slot.id] === slot.
|
|
19926
|
+
correct: placements[slot.id] === slot.requiredComponentId
|
|
19921
19927
|
})) : [];
|
|
19922
|
-
const
|
|
19928
|
+
const showHint = attempts >= 2 && Boolean(str(resolved?.hint));
|
|
19923
19929
|
const handlePlaceComponent = (slotId) => {
|
|
19924
19930
|
if (submitted || !selectedComponent) return;
|
|
19925
|
-
|
|
19931
|
+
if (placeEvent) emit(`UI:${placeEvent}`, { slotId, componentId: selectedComponent });
|
|
19926
19932
|
setSelectedComponent(null);
|
|
19927
19933
|
};
|
|
19928
19934
|
const handleRemoveFromSlot = (slotId) => {
|
|
19929
19935
|
if (submitted) return;
|
|
19930
|
-
|
|
19931
|
-
const next = { ...prev };
|
|
19932
|
-
delete next[slotId];
|
|
19933
|
-
return next;
|
|
19934
|
-
});
|
|
19936
|
+
if (placeEvent) emit(`UI:${placeEvent}`, { slotId, componentId: "" });
|
|
19935
19937
|
};
|
|
19936
|
-
const handleSubmit =
|
|
19937
|
-
|
|
19938
|
-
|
|
19939
|
-
|
|
19940
|
-
if (correct) {
|
|
19938
|
+
const handleSubmit = () => {
|
|
19939
|
+
if (checkEvent) emit(`UI:${checkEvent}`, {});
|
|
19940
|
+
const solved = slots.length > 0 && slots.every((s) => placements[s.id] === s.requiredComponentId);
|
|
19941
|
+
if (solved && completeEvent) {
|
|
19941
19942
|
emit(`UI:${completeEvent}`, { success: true, attempts: attempts + 1 });
|
|
19942
19943
|
}
|
|
19943
|
-
}, [slots, placements, attempts, completeEvent, emit]);
|
|
19944
|
-
const handleReset = () => {
|
|
19945
|
-
setSubmitted(false);
|
|
19946
|
-
if (attempts >= 2 && str(resolved?.hint)) {
|
|
19947
|
-
setShowHint(true);
|
|
19948
|
-
}
|
|
19949
19944
|
};
|
|
19950
|
-
const
|
|
19951
|
-
setPlacements({});
|
|
19952
|
-
setSubmitted(false);
|
|
19945
|
+
const handlePlayAgain = () => {
|
|
19953
19946
|
setSelectedComponent(null);
|
|
19954
|
-
|
|
19955
|
-
setShowHint(false);
|
|
19947
|
+
if (playAgainEvent) emit(`UI:${playAgainEvent}`, {});
|
|
19956
19948
|
};
|
|
19957
19949
|
const getComponentById = (id) => components.find((c) => c.id === id);
|
|
19958
19950
|
if (!resolved) return null;
|
|
@@ -20002,13 +19994,13 @@ function BuilderBoard({
|
|
|
20002
19994
|
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "small", weight: "bold", className: "uppercase tracking-wider text-muted-foreground", children: t("builder.blueprint") }),
|
|
20003
19995
|
/* @__PURE__ */ jsxRuntime.jsx(VStack, { gap: "sm", children: slots.map((slot) => {
|
|
20004
19996
|
const placedComp = placements[slot.id] ? getComponentById(placements[slot.id]) : null;
|
|
20005
|
-
const
|
|
19997
|
+
const result2 = results.find((r2) => r2.slot.id === slot.id);
|
|
20006
19998
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
20007
19999
|
HStack,
|
|
20008
20000
|
{
|
|
20009
20001
|
gap: "sm",
|
|
20010
20002
|
align: "center",
|
|
20011
|
-
className: `p-3 border-2 rounded ${
|
|
20003
|
+
className: `p-3 border-2 rounded ${result2 ? result2.correct ? "border-success" : "border-error" : selectedComponent ? "border-dashed border-foreground cursor-pointer" : "border-border"}`,
|
|
20012
20004
|
onClick: () => handlePlaceComponent(slot.id),
|
|
20013
20005
|
children: [
|
|
20014
20006
|
/* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "none", className: "flex-1", children: [
|
|
@@ -20023,7 +20015,7 @@ function BuilderBoard({
|
|
|
20023
20015
|
] }) : null,
|
|
20024
20016
|
placedComp.label
|
|
20025
20017
|
] }),
|
|
20026
|
-
|
|
20018
|
+
result2 && /* @__PURE__ */ jsxRuntime.jsx(Icon, { icon: result2.correct ? LucideIcons2.CheckCircle : LucideIcons2.XCircle, size: "sm", className: result2.correct ? "text-success" : "text-error" })
|
|
20027
20019
|
] }) : /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "caption", className: "text-muted-foreground", children: t("builder.empty") })
|
|
20028
20020
|
]
|
|
20029
20021
|
},
|
|
@@ -20032,16 +20024,16 @@ function BuilderBoard({
|
|
|
20032
20024
|
}) })
|
|
20033
20025
|
] }) }),
|
|
20034
20026
|
submitted && /* @__PURE__ */ jsxRuntime.jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "sm", align: "center", children: [
|
|
20035
|
-
/* @__PURE__ */ jsxRuntime.jsx(Icon, { icon:
|
|
20036
|
-
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body", weight: "bold", children:
|
|
20027
|
+
/* @__PURE__ */ jsxRuntime.jsx(Icon, { icon: LucideIcons2.CheckCircle, size: "lg", className: "text-success" }),
|
|
20028
|
+
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body", weight: "bold", children: str(resolved.successMessage) || t("builder.success") })
|
|
20037
20029
|
] }) }),
|
|
20038
20030
|
showHint && hint && /* @__PURE__ */ jsxRuntime.jsx(Card, { className: "p-4 border-l-4 border-l-warning", children: /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body", children: hint }) }),
|
|
20039
20031
|
/* @__PURE__ */ jsxRuntime.jsxs(HStack, { gap: "sm", justify: "center", children: [
|
|
20040
|
-
!submitted
|
|
20032
|
+
!submitted && /* @__PURE__ */ jsxRuntime.jsxs(Button, { variant: "primary", onClick: handleSubmit, disabled: !allPlaced, children: [
|
|
20041
20033
|
/* @__PURE__ */ jsxRuntime.jsx(Icon, { icon: LucideIcons2.Wrench, size: "sm" }),
|
|
20042
20034
|
t("builder.build")
|
|
20043
|
-
] })
|
|
20044
|
-
/* @__PURE__ */ jsxRuntime.jsxs(Button, { variant: "secondary", onClick:
|
|
20035
|
+
] }),
|
|
20036
|
+
/* @__PURE__ */ jsxRuntime.jsxs(Button, { variant: "secondary", onClick: handlePlayAgain, children: [
|
|
20045
20037
|
/* @__PURE__ */ jsxRuntime.jsx(Icon, { icon: LucideIcons2.RotateCcw, size: "sm" }),
|
|
20046
20038
|
t("builder.reset")
|
|
20047
20039
|
] })
|
|
@@ -23497,57 +23489,84 @@ var init_ChartLegend = __esm({
|
|
|
23497
23489
|
function ClassifierBoard({
|
|
23498
23490
|
entity,
|
|
23499
23491
|
completeEvent = "PUZZLE_COMPLETE",
|
|
23492
|
+
assignEvent,
|
|
23493
|
+
checkEvent,
|
|
23494
|
+
playAgainEvent,
|
|
23500
23495
|
className
|
|
23501
23496
|
}) {
|
|
23502
23497
|
const { emit } = useEventBus();
|
|
23503
23498
|
const { t } = hooks.useTranslate();
|
|
23504
23499
|
const resolved = boardEntity(entity);
|
|
23505
|
-
const [
|
|
23500
|
+
const [localAssignments, setLocalAssignments] = React91.useState({});
|
|
23506
23501
|
const [headerError, setHeaderError] = React91.useState(false);
|
|
23507
|
-
const [
|
|
23508
|
-
const [
|
|
23502
|
+
const [localSubmitted, setLocalSubmitted] = React91.useState(false);
|
|
23503
|
+
const [localAttempts, setLocalAttempts] = React91.useState(0);
|
|
23509
23504
|
const [showHint, setShowHint] = React91.useState(false);
|
|
23510
23505
|
const items = Array.isArray(resolved?.items) ? resolved.items : [];
|
|
23511
23506
|
const categories = Array.isArray(resolved?.categories) ? resolved.categories : [];
|
|
23507
|
+
const entityResult = str(resolved?.result);
|
|
23508
|
+
const entityDrivesResult = entityResult.length > 0;
|
|
23509
|
+
const entityHasAssignments = items.some((item) => item.assignedCategory != null);
|
|
23510
|
+
const assignments = entityHasAssignments ? items.reduce((acc, item) => {
|
|
23511
|
+
if (item.assignedCategory != null) acc[item.id] = item.assignedCategory;
|
|
23512
|
+
return acc;
|
|
23513
|
+
}, {}) : localAssignments;
|
|
23514
|
+
const attempts = entityDrivesResult ? num(resolved?.attempts) : localAttempts;
|
|
23515
|
+
const submitted = entityDrivesResult || localSubmitted;
|
|
23512
23516
|
const unassignedItems = items.filter((item) => !assignments[item.id]);
|
|
23513
|
-
const allAssigned = Object.keys(assignments).length === items.length;
|
|
23517
|
+
const allAssigned = items.length > 0 && Object.keys(assignments).length === items.length;
|
|
23514
23518
|
const results = submitted ? items.map((item) => ({
|
|
23515
23519
|
item,
|
|
23516
23520
|
assigned: assignments[item.id],
|
|
23517
23521
|
correct: assignments[item.id] === item.correctCategory
|
|
23518
23522
|
})) : [];
|
|
23519
|
-
const allCorrect = results.length > 0 && results.every((r2) => r2.correct);
|
|
23523
|
+
const allCorrect = entityDrivesResult ? entityResult === "success" : results.length > 0 && results.every((r2) => r2.correct);
|
|
23520
23524
|
const correctCount = results.filter((r2) => r2.correct).length;
|
|
23521
23525
|
const handleAssign = (itemId, categoryId) => {
|
|
23522
23526
|
if (submitted) return;
|
|
23523
|
-
|
|
23527
|
+
if (assignEvent) {
|
|
23528
|
+
emit(`UI:${assignEvent}`, { itemId, categoryId });
|
|
23529
|
+
}
|
|
23530
|
+
if (!entityHasAssignments) {
|
|
23531
|
+
setLocalAssignments((prev) => ({ ...prev, [itemId]: categoryId }));
|
|
23532
|
+
}
|
|
23524
23533
|
};
|
|
23525
23534
|
const handleUnassign = (itemId) => {
|
|
23526
23535
|
if (submitted) return;
|
|
23527
|
-
|
|
23528
|
-
|
|
23529
|
-
|
|
23530
|
-
|
|
23531
|
-
|
|
23536
|
+
if (!entityHasAssignments) {
|
|
23537
|
+
setLocalAssignments((prev) => {
|
|
23538
|
+
const next = { ...prev };
|
|
23539
|
+
delete next[itemId];
|
|
23540
|
+
return next;
|
|
23541
|
+
});
|
|
23542
|
+
}
|
|
23532
23543
|
};
|
|
23533
23544
|
const handleSubmit = React91.useCallback(() => {
|
|
23534
|
-
|
|
23535
|
-
|
|
23536
|
-
|
|
23537
|
-
if (
|
|
23538
|
-
|
|
23545
|
+
if (checkEvent) {
|
|
23546
|
+
emit(`UI:${checkEvent}`, {});
|
|
23547
|
+
}
|
|
23548
|
+
if (!entityDrivesResult) {
|
|
23549
|
+
setLocalSubmitted(true);
|
|
23550
|
+
setLocalAttempts((a) => a + 1);
|
|
23551
|
+
const correct = items.every((item) => assignments[item.id] === item.correctCategory);
|
|
23552
|
+
if (correct) {
|
|
23553
|
+
emit(`UI:${completeEvent}`, { success: true, attempts: attempts + 1 });
|
|
23554
|
+
}
|
|
23539
23555
|
}
|
|
23540
|
-
}, [items, assignments, attempts, completeEvent, emit]);
|
|
23556
|
+
}, [checkEvent, entityDrivesResult, items, assignments, attempts, completeEvent, emit]);
|
|
23541
23557
|
const handleReset = () => {
|
|
23542
|
-
|
|
23558
|
+
if (!entityDrivesResult) setLocalSubmitted(false);
|
|
23543
23559
|
if (attempts >= 2 && str(resolved?.hint)) {
|
|
23544
23560
|
setShowHint(true);
|
|
23545
23561
|
}
|
|
23546
23562
|
};
|
|
23547
23563
|
const handleFullReset = () => {
|
|
23548
|
-
|
|
23549
|
-
|
|
23550
|
-
|
|
23564
|
+
if (playAgainEvent) {
|
|
23565
|
+
emit(`UI:${playAgainEvent}`, {});
|
|
23566
|
+
}
|
|
23567
|
+
setLocalAssignments({});
|
|
23568
|
+
setLocalSubmitted(false);
|
|
23569
|
+
setLocalAttempts(0);
|
|
23551
23570
|
setShowHint(false);
|
|
23552
23571
|
};
|
|
23553
23572
|
if (!resolved) return null;
|
|
@@ -31430,13 +31449,13 @@ var init_MapView = __esm({
|
|
|
31430
31449
|
shadowSize: [41, 41]
|
|
31431
31450
|
});
|
|
31432
31451
|
L.Marker.prototype.options.icon = defaultIcon;
|
|
31433
|
-
const { useEffect:
|
|
31452
|
+
const { useEffect: useEffect78, useRef: useRef70, useCallback: useCallback117, useState: useState115 } = React91__namespace.default;
|
|
31434
31453
|
const { Typography: Typography2 } = await Promise.resolve().then(() => (init_Typography(), Typography_exports));
|
|
31435
31454
|
const { useEventBus: useEventBus3 } = await Promise.resolve().then(() => (init_useEventBus(), useEventBus_exports));
|
|
31436
31455
|
function MapUpdater({ centerLat, centerLng, zoom }) {
|
|
31437
31456
|
const map = useMap();
|
|
31438
|
-
const prevRef =
|
|
31439
|
-
|
|
31457
|
+
const prevRef = useRef70({ centerLat, centerLng, zoom });
|
|
31458
|
+
useEffect78(() => {
|
|
31440
31459
|
const prev = prevRef.current;
|
|
31441
31460
|
if (prev.centerLat !== centerLat || prev.centerLng !== centerLng || prev.zoom !== zoom) {
|
|
31442
31461
|
map.setView([centerLat, centerLng], zoom);
|
|
@@ -31447,7 +31466,7 @@ var init_MapView = __esm({
|
|
|
31447
31466
|
}
|
|
31448
31467
|
function MapClickHandler({ onMapClick }) {
|
|
31449
31468
|
const map = useMap();
|
|
31450
|
-
|
|
31469
|
+
useEffect78(() => {
|
|
31451
31470
|
if (!onMapClick) return;
|
|
31452
31471
|
const handler = (e) => {
|
|
31453
31472
|
onMapClick(e.latlng.lat, e.latlng.lng);
|
|
@@ -31476,7 +31495,7 @@ var init_MapView = __esm({
|
|
|
31476
31495
|
}) {
|
|
31477
31496
|
const eventBus = useEventBus3();
|
|
31478
31497
|
const [clickedPosition, setClickedPosition] = useState115(null);
|
|
31479
|
-
const handleMapClick =
|
|
31498
|
+
const handleMapClick = useCallback117((lat, lng) => {
|
|
31480
31499
|
if (showClickedPin) {
|
|
31481
31500
|
setClickedPosition({ lat, lng });
|
|
31482
31501
|
}
|
|
@@ -31485,7 +31504,7 @@ var init_MapView = __esm({
|
|
|
31485
31504
|
eventBus.emit(`UI:${mapClickEvent}`, { latitude: lat, longitude: lng });
|
|
31486
31505
|
}
|
|
31487
31506
|
}, [onMapClick, mapClickEvent, eventBus, showClickedPin]);
|
|
31488
|
-
const handleMarkerClick =
|
|
31507
|
+
const handleMarkerClick = useCallback117((marker) => {
|
|
31489
31508
|
onMarkerClick?.(marker);
|
|
31490
31509
|
if (markerClickEvent) {
|
|
31491
31510
|
eventBus.emit(`UI:${markerClickEvent}`, { ...marker });
|
|
@@ -40298,51 +40317,52 @@ var init_DataTable = __esm({
|
|
|
40298
40317
|
function DebuggerBoard({
|
|
40299
40318
|
entity,
|
|
40300
40319
|
completeEvent = "PUZZLE_COMPLETE",
|
|
40320
|
+
toggleFlagEvent,
|
|
40321
|
+
checkEvent,
|
|
40322
|
+
playAgainEvent,
|
|
40301
40323
|
className
|
|
40302
40324
|
}) {
|
|
40303
40325
|
const { emit } = useEventBus();
|
|
40304
40326
|
const { t } = hooks.useTranslate();
|
|
40305
40327
|
const resolved = boardEntity(entity);
|
|
40306
|
-
const [flaggedLines, setFlaggedLines] = React91.useState(/* @__PURE__ */ new Set());
|
|
40307
40328
|
const [headerError, setHeaderError] = React91.useState(false);
|
|
40308
|
-
const [submitted, setSubmitted] = React91.useState(false);
|
|
40309
|
-
const [attempts, setAttempts] = React91.useState(0);
|
|
40310
40329
|
const [showHint, setShowHint] = React91.useState(false);
|
|
40330
|
+
const lines = Array.isArray(resolved?.lines) ? resolved.lines : [];
|
|
40331
|
+
const result = resolved?.result ?? null;
|
|
40332
|
+
const attempts = num(resolved?.attempts);
|
|
40333
|
+
const submitted = result != null;
|
|
40334
|
+
const bugLines = lines.filter((l) => l.isBug);
|
|
40335
|
+
const flaggedLines = lines.filter((l) => l.isFlagged);
|
|
40336
|
+
const correctFlags = lines.filter((l) => l.isBug && l.isFlagged);
|
|
40337
|
+
const falseFlags = lines.filter((l) => !l.isBug && l.isFlagged);
|
|
40338
|
+
const allCorrect = result === "win";
|
|
40311
40339
|
const toggleLine = (lineId) => {
|
|
40312
40340
|
if (submitted) return;
|
|
40313
|
-
|
|
40314
|
-
|
|
40315
|
-
|
|
40316
|
-
next.delete(lineId);
|
|
40317
|
-
} else {
|
|
40318
|
-
next.add(lineId);
|
|
40319
|
-
}
|
|
40320
|
-
return next;
|
|
40321
|
-
});
|
|
40341
|
+
if (toggleFlagEvent) {
|
|
40342
|
+
emit(`UI:${toggleFlagEvent}`, { lineId });
|
|
40343
|
+
}
|
|
40322
40344
|
};
|
|
40323
|
-
const lines = Array.isArray(resolved?.lines) ? resolved.lines : [];
|
|
40324
|
-
const bugLines = lines.filter((l) => l.isBug);
|
|
40325
|
-
const correctFlags = lines.filter((l) => l.isBug && flaggedLines.has(l.id));
|
|
40326
|
-
const falseFlags = lines.filter((l) => !l.isBug && flaggedLines.has(l.id));
|
|
40327
|
-
const allCorrect = submitted && correctFlags.length === bugLines.length && falseFlags.length === 0;
|
|
40328
40345
|
const handleSubmit = React91.useCallback(() => {
|
|
40329
|
-
|
|
40330
|
-
|
|
40346
|
+
if (checkEvent) {
|
|
40347
|
+
emit(`UI:${checkEvent}`, {});
|
|
40348
|
+
}
|
|
40331
40349
|
const correct = correctFlags.length === bugLines.length && falseFlags.length === 0;
|
|
40332
40350
|
if (correct) {
|
|
40333
40351
|
emit(`UI:${completeEvent}`, { success: true, attempts: attempts + 1 });
|
|
40334
40352
|
}
|
|
40335
|
-
}, [correctFlags.length, bugLines.length, falseFlags.length, attempts, completeEvent, emit]);
|
|
40353
|
+
}, [checkEvent, correctFlags.length, bugLines.length, falseFlags.length, attempts, completeEvent, emit]);
|
|
40336
40354
|
const handleReset = () => {
|
|
40337
|
-
|
|
40355
|
+
if (playAgainEvent) {
|
|
40356
|
+
emit(`UI:${playAgainEvent}`, {});
|
|
40357
|
+
}
|
|
40338
40358
|
if (attempts >= 2 && str(resolved?.hint)) {
|
|
40339
40359
|
setShowHint(true);
|
|
40340
40360
|
}
|
|
40341
40361
|
};
|
|
40342
40362
|
const handleFullReset = () => {
|
|
40343
|
-
|
|
40344
|
-
|
|
40345
|
-
|
|
40363
|
+
if (playAgainEvent) {
|
|
40364
|
+
emit(`UI:${playAgainEvent}`, {});
|
|
40365
|
+
}
|
|
40346
40366
|
setShowHint(false);
|
|
40347
40367
|
};
|
|
40348
40368
|
if (!resolved) return null;
|
|
@@ -40370,7 +40390,7 @@ function DebuggerBoard({
|
|
|
40370
40390
|
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "caption", className: "text-muted-foreground", children: t("debugger.findBugs", { count: String(num(resolved.bugCount)) }) })
|
|
40371
40391
|
] }) }),
|
|
40372
40392
|
/* @__PURE__ */ jsxRuntime.jsx(Card, { className: "p-0 overflow-hidden", children: /* @__PURE__ */ jsxRuntime.jsx(VStack, { gap: "none", children: lines.map((line, i) => {
|
|
40373
|
-
const isFlagged =
|
|
40393
|
+
const isFlagged = !!line.isFlagged;
|
|
40374
40394
|
let lineStyle = "";
|
|
40375
40395
|
if (submitted) {
|
|
40376
40396
|
if (line.isBug && isFlagged) lineStyle = "bg-success/10";
|
|
@@ -40404,9 +40424,9 @@ function DebuggerBoard({
|
|
|
40404
40424
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
40405
40425
|
Icon,
|
|
40406
40426
|
{
|
|
40407
|
-
icon:
|
|
40427
|
+
icon: line.isFlagged ? LucideIcons2.CheckCircle : LucideIcons2.XCircle,
|
|
40408
40428
|
size: "xs",
|
|
40409
|
-
className:
|
|
40429
|
+
className: line.isFlagged ? "text-success mt-0.5" : "text-warning mt-0.5"
|
|
40410
40430
|
}
|
|
40411
40431
|
),
|
|
40412
40432
|
/* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "none", children: [
|
|
@@ -40417,7 +40437,7 @@ function DebuggerBoard({
|
|
|
40417
40437
|
] }) }),
|
|
40418
40438
|
showHint && hint && /* @__PURE__ */ jsxRuntime.jsx(Card, { className: "p-4 border-l-4 border-l-warning", children: /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body", children: hint }) }),
|
|
40419
40439
|
/* @__PURE__ */ jsxRuntime.jsxs(HStack, { gap: "sm", justify: "center", children: [
|
|
40420
|
-
!submitted ? /* @__PURE__ */ jsxRuntime.jsxs(Button, { variant: "primary", onClick: handleSubmit, disabled: flaggedLines.
|
|
40440
|
+
!submitted ? /* @__PURE__ */ jsxRuntime.jsxs(Button, { variant: "primary", onClick: handleSubmit, disabled: flaggedLines.length === 0, children: [
|
|
40421
40441
|
/* @__PURE__ */ jsxRuntime.jsx(Icon, { icon: LucideIcons2.Send, size: "sm" }),
|
|
40422
40442
|
t("debugger.submit")
|
|
40423
40443
|
] }) : !allCorrect ? /* @__PURE__ */ jsxRuntime.jsx(Button, { variant: "primary", onClick: handleReset, children: t("debugger.tryAgain") }) : null,
|
|
@@ -44181,6 +44201,9 @@ function getOpponentAction(strategy, actions, history) {
|
|
|
44181
44201
|
function NegotiatorBoard({
|
|
44182
44202
|
entity,
|
|
44183
44203
|
completeEvent = "PUZZLE_COMPLETE",
|
|
44204
|
+
playRoundEvent,
|
|
44205
|
+
finishEvent,
|
|
44206
|
+
playAgainEvent,
|
|
44184
44207
|
className
|
|
44185
44208
|
}) {
|
|
44186
44209
|
const { emit } = useEventBus();
|
|
@@ -44189,13 +44212,14 @@ function NegotiatorBoard({
|
|
|
44189
44212
|
const [history, setHistory] = React91.useState([]);
|
|
44190
44213
|
const [headerError, setHeaderError] = React91.useState(false);
|
|
44191
44214
|
const [showHint, setShowHint] = React91.useState(false);
|
|
44192
|
-
const totalRounds = num(resolved?.
|
|
44215
|
+
const totalRounds = num(resolved?.maxRounds);
|
|
44193
44216
|
const targetScore = num(resolved?.targetScore);
|
|
44194
|
-
const currentRound =
|
|
44195
|
-
const
|
|
44196
|
-
const playerTotal =
|
|
44217
|
+
const currentRound = num(resolved?.round);
|
|
44218
|
+
const result = str(resolved?.result) || "none";
|
|
44219
|
+
const playerTotal = num(resolved?.score);
|
|
44220
|
+
const isComplete = result !== "none" || totalRounds > 0 && currentRound >= totalRounds;
|
|
44221
|
+
const won = result === "win";
|
|
44197
44222
|
const opponentTotal = history.reduce((s, r2) => s + r2.opponentPayoff, 0);
|
|
44198
|
-
const won = isComplete && playerTotal >= targetScore;
|
|
44199
44223
|
const actions = Array.isArray(resolved?.actions) ? resolved.actions : [];
|
|
44200
44224
|
const payoffMatrix = Array.isArray(resolved?.payoffMatrix) ? resolved.payoffMatrix : [];
|
|
44201
44225
|
const handleAction = React91.useCallback((actionId) => {
|
|
@@ -44204,29 +44228,45 @@ function NegotiatorBoard({
|
|
|
44204
44228
|
const payoff = payoffMatrix.find(
|
|
44205
44229
|
(p2) => p2.playerAction === actionId && p2.opponentAction === opponentAction
|
|
44206
44230
|
);
|
|
44207
|
-
const
|
|
44208
|
-
|
|
44209
|
-
|
|
44210
|
-
|
|
44211
|
-
|
|
44212
|
-
|
|
44213
|
-
|
|
44214
|
-
|
|
44215
|
-
|
|
44216
|
-
|
|
44217
|
-
|
|
44218
|
-
|
|
44219
|
-
|
|
44220
|
-
|
|
44221
|
-
|
|
44231
|
+
const playerPayoff = payoff?.playerPayoff ?? 0;
|
|
44232
|
+
setHistory((prev) => [
|
|
44233
|
+
...prev,
|
|
44234
|
+
{
|
|
44235
|
+
round: prev.length + 1,
|
|
44236
|
+
playerAction: actionId,
|
|
44237
|
+
opponentAction,
|
|
44238
|
+
playerPayoff,
|
|
44239
|
+
opponentPayoff: payoff?.opponentPayoff ?? 0
|
|
44240
|
+
}
|
|
44241
|
+
]);
|
|
44242
|
+
if (playRoundEvent) {
|
|
44243
|
+
emit(`UI:${playRoundEvent}`, { playerAction: actionId, payoff: playerPayoff });
|
|
44244
|
+
}
|
|
44245
|
+
if (totalRounds > 0 && currentRound + 1 >= totalRounds) {
|
|
44246
|
+
if (finishEvent) {
|
|
44247
|
+
emit(`UI:${finishEvent}`, {});
|
|
44248
|
+
}
|
|
44249
|
+
if (str(resolved?.hint)) {
|
|
44222
44250
|
setShowHint(true);
|
|
44223
44251
|
}
|
|
44224
44252
|
}
|
|
44225
|
-
}, [isComplete, resolved, totalRounds,
|
|
44226
|
-
const handleReset = () => {
|
|
44253
|
+
}, [isComplete, resolved, totalRounds, currentRound, actions, payoffMatrix, history, playRoundEvent, finishEvent, emit]);
|
|
44254
|
+
const handleReset = React91.useCallback(() => {
|
|
44227
44255
|
setHistory([]);
|
|
44228
44256
|
setShowHint(false);
|
|
44229
|
-
|
|
44257
|
+
if (playAgainEvent) {
|
|
44258
|
+
emit(`UI:${playAgainEvent}`, {});
|
|
44259
|
+
}
|
|
44260
|
+
}, [playAgainEvent, emit]);
|
|
44261
|
+
const completedRef = React91.useRef(false);
|
|
44262
|
+
React91.useEffect(() => {
|
|
44263
|
+
if (result === "win" && !completedRef.current) {
|
|
44264
|
+
completedRef.current = true;
|
|
44265
|
+
emit(`UI:${completeEvent}`, { success: true, score: playerTotal });
|
|
44266
|
+
} else if (result === "none") {
|
|
44267
|
+
completedRef.current = false;
|
|
44268
|
+
}
|
|
44269
|
+
}, [result, playerTotal, completeEvent, emit]);
|
|
44230
44270
|
const getActionLabel = (id) => actions.find((a) => a.id === id)?.label ?? id;
|
|
44231
44271
|
if (!resolved) return null;
|
|
44232
44272
|
const theme = resolved.theme ?? void 0;
|
|
@@ -47192,67 +47232,47 @@ var init_SimulationGraph = __esm({
|
|
|
47192
47232
|
function SimulatorBoard({
|
|
47193
47233
|
entity,
|
|
47194
47234
|
completeEvent = "PUZZLE_COMPLETE",
|
|
47235
|
+
setAEvent,
|
|
47236
|
+
setBEvent,
|
|
47237
|
+
checkEvent,
|
|
47238
|
+
playAgainEvent,
|
|
47195
47239
|
className
|
|
47196
47240
|
}) {
|
|
47197
47241
|
const { emit } = useEventBus();
|
|
47198
47242
|
const { t } = hooks.useTranslate();
|
|
47199
47243
|
const resolved = boardEntity(entity);
|
|
47200
47244
|
const parameters = Array.isArray(resolved?.parameters) ? resolved.parameters : [];
|
|
47201
|
-
const [values, setValues] = React91.useState(() => {
|
|
47202
|
-
const init = {};
|
|
47203
|
-
for (const p2 of parameters) {
|
|
47204
|
-
init[p2.id] = p2.initial;
|
|
47205
|
-
}
|
|
47206
|
-
return init;
|
|
47207
|
-
});
|
|
47208
47245
|
const [headerError, setHeaderError] = React91.useState(false);
|
|
47209
|
-
|
|
47210
|
-
const
|
|
47211
|
-
const
|
|
47212
|
-
const
|
|
47213
|
-
|
|
47214
|
-
|
|
47215
|
-
|
|
47216
|
-
|
|
47217
|
-
|
|
47218
|
-
|
|
47219
|
-
|
|
47220
|
-
const
|
|
47221
|
-
const
|
|
47222
|
-
const
|
|
47223
|
-
const
|
|
47224
|
-
|
|
47225
|
-
|
|
47226
|
-
|
|
47246
|
+
if (!resolved) return null;
|
|
47247
|
+
const paramA = num(resolved.paramA);
|
|
47248
|
+
const paramB = num(resolved.paramB);
|
|
47249
|
+
const output = num(resolved.output);
|
|
47250
|
+
const targetValue = num(resolved.target);
|
|
47251
|
+
const targetTolerance = num(resolved.tolerance);
|
|
47252
|
+
const attempts = num(resolved.attempts);
|
|
47253
|
+
const result = str(resolved.result);
|
|
47254
|
+
const isWin = result === "win";
|
|
47255
|
+
const isComplete = result !== "none" && result !== "";
|
|
47256
|
+
const paramAValue = parameters[0];
|
|
47257
|
+
const paramBValue = parameters[1];
|
|
47258
|
+
const sliderValues = [paramA, paramB];
|
|
47259
|
+
const sliderEvents = [setAEvent, setBEvent];
|
|
47260
|
+
const handleParameterChange = (index, value) => {
|
|
47261
|
+
if (isComplete) return;
|
|
47262
|
+
const ev = sliderEvents[index];
|
|
47263
|
+
if (ev) emit(`UI:${ev}`, { value });
|
|
47227
47264
|
};
|
|
47228
|
-
const
|
|
47229
|
-
|
|
47230
|
-
setAttempts((a) => a + 1);
|
|
47231
|
-
if (isCorrect) {
|
|
47232
|
-
emit(`UI:${completeEvent}`, { success: true, attempts: attempts + 1 });
|
|
47233
|
-
}
|
|
47265
|
+
const handleCheck = () => {
|
|
47266
|
+
if (checkEvent) emit(`UI:${checkEvent}`, {});
|
|
47234
47267
|
};
|
|
47235
|
-
const
|
|
47236
|
-
|
|
47237
|
-
if (attempts >= 2 && str(resolved?.hint)) {
|
|
47238
|
-
setShowHint(true);
|
|
47239
|
-
}
|
|
47268
|
+
const handlePlayAgain = () => {
|
|
47269
|
+
if (playAgainEvent) emit(`UI:${playAgainEvent}`, {});
|
|
47240
47270
|
};
|
|
47241
|
-
const handleFullReset = () => {
|
|
47242
|
-
const init = {};
|
|
47243
|
-
for (const p2 of parameters) {
|
|
47244
|
-
init[p2.id] = p2.initial;
|
|
47245
|
-
}
|
|
47246
|
-
setValues(init);
|
|
47247
|
-
setSubmitted(false);
|
|
47248
|
-
setAttempts(0);
|
|
47249
|
-
setShowHint(false);
|
|
47250
|
-
};
|
|
47251
|
-
if (!resolved) return null;
|
|
47252
47271
|
const theme = resolved.theme ?? void 0;
|
|
47253
47272
|
const themeBackground = theme?.background;
|
|
47254
47273
|
const headerImage = str(resolved.headerImage);
|
|
47255
47274
|
const hint = str(resolved.hint);
|
|
47275
|
+
const showHint = isComplete && !isWin && attempts >= 2 && Boolean(hint);
|
|
47256
47276
|
const outputLabel = str(resolved.outputLabel);
|
|
47257
47277
|
const outputUnit = str(resolved.outputUnit);
|
|
47258
47278
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -47272,41 +47292,43 @@ function SimulatorBoard({
|
|
|
47272
47292
|
] }) }),
|
|
47273
47293
|
/* @__PURE__ */ jsxRuntime.jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "md", children: [
|
|
47274
47294
|
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "small", weight: "bold", className: "uppercase tracking-wider text-muted-foreground", children: t("simulator.parameters") }),
|
|
47275
|
-
|
|
47276
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
47277
|
-
/* @__PURE__ */ jsxRuntime.
|
|
47278
|
-
|
|
47279
|
-
|
|
47280
|
-
|
|
47281
|
-
|
|
47282
|
-
|
|
47283
|
-
|
|
47284
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
47285
|
-
"input",
|
|
47286
|
-
{
|
|
47287
|
-
type: "range",
|
|
47288
|
-
min: param.min,
|
|
47289
|
-
max: param.max,
|
|
47290
|
-
step: param.step,
|
|
47291
|
-
value: values[param.id],
|
|
47292
|
-
onChange: (e) => handleParameterChange(param.id, Number(e.target.value)),
|
|
47293
|
-
disabled: submitted,
|
|
47294
|
-
className: "w-full accent-foreground"
|
|
47295
|
-
}
|
|
47296
|
-
),
|
|
47297
|
-
/* @__PURE__ */ jsxRuntime.jsxs(HStack, { justify: "between", children: [
|
|
47298
|
-
/* @__PURE__ */ jsxRuntime.jsxs(Typography, { variant: "caption", className: "text-muted-foreground", children: [
|
|
47299
|
-
param.min,
|
|
47300
|
-
" ",
|
|
47301
|
-
param.unit
|
|
47295
|
+
[paramAValue, paramBValue].map(
|
|
47296
|
+
(param, index) => param ? /* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "xs", children: [
|
|
47297
|
+
/* @__PURE__ */ jsxRuntime.jsxs(HStack, { justify: "between", align: "center", children: [
|
|
47298
|
+
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body", weight: "medium", children: param.label }),
|
|
47299
|
+
/* @__PURE__ */ jsxRuntime.jsxs(Badge, { size: "sm", children: [
|
|
47300
|
+
sliderValues[index],
|
|
47301
|
+
" ",
|
|
47302
|
+
param.unit
|
|
47303
|
+
] })
|
|
47302
47304
|
] }),
|
|
47303
|
-
/* @__PURE__ */ jsxRuntime.
|
|
47304
|
-
|
|
47305
|
-
|
|
47306
|
-
|
|
47305
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
47306
|
+
"input",
|
|
47307
|
+
{
|
|
47308
|
+
type: "range",
|
|
47309
|
+
min: param.min,
|
|
47310
|
+
max: param.max,
|
|
47311
|
+
step: param.step,
|
|
47312
|
+
value: sliderValues[index],
|
|
47313
|
+
onChange: (e) => handleParameterChange(index, Number(e.target.value)),
|
|
47314
|
+
disabled: isComplete,
|
|
47315
|
+
className: "w-full accent-foreground"
|
|
47316
|
+
}
|
|
47317
|
+
),
|
|
47318
|
+
/* @__PURE__ */ jsxRuntime.jsxs(HStack, { justify: "between", children: [
|
|
47319
|
+
/* @__PURE__ */ jsxRuntime.jsxs(Typography, { variant: "caption", className: "text-muted-foreground", children: [
|
|
47320
|
+
param.min,
|
|
47321
|
+
" ",
|
|
47322
|
+
param.unit
|
|
47323
|
+
] }),
|
|
47324
|
+
/* @__PURE__ */ jsxRuntime.jsxs(Typography, { variant: "caption", className: "text-muted-foreground", children: [
|
|
47325
|
+
param.max,
|
|
47326
|
+
" ",
|
|
47327
|
+
param.unit
|
|
47328
|
+
] })
|
|
47307
47329
|
] })
|
|
47308
|
-
] })
|
|
47309
|
-
|
|
47330
|
+
] }, param.id ?? index) : null
|
|
47331
|
+
)
|
|
47310
47332
|
] }) }),
|
|
47311
47333
|
/* @__PURE__ */ jsxRuntime.jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "sm", align: "center", children: [
|
|
47312
47334
|
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "small", weight: "bold", className: "uppercase tracking-wider text-muted-foreground", children: outputLabel }),
|
|
@@ -47315,9 +47337,9 @@ function SimulatorBoard({
|
|
|
47315
47337
|
" ",
|
|
47316
47338
|
outputUnit
|
|
47317
47339
|
] }),
|
|
47318
|
-
|
|
47319
|
-
/* @__PURE__ */ jsxRuntime.jsx(Icon, { icon:
|
|
47320
|
-
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body", className:
|
|
47340
|
+
isComplete && /* @__PURE__ */ jsxRuntime.jsxs(HStack, { gap: "xs", align: "center", children: [
|
|
47341
|
+
/* @__PURE__ */ jsxRuntime.jsx(Icon, { icon: isWin ? LucideIcons2.CheckCircle : LucideIcons2.XCircle, size: "sm", className: isWin ? "text-success" : "text-error" }),
|
|
47342
|
+
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body", className: isWin ? "text-success" : "text-error", children: isWin ? str(resolved.successMessage) || t("simulator.correct") : str(resolved.failMessage) || t("simulator.incorrect") })
|
|
47321
47343
|
] }),
|
|
47322
47344
|
/* @__PURE__ */ jsxRuntime.jsxs(Typography, { variant: "caption", className: "text-muted-foreground", children: [
|
|
47323
47345
|
t("simulator.target"),
|
|
@@ -47332,11 +47354,11 @@ function SimulatorBoard({
|
|
|
47332
47354
|
] }) }),
|
|
47333
47355
|
showHint && hint && /* @__PURE__ */ jsxRuntime.jsx(Card, { className: "p-4 border-l-4 border-l-warning", children: /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body", children: hint }) }),
|
|
47334
47356
|
/* @__PURE__ */ jsxRuntime.jsxs(HStack, { gap: "sm", justify: "center", children: [
|
|
47335
|
-
!
|
|
47357
|
+
!isComplete ? /* @__PURE__ */ jsxRuntime.jsxs(Button, { variant: "primary", onClick: handleCheck, children: [
|
|
47336
47358
|
/* @__PURE__ */ jsxRuntime.jsx(Icon, { icon: LucideIcons2.Play, size: "sm" }),
|
|
47337
47359
|
t("simulator.simulate")
|
|
47338
|
-
] }) :
|
|
47339
|
-
/* @__PURE__ */ jsxRuntime.jsxs(Button, { variant: "secondary", onClick:
|
|
47360
|
+
] }) : null,
|
|
47361
|
+
/* @__PURE__ */ jsxRuntime.jsxs(Button, { variant: "secondary", onClick: handlePlayAgain, children: [
|
|
47340
47362
|
/* @__PURE__ */ jsxRuntime.jsx(Icon, { icon: LucideIcons2.RotateCcw, size: "sm" }),
|
|
47341
47363
|
t("simulator.reset")
|
|
47342
47364
|
] })
|