@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.js
CHANGED
|
@@ -19849,61 +19849,53 @@ var init_Breadcrumb = __esm({
|
|
|
19849
19849
|
function BuilderBoard({
|
|
19850
19850
|
entity,
|
|
19851
19851
|
completeEvent = "PUZZLE_COMPLETE",
|
|
19852
|
+
placeEvent,
|
|
19853
|
+
checkEvent,
|
|
19854
|
+
playAgainEvent,
|
|
19852
19855
|
className
|
|
19853
19856
|
}) {
|
|
19854
19857
|
const { emit } = useEventBus();
|
|
19855
19858
|
const { t } = useTranslate();
|
|
19856
19859
|
const resolved = boardEntity(entity);
|
|
19857
|
-
const [placements, setPlacements] = useState({});
|
|
19858
19860
|
const [headerError, setHeaderError] = useState(false);
|
|
19859
|
-
const [
|
|
19860
|
-
const [attempts, setAttempts] = useState(0);
|
|
19861
|
-
const [showHint, setShowHint] = useState(false);
|
|
19861
|
+
const [selectedComponent, setSelectedComponent] = useState(null);
|
|
19862
19862
|
const components = Array.isArray(resolved?.components) ? resolved.components : [];
|
|
19863
19863
|
const slots = Array.isArray(resolved?.slots) ? resolved.slots : [];
|
|
19864
|
+
const placements = {};
|
|
19865
|
+
for (const slot of slots) {
|
|
19866
|
+
if (slot.placedComponentId) placements[slot.id] = slot.placedComponentId;
|
|
19867
|
+
}
|
|
19868
|
+
const attempts = num(resolved?.attempts);
|
|
19869
|
+
const result = str(resolved?.result) || "none";
|
|
19870
|
+
const submitted = result === "win";
|
|
19864
19871
|
const usedComponentIds = new Set(Object.values(placements));
|
|
19865
19872
|
const availableComponents = components.filter((c) => !usedComponentIds.has(c.id));
|
|
19866
|
-
const
|
|
19867
|
-
const allPlaced = Object.keys(placements).length === slots.length;
|
|
19873
|
+
const allPlaced = slots.length > 0 && slots.every((s) => Boolean(placements[s.id]));
|
|
19868
19874
|
const results = submitted ? slots.map((slot) => ({
|
|
19869
19875
|
slot,
|
|
19870
19876
|
placed: placements[slot.id],
|
|
19871
|
-
correct: placements[slot.id] === slot.
|
|
19877
|
+
correct: placements[slot.id] === slot.requiredComponentId
|
|
19872
19878
|
})) : [];
|
|
19873
|
-
const
|
|
19879
|
+
const showHint = attempts >= 2 && Boolean(str(resolved?.hint));
|
|
19874
19880
|
const handlePlaceComponent = (slotId) => {
|
|
19875
19881
|
if (submitted || !selectedComponent) return;
|
|
19876
|
-
|
|
19882
|
+
if (placeEvent) emit(`UI:${placeEvent}`, { slotId, componentId: selectedComponent });
|
|
19877
19883
|
setSelectedComponent(null);
|
|
19878
19884
|
};
|
|
19879
19885
|
const handleRemoveFromSlot = (slotId) => {
|
|
19880
19886
|
if (submitted) return;
|
|
19881
|
-
|
|
19882
|
-
const next = { ...prev };
|
|
19883
|
-
delete next[slotId];
|
|
19884
|
-
return next;
|
|
19885
|
-
});
|
|
19887
|
+
if (placeEvent) emit(`UI:${placeEvent}`, { slotId, componentId: "" });
|
|
19886
19888
|
};
|
|
19887
|
-
const handleSubmit =
|
|
19888
|
-
|
|
19889
|
-
|
|
19890
|
-
|
|
19891
|
-
if (correct) {
|
|
19889
|
+
const handleSubmit = () => {
|
|
19890
|
+
if (checkEvent) emit(`UI:${checkEvent}`, {});
|
|
19891
|
+
const solved = slots.length > 0 && slots.every((s) => placements[s.id] === s.requiredComponentId);
|
|
19892
|
+
if (solved && completeEvent) {
|
|
19892
19893
|
emit(`UI:${completeEvent}`, { success: true, attempts: attempts + 1 });
|
|
19893
19894
|
}
|
|
19894
|
-
}, [slots, placements, attempts, completeEvent, emit]);
|
|
19895
|
-
const handleReset = () => {
|
|
19896
|
-
setSubmitted(false);
|
|
19897
|
-
if (attempts >= 2 && str(resolved?.hint)) {
|
|
19898
|
-
setShowHint(true);
|
|
19899
|
-
}
|
|
19900
19895
|
};
|
|
19901
|
-
const
|
|
19902
|
-
setPlacements({});
|
|
19903
|
-
setSubmitted(false);
|
|
19896
|
+
const handlePlayAgain = () => {
|
|
19904
19897
|
setSelectedComponent(null);
|
|
19905
|
-
|
|
19906
|
-
setShowHint(false);
|
|
19898
|
+
if (playAgainEvent) emit(`UI:${playAgainEvent}`, {});
|
|
19907
19899
|
};
|
|
19908
19900
|
const getComponentById = (id) => components.find((c) => c.id === id);
|
|
19909
19901
|
if (!resolved) return null;
|
|
@@ -19953,13 +19945,13 @@ function BuilderBoard({
|
|
|
19953
19945
|
/* @__PURE__ */ jsx(Typography, { variant: "small", weight: "bold", className: "uppercase tracking-wider text-muted-foreground", children: t("builder.blueprint") }),
|
|
19954
19946
|
/* @__PURE__ */ jsx(VStack, { gap: "sm", children: slots.map((slot) => {
|
|
19955
19947
|
const placedComp = placements[slot.id] ? getComponentById(placements[slot.id]) : null;
|
|
19956
|
-
const
|
|
19948
|
+
const result2 = results.find((r2) => r2.slot.id === slot.id);
|
|
19957
19949
|
return /* @__PURE__ */ jsxs(
|
|
19958
19950
|
HStack,
|
|
19959
19951
|
{
|
|
19960
19952
|
gap: "sm",
|
|
19961
19953
|
align: "center",
|
|
19962
|
-
className: `p-3 border-2 rounded ${
|
|
19954
|
+
className: `p-3 border-2 rounded ${result2 ? result2.correct ? "border-success" : "border-error" : selectedComponent ? "border-dashed border-foreground cursor-pointer" : "border-border"}`,
|
|
19963
19955
|
onClick: () => handlePlaceComponent(slot.id),
|
|
19964
19956
|
children: [
|
|
19965
19957
|
/* @__PURE__ */ jsxs(VStack, { gap: "none", className: "flex-1", children: [
|
|
@@ -19974,7 +19966,7 @@ function BuilderBoard({
|
|
|
19974
19966
|
] }) : null,
|
|
19975
19967
|
placedComp.label
|
|
19976
19968
|
] }),
|
|
19977
|
-
|
|
19969
|
+
result2 && /* @__PURE__ */ jsx(Icon, { icon: result2.correct ? CheckCircle : XCircle, size: "sm", className: result2.correct ? "text-success" : "text-error" })
|
|
19978
19970
|
] }) : /* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-muted-foreground", children: t("builder.empty") })
|
|
19979
19971
|
]
|
|
19980
19972
|
},
|
|
@@ -19983,16 +19975,16 @@ function BuilderBoard({
|
|
|
19983
19975
|
}) })
|
|
19984
19976
|
] }) }),
|
|
19985
19977
|
submitted && /* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", align: "center", children: [
|
|
19986
|
-
/* @__PURE__ */ jsx(Icon, { icon:
|
|
19987
|
-
/* @__PURE__ */ jsx(Typography, { variant: "body", weight: "bold", children:
|
|
19978
|
+
/* @__PURE__ */ jsx(Icon, { icon: CheckCircle, size: "lg", className: "text-success" }),
|
|
19979
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body", weight: "bold", children: str(resolved.successMessage) || t("builder.success") })
|
|
19988
19980
|
] }) }),
|
|
19989
19981
|
showHint && hint && /* @__PURE__ */ jsx(Card, { className: "p-4 border-l-4 border-l-warning", children: /* @__PURE__ */ jsx(Typography, { variant: "body", children: hint }) }),
|
|
19990
19982
|
/* @__PURE__ */ jsxs(HStack, { gap: "sm", justify: "center", children: [
|
|
19991
|
-
!submitted
|
|
19983
|
+
!submitted && /* @__PURE__ */ jsxs(Button, { variant: "primary", onClick: handleSubmit, disabled: !allPlaced, children: [
|
|
19992
19984
|
/* @__PURE__ */ jsx(Icon, { icon: Wrench, size: "sm" }),
|
|
19993
19985
|
t("builder.build")
|
|
19994
|
-
] })
|
|
19995
|
-
/* @__PURE__ */ jsxs(Button, { variant: "secondary", onClick:
|
|
19986
|
+
] }),
|
|
19987
|
+
/* @__PURE__ */ jsxs(Button, { variant: "secondary", onClick: handlePlayAgain, children: [
|
|
19996
19988
|
/* @__PURE__ */ jsx(Icon, { icon: RotateCcw, size: "sm" }),
|
|
19997
19989
|
t("builder.reset")
|
|
19998
19990
|
] })
|
|
@@ -23448,57 +23440,84 @@ var init_ChartLegend = __esm({
|
|
|
23448
23440
|
function ClassifierBoard({
|
|
23449
23441
|
entity,
|
|
23450
23442
|
completeEvent = "PUZZLE_COMPLETE",
|
|
23443
|
+
assignEvent,
|
|
23444
|
+
checkEvent,
|
|
23445
|
+
playAgainEvent,
|
|
23451
23446
|
className
|
|
23452
23447
|
}) {
|
|
23453
23448
|
const { emit } = useEventBus();
|
|
23454
23449
|
const { t } = useTranslate();
|
|
23455
23450
|
const resolved = boardEntity(entity);
|
|
23456
|
-
const [
|
|
23451
|
+
const [localAssignments, setLocalAssignments] = useState({});
|
|
23457
23452
|
const [headerError, setHeaderError] = useState(false);
|
|
23458
|
-
const [
|
|
23459
|
-
const [
|
|
23453
|
+
const [localSubmitted, setLocalSubmitted] = useState(false);
|
|
23454
|
+
const [localAttempts, setLocalAttempts] = useState(0);
|
|
23460
23455
|
const [showHint, setShowHint] = useState(false);
|
|
23461
23456
|
const items = Array.isArray(resolved?.items) ? resolved.items : [];
|
|
23462
23457
|
const categories = Array.isArray(resolved?.categories) ? resolved.categories : [];
|
|
23458
|
+
const entityResult = str(resolved?.result);
|
|
23459
|
+
const entityDrivesResult = entityResult.length > 0;
|
|
23460
|
+
const entityHasAssignments = items.some((item) => item.assignedCategory != null);
|
|
23461
|
+
const assignments = entityHasAssignments ? items.reduce((acc, item) => {
|
|
23462
|
+
if (item.assignedCategory != null) acc[item.id] = item.assignedCategory;
|
|
23463
|
+
return acc;
|
|
23464
|
+
}, {}) : localAssignments;
|
|
23465
|
+
const attempts = entityDrivesResult ? num(resolved?.attempts) : localAttempts;
|
|
23466
|
+
const submitted = entityDrivesResult || localSubmitted;
|
|
23463
23467
|
const unassignedItems = items.filter((item) => !assignments[item.id]);
|
|
23464
|
-
const allAssigned = Object.keys(assignments).length === items.length;
|
|
23468
|
+
const allAssigned = items.length > 0 && Object.keys(assignments).length === items.length;
|
|
23465
23469
|
const results = submitted ? items.map((item) => ({
|
|
23466
23470
|
item,
|
|
23467
23471
|
assigned: assignments[item.id],
|
|
23468
23472
|
correct: assignments[item.id] === item.correctCategory
|
|
23469
23473
|
})) : [];
|
|
23470
|
-
const allCorrect = results.length > 0 && results.every((r2) => r2.correct);
|
|
23474
|
+
const allCorrect = entityDrivesResult ? entityResult === "success" : results.length > 0 && results.every((r2) => r2.correct);
|
|
23471
23475
|
const correctCount = results.filter((r2) => r2.correct).length;
|
|
23472
23476
|
const handleAssign = (itemId, categoryId) => {
|
|
23473
23477
|
if (submitted) return;
|
|
23474
|
-
|
|
23478
|
+
if (assignEvent) {
|
|
23479
|
+
emit(`UI:${assignEvent}`, { itemId, categoryId });
|
|
23480
|
+
}
|
|
23481
|
+
if (!entityHasAssignments) {
|
|
23482
|
+
setLocalAssignments((prev) => ({ ...prev, [itemId]: categoryId }));
|
|
23483
|
+
}
|
|
23475
23484
|
};
|
|
23476
23485
|
const handleUnassign = (itemId) => {
|
|
23477
23486
|
if (submitted) return;
|
|
23478
|
-
|
|
23479
|
-
|
|
23480
|
-
|
|
23481
|
-
|
|
23482
|
-
|
|
23487
|
+
if (!entityHasAssignments) {
|
|
23488
|
+
setLocalAssignments((prev) => {
|
|
23489
|
+
const next = { ...prev };
|
|
23490
|
+
delete next[itemId];
|
|
23491
|
+
return next;
|
|
23492
|
+
});
|
|
23493
|
+
}
|
|
23483
23494
|
};
|
|
23484
23495
|
const handleSubmit = useCallback(() => {
|
|
23485
|
-
|
|
23486
|
-
|
|
23487
|
-
|
|
23488
|
-
if (
|
|
23489
|
-
|
|
23496
|
+
if (checkEvent) {
|
|
23497
|
+
emit(`UI:${checkEvent}`, {});
|
|
23498
|
+
}
|
|
23499
|
+
if (!entityDrivesResult) {
|
|
23500
|
+
setLocalSubmitted(true);
|
|
23501
|
+
setLocalAttempts((a) => a + 1);
|
|
23502
|
+
const correct = items.every((item) => assignments[item.id] === item.correctCategory);
|
|
23503
|
+
if (correct) {
|
|
23504
|
+
emit(`UI:${completeEvent}`, { success: true, attempts: attempts + 1 });
|
|
23505
|
+
}
|
|
23490
23506
|
}
|
|
23491
|
-
}, [items, assignments, attempts, completeEvent, emit]);
|
|
23507
|
+
}, [checkEvent, entityDrivesResult, items, assignments, attempts, completeEvent, emit]);
|
|
23492
23508
|
const handleReset = () => {
|
|
23493
|
-
|
|
23509
|
+
if (!entityDrivesResult) setLocalSubmitted(false);
|
|
23494
23510
|
if (attempts >= 2 && str(resolved?.hint)) {
|
|
23495
23511
|
setShowHint(true);
|
|
23496
23512
|
}
|
|
23497
23513
|
};
|
|
23498
23514
|
const handleFullReset = () => {
|
|
23499
|
-
|
|
23500
|
-
|
|
23501
|
-
|
|
23515
|
+
if (playAgainEvent) {
|
|
23516
|
+
emit(`UI:${playAgainEvent}`, {});
|
|
23517
|
+
}
|
|
23518
|
+
setLocalAssignments({});
|
|
23519
|
+
setLocalSubmitted(false);
|
|
23520
|
+
setLocalAttempts(0);
|
|
23502
23521
|
setShowHint(false);
|
|
23503
23522
|
};
|
|
23504
23523
|
if (!resolved) return null;
|
|
@@ -31381,13 +31400,13 @@ var init_MapView = __esm({
|
|
|
31381
31400
|
shadowSize: [41, 41]
|
|
31382
31401
|
});
|
|
31383
31402
|
L.Marker.prototype.options.icon = defaultIcon;
|
|
31384
|
-
const { useEffect:
|
|
31403
|
+
const { useEffect: useEffect78, useRef: useRef70, useCallback: useCallback117, useState: useState115 } = React91__default;
|
|
31385
31404
|
const { Typography: Typography2 } = await Promise.resolve().then(() => (init_Typography(), Typography_exports));
|
|
31386
31405
|
const { useEventBus: useEventBus3 } = await Promise.resolve().then(() => (init_useEventBus(), useEventBus_exports));
|
|
31387
31406
|
function MapUpdater({ centerLat, centerLng, zoom }) {
|
|
31388
31407
|
const map = useMap();
|
|
31389
|
-
const prevRef =
|
|
31390
|
-
|
|
31408
|
+
const prevRef = useRef70({ centerLat, centerLng, zoom });
|
|
31409
|
+
useEffect78(() => {
|
|
31391
31410
|
const prev = prevRef.current;
|
|
31392
31411
|
if (prev.centerLat !== centerLat || prev.centerLng !== centerLng || prev.zoom !== zoom) {
|
|
31393
31412
|
map.setView([centerLat, centerLng], zoom);
|
|
@@ -31398,7 +31417,7 @@ var init_MapView = __esm({
|
|
|
31398
31417
|
}
|
|
31399
31418
|
function MapClickHandler({ onMapClick }) {
|
|
31400
31419
|
const map = useMap();
|
|
31401
|
-
|
|
31420
|
+
useEffect78(() => {
|
|
31402
31421
|
if (!onMapClick) return;
|
|
31403
31422
|
const handler = (e) => {
|
|
31404
31423
|
onMapClick(e.latlng.lat, e.latlng.lng);
|
|
@@ -31427,7 +31446,7 @@ var init_MapView = __esm({
|
|
|
31427
31446
|
}) {
|
|
31428
31447
|
const eventBus = useEventBus3();
|
|
31429
31448
|
const [clickedPosition, setClickedPosition] = useState115(null);
|
|
31430
|
-
const handleMapClick =
|
|
31449
|
+
const handleMapClick = useCallback117((lat, lng) => {
|
|
31431
31450
|
if (showClickedPin) {
|
|
31432
31451
|
setClickedPosition({ lat, lng });
|
|
31433
31452
|
}
|
|
@@ -31436,7 +31455,7 @@ var init_MapView = __esm({
|
|
|
31436
31455
|
eventBus.emit(`UI:${mapClickEvent}`, { latitude: lat, longitude: lng });
|
|
31437
31456
|
}
|
|
31438
31457
|
}, [onMapClick, mapClickEvent, eventBus, showClickedPin]);
|
|
31439
|
-
const handleMarkerClick =
|
|
31458
|
+
const handleMarkerClick = useCallback117((marker) => {
|
|
31440
31459
|
onMarkerClick?.(marker);
|
|
31441
31460
|
if (markerClickEvent) {
|
|
31442
31461
|
eventBus.emit(`UI:${markerClickEvent}`, { ...marker });
|
|
@@ -40249,51 +40268,52 @@ var init_DataTable = __esm({
|
|
|
40249
40268
|
function DebuggerBoard({
|
|
40250
40269
|
entity,
|
|
40251
40270
|
completeEvent = "PUZZLE_COMPLETE",
|
|
40271
|
+
toggleFlagEvent,
|
|
40272
|
+
checkEvent,
|
|
40273
|
+
playAgainEvent,
|
|
40252
40274
|
className
|
|
40253
40275
|
}) {
|
|
40254
40276
|
const { emit } = useEventBus();
|
|
40255
40277
|
const { t } = useTranslate();
|
|
40256
40278
|
const resolved = boardEntity(entity);
|
|
40257
|
-
const [flaggedLines, setFlaggedLines] = useState(/* @__PURE__ */ new Set());
|
|
40258
40279
|
const [headerError, setHeaderError] = useState(false);
|
|
40259
|
-
const [submitted, setSubmitted] = useState(false);
|
|
40260
|
-
const [attempts, setAttempts] = useState(0);
|
|
40261
40280
|
const [showHint, setShowHint] = useState(false);
|
|
40281
|
+
const lines = Array.isArray(resolved?.lines) ? resolved.lines : [];
|
|
40282
|
+
const result = resolved?.result ?? null;
|
|
40283
|
+
const attempts = num(resolved?.attempts);
|
|
40284
|
+
const submitted = result != null;
|
|
40285
|
+
const bugLines = lines.filter((l) => l.isBug);
|
|
40286
|
+
const flaggedLines = lines.filter((l) => l.isFlagged);
|
|
40287
|
+
const correctFlags = lines.filter((l) => l.isBug && l.isFlagged);
|
|
40288
|
+
const falseFlags = lines.filter((l) => !l.isBug && l.isFlagged);
|
|
40289
|
+
const allCorrect = result === "win";
|
|
40262
40290
|
const toggleLine = (lineId) => {
|
|
40263
40291
|
if (submitted) return;
|
|
40264
|
-
|
|
40265
|
-
|
|
40266
|
-
|
|
40267
|
-
next.delete(lineId);
|
|
40268
|
-
} else {
|
|
40269
|
-
next.add(lineId);
|
|
40270
|
-
}
|
|
40271
|
-
return next;
|
|
40272
|
-
});
|
|
40292
|
+
if (toggleFlagEvent) {
|
|
40293
|
+
emit(`UI:${toggleFlagEvent}`, { lineId });
|
|
40294
|
+
}
|
|
40273
40295
|
};
|
|
40274
|
-
const lines = Array.isArray(resolved?.lines) ? resolved.lines : [];
|
|
40275
|
-
const bugLines = lines.filter((l) => l.isBug);
|
|
40276
|
-
const correctFlags = lines.filter((l) => l.isBug && flaggedLines.has(l.id));
|
|
40277
|
-
const falseFlags = lines.filter((l) => !l.isBug && flaggedLines.has(l.id));
|
|
40278
|
-
const allCorrect = submitted && correctFlags.length === bugLines.length && falseFlags.length === 0;
|
|
40279
40296
|
const handleSubmit = useCallback(() => {
|
|
40280
|
-
|
|
40281
|
-
|
|
40297
|
+
if (checkEvent) {
|
|
40298
|
+
emit(`UI:${checkEvent}`, {});
|
|
40299
|
+
}
|
|
40282
40300
|
const correct = correctFlags.length === bugLines.length && falseFlags.length === 0;
|
|
40283
40301
|
if (correct) {
|
|
40284
40302
|
emit(`UI:${completeEvent}`, { success: true, attempts: attempts + 1 });
|
|
40285
40303
|
}
|
|
40286
|
-
}, [correctFlags.length, bugLines.length, falseFlags.length, attempts, completeEvent, emit]);
|
|
40304
|
+
}, [checkEvent, correctFlags.length, bugLines.length, falseFlags.length, attempts, completeEvent, emit]);
|
|
40287
40305
|
const handleReset = () => {
|
|
40288
|
-
|
|
40306
|
+
if (playAgainEvent) {
|
|
40307
|
+
emit(`UI:${playAgainEvent}`, {});
|
|
40308
|
+
}
|
|
40289
40309
|
if (attempts >= 2 && str(resolved?.hint)) {
|
|
40290
40310
|
setShowHint(true);
|
|
40291
40311
|
}
|
|
40292
40312
|
};
|
|
40293
40313
|
const handleFullReset = () => {
|
|
40294
|
-
|
|
40295
|
-
|
|
40296
|
-
|
|
40314
|
+
if (playAgainEvent) {
|
|
40315
|
+
emit(`UI:${playAgainEvent}`, {});
|
|
40316
|
+
}
|
|
40297
40317
|
setShowHint(false);
|
|
40298
40318
|
};
|
|
40299
40319
|
if (!resolved) return null;
|
|
@@ -40321,7 +40341,7 @@ function DebuggerBoard({
|
|
|
40321
40341
|
/* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-muted-foreground", children: t("debugger.findBugs", { count: String(num(resolved.bugCount)) }) })
|
|
40322
40342
|
] }) }),
|
|
40323
40343
|
/* @__PURE__ */ jsx(Card, { className: "p-0 overflow-hidden", children: /* @__PURE__ */ jsx(VStack, { gap: "none", children: lines.map((line, i) => {
|
|
40324
|
-
const isFlagged =
|
|
40344
|
+
const isFlagged = !!line.isFlagged;
|
|
40325
40345
|
let lineStyle = "";
|
|
40326
40346
|
if (submitted) {
|
|
40327
40347
|
if (line.isBug && isFlagged) lineStyle = "bg-success/10";
|
|
@@ -40355,9 +40375,9 @@ function DebuggerBoard({
|
|
|
40355
40375
|
/* @__PURE__ */ jsx(
|
|
40356
40376
|
Icon,
|
|
40357
40377
|
{
|
|
40358
|
-
icon:
|
|
40378
|
+
icon: line.isFlagged ? CheckCircle : XCircle,
|
|
40359
40379
|
size: "xs",
|
|
40360
|
-
className:
|
|
40380
|
+
className: line.isFlagged ? "text-success mt-0.5" : "text-warning mt-0.5"
|
|
40361
40381
|
}
|
|
40362
40382
|
),
|
|
40363
40383
|
/* @__PURE__ */ jsxs(VStack, { gap: "none", children: [
|
|
@@ -40368,7 +40388,7 @@ function DebuggerBoard({
|
|
|
40368
40388
|
] }) }),
|
|
40369
40389
|
showHint && hint && /* @__PURE__ */ jsx(Card, { className: "p-4 border-l-4 border-l-warning", children: /* @__PURE__ */ jsx(Typography, { variant: "body", children: hint }) }),
|
|
40370
40390
|
/* @__PURE__ */ jsxs(HStack, { gap: "sm", justify: "center", children: [
|
|
40371
|
-
!submitted ? /* @__PURE__ */ jsxs(Button, { variant: "primary", onClick: handleSubmit, disabled: flaggedLines.
|
|
40391
|
+
!submitted ? /* @__PURE__ */ jsxs(Button, { variant: "primary", onClick: handleSubmit, disabled: flaggedLines.length === 0, children: [
|
|
40372
40392
|
/* @__PURE__ */ jsx(Icon, { icon: Send, size: "sm" }),
|
|
40373
40393
|
t("debugger.submit")
|
|
40374
40394
|
] }) : !allCorrect ? /* @__PURE__ */ jsx(Button, { variant: "primary", onClick: handleReset, children: t("debugger.tryAgain") }) : null,
|
|
@@ -44132,6 +44152,9 @@ function getOpponentAction(strategy, actions, history) {
|
|
|
44132
44152
|
function NegotiatorBoard({
|
|
44133
44153
|
entity,
|
|
44134
44154
|
completeEvent = "PUZZLE_COMPLETE",
|
|
44155
|
+
playRoundEvent,
|
|
44156
|
+
finishEvent,
|
|
44157
|
+
playAgainEvent,
|
|
44135
44158
|
className
|
|
44136
44159
|
}) {
|
|
44137
44160
|
const { emit } = useEventBus();
|
|
@@ -44140,13 +44163,14 @@ function NegotiatorBoard({
|
|
|
44140
44163
|
const [history, setHistory] = useState([]);
|
|
44141
44164
|
const [headerError, setHeaderError] = useState(false);
|
|
44142
44165
|
const [showHint, setShowHint] = useState(false);
|
|
44143
|
-
const totalRounds = num(resolved?.
|
|
44166
|
+
const totalRounds = num(resolved?.maxRounds);
|
|
44144
44167
|
const targetScore = num(resolved?.targetScore);
|
|
44145
|
-
const currentRound =
|
|
44146
|
-
const
|
|
44147
|
-
const playerTotal =
|
|
44168
|
+
const currentRound = num(resolved?.round);
|
|
44169
|
+
const result = str(resolved?.result) || "none";
|
|
44170
|
+
const playerTotal = num(resolved?.score);
|
|
44171
|
+
const isComplete = result !== "none" || totalRounds > 0 && currentRound >= totalRounds;
|
|
44172
|
+
const won = result === "win";
|
|
44148
44173
|
const opponentTotal = history.reduce((s, r2) => s + r2.opponentPayoff, 0);
|
|
44149
|
-
const won = isComplete && playerTotal >= targetScore;
|
|
44150
44174
|
const actions = Array.isArray(resolved?.actions) ? resolved.actions : [];
|
|
44151
44175
|
const payoffMatrix = Array.isArray(resolved?.payoffMatrix) ? resolved.payoffMatrix : [];
|
|
44152
44176
|
const handleAction = useCallback((actionId) => {
|
|
@@ -44155,29 +44179,45 @@ function NegotiatorBoard({
|
|
|
44155
44179
|
const payoff = payoffMatrix.find(
|
|
44156
44180
|
(p2) => p2.playerAction === actionId && p2.opponentAction === opponentAction
|
|
44157
44181
|
);
|
|
44158
|
-
const
|
|
44159
|
-
|
|
44160
|
-
|
|
44161
|
-
|
|
44162
|
-
|
|
44163
|
-
|
|
44164
|
-
|
|
44165
|
-
|
|
44166
|
-
|
|
44167
|
-
|
|
44168
|
-
|
|
44169
|
-
|
|
44170
|
-
|
|
44171
|
-
|
|
44172
|
-
|
|
44182
|
+
const playerPayoff = payoff?.playerPayoff ?? 0;
|
|
44183
|
+
setHistory((prev) => [
|
|
44184
|
+
...prev,
|
|
44185
|
+
{
|
|
44186
|
+
round: prev.length + 1,
|
|
44187
|
+
playerAction: actionId,
|
|
44188
|
+
opponentAction,
|
|
44189
|
+
playerPayoff,
|
|
44190
|
+
opponentPayoff: payoff?.opponentPayoff ?? 0
|
|
44191
|
+
}
|
|
44192
|
+
]);
|
|
44193
|
+
if (playRoundEvent) {
|
|
44194
|
+
emit(`UI:${playRoundEvent}`, { playerAction: actionId, payoff: playerPayoff });
|
|
44195
|
+
}
|
|
44196
|
+
if (totalRounds > 0 && currentRound + 1 >= totalRounds) {
|
|
44197
|
+
if (finishEvent) {
|
|
44198
|
+
emit(`UI:${finishEvent}`, {});
|
|
44199
|
+
}
|
|
44200
|
+
if (str(resolved?.hint)) {
|
|
44173
44201
|
setShowHint(true);
|
|
44174
44202
|
}
|
|
44175
44203
|
}
|
|
44176
|
-
}, [isComplete, resolved, totalRounds,
|
|
44177
|
-
const handleReset = () => {
|
|
44204
|
+
}, [isComplete, resolved, totalRounds, currentRound, actions, payoffMatrix, history, playRoundEvent, finishEvent, emit]);
|
|
44205
|
+
const handleReset = useCallback(() => {
|
|
44178
44206
|
setHistory([]);
|
|
44179
44207
|
setShowHint(false);
|
|
44180
|
-
|
|
44208
|
+
if (playAgainEvent) {
|
|
44209
|
+
emit(`UI:${playAgainEvent}`, {});
|
|
44210
|
+
}
|
|
44211
|
+
}, [playAgainEvent, emit]);
|
|
44212
|
+
const completedRef = useRef(false);
|
|
44213
|
+
useEffect(() => {
|
|
44214
|
+
if (result === "win" && !completedRef.current) {
|
|
44215
|
+
completedRef.current = true;
|
|
44216
|
+
emit(`UI:${completeEvent}`, { success: true, score: playerTotal });
|
|
44217
|
+
} else if (result === "none") {
|
|
44218
|
+
completedRef.current = false;
|
|
44219
|
+
}
|
|
44220
|
+
}, [result, playerTotal, completeEvent, emit]);
|
|
44181
44221
|
const getActionLabel = (id) => actions.find((a) => a.id === id)?.label ?? id;
|
|
44182
44222
|
if (!resolved) return null;
|
|
44183
44223
|
const theme = resolved.theme ?? void 0;
|
|
@@ -47143,67 +47183,47 @@ var init_SimulationGraph = __esm({
|
|
|
47143
47183
|
function SimulatorBoard({
|
|
47144
47184
|
entity,
|
|
47145
47185
|
completeEvent = "PUZZLE_COMPLETE",
|
|
47186
|
+
setAEvent,
|
|
47187
|
+
setBEvent,
|
|
47188
|
+
checkEvent,
|
|
47189
|
+
playAgainEvent,
|
|
47146
47190
|
className
|
|
47147
47191
|
}) {
|
|
47148
47192
|
const { emit } = useEventBus();
|
|
47149
47193
|
const { t } = useTranslate();
|
|
47150
47194
|
const resolved = boardEntity(entity);
|
|
47151
47195
|
const parameters = Array.isArray(resolved?.parameters) ? resolved.parameters : [];
|
|
47152
|
-
const [values, setValues] = useState(() => {
|
|
47153
|
-
const init = {};
|
|
47154
|
-
for (const p2 of parameters) {
|
|
47155
|
-
init[p2.id] = p2.initial;
|
|
47156
|
-
}
|
|
47157
|
-
return init;
|
|
47158
|
-
});
|
|
47159
47196
|
const [headerError, setHeaderError] = useState(false);
|
|
47160
|
-
|
|
47161
|
-
const
|
|
47162
|
-
const
|
|
47163
|
-
const
|
|
47164
|
-
|
|
47165
|
-
|
|
47166
|
-
|
|
47167
|
-
|
|
47168
|
-
|
|
47169
|
-
|
|
47170
|
-
|
|
47171
|
-
const
|
|
47172
|
-
const
|
|
47173
|
-
const
|
|
47174
|
-
const
|
|
47175
|
-
|
|
47176
|
-
|
|
47177
|
-
|
|
47197
|
+
if (!resolved) return null;
|
|
47198
|
+
const paramA = num(resolved.paramA);
|
|
47199
|
+
const paramB = num(resolved.paramB);
|
|
47200
|
+
const output = num(resolved.output);
|
|
47201
|
+
const targetValue = num(resolved.target);
|
|
47202
|
+
const targetTolerance = num(resolved.tolerance);
|
|
47203
|
+
const attempts = num(resolved.attempts);
|
|
47204
|
+
const result = str(resolved.result);
|
|
47205
|
+
const isWin = result === "win";
|
|
47206
|
+
const isComplete = result !== "none" && result !== "";
|
|
47207
|
+
const paramAValue = parameters[0];
|
|
47208
|
+
const paramBValue = parameters[1];
|
|
47209
|
+
const sliderValues = [paramA, paramB];
|
|
47210
|
+
const sliderEvents = [setAEvent, setBEvent];
|
|
47211
|
+
const handleParameterChange = (index, value) => {
|
|
47212
|
+
if (isComplete) return;
|
|
47213
|
+
const ev = sliderEvents[index];
|
|
47214
|
+
if (ev) emit(`UI:${ev}`, { value });
|
|
47178
47215
|
};
|
|
47179
|
-
const
|
|
47180
|
-
|
|
47181
|
-
setAttempts((a) => a + 1);
|
|
47182
|
-
if (isCorrect) {
|
|
47183
|
-
emit(`UI:${completeEvent}`, { success: true, attempts: attempts + 1 });
|
|
47184
|
-
}
|
|
47216
|
+
const handleCheck = () => {
|
|
47217
|
+
if (checkEvent) emit(`UI:${checkEvent}`, {});
|
|
47185
47218
|
};
|
|
47186
|
-
const
|
|
47187
|
-
|
|
47188
|
-
if (attempts >= 2 && str(resolved?.hint)) {
|
|
47189
|
-
setShowHint(true);
|
|
47190
|
-
}
|
|
47219
|
+
const handlePlayAgain = () => {
|
|
47220
|
+
if (playAgainEvent) emit(`UI:${playAgainEvent}`, {});
|
|
47191
47221
|
};
|
|
47192
|
-
const handleFullReset = () => {
|
|
47193
|
-
const init = {};
|
|
47194
|
-
for (const p2 of parameters) {
|
|
47195
|
-
init[p2.id] = p2.initial;
|
|
47196
|
-
}
|
|
47197
|
-
setValues(init);
|
|
47198
|
-
setSubmitted(false);
|
|
47199
|
-
setAttempts(0);
|
|
47200
|
-
setShowHint(false);
|
|
47201
|
-
};
|
|
47202
|
-
if (!resolved) return null;
|
|
47203
47222
|
const theme = resolved.theme ?? void 0;
|
|
47204
47223
|
const themeBackground = theme?.background;
|
|
47205
47224
|
const headerImage = str(resolved.headerImage);
|
|
47206
47225
|
const hint = str(resolved.hint);
|
|
47226
|
+
const showHint = isComplete && !isWin && attempts >= 2 && Boolean(hint);
|
|
47207
47227
|
const outputLabel = str(resolved.outputLabel);
|
|
47208
47228
|
const outputUnit = str(resolved.outputUnit);
|
|
47209
47229
|
return /* @__PURE__ */ jsx(
|
|
@@ -47223,41 +47243,43 @@ function SimulatorBoard({
|
|
|
47223
47243
|
] }) }),
|
|
47224
47244
|
/* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "md", children: [
|
|
47225
47245
|
/* @__PURE__ */ jsx(Typography, { variant: "small", weight: "bold", className: "uppercase tracking-wider text-muted-foreground", children: t("simulator.parameters") }),
|
|
47226
|
-
|
|
47227
|
-
/* @__PURE__ */ jsxs(
|
|
47228
|
-
/* @__PURE__ */
|
|
47229
|
-
|
|
47230
|
-
|
|
47231
|
-
|
|
47232
|
-
|
|
47233
|
-
|
|
47234
|
-
|
|
47235
|
-
/* @__PURE__ */ jsx(
|
|
47236
|
-
"input",
|
|
47237
|
-
{
|
|
47238
|
-
type: "range",
|
|
47239
|
-
min: param.min,
|
|
47240
|
-
max: param.max,
|
|
47241
|
-
step: param.step,
|
|
47242
|
-
value: values[param.id],
|
|
47243
|
-
onChange: (e) => handleParameterChange(param.id, Number(e.target.value)),
|
|
47244
|
-
disabled: submitted,
|
|
47245
|
-
className: "w-full accent-foreground"
|
|
47246
|
-
}
|
|
47247
|
-
),
|
|
47248
|
-
/* @__PURE__ */ jsxs(HStack, { justify: "between", children: [
|
|
47249
|
-
/* @__PURE__ */ jsxs(Typography, { variant: "caption", className: "text-muted-foreground", children: [
|
|
47250
|
-
param.min,
|
|
47251
|
-
" ",
|
|
47252
|
-
param.unit
|
|
47246
|
+
[paramAValue, paramBValue].map(
|
|
47247
|
+
(param, index) => param ? /* @__PURE__ */ jsxs(VStack, { gap: "xs", children: [
|
|
47248
|
+
/* @__PURE__ */ jsxs(HStack, { justify: "between", align: "center", children: [
|
|
47249
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body", weight: "medium", children: param.label }),
|
|
47250
|
+
/* @__PURE__ */ jsxs(Badge, { size: "sm", children: [
|
|
47251
|
+
sliderValues[index],
|
|
47252
|
+
" ",
|
|
47253
|
+
param.unit
|
|
47254
|
+
] })
|
|
47253
47255
|
] }),
|
|
47254
|
-
/* @__PURE__ */
|
|
47255
|
-
|
|
47256
|
-
|
|
47257
|
-
|
|
47256
|
+
/* @__PURE__ */ jsx(
|
|
47257
|
+
"input",
|
|
47258
|
+
{
|
|
47259
|
+
type: "range",
|
|
47260
|
+
min: param.min,
|
|
47261
|
+
max: param.max,
|
|
47262
|
+
step: param.step,
|
|
47263
|
+
value: sliderValues[index],
|
|
47264
|
+
onChange: (e) => handleParameterChange(index, Number(e.target.value)),
|
|
47265
|
+
disabled: isComplete,
|
|
47266
|
+
className: "w-full accent-foreground"
|
|
47267
|
+
}
|
|
47268
|
+
),
|
|
47269
|
+
/* @__PURE__ */ jsxs(HStack, { justify: "between", children: [
|
|
47270
|
+
/* @__PURE__ */ jsxs(Typography, { variant: "caption", className: "text-muted-foreground", children: [
|
|
47271
|
+
param.min,
|
|
47272
|
+
" ",
|
|
47273
|
+
param.unit
|
|
47274
|
+
] }),
|
|
47275
|
+
/* @__PURE__ */ jsxs(Typography, { variant: "caption", className: "text-muted-foreground", children: [
|
|
47276
|
+
param.max,
|
|
47277
|
+
" ",
|
|
47278
|
+
param.unit
|
|
47279
|
+
] })
|
|
47258
47280
|
] })
|
|
47259
|
-
] })
|
|
47260
|
-
|
|
47281
|
+
] }, param.id ?? index) : null
|
|
47282
|
+
)
|
|
47261
47283
|
] }) }),
|
|
47262
47284
|
/* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", align: "center", children: [
|
|
47263
47285
|
/* @__PURE__ */ jsx(Typography, { variant: "small", weight: "bold", className: "uppercase tracking-wider text-muted-foreground", children: outputLabel }),
|
|
@@ -47266,9 +47288,9 @@ function SimulatorBoard({
|
|
|
47266
47288
|
" ",
|
|
47267
47289
|
outputUnit
|
|
47268
47290
|
] }),
|
|
47269
|
-
|
|
47270
|
-
/* @__PURE__ */ jsx(Icon, { icon:
|
|
47271
|
-
/* @__PURE__ */ jsx(Typography, { variant: "body", className:
|
|
47291
|
+
isComplete && /* @__PURE__ */ jsxs(HStack, { gap: "xs", align: "center", children: [
|
|
47292
|
+
/* @__PURE__ */ jsx(Icon, { icon: isWin ? CheckCircle : XCircle, size: "sm", className: isWin ? "text-success" : "text-error" }),
|
|
47293
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body", className: isWin ? "text-success" : "text-error", children: isWin ? str(resolved.successMessage) || t("simulator.correct") : str(resolved.failMessage) || t("simulator.incorrect") })
|
|
47272
47294
|
] }),
|
|
47273
47295
|
/* @__PURE__ */ jsxs(Typography, { variant: "caption", className: "text-muted-foreground", children: [
|
|
47274
47296
|
t("simulator.target"),
|
|
@@ -47283,11 +47305,11 @@ function SimulatorBoard({
|
|
|
47283
47305
|
] }) }),
|
|
47284
47306
|
showHint && hint && /* @__PURE__ */ jsx(Card, { className: "p-4 border-l-4 border-l-warning", children: /* @__PURE__ */ jsx(Typography, { variant: "body", children: hint }) }),
|
|
47285
47307
|
/* @__PURE__ */ jsxs(HStack, { gap: "sm", justify: "center", children: [
|
|
47286
|
-
!
|
|
47308
|
+
!isComplete ? /* @__PURE__ */ jsxs(Button, { variant: "primary", onClick: handleCheck, children: [
|
|
47287
47309
|
/* @__PURE__ */ jsx(Icon, { icon: Play, size: "sm" }),
|
|
47288
47310
|
t("simulator.simulate")
|
|
47289
|
-
] }) :
|
|
47290
|
-
/* @__PURE__ */ jsxs(Button, { variant: "secondary", onClick:
|
|
47311
|
+
] }) : null,
|
|
47312
|
+
/* @__PURE__ */ jsxs(Button, { variant: "secondary", onClick: handlePlayAgain, children: [
|
|
47291
47313
|
/* @__PURE__ */ jsx(Icon, { icon: RotateCcw, size: "sm" }),
|
|
47292
47314
|
t("simulator.reset")
|
|
47293
47315
|
] })
|