Skip to content

Commit 9f39ef3

Browse files
mbreiserclaude
andcommitted
fix: Restore GENERATIONS, ARENA_REGISTRY, and ES6 exports in arena-configs.js
The generator was stripping hand-written sections (GENERATIONS registry, ARENA_REGISTRY, getArenaId/getArenaName/getGenerationId/getGenerationName functions, window globals, and ES6 module exports) on regeneration. This broke the pattern editor and arena editor (empty arena dropdowns) because ES module imports couldn't resolve the missing exports. Fixed the generator to: - Read arena_registry/index.yaml and emit ARENA_REGISTRY - Include GENERATIONS constants - Include all registry lookup functions - Emit window.* globals for non-module scripts - Emit ES6 export {} block for module scripts All 55 header V2 validation tests pass. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent b5cddc3 commit 9f39ef3

2 files changed

Lines changed: 233 additions & 5 deletions

File tree

js/arena-configs.js

Lines changed: 93 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/**
22
* Arena Configurations
3-
* Auto-generated from maDisplayTools/configs/arenas/
4-
* Last updated: 2026-02-18T23:04:32.832Z
3+
* Auto-generated from maDisplayTools/configs/arenas/ and arena_registry/
4+
* Last updated: 2026-02-18T23:17:28.795Z
55
*
66
* DO NOT EDIT MANUALLY - regenerate with: node scripts/generate-arena-configs.js
77
*/
@@ -174,6 +174,71 @@ const STANDARD_CONFIGS = {
174174
}
175175
};
176176

177+
// Generation ID registry (from maDisplayTools/configs/arena_registry/generations.yaml)
178+
const GENERATIONS = {
179+
0: { name: 'unspecified', panel_size: null },
180+
1: { name: 'G3', panel_size: 8 },
181+
2: { name: 'G4', panel_size: 16 },
182+
3: { name: 'G4.1', panel_size: 16 },
183+
4: { name: 'G6', panel_size: 20 },
184+
5: { name: 'G5', panel_size: null, deprecated: true }
185+
};
186+
187+
// Arena ID registry — per-generation namespaces (from maDisplayTools/configs/arena_registry/index.yaml)
188+
const ARENA_REGISTRY = {
189+
'G4': { 1: 'G4_4x12', 2: 'G4_3x12of18' },
190+
'G4.1': { 1: 'G41_2x12_cw' },
191+
'G6': { 1: 'G6_2x10', 2: 'G6_2x8of10', 3: 'G6_3x12of18' }
192+
};
193+
194+
/**
195+
* Get generation name from ID
196+
* @param {number} id - Generation ID (0-7)
197+
* @returns {string} Generation name or 'unknown'
198+
*/
199+
function getGenerationName(id) {
200+
return GENERATIONS[id] ? GENERATIONS[id].name : 'unknown';
201+
}
202+
203+
/**
204+
* Get generation ID from name
205+
* @param {string} name - Generation name (e.g., 'G6', 'G4.1')
206+
* @returns {number} Generation ID or 0
207+
*/
208+
function getGenerationId(name) {
209+
for (const [id, gen] of Object.entries(GENERATIONS)) {
210+
if (gen.name === name) return parseInt(id);
211+
}
212+
return 0;
213+
}
214+
215+
/**
216+
* Get arena config name from generation and arena ID
217+
* @param {string} generation - Generation name (e.g., 'G6', 'G4')
218+
* @param {number} arenaId - Arena ID
219+
* @returns {string|null} Arena config name or null
220+
*/
221+
function getArenaName(generation, arenaId) {
222+
const genRegistry = ARENA_REGISTRY[generation];
223+
if (!genRegistry) return null;
224+
return genRegistry[arenaId] || null;
225+
}
226+
227+
/**
228+
* Get arena ID from generation and config name
229+
* @param {string} generation - Generation name (e.g., 'G6', 'G4')
230+
* @param {string} arenaName - Arena config name (e.g., 'G6_2x10')
231+
* @returns {number} Arena ID or 0
232+
*/
233+
function getArenaId(generation, arenaName) {
234+
const genRegistry = ARENA_REGISTRY[generation];
235+
if (!genRegistry) return 0;
236+
for (const [id, name] of Object.entries(genRegistry)) {
237+
if (name === arenaName) return parseInt(id);
238+
}
239+
return 0;
240+
}
241+
177242
// Panel specifications by generation
178243
const PANEL_SPECS = {
179244
'G3': {
@@ -233,5 +298,30 @@ function getConfigsByGeneration() {
233298

234299
// Export for both browser and Node.js
235300
if (typeof module !== 'undefined' && module.exports) {
236-
module.exports = { STANDARD_CONFIGS, PANEL_SPECS, getConfig, getConfigsByGeneration };
301+
module.exports = {
302+
STANDARD_CONFIGS, PANEL_SPECS, GENERATIONS, ARENA_REGISTRY,
303+
getConfig, getConfigsByGeneration,
304+
getGenerationName, getGenerationId, getArenaName, getArenaId
305+
};
306+
}
307+
308+
// Browser global export (for non-module scripts)
309+
if (typeof window !== 'undefined') {
310+
window.STANDARD_CONFIGS = STANDARD_CONFIGS;
311+
window.PANEL_SPECS = PANEL_SPECS;
312+
window.GENERATIONS = GENERATIONS;
313+
window.ARENA_REGISTRY = ARENA_REGISTRY;
314+
window.getConfig = getConfig;
315+
window.getConfigsByGeneration = getConfigsByGeneration;
316+
window.getGenerationName = getGenerationName;
317+
window.getGenerationId = getGenerationId;
318+
window.getArenaName = getArenaName;
319+
window.getArenaId = getArenaId;
237320
}
321+
322+
// ES6 module export
323+
export {
324+
STANDARD_CONFIGS, PANEL_SPECS, GENERATIONS, ARENA_REGISTRY,
325+
getConfig, getConfigsByGeneration,
326+
getGenerationName, getGenerationId, getArenaName, getArenaId
327+
};

scripts/generate-arena-configs.js

Lines changed: 140 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -135,13 +135,55 @@ function findConfigDir() {
135135
process.exit(1);
136136
}
137137

138+
// Parse arena registry index.yaml to build ARENA_REGISTRY
139+
function parseArenaRegistry(registryDir) {
140+
const indexFile = path.join(registryDir, 'index.yaml');
141+
if (!fs.existsSync(indexFile)) {
142+
console.warn('Warning: arena_registry/index.yaml not found, using empty registry');
143+
return {};
144+
}
145+
146+
const content = fs.readFileSync(indexFile, 'utf8');
147+
const registry = {};
148+
let currentGen = null;
149+
150+
for (const line of content.split('\n')) {
151+
if (line.trim().startsWith('#') || line.trim() === '') continue;
152+
if (line.match(/^version:/)) continue;
153+
154+
// Generation section header (e.g., "G41:" or "G6:")
155+
const sectionMatch = line.match(/^(\w+):$/);
156+
if (sectionMatch) {
157+
// Map YAML keys to generation names: G41 -> G4.1, G4 -> G4, G6 -> G6
158+
const key = sectionMatch[1];
159+
if (key === 'G41') currentGen = 'G4.1';
160+
else currentGen = key;
161+
registry[currentGen] = {};
162+
continue;
163+
}
164+
165+
// Arena ID entry (e.g., " 1: G41_2x12_cw")
166+
const entryMatch = line.match(/^\s+(\d+):\s*(\S+)/);
167+
if (entryMatch && currentGen) {
168+
registry[currentGen][parseInt(entryMatch[1])] = entryMatch[2];
169+
}
170+
}
171+
172+
return registry;
173+
}
174+
138175
// Main
139176
function main() {
140177
const configDir = findConfigDir();
141178
const outputFile = path.join(process.cwd(), 'js', 'arena-configs.js');
142179

143180
console.log(`Reading configs from: ${configDir}`);
144181

182+
// Also find registry directory (sibling of arenas/)
183+
const registryDir = path.join(path.dirname(configDir), 'arena_registry');
184+
const arenaRegistry = parseArenaRegistry(registryDir);
185+
console.log(` Arena registry: ${JSON.stringify(arenaRegistry)}`);
186+
145187
const configs = {};
146188
const files = fs.readdirSync(configDir).filter(f => f.endsWith('.yaml') || f.endsWith('.yml'));
147189

@@ -181,17 +223,88 @@ function main() {
181223
sortedConfigs[key] = configs[key];
182224
});
183225

226+
// Format ARENA_REGISTRY as readable JS
227+
const registryLines = [];
228+
for (const [gen, entries] of Object.entries(arenaRegistry)) {
229+
const items = Object.entries(entries).map(([id, name]) => `${id}: '${name}'`).join(', ');
230+
registryLines.push(` '${gen}': { ${items} }`);
231+
}
232+
const registryStr = registryLines.join(',\n');
233+
184234
// Generate output
185235
const output = `/**
186236
* Arena Configurations
187-
* Auto-generated from maDisplayTools/configs/arenas/
237+
* Auto-generated from maDisplayTools/configs/arenas/ and arena_registry/
188238
* Last updated: ${new Date().toISOString()}
189239
*
190240
* DO NOT EDIT MANUALLY - regenerate with: node scripts/generate-arena-configs.js
191241
*/
192242
193243
const STANDARD_CONFIGS = ${JSON.stringify(sortedConfigs, null, 2)};
194244
245+
// Generation ID registry (from maDisplayTools/configs/arena_registry/generations.yaml)
246+
const GENERATIONS = {
247+
0: { name: 'unspecified', panel_size: null },
248+
1: { name: 'G3', panel_size: 8 },
249+
2: { name: 'G4', panel_size: 16 },
250+
3: { name: 'G4.1', panel_size: 16 },
251+
4: { name: 'G6', panel_size: 20 },
252+
5: { name: 'G5', panel_size: null, deprecated: true }
253+
};
254+
255+
// Arena ID registry — per-generation namespaces (from maDisplayTools/configs/arena_registry/index.yaml)
256+
const ARENA_REGISTRY = {
257+
${registryStr}
258+
};
259+
260+
/**
261+
* Get generation name from ID
262+
* @param {number} id - Generation ID (0-7)
263+
* @returns {string} Generation name or 'unknown'
264+
*/
265+
function getGenerationName(id) {
266+
return GENERATIONS[id] ? GENERATIONS[id].name : 'unknown';
267+
}
268+
269+
/**
270+
* Get generation ID from name
271+
* @param {string} name - Generation name (e.g., 'G6', 'G4.1')
272+
* @returns {number} Generation ID or 0
273+
*/
274+
function getGenerationId(name) {
275+
for (const [id, gen] of Object.entries(GENERATIONS)) {
276+
if (gen.name === name) return parseInt(id);
277+
}
278+
return 0;
279+
}
280+
281+
/**
282+
* Get arena config name from generation and arena ID
283+
* @param {string} generation - Generation name (e.g., 'G6', 'G4')
284+
* @param {number} arenaId - Arena ID
285+
* @returns {string|null} Arena config name or null
286+
*/
287+
function getArenaName(generation, arenaId) {
288+
const genRegistry = ARENA_REGISTRY[generation];
289+
if (!genRegistry) return null;
290+
return genRegistry[arenaId] || null;
291+
}
292+
293+
/**
294+
* Get arena ID from generation and config name
295+
* @param {string} generation - Generation name (e.g., 'G6', 'G4')
296+
* @param {string} arenaName - Arena config name (e.g., 'G6_2x10')
297+
* @returns {number} Arena ID or 0
298+
*/
299+
function getArenaId(generation, arenaName) {
300+
const genRegistry = ARENA_REGISTRY[generation];
301+
if (!genRegistry) return 0;
302+
for (const [id, name] of Object.entries(genRegistry)) {
303+
if (name === arenaName) return parseInt(id);
304+
}
305+
return 0;
306+
}
307+
195308
// Panel specifications by generation
196309
const PANEL_SPECS = {
197310
'G3': {
@@ -251,8 +364,33 @@ function getConfigsByGeneration() {
251364
252365
// Export for both browser and Node.js
253366
if (typeof module !== 'undefined' && module.exports) {
254-
module.exports = { STANDARD_CONFIGS, PANEL_SPECS, getConfig, getConfigsByGeneration };
367+
module.exports = {
368+
STANDARD_CONFIGS, PANEL_SPECS, GENERATIONS, ARENA_REGISTRY,
369+
getConfig, getConfigsByGeneration,
370+
getGenerationName, getGenerationId, getArenaName, getArenaId
371+
};
372+
}
373+
374+
// Browser global export (for non-module scripts)
375+
if (typeof window !== 'undefined') {
376+
window.STANDARD_CONFIGS = STANDARD_CONFIGS;
377+
window.PANEL_SPECS = PANEL_SPECS;
378+
window.GENERATIONS = GENERATIONS;
379+
window.ARENA_REGISTRY = ARENA_REGISTRY;
380+
window.getConfig = getConfig;
381+
window.getConfigsByGeneration = getConfigsByGeneration;
382+
window.getGenerationName = getGenerationName;
383+
window.getGenerationId = getGenerationId;
384+
window.getArenaName = getArenaName;
385+
window.getArenaId = getArenaId;
255386
}
387+
388+
// ES6 module export
389+
export {
390+
STANDARD_CONFIGS, PANEL_SPECS, GENERATIONS, ARENA_REGISTRY,
391+
getConfig, getConfigsByGeneration,
392+
getGenerationName, getGenerationId, getArenaName, getArenaId
393+
};
256394
`;
257395

258396
// Ensure js/ directory exists

0 commit comments

Comments
 (0)