function init() { var margin = 150; //equal margins on all sides var width = window.screen.width - 2 * margin; var height = 700 - 2 * margin; var x = d3.scaleTime().range([0, width]); var y = d3.scaleLinear().range([height, 0]); var yLog = d3.scaleLog().clamp(true).range([height, 0]); var ySqrt = d3.scaleSqrt().range([height, 0]); var timeParser = d3.timeFormat("%b %Y"); var dateParse = d3.timeParse("%Y-%m-%d"); var legends = ['Catan', 'Dominion', 'Codenames', 'Terraforming Mars', 'Gloomhaven', 'Magic: The Gathering', 'Dixit', 'Monopoly']; function lineGraphs(i) { return d3.line().x(function (d) { return x(dateParse(d.date)); }).y(function (d) { return y(+d[legends[i]]) }); } function lineGraphsLog(i) { return d3.line().x(function (d) { return x(dateParse(d.date)); }).y(function (d) { return yLog(+d[legends[i]]) }); } function lineGraphsSqrt(i) { return d3.line().x(function (d) { return x(dateParse(d.date)); }).y(function (d) { return ySqrt(+d[legends[i]]) }); } var svgFig1 = d3.select("body") .append("svg") .attr("class", "fig1") .attr("width", width + 2 * margin) .attr("height", height + 2 * margin) .append("g") .attr("transform", "translate(" + margin + "," + margin + ")"); d3.select("body").append("div").attr("class", "pagebreak"); var svgFig2 = d3.select("body") .append("svg") .attr("class", "fig1") .attr("width", width + 2 * margin) .attr("height", height + 2 * margin) .append("g") .attr("transform", "translate(" + margin + "," + margin + ")"); d3.select("body").append("div").attr("class", "pagebreak"); var svgFig4 = d3.select("body") .append("svg") .attr("class", "fig1") .attr("width", width + 2 * margin) .attr("height", height + 2 * margin) .append("g") .attr("transform", "translate(" + margin + "," + margin + ")"); d3.select("body").append("div").attr("class", "pagebreak"); var svgFig3 = d3.select("body") .append("svg") .attr("class", "fig1") .attr("width", width + 2 * margin) .attr("height", height + 2 * margin) .append("g") .attr("transform", "translate(" + margin + "," + margin + ")"); d3.select("body").append("div").attr("class", "pagebreak"); svgFig3.append("text") .attr("x", width - 250) .attr("y", height + 100) .attr("text-anchor", "middle") .style("font-size", "16px") .text("psrinivasan48"); d3.dsv(",", "boardgame_ratings.csv", function (d) { var obj = { month: timeParser(new Date(d.date)), date: d.date }; for (var i in legends) { obj[legends[i]] = +d[legends[i] + "=count"]; obj[legends[i] + '=rank'] = +d[legends[i] + "=rank"]; } return obj; }).then(function (data) { var minMax = findMinMax(data); var min = minMax[0], max = minMax[1]; x.domain(d3.extent(data, function (d) { return dateParse(d.date); })); y.domain([min, max]); yLog.domain([min, max]); ySqrt.domain([min, max]); for (var i in legends) { var lg = lineGraphs(i); var lgLog = lineGraphsLog(i); var lgSqrt = lineGraphsSqrt(i); svgFig1.append("path") .data([data]) .attr("class", "line") .attr("d", lg) .style("stroke", d3.schemeCategory10[i]) .append("text") .text(legends[i]); svgFig1.append("text") .attr("transform", "translate(" + (width + 10) + "," + y(data[data.length - 1][legends[i]]) + ")") .attr("text-anchor", "start") .style("fill", d3.schemeCategory10[i]) .text(legends[i]); svgFig2.append("path") .data([data]) .attr("class", "line") .attr("d", lg) .style("stroke", d3.schemeCategory10[i]) .append("text") .text(legends[i]); svgFig2.append("text") .attr("transform", "translate(" + (width + 10) + "," + y(data[data.length - 1][legends[i]]) + ")") .attr("text-anchor", "start") .style("fill", d3.schemeCategory10[i]) .text(legends[i]); svgFig3.append("path") .data([data]) .attr("class", "line") .attr("d", lgLog) .style("stroke", d3.schemeCategory10[i]) .append("text") .text(legends[i]); svgFig3.append("text") .attr("transform", "translate(" + (width + 10) + "," + yLog(data[data.length - 1][legends[i]]) + ")") .attr("text-anchor", "start") .style("fill", d3.schemeCategory10[i]) .text(legends[i]); svgFig4.append("path") .data([data]) .attr("class", "line") .attr("d", lgSqrt) .style("stroke", d3.schemeCategory10[i]) .append("text") .text(legends[i]); svgFig4.append("text") .attr("transform", "translate(" + (width + 10) + "," + ySqrt(data[data.length - 1][legends[i]]) + ")") .attr("text-anchor", "start") .style("fill", d3.schemeCategory10[i]) .text(legends[i]); if (["Catan", "Codenames", "Terraforming Mars", "Gloomhaven"].includes(legends[i])) { svgFig2.selectAll("circles") .data(data) .enter() .append("circle") .filter(function(d, iter){ return iter%3===2; }) .attr("fill", d3.schemeCategory10[i]) .attr("cx", function (d) { return x(dateParse(d.date)) }) .attr("cy", function (d) { return y(d[legends[i]]) }) .attr("r", 10); svgFig2.selectAll("circles") .data(data) .enter() .filter(function(d, iter){ return iter%3===2; }) .append("text") .attr("class", "count-font") .text(function (d) { return d[legends[i] + "=rank"]; }).attr("x", function (d) { return x(dateParse(d.date)) - 5; }).attr("y", function (d) { return y(d[legends[i]]) + 5 }); svgFig3.selectAll("circles") .data(data) .enter() .filter(function(d, iter){ return iter%3===2; }) .append("circle") .attr("fill", d3.schemeCategory10[i]) .attr("cx", function (d) { return x(dateParse(d.date)) }) .attr("cy", function (d) { return yLog(d[legends[i]]) }) .attr("r", 10); svgFig3.selectAll("circles") .data(data) .enter() .filter(function(d, iter){ return iter%3===2; }) .append("text") .attr("class", "count-font") .text(function (d) { return d[legends[i] + "=rank"]; }).attr("x", function (d) { return x(dateParse(d.date)) - 5; }).attr("y", function (d) { return yLog(d[legends[i]]) + 5 }); svgFig4.selectAll("circles") .data(data) .enter() .filter(function(d, iter){ return iter%3===2; }) .append("circle") .attr("fill", d3.schemeCategory10[i]) .attr("cx", function (d) { return x(dateParse(d.date)) }) .attr("cy", function (d) { return ySqrt(d[legends[i]]) }) .attr("r", 10); svgFig4.selectAll("circles") .data(data) .enter() .filter(function(d, iter){ return iter%3===2; }) .append("text") .attr("class", "count-font") .text(function (d) { return d[legends[i] + "=rank"]; }).attr("x", function (d) { return x(dateParse(d.date)) - 5; }).attr("y", function (d) { return ySqrt(d[legends[i]]) + 5 }); } } svgFig2.append("circle") .attr("fill", "black") .attr("transform", "translate(" + (width + 20) + "," + (height - 30) + ")") .attr("r", 10); svgFig2.append("text") .attr("class", "count-font") .attr("transform", "translate(" + (width + 10) + "," + (height - 27) + ")").text("RANK"); svgFig2.append("text") .attr("transform", "translate(" + (width - 30) + "," + (height - 10) + ")").text("BoardGameGeek Rank"); svgFig3.append("circle") .attr("fill", "black") .attr("transform", "translate(" + (width + 20) + "," + (height - 30) + ")") .attr("r", 10); svgFig3.append("text") .attr("class", "count-font") .attr("transform", "translate(" + (width + 10) + "," + (height - 27) + ")").text("RANK"); svgFig3.append("text") .attr("transform", "translate(" + (width - 30) + "," + (height - 10) + ")").text("BoardGameGeek Rank"); svgFig4.append("circle") .attr("fill", "black") .attr("transform", "translate(" + (width + 20) + "," + (height - 30) + ")") .attr("r", 10); svgFig4.append("text") .attr("class", "count-font") .attr("transform", "translate(" + (width + 10) + "," + (height - 27) + ")").text("RANK"); svgFig4.append("text") .attr("transform", "translate(" + (width - 30) + "," + (height - 10) + ")").text("BoardGameGeek Rank"); svgFig1.append("g") .attr("transform", "translate(0," + height + ")") .call(d3.axisBottom(x).tickFormat(d3.timeFormat("%b %Y"))); svgFig1.append("g") .call(d3.axisLeft(y)); svgFig2.append("g") .attr("transform", "translate(0," + height + ")") .call(d3.axisBottom(x).tickFormat(d3.timeFormat("%b %Y"))); svgFig2.append("g") .call(d3.axisLeft(y)); svgFig3.append("g") .attr("transform", "translate(0," + height + ")") .call(d3.axisBottom(x).tickFormat(d3.timeFormat("%b %Y"))); svgFig3.append("g") .call(d3.axisLeft(yLog)); svgFig4.append("g") .attr("transform", "translate(0," + height + ")") .call(d3.axisBottom(x).tickFormat(d3.timeFormat("%b %Y"))); svgFig4.append("g") .call(d3.axisLeft(ySqrt)); function findMinMax(data) { var min = Number.POSITIVE_INFINITY; var max = Number.NEGATIVE_INFINITY; for (var j in data) { var datum = data[j]; for (var i in legends) { if (datum[legends[i]] < min) min = datum[legends[i]]; if (datum[legends[i]] > max) max = datum[legends[i]]; } } return [min, max]; } svgFig1.append("text") .attr("transform", "translate(" + width / 2 + " ," + (height + 30) + ")") .style("text-anchor", "middle") .text("Month"); svgFig1.append("text") .attr("y", -50) .attr("x", -height / 2) .attr("transform", "rotate(-90)") .style("text-anchor", "middle") .text("Number of Ratings"); svgFig1.append("text") .attr("x", (width / 2)) .attr("text-anchor", "middle") .style("font-size", "16px") .text("Number of Ratings 2016-2020"); svgFig2.append("text") .attr("transform", "translate(" + width / 2 + " ," + (height + 30) + ")") .style("text-anchor", "middle") .text("Month"); svgFig2.append("text") .attr("y", -50) .attr("x", -height / 2) .attr("transform", "rotate(-90)") .style("text-anchor", "middle") .text("Number of Ratings"); svgFig2.append("text") .attr("x", (width / 2)) .attr("text-anchor", "middle") .style("font-size", "16px") .text("Number of Ratings 2016-2020 with Rankings"); svgFig3.append("text") .attr("transform", "translate(" + width / 2 + " ," + (height + 30) + ")") .style("text-anchor", "middle") .text("Month"); svgFig3.append("text") .attr("y", -50) .attr("x", -height / 2) .attr("transform", "rotate(-90)") .style("text-anchor", "middle") .text("Number of Ratings"); svgFig3.append("text") .attr("x", (width / 2)) .attr("y", -5) .attr("text-anchor", "middle") .style("font-size", "16px") .text("Number of Ratings 2016-2020 with Rankings (Log Scale)"); svgFig4.append("text") .attr("transform", "translate(" + width / 2 + " ," + (height + 30) + ")") .style("text-anchor", "middle") .text("Month"); svgFig4.append("text") .attr("y", -50) .attr("x", -height / 2) .attr("transform", "rotate(-90)") .style("text-anchor", "middle") .text("Number of Ratings"); svgFig4.append("text") .attr("x", (width / 2)) .attr("text-anchor", "middle") .style("font-size", "16px") .text("Number of Ratings 2016-2020 with Rankings (Square Root Scale)"); }).catch(function (error) { console.log(error); }); }