deckhearth/lib/deck-builder-stats.js
Randall Stillwell 4645095105 refactor(deck-builder): extract stats lib and stats bar (Brief 1)
Move Commander basic-land checks and deck aggregate metrics into
lib/deck-builder-stats.js with unit tests; render the summary row via
DeckBuilderStatsBar to shrink the page god-component.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-03 17:11:32 -05:00

47 lines
1.4 KiB
JavaScript

/** 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 };
}