1016 lines
29 KiB
HTML
1016 lines
29 KiB
HTML
<!DOCTYPE html>
|
|
|
|
<head>
|
|
<title>Line Charts</title>
|
|
<meta charset="utf-8" />
|
|
|
|
<script type="text/javascript" src="../lib/d3.v5.min.js"></script>
|
|
</head>
|
|
|
|
<body>
|
|
<div id="signature">tlou31</div>
|
|
|
|
<!-- common -->
|
|
<script>
|
|
var formatDate = d3.timeParse("%Y-%m-%d");
|
|
</script>
|
|
|
|
<!-- Q3.a -->
|
|
<script>
|
|
d3.dsv(",", "boardgame_ratings.csv", function (d) {
|
|
return {
|
|
date: formatDate(d.date),
|
|
"Catan=count": d["Catan=count"],
|
|
"Dominion=count": d["Dominion=count"],
|
|
"Dixit=count": d["Dixit=count"],
|
|
"Codenames=count": d["Codenames=count"],
|
|
"Gloomhaven=count": d["Gloomhaven=count"],
|
|
"Magic: The Gathering=count": d["Magic: The Gathering=count"],
|
|
"Monopoly=count": d["Monopoly=count"],
|
|
"Terraforming Mars=count": d["Terraforming Mars=count"],
|
|
};
|
|
}).then(function (data) {
|
|
var margin = { top: 60, right: 180, bottom: 60, left: 80 };
|
|
var width = 1000 - margin.left - margin.right;
|
|
var height = 600 - margin.top - margin.bottom;
|
|
|
|
// DOM config
|
|
var svg_a = d3.select("body").append("svg").attr("id", "svg-a");
|
|
var title_text_a = svg_a.append("text").attr("id", "title-a");
|
|
var plot_a = svg_a.append("g").attr("id", "plot-a");
|
|
|
|
// plotlines
|
|
var lines_a = plot_a.append("g").attr("id", "lines-a");
|
|
|
|
var x_axis_a = plot_a
|
|
.append("g")
|
|
.attr("id", "x-axis-a")
|
|
.attr("class", "x_axis_a")
|
|
.attr("transform", "translate(0," + height + ")");
|
|
var x_axis_a_text = x_axis_a.append("text");
|
|
|
|
var y_axis_a = plot_a.append("g").attr("id", "y-axis-a");
|
|
var y_axis_a_text = y_axis_a.append("text");
|
|
|
|
// DOM config end
|
|
|
|
// init
|
|
x_axis_a_text.text("Month");
|
|
y_axis_a_text.text("Num of Ratings");
|
|
|
|
svg_a
|
|
.attr("width", width + margin.left + margin.right)
|
|
.attr("height", height + margin.top + margin.bottom);
|
|
title_text_a
|
|
.text("Number of Ratings 2016-2020")
|
|
.attr("y", 40)
|
|
.attr("x", 300)
|
|
.attr("font-size", "20px");
|
|
|
|
plot_a.attr(
|
|
"transform",
|
|
"translate(" + margin.left + "," + margin.top + ")"
|
|
);
|
|
|
|
x_axis_a.attr("transform", "translate(0," + height + ")");
|
|
y_axis_a.attr("transform", "translate(0,0)");
|
|
|
|
// init end
|
|
|
|
// main
|
|
// init
|
|
var xScale = d3
|
|
.scaleTime()
|
|
.domain(
|
|
d3.extent(data, function (d) {
|
|
return d.date;
|
|
})
|
|
)
|
|
.range([0, width]);
|
|
|
|
yScale_max = -1;
|
|
|
|
x_axis_a.call(
|
|
d3
|
|
.axisBottom(xScale)
|
|
.tickFormat(d3.timeFormat("%b %y"))
|
|
.tickValues(data.map((d) => d.date))
|
|
);
|
|
|
|
var yScale = d3.scaleLinear().domain([0, yScale_max]).range([height, 0]);
|
|
y_axis_a.call(d3.axisLeft(yScale));
|
|
|
|
const myNode = document.getElementsByClassName("x_axis_a");
|
|
const myNode_wkng = myNode[0].getElementsByClassName("tick");
|
|
|
|
iter_node = 2;
|
|
|
|
while (iter_node < myNode_wkng.length) {
|
|
myNode_wkng[0].parentNode.removeChild(myNode_wkng[iter_node - 2]);
|
|
|
|
myNode_wkng[0].parentNode.removeChild(myNode_wkng[iter_node - 2]);
|
|
iter_node = iter_node + 1;
|
|
}
|
|
|
|
nodes_to_remove_at_last = myNode_wkng.length % 3;
|
|
while (nodes_to_remove_at_last > 0) {
|
|
myNode_wkng[0].parentNode.removeChild(
|
|
myNode_wkng[myNode_wkng.length - 1]
|
|
);
|
|
nodes_to_remove_at_last = nodes_to_remove_at_last - 1;
|
|
}
|
|
|
|
Columns = [
|
|
"Catan=count",
|
|
"Dominion=count",
|
|
"Dixit=count",
|
|
"Codenames=count",
|
|
"Gloomhaven=count",
|
|
"Magic: The Gathering=count",
|
|
"Monopoly=count",
|
|
"Terraforming Mars=count",
|
|
];
|
|
Column_Names = [
|
|
"Catan",
|
|
"Dominion",
|
|
"Dixit",
|
|
"Codenames",
|
|
"Gloomhaven",
|
|
"Magic: The Gathering",
|
|
"Monopoly",
|
|
"Terraforming Mars",
|
|
];
|
|
|
|
for (c in Columns) {
|
|
min_max_col = d3.extent(data, (d) => d[Columns[c]]);
|
|
|
|
if (yScale_max < min_max_col[1]) {
|
|
yScale_max = min_max_col[1];
|
|
}
|
|
}
|
|
|
|
var yScale = d3.scaleLinear().domain([0, yScale_max]).range([height, 0]);
|
|
var yAxis = d3.axisLeft(yScale);
|
|
|
|
column_iter = 0;
|
|
for (column_iter in Columns) {
|
|
lines_a
|
|
.append("path")
|
|
.datum(data)
|
|
.attr("fill", "none")
|
|
.attr("stroke", d3.schemeCategory10[column_iter])
|
|
.attr("stroke-width", 1.5)
|
|
.attr(
|
|
"d",
|
|
d3
|
|
.line()
|
|
.x(function (d) {
|
|
return xScale(d.date);
|
|
})
|
|
.y(function (d) {
|
|
return yScale(+d[Columns[column_iter]]);
|
|
})
|
|
);
|
|
|
|
lines_a
|
|
.append("text")
|
|
.attr(
|
|
"transform",
|
|
"translate(" +
|
|
(width + 3) +
|
|
"," +
|
|
yScale(data.slice(-1)[0][Columns[column_iter]]) +
|
|
")"
|
|
)
|
|
.attr("dy", ".35em")
|
|
.attr("text-anchor", "start")
|
|
.style("fill", d3.schemeCategory10[column_iter])
|
|
.text(Column_Names[column_iter]);
|
|
}
|
|
|
|
// main end
|
|
});
|
|
</script>
|
|
|
|
<!-- Q3.b -->
|
|
<script>
|
|
d3.dsv(",", "boardgame_ratings.csv", function (d) {
|
|
return {
|
|
date: formatDate(d.date),
|
|
"Catan=count": d["Catan=count"],
|
|
"Dominion=count": d["Dominion=count"],
|
|
"Dixit=count": d["Dixit=count"],
|
|
"Codenames=count": d["Codenames=count"],
|
|
"Gloomhaven=count": d["Gloomhaven=count"],
|
|
"Magic: The Gathering=count": d["Magic: The Gathering=count"],
|
|
"Monopoly=count": d["Monopoly=count"],
|
|
"Terraforming Mars=count": d["Terraforming Mars=count"],
|
|
|
|
"Catan=rank": d["Catan=rank"],
|
|
"Dominion=rank": d["Dominion=rank"],
|
|
"Dixit=rank": d["Dixit=rank"],
|
|
"Codenames=rank": d["Codenames=rank"],
|
|
"Gloomhaven=rank": d["Gloomhaven=rank"],
|
|
"Magic: The Gathering=rank": d["Magic: The Gathering=rank"],
|
|
"Monopoly=rank": d["Monopoly=rank"],
|
|
"Terraforming Mars=rank": d["Terraforming Mars=rank"],
|
|
};
|
|
}).then(function (data) {
|
|
var margin = { top: 60, right: 180, bottom: 60, left: 80 };
|
|
var width = 1000 - margin.left - margin.right;
|
|
var height = 600 - margin.top - margin.bottom;
|
|
|
|
// DOM config
|
|
var svg_b = d3.select("body").append("svg").attr("id", "svg-b");
|
|
var svg = svg_b;
|
|
var title_text_b = svg_b.append("text").attr("id", "title-b");
|
|
var plot_b = svg_b.append("g").attr("id", "plot-b");
|
|
|
|
// plotlines
|
|
var lines_b = plot_b.append("g").attr("id", "lines-b");
|
|
|
|
var x_axis_b = plot_b
|
|
.append("g")
|
|
.attr("id", "x-axis-b")
|
|
.attr("class", "x_axis_b");
|
|
|
|
var x_axis_b_text = x_axis_b.append("text");
|
|
|
|
var y_axis_b = plot_b.append("g").attr("id", "y-axis-b");
|
|
var y_axis_b_text = y_axis_b.append("text");
|
|
|
|
symbols_b = plot_b.append("g").attr("id", "symbols-b");
|
|
legend_b = svg_b.append("g").attr("id", "legend-b");
|
|
|
|
// DOM config end
|
|
|
|
// init
|
|
x_axis_b_text
|
|
.attr("transform", "translate(0," + height + ")")
|
|
.text("Month");
|
|
y_axis_b_text.text("Num of Ratings");
|
|
|
|
svg_b
|
|
.attr("width", width + margin.left + margin.right)
|
|
.attr("height", height + margin.top + margin.bottom);
|
|
|
|
title_text_b
|
|
.text("Number of Ratings 2016-2020 with Rankings")
|
|
.attr("y", 40)
|
|
.attr("x", 300)
|
|
.attr("font-size", "20px");
|
|
|
|
plot_b.attr(
|
|
"transform",
|
|
"translate(" + margin.left + "," + margin.top + ")"
|
|
);
|
|
|
|
x_axis_b.attr("transform", "translate(0," + height + ")");
|
|
y_axis_b.attr("transform", "translate(0,0)");
|
|
|
|
plot_b.attr(
|
|
"transform",
|
|
"translate(" + margin.left + "," + margin.top + ")"
|
|
);
|
|
|
|
x_axis_b.attr("transform", "translate(0," + height + ")");
|
|
y_axis_b.attr("transform", "translate(0,0)");
|
|
|
|
// init end
|
|
|
|
// append the svg object to the body of the page
|
|
|
|
var xScale = d3
|
|
.scaleTime()
|
|
.domain(d3.extent(data, (d) => d.date))
|
|
.range([0, width]);
|
|
|
|
yScale_max = -1;
|
|
|
|
Columns = [
|
|
"Catan=count",
|
|
"Dominion=count",
|
|
"Dixit=count",
|
|
"Codenames=count",
|
|
"Gloomhaven=count",
|
|
"Magic: The Gathering=count",
|
|
"Monopoly=count",
|
|
"Terraforming Mars=count",
|
|
];
|
|
|
|
Column_Names = [
|
|
"Catan",
|
|
"Dominion",
|
|
"Dixit",
|
|
"Codenames",
|
|
"Gloomhaven",
|
|
"Magic: The Gathering",
|
|
"Monopoly",
|
|
"Terraforming Mars",
|
|
];
|
|
|
|
Columns_rank = [
|
|
"Catan=rank",
|
|
"Dominion=rank",
|
|
"Dixit=rank",
|
|
"Codenames=rank",
|
|
"Gloomhaven=rank",
|
|
"Magic: The Gathering=rank",
|
|
"Monopoly=rank",
|
|
"Terraforming Mars=rank",
|
|
];
|
|
|
|
for (c in Columns) {
|
|
min_max_col = d3.extent(data, (d) => d[Columns[c]]);
|
|
|
|
if (yScale_max < min_max_col[1]) {
|
|
yScale_max = min_max_col[1];
|
|
}
|
|
}
|
|
|
|
var yScale = d3.scaleLinear().domain([0, yScale_max]).range([height, 0]);
|
|
|
|
symbols_b = plot_b.append("g").attr("id", "symbols-b");
|
|
|
|
legend_b = d3.select("#svg-b").append("g").attr("id", "legend-b");
|
|
|
|
column_iter = 0;
|
|
for (column_iter in Columns) {
|
|
lines_b
|
|
.append("path")
|
|
.datum(data)
|
|
.attr("fill", "none")
|
|
.attr("stroke", d3.schemeCategory10[column_iter])
|
|
.attr("stroke-width", 1.5)
|
|
.attr(
|
|
"d",
|
|
d3
|
|
.line()
|
|
.x((d) => xScale(d.date))
|
|
.y((d) => yScale(+d[Columns[column_iter]]))
|
|
);
|
|
|
|
lines_b
|
|
.append("text")
|
|
.attr(
|
|
"transform",
|
|
"translate(" +
|
|
(width + 3) +
|
|
"," +
|
|
yScale(data.slice(-1)[0][Columns[column_iter]]) +
|
|
")"
|
|
)
|
|
.attr("dy", ".35em")
|
|
.attr("text-anchor", "start")
|
|
.style("fill", d3.schemeCategory10[column_iter])
|
|
.text(Column_Names[column_iter]);
|
|
}
|
|
|
|
x_axis_b.call(
|
|
d3
|
|
.axisBottom(xScale)
|
|
.tickFormat(d3.timeFormat("%b %y"))
|
|
.tickValues(data.map((d) => d.date))
|
|
);
|
|
y_axis_b.call(d3.axisLeft(yScale));
|
|
|
|
const myNode = document.getElementsByClassName("x_axis_b");
|
|
const myNode_wkng = myNode[0].getElementsByClassName("tick");
|
|
|
|
iter_node = 2;
|
|
|
|
while (iter_node < myNode_wkng.length) {
|
|
myNode_wkng[0].parentNode.removeChild(myNode_wkng[iter_node - 2]);
|
|
|
|
myNode_wkng[0].parentNode.removeChild(myNode_wkng[iter_node - 2]);
|
|
iter_node = iter_node + 1;
|
|
}
|
|
|
|
nodes_to_remove_at_last = myNode_wkng.length % 3;
|
|
while (nodes_to_remove_at_last > 0) {
|
|
myNode_wkng[0].parentNode.removeChild(
|
|
myNode_wkng[myNode_wkng.length - 1]
|
|
);
|
|
nodes_to_remove_at_last = nodes_to_remove_at_last - 1;
|
|
}
|
|
|
|
for (column_iter in Columns) {
|
|
if (
|
|
[
|
|
"Catan=count",
|
|
"Codenames=count",
|
|
"Terraforming Mars=count",
|
|
"Gloomhaven=count",
|
|
].indexOf(Columns[column_iter]) > -1
|
|
) {
|
|
symbols_b
|
|
.selectAll(".dot" + column_iter)
|
|
.data(data)
|
|
.enter()
|
|
.append("circle")
|
|
.attr("class", "dot" + column_iter)
|
|
.attr("fill", d3.schemeCategory10[column_iter])
|
|
.attr("cx", (d) => xScale(d.date))
|
|
.attr("cy", (d) => yScale(d[Columns[column_iter]]))
|
|
.attr("r", function (d, i) {
|
|
if ((i - 2) % 3 != 0) {
|
|
return 0;
|
|
}
|
|
return 10;
|
|
});
|
|
|
|
symbols_b
|
|
.selectAll(".dot_label" + column_iter)
|
|
.data(data)
|
|
.enter()
|
|
.append("text")
|
|
.attr("class", "dot_label" + column_iter)
|
|
.attr("fill", "white")
|
|
.attr("font-size", "10px")
|
|
.text(function (d, i) {
|
|
if ((i - 2) % 3 == 0) {
|
|
return d[Columns_rank[column_iter]];
|
|
}
|
|
return "";
|
|
})
|
|
.attr("x", (d) => xScale(d.date))
|
|
.attr("y", (d) => yScale(d[Columns[column_iter]]) + 1)
|
|
.attr("text-anchor", "middle");
|
|
}
|
|
}
|
|
|
|
// symbols_b
|
|
|
|
const circle_center_x = 870;
|
|
const circle_center_y = 520;
|
|
|
|
legend_b
|
|
.append("circle")
|
|
.attr("cx", circle_center_x)
|
|
.attr("cy", circle_center_y)
|
|
.attr("r", 15)
|
|
.attr("fill", "black");
|
|
|
|
legend_b
|
|
.append("text")
|
|
.attr("x", circle_center_x - 9)
|
|
.attr("y", circle_center_y + 3)
|
|
.text("rank")
|
|
.attr("fill", "white")
|
|
.attr("font-size", "10px");
|
|
|
|
legend_b
|
|
.append("text")
|
|
.attr("x", circle_center_x - 45)
|
|
.attr("y", circle_center_y + 30)
|
|
.text("BoardGameGeek rank")
|
|
.attr("font-size", "10px");
|
|
|
|
// symbols_b
|
|
|
|
// axis labels
|
|
d3.select("#x-axis-b").append("text").text("Month");
|
|
d3.select("#y-axis-b").append("text").text("Num of Ratings");
|
|
// axis labels
|
|
});
|
|
</script>
|
|
|
|
<!-- Q3.c1 -->
|
|
<script>
|
|
d3.dsv(",", "boardgame_ratings.csv", function (d) {
|
|
return {
|
|
date: formatDate(d.date),
|
|
"Catan=count": d["Catan=count"],
|
|
"Dominion=count": d["Dominion=count"],
|
|
"Dixit=count": d["Dixit=count"],
|
|
"Codenames=count": d["Codenames=count"],
|
|
"Gloomhaven=count": d["Gloomhaven=count"],
|
|
"Magic: The Gathering=count": d["Magic: The Gathering=count"],
|
|
"Monopoly=count": d["Monopoly=count"],
|
|
"Terraforming Mars=count": d["Terraforming Mars=count"],
|
|
|
|
"Catan=rank": d["Catan=rank"],
|
|
"Dominion=rank": d["Dominion=rank"],
|
|
"Dixit=rank": d["Dixit=rank"],
|
|
"Codenames=rank": d["Codenames=rank"],
|
|
"Gloomhaven=rank": d["Gloomhaven=rank"],
|
|
"Magic: The Gathering=rank": d["Magic: The Gathering=rank"],
|
|
"Monopoly=rank": d["Monopoly=rank"],
|
|
"Terraforming Mars=rank": d["Terraforming Mars=rank"],
|
|
};
|
|
}).then(function (data) {
|
|
// config
|
|
var margin = { top: 60, right: 180, bottom: 60, left: 80 };
|
|
var width = 1000 - margin.left - margin.right;
|
|
var height = 600 - margin.top - margin.bottom;
|
|
|
|
var xScale = d3
|
|
.scaleTime()
|
|
.domain(d3.extent(data, (d) => d.date))
|
|
.range([0, width]);
|
|
|
|
yScale_max = -1;
|
|
|
|
Columns = [
|
|
"Catan=count",
|
|
"Dominion=count",
|
|
"Dixit=count",
|
|
"Codenames=count",
|
|
"Gloomhaven=count",
|
|
"Magic: The Gathering=count",
|
|
"Monopoly=count",
|
|
"Terraforming Mars=count",
|
|
];
|
|
|
|
Column_Names = [
|
|
"Catan",
|
|
"Dominion",
|
|
"Dixit",
|
|
"Codenames",
|
|
"Gloomhaven",
|
|
"Magic: The Gathering",
|
|
"Monopoly",
|
|
"Terraforming Mars",
|
|
];
|
|
|
|
Columns_rank = [
|
|
"Catan=rank",
|
|
"Dominion=rank",
|
|
"Dixit=rank",
|
|
"Codenames=rank",
|
|
"Gloomhaven=rank",
|
|
"Magic: The Gathering=rank",
|
|
"Monopoly=rank",
|
|
"Terraforming Mars=rank",
|
|
];
|
|
|
|
for (c in Columns) {
|
|
min_max_col = d3.extent(data, (d) => d[Columns[c]]);
|
|
|
|
if (yScale_max < min_max_col[1]) {
|
|
yScale_max = min_max_col[1];
|
|
}
|
|
}
|
|
|
|
var yScale = d3.scaleSqrt().domain([0, yScale_max]).range([height, 0]);
|
|
// config
|
|
|
|
// create tree
|
|
var svg_c_1 = d3.select("body").append("svg").attr("id", "svg-c-1");
|
|
var title_text_c_1 = svg_c_1.append("text").attr("id", "title-c-1");
|
|
var plot_c_1 = svg_c_1.append("g").attr("id", "plot-c-1");
|
|
// plotlines
|
|
var lines_c_1 = plot_c_1.append("g").attr("id", "lines-c-1");
|
|
|
|
// xaxis_area
|
|
var x_axis_c_1 = plot_c_1
|
|
.append("g")
|
|
.attr("id", "x-axis-c-1")
|
|
.attr("class", "x_axis_c_1")
|
|
.attr("transform", "translate(0," + height + ")");
|
|
var x_axis_c_1_text = x_axis_c_1.append("text");
|
|
|
|
// yaxis_area
|
|
var y_axis_c_1 = plot_c_1.append("g").attr("id", "y-axis-c-1");
|
|
var y_axis_c_1_text = y_axis_c_1.append("text");
|
|
|
|
var symbol_c_1 = plot_c_1.append("g").attr("id", "symbols-c-1");
|
|
var symbol = symbol_c_1;
|
|
var legend_c_1 = svg_c_1.append("g").attr("id", "legend-c-1");
|
|
|
|
// init canvas
|
|
svg_c_1
|
|
.attr("width", width + margin.left + margin.right)
|
|
.attr("height", height + margin.top + margin.bottom);
|
|
|
|
title_text_c_1
|
|
.text("Number of Ratings 2016-2020 (Square root Scale)")
|
|
.attr("x", 300)
|
|
.attr("y", 40)
|
|
.attr("font-size", "20px");
|
|
|
|
plot_c_1.attr(
|
|
"transform",
|
|
"translate(" + margin.left + "," + margin.top + ")"
|
|
);
|
|
|
|
x_axis_c_1_text
|
|
.attr("transform", "translate(0," + height + ")")
|
|
.text("Month");
|
|
|
|
y_axis_c_1_text
|
|
.attr("transform", "translate(0,0)")
|
|
.text("Num of Ratings");
|
|
|
|
x_axis_c_1.call(
|
|
d3
|
|
.axisBottom(xScale)
|
|
.tickFormat(d3.timeFormat("%b %y"))
|
|
.tickValues(data.map((d) => d.date))
|
|
.ticks(d3.utcMonth.every(5))
|
|
);
|
|
|
|
const myNode = document.getElementsByClassName("x_axis_c_1");
|
|
const myNode_wkng = myNode[0].getElementsByClassName("tick");
|
|
|
|
iter_node = 2;
|
|
|
|
while (iter_node < myNode_wkng.length) {
|
|
myNode_wkng[0].parentNode.removeChild(myNode_wkng[iter_node - 2]);
|
|
|
|
myNode_wkng[0].parentNode.removeChild(myNode_wkng[iter_node - 2]);
|
|
iter_node = iter_node + 1;
|
|
}
|
|
|
|
nodes_to_remove_at_last = myNode_wkng.length % 3;
|
|
while (nodes_to_remove_at_last > 0) {
|
|
myNode_wkng[0].parentNode.removeChild(
|
|
myNode_wkng[myNode_wkng.length - 1]
|
|
);
|
|
nodes_to_remove_at_last = nodes_to_remove_at_last - 1;
|
|
}
|
|
|
|
y_axis_c_1.call(d3.axisLeft(yScale));
|
|
// init canvas end
|
|
|
|
// define content
|
|
for (column_iter in Columns) {
|
|
// lines_c_1
|
|
lines_c_1
|
|
.append("path")
|
|
.datum(data)
|
|
.attr("fill", "none")
|
|
.attr("stroke", d3.schemeCategory10[column_iter])
|
|
.attr("stroke-width", 1.5)
|
|
.attr(
|
|
"d",
|
|
d3
|
|
.line()
|
|
.x((d) => xScale(d.date))
|
|
.y((d) => yScale(+d[Columns[column_iter]]))
|
|
);
|
|
lines_c_1
|
|
.append("text")
|
|
.attr(
|
|
"transform",
|
|
"translate(" +
|
|
(width + 3) +
|
|
"," +
|
|
yScale(data.slice(-1)[0][Columns[column_iter]]) +
|
|
")"
|
|
)
|
|
.attr("dy", ".35em")
|
|
.attr("text-anchor", "start")
|
|
.style("fill", d3.schemeCategory10[column_iter])
|
|
.text(Column_Names[column_iter]);
|
|
}
|
|
|
|
for (column_iter in Columns) {
|
|
console.log({ column_iter });
|
|
if (
|
|
[
|
|
"Catan=count",
|
|
"Codenames=count",
|
|
"Terraforming Mars=count",
|
|
"Gloomhaven=count",
|
|
].indexOf(Columns[column_iter]) > -1
|
|
) {
|
|
symbol
|
|
.selectAll(".dot" + column_iter)
|
|
.data(data)
|
|
.enter()
|
|
.append("circle")
|
|
.attr("class", "dot" + column_iter)
|
|
.attr("fill", d3.schemeCategory10[column_iter])
|
|
.attr("cx", (d) => xScale(d.date))
|
|
.attr("cy", (d) => yScale(d[Columns[column_iter]]))
|
|
.attr("r", function (d, i) {
|
|
if ((i - 2) % 3 != 0) {
|
|
return 0;
|
|
}
|
|
return 10;
|
|
});
|
|
|
|
symbol
|
|
.selectAll(".dot_label" + column_iter)
|
|
.data(data)
|
|
.enter()
|
|
.append("text")
|
|
.attr("class", "dot_label" + column_iter)
|
|
.attr("fill", "white")
|
|
.attr("font-size", "10px")
|
|
.text(function (d, i) {
|
|
if ((i - 2) % 3 == 0) {
|
|
return d[Columns_rank[column_iter]];
|
|
}
|
|
return "";
|
|
})
|
|
.attr("x", (d) => xScale(d.date))
|
|
.attr("y", (d) => yScale(d[Columns[column_iter]]) + 1)
|
|
.attr("text-anchor", "middle");
|
|
}
|
|
}
|
|
|
|
// define content end
|
|
|
|
// legend
|
|
const circle_center_x = 880;
|
|
const circle_center_y = 530;
|
|
|
|
legend_c_1
|
|
.append("circle")
|
|
.attr("cx", circle_center_x)
|
|
.attr("cy", circle_center_y)
|
|
.attr("r", 15)
|
|
.attr("fill", "black");
|
|
|
|
legend_c_1
|
|
.append("text")
|
|
.attr("x", circle_center_x - 9)
|
|
.attr("y", circle_center_y + 3)
|
|
.text("rank")
|
|
.attr("fill", "white")
|
|
.attr("font-size", "10px");
|
|
|
|
legend_c_1
|
|
.append("text")
|
|
.attr("x", circle_center_x - 45)
|
|
.attr("y", circle_center_y + 30)
|
|
.text("BoardGameGeek rank")
|
|
.attr("font-size", "10px");
|
|
|
|
// legend end
|
|
});
|
|
// c-1
|
|
</script>
|
|
|
|
<!-- Q3.c2 -->
|
|
<script>
|
|
var margin = { top: 60, right: 180, bottom: 60, left: 80 };
|
|
var width = 1000 - margin.left - margin.right;
|
|
var height = 600 - margin.top - margin.bottom;
|
|
|
|
// canvas config
|
|
|
|
// c-2
|
|
d3.dsv(",", "boardgame_ratings.csv", function (d) {
|
|
return {
|
|
date: formatDate(d.date),
|
|
"Catan=count": d["Catan=count"],
|
|
"Dominion=count": d["Dominion=count"],
|
|
"Dixit=count": d["Dixit=count"],
|
|
"Codenames=count": d["Codenames=count"],
|
|
"Gloomhaven=count": d["Gloomhaven=count"],
|
|
"Magic: The Gathering=count": d["Magic: The Gathering=count"],
|
|
"Monopoly=count": d["Monopoly=count"],
|
|
"Terraforming Mars=count": d["Terraforming Mars=count"],
|
|
|
|
"Catan=rank": d["Catan=rank"],
|
|
"Dominion=rank": d["Dominion=rank"],
|
|
"Dixit=rank": d["Dixit=rank"],
|
|
"Codenames=rank": d["Codenames=rank"],
|
|
"Gloomhaven=rank": d["Gloomhaven=rank"],
|
|
"Magic: The Gathering=rank": d["Magic: The Gathering=rank"],
|
|
"Monopoly=rank": d["Monopoly=rank"],
|
|
"Terraforming Mars=rank": d["Terraforming Mars=rank"],
|
|
};
|
|
}).then(function (data) {
|
|
// DOM config
|
|
var svg_c_2 = d3.select("body").append("svg").attr("id", "svg-c-2");
|
|
var title_text_c_2 = svg_c_2.append("text").attr("id", "title-c-2");
|
|
var plot_c_2 = svg_c_2.append("g").attr("id", "plot-c-2");
|
|
|
|
// plotlines
|
|
var lines_c_2 = plot_c_2.append("g").attr("id", "lines-c-2");
|
|
|
|
var x_axis_c_2 = plot_c_2
|
|
.append("g")
|
|
.attr("id", "x-axis-c-2")
|
|
.attr("class", "x_axis_c_2")
|
|
.attr("transform", "translate(0," + height + ")");
|
|
var x_axis_c_2_text = x_axis_c_2.append("text");
|
|
|
|
var y_axis_c_2 = plot_c_2.append("g").attr("id", "y-axis-c-2");
|
|
var y_axis_c_2_text = y_axis_c_2.append("text");
|
|
|
|
var symbol_c_2 = plot_c_2.append("g").attr("id", "symbols-c-2");
|
|
var legend_c_2 = svg_c_2.append("g").attr("id", "legend-c-2");
|
|
// DOM config
|
|
|
|
// config
|
|
|
|
var xScale = d3
|
|
.scaleTime()
|
|
.domain(d3.extent(data, (d) => d.date))
|
|
.range([0, width]);
|
|
|
|
yScale_max = -1;
|
|
|
|
Columns = [
|
|
"Catan=count",
|
|
"Dominion=count",
|
|
"Dixit=count",
|
|
"Codenames=count",
|
|
"Gloomhaven=count",
|
|
"Magic: The Gathering=count",
|
|
"Monopoly=count",
|
|
"Terraforming Mars=count",
|
|
];
|
|
|
|
Column_Names = [
|
|
"Catan",
|
|
"Dominion",
|
|
"Dixit",
|
|
"Codenames",
|
|
"Gloomhaven",
|
|
"Magic: The Gathering",
|
|
"Monopoly",
|
|
"Terraforming Mars",
|
|
];
|
|
|
|
Columns_rank = [
|
|
"Catan=rank",
|
|
"Dominion=rank",
|
|
"Dixit=rank",
|
|
"Codenames=rank",
|
|
"Gloomhaven=rank",
|
|
"Magic: The Gathering=rank",
|
|
"Monopoly=rank",
|
|
"Terraforming Mars=rank",
|
|
];
|
|
|
|
for (c in Columns) {
|
|
min_max_col = d3.extent(data, (d) => d[Columns[c]]);
|
|
|
|
if (yScale_max < min_max_col[1]) {
|
|
yScale_max = min_max_col[1];
|
|
}
|
|
}
|
|
|
|
var yScale = d3.scaleLog().domain([1, yScale_max]).range([height, 0]);
|
|
// config
|
|
|
|
// init canvas
|
|
svg_c_2
|
|
.attr("width", width + margin.left + margin.right)
|
|
.attr("height", height + margin.top + margin.bottom);
|
|
|
|
title_text_c_2
|
|
.text("Number of Ratings 2016-2020 (Log Scale)")
|
|
.attr("x", 300)
|
|
.attr("y", 40)
|
|
.attr("font-size", "20px");
|
|
|
|
plot_c_2.attr(
|
|
"transform",
|
|
"translate(" + margin.left + "," + margin.top + ")"
|
|
);
|
|
|
|
x_axis_c_2_text
|
|
.attr("transform", "translate(0," + height + ")")
|
|
.text("Month");
|
|
|
|
y_axis_c_2_text
|
|
.attr("transform", "translate(0,0)")
|
|
.text("Num of Ratings");
|
|
|
|
x_axis_c_2.call(
|
|
d3
|
|
.axisBottom(xScale)
|
|
.tickFormat(d3.timeFormat("%b %y"))
|
|
.tickValues(data.map((d) => d.date))
|
|
.ticks(d3.utcMonth.every(5))
|
|
);
|
|
|
|
const myNode = document.getElementsByClassName("x_axis_c_2");
|
|
const myNode_wkng = myNode[0].getElementsByClassName("tick");
|
|
|
|
iter_node = 2;
|
|
|
|
while (iter_node < myNode_wkng.length) {
|
|
myNode_wkng[0].parentNode.removeChild(myNode_wkng[iter_node - 2]);
|
|
|
|
myNode_wkng[0].parentNode.removeChild(myNode_wkng[iter_node - 2]);
|
|
iter_node = iter_node + 1;
|
|
}
|
|
|
|
nodes_to_remove_at_last = myNode_wkng.length % 3;
|
|
while (nodes_to_remove_at_last > 0) {
|
|
myNode_wkng[0].parentNode.removeChild(
|
|
myNode_wkng[myNode_wkng.length - 1]
|
|
);
|
|
nodes_to_remove_at_last = nodes_to_remove_at_last - 1;
|
|
}
|
|
y_axis_c_2.call(d3.axisLeft(yScale));
|
|
// init canvas end
|
|
|
|
// define content
|
|
for (column_iter in Columns) {
|
|
// lines_c_2
|
|
lines_c_2
|
|
.append("path")
|
|
.datum(data)
|
|
.attr("fill", "none")
|
|
.attr("stroke", d3.schemeCategory10[column_iter])
|
|
.attr("stroke-width", 1.5)
|
|
.attr(
|
|
"d",
|
|
d3
|
|
.line()
|
|
.x((d) => xScale(d.date))
|
|
.y((d) => yScale(+d[Columns[column_iter]]))
|
|
);
|
|
lines_c_2
|
|
.append("text")
|
|
.attr(
|
|
"transform",
|
|
"translate(" +
|
|
(width + 3) +
|
|
"," +
|
|
yScale(data.slice(-1)[0][Columns[column_iter]]) +
|
|
")"
|
|
)
|
|
.attr("dy", ".35em")
|
|
.attr("text-anchor", "start")
|
|
.style("fill", d3.schemeCategory10[column_iter])
|
|
.text(Column_Names[column_iter]);
|
|
}
|
|
|
|
for (column_iter in Columns) {
|
|
console.log({ column_iter });
|
|
if (
|
|
[
|
|
"Catan=count",
|
|
"Codenames=count",
|
|
"Terraforming Mars=count",
|
|
"Gloomhaven=count",
|
|
].indexOf(Columns[column_iter]) > -1
|
|
) {
|
|
symbol_c_2
|
|
.selectAll(".dot" + column_iter)
|
|
.data(data)
|
|
.enter()
|
|
.append("circle")
|
|
.attr("class", "dot" + column_iter)
|
|
.attr("fill", d3.schemeCategory10[column_iter])
|
|
.attr("cx", (d) => xScale(d.date))
|
|
.attr("cy", (d) => yScale(d[Columns[column_iter]]))
|
|
.attr("r", function (d, i) {
|
|
if ((i - 2) % 3 != 0) {
|
|
return 0;
|
|
}
|
|
return 10;
|
|
});
|
|
|
|
symbol_c_2
|
|
.selectAll(".dot_label" + column_iter)
|
|
.data(data)
|
|
.enter()
|
|
.append("text")
|
|
.attr("class", "dot_label" + column_iter)
|
|
.attr("fill", "white")
|
|
.attr("font-size", "10px")
|
|
.text(function (d, i) {
|
|
if ((i - 2) % 3 == 0) {
|
|
return d[Columns_rank[column_iter]];
|
|
}
|
|
return "";
|
|
})
|
|
.attr("x", (d) => xScale(d.date))
|
|
.attr("y", (d) => yScale(d[Columns[column_iter]]) + 1)
|
|
.attr("text-anchor", "middle");
|
|
}
|
|
}
|
|
// define content end
|
|
|
|
// legend
|
|
const circle_center_x = 880;
|
|
const circle_center_y = 530;
|
|
|
|
legend_c_2
|
|
.append("circle")
|
|
.attr("cx", circle_center_x)
|
|
.attr("cy", circle_center_y)
|
|
.attr("r", 15)
|
|
.attr("fill", "black");
|
|
|
|
legend_c_2
|
|
.append("text")
|
|
.attr("x", circle_center_x - 9)
|
|
.attr("y", circle_center_y + 3)
|
|
.text("rank")
|
|
.attr("fill", "white")
|
|
.attr("font-size", "10px");
|
|
|
|
legend_c_2
|
|
.append("text")
|
|
.attr("x", circle_center_x - 45)
|
|
.attr("y", circle_center_y + 30)
|
|
.text("BoardGameGeek rank")
|
|
.attr("font-size", "10px");
|
|
|
|
// legend end
|
|
});
|
|
</script>
|
|
</body>
|