const SNAPSHOT_FIELDS = [ 'cardId', 'chapterId', 'chapterNumber', 'chapterTitle', 'characterName', 'eraLine', 'tableEcho', 'lifeAction', 'familyLine', 'eraObject', ] function cleanSnapshot(source = {}) { return SNAPSHOT_FIELDS.reduce((snapshot, field) => { const value = source[field] if (field === 'chapterNumber') { const number = Number(value) if (number > 0) snapshot[field] = number } else if (typeof value === 'string' && value.trim()) { snapshot[field] = value.trim() } return snapshot }, {}) } function normalizeProgress(progress) { const next = progress && typeof progress === 'object' ? { ...progress } : {} next.collectedMemoryCards = Array.isArray(next.collectedMemoryCards) ? [...new Set(next.collectedMemoryCards.filter((id) => typeof id === 'string' && id))] : [] next.memoryCardSnapshots = next.memoryCardSnapshots && typeof next.memoryCardSnapshots === 'object' && !Array.isArray(next.memoryCardSnapshots) ? { ...next.memoryCardSnapshots } : {} return next } function addMemoryCard(progress, card, chapter = {}) { const next = normalizeProgress(progress) if (!card || !card.cardId) return next const snapshot = cleanSnapshot({ ...chapter, ...card, chapterId: chapter.chapterId || card.chapterId, chapterNumber: chapter.chapterNumber || card.chapterNumber, chapterTitle: chapter.chapterTitle || chapter.title || card.chapterTitle, }) if (!snapshot.cardId) return next if (!next.collectedMemoryCards.includes(snapshot.cardId)) { next.collectedMemoryCards.push(snapshot.cardId) } next.memoryCardSnapshots[snapshot.cardId] = snapshot return next } function getCollectedMemories(progress, catalog = []) { const normalized = normalizeProgress(progress) const catalogById = (Array.isArray(catalog) ? catalog : []).reduce( (map, card) => { if (card && card.cardId) map[card.cardId] = cleanSnapshot(card) return map }, {}, ) return normalized.collectedMemoryCards .map((cardId) => { const fallback = catalogById[cardId] || {} const saved = cleanSnapshot(normalized.memoryCardSnapshots[cardId] || {}) const card = cleanSnapshot({ ...fallback, ...saved, cardId }) return card.chapterNumber ? card : null }) .filter(Boolean) .sort((a, b) => a.chapterNumber - b.chapterNumber) } module.exports = { addMemoryCard, cleanSnapshot, getCollectedMemories, normalizeProgress, }