동일 번호 카드가 많은 시리즈에서도 선택한 카드가 정확히 복원되도록 저장·검증·복원 흐름을 imgSrc 중심으로 정리하고, 이미지 누락 시 공통 뒷면 폴백을 적용한다. Co-authored-by: Cursor <cursoragent@cursor.com>
79 lines
2.2 KiB
JavaScript
79 lines
2.2 KiB
JavaScript
import { pathToFileURL } from 'url';
|
|
import path from 'path';
|
|
|
|
/**
|
|
* @typedef {object} CardIndex
|
|
* @property {Map<string, object>} byNumber
|
|
* @property {Map<string, object>} byImgSrc
|
|
*/
|
|
|
|
/** @type {Map<string, CardIndex>} */
|
|
const cache = new Map();
|
|
|
|
/**
|
|
* 시리즈 카드 인덱스 로드
|
|
* @param {string} seriesKey
|
|
* @returns {Promise<CardIndex>}
|
|
*/
|
|
export async function getCardMap(seriesKey) {
|
|
if (cache.has(seriesKey)) {
|
|
return cache.get(seriesKey);
|
|
}
|
|
|
|
const datasPath = process.env.DATAS_PATH || path.join(process.cwd(), '..', 'datas');
|
|
const filePath = path.join(datasPath, `${seriesKey}.js`);
|
|
|
|
let mod;
|
|
try {
|
|
mod = await import(pathToFileURL(filePath).href);
|
|
} catch {
|
|
throw new Error(`시리즈 데이터를 찾을 수 없습니다: ${seriesKey}`);
|
|
}
|
|
|
|
const byNumber = new Map();
|
|
const byImgSrc = new Map();
|
|
for (const card of mod.cardList) {
|
|
if (!byNumber.has(card.Number)) {
|
|
byNumber.set(card.Number, card);
|
|
}
|
|
if (card.imgSrc && !byImgSrc.has(card.imgSrc)) {
|
|
byImgSrc.set(card.imgSrc, card);
|
|
}
|
|
}
|
|
|
|
const index = { byNumber, byImgSrc };
|
|
cache.set(seriesKey, index);
|
|
return index;
|
|
}
|
|
|
|
/**
|
|
* 저장된 덱 카드를 풀 카드 객체로 합성
|
|
* @param {string} seriesKey
|
|
* @param {Array<{number?: string, imgSrc?: string, count: number, key: boolean}>} cards
|
|
* @returns {Promise<{cards: object[], totalCards: number}>}
|
|
*/
|
|
export async function resolveDeckCards(seriesKey, cards) {
|
|
const index = await getCardMap(seriesKey);
|
|
const resolved = [];
|
|
let totalCards = 0;
|
|
|
|
for (const item of cards) {
|
|
const base = (item.imgSrc && index.byImgSrc.get(item.imgSrc)) || index.byNumber.get(item.number);
|
|
if (!base) continue;
|
|
|
|
totalCards += item.count;
|
|
resolved.push({
|
|
number: base.Number,
|
|
count: item.count,
|
|
key: item.key,
|
|
imgSrc: base.imgSrc,
|
|
color: base.color,
|
|
rarity: base.rarity,
|
|
trigger: base.trigger ?? null,
|
|
parallel: Boolean(base.parallel),
|
|
});
|
|
}
|
|
|
|
return { cards: resolved, totalCards };
|
|
}
|