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
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(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
}
})