function setMatchStats(stats, selection, containerWidth, containerHeight) {
const margin = { top: 0, right: 20, bottom: 20, left: 20 };
const chartWidth = containerWidth - margin.left - margin.right;
const chartHeight = containerHeight - margin.top - margin.bottom;
const colorTeam1 = getColorByCountry(stats.metadata.nameTeam1);
const colorTeam2 = getColorByCountry(stats.metadata.nameTeam2);
const invColorTeam1 = getInverseColor(colorTeam1, 0.5);
const invColorTeam2 = getInverseColor(colorTeam2, 0.5);
stats.data.unshift(
{Metric: "datetime-category"},
{Metric: "names"},
{Metric: "score"}
)
const xScale = d3.scaleLinear().domain([-1, 1]).range([0, chartWidth]);
const yScale = d3
.scaleBand()
.domain(stats.data.map((d) => d.Metric))
.range([0.5, chartHeight])
.padding(0.6);
const denormalise = (d, total) => total * d;
const numFormatWrapper = (val, numType) => {
if (numType === "percentage") {
return d3.format(".1%")(val/100);
} else if (numType === "integer") {
return Math.round(val);
} else if (numType === "float") {
return d3.format(".1")(val);
} else {
return val;
}
}
const lrWrapper = (countryName, left) => {
const emojiStr = getWinnersEmoji(countryName)
if (emojiStr.length == 0) {
return countryName;
} else if (left) {
return `${emojiStr} ${countryName}`;
} else {
return `${countryName} ${emojiStr}`;
}
}
// get main SVG container
const svg = selection
.append("svg")
.attr("width", containerWidth)
.attr("height", containerHeight);
// Create a group for the chart
const chart = svg
.append("g")
.attr("transform", `translate(${margin.left}, ${margin.top})`);
// add category and datetime
chart
.append("text")
.attr("class", "datetime-cat-stats")
.attr("x", d => (xScale(-1)) )
.attr("y", d => yScale(stats.data[0].Metric))
.attr("text-anchor", "start")
.attr("alignment-baseline", "middle")
.text(stats.metadata.category);
chart
.append("text")
.attr("class", "datetime-cat-stats")
.attr("x", d => (xScale(1)))
.attr("y", d => yScale(stats.data[0].Metric))
.attr("text-anchor", "end")
.attr("alignment-baseline", "middle")
.text(`${stats.metadata.date} - ${stats.metadata.hour}`);
// add country names
chart
.append("text")
.attr("class", "title-stats")
.attr("x", d => (xScale(0 - 0.5)) )
.attr("y", d => yScale(stats.data[1].Metric))
.attr("text-anchor", "middle")
.attr("alignment-baseline", "middle")
.attr("fill", colorTeam1)
.text(lrWrapper(stats.metadata.nameTeam1, true));
chart
.append("text")
.attr("class", "title-stats")
.attr("x", d => (xScale(0 + 0.5)))
.attr("y", d => yScale(stats.data[1].Metric))
.attr("text-anchor", "middle")
.attr("alignment-baseline", "middle")
.attr("fill", colorTeam2)
.text(lrWrapper(stats.metadata.nameTeam2));
// add scores
const [scoreTeam1, scoreTeam2] = stats.metadata.score
chart
.append("text")
.attr("class", "score-stats")
.attr("x", d => (xScale(0) - 10))
.attr("y", d => yScale(stats.data[2].Metric))
.attr("text-anchor", "end")
.attr("alignment-baseline", "middle")
.text(scoreTeam1);
chart
.append("text")
.attr("class", "score-stats")
.attr("x", d => (xScale(0)))
.attr("y", d => yScale(stats.data[2].Metric))
.attr("text-anchor", "middle")
.attr("alignment-baseline", "middle")
.attr("fill", "white")
.text("-");
chart
.append("text")
.attr("class", "score-stats")
.attr("x", d => (xScale(0) + 10))
.attr("y", d => yScale(stats.data[2].Metric))
.attr("text-anchor", "start")
.attr("alignment-baseline", "middle")
.text(scoreTeam2);
// remove non-barplot stuff
stats.data.shift() // datetime-category
stats.data.shift() // names
stats.data.shift() // score
// Create the bars
const lbars = chart
.selectAll("team1-rect")
.data(stats.data)
.enter()
.append("rect")
.attr("class", "bar rect-stats")
.attr("x", d => xScale(0 - d.team1))
.attr("y", d => yScale(d.Metric))
.attr("width", d => Math.abs(xScale(d.team1) - xScale(0)))
.attr("height", yScale.bandwidth())
.attr("fill", colorTeam1);
const rbars = chart
.selectAll("team2-rect")
.data(stats.data)
.enter()
.append("rect")
.attr("class", "bar rect-stats")
.attr("x", d => xScale(0))
.attr("y", d => yScale(d.Metric))
.attr("width", d => Math.abs(xScale(d.team2) - xScale(0)))
.attr("height", yScale.bandwidth())
.attr("fill", colorTeam2);
// Add metric labels
chart
.selectAll(".metric-label")
.data(stats.data)
.enter()
.append("text")
.attr("class", "text-rect-stats")
.attr("x", d => (xScale(0)))
.attr("y", d => yScale(d.Metric) - yScale.bandwidth() / 2)
.attr("text-anchor", "middle")
.attr("alignment-baseline", "middle")
.attr("fill", "white")
.text(d => d.Metric);
// Add labels for team1 values
chart
.selectAll(".team1-label")
.data(stats.data)
.enter()
.append("text")
.attr("class", "text-rect-stats")
.attr("x", d => (xScale(0)) - 10)
.attr("y", d => yScale(d.Metric) + yScale.bandwidth() / 1.75)
.attr("text-anchor", "end")
.attr("alignment-baseline", "middle")
.attr("fill", invColorTeam1)
.text(d => numFormatWrapper(denormalise(d.team1, d.total), d.numType));
// Add labels for team2 values
chart
.selectAll(".metric-label")
.data(stats.data)
.enter()
.append("text")
.attr("class", "text-rect-stats")
.attr("x", d => (xScale(0)) + 10)
.attr("y", d => yScale(d.Metric) + yScale.bandwidth() / 1.75)
.attr("text-anchor", "start")
.attr("alignment-baseline", "middle")
.attr("fill", invColorTeam2)
.text(d => numFormatWrapper(denormalise(d.team2, d.total), d.numType));
return svg.node();
}