jaml-ui 0.21.3 → 0.21.5
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/DESIGN.md +36 -6
- package/dist/assets.d.ts +0 -2
- package/dist/assets.js +7 -29
- package/dist/components/JamlAnalyzerFullscreen.d.ts +1 -1
- package/dist/components/JamlAnalyzerFullscreen.js +5 -81
- package/dist/components/JamlCurator.js +1 -1
- package/dist/components/JamlSpeedometer.d.ts +7 -2
- package/dist/components/JamlSpeedometer.js +8 -15
- package/dist/components/jamlMap/JamlMapEditor.js +42 -38
- package/dist/components/jamlMap/JokerPicker.js +2 -2
- package/dist/components/jamlMap/MysterySlot.js +4 -4
- package/dist/core.d.ts +1 -1
- package/dist/core.js +1 -1
- package/dist/hooks/useSearch.d.ts +2 -1
- package/dist/hooks/useSearch.js +111 -8
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/lib/SpriteMapper.d.ts +10 -0
- package/dist/lib/SpriteMapper.js +48 -0
- package/dist/lib/cardParser.d.ts +8 -0
- package/dist/lib/cardParser.js +65 -0
- package/dist/lib/classes/BuyMetaData.d.ts +11 -0
- package/dist/lib/classes/BuyMetaData.js +1 -0
- package/dist/lib/config.d.ts +13 -0
- package/dist/lib/config.js +15 -0
- package/dist/lib/const.d.ts +61 -0
- package/dist/lib/const.js +521 -0
- package/dist/lib/data/constants.d.ts +11 -0
- package/dist/lib/data/constants.js +17 -0
- package/dist/lib/hooks/useDragScroll.d.ts +4 -0
- package/dist/lib/hooks/useDragScroll.js +48 -0
- package/dist/lib/hooks/useJamlFilter.d.ts +48 -0
- package/dist/lib/hooks/useJamlFilter.js +219 -0
- package/dist/lib/hooks/useSeedAnalyzer.d.ts +6 -0
- package/dist/lib/hooks/useSeedAnalyzer.js +48 -0
- package/dist/lib/jaml/jamlCompletion.d.ts +12 -0
- package/dist/lib/jaml/jamlCompletion.js +13 -0
- package/dist/lib/jaml/jamlData.d.ts +3 -0
- package/dist/lib/jaml/jamlData.js +8 -0
- package/dist/lib/jaml/jamlObjectives.d.ts +13 -0
- package/dist/lib/jaml/jamlObjectives.js +97 -0
- package/dist/lib/jaml/jamlParser.d.ts +14 -0
- package/dist/lib/jaml/jamlParser.js +47 -0
- package/dist/lib/jaml/jamlPresets.d.ts +8 -0
- package/dist/lib/jaml/jamlPresets.js +61 -0
- package/dist/lib/jaml/jamlSchema.d.ts +54 -0
- package/dist/lib/jaml/jamlSchema.js +91 -0
- package/dist/lib/parseDailyRitual.d.ts +45 -0
- package/dist/lib/parseDailyRitual.js +69 -0
- package/dist/lib/tts/getRevealPos.d.ts +5 -0
- package/dist/lib/tts/getRevealPos.js +16 -0
- package/dist/lib/tts/splitTtsDisplay.d.ts +19 -0
- package/dist/lib/tts/splitTtsDisplay.js +35 -0
- package/dist/lib/types.d.ts +121 -0
- package/dist/lib/types.js +1 -0
- package/dist/lib/utils.d.ts +2 -0
- package/dist/lib/utils.js +5 -0
- package/dist/motelyDisplay.js +10 -17
- package/dist/ui/JimboIconButton.d.ts +10 -0
- package/dist/ui/JimboIconButton.js +28 -0
- package/dist/ui/JimboInputModal.d.ts +13 -0
- package/dist/ui/JimboInputModal.js +60 -0
- package/dist/ui/JimboSelect.d.ts +18 -0
- package/dist/ui/JimboSelect.js +43 -0
- package/dist/ui/PanelSplitter.d.ts +7 -0
- package/dist/ui/PanelSplitter.js +76 -0
- package/dist/ui/ide/AgnosticSeedCard.d.ts +19 -0
- package/dist/ui/ide/AgnosticSeedCard.js +48 -0
- package/dist/ui/ide/DeckSprite.d.ts +1 -0
- package/dist/ui/ide/DeckSprite.js +2 -0
- package/dist/ui/ide/JamlBuilder.d.ts +1 -0
- package/dist/ui/ide/JamlBuilder.js +112 -0
- package/dist/ui/ide/JamlEditor.d.ts +7 -0
- package/dist/ui/ide/JamlEditor.js +496 -0
- package/dist/ui/ide/JamlEditorMonaco.d.ts +8 -0
- package/dist/ui/ide/JamlEditorMonaco.js +78 -0
- package/dist/ui/ide/WasmStatus.d.ts +1 -0
- package/dist/ui/ide/WasmStatus.js +42 -0
- package/dist/ui/jimbo.css +338 -32
- package/dist/ui/jimboApp.d.ts +12 -0
- package/dist/ui/jimboApp.js +15 -0
- package/dist/ui/jimboInfoCard.d.ts +31 -0
- package/dist/ui/jimboInfoCard.js +26 -0
- package/dist/ui/jimboInset.d.ts +9 -0
- package/dist/ui/jimboInset.js +9 -0
- package/dist/ui/jimboSectionHeader.d.ts +11 -0
- package/dist/ui/jimboSectionHeader.js +9 -0
- package/dist/ui/jimboStatGrid.d.ts +13 -0
- package/dist/ui/jimboStatGrid.js +9 -0
- package/dist/ui/jimboTabs.d.ts +1 -1
- package/dist/ui/jimboWordmark.d.ts +10 -0
- package/dist/ui/jimboWordmark.js +9 -0
- package/dist/ui/mascot/JammySpeechBox.d.ts +9 -0
- package/dist/ui/mascot/JammySpeechBox.js +30 -0
- package/dist/ui/mascot/SeedMascot.d.ts +37 -0
- package/dist/ui/mascot/SeedMascot.js +17 -0
- package/dist/ui/mascot/index.d.ts +3 -0
- package/dist/ui/mascot/index.js +3 -0
- package/dist/ui/mascot/menuConfig.d.ts +102 -0
- package/dist/ui/mascot/menuConfig.js +12 -0
- package/dist/ui/panel.d.ts +1 -1
- package/dist/ui/panel.js +3 -25
- package/dist/ui/radial/RadialBadge.d.ts +17 -0
- package/dist/ui/radial/RadialBadge.js +43 -0
- package/dist/ui/radial/RadialBreadcrumb.d.ts +12 -0
- package/dist/ui/radial/RadialBreadcrumb.js +18 -0
- package/dist/ui/radial/RadialButton.d.ts +61 -0
- package/dist/ui/radial/RadialButton.js +102 -0
- package/dist/ui/radial/RadialMenu.d.ts +38 -0
- package/dist/ui/radial/RadialMenu.js +168 -0
- package/dist/ui/radial/RadialPill.d.ts +18 -0
- package/dist/ui/radial/RadialPill.js +15 -0
- package/dist/ui/radial/index.d.ts +16 -0
- package/dist/ui/radial/index.js +18 -0
- package/dist/ui/radial/radialMenuStore.d.ts +31 -0
- package/dist/ui/radial/radialMenuStore.js +122 -0
- package/dist/ui/radial/radialMenuViewport.d.ts +6 -0
- package/dist/ui/radial/radialMenuViewport.js +59 -0
- package/dist/ui/radial/useRadialMenu.d.ts +35 -0
- package/dist/ui/radial/useRadialMenu.js +107 -0
- package/dist/ui/showcase.d.ts +14 -6
- package/dist/ui/showcase.js +13 -21
- package/dist/ui/tokens.d.ts +5 -19
- package/dist/ui/tokens.js +5 -21
- package/dist/ui.d.ts +14 -0
- package/dist/ui.js +15 -0
- package/package.json +145 -146
package/dist/hooks/useSearch.js
CHANGED
|
@@ -1,9 +1,5 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { useState, useCallback, useRef, useEffect } from "react";
|
|
3
|
-
import SearchWorker from "./searchWorker.js?worker&inline";
|
|
4
|
-
function createWorker() {
|
|
5
|
-
return new SearchWorker();
|
|
6
|
-
}
|
|
7
3
|
const INITIAL_STATE = {
|
|
8
4
|
results: [],
|
|
9
5
|
totalSearched: 0n,
|
|
@@ -13,15 +9,107 @@ const INITIAL_STATE = {
|
|
|
13
9
|
seedsPerSecond: 0,
|
|
14
10
|
tallyLabels: [],
|
|
15
11
|
};
|
|
16
|
-
|
|
12
|
+
const SEARCH_WORKER_CODE = `
|
|
13
|
+
let MotelyWasm = null;
|
|
14
|
+
let MotelyWasmEvents = null;
|
|
15
|
+
let activeSearch = null;
|
|
16
|
+
|
|
17
|
+
self.addEventListener('message', async function(e) {
|
|
18
|
+
const msg = e.data;
|
|
19
|
+
|
|
20
|
+
if (msg.type === 'init') {
|
|
21
|
+
try {
|
|
22
|
+
const mod = await import(msg.url);
|
|
23
|
+
await mod.default.boot();
|
|
24
|
+
MotelyWasm = mod.MotelyWasm;
|
|
25
|
+
MotelyWasmEvents = mod.MotelyWasmEvents;
|
|
26
|
+
self.postMessage({ type: 'ready' });
|
|
27
|
+
} catch (err) {
|
|
28
|
+
self.postMessage({ type: 'error', message: String(err) });
|
|
29
|
+
}
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
if (msg.type === 'start') {
|
|
34
|
+
if (!MotelyWasm) { self.postMessage({ type: 'error', message: 'Not initialized' }); return; }
|
|
35
|
+
const validation = MotelyWasm.validateJaml(msg.jaml);
|
|
36
|
+
if (validation !== 'valid') { self.postMessage({ type: 'error', message: validation }); return; }
|
|
37
|
+
|
|
38
|
+
function cleanup() {
|
|
39
|
+
MotelyWasmEvents.notifyResult = () => {};
|
|
40
|
+
MotelyWasmEvents.notifyProgress = () => {};
|
|
41
|
+
MotelyWasmEvents.notifyComplete = () => {};
|
|
42
|
+
activeSearch = null;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
MotelyWasmEvents.notifyResult = function(seed, score, tallyColumns) {
|
|
46
|
+
self.postMessage({ type: 'result', seed, score, tallyColumns: Array.from(tallyColumns) });
|
|
47
|
+
};
|
|
48
|
+
MotelyWasmEvents.notifyProgress = function(searched, matching) {
|
|
49
|
+
self.postMessage({ type: 'progress', searched: searched.toString(), matching: matching.toString() });
|
|
50
|
+
};
|
|
51
|
+
MotelyWasmEvents.notifyComplete = function(status, searched, matched) {
|
|
52
|
+
cleanup();
|
|
53
|
+
self.postMessage({ type: 'complete', status, searched: searched.toString(), matched: matched.toString() });
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
try {
|
|
57
|
+
const mode = msg.mode || 'random';
|
|
58
|
+
|
|
59
|
+
if (mode === 'random') {
|
|
60
|
+
activeSearch = MotelyWasm.startRandomSearch(msg.jaml, msg.count);
|
|
61
|
+
} else if (mode === 'aesthetic') {
|
|
62
|
+
activeSearch = MotelyWasm.startAestheticSearch(msg.jaml, msg.aesthetic);
|
|
63
|
+
} else if (mode === 'seedList') {
|
|
64
|
+
activeSearch = MotelyWasm.startSeedListSearch(msg.jaml, msg.seeds);
|
|
65
|
+
} else if (mode === 'keyword') {
|
|
66
|
+
activeSearch = MotelyWasm.startKeywordSearch(msg.jaml, msg.keywords, msg.padding || '');
|
|
67
|
+
} else if (mode === 'sequential') {
|
|
68
|
+
activeSearch = MotelyWasm.startSequentialSearch(msg.jaml, msg.batchCharCount, BigInt(msg.startBatch), BigInt(msg.endBatch));
|
|
69
|
+
} else {
|
|
70
|
+
self.postMessage({ type: 'error', message: 'Unknown search mode: ' + mode });
|
|
71
|
+
cleanup();
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
} catch (err) {
|
|
75
|
+
cleanup();
|
|
76
|
+
self.postMessage({ type: 'error', message: String(err) });
|
|
77
|
+
}
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
if (msg.type === 'stop') {
|
|
82
|
+
if (activeSearch) { activeSearch.cancel(); activeSearch = null; }
|
|
83
|
+
self.postMessage({ type: 'cancelled' });
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
if (msg.type === 'get_tally_labels') {
|
|
87
|
+
if (!MotelyWasm) { self.postMessage({ type: 'error', message: 'Not initialized' }); return; }
|
|
88
|
+
try {
|
|
89
|
+
const labels = MotelyWasm.getTallyLabels(msg.jaml);
|
|
90
|
+
self.postMessage({ type: 'tally_labels', labels: Array.from(labels) });
|
|
91
|
+
} catch (err) {
|
|
92
|
+
self.postMessage({ type: 'error', message: String(err) });
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
});
|
|
96
|
+
`;
|
|
97
|
+
function createWorker() {
|
|
98
|
+
const blob = new Blob([SEARCH_WORKER_CODE], { type: "application/javascript" });
|
|
99
|
+
return new Worker(URL.createObjectURL(blob), { type: "module" });
|
|
100
|
+
}
|
|
101
|
+
export function useSearch(motelyWasmUrl) {
|
|
17
102
|
const [state, setState] = useState(INITIAL_STATE);
|
|
18
103
|
const workerRef = useRef(null);
|
|
19
|
-
const readyRef = useRef(
|
|
104
|
+
const readyRef = useRef(false); // Worker is NOT implicitly ready, must wait for 'ready' message
|
|
20
105
|
const speedRef = useRef({ lastSearched: 0n, lastTime: 0, ema: 0 });
|
|
21
106
|
useEffect(() => {
|
|
22
107
|
setState((s) => ({ ...s, status: "idle" }));
|
|
23
108
|
const worker = createWorker();
|
|
24
109
|
workerRef.current = worker;
|
|
110
|
+
if (motelyWasmUrl) {
|
|
111
|
+
worker.postMessage({ type: 'init', url: motelyWasmUrl });
|
|
112
|
+
}
|
|
25
113
|
worker.onmessage = (e) => {
|
|
26
114
|
const msg = e.data;
|
|
27
115
|
if (msg.type === "ready") {
|
|
@@ -83,7 +171,7 @@ export function useSearch() {
|
|
|
83
171
|
worker.terminate();
|
|
84
172
|
workerRef.current = null;
|
|
85
173
|
};
|
|
86
|
-
}, []);
|
|
174
|
+
}, [motelyWasmUrl]);
|
|
87
175
|
const sendStart = useCallback((payload) => {
|
|
88
176
|
const worker = workerRef.current;
|
|
89
177
|
if (!worker)
|
|
@@ -117,6 +205,21 @@ export function useSearch() {
|
|
|
117
205
|
const startKeyword = useCallback((jaml, keywords, padding) => {
|
|
118
206
|
sendStart({ type: "start", mode: "keyword", jaml, keywords, padding });
|
|
119
207
|
}, [sendStart]);
|
|
208
|
+
const startSequential = useCallback((jaml, startSeed, endSeed) => {
|
|
209
|
+
// Sequential search: single-threaded, deterministic order.
|
|
210
|
+
// batchCharCount = length of start seed, startBatch/endBatch = numeric range.
|
|
211
|
+
const charCount = startSeed.length || 1;
|
|
212
|
+
const startNum = parseInt(startSeed, 36) || 0;
|
|
213
|
+
const endNum = endSeed ? parseInt(endSeed, 36) : startNum + 10_000_000;
|
|
214
|
+
sendStart({
|
|
215
|
+
type: "start",
|
|
216
|
+
mode: "sequential",
|
|
217
|
+
jaml,
|
|
218
|
+
batchCharCount: charCount,
|
|
219
|
+
startBatch: startNum.toString(),
|
|
220
|
+
endBatch: endNum.toString(),
|
|
221
|
+
});
|
|
222
|
+
}, [sendStart]);
|
|
120
223
|
const cancel = useCallback(() => {
|
|
121
224
|
workerRef.current?.postMessage({ type: "stop" });
|
|
122
225
|
}, []);
|
|
@@ -126,5 +229,5 @@ export function useSearch() {
|
|
|
126
229
|
const fetchTallyLabels = useCallback((jaml) => {
|
|
127
230
|
workerRef.current?.postMessage({ type: "get_tally_labels", jaml });
|
|
128
231
|
}, []);
|
|
129
|
-
return { ...state, start, startAesthetic, startSeedList, startKeyword, cancel, clearError, fetchTallyLabels };
|
|
232
|
+
return { ...state, start, startAesthetic, startSeedList, startKeyword, startSequential, cancel, clearError, fetchTallyLabels };
|
|
130
233
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { JAML_ASSET_FILES,
|
|
1
|
+
export { JAML_ASSET_FILES, resolveJamlAssetUrl, setJamlAssetBaseUrl, type JamlAssetFile, type JamlAssetKey, } from "./assets.js";
|
|
2
2
|
export { Layer, type LayerOptions } from "./render/Layer.js";
|
|
3
3
|
export { JamlCardRenderer, type JamlCardRendererProps } from "./render/CanvasRenderer.js";
|
|
4
4
|
export { JamlGameCard, JamlVoucher, JamlTag, JamlBoss, resolveAnalyzerShopItem, type JamlGameCardProps, type AnalyzerShopItem, type AnalyzerResolvedItem, } from "./components/GameCard.js";
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
export { JAML_ASSET_FILES,
|
|
2
|
+
export { JAML_ASSET_FILES, resolveJamlAssetUrl, setJamlAssetBaseUrl, } from "./assets.js";
|
|
3
3
|
export { Layer } from "./render/Layer.js";
|
|
4
4
|
export { JamlCardRenderer } from "./render/CanvasRenderer.js";
|
|
5
5
|
export { JamlGameCard, JamlVoucher, JamlTag, JamlBoss, resolveAnalyzerShopItem, } from "./components/GameCard.js";
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
interface SpritePos {
|
|
2
|
+
x: number;
|
|
3
|
+
y: number;
|
|
4
|
+
}
|
|
5
|
+
export interface SpriteData {
|
|
6
|
+
pos: SpritePos;
|
|
7
|
+
type: 'Jokers' | 'Tarots' | 'Vouchers' | 'Boosters' | 'Enhancers' | 'Editions' | 'BlindChips' | 'Shop' | 'tags';
|
|
8
|
+
}
|
|
9
|
+
export declare function getSpriteData(name: string): SpriteData;
|
|
10
|
+
export {};
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { jokers, tarotsAndPlanets, vouchers, boosterPacks, jokerFaces, consumablesFaces, bosses, tags } from './const';
|
|
2
|
+
// Consolidate all item arrays into a single map for O(1) lookup
|
|
3
|
+
const ITEM_MAP = new Map();
|
|
4
|
+
function addToMap(items, type) {
|
|
5
|
+
items.forEach(item => {
|
|
6
|
+
if (item.name && item.pos) {
|
|
7
|
+
const data = { pos: item.pos, type };
|
|
8
|
+
ITEM_MAP.set(item.name, data);
|
|
9
|
+
ITEM_MAP.set(item.name.toLowerCase(), data);
|
|
10
|
+
ITEM_MAP.set(item.name.replace(/ /g, ''), data);
|
|
11
|
+
ITEM_MAP.set(item.name.replace(/ /g, '').toLowerCase(), data);
|
|
12
|
+
}
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
// Populate the map with explicit types
|
|
16
|
+
addToMap(jokers, 'Jokers');
|
|
17
|
+
addToMap(tarotsAndPlanets, 'Tarots');
|
|
18
|
+
addToMap(vouchers, 'Vouchers');
|
|
19
|
+
addToMap(boosterPacks, 'Boosters');
|
|
20
|
+
addToMap(bosses, 'BlindChips');
|
|
21
|
+
addToMap(tags, 'tags');
|
|
22
|
+
// Explicit overrides/faces
|
|
23
|
+
addToMap(jokerFaces, 'Jokers');
|
|
24
|
+
addToMap(consumablesFaces, 'Tarots');
|
|
25
|
+
export function getSpriteData(name) {
|
|
26
|
+
// 1. Try stripping common prefixes used by some analyzers (e.g., "Planet | Venus")
|
|
27
|
+
const cleanedName = name.replace(/^(Joker|Tarot|Planet|Voucher|Pack|Edition|Tag) [|:] /i, "").trim();
|
|
28
|
+
// 2. Precise lookup
|
|
29
|
+
if (ITEM_MAP.has(cleanedName))
|
|
30
|
+
return ITEM_MAP.get(cleanedName);
|
|
31
|
+
if (ITEM_MAP.has(name))
|
|
32
|
+
return ITEM_MAP.get(name);
|
|
33
|
+
// 3. Normalized lookups
|
|
34
|
+
const variants = [
|
|
35
|
+
cleanedName.toLowerCase(),
|
|
36
|
+
cleanedName.replace(/ /g, ''),
|
|
37
|
+
cleanedName.replace(/ /g, '').toLowerCase(),
|
|
38
|
+
name.toLowerCase(),
|
|
39
|
+
name.replace(/ /g, ''),
|
|
40
|
+
name.replace(/ /g, '').toLowerCase()
|
|
41
|
+
];
|
|
42
|
+
for (const v of variants) {
|
|
43
|
+
if (ITEM_MAP.has(v))
|
|
44
|
+
return ITEM_MAP.get(v);
|
|
45
|
+
}
|
|
46
|
+
// Default Fallback
|
|
47
|
+
return { pos: { x: 0, y: 0 }, type: 'Jokers' };
|
|
48
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
const ENHANCEMENTS = ["Bonus", "Mult", "Wild", "Lucky", "Glass", "Steel", "Stone", "Gold"];
|
|
2
|
+
const SEALS = ["Gold", "Purple", "Red", "Blue"];
|
|
3
|
+
const EDITIONS = ["Foil", "Holographic", "Polychrome", "Negative"];
|
|
4
|
+
const RANKS = ["2", "3", "4", "5", "6", "7", "8", "9", "10", "Jack", "Queen", "King", "Ace"];
|
|
5
|
+
const SUITS = ["Hearts", "Clubs", "Diamonds", "Spades"];
|
|
6
|
+
// Internal Balatro short codes
|
|
7
|
+
const RANK_MAP = {
|
|
8
|
+
"2": "2", "3": "3", "4": "4", "5": "5", "6": "6", "7": "7", "8": "8", "9": "9", "10": "10",
|
|
9
|
+
"T": "10", "J": "Jack", "Q": "Queen", "K": "King", "A": "Ace"
|
|
10
|
+
};
|
|
11
|
+
const SUIT_MAP = {
|
|
12
|
+
"H": "Hearts", "C": "Clubs", "D": "Diamonds", "S": "Spades"
|
|
13
|
+
};
|
|
14
|
+
export function parseCardToken(item) {
|
|
15
|
+
if (!item)
|
|
16
|
+
return null;
|
|
17
|
+
// 1. If it's already an object with rank/suit
|
|
18
|
+
if (typeof item === 'object' && (item.rank || item.base)) {
|
|
19
|
+
let rank = item.rank || item.base?.[2] || item.base?.[0]; // Handle different analyzer versions
|
|
20
|
+
let suit = item.suit || item.base?.[0];
|
|
21
|
+
// Normalize
|
|
22
|
+
rank = RANK_MAP[rank] || rank;
|
|
23
|
+
suit = SUIT_MAP[suit] || suit;
|
|
24
|
+
if (suit && !suit.endsWith('s'))
|
|
25
|
+
suit += 's';
|
|
26
|
+
return {
|
|
27
|
+
rank: rank || "Ace",
|
|
28
|
+
suit: suit || "Spades",
|
|
29
|
+
enhancement: item.enhancement || item.modifier || null,
|
|
30
|
+
seal: item.seal || null,
|
|
31
|
+
edition: item.edition || null
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
// 2. If it's a string token
|
|
35
|
+
if (typeof item === 'string') {
|
|
36
|
+
const str = item.trim();
|
|
37
|
+
// Handle rank_suit format e.g. "2_C"
|
|
38
|
+
if (str.includes('_')) {
|
|
39
|
+
const [r, s] = str.split('_');
|
|
40
|
+
const rank = RANK_MAP[r.toUpperCase()] || r;
|
|
41
|
+
const suit = SUIT_MAP[s.toUpperCase()] || s;
|
|
42
|
+
return { rank, suit, enhancement: null, seal: null, edition: null };
|
|
43
|
+
}
|
|
44
|
+
// Handle "Rank of Suit" format
|
|
45
|
+
const parts = str.toLowerCase().split(' ');
|
|
46
|
+
const ofIndex = parts.indexOf('of');
|
|
47
|
+
if (ofIndex > 0 && ofIndex < parts.length - 1) {
|
|
48
|
+
let rank = parts[ofIndex - 1];
|
|
49
|
+
let suit = parts[ofIndex + 1];
|
|
50
|
+
// Normalize
|
|
51
|
+
rank = rank.charAt(0).toUpperCase() + rank.slice(1);
|
|
52
|
+
suit = suit.charAt(0).toUpperCase() + suit.slice(1);
|
|
53
|
+
if (!suit.endsWith('s'))
|
|
54
|
+
suit += 's';
|
|
55
|
+
return {
|
|
56
|
+
rank: RANK_MAP[rank.toUpperCase()] || rank,
|
|
57
|
+
suit: SUIT_MAP[suit.toUpperCase()] || suit,
|
|
58
|
+
enhancement: parts.find(p => ENHANCEMENTS.some(e => e.toLowerCase() === p)) || null,
|
|
59
|
+
seal: parts.find(p => SEALS.some(s => s.toLowerCase() === p)) || null,
|
|
60
|
+
edition: parts.find(p => EDITIONS.some(e => e.toLowerCase() === p)) || null
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
return null;
|
|
65
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export declare const ritualConfig: {
|
|
2
|
+
title: string;
|
|
3
|
+
tagline: string;
|
|
4
|
+
id: string;
|
|
5
|
+
defaultObjective: string;
|
|
6
|
+
/**
|
|
7
|
+
* The Weepoch (Jan 30, 2026)
|
|
8
|
+
* This is the canonical start date for Day 1.
|
|
9
|
+
*/
|
|
10
|
+
epochDate: string;
|
|
11
|
+
readonly epoch: number;
|
|
12
|
+
};
|
|
13
|
+
export declare const EPOCH: number;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export const ritualConfig = {
|
|
2
|
+
title: "The Daily Wee",
|
|
3
|
+
tagline: "A curated daily Balatro ritual",
|
|
4
|
+
id: "TheDailyWee",
|
|
5
|
+
defaultObjective: "Wee Joker",
|
|
6
|
+
/**
|
|
7
|
+
* The Weepoch (Jan 30, 2026)
|
|
8
|
+
* This is the canonical start date for Day 1.
|
|
9
|
+
*/
|
|
10
|
+
epochDate: "2026-02-02T00:00:00Z",
|
|
11
|
+
get epoch() {
|
|
12
|
+
return new Date(this.epochDate).getTime();
|
|
13
|
+
}
|
|
14
|
+
};
|
|
15
|
+
export const EPOCH = ritualConfig.epoch;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import type { ReactNode } from "react";
|
|
2
|
+
import type { BuyMetaData } from "./classes/BuyMetaData.ts";
|
|
3
|
+
export declare const jokers: any;
|
|
4
|
+
export declare const jokerFaces: any;
|
|
5
|
+
export declare const consumablesFaces: any;
|
|
6
|
+
export declare const boosterPacks: any;
|
|
7
|
+
export declare const tarotsAndPlanets: any;
|
|
8
|
+
export declare const tags: any;
|
|
9
|
+
export declare const vouchers: any;
|
|
10
|
+
export declare const bosses: any;
|
|
11
|
+
export declare const editionMap: any;
|
|
12
|
+
export declare const stickerMap: any;
|
|
13
|
+
export declare const options: any;
|
|
14
|
+
export declare const blinds: any;
|
|
15
|
+
export declare const blindsCamelCase: string[];
|
|
16
|
+
export declare const SeedsWithLegendary: Array<string>;
|
|
17
|
+
export declare const popularSeeds: Array<string>;
|
|
18
|
+
export interface AnalyzeOptions {
|
|
19
|
+
showCardSpoilers: boolean;
|
|
20
|
+
buys: {
|
|
21
|
+
[key: string]: BuyMetaData;
|
|
22
|
+
};
|
|
23
|
+
sells: {
|
|
24
|
+
[key: string]: BuyMetaData;
|
|
25
|
+
};
|
|
26
|
+
updates: Array<{
|
|
27
|
+
[key: string]: any;
|
|
28
|
+
}>;
|
|
29
|
+
unlocks: Array<string>;
|
|
30
|
+
events: Array<Event>;
|
|
31
|
+
}
|
|
32
|
+
export interface BuyWrapperProps {
|
|
33
|
+
children: ReactNode;
|
|
34
|
+
bottomOffset?: number;
|
|
35
|
+
topOffset?: number;
|
|
36
|
+
metaData?: BuyMetaData;
|
|
37
|
+
horizontal?: boolean;
|
|
38
|
+
}
|
|
39
|
+
export declare enum LOCATIONS {
|
|
40
|
+
SHOP = "SHOP",
|
|
41
|
+
PACK = "PACK",
|
|
42
|
+
MISC = "MISC",
|
|
43
|
+
VOUCHER = "VOUCHER"
|
|
44
|
+
}
|
|
45
|
+
export declare enum LOCATION_TYPES {
|
|
46
|
+
SHOP = "SHOP",
|
|
47
|
+
PACK = "PACK",
|
|
48
|
+
CARD = "CARD"
|
|
49
|
+
}
|
|
50
|
+
export interface CardEvent {
|
|
51
|
+
name: string;
|
|
52
|
+
ante: number;
|
|
53
|
+
blind: string;
|
|
54
|
+
}
|
|
55
|
+
export declare const EVENT_UNLOCKS: {
|
|
56
|
+
name: string;
|
|
57
|
+
condition: string;
|
|
58
|
+
}[];
|
|
59
|
+
export declare const tagDescriptions: {
|
|
60
|
+
[key: string]: string;
|
|
61
|
+
};
|