mirror of
https://github.com/placeAtlas/atlas.git
synced 2024-11-16 15:01:44 +01:00
294 lines
5.7 KiB
JavaScript
294 lines
5.7 KiB
JavaScript
/*
|
|
========================================================================
|
|
The 2022 /r/place Atlas
|
|
|
|
An Atlas of Reddit's 2022 /r/place, with information to each
|
|
artwork of the canvas provided by the community.
|
|
|
|
Copyright (c) 2017 Roland Rytz <roland@draemm.li>
|
|
Copyright (c) 2022 r/placeAtlas2 contributors
|
|
|
|
Licensed under the GNU Affero General Public License Version 3
|
|
https://place-atlas.stefanocoding.me/license.txt
|
|
========================================================================
|
|
*/
|
|
|
|
let areasSum = 0;
|
|
const areas = [];
|
|
|
|
for (let q = 0; q < atlas.length; q++) {
|
|
|
|
const path = atlas[q].path;
|
|
|
|
let area = 0,
|
|
i,
|
|
j,
|
|
point1,
|
|
point2;
|
|
|
|
for (i = 0, j = path.length - 1; i < path.length; j = i, i++) {
|
|
point1 = path[i];
|
|
point2 = path[j];
|
|
area += point1[0] * point2[1];
|
|
area -= point1[1] * point2[0];
|
|
}
|
|
|
|
area = Math.abs(area / 2);
|
|
|
|
areasSum += area;
|
|
areas.push(area);
|
|
|
|
atlas[q].area = area;
|
|
|
|
}
|
|
|
|
areas.sort(function (a, b) {
|
|
if (a < b) {
|
|
return -1;
|
|
}
|
|
if (a > b) {
|
|
return 1;
|
|
}
|
|
// a must be equal to b
|
|
return 0;
|
|
});
|
|
|
|
atlas.sort(function (a, b) {
|
|
if (a.area < b.area) {
|
|
return -1;
|
|
}
|
|
if (a.area > b.area) {
|
|
return 1;
|
|
}
|
|
// a must be equal to b
|
|
return 0;
|
|
});
|
|
|
|
const el = document.createElement("canvas");
|
|
el.style.position = "absolute";
|
|
el.style.top = "0px";
|
|
el.style.zIndex = "10000";
|
|
const ctx = el.getContext("2d");
|
|
el.width = 1600;
|
|
el.height = 500;
|
|
const steps = 150;
|
|
const max = 1500;
|
|
|
|
let largerThanMax = 0;
|
|
|
|
for (const i in areas) {
|
|
if (areas[i] > max) {
|
|
largerThanMax++;
|
|
}
|
|
}
|
|
|
|
console.info("There are " + largerThanMax + " entries larger than " + max + ", accounting for " + (largerThanMax / areas.length * 100) + "% of all entries.");
|
|
console.info("The largest entry has an area of " + areas[areas.length - 1] + " pixels.");
|
|
|
|
const counts = [0];
|
|
const brackets = [max / steps];
|
|
|
|
let bracket = 0;
|
|
|
|
let mostCounts = 0;
|
|
|
|
for (const i in areas) {
|
|
if (areas[i] > (bracket + 1) * (max / steps)) {
|
|
mostCounts = Math.max(mostCounts, counts[bracket]);
|
|
bracket++;
|
|
if (bracket >= steps) {
|
|
break;
|
|
}
|
|
counts[bracket] = 0;
|
|
brackets[bracket] = (bracket + 1) * (max / steps);
|
|
}
|
|
counts[bracket]++;
|
|
}
|
|
//console.log(counts);
|
|
//console.log(brackets);
|
|
//console.log(mostCounts);
|
|
|
|
ctx.fillStyle = "#FFFFFF";
|
|
ctx.fillRect(0, 0, el.width, el.height);
|
|
ctx.strokeStyle = "#F5F5F5";
|
|
|
|
ctx.fillStyle = "#333333";
|
|
ctx.font = "15px sans";
|
|
ctx.textAlign = "right";
|
|
ctx.textBaseline = "middle";
|
|
|
|
let linesDistance = 1;
|
|
|
|
for (let i = 0; i <= Math.ceil((mostCounts / linesDistance) / 5) * 5; i++) {
|
|
ctx.beginPath();
|
|
ctx.moveTo(
|
|
50
|
|
, ~~(el.height - 50 - i * (linesDistance / mostCounts) * (el.height - 100)) + 0.5
|
|
);
|
|
ctx.lineTo(
|
|
el.width - 25
|
|
, ~~(el.height - 50 - i * (linesDistance / mostCounts) * (el.height - 100)) + 0.5
|
|
);
|
|
ctx.stroke();
|
|
}
|
|
|
|
ctx.strokeStyle = "#333333";
|
|
linesDistance = 5;
|
|
|
|
for (let i = 0; i <= Math.ceil(mostCounts / linesDistance); i++) {
|
|
ctx.beginPath();
|
|
ctx.moveTo(
|
|
50
|
|
, ~~(el.height - 50 - i * (linesDistance / mostCounts) * (el.height - 100)) + 0.5
|
|
);
|
|
ctx.lineTo(
|
|
el.width - 25
|
|
, ~~(el.height - 50 - i * (linesDistance / mostCounts) * (el.height - 100)) + 0.5
|
|
);
|
|
ctx.stroke();
|
|
|
|
ctx.fillText(
|
|
i * linesDistance
|
|
, 40
|
|
, ~~(el.height - 50 - i * (linesDistance / mostCounts) * (el.height - 100)) + 0.5
|
|
);
|
|
}
|
|
|
|
const skip = 2;
|
|
|
|
ctx.textAlign = "center";
|
|
ctx.textBaseline = "hanging";
|
|
ctx.font = "10px sans";
|
|
|
|
let a = 0;
|
|
for (let i = 0; i <= counts.length; i++) {
|
|
if (i % skip == 0) {
|
|
let y = 0;
|
|
if (a % 2 == 0) {
|
|
y = ~~(el.height - 30) + 0.5;
|
|
} else {
|
|
y = ~~(el.height - 45) + 0.5;
|
|
}
|
|
a++;
|
|
ctx.beginPath();
|
|
ctx.moveTo(
|
|
~~(((i) / steps) * (el.width - 125) + 75) + 0.5
|
|
, ~~(el.height - 50) + 0.5
|
|
);
|
|
ctx.lineTo(
|
|
~~(((i) / steps) * (el.width - 125) + 75) + 0.5
|
|
, y
|
|
);
|
|
ctx.stroke();
|
|
|
|
ctx.fillText(
|
|
(i) * (max / steps)
|
|
, ~~(((i) / steps) * (el.width - 125) + 75) - 0.5
|
|
, y + 5
|
|
);
|
|
}
|
|
}
|
|
|
|
ctx.fillStyle = "#FF0000";
|
|
ctx.strokeStyle = "#CC0000";
|
|
|
|
for (let i = 0; i < counts.length; i++) {
|
|
if (i % 2 == 0) {
|
|
ctx.fillStyle = "#FF0000";
|
|
} else {
|
|
ctx.fillStyle = "#DD0000";
|
|
}
|
|
|
|
ctx.fillRect(
|
|
~~((i / steps) * (el.width - 125) + 75)
|
|
, el.height - 50
|
|
, Math.ceil(1 / steps * (el.width - 125))
|
|
, ~~(-(counts[i] / mostCounts) * (el.height - 100))
|
|
);
|
|
|
|
/*ctx.beginPath();
|
|
ctx.moveTo(
|
|
~~((i/steps)*(el.width-125)+75)+0.5
|
|
,~~(el.height - 50)
|
|
);
|
|
ctx.lineTo(
|
|
~~((i/steps)*(el.width-125)+75)+0.5
|
|
,~~(el.height-(counts[i]/mostCounts)*(el.height-100))-50+0.5
|
|
);
|
|
ctx.lineTo(
|
|
~~(((i+1)/steps)*(el.width-125)+75)+0.5
|
|
,~~(el.height-(counts[i]/mostCounts)*(el.height-100))-50+0.5
|
|
);
|
|
ctx.lineTo(
|
|
~~(((i+1)/steps)*(el.width-125)+75)+0.5
|
|
,~~(el.height - 50)
|
|
);
|
|
ctx.stroke();*/
|
|
}
|
|
|
|
document.getElementById("wrapper").appendChild(el);
|
|
|
|
//console.log(areas);
|
|
|
|
console.info("Median area: " + areas[~~(areas.length / 2)]);
|
|
|
|
console.info("Average area: " + (areasSum / atlas.length));
|
|
|
|
const topCount = 50;
|
|
console.info("The " + topCount + " largest entries:");
|
|
|
|
let outstring = "";
|
|
|
|
for (let i = 0; i < topCount; i++) {
|
|
outstring += ((i + 1) + "|[" + atlas[atlas.length - i - 1].name + "](http://place-atlas.stefanocoding.me/?id=" + atlas[atlas.length - i - 1].id + ")|" + ~~atlas[atlas.length - i - 1].area + "|" + Math.round(atlas[atlas.length - i - 1].area / 100) / 100 + "%\n");
|
|
}
|
|
|
|
console.info(outstring);
|
|
|
|
atlas.sort(function (a, b) {
|
|
if (a.center[0] < b.center[0]) {
|
|
return -1;
|
|
}
|
|
if (a.center[0] > b.center[0]) {
|
|
return 1;
|
|
}
|
|
// a must be equal to b
|
|
return 0;
|
|
});
|
|
|
|
console.info("Median x: " + atlas[~~(atlas.length / 2)].center[0]);
|
|
|
|
atlas.sort(function (a, b) {
|
|
if (a.center[1] < b.center[1]) {
|
|
return -1;
|
|
}
|
|
if (a.center[1] > b.center[1]) {
|
|
return 1;
|
|
}
|
|
// a must be equal to b
|
|
return 0;
|
|
});
|
|
|
|
console.info("Median y: " + atlas[~~(atlas.length / 2)].center[1]);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|