import { readFileSync } from 'node:fs'; const cards = JSON.parse(readFileSync('data/cards.json', 'utf8')).cards; const rogueClasses = new Set(['rogue', 'thief', 'thiefmaster', 'assassin', 'hermit']); const mapleSkillCards = { DoubleStab: '더블 스탭', LuckySeven: '럭키 세븐', Haste: '헤이스트', DarkSight: '다크 사이트', FlashJump: '플래시 점프', NimbleBody: '님블 바디', SavageBlow: '새비지 블로우', CriticalEdge: '크리티컬 엣지', Steal: '스틸', DaggerAcceleration: '대거 액셀레이션', Karma: '카르마', DaggerMastery: '대거 마스터리', PhysicalTraining: '피지컬 트레이닝', ShieldMastery: '실드 마스터리', ThiefAgility: '시프 어질리티', EdgeCarnival: '엣지 카니발', MuspelHeim: '무스펠 하임', MesoExplosion: '메소 익스플로젼', DarkFlare: '다크 플레어', PickPocket: '픽 파킷', ShadowPartner: '쉐도우 파트너', AdvancedDarkSight: '어드밴스드 다크 사이트', IntoDarkness: '인투 다크니스', Venom: '베놈', Grid: '그리드', RadicalDarkness: '래디컬 다크니스', ShurikenBurst: '슈리켄 버스트', WindTalisman: '윈드 탈리스만', MarkOfAssassin: '마크 오브 어쌔신', ShadowRush: '쉐도우 러쉬', ShadowLeap: '쉐도우 리프', ShadowBlink: '쉐도우 블링크', JavelinMastery: '자벨린 마스터리', JavelinAcceleration: '자벨린 액셀레이션', CriticalThrow: '크리티컬 스로우', AssassinPhysicalTraining: '피지컬 트레이닝', TripleThrow: '트리플 스로우', ShurikenChallenge: '슈리켄 챌린지', HermitDarkFlare: '다크 플레어', HermitShadowPartner: '쉐도우 파트너', SpiritJavelin: '스피릿 자벨린', HermitRadicalDarkness: '래디컬 다크니스', HermitVenom: '베놈', SkilledJavelin: '숙련된 표창술', HermitAdrenaline: '아드레날린', }; const errors = []; for (const [id, expectedName] of Object.entries(mapleSkillCards)) { if (!cards[id]) errors.push(`원본 스킬 카드 없음: ${id}`); else if (cards[id].name !== expectedName) errors.push(`원본 스킬명 변경: ${id} (${cards[id].name} != ${expectedName})`); } const customCards = Object.entries(cards).filter(([id, card]) => rogueClasses.has(card.class) && !mapleSkillCards[id]); if (customCards.length !== 78) errors.push(`도적 비스킬 카드 수 불일치: ${customCards.length} != 78`); const names = new Map(); for (const [id, card] of Object.entries(cards)) { if (!names.has(card.name)) names.set(card.name, []); names.get(card.name).push(id); } const nonRogueNames = new Set(Object.values(cards).filter((card) => !rogueClasses.has(card.class) && card.class !== 'shiv').map((card) => card.name)); for (const [id, card] of customCards) { const sameNameIds = names.get(card.name) || []; if (sameNameIds.length > 1) errors.push(`비스킬 카드명 중복: ${id} ${card.name} (${sameNameIds.join(', ')})`); if (nonRogueNames.has(card.name)) errors.push(`다른 직업 카드명 충돌: ${id} ${card.name}`); } console.log(`메이플 원본 스킬명 고정 ${Object.keys(mapleSkillCards).length}장 | 도적 비스킬 고유 이름 ${customCards.length}장`); if (errors.length > 0) { for (const error of errors) console.error(`ERROR: ${error}`); process.exitCode = 1; } else { console.log('RESULT: 도적 카드 이름 규칙 이상 0'); }