/** Basic land names for Commander singleton rule checks. */ export const BASIC_LAND_NAMES = ['Plains', 'Island', 'Swamp', 'Mountain', 'Forest']; export function isBasicLand(card) { return BASIC_LAND_NAMES.includes(card.name); } /** * Aggregate deck list metrics from deck card rows (quantity-weighted). * @param {Array<{ quantity: number, cmc?: number, colors?: string, card_type?: string }>} deckCards */ export function computeDeckStats(deckCards) { const totalCards = deckCards.reduce((sum, card) => sum + card.quantity, 0); const avgCmc = deckCards.length > 0 ? ( deckCards.reduce((sum, card) => sum + (card.cmc || 0) * card.quantity, 0) / totalCards ).toFixed(1) : 0; const colorCounts = deckCards.reduce((counts, card) => { if (card.colors) { try { const colors = JSON.parse(card.colors); colors.forEach((color) => { counts[color] = (counts[color] || 0) + card.quantity; }); } catch { // Handle non-JSON color format } } return counts; }, {}); const typeCounts = deckCards.reduce((counts, card) => { if (card.card_type) { const types = card.card_type.split(' — ')[0].split(' '); types.forEach((type) => { counts[type] = (counts[type] || 0) + card.quantity; }); } return counts; }, {}); return { totalCards, avgCmc, colorCounts, typeCounts }; }