Creatures
Non-Creatures
Nonbasic Lands
viewof playerPick = Inputs.select(
playersData.map(d => d.player),
{
label: "Player",
value: playersData[0]?.player
}
)
viewof deckPick = Inputs.select(
playerDecks.map(d => `${d.deck_id}|${d.draft_id}`),
{
label: "Deck",
format: key => {
const d = deckByKey.get(key);
return d ? `${d.deck_id} (${d.season_draft_label})` : key;
},
value: playerDecks[0] ? `${playerDecks[0].deck_id}|${playerDecks[0].draft_id}` : null
}
)selectedCards = {
if (!selectedDeck) return [];
const seen = new Set();
return deckCardsData
.filter(d =>
d.deck_id === selectedDeck.deck_id &&
d.draft_id === selectedDeck.draft_id
)
.map(d => cardByName.get(d.card_name))
.filter(d => {
if (!d || seen.has(d.card_name)) return false;
seen.add(d.card_name);
return true;
})
.sort((a, b) => d3.ascending(a.card_name, b.card_name));
}CMC_KEYS = ["0", "1", "2", "3", "4", "5+"]
bucket = c => c.cmc >= 5 ? "5+" : String(Math.trunc(c.cmc || 0))
cardGrid = cards => {
const root = document.createElement("div");
root.className = "cmc-grid";
if (!cards.length) {
root.innerHTML = `<p class="text-muted">No cards.</p>`;
return root;
}
const groups = d3.group(cards, bucket);
for (const k of CMC_KEYS) {
const group = groups.get(k);
if (!group) continue;
const column = document.createElement("div");
const header = document.createElement("div");
header.className = "cmc-col-head";
header.textContent = `CMC ${k} · ${group.length}`;
const stack = document.createElement("div");
stack.className = "card-stack";
for (const c of group) {
const img = document.createElement("img");
img.src = c.image_src;
img.alt = c.card_name;
img.title = c.card_name;
img.loading = "lazy";
stack.appendChild(img);
}
column.appendChild(header);
column.appendChild(stack);
root.appendChild(column);
}
return root;
};selectedDeck === undefined
? html`<p class="text-muted">Select a deck.</p>`
: html`
<div class="stat-grid">
<div class="stat-item">
<div class="stat-label">Archetype</div>
<div class="stat-value">${selectedDeck.archetype ?? "—"}</div>
</div>
<div class="stat-item">
<div class="stat-label">Deck Type</div>
<div class="stat-value">${selectedDeck.decktype ?? "—"}</div>
</div>
<div class="stat-item">
<div class="stat-label">Deck Color</div>
<div class="stat-value">${selectedDeck.deck_color_short ?? "—"}</div>
</div>
<div class="stat-item">
<div class="stat-label">Match Points</div>
<div class="stat-value">${selectedDeck.match_points ?? "—"}</div>
</div>
<div class="stat-item">
<div class="stat-label">Standing</div>
<div class="stat-value">${selectedDeck.standing ?? "—"}</div>
</div>
<div class="stat-item">
<div class="stat-label">Average CMC</div>
<div class="stat-value">${d3.format(".2f")(selectedDeck.avg_cmc ?? 0)}</div>
</div>
<div class="stat-item">
<div class="stat-label">Creatures</div>
<div class="stat-value">${selectedDeck.n_creatures ?? 0}</div>
</div>
<div class="stat-item">
<div class="stat-label">Non-Creatures</div>
<div class="stat-value">${selectedDeck.n_noncreatures ?? 0}</div>
</div>
<div class="stat-item">
<div class="stat-label">Nonbasic Lands</div>
<div class="stat-value">${selectedDeck.n_lands ?? 0}</div>
</div>
</div>
`