Files
tunmnlu/task_2/hw2_skeleton/Q3/submit9/script.js
louiscklaw 9035c1312b update,
2025-02-01 02:09:32 +08:00

575 lines
16 KiB
JavaScript

function init() {
var margin = 150; //equal margins on all sides
var width = 1000 - 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 svg_a = d3.select("body").append("svg").attr("id", "svg-a");
var svgFig1 = svg_a
.attr("class", "fig1")
.attr("width", width + 2 * margin)
.attr("height", height + 2 * margin)
.append("g")
.attr("id", "plot-a")
.attr("transform", "translate(" + margin + "," + margin + ")");
var g_plot_a = svgFig1;
var g_x_axis_a = g_plot_a.append("g").attr("id", "x-axis-a");
var g_y_axis_a = g_plot_a.append("g").attr("id", "y-axis-a");
var g_lines_a = g_plot_a.append("g").attr("id", "lines-a");
var text_title_a = svg_a.append("text").attr("id", "title-a");
d3.select("body").append("div").attr("class", "pagebreak");
var svg_b = d3.select("body").append("svg").attr("id", "svg-b");
var svgFig2 = svg_b
.attr("class", "fig1")
.attr("width", width + 2 * margin)
.attr("height", height + 2 * margin)
.append("g")
.attr("id", "plot-b")
.attr("transform", "translate(" + margin + "," + margin + ")");
var g_plot_b = svgFig2;
var g_x_axis_b = g_plot_b.append("g").attr("id", "x-axis-b");
var g_y_axis_b = g_plot_b.append("g").attr("id", "y-axis-b");
var g_lines_b = g_plot_b.append("g").attr("id", "lines-b");
var g_symbols_b = g_plot_b.append("g").attr("id", "symbols-b");
var text_title_b = svg_b.append("text").attr("id", "title-b");
var g_legend_b = svg_b
.append("g")
.attr("id", "legend-b")
.attr("transform", "translate(200,170)");
d3.select("body").append("div").attr("class", "pagebreak");
//
var svg_c_1 = d3.select("body").append("svg").attr("id", "svg-c-1");
var svgFig4 = svg_c_1
.attr("class", "fig1")
.attr("width", width + 2 * margin)
.attr("height", height + 2 * margin)
.append("g")
.attr("id", "plot-c-1")
.attr("transform", "translate(" + margin + "," + margin + ")");
var g_plot_c_1 = svgFig4;
var g_x_axis_c_1 = g_plot_c_1.append("g").attr("id", "x-axis-c-1");
var g_y_axis_c_1 = g_plot_c_1.append("g").attr("id", "y-axis-c-1");
var g_lines_c_1 = g_plot_c_1.append("g").attr("id", "lines-c-1");
var g_symbols_c_1 = g_plot_c_1.append("g").attr("id", "symbols-c-1");
var text_title_c_1 = svg_c_1.append("text").attr("id", "title-c-1");
var g_legend_c_1 = svg_c_1
.append("g")
.attr("id", "legend-c-1")
.attr("transform", "translate(200,170)");
//
d3.select("body").append("div").attr("class", "pagebreak");
var svg_c_2 = d3.select("body").append("svg").attr("id", "svg-c-2");
var svgFig3 = svg_c_2
.attr("class", "fig1")
.attr("width", width + 2 * margin)
.attr("height", height + 2 * margin)
.append("g")
.attr("id", "plot-c-2")
.attr("transform", "translate(" + margin + "," + margin + ")");
var g_plot_c_2 = svgFig3;
var g_x_axis_c_2 = g_plot_c_2.append("g").attr("id", "x-axis-c-2");
var g_y_axis_c_2 = g_plot_c_2.append("g").attr("id", "y-axis-c-2");
var g_lines_c_2 = g_plot_c_2.append("g").attr("id", "lines-c-2");
var g_symbols_c_2 = g_plot_c_2.append("g").attr("id", "symbols-c-2");
var text_title_c_2 = svg_c_2.append("text").attr("id", "title-c-2");
var g_legend_c_2 = svg_c_2
.append("g")
.attr("id", "legend-c-2")
.attr("transform", "translate(200,170)");
d3.select("body").append("div").attr("class", "pagebreak");
d3.select("body").append("div").attr("id", "signature").text("tlou31");
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([0, max]);
ySqrt.domain([0, max]);
yLog.domain([1, 99999]);
for (var i in legends) {
var lg = lineGraphs(i);
var lgLog = lineGraphsLog(i);
var lgSqrt = lineGraphsSqrt(i);
g_lines_a
.append("path")
.data([data])
.attr("class", "line")
.attr("d", lg)
.style("stroke", d3.schemeCategory10[i])
// .append("text")
// .text(legends[i]);
g_lines_a
.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]);
g_lines_b
.append("path")
.data([data])
.attr("class", "line")
.attr("d", lg)
.style("stroke", d3.schemeCategory10[i])
// .append("text")
// .text(legends[i]);
g_lines_b
.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]);
g_lines_c_1
.append("path")
.data([data])
.attr("class", "line")
.attr("d", lgSqrt)
.style("stroke", d3.schemeCategory10[i])
// .append("text")
// .text(legends[i]);
g_lines_c_1
.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]);
g_lines_c_2
.append("path")
.data([data])
.attr("class", "line")
.attr("d", lgLog)
.style("stroke", d3.schemeCategory10[i])
// .append("text")
// .text(legends[i]);
g_lines_c_2
.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]);
if (
["Catan", "Codenames", "Terraforming Mars", "Gloomhaven"].includes(
legends[i]
)
) {
// 2
g_symbols_b
.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 y(d[legends[i]]);
})
.attr("r", 10);
// 1
g_symbols_b
.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;
});
g_symbols_c_1
.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);
g_symbols_c_1
.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;
});
g_symbols_c_2
.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);
g_symbols_c_2
.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;
});
}
}
g_legend_b
.append("circle")
.attr("fill", "black")
.attr(
"transform",
"translate(" + (width + 20) + "," + (height - 30) + ")"
)
.attr("r", 10);
g_legend_b
.append("text")
.attr("class", "count-font")
.attr(
"transform",
"translate(" + (width + 10) + "," + (height - 27) + ")"
)
.text("RANK");
g_legend_b
.append("text")
.attr(
"transform",
"translate(" + (width - 30) + "," + (height - 10) + ")"
)
.text("BoardGameGeek Rank");
g_legend_c_1
.append("circle")
.attr("fill", "black")
.attr(
"transform",
"translate(" + (width + 20) + "," + (height - 30) + ")"
)
.attr("r", 10);
g_legend_c_1
.append("text")
.attr("class", "count-font")
.attr(
"transform",
"translate(" + (width + 10) + "," + (height - 27) + ")"
)
.text("RANK");
g_legend_c_1
.append("text")
.attr(
"transform",
"translate(" + (width - 30) + "," + (height - 10) + ")"
)
.text("BoardGameGeek Rank");
g_legend_c_2
.append("circle")
.attr("fill", "black")
.attr(
"transform",
"translate(" + (width + 20) + "," + (height - 30) + ")"
)
.attr("r", 10);
g_legend_c_2
.append("text")
.attr("class", "count-font")
.attr(
"transform",
"translate(" + (width + 10) + "," + (height - 27) + ")"
)
.text("RANK");
g_legend_c_2
.append("text")
.attr(
"transform",
"translate(" + (width - 30) + "," + (height - 10) + ")"
)
.text("BoardGameGeek Rank");
g_x_axis_a
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x).tickFormat(d3.timeFormat("%b %y")));
g_y_axis_a.call(d3.axisLeft(y));
g_x_axis_b
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x).tickFormat(d3.timeFormat("%b %y")));
g_y_axis_b.call(d3.axisLeft(y));
g_x_axis_c_1
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x).tickFormat(d3.timeFormat("%b %y")));
g_y_axis_c_1.call(d3.axisLeft(ySqrt));
g_x_axis_c_2
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x).tickFormat(d3.timeFormat("%b %y")));
g_y_axis_c_2.call(d3.axisLeft(yLog));
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];
}
g_x_axis_a
.append("text")
.attr(
"transform",
"translate(" + width / 2 + " ," + (height + 30) + ")"
)
.style("text-anchor", "middle")
.text("Month");
g_y_axis_a
.append("text")
.attr("y", -50)
.attr("x", -height / 2)
.attr("transform", "rotate(-90)")
.style("text-anchor", "middle")
.text("Num of Ratings");
text_title_a
.attr("x", width / 2)
.attr("y", 50)
.attr("text-anchor", "middle")
.style("font-size", "16px")
.text("Number of Ratings 2016-2020");
g_x_axis_b
.append("text")
.attr(
"transform",
"translate(" + width / 2 + " ," + (height + 30) + ")"
)
.style("text-anchor", "middle")
.text("Month");
g_y_axis_b
.append("text")
.attr("y", -50)
.attr("x", -height / 2)
.attr("transform", "rotate(-90)")
.style("text-anchor", "middle")
.text("Num of Ratings");
text_title_b
.attr("x", width / 2)
.attr("y", 50)
.attr("text-anchor", "middle")
.style("font-size", "16px")
.text("Number of Ratings 2016-2020 with Rankings");
g_x_axis_c_1
.append("text")
.attr(
"transform",
"translate(" + width / 2 + " ," + (height + 30) + ")"
)
.style("text-anchor", "middle")
.text("Month");
g_y_axis_c_1
.append("text")
.attr("y", -50)
.attr("x", -height / 2)
.attr("transform", "rotate(-90)")
.style("text-anchor", "middle")
.text("Num of Ratings");
text_title_c_1
.attr("x", width / 2)
.attr("y", 50)
.attr("text-anchor", "middle")
.style("font-size", "16px")
.text(
"Number of Ratings 2016-2020 with Rankings (Square Root Scale)"
);
g_x_axis_c_2
.append("text")
.attr(
"transform",
"translate(" + width / 2 + " ," + (height + 30) + ")"
)
.style("text-anchor", "middle")
.text("Month");
g_y_axis_c_2
.append("text")
.attr("y", -50)
.attr("x", -height / 2)
.attr("transform", "rotate(-90)")
.style("text-anchor", "middle")
.text("Num of Ratings");
text_title_c_2
.attr("x", width / 2)
.attr("y", 50)
.attr("text-anchor", "middle")
.style("font-size", "16px")
.text("Number of Ratings 2016-2020 with Rankings (Log Scale)");
})
.catch(function (error) {
console.log(error);
});
}