Skip to content

Instantly share code, notes, and snippets.

@puripant
Forked from syntagmatic/.block
Last active February 14, 2024 13:09
Show Gist options
  • Save puripant/857f1981667e8b42da2c72328ba94ead to your computer and use it in GitHub Desktop.
Save puripant/857f1981667e8b42da2c72328ba94ead to your computer and use it in GitHub Desktop.
Gold Medal Ranking in SEA Games since 1959
license: gpl-3.0

A bump chart for gold medals in Southeast Asian Games, just like the Olympic Games but for the region of Southeast Asia. In the recent years, there is a criticism that host countries (marked in circles) often won the most (or the second most) gold medals. Only the top 5 countries with the most accumulative gold medals are highlighted in colors.

The data are manually compiled from each page of the games in Wikipedia. Due to previous political situations in the countries in this region, many have changed their names, such as Burma to Myanmar, Malaya to Malaysia, and Cambodia to Khmer Republic. Some skipped a few games. Or a portion of the country as known now such as South Vietnam was represented in some games. The games itself was called Southeast Asian Peninsular Games from 1959 to 1975. This visualization uses the current names and tries to match any regions formerly known otherwise to their closest names. Please report any errors if you find one.

<html>
<head>
<meta charset="utf-8">
<title>Gold Medal Ranking in SEA Games since 1959</title>
<link href="main.css" rel="stylesheet">
</head>
<body>
<canvas></canvas>
<svg></svg>
<script src="https://d3js.org/d3.v4.min.js"></script>
<!-- <script src="https://d3js.org/d3-scale-chromatic.v1.min.js"></script> -->
<script src="main.js"></script>
</body>
</html>
body {
background: #fff;
font: 12px sans-serif;
}
svg,
canvas {
position: absolute;
}
.axis path,
.axis line {
fill: none;
stroke: #d0d0d0;
}
.x.axis .tick text {
font: 10px sans-serif;
fill: #555;
}
.guide {
stroke: #555;
}
var num = 11;
var numTop = 5;
var margin = {top: 35, right: 70, bottom: 30, left: 70};
var width = 950,
height = 500;
var devicePixelRatio = window.devicePixelRatio || 1;
var canvas = d3.select("canvas")
.attr("width", width * devicePixelRatio)
.attr("height", height * devicePixelRatio)
.style("width", width + "px")
.style("height", height + "px");
var svg = d3.select("svg")
.style("width", width + "px")
.style("height", height + "px");
var color = d3.scaleOrdinal()
.range(["#DB7F85", "#50AB84", "#4C6C86", "#C47DCB", "#B59248", "#DD6CA7", "#E15E5A", "#5DA5B3", "#725D82", "#54AF52", "#954D56"]);
var xscale = d3.scaleLinear()
.domain([1959, 2021])
.range([margin.left, width-margin.right]);
var xaxis = d3.axisBottom()
.scale(xscale)
.tickFormat(d3.format(""));
var xaxis2 = d3.axisTop()
.scale(xscale)
.tickFormat(d3.format(""));
var yscale = d3.scaleLinear()
.domain([0-0.2, num-0.5])
.range([margin.top, height-margin.bottom]);
var radius = d3.scaleSqrt()
.domain([0,0.1])
.range([0,4]);
d3.csv("medals.csv", function(error, data) {
var hostCountries = {}; // Find host countries by year
data.forEach(function(d) {
d.gold = +d.gold;
d.year = +d.year;
if (d.host === "y") {
hostCountries[d.year] = d.name;
}
});
var years = Object.keys(hostCountries).map(function(d) {return +d;});
xaxis.tickValues(years);
xaxis2.tickValues(years);
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + (height-margin.bottom) + ")")
.call(xaxis);
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + (margin.top-10) + ")")
.call(xaxis2);
// Vertical guide line
var hiddenMargin = 100;
var highlightedYear;
var verticalGuide = svg.append("line")
.attr("class", "guide")
.attr("x1", -hiddenMargin)
.attr("y1", margin.top - 10)
.attr("x2", -hiddenMargin)
.attr("y2", height - margin.bottom)
.style("stroke-width", function() { return xscale(2) - xscale(0); }) //two year interval
.style("opacity", 0);
var mouseTrap = svg.append("rect")
.attr("width", width)
.attr("height", height)
.style("opacity", 0)
.on("mouseover", function() { verticalGuide.style("opacity", 0.1); })
.on("mouseout", function() { verticalGuide.style("opacity", 0); })
.on("mousemove", function() {
var mousex = d3.mouse(this)[0]
var x = xscale.invert(mousex);
var found = false;
for (var i = 0; i < years.length; i++) {
if (Math.abs(years[i] - x) <= 1) { // game interval (2 years) in half
highlightedYear = years[i];
found = true;
break;
}
}
if (!found) {
highlightedYear = undefined;
}
mouseTrap.style("cursor", highlightedYear? "pointer":"auto");
verticalGuide.attr("transform", "translate(" + (xscale(highlightedYear)+hiddenMargin) + ", 0)");
})
.on("click", function() {
if (highlightedYear) {
var url = "https://en.wikipedia.org/wiki/" + highlightedYear + ((highlightedYear <= 1975) ? "_Southeast_Asian_Peninsular_Games":"_Southeast_Asian_Games");
window.open(url, "_blank");
}
});
// nest by name and rank by total popularity
var nested = d3.nest()
.key(function(d) { return d.name; })
.rollup(function(leaves) {
return {
data: leaves,
sum: d3.sum(leaves, function(d) { return d.gold; })
};
})
.entries(data)
.sort(function(a, b) { return d3.descending(a.value.sum, b.value.sum); })
var topnames = nested.slice(0, num).map(function(d) { return d.key; });
data = data.filter(function(d) {
return topnames.indexOf(d.name) > -1;
});
// nest by name and rank by total popularity
window.byYear = {}
d3.nest()
.key(function(d) { return d.year; })
.key(function(d) { return d.name; })
// .sortValues(function(a, b) { return a.gold - b.gold; })
.rollup(function(leaves,i) {
return leaves[0].gold;
})
.entries(data)
.forEach(function(year) {
byYear[year.key] = {};
year.values
.sort(function(a, b) { return d3.descending(a.value, b.value); })
.forEach(function(name, i) {
byYear[year.key][name.key] = i;
});
});
// window.byName = {};
// d3.nest()
// .key(function(d) { return d.name; })
// .key(function(d) { return d.year; })
// .rollup(function(leaves,i) {
// return leaves[0].gold;
// })
// .entries(data)
// .forEach(function(name) {
// byName[name.key] = [];
// name.values
// .forEach(function(year) {
// byName[name.key].push(year.value);
// });
// });
// console.log(byName["Thailand"].join(", "));
var ctx = canvas.node().getContext("2d");
ctx.scale(devicePixelRatio, devicePixelRatio);
// Draw a circle for each host country
var countrySumRank = nested.map(function(d) { return d.key; });
for (var year in hostCountries) {
if (countrySumRank.indexOf(hostCountries[year]) < numTop) {
ctx.fillStyle = color(hostCountries[year]);
} else {
ctx.fillStyle = "#888";
}
ctx.beginPath();
ctx.arc(xscale(year), yscale(byYear[year][hostCountries[year]]), 5, 0, 2*Math.PI);
ctx.fill();
ctx.closePath();
}
nested.slice(0, num).reverse().forEach(function(name, i) {
var yearspopular = name.value.data;
if (i >= num-numTop) {
ctx.globalAlpha = 0.85;
ctx.strokeStyle = color(name.key);
ctx.lineWidth = 2.5;
} else {
ctx.globalAlpha = 0.55;
ctx.strokeStyle = "#888";
ctx.lineWidth = 1;
}
// bump line
ctx.globalCompositeOperation = "darken";
ctx.lineCap = "round";
yearspopular.forEach(function(d, j) {
if (j > 0) {
var previousYear = yearspopular[j-1].year;
ctx.beginPath();
if ((d.year - previousYear) > 4) { //skipping games
ctx.setLineDash([5, 10]);
} else {
ctx.setLineDash([]);
}
ctx.moveTo(xscale(previousYear), yscale(byYear[previousYear][name.key]))
// ctx.lineTo(xscale(d.year), yscale(byYear[d.year][name.key]));
ctx.bezierCurveTo(
xscale(previousYear)+15, yscale(byYear[previousYear][name.key]),
xscale(d.year)-15, yscale(byYear[d.year][name.key]),
xscale(d.year), yscale(byYear[d.year][name.key]));
// ctx.closePath();
ctx.stroke();
}
});
});
ctx.textAlign = "right";
ctx.textBaseline = "middle";
ctx.font = "10px sans-serif";
nested.slice(0, num).reverse().forEach(function(name, i) {
var yearspopular = name.value.data;
if (i >= num-numTop) {
ctx.fillStyle = color(name.key);
} else {
ctx.fillStyle = "#555";
}
ctx.globalCompositeOperation = "source-over";
ctx.globalAlpha = 0.9;
// start names
ctx.save();
ctx.textAlign = "end";
var start = yearspopular[0].year;
var x = xscale(start)-10;
var y = yscale(byYear[start][name.key]);
switch (name.key) {
case "Indonesia": x += 30; y -= 10; break;
case "Philippines": x += 45; y -= 10; break;
case "Cambodia": x += 10; y -= 10; break;
default: break;
}
ctx.fillText(name.key, x, y);
ctx.restore();
// end names
ctx.textAlign = "start";
var end= yearspopular[yearspopular.length-1].year;
ctx.fillText(name.key, xscale(end)+10, yscale(byYear[end][name.key]));
});
// legend
var legendPos = {x: width*0.12, y: height*0.78};
ctx.fillStyle = "#888";
ctx.beginPath();
ctx.arc(legendPos.x, legendPos.y, 5, 0, 2*Math.PI);
ctx.fill();
ctx.closePath();
ctx.textAlign = "start";
ctx.fillText("marks the years that each country hosts the SEA Games.", legendPos.x + 10, legendPos.y - 1);
});
year name gold host
1959 Thailand 35 y
1959 Myanmar 11 n
1959 Malaysia 8 n
1959 Singapore 8 n
1959 Vietnam 5 n
1959 Laos 0 n
1961 Thailand 21 n
1961 Myanmar 35 y
1961 Malaysia 16 n
1961 Singapore 4 n
1961 Vietnam 9 n
1961 Cambodia 1 n
1961 Laos 0 n
1965 Thailand 38 n
1965 Myanmar 18 n
1965 Malaysia 33 y
1965 Singapore 26 n
1965 Vietnam 5 n
1965 Cambodia 15 n
1965 Laos 0 n
1967 Thailand 77 y
1967 Myanmar 11 n
1967 Malaysia 23 n
1967 Singapore 28 n
1967 Vietnam 6 n
1967 Laos 0 n
1969 Thailand 32 n
1969 Myanmar 57 y
1969 Malaysia 16 n
1969 Singapore 31 n
1969 Vietnam 9 n
1969 Laos 0 n
1971 Thailand 44 n
1971 Myanmar 20 n
1971 Malaysia 41 y
1971 Singapore 32 n
1971 Cambodia 17 n
1971 Vietnam 3 n
1971 Laos 0 n
1973 Thailand 47 n
1973 Myanmar 28 n
1973 Malaysia 30 n
1973 Singapore 45 y
1973 Cambodia 9 n
1973 Vietnam 2 n
1973 Laos 0 n
1975 Thailand 80 y
1975 Myanmar 28 n
1975 Malaysia 16 n
1975 Singapore 38 n
1977 Malaysia 21 y
1977 Thailand 37 n
1977 Singapore 14 n
1977 Indonesia 62 n
1977 Philippines 31 n
1977 Myanmar 25 n
1977 Brunei 0 n
1979 Malaysia 19 n
1979 Thailand 50 n
1979 Singapore 16 n
1979 Indonesia 92 y
1979 Philippines 24 n
1979 Myanmar 26 n
1979 Brunei 0 n
1981 Malaysia 16 n
1981 Thailand 62 n
1981 Singapore 12 n
1981 Indonesia 85 n
1981 Philippines 55 y
1981 Myanmar 15 n
1981 Brunei 0 n
1983 Malaysia 16 n
1983 Philippines 49 n
1983 Thailand 49 n
1983 Singapore 38 y
1983 Indonesia 64 n
1983 Myanmar 18 n
1983 Brunei 0 n
1983 Cambodia 0 n
1985 Malaysia 26 n
1985 Philippines 43 n
1985 Thailand 92 y
1985 Singapore 16 n
1985 Indonesia 62 n
1985 Myanmar 13 n
1985 Brunei 0 n
1985 Cambodia 0 n
1987 Malaysia 35 n
1987 Philippines 59 n
1987 Thailand 63 n
1987 Singapore 19 n
1987 Indonesia 183 y
1987 Myanmar 13 n
1987 Brunei 1 n
1987 Cambodia 0 n
1989 Indonesia 102 n
1989 Malaysia 67 y
1989 Thailand 62 n
1989 Singapore 32 n
1989 Philippines 26 n
1989 Myanmar 10 n
1989 Vietnam 3 n
1989 Brunei 1 n
1989 Laos 0 n
1991 Indonesia 92 n
1991 Malaysia 36 n
1991 Thailand 72 n
1991 Singapore 18 n
1991 Philippines 91 y
1991 Myanmar 12 n
1991 Vietnam 7 n
1991 Brunei 0 n
1991 Laos 0 n
1993 Indonesia 88 n
1993 Malaysia 43 n
1993 Thailand 63 n
1993 Singapore 50 y
1993 Philippines 57 n
1993 Myanmar 8 n
1993 Vietnam 9 n
1993 Brunei 1 n
1993 Laos 0 n
1995 Thailand 157 y
1995 Indonesia 77 n
1995 Philippines 33 n
1995 Malaysia 31 n
1995 Singapore 26 n
1995 Vietnam 10 n
1995 Myanmar 4 n
1995 Brunei 0 n
1995 Laos 0 n
1995 Cambodia 0 n
1997 Thailand 83 n
1997 Indonesia 194 y
1997 Philippines 43 n
1997 Malaysia 55 n
1997 Singapore 30 n
1997 Vietnam 35 n
1997 Myanmar 8 n
1997 Brunei 0 n
1997 Laos 0 n
1997 Cambodia 0 n
1999 Thailand 65 n
1999 Indonesia 44 n
1999 Philippines 19 n
1999 Malaysia 57 n
1999 Singapore 23 n
1999 Vietnam 17 n
1999 Myanmar 3 n
1999 Brunei 4 y
1999 Laos 1 n
1999 Cambodia 0 n
2001 Thailand 103 n
2001 Indonesia 72 n
2001 Philippines 30 n
2001 Malaysia 111 y
2001 Singapore 22 n
2001 Vietnam 33 n
2001 Myanmar 19 n
2001 Brunei 0 n
2001 Laos 1 n
2001 Cambodia 1 n
2003 Malaysia 44 n
2003 Thailand 90 n
2003 Vietnam 158 y
2003 Singapore 30 n
2003 Indonesia 55 n
2003 Philippines 48 n
2003 Myanmar 16 n
2003 Laos 1 n
2003 Cambodia 1 n
2003 Brunei 1 n
2003 Timor-Leste 0 n
2005 Malaysia 61 n
2005 Thailand 87 n
2005 Vietnam 71 n
2005 Singapore 42 n
2005 Indonesia 49 n
2005 Philippines 113 y
2005 Myanmar 17 n
2005 Laos 3 n
2005 Cambodia 0 n
2005 Brunei 1 n
2005 Timor-Leste 0 n
2007 Malaysia 68 n
2007 Thailand 183 y
2007 Vietnam 64 n
2007 Singapore 43 n
2007 Indonesia 56 n
2007 Philippines 41 n
2007 Myanmar 14 n
2007 Laos 5 n
2007 Cambodia 2 n
2007 Brunei 1 n
2007 Timor-Leste 0 n
2009 Malaysia 40 n
2009 Thailand 86 n
2009 Vietnam 83 n
2009 Singapore 33 n
2009 Indonesia 43 n
2009 Philippines 38 n
2009 Myanmar 12 n
2009 Laos 33 y
2009 Cambodia 3 n
2009 Brunei 1 n
2009 Timor-Leste 0 n
2011 Malaysia 58 n
2011 Thailand 109 n
2011 Vietnam 96 n
2011 Singapore 42 n
2011 Indonesia 182 y
2011 Philippines 37 n
2011 Myanmar 16 n
2011 Cambodia 4 n
2011 Laos 9 n
2011 Brunei 0 n
2011 Timor-Leste 1 n
2013 Malaysia 43 n
2013 Thailand 107 n
2013 Vietnam 73 n
2013 Singapore 34 n
2013 Indonesia 65 n
2013 Philippines 29 n
2013 Myanmar 86 y
2013 Cambodia 8 n
2013 Laos 13 n
2013 Brunei 1 n
2013 Timor-Leste 2 n
2015 Malaysia 62 n
2015 Thailand 95 n
2015 Vietnam 73 n
2015 Singapore 84 y
2015 Indonesia 47 n
2015 Philippines 29 n
2015 Myanmar 12 n
2015 Cambodia 1 n
2015 Laos 0 n
2015 Brunei 0 n
2015 Timor-Leste 0 n
2017 Malaysia 145 y
2017 Thailand 72 n
2017 Vietnam 58 n
2017 Singapore 57 n
2017 Indonesia 38 n
2017 Philippines 24 n
2017 Myanmar 7 n
2017 Cambodia 3 n
2017 Laos 2 n
2017 Brunei 0 n
2017 Timor-Leste 0 n
2019 Philippines 149 y
2019 Vietnam 98 n
2019 Thailand 92 n
2019 Indonesia 72 n
2019 Malaysia 55 n
2019 Singapore 53 n
2019 Myanmar 4 n
2019 Cambodia 4 n
2019 Brunei 2 n
2019 Laos 1 n
2019 Timor-Leste 0 n
2021 Vietnam 205 y
2021 Thailand 92 n
2021 Indonesia 69 n
2021 Philippines 52 n
2021 Singapore 47 n
2021 Malaysia 39 n
2021 Myanmar 9 n
2021 Cambodia 9 n
2021 Laos 2 n
2021 Brunei 1 n
2021 Timor-Leste 0 n
2023 Vietnam 136 n
2023 Thailand 108 n
2023 Indonesia 87 n
2023 Cambodia 81 y
2023 Philippines 58 n
2023 Singapore 51 n
2023 Malaysia 34 n
2023 Myanmar 21 n
2023 Laos 6 n
2023 Brunei 2 n
2023 Timor-Leste 0 n
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment