jaml-ui 0.24.20 → 0.25.2
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/README.md +0 -13
- package/assets/WeeJokerExampleDAilyGame.png +0 -0
- package/assets/balatro-stake-chips.png +0 -0
- package/dist/assets.d.ts +1 -2
- package/dist/chunks/Layer-BBPJFHfs.js +17 -0
- package/dist/chunks/Layer-BBPJFHfs.js.map +1 -0
- package/dist/chunks/assets-RWUiFSTc.js +37 -0
- package/dist/chunks/assets-RWUiFSTc.js.map +1 -0
- package/dist/chunks/motelyItemDecoder-CueyZ0XD.js +6039 -0
- package/dist/chunks/motelyItemDecoder-CueyZ0XD.js.map +1 -0
- package/dist/chunks/spriteMapper-CFjN0_TV.js +2415 -0
- package/dist/chunks/spriteMapper-CFjN0_TV.js.map +1 -0
- package/dist/chunks/tokens-B65Fzble.js +57 -0
- package/dist/chunks/tokens-B65Fzble.js.map +1 -0
- package/dist/chunks/ui-5cBy3zAm.js +1387 -0
- package/dist/chunks/ui-5cBy3zAm.js.map +1 -0
- package/dist/components/AnalyzerExplorer.d.ts +1 -1
- package/dist/components/CardFan.d.ts +1 -1
- package/dist/components/CardList.d.ts +1 -1
- package/dist/components/DeckSprite.d.ts +1 -1
- package/dist/components/JamlAestheticSelector.d.ts +1 -1
- package/dist/components/JamlAnalyzerFullscreen.d.ts +5 -5
- package/dist/components/JamlCurator.d.ts +1 -6
- package/dist/components/JamlIde.d.ts +5 -5
- package/dist/components/JamlSeedInput.d.ts +1 -1
- package/dist/components/JamlSpeedometer.d.ts +1 -1
- package/dist/components/MotelyVersionBadge.d.ts +1 -1
- package/dist/components/Standardcard.d.ts +1 -1
- package/dist/components/jamlMap/CategoryPicker.d.ts +3 -3
- package/dist/components/jamlMap/JamlMapEditor.d.ts +1 -1
- package/dist/components/jamlMap/JokerPicker.d.ts +1 -1
- package/dist/components/jamlMap/MysterySlot.d.ts +2 -2
- package/dist/components/jamlMap/index.d.ts +4 -4
- package/dist/core.d.ts +5 -5
- package/dist/core.js +27 -5
- package/dist/core.js.map +1 -0
- package/dist/decode/motelyItemDecoder.d.ts +0 -10
- package/dist/decode/motelySprite.d.ts +1 -1
- package/dist/fonts/m6x11plus.otf +0 -0
- package/dist/hooks/analyzerStreamRegistry.d.ts +2 -2
- package/dist/hooks/useAnalyzer.d.ts +3 -3
- package/dist/hooks/useSearch.d.ts +2 -2
- package/dist/index.d.ts +29 -31
- package/dist/index.js +16721 -34
- package/dist/index.js.map +1 -0
- package/dist/lib/const.d.ts +2 -2
- package/dist/lib/hooks/useDragScroll.d.ts +1 -1
- package/dist/lib/hooks/useJamlFilter.d.ts +2 -2
- package/dist/lib/hooks/useSeedAnalyzer.d.ts +2 -2
- package/dist/lib/utils.d.ts +1 -1
- package/dist/motely.d.ts +4 -3
- package/dist/motely.js +65 -3
- package/dist/motely.js.map +1 -0
- package/dist/motelyBoot.d.ts +2 -0
- package/dist/motelyDisplay.d.ts +0 -2
- package/dist/r3f/Card3D.d.ts +2 -2
- package/dist/r3f/JimboBillboard.d.ts +1 -1
- package/dist/r3f.js +235 -3
- package/dist/r3f.js.map +1 -0
- package/dist/render/CanvasRenderer.d.ts +1 -1
- package/dist/sprites/spriteData.d.ts +1 -6
- package/dist/sprites/spriteMapper.d.ts +1 -1
- package/dist/ui/JimboBadge.d.ts +1 -1
- package/dist/ui/JimboFloating.d.ts +1 -1
- package/dist/ui/JimboIconButton.d.ts +1 -1
- package/dist/ui/JimboSelect.d.ts +1 -1
- package/dist/ui/footer.d.ts +2 -3
- package/dist/ui/hooks.d.ts +1 -1
- package/dist/ui/ide/DeckSprite.d.ts +1 -1
- package/dist/ui/jimbo.css +2 -1856
- package/dist/ui/jimboApp.d.ts +1 -1
- package/dist/ui/jimboFilterBar.d.ts +1 -1
- package/dist/ui/jimboFlankNav.d.ts +1 -1
- package/dist/ui/jimboInfoCard.d.ts +1 -1
- package/dist/ui/jimboInset.d.ts +1 -1
- package/dist/ui/jimboStatGrid.d.ts +1 -1
- package/dist/ui/jimboText.d.ts +1 -1
- package/dist/ui/jimboTooltip.d.ts +2 -2
- package/dist/ui/mascot/SeedMascot.d.ts +2 -2
- package/dist/ui/panel.d.ts +1 -1
- package/dist/ui/radial/RadialBadge.d.ts +1 -2
- package/dist/ui/radial/RadialButton.d.ts +1 -2
- package/dist/ui/radial/RadialMenu.d.ts +2 -2
- package/dist/ui/radial/RadialPill.d.ts +1 -2
- package/dist/ui/radial/index.d.ts +16 -16
- package/dist/ui/radial/radialMenuStore.d.ts +1 -1
- package/dist/ui/showcase.d.ts +1 -1
- package/dist/ui/sprites.d.ts +2 -2
- package/dist/ui.d.ts +0 -1
- package/dist/ui.js +3 -36
- package/dist/utils/gameCardUtils.d.ts +1 -1
- package/dist/utils/jamlVisualFilter.d.ts +1 -7
- package/package.json +13 -25
- package/dist/assets.js +0 -48
- package/dist/components/AnalyzerExplorer.js +0 -391
- package/dist/components/CardFan.js +0 -80
- package/dist/components/CardList.js +0 -5
- package/dist/components/DeckSprite.js +0 -75
- package/dist/components/GameCard.js +0 -355
- package/dist/components/JamlAestheticSelector.js +0 -22
- package/dist/components/JamlAnalyzerFullscreen.js +0 -263
- package/dist/components/JamlCodeEditor.js +0 -137
- package/dist/components/JamlCurator.js +0 -64
- package/dist/components/JamlCurator.stories.d.ts +0 -6
- package/dist/components/JamlCurator.stories.js +0 -14
- package/dist/components/JamlIde.js +0 -193
- package/dist/components/JamlIdeToolbar.js +0 -23
- package/dist/components/JamlIdeVisual.js +0 -218
- package/dist/components/JamlMapPreview.js +0 -121
- package/dist/components/JamlSeedInput.js +0 -26
- package/dist/components/JamlSpeedometer.js +0 -70
- package/dist/components/Jimbolate.js +0 -17
- package/dist/components/MotelyVersionBadge.js +0 -19
- package/dist/components/PaginatedFilterBrowser.js +0 -54
- package/dist/components/RunConfigModal.js +0 -59
- package/dist/components/Standardcard.js +0 -80
- package/dist/components/jamlMap/CategoryPicker.js +0 -135
- package/dist/components/jamlMap/JamlMapEditor.js +0 -304
- package/dist/components/jamlMap/JamlMapEditor.stories.d.ts +0 -7
- package/dist/components/jamlMap/JamlMapEditor.stories.js +0 -26
- package/dist/components/jamlMap/JamlMapEditorDemo.d.ts +0 -8
- package/dist/components/jamlMap/JamlMapEditorDemo.js +0 -323
- package/dist/components/jamlMap/JokerPicker.js +0 -113
- package/dist/components/jamlMap/MysterySlot.js +0 -128
- package/dist/components/jamlMap/MysterySlot.stories.d.ts +0 -7
- package/dist/components/jamlMap/MysterySlot.stories.js +0 -31
- package/dist/components/jamlMap/index.js +0 -4
- package/dist/decode/motelyItemDecoder.js +0 -164
- package/dist/decode/motelySprite.js +0 -84
- package/dist/hooks/analyzerStreamRegistry.js +0 -96
- package/dist/hooks/searchWorker.d.ts +0 -1
- package/dist/hooks/searchWorker.js +0 -119
- package/dist/hooks/searchWorkerCode.d.ts +0 -1
- package/dist/hooks/searchWorkerCode.js +0 -85
- package/dist/hooks/useAnalyzer.js +0 -91
- package/dist/hooks/useIntersectionObserver.js +0 -52
- package/dist/hooks/useSearch.js +0 -161
- package/dist/hooks/useShopStream.js +0 -85
- package/dist/lib/SpriteMapper.js +0 -48
- package/dist/lib/cardParser.js +0 -67
- package/dist/lib/classes/BuyMetaData.js +0 -1
- package/dist/lib/config.js +0 -15
- package/dist/lib/const.js +0 -521
- package/dist/lib/data/constants.js +0 -14
- package/dist/lib/hooks/useDragScroll.js +0 -48
- package/dist/lib/hooks/useJamlFilter.js +0 -219
- package/dist/lib/hooks/useSeedAnalyzer.js +0 -50
- package/dist/lib/jaml/jamlCompletion.js +0 -13
- package/dist/lib/jaml/jamlData.js +0 -6
- package/dist/lib/jaml/jamlObjectives.js +0 -97
- package/dist/lib/jaml/jamlParser.js +0 -47
- package/dist/lib/jaml/jamlPresets.js +0 -61
- package/dist/lib/jaml/jamlSchema.js +0 -91
- package/dist/lib/parseDailyRitual.js +0 -70
- package/dist/lib/tts/getRevealPos.js +0 -16
- package/dist/lib/tts/splitTtsDisplay.js +0 -35
- package/dist/lib/types.js +0 -1
- package/dist/lib/utils.js +0 -5
- package/dist/motelyDisplay.js +0 -59
- package/dist/r3f/Card3D.js +0 -72
- package/dist/r3f/JimboBillboard.js +0 -32
- package/dist/r3f/JimboText3D.js +0 -8
- package/dist/render/CanvasRenderer.js +0 -11
- package/dist/render/Layer.js +0 -18
- package/dist/sprites/spriteData.js +0 -100
- package/dist/sprites/spriteMapper.js +0 -75
- package/dist/stories/Button.d.ts +0 -15
- package/dist/stories/Button.js +0 -7
- package/dist/stories/Button.stories.d.ts +0 -24
- package/dist/stories/Button.stories.js +0 -50
- package/dist/stories/Header.d.ts +0 -12
- package/dist/stories/Header.js +0 -4
- package/dist/stories/Header.stories.d.ts +0 -18
- package/dist/stories/Header.stories.js +0 -26
- package/dist/stories/Page.d.ts +0 -3
- package/dist/stories/Page.js +0 -8
- package/dist/stories/Page.stories.d.ts +0 -12
- package/dist/stories/Page.stories.js +0 -24
- package/dist/ui/Jimbo.stories.d.ts +0 -7
- package/dist/ui/Jimbo.stories.js +0 -28
- package/dist/ui/JimboBadge.js +0 -8
- package/dist/ui/JimboFloating.js +0 -17
- package/dist/ui/JimboIconButton.js +0 -28
- package/dist/ui/JimboInputModal.js +0 -66
- package/dist/ui/JimboSelect.js +0 -43
- package/dist/ui/JimboToggleList.js +0 -5
- package/dist/ui/PanelSplitter.js +0 -78
- package/dist/ui/codeBlock.js +0 -14
- package/dist/ui/footer.js +0 -20
- package/dist/ui/hooks.js +0 -634
- package/dist/ui/ide/AgnosticSeedCard.d.ts +0 -19
- package/dist/ui/ide/AgnosticSeedCard.js +0 -48
- package/dist/ui/ide/DeckSprite.js +0 -2
- package/dist/ui/ide/JamlBuilder.d.ts +0 -1
- package/dist/ui/ide/JamlBuilder.js +0 -112
- package/dist/ui/ide/JamlEditor.js +0 -486
- package/dist/ui/ide/JamlEditorMonaco.d.ts +0 -8
- package/dist/ui/ide/JamlEditorMonaco.js +0 -78
- package/dist/ui/ide/WasmStatus.d.ts +0 -1
- package/dist/ui/ide/WasmStatus.js +0 -42
- package/dist/ui/jimboApp.js +0 -15
- package/dist/ui/jimboBackground.js +0 -27
- package/dist/ui/jimboCopyRow.js +0 -18
- package/dist/ui/jimboFilterBar.js +0 -16
- package/dist/ui/jimboFlankNav.js +0 -18
- package/dist/ui/jimboInfoCard.js +0 -26
- package/dist/ui/jimboInset.js +0 -9
- package/dist/ui/jimboSectionHeader.js +0 -9
- package/dist/ui/jimboStatGrid.js +0 -9
- package/dist/ui/jimboTabs.js +0 -22
- package/dist/ui/jimboText.js +0 -33
- package/dist/ui/jimboTooltip.js +0 -39
- package/dist/ui/jimboWordmark.js +0 -9
- package/dist/ui/mascot/JammySpeechBox.js +0 -30
- package/dist/ui/mascot/SeedMascot.js +0 -17
- package/dist/ui/mascot/index.js +0 -3
- package/dist/ui/mascot/menuConfig.js +0 -12
- package/dist/ui/panel.js +0 -24
- package/dist/ui/radial/RadialBadge.js +0 -43
- package/dist/ui/radial/RadialBreadcrumb.js +0 -18
- package/dist/ui/radial/RadialButton.js +0 -102
- package/dist/ui/radial/RadialMenu.js +0 -168
- package/dist/ui/radial/RadialPill.js +0 -15
- package/dist/ui/radial/index.js +0 -18
- package/dist/ui/radial/radialMenuStore.js +0 -122
- package/dist/ui/radial/radialMenuViewport.js +0 -59
- package/dist/ui/radial/useRadialMenu.js +0 -107
- package/dist/ui/showcase.js +0 -20
- package/dist/ui/sprites.js +0 -77
- package/dist/ui/tokens.js +0 -64
- package/dist/utils/gameCardUtils.js +0 -15
- package/dist/utils/jamlMapPreview.js +0 -106
- package/dist/utils/jamlVisualFilter.js +0 -210
|
@@ -1,219 +0,0 @@
|
|
|
1
|
-
import { useState, useCallback, useMemo } from 'react';
|
|
2
|
-
import { DECK_OPTIONS, STAKE_OPTIONS, ANTE_OPTIONS, SLOT_OPTIONS, CLAUSE_TYPES, SOURCE_OPTIONS, EDITION_OPTIONS, SEAL_OPTIONS, ENHANCEMENT_OPTIONS } from '../data/constants.js';
|
|
3
|
-
export { DECK_OPTIONS, STAKE_OPTIONS, ANTE_OPTIONS, SLOT_OPTIONS, CLAUSE_TYPES, SOURCE_OPTIONS, EDITION_OPTIONS, SEAL_OPTIONS, ENHANCEMENT_OPTIONS };
|
|
4
|
-
export function useJamlFilter(initialJaml) {
|
|
5
|
-
const [filter, setFilter] = useState(parseJamlToFilter(initialJaml || ''));
|
|
6
|
-
const [editingClause, setEditingClause] = useState(null);
|
|
7
|
-
// useEffect removed to restore previous UX behavior
|
|
8
|
-
// The JAML from server (Rules format) parses to empty clauses,
|
|
9
|
-
// causing the UI to lose state after load. we want to keep the initial state.
|
|
10
|
-
const jamlText = useMemo(() => filterToJaml(filter), [filter]);
|
|
11
|
-
const updateFilter = useCallback((updates) => {
|
|
12
|
-
setFilter(prev => ({ ...prev, ...updates }));
|
|
13
|
-
}, []);
|
|
14
|
-
const addClause = useCallback((bucket, clause) => {
|
|
15
|
-
setFilter(prev => ({
|
|
16
|
-
...prev,
|
|
17
|
-
[bucket]: [...prev[bucket], clause]
|
|
18
|
-
}));
|
|
19
|
-
}, []);
|
|
20
|
-
const editClause = useCallback((bucket, index, clause) => {
|
|
21
|
-
setFilter(prev => ({
|
|
22
|
-
...prev,
|
|
23
|
-
[bucket]: prev[bucket].map((c, i) => i === index ? clause : c)
|
|
24
|
-
}));
|
|
25
|
-
}, []);
|
|
26
|
-
const deleteClause = useCallback((bucket, index) => {
|
|
27
|
-
setFilter(prev => ({
|
|
28
|
-
...prev,
|
|
29
|
-
[bucket]: prev[bucket].filter((_, i) => i !== index)
|
|
30
|
-
}));
|
|
31
|
-
}, []);
|
|
32
|
-
const setFromJaml = useCallback((text) => {
|
|
33
|
-
const newFilter = parseJamlToFilter(text);
|
|
34
|
-
setFilter(newFilter);
|
|
35
|
-
}, []);
|
|
36
|
-
return {
|
|
37
|
-
filter,
|
|
38
|
-
jamlText,
|
|
39
|
-
setFromJaml,
|
|
40
|
-
updateFilter,
|
|
41
|
-
addClause,
|
|
42
|
-
editClause,
|
|
43
|
-
deleteClause,
|
|
44
|
-
editingClause,
|
|
45
|
-
setEditingClause
|
|
46
|
-
};
|
|
47
|
-
}
|
|
48
|
-
function parseJamlToFilter(text) {
|
|
49
|
-
if (!text.trim())
|
|
50
|
-
return createBlankFilter();
|
|
51
|
-
try {
|
|
52
|
-
const filter = createBlankFilter();
|
|
53
|
-
// Reset arrays to empty since we are parsing fresh
|
|
54
|
-
filter.must = [];
|
|
55
|
-
filter.should = [];
|
|
56
|
-
filter.mustNot = [];
|
|
57
|
-
const lines = text.split('\n');
|
|
58
|
-
let currentSection = null;
|
|
59
|
-
let currentClause = null;
|
|
60
|
-
for (const line of lines) {
|
|
61
|
-
const trimmed = line.trim();
|
|
62
|
-
if (!trimmed || trimmed.startsWith('#'))
|
|
63
|
-
continue;
|
|
64
|
-
// 1. Detect Section Headers
|
|
65
|
-
if (trimmed === 'must:') {
|
|
66
|
-
currentSection = 'must';
|
|
67
|
-
currentClause = null;
|
|
68
|
-
continue;
|
|
69
|
-
}
|
|
70
|
-
if (trimmed === 'should:') {
|
|
71
|
-
currentSection = 'should';
|
|
72
|
-
currentClause = null;
|
|
73
|
-
continue;
|
|
74
|
-
}
|
|
75
|
-
if (trimmed === 'mustNot:') {
|
|
76
|
-
currentSection = 'mustNot';
|
|
77
|
-
currentClause = null;
|
|
78
|
-
continue;
|
|
79
|
-
}
|
|
80
|
-
if (trimmed === 'defaults:') {
|
|
81
|
-
currentSection = 'defaults';
|
|
82
|
-
continue;
|
|
83
|
-
}
|
|
84
|
-
// 2. Detect Root Properties (indent 0)
|
|
85
|
-
const rootMatch = line.match(/^(\w+):\s*(.+)$/);
|
|
86
|
-
if (rootMatch && !line.startsWith(' ') && !line.startsWith('-')) {
|
|
87
|
-
const [, key, val] = rootMatch;
|
|
88
|
-
if (['name', 'deck', 'stake', 'description', 'author'].includes(key)) {
|
|
89
|
-
filter[key] = val.trim();
|
|
90
|
-
}
|
|
91
|
-
continue;
|
|
92
|
-
}
|
|
93
|
-
// 3. Handle Sections
|
|
94
|
-
if (currentSection) {
|
|
95
|
-
if (currentSection === 'defaults') {
|
|
96
|
-
const propMatch = trimmed.match(/^(\w+):\s*(.+)$/);
|
|
97
|
-
if (propMatch) {
|
|
98
|
-
const [, key, val] = propMatch;
|
|
99
|
-
if (key === 'antes')
|
|
100
|
-
filter.defaults.antes = parseNumArray(val);
|
|
101
|
-
if (key === 'packSlots')
|
|
102
|
-
filter.defaults.packSlots = parseNumArray(val);
|
|
103
|
-
if (key === 'shopSlots')
|
|
104
|
-
filter.defaults.shopSlots = parseNumArray(val);
|
|
105
|
-
if (key === 'score')
|
|
106
|
-
filter.defaults.score = parseInt(val) || 0;
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
else {
|
|
110
|
-
// Start of new clause
|
|
111
|
-
const typeMatch = trimmed.match(/^-\s*type:\s*(.+)$/);
|
|
112
|
-
if (typeMatch) {
|
|
113
|
-
currentClause = { type: typeMatch[1].trim(), value: '' };
|
|
114
|
-
filter[currentSection].push(currentClause);
|
|
115
|
-
continue;
|
|
116
|
-
}
|
|
117
|
-
// Properties of current clause
|
|
118
|
-
if (currentClause) {
|
|
119
|
-
const propMatch = trimmed.match(/^(\w+):\s*(.+)$/);
|
|
120
|
-
if (propMatch) {
|
|
121
|
-
const [, key, val] = propMatch;
|
|
122
|
-
if (key === 'antes')
|
|
123
|
-
currentClause.antes = parseNumArray(val);
|
|
124
|
-
else if (key === 'sources')
|
|
125
|
-
currentClause.sources = parseStringArray(val);
|
|
126
|
-
else if (key === 'score')
|
|
127
|
-
currentClause.score = parseInt(val) || 0;
|
|
128
|
-
else
|
|
129
|
-
currentClause[key] = val.trim();
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
return filter;
|
|
136
|
-
}
|
|
137
|
-
catch (e) {
|
|
138
|
-
console.warn('JAML Parse Error:', e);
|
|
139
|
-
return createBlankFilter();
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
function parseNumArray(str) {
|
|
143
|
-
return str.replace(/[[\]]/g, '').split(',').map(s => parseInt(s.trim())).filter(n => !isNaN(n));
|
|
144
|
-
}
|
|
145
|
-
function parseStringArray(str) {
|
|
146
|
-
return str.replace(/[[\]]/g, '').split(',').map(s => s.trim()).filter(s => !!s);
|
|
147
|
-
}
|
|
148
|
-
function filterToJaml(filter) {
|
|
149
|
-
const lines = [];
|
|
150
|
-
lines.push(`name: ${filter.name}`);
|
|
151
|
-
lines.push(`description: ${filter.description || ''}`);
|
|
152
|
-
lines.push(`author: ${filter.author || ''}`);
|
|
153
|
-
lines.push(`deck: ${filter.deck}`);
|
|
154
|
-
lines.push(`stake: ${filter.stake}`);
|
|
155
|
-
lines.push('');
|
|
156
|
-
lines.push('defaults:');
|
|
157
|
-
lines.push(` antes: [${filter.defaults.antes.join(', ')}]`);
|
|
158
|
-
lines.push(` packSlots: [${filter.defaults.packSlots.join(', ')}]`);
|
|
159
|
-
lines.push(` shopSlots: [${filter.defaults.shopSlots.join(', ')}]`);
|
|
160
|
-
lines.push(` score: ${filter.defaults.score}`);
|
|
161
|
-
lines.push('');
|
|
162
|
-
if (filter.must.length > 0) {
|
|
163
|
-
lines.push('must:');
|
|
164
|
-
filter.must.forEach(clause => lines.push(...clauseToLines(clause, ' ')));
|
|
165
|
-
}
|
|
166
|
-
if (filter.should.length > 0) {
|
|
167
|
-
lines.push('should:');
|
|
168
|
-
filter.should.forEach(clause => lines.push(...clauseToLines(clause, ' ')));
|
|
169
|
-
}
|
|
170
|
-
if (filter.mustNot.length > 0) {
|
|
171
|
-
lines.push('mustNot:');
|
|
172
|
-
filter.mustNot.forEach(clause => lines.push(...clauseToLines(clause, ' ')));
|
|
173
|
-
}
|
|
174
|
-
return lines.join('\n');
|
|
175
|
-
}
|
|
176
|
-
function clauseToLines(clause, indent) {
|
|
177
|
-
const lines = [];
|
|
178
|
-
lines.push(`${indent}- type: ${clause.type}`);
|
|
179
|
-
lines.push(`${indent} value: ${clause.value}`);
|
|
180
|
-
if (clause.label)
|
|
181
|
-
lines.push(`${indent} label: ${clause.label}`);
|
|
182
|
-
if (clause.antes && clause.antes.length > 0)
|
|
183
|
-
lines.push(`${indent} antes: [${clause.antes.join(', ')}]`);
|
|
184
|
-
if (clause.score)
|
|
185
|
-
lines.push(`${indent} score: ${clause.score}`);
|
|
186
|
-
if (clause.edition)
|
|
187
|
-
lines.push(`${indent} edition: ${clause.edition}`);
|
|
188
|
-
if (clause.seal)
|
|
189
|
-
lines.push(`${indent} seal: ${clause.seal}`);
|
|
190
|
-
if (clause.enhancement)
|
|
191
|
-
lines.push(`${indent} enhancement: ${clause.enhancement}`);
|
|
192
|
-
if (clause.rank)
|
|
193
|
-
lines.push(`${indent} rank: ${clause.rank}`);
|
|
194
|
-
if (clause.suit)
|
|
195
|
-
lines.push(`${indent} suit: ${clause.suit}`);
|
|
196
|
-
if (clause.sources && clause.sources.length > 0)
|
|
197
|
-
lines.push(`${indent} sources: [${clause.sources.join(', ')}]`);
|
|
198
|
-
return lines;
|
|
199
|
-
}
|
|
200
|
-
function createBlankFilter() {
|
|
201
|
-
return {
|
|
202
|
-
name: 'New Filter',
|
|
203
|
-
description: '',
|
|
204
|
-
author: '',
|
|
205
|
-
deck: 'Erratic',
|
|
206
|
-
stake: 'White',
|
|
207
|
-
defaults: {
|
|
208
|
-
antes: [...ANTE_OPTIONS],
|
|
209
|
-
packSlots: [...SLOT_OPTIONS],
|
|
210
|
-
shopSlots: [...SLOT_OPTIONS],
|
|
211
|
-
score: 1
|
|
212
|
-
},
|
|
213
|
-
must: [],
|
|
214
|
-
should: [
|
|
215
|
-
{ type: 'joker', value: 'Joker' }
|
|
216
|
-
],
|
|
217
|
-
mustNot: []
|
|
218
|
-
};
|
|
219
|
-
}
|
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
import { useState, useEffect } from "react";
|
|
3
|
-
export function useSeedAnalyzer(motely, seed) {
|
|
4
|
-
const [data, setData] = useState(null);
|
|
5
|
-
const [loading, setLoading] = useState(false);
|
|
6
|
-
const [error, setError] = useState(null);
|
|
7
|
-
const [prevInputs, setPrevInputs] = useState({ seed, motely });
|
|
8
|
-
if (seed !== prevInputs.seed || motely !== prevInputs.motely) {
|
|
9
|
-
setPrevInputs({ seed, motely });
|
|
10
|
-
if (!seed || seed === "LOCKED" || !motely) {
|
|
11
|
-
setData(null);
|
|
12
|
-
}
|
|
13
|
-
}
|
|
14
|
-
useEffect(() => {
|
|
15
|
-
if (!seed || seed === "LOCKED" || !motely) {
|
|
16
|
-
return;
|
|
17
|
-
}
|
|
18
|
-
const abortController = new AbortController();
|
|
19
|
-
const runAnalysis = async () => {
|
|
20
|
-
setLoading(true);
|
|
21
|
-
setError(null);
|
|
22
|
-
try {
|
|
23
|
-
const jaml = `version: 1\nconfig:\n deck: Erratic\n stake: White\n`;
|
|
24
|
-
const rawResult = motely.MotelyWasm.analyzeJamlSeeds(jaml, [seed]);
|
|
25
|
-
if (abortController.signal.aborted)
|
|
26
|
-
return;
|
|
27
|
-
if (rawResult && rawResult.seeds.length > 0) {
|
|
28
|
-
const result = rawResult.seeds[0];
|
|
29
|
-
setData(result.analysis || null);
|
|
30
|
-
}
|
|
31
|
-
else {
|
|
32
|
-
throw new Error("No analysis result returned");
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
catch (err) {
|
|
36
|
-
if (abortController.signal.aborted)
|
|
37
|
-
return;
|
|
38
|
-
console.error("[useSeedAnalyzer] Analysis error:", err);
|
|
39
|
-
setError(err instanceof Error ? err.message : String(err));
|
|
40
|
-
}
|
|
41
|
-
finally {
|
|
42
|
-
if (!abortController.signal.aborted)
|
|
43
|
-
setLoading(false);
|
|
44
|
-
}
|
|
45
|
-
};
|
|
46
|
-
runAnalysis();
|
|
47
|
-
return () => abortController.abort();
|
|
48
|
-
}, [motely, seed]);
|
|
49
|
-
return { data, loading, error };
|
|
50
|
-
}
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import { JAML_KEYWORDS } from './jamlData';
|
|
2
|
-
export class JamlCompletionService {
|
|
3
|
-
static getCompletions(currentValue) {
|
|
4
|
-
const lower = currentValue.toLowerCase();
|
|
5
|
-
return JAML_KEYWORDS
|
|
6
|
-
.filter(k => k.toLowerCase().includes(lower))
|
|
7
|
-
.map(k => ({
|
|
8
|
-
text: k,
|
|
9
|
-
displayText: k,
|
|
10
|
-
type: 'keyword'
|
|
11
|
-
}));
|
|
12
|
-
}
|
|
13
|
-
}
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
import { CLAUSE_TYPE_KEYS } from './jamlSchema.js';
|
|
2
|
-
export const CLAUSE_TYPES = [...CLAUSE_TYPE_KEYS];
|
|
3
|
-
export const ARRAY_KEYS = ['antes', 'tags', 'labels'];
|
|
4
|
-
export const JAML_KEYWORDS = [
|
|
5
|
-
'must', 'should', 'mustNot', 'any', 'Any', ...CLAUSE_TYPES, ...ARRAY_KEYS
|
|
6
|
-
];
|
|
@@ -1,97 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* JAML Objectives Parser
|
|
3
|
-
*
|
|
4
|
-
* Extracts display-ready objective names from a JAML config string
|
|
5
|
-
* using the existing useJamlFilter parser — no hand-rolled regex.
|
|
6
|
-
*
|
|
7
|
-
* This is the ONLY place JAML → objective extraction should happen.
|
|
8
|
-
*/
|
|
9
|
-
/**
|
|
10
|
-
* Parse a JAML config string and extract objectives (must-clause values).
|
|
11
|
-
* Returns an array of human-readable objective names.
|
|
12
|
-
*/
|
|
13
|
-
export function parseJamlToObjectives(jamlConfig) {
|
|
14
|
-
if (!jamlConfig.trim())
|
|
15
|
-
return [];
|
|
16
|
-
const objectives = [];
|
|
17
|
-
const lines = jamlConfig.split('\n');
|
|
18
|
-
let inMustBlock = false;
|
|
19
|
-
let currentClause = null;
|
|
20
|
-
for (const line of lines) {
|
|
21
|
-
const trimmed = line.trim();
|
|
22
|
-
if (!trimmed || trimmed.startsWith('#'))
|
|
23
|
-
continue;
|
|
24
|
-
// Section headers
|
|
25
|
-
if (trimmed === 'must:') {
|
|
26
|
-
inMustBlock = true;
|
|
27
|
-
currentClause = null;
|
|
28
|
-
continue;
|
|
29
|
-
}
|
|
30
|
-
if (trimmed === 'should:' || trimmed === 'mustNot:' || trimmed === 'defaults:') {
|
|
31
|
-
// Flush current clause before leaving must block
|
|
32
|
-
if (inMustBlock && currentClause) {
|
|
33
|
-
const name = currentClause.label || currentClause.value;
|
|
34
|
-
if (name)
|
|
35
|
-
objectives.push(name);
|
|
36
|
-
}
|
|
37
|
-
inMustBlock = false;
|
|
38
|
-
currentClause = null;
|
|
39
|
-
continue;
|
|
40
|
-
}
|
|
41
|
-
if (!inMustBlock)
|
|
42
|
-
continue;
|
|
43
|
-
// New clause (starts with -)
|
|
44
|
-
if (trimmed.startsWith('-')) {
|
|
45
|
-
// Flush previous clause
|
|
46
|
-
if (currentClause) {
|
|
47
|
-
const name = currentClause.label || currentClause.value;
|
|
48
|
-
if (name)
|
|
49
|
-
objectives.push(name);
|
|
50
|
-
}
|
|
51
|
-
currentClause = {};
|
|
52
|
-
// Parse inline key:value on same line as dash
|
|
53
|
-
const inlineMatch = trimmed.match(/^-\s*(\w+):\s*(.+)$/);
|
|
54
|
-
if (inlineMatch) {
|
|
55
|
-
const [, key, val] = inlineMatch;
|
|
56
|
-
if (key === 'type')
|
|
57
|
-
currentClause.type = val.trim();
|
|
58
|
-
else if (key === 'value')
|
|
59
|
-
currentClause.value = val.trim();
|
|
60
|
-
else if (key === 'label')
|
|
61
|
-
currentClause.label = val.trim();
|
|
62
|
-
else {
|
|
63
|
-
// Shorthand: `- joker: Blueprint` means type=joker, value=Blueprint
|
|
64
|
-
currentClause.type = key;
|
|
65
|
-
currentClause.value = val.trim();
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
continue;
|
|
69
|
-
}
|
|
70
|
-
// Properties of current clause (indented, no dash)
|
|
71
|
-
if (currentClause) {
|
|
72
|
-
const propMatch = trimmed.match(/^(\w+):\s*(.+)$/);
|
|
73
|
-
if (propMatch) {
|
|
74
|
-
const [, key, val] = propMatch;
|
|
75
|
-
if (key === 'value')
|
|
76
|
-
currentClause.value = val.trim();
|
|
77
|
-
else if (key === 'label')
|
|
78
|
-
currentClause.label = val.trim();
|
|
79
|
-
else if (key === 'type')
|
|
80
|
-
currentClause.type = val.trim();
|
|
81
|
-
else if (!currentClause.value && key !== 'antes' && key !== 'score' && key !== 'sources' && key !== 'edition' && key !== 'seal' && key !== 'enhancement') {
|
|
82
|
-
// Shorthand values like `joker: Blueprint` inside a clause
|
|
83
|
-
// Only use as value if we don't already have one
|
|
84
|
-
currentClause.type = currentClause.type || key;
|
|
85
|
-
currentClause.value = val.trim();
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
// Flush final clause
|
|
91
|
-
if (inMustBlock && currentClause) {
|
|
92
|
-
const name = currentClause.label || currentClause.value;
|
|
93
|
-
if (name)
|
|
94
|
-
objectives.push(name);
|
|
95
|
-
}
|
|
96
|
-
return objectives;
|
|
97
|
-
}
|
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Simple regex-based JAML parser for extracting highlighting rules.
|
|
3
|
-
* Handles basic YAML structure:
|
|
4
|
-
* Must:
|
|
5
|
-
* - joker: WeeJoker
|
|
6
|
-
* Should:
|
|
7
|
-
* - joker: HangingChad
|
|
8
|
-
*/
|
|
9
|
-
export function parseJamlHighlights(jamlContent) {
|
|
10
|
-
const rules = {
|
|
11
|
-
highPriority: new Set(),
|
|
12
|
-
mediumPriority: new Set()
|
|
13
|
-
};
|
|
14
|
-
if (!jamlContent)
|
|
15
|
-
return rules;
|
|
16
|
-
const lines = jamlContent.split('\n');
|
|
17
|
-
let currentSection = null;
|
|
18
|
-
for (const line of lines) {
|
|
19
|
-
const trimmed = line.trim();
|
|
20
|
-
if (trimmed.startsWith('Must:')) {
|
|
21
|
-
currentSection = 'Must';
|
|
22
|
-
continue;
|
|
23
|
-
}
|
|
24
|
-
if (trimmed.startsWith('Should:')) {
|
|
25
|
-
currentSection = 'Should';
|
|
26
|
-
continue;
|
|
27
|
-
}
|
|
28
|
-
// Look for "- joker: Name" or "- souljoker: Name"
|
|
29
|
-
const jokerMatch = trimmed.match(/- (?:joker|souljoker): (.+)/);
|
|
30
|
-
if (jokerMatch) {
|
|
31
|
-
const name = jokerMatch[1].trim();
|
|
32
|
-
// Normalize: "WeeJoker" -> "Wee Joker" if needed?
|
|
33
|
-
// Blueprint output usually has spaces "Wee Joker".
|
|
34
|
-
// JAML uses "WeeJoker".
|
|
35
|
-
// We'll normalize by removing spaces for comparison.
|
|
36
|
-
const normalized = name.replace(/\s+/g, '').toLowerCase();
|
|
37
|
-
if (currentSection === 'Must')
|
|
38
|
-
rules.highPriority.add(normalized);
|
|
39
|
-
if (currentSection === 'Should')
|
|
40
|
-
rules.mediumPriority.add(normalized);
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
return rules;
|
|
44
|
-
}
|
|
45
|
-
export function normalizeName(name) {
|
|
46
|
-
return name.replace(/\s+/g, '').toLowerCase();
|
|
47
|
-
}
|
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
export const JAML_PRESETS = [
|
|
2
|
-
{
|
|
3
|
-
id: 'soul-hunter',
|
|
4
|
-
label: 'Soul Hunter',
|
|
5
|
-
description: 'Find a Spectral Soul card in early Antes.',
|
|
6
|
-
jaml: `# The Soul Hunter
|
|
7
|
-
name: Soul Hunter
|
|
8
|
-
deck: Red
|
|
9
|
-
stake: White
|
|
10
|
-
|
|
11
|
-
must:
|
|
12
|
-
- spectralCard: The Soul
|
|
13
|
-
antes: [1, 2, 3]
|
|
14
|
-
`
|
|
15
|
-
},
|
|
16
|
-
{
|
|
17
|
-
id: 'negative-blueprint',
|
|
18
|
-
label: 'Negative Blueprint',
|
|
19
|
-
description: 'Find a Negative Blueprint early.',
|
|
20
|
-
jaml: `# Negative Blueprint
|
|
21
|
-
name: Negative Blueprint
|
|
22
|
-
deck: Red
|
|
23
|
-
stake: White
|
|
24
|
-
|
|
25
|
-
must:
|
|
26
|
-
- joker: Blueprint
|
|
27
|
-
edition: Negative
|
|
28
|
-
antes: [1, 2, 3, 4]
|
|
29
|
-
`
|
|
30
|
-
},
|
|
31
|
-
{
|
|
32
|
-
id: 'mega-tags',
|
|
33
|
-
label: 'Mega Tags',
|
|
34
|
-
description: 'Find a lot of Investment and Double Tags.',
|
|
35
|
-
jaml: `# Mega Tags
|
|
36
|
-
name: Mega Tags
|
|
37
|
-
deck: Red
|
|
38
|
-
stake: White
|
|
39
|
-
|
|
40
|
-
must:
|
|
41
|
-
- tag: Double Tag
|
|
42
|
-
antes: [1, 2]
|
|
43
|
-
- tag: Investment Tag
|
|
44
|
-
antes: [1, 2]
|
|
45
|
-
`
|
|
46
|
-
},
|
|
47
|
-
{
|
|
48
|
-
id: 'black-hole',
|
|
49
|
-
label: 'Black Hole',
|
|
50
|
-
description: 'Find the elusive Black Hole spectral card.',
|
|
51
|
-
jaml: `# Black Hole
|
|
52
|
-
name: Black Hole
|
|
53
|
-
deck: Red
|
|
54
|
-
stake: White
|
|
55
|
-
|
|
56
|
-
must:
|
|
57
|
-
- spectralCard: Black Hole
|
|
58
|
-
antes: [1, 2, 3, 4]
|
|
59
|
-
`
|
|
60
|
-
}
|
|
61
|
-
];
|
|
@@ -1,91 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* JAML Schema Bridge
|
|
3
|
-
*
|
|
4
|
-
* Derives all JAML schema constants from motely-wasm/jaml.schema.json.
|
|
5
|
-
* All JAML-aware files import from here — single swap point if the API changes.
|
|
6
|
-
*/
|
|
7
|
-
import jamlSchemaJson from '../../../jaml.schema.json';
|
|
8
|
-
const schema = jamlSchemaJson;
|
|
9
|
-
const clauseDef = schema.definitions?.clause?.properties ?? {};
|
|
10
|
-
export const JAML_SCHEMA_VERSION = schema.version ?? 'unknown';
|
|
11
|
-
/** The raw JSON schema object. */
|
|
12
|
-
export const jamlSchema = schema;
|
|
13
|
-
// ── Key groups ─────────────────────────────────────────────────────────────
|
|
14
|
-
/** Root-level metadata keys (name, author, deck, etc.) */
|
|
15
|
-
export const METADATA_KEYS = [
|
|
16
|
-
'id', 'name', 'description', 'author', 'dateCreated',
|
|
17
|
-
'deck', 'stake', 'seeds', 'hashtags', 'aesthetics', 'defaults',
|
|
18
|
-
];
|
|
19
|
-
/** Section keys that contain clause arrays. */
|
|
20
|
-
export const SECTION_KEYS = ['must', 'should', 'mustNot'];
|
|
21
|
-
/** Clause type keys — the primary discriminators (joker, voucher, tarot, etc.). */
|
|
22
|
-
export const CLAUSE_TYPE_KEYS = (clauseDef.type?.enum ?? []);
|
|
23
|
-
/** Property keys available inside a clause. */
|
|
24
|
-
export const PROPERTY_KEYS = Object.keys(clauseDef);
|
|
25
|
-
/** Source-configuration keys (shopItems, boosterPacks, etc.). */
|
|
26
|
-
export const SOURCE_KEYS = (() => {
|
|
27
|
-
const srcProps = clauseDef.sources?.properties;
|
|
28
|
-
return srcProps ? Object.keys(srcProps) : ['shopItems', 'boosterPacks'];
|
|
29
|
-
})();
|
|
30
|
-
// ── Value lookups ──────────────────────────────────────────────────────────
|
|
31
|
-
/**
|
|
32
|
-
* Get the valid enum values for a given JAML key.
|
|
33
|
-
* Checks top-level properties first, then falls back to clause properties.
|
|
34
|
-
*/
|
|
35
|
-
export function getValidValuesForKey(key) {
|
|
36
|
-
// Top-level enum (deck, stake)
|
|
37
|
-
const topProp = schema.properties?.[key];
|
|
38
|
-
if (topProp?.enum)
|
|
39
|
-
return topProp.enum;
|
|
40
|
-
if (topProp?.items?.enum)
|
|
41
|
-
return topProp.items.enum;
|
|
42
|
-
// Clause-level enum
|
|
43
|
-
const clauseProp = clauseDef[key];
|
|
44
|
-
if (clauseProp?.enum)
|
|
45
|
-
return clauseProp.enum;
|
|
46
|
-
if (clauseProp?.items?.enum)
|
|
47
|
-
return clauseProp.items.enum;
|
|
48
|
-
return null;
|
|
49
|
-
}
|
|
50
|
-
/**
|
|
51
|
-
* Get the available properties for a given clause type.
|
|
52
|
-
* Returns all clause property keys (the type system doesn't restrict per-type in JSON schema v7).
|
|
53
|
-
*/
|
|
54
|
-
export function getAvailablePropsForType( /* _clauseType */) {
|
|
55
|
-
return PROPERTY_KEYS;
|
|
56
|
-
}
|
|
57
|
-
/**
|
|
58
|
-
* Check if a property is invalid for a clause type.
|
|
59
|
-
* In the v7 schema, all properties are available on all clause types.
|
|
60
|
-
*/
|
|
61
|
-
export function isInvalidPropForType( /* _prop, _clauseType */) {
|
|
62
|
-
return false;
|
|
63
|
-
}
|
|
64
|
-
/**
|
|
65
|
-
* Check if a value is invalid for a property.
|
|
66
|
-
*/
|
|
67
|
-
export function isInvalidValueForProp(value, prop) {
|
|
68
|
-
const valid = getValidValuesForKey(prop);
|
|
69
|
-
if (!valid)
|
|
70
|
-
return false; // No enum constraint — anything goes
|
|
71
|
-
return !valid.includes(value);
|
|
72
|
-
}
|
|
73
|
-
// ── Convenience lookups ────────────────────────────────────────────────────
|
|
74
|
-
export const DECK_VALUES = (getValidValuesForKey('deck') ?? []);
|
|
75
|
-
export const STAKE_VALUES = (getValidValuesForKey('stake') ?? []);
|
|
76
|
-
export const EDITION_VALUES = (getValidValuesForKey('edition') ?? []);
|
|
77
|
-
export const SEAL_VALUES = (getValidValuesForKey('seal') ?? []);
|
|
78
|
-
export const ENHANCEMENT_VALUES = (getValidValuesForKey('enhancement') ?? []);
|
|
79
|
-
export const RANK_VALUES = (getValidValuesForKey('rank') ?? []);
|
|
80
|
-
export const SUIT_VALUES = (getValidValuesForKey('suit') ?? []);
|
|
81
|
-
export const STICKER_VALUES = (getValidValuesForKey('stickers') ?? []);
|
|
82
|
-
/**
|
|
83
|
-
* All JAML keywords — sections, metadata keys, clause types, and property keys.
|
|
84
|
-
*/
|
|
85
|
-
export const ALL_JAML_KEYWORDS = [
|
|
86
|
-
...SECTION_KEYS,
|
|
87
|
-
...METADATA_KEYS,
|
|
88
|
-
...CLAUSE_TYPE_KEYS,
|
|
89
|
-
...PROPERTY_KEYS,
|
|
90
|
-
...SOURCE_KEYS,
|
|
91
|
-
];
|
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Parser for daily_ritual.json abbreviated format
|
|
3
|
-
*
|
|
4
|
-
* Expands abbreviated fields like "wj2", "hc1" into full item objects
|
|
5
|
-
*/
|
|
6
|
-
// Mapping of abbreviations to full item data
|
|
7
|
-
const ITEM_MAP = {
|
|
8
|
-
wj: { id: 'weejoker', name: 'Wee Joker', type: 'joker' },
|
|
9
|
-
hc: { id: 'hangingchad', name: 'Hanging Chad', type: 'joker' },
|
|
10
|
-
hk: { id: 'hack', name: 'Hack', type: 'joker' },
|
|
11
|
-
bp: { id: 'blueprint', name: 'Blueprint', type: 'joker' },
|
|
12
|
-
bs: { id: 'brainstorm', name: 'Brainstorm', type: 'joker' },
|
|
13
|
-
sh: { id: 'showman', name: 'Showman', type: 'joker' },
|
|
14
|
-
cp: { id: 'copy', name: 'Copy', type: 'consumable' }, // Placeholder
|
|
15
|
-
// Add more as needed
|
|
16
|
-
};
|
|
17
|
-
/**
|
|
18
|
-
* Parse daily_ritual.json seed format
|
|
19
|
-
*
|
|
20
|
-
* Example input:
|
|
21
|
-
* {"id":"J4SPZMWW","t":"Twosday","j":"Joker","s":206,"w":16,"wj2":1,"hc2":1}
|
|
22
|
-
*
|
|
23
|
-
* Output:
|
|
24
|
-
* {
|
|
25
|
-
* seed: "J4SPZMWW",
|
|
26
|
-
* title: "Twosday",
|
|
27
|
-
* score: 206,
|
|
28
|
-
* twos: 16,
|
|
29
|
-
* items: [
|
|
30
|
-
* { id: 'weejoker', name: 'Wee Joker', type: 'joker', ante: 2 },
|
|
31
|
-
* { id: 'hangingchad', name: 'Hanging Chad', type: 'joker', ante: 2 }
|
|
32
|
-
* ]
|
|
33
|
-
* }
|
|
34
|
-
*/
|
|
35
|
-
export function parseDailyRitualSeed(raw) {
|
|
36
|
-
const items = [];
|
|
37
|
-
// Parse each field looking for pattern: letters + number (e.g., "wj2", "hc1")
|
|
38
|
-
Object.keys(raw).forEach(key => {
|
|
39
|
-
if (key === 'id' || key === 't' || key === 's' || key === 'w')
|
|
40
|
-
return;
|
|
41
|
-
const match = key.match(/^([a-z]+)(\d+)$/);
|
|
42
|
-
if (match) {
|
|
43
|
-
const [, code, ante] = match;
|
|
44
|
-
const itemData = ITEM_MAP[code];
|
|
45
|
-
if (itemData) {
|
|
46
|
-
items.push({
|
|
47
|
-
...itemData,
|
|
48
|
-
ante: Number(ante)
|
|
49
|
-
});
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
});
|
|
53
|
-
return {
|
|
54
|
-
seed: raw.id || '',
|
|
55
|
-
title: raw.t || '',
|
|
56
|
-
score: raw.s || 0,
|
|
57
|
-
twos: raw.w || 0,
|
|
58
|
-
items
|
|
59
|
-
};
|
|
60
|
-
}
|
|
61
|
-
/**
|
|
62
|
-
* Group items by type for rendering
|
|
63
|
-
*/
|
|
64
|
-
export function groupItemsByType(items) {
|
|
65
|
-
return {
|
|
66
|
-
jokers: items.filter(i => i.type === 'joker'),
|
|
67
|
-
consumables: items.filter(i => i.type === 'consumable'),
|
|
68
|
-
vouchers: items.filter(i => i.type === 'voucher')
|
|
69
|
-
};
|
|
70
|
-
}
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Advance past trailing punctuation and whitespace so reveal snaps to word boundaries.
|
|
3
|
-
* Used by both JammySpeechBox (home announcement) and ChatInterface (streaming chat).
|
|
4
|
-
*/
|
|
5
|
-
export function getRevealPos(text, highlightPos) {
|
|
6
|
-
if (highlightPos <= 0)
|
|
7
|
-
return 0;
|
|
8
|
-
if (highlightPos >= text.length)
|
|
9
|
-
return text.length;
|
|
10
|
-
let i = highlightPos;
|
|
11
|
-
while (i < text.length && /[)\]}'"'\u2018\u2019.,!?;:]/.test(text[i]))
|
|
12
|
-
i++;
|
|
13
|
-
while (i < text.length && /\s/.test(text[i]))
|
|
14
|
-
i++;
|
|
15
|
-
return i;
|
|
16
|
-
}
|