ManaDash logo ManaDash logo ManaDash
  • Home
  • Archetypes
  • Decktypes
  • Players
  • Elo
  • Deck Viewer
  • Cards Stats
  • Card Groups
  • Card Impact
  • Standings
Deck Viewer
  • Main Content
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
  }
)
playersData = transpose(players)
deckIndexData = transpose(deck_index)
deckCardsData = transpose(deck_cards)
cardMetaData = transpose(card_meta)
cardByName = new Map(cardMetaData.map(d => [d.card_name, d]))
deckByKey = new Map(
  deckIndexData.map(d => [`${d.deck_id}|${d.draft_id}`, d])
)
// Rebuilds when the player changes, which re-creates the deck select.
playerDecks = deckIndexData.filter(d => d.player === playerPick)
selectedDeck = deckByKey.get(deckPick)
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>
    `
Creatures
cardGrid(selectedCards.filter(c => c.is_creature && !c.is_land))
Non-Creatures
cardGrid(selectedCards.filter(c => !c.is_creature && !c.is_land))
Nonbasic Lands
cardGrid(selectedCards.filter(c => c.is_land))
 

ManaDash — Vintage Cube Analysis