statsEsc = window.statsEsc
statsTable = window.statsTable
fetchParquet = window.fetchParquet
noData = () => html`<p class="text-muted">Data could not be loaded. Try refreshing the page.</p>`
base_url = window.DATA_BASE_URL
t20_batting = fetchParquet(base_url + "cricket/t20-batting.parquet")
t20_bowling = fetchParquet(base_url + "cricket/t20-bowling.parquet")
odi_batting = fetchParquet(base_url + "cricket/odi-batting.parquet")
odi_bowling = fetchParquet(base_url + "cricket/odi-bowling.parquet")
test_batting = fetchParquet(base_url + "cricket/test-batting.parquet")
test_bowling = fetchParquet(base_url + "cricket/test-bowling.parquet")
// Calculate age from DOB string (YYYY-MM-DD)
function addAge(data) {
if (!data) return null
const now = Date.now()
return data.map(r => {
if (!r.dob) return r
const ms = now - new Date(r.dob).getTime()
return { ...r, age: +(ms / 31557600000).toFixed(1) }
})
}
t20_batting_enriched = addAge(t20_batting)
t20_bowling_enriched = addAge(t20_bowling)
odi_batting_enriched = addAge(odi_batting)
odi_bowling_enriched = addAge(odi_bowling)
test_batting_enriched = addAge(test_batting)
test_bowling_enriched = addAge(test_bowling)
posBadge = window.posBadge
batStyleColors = window.cricketStyleMaps.batStyleColors
bowlStyleColors = window.cricketStyleMaps.bowlStyleColors
normBat = window.cricketStyleMaps.normalizeBatStyle
normBowl = window.cricketStyleMaps.normalizeBowlStyle
// Styled country dropdown (OJS-compatible viewof container)
function countrySelect(data) {
if (!data) return html``
if (!window.uiHelpers?.makeSelect) return html``
const countries = ["All countries", ...[...new Set(data.map(d => d.country).filter(Boolean))].sort()]
const { wrap, sel } = window.uiHelpers.makeSelect(countries, "All countries", "Country")
wrap.value = "All countries"
sel.addEventListener("change", () => {
wrap.value = sel.value
wrap.dispatchEvent(new Event("input", { bubbles: true }))
})
return wrap
}
function getCountries(data) {
if (!data) return []
return [...new Set(data.map(d => d.country).filter(Boolean))].sort()
}
function makeBattingConfig(fullData) {
return {
columns: ["player", "batting_style", "age", "scoring_index", "survival_rate", "balls_faced"],
header: {
player: "Player",
batting_style: "Bat",
age: "Age",
scoring_index: "Scoring",
survival_rate: "Survival",
balls_faced: "BF"
},
groups: [
{ label: "Player", span: 3 },
{ label: "Rating", span: 2 },
{ label: "", span: 1 }
],
format: {
scoring_index: x => x?.toFixed(4) ?? "",
survival_rate: x => x?.toFixed(4) ?? "",
balls_faced: x => x?.toLocaleString() ?? "",
age: x => x?.toFixed(1) ?? ""
},
render: {
player: (v, row) => {
const name = row.full_name || v
const href = `player.html#name=${encodeURIComponent(name)}`
const sub = `<span class="player-sub">${statsEsc(row.country || "")}</span>`
return `<a href="${href}" class="player-link"><strong>${statsEsc(name)}</strong>${sub}</a>`
},
batting_style: (v) => posBadge(normBat(v), batStyleColors)
},
heatmap: {
scoring_index: "high-good",
survival_rate: "high-good"
},
heatmapData: fullData,
filters: {
scoring_index: "range",
balls_faced: "range",
age: "range"
},
sort: "scoring_index",
reverse: true,
rows: 20
}
}
function makeBowlingConfig(fullData) {
return {
columns: ["player", "bowling_style", "age", "economy_index", "strike_rate", "balls_bowled"],
header: {
player: "Player",
bowling_style: "Bowl",
age: "Age",
economy_index: "Economy",
strike_rate: "Strike Rate",
balls_bowled: "BB"
},
groups: [
{ label: "Player", span: 3 },
{ label: "Rating", span: 2 },
{ label: "", span: 1 }
],
format: {
economy_index: x => x?.toFixed(4) ?? "",
strike_rate: x => x?.toFixed(4) ?? "",
balls_bowled: x => x?.toLocaleString() ?? "",
age: x => x?.toFixed(1) ?? ""
},
render: {
player: (v, row) => {
const name = row.full_name || v
const href = `player.html#name=${encodeURIComponent(name)}`
const sub = `<span class="player-sub">${statsEsc(row.country || "")}</span>`
return `<a href="${href}" class="player-link"><strong>${statsEsc(name)}</strong>${sub}</a>`
},
bowling_style: (v) => posBadge(normBowl(v), bowlStyleColors)
},
heatmap: {
economy_index: "low-good",
strike_rate: "low-good"
},
heatmapData: fullData,
filters: {
economy_index: "range",
balls_bowled: "range",
age: "range"
},
sort: "economy_index",
rows: 20
}
}