48 lines
1.4 KiB
JavaScript
48 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 };
|
||
|
|
}
|