ManaDash logo ManaDash logo ManaDash
  • Home
  • Archetypes
  • Decktypes
  • Players
  • Elo
  • Deck Viewer
  • Cards Stats
  • Card Groups
  • Card Impact
  • Standings
Players
  • Main Content
archetypeCountsData = transpose(player_archetype_counts)
decktypeCountsData = transpose(player_decktype_counts)
playerStatsData = transpose(player_stats)
playerVsData = transpose(player_vs_stats)
mostPlayedCardsData = transpose(most_played_cards)
archetypeWinrateData = transpose(player_archetype_winrate)
decktypeWinrateData = transpose(player_decktype_winrate)
cardWinrateData = transpose(player_card_winrate)
function forSelection(rows) {
  return rows.filter(d =>
    d.player === player && (d.season_id === undefined || d.season_id === season)
  );
}

pct = d => (d == null || isNaN(d)) ? "" : (d * 100).toFixed(1) + "%"
pctRaw = d => (d == null || isNaN(d)) ? "" : d.toFixed(1) + "%"
num = d => (d == null || isNaN(d)) ? "" : d3.format(".2f")(d)
// Sorts descending by `y`, optionally keeps the top `top` rows, and draws a bar
// chart. `rule` adds the 50% reference line.
function barChart(data, {x, y, yLabel, colors, top, rule = false, yMin,
                        height = 700, fontSize = 28, wrap = true} = {}) {
  const rows = data
    .filter(d => d.season_id === season)
    .sort((a, b) => d3.descending(a[y], b[y]))
    .slice(0, top ?? Infinity);

  const label = s => String(s).replace(/[_\s]+/g, "\n");
  const lines = wrap ? d3.max(rows, d => label(d[x]).split("\n").length) : 1;
  const rotate = wrap ? 0 : (rows.length > 12 ? -45 : 0);

  return Plot.plot({
    width,
    height,
    marginBottom: rotate ? height * 0.31
                : wrap ? fontSize * 1.2 * lines + 24
                : height * 0.16,
    marginLeft: fontSize * 2.5,
    style: {fontSize: `${fontSize}px`},
    x: {
      label: null,
      domain: rows.map(d => d[x]),
      ticks: rows.map(d => d[x]),
      tickFormat: wrap ? label : undefined,
      tickRotate: rotate,
      tickPadding: 8
    },
    y: {
      label: yLabel,
      labelArrow: "none",
      labelAnchor: "center",
      labelOffset: fontSize * 2.5,
      ticks: 5,
      grid: true,
      domain: yMin === undefined ? undefined : [yMin, d3.max(rows, d => d[y])]
    },
    color: {domain: Object.keys(colors), range: Object.values(colors)},
    marks: [
      Plot.barY(rows, {x, y, fill: x, tip: true}),
      rule ? Plot.ruleY([0.5], {
        stroke: "gray", strokeDasharray: "4,4", strokeOpacity: 0.5
      }) : null
    ]
  });
}
// Replaces the Dash DataTable: a search box plus a sortable, paged table.
function searchTable(rows, options = {}) {
  const search = Inputs.search(rows, {placeholder: "Filter rows…"});
  const out = document.createElement("div");

  const render = () => out.replaceChildren(
    Inputs.table(search.value, {layout: "auto", ...options})
  );

  search.addEventListener("input", render);
  render();

  const wrapper = document.createElement("div");
  wrapper.style.width = "100%";
  wrapper.style.height = "100%";
  wrapper.style.display = "flex";
  wrapper.style.flexDirection = "column";

  out.style.flex = "1";
  out.style.minHeight = "0";
  out.style.overflow = "auto";

  wrapper.append(search, out);
  return wrapper;
}
Archetypes
barChart(forSelection(archetypeCountsData), {
  x: "archetype",
  y: "arche_types_count",
  yLabel: "Count",
  colors: archetype_color_map
})
Decktypes
barChart(forSelection(decktypeCountsData), {
  x: "decktype",
  y: "deck_types_count",
  yLabel: "Count",
  colors: decktype_color_map
})
  • Player Statistics Overview
  • Player Versus Overview
  • Most Played Cards
  • Archetype Winrates
  • Decktype Winrates
  • Card Winrate Per Season
searchTable(forSelection(playerStatsData), {
  header: {
    season_id: "Season",
    player: "Player",
    games_played: "Drafts Attended",
    total_wins: "Drafts Won",
    total_points: "Total Points",
    avg_points_per_draft: "Average Points",
    most_common_archetype: "Most Common Archetype",
    most_common_decktype: "Most Common Decktype",
    average_omp: "Average OMP",
    average_gwp: "Average GWP",
    average_ogp: "Average OGP"
  },
  format: {
    avg_points_per_draft: num,
    average_omp: pctRaw,
    average_gwp: pctRaw,
    average_ogp: pctRaw
  }
})
searchTable(forSelection(playerVsData), {
  header: {
    season_id: "Season",
    player: "Player",
    opponent: "Opponent",
    games_played_vs: "Games Played VS",
    games_won_vs: "Games Won VS",
    game_win_rate_vs: "Game Win Rate",
    matches_played_vs: "Matches Played",
    matches_won_vs: "Matches Won",
    match_win_rate_vs: "Match Win Rate"
  },
  format: {
    game_win_rate_vs: pct,
    match_win_rate_vs: pct
  }
})
searchTable(forSelection(mostPlayedCardsData), {
  header: {
    season_id: "Season",
    player: "Player",
    card_name: "Card Name",
    pick_count: "Pick Count"
  }
})
searchTable(forSelection(archetypeWinrateData), {
  header: {
    season_id: "Season",
    player: "Player",
    archetype: "Archetype",
    archtype: "Archetype",
    games_won: "Games Won",
    games_played: "Games Played",
    game_win_rate: "Game Win Rate",
    matches_played: "Matches Played",
    matches_won: "Matches Won",
    match_win_rate: "Match Win Rate"
  },
  format: {
    game_win_rate: pct,
    match_win_rate: pct
  }
})
searchTable(forSelection(decktypeWinrateData), {
  header: {
    season_id: "Season",
    player: "Player",
    decktype: "Decktype",
    games_won: "Games Won",
    games_played: "Games Played",
    game_win_rate: "Game Win Rate",
    matches_played: "Matches Played",
    matches_won: "Matches Won",
    match_win_rate: "Match Win Rate"
  },
  format: {
    game_win_rate: pct,
    match_win_rate: pct
  }
})
searchTable(forSelection(cardWinrateData), {
  header: {
    season_id: "Season",
    player: "Player",
    card_name: "Card Name",
    num_drafts_with_card: "Drafts with Card",
    games_won: "Games Won",
    games_played: "Games Played",
    game_win_rate: "Game Win Rate",
    matches_played: "Matches Played",
    matches_won: "Matches Won",
    match_win_rate: "Match Win Rate"
  },
  format: {
    game_win_rate: pct,
    match_win_rate: pct
  }
})
viewof player = Inputs.select(players, {
  label: "Player",
  value: players[0]
})
viewof season = Inputs.select(seasons, {
  label: "Season",
  value: seasons[0]
})
 

ManaDash — Vintage Cube Analysis