Merge branch 'cleanup' of github.com:GeoDash897/place-atlas into cleanup

This commit is contained in:
GeoDash897 2022-04-09 19:35:19 -04:00
commit b5bb462748
18 changed files with 2339 additions and 2452 deletions

1
.gitignore vendored
View file

@ -13,3 +13,4 @@ combined.js
*.DS_Store
.vscode/
web/atlas-before-ids-migration.json
*.pyc

View file

@ -1,4 +1,4 @@
[![Entry count](https://img.shields.io/badge/dynamic/json?color=blue&label=count&query=%24.length&url=https%3A%2F%2Fgithub.com%2FplaceAtlas%2Fatlas%2Fblob%2Fmaster%2Fweb%2Fatlas.json%3Fraw%3Dtrue)](https://place-atlas.stefanocoding.me/)
[![Entry count](https://img.shields.io/badge/dynamic/json?color=blue&label=entries&query=%24.length&url=https%3A%2F%2Fgithub.com%2FplaceAtlas%2Fatlas%2Fblob%2Fmaster%2Fweb%2Fatlas.json%3Fraw%3Dtrue)](https://place-atlas.stefanocoding.me/)
![Commit activity](https://img.shields.io/github/commit-activity/w/placeAtlas/atlas)
[![Netlify](https://img.shields.io/netlify/1e7291ce-0680-45ed-9843-47a32a992bbb?logo=netlify&logoColor=white)](https://app.netlify.com/sites/place-atlas/deploys)
[![License](https://img.shields.io/github/license/placeAtlas/atlas)](https://github.com/placeAtlas/atlas/blob/master/LICENSE)

View file

@ -35,7 +35,10 @@
}
CL_REGEX = r'\[(.+?)\]\((.+?)\)'
CWTS_REGEX = r'^(?:(?:https?:\/\/)?(?:(?:www|old|new|np)\.)?)?reddit\.com\/r\/([A-Za-z0-9][A-Za-z0-9_]{1,20})(?:\/)$'
CWTS_REGEX = {
"url": r'^(?:(?:https?:\/\/)?(?:(?:www|old|new|np)\.)?)?reddit\.com\/r\/([A-Za-z0-9][A-Za-z0-9_]{1,20})(?:\/)$',
"subreddit": r'^\/*[rR]\/([A-Za-z0-9][A-Za-z0-9_]{1,20})\/?$'
}
CSTW_REGEX = {
"website": r'^https?://[^\s/$.?#].[^\s]*$',
"user": r'^\/*u\/([A-Za-z0-9][A-Za-z0-9_]{1,20})$'
@ -46,6 +49,9 @@
USER_TEMPLATE = r"/u/\1"
def format_subreddit(entry: dict):
"""
Fix formatting of the value on "subreddit".
"""
if not "subreddit" in entry or not entry['subreddit']:
return entry
@ -65,9 +71,7 @@ def format_subreddit(entry: dict):
return entry
def collapse_links(entry: dict):
if not "website" in entry or not entry['website']:
return entry
if "website" in entry and entry['website']:
website = entry["website"];
if re.search(CL_REGEX, website):
match = re.search(CL_REGEX, website)
@ -75,9 +79,22 @@ def collapse_links(entry: dict):
website = match.group(2)
entry["website"] = website
if "subreddit" in entry and entry['subreddit']:
subreddit = entry["subreddit"];
if re.search(CL_REGEX, subreddit):
match = re.search(CL_REGEX, subreddit)
if match.group(1) == match.group(2):
subreddit = match.group(2)
entry["subreddit"] = subreddit
return entry
def remove_extras(entry: dict):
"""
Removing unnecessary extra characters and converts select characters.
"""
if "subreddit" in entry and entry["subreddit"]:
# if not entry["subreddit"].startswith('/r/'):
# entry["subreddit"] = re.sub(r'^(.*)(?=\/r\/)', r'', entry["subreddit"])
@ -94,6 +111,9 @@ def remove_extras(entry: dict):
entry[key] = re.sub(r'\n{3,}', r'\n\n', entry[key])
entry[key] = re.sub(r'r\/{2,}', r'r\/', entry[key])
entry[key] = re.sub(r',{2,}', r',', entry[key])
# Smart quotation marks
entry[key] = re.sub(r'[\u201c\u201d]', '"', entry[key])
entry[key] = re.sub(r'[\u2018\u2019]', "'", entry[key])
# Psuedo-empty strings
if entry[key] in ["n/a", "N/A", "na", "NA", "-", "null", "none", "None"]:
entry[key] = ""
@ -101,6 +121,9 @@ def remove_extras(entry: dict):
return entry
def fix_r_caps(entry: dict):
"""
Fixes capitalization of /r/. (/R/place -> /r/place)
"""
if not "description" in entry or not entry['description']:
return entry
@ -110,6 +133,9 @@ def fix_r_caps(entry: dict):
return entry
def fix_no_protocol_urls(entry: dict):
"""
Fixes URLs with no protocol by adding "https://" protocol.
"""
if not "website" in entry or not entry['website']:
return entry
@ -119,11 +145,21 @@ def fix_no_protocol_urls(entry: dict):
return entry
def convert_website_to_subreddit(entry: dict):
"""
Converts the subreddit link on "website" to "subreddit" if possible.
"""
if not "website" in entry or not entry['website']:
return entry
if re.match(CWTS_REGEX, entry["website"]):
new_subreddit = re.sub(CWTS_REGEX, SUBREDDIT_TEMPLATE, entry["website"])
if re.match(CWTS_REGEX["url"], entry["website"]):
new_subreddit = re.sub(CWTS_REGEX["url"], SUBREDDIT_TEMPLATE, entry["website"])
if (new_subreddit.lower() == entry["subreddit"].lower()):
entry["website"] = ""
elif not "subreddit" in entry or entry['subreddit'] == "":
entry["subreddit"] = new_subreddit
entry["website"] = ""
elif re.match(CWTS_REGEX["subreddit"], entry["website"]):
new_subreddit = re.sub(CWTS_REGEX["subreddit"], SUBREDDIT_TEMPLATE, entry["website"])
if (new_subreddit.lower() == entry["subreddit"].lower()):
entry["website"] = ""
elif not "subreddit" in entry or entry['subreddit'] == "":
@ -133,6 +169,9 @@ def convert_website_to_subreddit(entry: dict):
return entry
def convert_subreddit_to_website(entry: dict):
"""
Converts the links on "subreddit" to a "website" if needed. This also supports Reddit users (/u/reddit).
"""
if not "subreddit" in entry or not entry['subreddit']:
return entry
@ -150,29 +189,103 @@ def convert_subreddit_to_website(entry: dict):
return entry
def calculate_center(path: list):
"""
Caluclates the center of a polygon
adapted from /web/_js/draw.js:calucalteCenter()
"""
area = 0
x = 0
y = 0
for i in range(len(path)):
point1 = path[i]
point2 = path[i-1 if i != 0 else len(path)-1]
f = point1[0] * point2[1] - point2[0] * point1[1]
area += f
x += (point1[0] + point2[0]) * f
y += (point1[1] + point2[1]) * f
area *= 3
if area != 0:
return [x // area + 0.5, y // area + 0.5]
else:
# get the center of a straight line
max_x = max(i[0] for i in path)
min_x = min(i[0] for i in path)
max_y = max(i[1] for i in path)
min_y = min(i[1] for i in path)
return [(max_x + min_x) // 2 + 0.5, (max_y + min_y) // 2 + 0.5]
def update_center(entry: dict):
"""
checks if the center of a entry is up to date, and updates it if it's either missing or outdated
"""
if 'path' not in entry:
return entry
path = entry['path']
if len(path) > 1:
calculated_center = calculate_center(path)
if 'center' not in entry or entry['center'] != calculated_center:
entry['center'] = calculated_center
return entry
def validate(entry: dict):
"""
Validates the entry. Catch errors and tell warnings related to the entry.
Status code key:
0: All valid, no problems
1: Informational logs that may be ignored
2: Warnings that may effect user experience when interacting with the entry
3: Errors that make the entry inaccessible or broken.
"""
return_status = 0
if (not "id" in entry or (not entry['id'] and not entry['id'] == 0)):
print(f"Wait, no id here! How did this happened? {entry}")
return
return_status = 3
entry['id'] = '[MISSING_ID]'
if not ("path" in entry and isinstance(entry["path"], list) and len(entry["path"]) > 0):
print(f"Entry {entry['id']} has no points!")
return_status = 3
elif len(entry["path"]) < 3:
print(f"Entry {entry['id']} only has {len(entry['path'])} point(s)!")
return_status = 3
for key in entry:
if key in VALIDATE_REGEX and not re.match(VALIDATE_REGEX[key], entry[key]):
if return_status < 2: return_status = 2
print(f"{key} of entry {entry['id']} is still invalid! {entry[key]}")
return return_status
def per_line_entries(entries: list):
"""
Returns a string of all the entries, with every entry in one line.
"""
out = "[\n"
for entry in entries:
out += json.dumps(entry) + ",\n"
if entry:
out += json.dumps(entry, ensure_ascii=False) + ",\n"
out = out[:-2] + "\n]"
return out
def format_all(entry: dict, silent=False):
"""
Format using all the available formatters.
Outputs a tuple containing the entry and the validation status code.
Status code key:
0: All valid, no problems
1: Informational logs that may be ignored
2: Warnings that may effect user experience when interacting with the entry
3: Errors that make the entry inaccessible or broken.
"""
def print_(*args, **kwargs):
if not silent:
print(*args, **kwargs)
print_("Fixing r/ capitalization...")
entry = fix_r_caps(entry)
print_("Fixing links without protocol...")
entry = fix_no_protocol_urls(entry)
print_("Fix formatting of subreddit...")
entry = format_subreddit(entry)
print_("Collapsing Markdown links...")
@ -181,12 +294,16 @@ def print_(*args, **kwargs):
entry = convert_website_to_subreddit(entry)
print_("Converting subreddit links to website (if needed)...")
entry = convert_subreddit_to_website(entry)
print_("Fixing links without protocol...")
entry = fix_no_protocol_urls(entry)
print_("Removing extras...")
entry = remove_extras(entry)
print_("Updating center")
entry = update_center(entry)
print_("Validating...")
validate(entry)
status_code = validate(entry)
print_("Completed!")
return entry
return ( entry, status_code )
if __name__ == '__main__':
@ -198,7 +315,12 @@ def go(path):
entries = json.loads(f1.read())
for i in range(len(entries)):
entries[i] = format_all(entries[i], True)
entry_formatted, validation_status = format_all(entries[i], True)
if validation_status > 2:
print(f"Entry {entry_formatted['id']} will be removed! {json.dumps(entry_formatted)}")
entries[i] = None
else:
entries[i] = entry_formatted
if not (i % 500):
print(f"{i} checked.")
@ -210,4 +332,3 @@ def go(path):
print("Writing completed. All done.")
go("../web/atlas.json")
go("../web/atlas-before-ids-migration.json")

View file

@ -13,8 +13,8 @@
credentials = file.readlines()
client_id = credentials[0].strip()
client_secret = credentials[1].strip()
username = credentials[2].strip()
password = credentials[3].strip()
username = credentials[2].strip() if len(credentials) > 3 else ""
password = credentials[3].strip() if len(credentials) > 3 else ""
reddit = praw.Reddit(
client_id=client_id,
@ -102,9 +102,6 @@ def set_flair(submission, flair):
if submission_json:
# Assert if path does not empty
assert len(submission_json["path"]) > 0
submission_json_dummy = {"id": submission.id, "submitted_by": ""}
try:
submission_json_dummy["submitted_by"] = submission.author.name
@ -113,9 +110,12 @@ def set_flair(submission, flair):
for key in submission_json:
if not key in submission_json_dummy:
submission_json_dummy[key] = submission_json[key];
submission_json = format_all(submission_json_dummy, True)
(submission_json, validation_status) = format_all(submission_json_dummy, True)
outfile.write(json.dumps(submission_json) + ",\n")
assert validation_status < 3, \
"Submission invalid after validation. This may be caused by not enough points on the path."
outfile.write(json.dumps(submission_json, ensure_ascii=False) + ",\n")
successcount += 1
set_flair(submission, "Processed Entry")

View file

@ -1,23 +1,16 @@
<!--
========================================================================
The /r/place Atlas
The 2022 /r/place Atlas
An Atlas of Reddit's /r/place, with information to each
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>
Licensed under the GNU Affero General Public License Version 3
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
For more information, see:
http://place-atlas.stefanocoding.me/license.txt
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
========================================================================
-->

View file

@ -1,22 +1,15 @@
/*
========================================================================
The /r/place Atlas
The 2022 /r/place Atlas
An Atlas of Reddit's /r/place, with information to each
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>
Licensed under the GNU Affero General Public License Version 3
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
For more information, see:
https://draemm.li/various/place-atlas/license.txt
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
========================================================================
*/
@ -78,9 +71,7 @@ a:hover {
}
button,
#exportDirectPost,
#aboutBackButton,
#drawBackButton {
.button {
background-image: linear-gradient(to bottom, #888, #666);
border: 1px #000 solid;
color: #FFF;
@ -91,12 +82,15 @@ #drawBackButton {
text-shadow: 1px 1px 0 #444;
}
button::-moz-focus-inner {
button::-moz-focus-inner,
.button::-moz-focus-inner {
border: 0;
}
button:disabled,
button:disabled:hover {
button:disabled:hover,
.button:disabled,
.button:disabled:hover {
background-image: none;
background-color: #666;
color: #AAA;
@ -104,9 +98,7 @@ button:disabled:hover {
}
button:hover,
#exportDirectPost:hover,
#aboutBackButton:hover,
#drawBackButton:hover {
.button:hover {
background-image: linear-gradient(to bottom, #999, #777);
text-decoration: none;
}
@ -257,7 +249,7 @@ #loading {
left: 0;
right: 0;
bottom: 0;
z-index: 100;
z-index: 1000;
}
#loading > div {
@ -514,7 +506,7 @@ #drawControlsContainer {
padding: 0 20px;
}
.draw #drawControlsContainer {
[data-mode="draw"] #drawControlsContainer {
display: block;
}
@ -616,6 +608,7 @@ .overlay {
background-color: rgba(0, 0, 0, .8);
display: none;
justify-content: center;
z-index: 1000;
}
#exportWindow {
@ -664,15 +657,15 @@ #coordsWrapper {
display: flex;
gap: 10px;
z-index: 100;
top: 5px;
left: 364px;
}
.collapsed {
#wrapper.listHidden #coordsWrapper {
top: 49px;
left: 149px;
}
.uncollapsed {
top: 49px;
left: 380px;
}
@media (max-width: 750px) {
#coordsWrapper {
display: none;
@ -681,9 +674,8 @@ @media (max-width: 750px) {
#coords {
background-color: #555;
border: 1px #000 solid;
padding: 3px;
font-size: 18px;
z-index: 1100;
padding: 6.5px;
font-size: 17px;
display: flex;
align-items: center;
justify-content: center;
@ -702,7 +694,6 @@ #bottomBar {
right: 10px;
display: flex;
gap: 10px;
z-index: 100;
}
div:not(.listHidden) > #bottomBar {
@ -863,18 +854,18 @@ @media (max-width: 500px) {
height: 40px;
}
#entriesListContainer > nav {
#entriesListNav {
width: calc(100% - 45px);
}
}
@media (max-width: 350px) {
#entriesListContainer > nav > a#drawLink {
#entriesListNav > a#drawLink {
display: none;
}
}
.draw #entriesListContainer {
[data-mode="draw"] #entriesListContainer {
display: none;
}
@ -882,55 +873,48 @@ .listHidden #entriesListContainer {
display: none;
}
#entriesListContainer > nav {
#entriesListNav {
margin: 10px 0;
display: flex;
flex-shrink: 0;
justify-content: center;
}
#entriesListContainer > nav > a,
#entriesListContainer > nav > button {
background-image: linear-gradient(to bottom, #888, #666);
border: 1px #000 solid;
color: #FFF;
text-align: center;
#entriesListNav > * {
display: block;
padding: 4px;
cursor: pointer;
width: 120px;
height: 30px;
margin-right: 10px;
text-shadow: 1px 1px 0 #444;
}
#entriesListContainer > nav > button {
#entriesListNav > .small {
width: 30px;
padding: 2px;
flex-shrink: 0;
}
#entriesListContainer > nav > button > img {
#entriesListNav > .small > img {
height: 22px;
width: 22px;
}
#entriesListContainer > nav > button:last-child {
#entriesListNav > .small:last-child {
margin-right: 0;
}
#entriesListContainer > nav > a:hover {
#entriesListNav > a:hover {
text-decoration: none;
background-image: linear-gradient(to bottom, #999, #777);
}
#entriesListContainer > nav > button:hover {
#entriesListNav > .small:hover {
background-image: none;
background: transparent;
border-color: transparent;
}
#entriesListContainer > nav > button:hover > img {
#entriesListDonate:hover > img {
text-decoration: none;
background-image: linear-gradient(to bottom, #FFAA00, #FFAA00);
border-radius: 15px;
@ -939,7 +923,7 @@ #entriesListContainer > nav > button:hover > img {
height: 28px;
width: 28px;
}
#entriesListContainer > nav > button:hover > img.Discord {
#entriesListDiscord:hover > img {
text-decoration: none;
background-image: linear-gradient(to bottom, #7289DA, #7289DA);
border-radius: 12px;
@ -955,12 +939,12 @@ #entriesListBackground {
top: 50px;
bottom: 0;
width: 360px;
z-index: -600;
z-index: -400;
background-color: #333;
border-right: 1px #000 solid;
}
.draw #entriesListBackground {
[data-mode="draw"] #entriesListBackground {
display: none;
}
@ -994,7 +978,7 @@ #hideListButton:hover {
background-color: #555;
}
.draw #hideListButton {
[data-mode="draw"] #hideListButton {
display: none;
}
@ -1009,7 +993,7 @@ .listHidden #hideListButton {
border-top: 1px #333 solid;
width: 130px;
height: 35px;
z-index: 2000;
z-index: 100;
}
#hideListButton:focus {
@ -1029,6 +1013,10 @@ #entriesListControls input:focus {
border-color: #CCC;
}
[data-mode="explore"] #entriesListControls {
display: none;
}
#atlasSize {
display: block;
margin: 3px 0 5px 0;
@ -1080,7 +1068,7 @@ #aboutContainer {
}
#aboutBackButton {
margin: 20px 20px 0 20px;
margin: 20px 0 20px;
padding: 10px 20px;
}
@ -1124,11 +1112,10 @@ #contributors a {
line-height: 26px;
}
#bitcoinButton {
#donateButton {
cursor: pointer;
}
#bitcoinWindow,
#donateWindow {
display: inline-block;
z-index: 2000;
@ -1150,10 +1137,6 @@ #donateWindow {
max-width: 800px;
}
#donateWindow > #bitcoinQR {
}
#donateWindow > p {
margin: 2px 0;
padding: 0 20px;
@ -1161,13 +1144,11 @@ #donateWindow > p {
width: 100%;
}
#bitcoinWindow > *,
#donateWindow > * {
display: inline-block;
margin: 5px 0;
}
#bitcoinWindow > h2,
#donateWindow > h2 {
font-weight: 200;
background-color: #555;
@ -1177,7 +1158,6 @@ #donateWindow > h2 {
text-shadow: 1px 1px 0 #000;
}
#bitcoinWindow input,
#donateWindow input {
width: 100%;
max-width: 350px;
@ -1188,7 +1168,6 @@ #donateWindow input {
color: #FFF;
}
#bitcoinWindow button,
#donateWindow button {
padding: 10px 20px;
margin-bottom: 20px;
@ -1201,7 +1180,68 @@ h2#abouth2 {
text-shadow: 2px 2px 0 #000;
}
#bitcoinNotice {
color: #AAA;
margin-top: 7px;
#viewModes {
position: relative;
display: inline-block;
}
#viewModes .buffer {
bottom: -10px;
left: 0;
position: absolute;
height: 20px;
width: 100%
}
#viewModes .dropdown-content {
margin-top: 1.5rem;
top: 10px;
left: 0;
position: absolute;
display: none;
background: #666;
border: 1px #000 solid;
cursor: pointer;
width: 125%
}
#viewModes .dropdown-content a {
color: #FFF;
text-align: left;
padding: 5px 10px;
display: block;
text-decoration: none;
text-shadow: 1px 1px 0 #444;
}
#viewModes .dropdown-content a:hover {
background-image: linear-gradient(to bottom, #999, #777);
}
#viewModes:hover .dropdown-content,
#viewModes:active .dropdown-content {
display: block;
}
body:not([data-dev]) .show-only-on-dev {
display: none !important;
}
#netlifyBadges {
display: flex;
align-items: center;
gap: .5rem
}
#donateWindow a.button {
padding: 1rem
}
#donateWindow a.button svg {
height: 1em;
vertical-align: -0.125em;
}
#donateWindow a.button path {
color: white;
}

View file

@ -1,22 +1,15 @@
/*
========================================================================
The /r/place Atlas
The 2022 /r/place Atlas
An Atlas of Reddit's /r/place, with information to each
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>
Licensed under the GNU Affero General Public License Version 3
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
For more information, see:
http://place-atlas.stefanocoding.me/license.txt
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
========================================================================
*/
@ -25,7 +18,7 @@ window.addEventListener("error", function (e) {
var errorMessage = "<p class=\"error\">An error has occurred:</p>";
errorMessage += "<p class=\"errorBody\">" + e.message + "</p>";
errorMessage += "<p class=\"errorBody\">on line " + e.lineno + "</p>";
errorMessage += "<p class=\"error\">If this keeps happening, feel free to send me a <a href=\"mailto:roland.rytz@gmail.com\">mail</a>.</p>";
errorMessage += "<p class=\"error\">If this keeps happening, feel free to tell us on <a href=\"https://discord.gg/pJkm23b2nA\">our Discord server</a>.</p>";
document.getElementById("loadingContent").innerHTML = errorMessage;
});

View file

@ -1,32 +1,26 @@
/*
========================================================================
The /r/place Atlas
The 2022 /r/place Atlas
An Atlas of Reddit's /r/place, with information to each
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>
Licensed under the GNU Affero General Public License Version 3
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
For more information, see:
http://place-atlas.stefanocoding.me/license.txt
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
========================================================================
*/
function initDraw(){
wrapper.classList.remove('listHidden')
window.render = render
window.renderBackground = renderBackground
window.updateHovering = updateHovering
var finishButton = document.getElementById("finishButton");
var resetButton = document.getElementById("resetButton");
var undoButton = document.getElementById("undoButton");
@ -46,14 +40,10 @@ function initDraw(){
var lShiftPressed = false;
var shiftPressed = false;
var backgroundCanvas = document.createElement("canvas");
backgroundCanvas.width = 2000;
backgroundCanvas.height = 2000;
var backgroundContext = backgroundCanvas.getContext("2d");
var highlightUncharted = true;
renderBackground();
applyView();
container.style.cursor = "crosshair";
@ -62,8 +52,6 @@ function initDraw(){
var undoHistory = [];
var lastPos = [0, 0];
render(path);
container.addEventListener("mousedown", function(e){
@ -119,6 +107,8 @@ function initDraw(){
if(!dragging && drawing && path.length > 0){
console.log(123)
var coords = getCanvasCoords(e.clientX, e.clientY);
render(path.concat([coords]));
}
@ -244,17 +234,8 @@ function initDraw(){
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 *= 3;
var x = 0,
point2,
x = 0,
y = 0,
f;
@ -262,12 +243,13 @@ function initDraw(){
point1 = path[i];
point2 = path[j];
f = point1[0] * point2[1] - point2[0] * point1[1];
area += f;
x += (point1[0] + point2[0]) * f;
y += (point1[1] + point2[1]) * f;
}
area *= 3;
return [~~(x / area)+0.5, ~~(y / area)+0.5];
return [Math.floor(x / area)+0.5, Math.floor(y / area)+0.5];
}
function undo(){
@ -390,6 +372,18 @@ function initDraw(){
}
function updateHovering(e, tapped){
if(!dragging && (!fixed || tapped)){
var pos = [
(e.clientX - (container.clientWidth/2 - innerContainer.clientWidth/2 + zoomOrigin[0] + container.offsetLeft))/zoom
,(e.clientY - (container.clientHeight/2 - innerContainer.clientHeight/2 + zoomOrigin[1] + container.offsetTop))/zoom
];
var coords_p = document.getElementById("coords_p");
coords_p.innerText = Math.ceil(pos[0]) + ", " + Math.ceil(pos[1]);
}
}
}

View file

@ -1,3 +1,18 @@
/*
========================================================================
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
========================================================================
*/
function createInfoBlock(entry) {
function createInfoParagraph(name, value){
let entryParagraphPositionElement = document.createElement("p");
@ -35,7 +50,7 @@ function createInfoBlock(entry) {
}
let [x, y] = entry.center;
element.appendChild(createInfoParagraph("Position: ", `${Math.floor(x)}x${Math.floor(y)}`));
element.appendChild(createInfoParagraph("Position: ", `${Math.floor(x)}, ${Math.floor(y)}`));
if(entry.path){
let area = calcPolygonArea(entry.path);

View file

@ -1,28 +1,19 @@
/*
========================================================================
The /r/place Atlas
The 2022 /r/place Atlas
An Atlas of Reddit's /r/place, with information to each
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>
Licensed under the GNU Affero General Public License Version 3
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
For more information, see:
http://place-atlas.stefanocoding.me/license.txt
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
========================================================================
*/
const prodDomain = "place-atlas.stefanocoding.me"
var innerContainer = document.getElementById("innerContainer");
var container = document.getElementById("container");
@ -46,12 +37,11 @@ var lastPosition = [0, 0];
var viewportSize = [0, 0];
document.getElementById("donateButton").addEventListener("click", function(e){
// document.getElementById("bitcoinQR").src = "./_img/bitcoinQR.png?from=index";
document.getElementById("entriesListDonate").addEventListener("click", function(e){
document.getElementById("donateOverlay").style.display = "flex";
});
document.getElementById("closeBitcoinButton").addEventListener("click", function(e){
document.getElementById("closeDonateButton").addEventListener("click", function(e){
document.getElementById("donateOverlay").style.display = "none";
});
@ -75,6 +65,8 @@ function applyView(){
var atlas = null;
if (document.location.host !== prodDomain) document.body.dataset.dev = ""
init();
async function init(){
@ -120,25 +112,20 @@ async function init(){
}
}
if(mode == "view"){
document.body.dataset.mode = mode
wrapper.className = wrapper.className.replace(/ drawMode/g, "");
initView();
initGlobal()
if (mode !== "draw") initViewGlobal()
} else if(mode=="draw"){
wrapper.className += " draw";
if(mode === "draw"){
initDraw();
} else if(mode=="about"){
} else if(mode === "about"){
window.location = "./about.html";
} else if(mode=="overlap"){
wrapper.className = wrapper.className.replace(/ drawMode/g, "");
} else if(mode === "overlap"){
if(initOverlap){
initOverlap();
}
} else if(mode.startsWith("diff")){
wrapper.className = wrapper.className.replace(/ drawMode/g, "");
try {
let liveResp = await fetch("https://place-atlas.stefanocoding.me/atlas.json");
let liveJson = await liveResp.json();
@ -161,12 +148,12 @@ async function init(){
a[c.id] = c;
return a;
},{});
let removedEntries = liveJson.map(function(entry) {
if(atlasReduced[entry.id] === undefined){
entry.diff = "delete";
}
return entry;
});
let removedEntries = liveJson.filter(entry =>
atlasReduced[entry.id] === undefined
).map(entry => {
entry.diff = "delete"
return entry
})
atlas.push(...removedEntries)
if(mode.includes("only")){
@ -174,11 +161,10 @@ async function init(){
return typeof entry.diff == "string"
});
}
//TEMP FOR TIME TRAVEL
atlasBackup = atlas;
} catch (error) {
console.log("Diff mode failed to load, reverting to normal view - " + error);
console.warn("Diff mode failed to load, reverting to normal view.", error);
} finally {
if(initOverlap && mode.includes("overlap")){
initOverlap();
@ -186,35 +172,12 @@ async function init(){
initView();
}
}
} else if(mode === "explore"){
initExplore();
} else {
initView();
}
function changeOverlapMode(){
console.log(mode)
switch(mode){
case "overlap":
window.location.href = "?mode=explore"
break;
case "explore":
window.location.href = "?"
break;
default:
window.location.href = "?mode=overlap"
break;
}
return false;
}
const modeMap = {
"view": "Overlap",
"overlap": "Explore",
"explore": "Atlas"
}
const toggleMode = document.getElementById("toggleMode");
toggleMode.onclick = changeOverlapMode;
toggleMode.innerHTML = modeMap[mode] || "Overlap";
document.getElementById("loading").style.display = "none";
document.getElementById("zoomInButton").addEventListener("click", function(e){

View file

@ -1,93 +1,32 @@
/*
========================================================================
The /r/place Atlas
The 2022 /r/place Atlas
An Atlas of Reddit's /r/place, with information to each
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>
Licensed under the GNU Affero General Public License Version 3
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
For more information, see:
http://place-atlas.stefanocoding.me/license.txt
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
========================================================================
*/
function initOverlap(){
var wrapper = document.getElementById("wrapper");
var objectsContainer = document.getElementById("objectsList");
var linesCanvas = document.getElementById("linesCanvas");
var linesContext = linesCanvas.getContext("2d");
var backgroundCanvas = document.createElement("canvas");
backgroundCanvas.width = 2000;
backgroundCanvas.height = 2000;
var backgroundContext = backgroundCanvas.getContext("2d");
var filterInput = document.getElementById("searchList");
var entriesList = document.getElementById("entriesList");
var hideListButton = document.getElementById("hideListButton");
var entriesListShown = true;
var entriesLimit = 50;
var entriesOffset = 0;
var moreEntriesButton = document.createElement("button");
moreEntriesButton.innerHTML = "Show "+entriesLimit+" more";
moreEntriesButton.id = "moreEntriesButton";
moreEntriesButton.onclick = function(){
buildObjectsList();
};
var viewportWidth = document.documentElement.clientWidth;
window.renderBackground = renderBackground
var hovered = [];
var lastPos = [0, 0];
var fixed = false; // Fix hovered items in place, so that clicking on links is possible
renderBackground();
buildObjectsList(null, null);
renderBackground(atlas);
render();
buildObjectsList();
// parse linked atlas entry id from link hash
/*if (window.location.hash.substring(3)){
zoom = 4;
applyView();
highlightEntryFromUrl();
}*/
if(document.documentElement.clientWidth > 2000){
entriesListShown = true;
wrapper.className = wrapper.className.replace(/ listHidden/g, "");
}
if(document.documentElement.clientWidth < 2000){
entriesListShown = false;
wrapper.className += " listHidden";
}
applyView();
render();
updateLines();
var args = window.location.search;
if(args){
id = args.split("id=")[1];
@ -96,138 +35,7 @@ function initOverlap(){
}
}
container.addEventListener("mousemove", function(e){
updateHovering(e);
});
filterInput.addEventListener("input", function(e){
entriesOffset = 0;
entriesList.innerHTML = "";
entriesList.appendChild(moreEntriesButton);
buildObjectsList(this.value.toLowerCase());
});
document.getElementById("sort").addEventListener("input", function(e){
entriesOffset = 0;
entriesList.innerHTML = "";
entriesList.appendChild(moreEntriesButton);
buildObjectsList(filterInput.value.toLowerCase());
});
hideListButton.addEventListener("click", function(e){
entriesListShown = !entriesListShown;
if(entriesListShown){
wrapper.className = wrapper.className.replace(/ listHidden/g, "");
} else {
wrapper.className += " listHidden";
}
applyView();
updateHovering(e);
render();
updateLines();
});
function highlightEntryFromUrl(){
var objectsContainer = document.getElementById("objectsList");
var id = 0;
var args = window.location.search;
if(args){
id = args.split("id=")[1];
if(id){
id = id.split("&")[0];
}
}
//var id = parseInt(window.location.hash.substring(3));
var entry = atlas.filter(function(e){
return e.id === id;
});
if (entry.length === 1){
entry = entry[0];
var infoElement = createInfoBlock(entry);
objectsContainer.innerHTML = "";
objectsContainer.appendChild(infoElement);
//console.log(entry.center[0]);
//console.log(entry.center[1]);
zoom = 4;
applyView();
zoomOrigin = [
innerContainer.clientWidth/2 - entry.center[0]* zoom// + container.offsetLeft
,innerContainer.clientHeight/2 - entry.center[1]* zoom// + container.offsetTop
];
//console.log(zoomOrigin);
applyView();
hovered = [entry];
render();
hovered[0].element = infoElement;
updateLines();
fixed = true;
}
}
function updateHovering(e){
if(!dragging && !fixed){
var pos = [
(e.clientX - (container.clientWidth/2 - innerContainer.clientWidth/2 + zoomOrigin[0] + container.offsetLeft))/zoom
,(e.clientY - (container.clientHeight/2 - innerContainer.clientHeight/2 + zoomOrigin[1] + container.offsetTop))/zoom
];
if(pos[0] <= 2200 && pos[0] >= -100 && pos[0] <= 2200 && pos[0] >= -100){
var newHovered = [];
for(var i = 0; i < atlas.length; i++){
if(pointIsInPolygon(pos, atlas[i].path)){
newHovered.push(atlas[i]);
}
}
var changed = false;
if(hovered.length == newHovered.length){
for(var i = 0; i < hovered.length; i++){
if(hovered[i].id != newHovered[i].id){
changed = true;
break;
}
}
} else {
changed = true;
}
if(changed){
hovered = newHovered;
objectsContainer.innerHTML = "";
for(var i in hovered){
var element = createInfoBlock(hovered[i]);
objectsContainer.appendChild(element);
hovered[i].element = element;
}
render();
}
}
}
}
function renderBackground(){
function renderBackground(atlas) {
backgroundContext.clearRect(0, 0, canvas.width, canvas.height);
@ -266,277 +74,4 @@ function initOverlap(){
console.log(blank+" blank pixels, which are "+Math.round(blank/100)/100+"% of the canvas ("+(100-Math.round(blank/100)/100)+"% mapped)");
}
function buildObjectsList(filter){
if(entriesList.contains(moreEntriesButton)){
entriesList.removeChild(moreEntriesButton);
}
var sortedAtlas;
if(filter){
sortedAtlas = atlas.filter(function(value){
return (value.name.toLowerCase().indexOf(filter) !== -1);
});
document.getElementById("atlasSize").innerHTML = "Found "+sortedAtlas.length+" entries.";
} else {
sortedAtlas = atlas.concat();
document.getElementById("atlasSize").innerHTML = "The Atlas contains "+sortedAtlas.length+" entries.";
}
var sort = document.getElementById("sort").value;
var sortFunction;
//console.log(sort);
switch(sort){
case "alphaAsc":
sortFunction = function(a, b){
return a.name.toLowerCase().localeCompare(b.name.toLowerCase());
}
break;
case "alphaDesc":
sortFunction = function(a, b){
return b.name.toLowerCase().localeCompare(a.name.toLowerCase());
}
break;
case "newest":
sortFunction = function(a, b){
if (a.id > b.id) {
return -1;
}
if (a.id < b.id) {
return 1;
}
// a must be equal to b
return 0;
}
break;
case "oldest":
sortFunction = function(a, b){
if (a.id < b.id) {
return -1;
}
if (a.id > b.id) {
return 1;
}
// a must be equal to b
return 0;
}
break;
}
sortedAtlas.sort(sortFunction);
for(var i = entriesOffset; i < entriesOffset+entriesLimit; i++){
if(i >= sortedAtlas.length){
break;
}
var element = createInfoBlock(sortedAtlas[i]);
element.entry = sortedAtlas[i];
element.addEventListener("mouseenter", function(e){
if(!fixed && !dragging){
objectsContainer.innerHTML = "";
zoomOrigin = [
innerContainer.clientWidth/2 - this.entry.center[0]* zoom// + container.offsetLeft
,innerContainer.clientHeight/2 - this.entry.center[1]* zoom// + container.offsetTop
]
//console.log(zoomOrigin);
applyView();
hovered = [this.entry];
render();
hovered[0].element = this;
updateLines();
}
});
element.addEventListener("mouseleave", function(e){
if(!fixed && !dragging){
hovered = [];
updateLines();
render();
}
});
entriesList.appendChild(element);
}
entriesOffset += entriesLimit;
if(sortedAtlas.length > entriesOffset){
moreEntriesButton.innerHTML = "Show "+Math.min(entriesLimit, sortedAtlas.length - entriesOffset)+" more";
entriesList.appendChild(moreEntriesButton);
}
}
function render(){
context.globalCompositeOperation = "source-over";
context.clearRect(0, 0, canvas.width, canvas.height);
if(hovered.length > 0){
container.style.cursor = "pointer";
} else {
container.style.cursor = "default";
}
for(var i = 0; i < hovered.length; i++){
var path = hovered[i].path;
context.beginPath();
if(path[0]){
context.moveTo(path[0][0], path[0][1]);
}
for(var p = 1; p < path.length; p++){
context.lineTo(path[p][0], path[p][1]);
}
context.closePath();
context.globalCompositeOperation = "source-over";
context.fillStyle = "rgba(0, 0, 0, 1)";
context.fill();
}
context.globalCompositeOperation = "source-out";
context.drawImage(backgroundCanvas, 0, 0);
for(var i = 0; i < hovered.length; i++){
var path = hovered[i].path;
context.beginPath();
if(path[0]){
context.moveTo(path[0][0], path[0][1]);
}
for(var p = 1; p < path.length; p++){
context.lineTo(path[p][0], path[p][1]);
}
context.closePath();
context.globalCompositeOperation = "source-over";
context.strokeStyle = "rgba(0, 0, 0, 1)";
context.stroke();
}
}
function toggleFixed(e){
if(!fixed && hovered.length == 0){
return 0;
}
fixed = !fixed;
if(!fixed){
updateHovering(e);
render();
}
}
function updateLines(){
linesCanvas.width = linesCanvas.clientWidth;
linesCanvas.height = linesCanvas.clientHeight;
linesContext.lineCap = "round";
linesContext.lineWidth = Math.max(Math.min(zoom*1.5, 16*1.5), 6);
linesContext.strokeStyle = "#000000";
for(var i = 0; i < hovered.length; i++){
var element = hovered[i].element;
linesContext.beginPath();
//linesContext.moveTo(element.offsetLeft + element.clientWidth - 10, element.offsetTop + 20);
linesContext.moveTo(
element.getBoundingClientRect().left + document.documentElement.scrollLeft + element.clientWidth/2
,element.getBoundingClientRect().top + document.documentElement.scrollTop + 20
);
linesContext.lineTo(
~~(hovered[i].center[0]*zoom) + innerContainer.offsetLeft
,~~(hovered[i].center[1]*zoom) + innerContainer.offsetTop
);
linesContext.stroke();
}
linesContext.lineWidth = Math.max(Math.min(zoom, 16), 4);
linesContext.strokeStyle = "#FFFFFF";
for(var i = 0; i < hovered.length; i++){
var element = hovered[i].element;
linesContext.beginPath();
linesContext.moveTo(
element.getBoundingClientRect().left + document.documentElement.scrollLeft + element.clientWidth/2
,element.getBoundingClientRect().top + document.documentElement.scrollTop + 20
);
linesContext.lineTo(
~~(hovered[i].center[0]*zoom) + innerContainer.offsetLeft
,~~(hovered[i].center[1]*zoom) + innerContainer.offsetTop
);
linesContext.stroke();
}
}
window.addEventListener("resize", updateLines);
window.addEventListener("mousemove", updateLines);
window.addEventListener("dblClick", updateLines);
window.addEventListener("wheel", updateLines);
container.addEventListener("mousedown", function(e){
lastPos = [
e.clientX
,e.clientY
];
});
container.addEventListener("mouseup", function(e){
if(Math.abs(lastPos[0] - e.clientX) + Math.abs(lastPos[1] - e.clientY) <= 4){
toggleFixed(e);
}
});
objectsContainer.addEventListener("scroll", function(e){
updateLines();
});
window.addEventListener("resize", function(){
//console.log(document.documentElement.clientWidth, document.documentElement.clientHeight);
if(document.documentElement.clientWidth > 2000 && viewportWidth <= 2000){
entriesListShown = true;
wrapper.className = wrapper.className.replace(/ listHidden/g, "");
}
if(document.documentElement.clientWidth < 2000 && viewportWidth >= 2000){
entriesListShown = false;
wrapper.className += " listHidden";
}
viewportWidth = document.documentElement.clientWidth;
applyView();
render();
updateLines();
});
}

View file

@ -24,9 +24,6 @@ SOFTWARE.
*/
function pointIsInPolygon (point, polygon) {
// ray-casting algorithm based on
// http://www.ecse.rpi.edu/Homepages/wrf/Research/Short_Notes/pnpoly.html

View file

@ -1,3 +1,17 @@
/*
========================================================================
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
========================================================================
*/
var areasSum = 0;
var areas = [];

View file

@ -1,3 +1,18 @@
/*
========================================================================
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
========================================================================
*/
const timeConfig = [
{
timestamp: 1648822500,

View file

@ -1,27 +1,18 @@
/*
========================================================================
The /r/place Atlas
The 2022 /r/place Atlas
An Atlas of Reddit's /r/place, with information to each
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>
Licensed under the GNU Affero General Public License Version 3
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
For more information, see:
http://place-atlas.stefanocoding.me/license.txt
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
========================================================================
*/
var linesCanvas = document.getElementById("linesCanvas");
var linesContext = linesCanvas.getContext("2d");
var hovered = [];
@ -34,6 +25,145 @@ backgroundCanvas.width = 2000;
backgroundCanvas.height = 2000;
var backgroundContext = backgroundCanvas.getContext("2d");
var wrapper = document.getElementById("wrapper");
var objectsContainer = document.getElementById("objectsList");
var closeObjectsListButton = document.getElementById("closeObjectsListButton");
var filterInput = document.getElementById("searchList");
var entriesList = document.getElementById("entriesList");
var hideListButton = document.getElementById("hideListButton");
var entriesListShown = false;
var sortedAtlas;
var entriesLimit = 50;
var entriesOffset = 0;
var moreEntriesButton = document.createElement("button");
moreEntriesButton.innerHTML = "Show "+entriesLimit+" more";
moreEntriesButton.id = "moreEntriesButton";
moreEntriesButton.onclick = function(){
buildObjectsList(null, null);
renderBackground();
render();
};
var defaultSort = "shuffle";
document.getElementById("sort").value = defaultSort;
var lastPos = [0, 0];
var fixed = false; // Fix hovered items in place, so that clicking on links is possible
if(document.documentElement.clientWidth > 2000){
entriesListShown = true;
wrapper.classList.remove('listHidden')
}
if(document.documentElement.clientWidth < 2000){
entriesListShown = false;
wrapper.classList.add('listHidden')
}
filterInput.addEventListener("input", function(e){
entriesOffset = 0;
entriesList.innerHTML = "";
entriesList.appendChild(moreEntriesButton);
if(this.value === ""){
document.getElementById("relevantOption").disabled = true;
sortedAtlas = atlas.concat();
buildObjectsList(null, null);
} else {
document.getElementById("relevantOption").disabled = false;
buildObjectsList(this.value.toLowerCase(), "relevant");
}
});
document.getElementById("sort").addEventListener("input", function(e){
entriesOffset = 0;
entriesList.innerHTML = "";
entriesList.appendChild(moreEntriesButton);
if(this.value != "relevant"){
defaultSort = this.value;
}
buildObjectsList(filterInput.value.toLowerCase(), this.value);
});
hideListButton.addEventListener("click", function(e){
entriesListShown = !entriesListShown;
if(entriesListShown){
wrapper.classList.remove('listHidden')
} else {
wrapper.classList.add('listHidden')
}
updateHovering();
applyView();
render();
updateLines();
return false;
});
closeObjectsListButton.addEventListener("click", function(e){
hovered = [];
objectsContainer.innerHTML = "";
updateLines();
closeObjectsListButton.className = "hidden";
fixed = false;
render();
});
function toggleFixed(e, tapped){
if(!fixed && hovered.length == 0){
return 0;
}
fixed = !fixed;
if(!fixed){
updateHovering(e, tapped);
render();
}
}
window.addEventListener("resize", updateLines);
window.addEventListener("mousemove", updateLines);
window.addEventListener("dblClick", updateLines);
window.addEventListener("wheel", updateLines);
objectsContainer.addEventListener("scroll", function(e){
updateLines();
});
window.addEventListener("resize", function(){
//console.log(document.documentElement.clientWidth, document.documentElement.clientHeight);
var viewportWidth = document.documentElement.clientWidth;
if(document.documentElement.clientWidth > 2000 && viewportWidth <= 2000){
entriesListShown = true;
wrapper.className = wrapper.className.replace(/ listHidden/g, "");
}
if(document.documentElement.clientWidth < 2000 && viewportWidth >= 2000){
entriesListShown = false;
wrapper.className += " listHidden";
}
updateHovering();
viewportWidth = document.documentElement.clientWidth;
applyView();
render();
updateLines();
});
function updateLines(){
linesCanvas.width = linesCanvas.clientWidth;
@ -138,274 +268,7 @@ function renderBackground(atlas){
}
}
function initView(){
var wrapper = document.getElementById("wrapper");
var objectsContainer = document.getElementById("objectsList");
var closeObjectsListButton = document.getElementById("closeObjectsListButton");
var filterInput = document.getElementById("searchList");
var entriesList = document.getElementById("entriesList");
var hideListButton = document.getElementById("hideListButton");
var entriesListShown = true;
var sortedAtlas;
var entriesLimit = 50;
var entriesOffset = 0;
var moreEntriesButton = document.createElement("button");
moreEntriesButton.innerHTML = "Show "+entriesLimit+" more";
moreEntriesButton.id = "moreEntriesButton";
moreEntriesButton.onclick = function(){
buildObjectsList(null, null);
};
var defaultSort = "shuffle";
document.getElementById("sort").value = defaultSort;
var lastPos = [0, 0];
var fixed = false; // Fix hovered items in place, so that clicking on links is possible
renderBackground(atlas);
render();
buildObjectsList(null, null);
timeCallback = (tempAtlas) => {
renderBackground(tempAtlas);
render();
}
// parse linked atlas entry id from link hash
/*if (window.location.hash.substring(3)){
zoom = 4;
applyView();
highlightEntryFromUrl();
}*/
if(document.documentElement.clientWidth > 2000){
entriesListShown = true;
wrapper.className = wrapper.className.replace(/ listHidden/g, "");
}
if(document.documentElement.clientWidth < 2000){
entriesListShown = false;
wrapper.className += " listHidden";
}
applyView();
render();
updateLines();
var args = window.location.search;
if(args){
id = args.split("id=")[1];
if(id){
highlightEntryFromUrl();
}
}
container.addEventListener("mousemove", function(e){
if(e.sourceCapabilities){
if(!e.sourceCapabilities.firesTouchEvents){
updateHovering(e);
}
} else {
updateHovering(e);
}
});
filterInput.addEventListener("input", function(e){
entriesOffset = 0;
entriesList.innerHTML = "";
entriesList.appendChild(moreEntriesButton);
if(this.value === ""){
document.getElementById("relevantOption").disabled = true;
sortedAtlas = atlas.concat();
buildObjectsList(null, null);
} else {
document.getElementById("relevantOption").disabled = false;
buildObjectsList(this.value.toLowerCase(), "relevant");
}
});
document.getElementById("sort").addEventListener("input", function(e){
entriesOffset = 0;
entriesList.innerHTML = "";
entriesList.appendChild(moreEntriesButton);
if(this.value != "relevant"){
defaultSort = this.value;
}
buildObjectsList(filterInput.value.toLowerCase(), this.value);
});
hideListButton.addEventListener("click", function(e){
entriesListShown = !entriesListShown;
if(entriesListShown){
wrapper.className = wrapper.className.replace(/ listHidden/g, "");
} else {
wrapper.className += " listHidden";
}
updateHovering();
applyView();
render();
updateLines();
return false;
});
closeObjectsListButton.addEventListener("click", function(e){
hovered = [];
objectsContainer.innerHTML = "";
updateLines();
closeObjectsListButton.className = "hidden";
fixed = false;
render();
});
function shuffle(){
//console.log("shuffled atlas");
for (var i = sortedAtlas.length - 1; i > 0; i--) {
var j = Math.floor(Math.random() * (i + 1));
var temp = sortedAtlas[i];
sortedAtlas[i] = sortedAtlas[j];
sortedAtlas[j] = temp;
}
}
function highlightEntryFromUrl(){
var objectsContainer = document.getElementById("objectsList");
var id = 0;
var args = window.location.search;
if(args){
id = args.split("id=")[1];
if(id){
id = id.split("&")[0];
}
}
//var id = parseInt(window.location.hash.substring(3));
var entries = atlas.filter(function(e){
return e.id === id;
});
if (entries.length === 1){
let entry = entries[0];
document.title = entry.name + " on the 2022 /r/place Atlas";
var infoElement = createInfoBlock(entry);
objectsContainer.innerHTML = "";
objectsContainer.appendChild(infoElement);
//console.log(entry.center[0]);
//console.log(entry.center[1]);
zoom = 4;
renderBackground(atlas);
applyView();
zoomOrigin = [
innerContainer.clientWidth/2 - entry.center[0]* zoom// + container.offsetLeft
,innerContainer.clientHeight/2 - entry.center[1]* zoom// + container.offsetTop
];
scaleZoomOrigin = [
2000/2 - entry.center[0]// + container.offsetLeft
,2000/2 - entry.center[1]// + container.offsetTop
];
//console.log(zoomOrigin);
applyView();
hovered = [entry];
render();
hovered[0].element = infoElement;
closeObjectsListButton.className = "";
updateLines();
fixed = true;
}
}
function updateHovering(e, tapped){
var coordsWrapper = document.getElementById("coordsWrapper");
if (entriesListShown) {
coordsWrapper.className = "uncollapsed"
} else {
coordsWrapper.className = "collapsed"
}
if(!dragging && (!fixed || tapped)){
var pos = [
(e.clientX - (container.clientWidth/2 - innerContainer.clientWidth/2 + zoomOrigin[0] + container.offsetLeft))/zoom
,(e.clientY - (container.clientHeight/2 - innerContainer.clientHeight/2 + zoomOrigin[1] + container.offsetTop))/zoom
];
var coords_p = document.getElementById("coords_p");
coords_p.innerText = Math.ceil(pos[0]) + ", " + Math.ceil(pos[1]);
if(pos[0] <= 2200 && pos[0] >= -100 && pos[0] <= 2200 && pos[0] >= -100){
var newHovered = [];
for(var i = 0; i < atlas.length; i++){
if(pointIsInPolygon(pos, atlas[i].path)){
newHovered.push(atlas[i]);
}
}
var changed = false;
if(hovered.length == newHovered.length){
for(var i = 0; i < hovered.length; i++){
if(hovered[i].id != newHovered[i].id){
changed = true;
break;
}
}
} else {
changed = true;
}
if(changed){
hovered = newHovered.sort(function(a, b){
return calcPolygonArea(a.path) - calcPolygonArea(b.path);
});
objectsContainer.innerHTML = "";
for(var i in hovered){
var element = createInfoBlock(hovered[i]);
objectsContainer.appendChild(element);
hovered[i].element = element;
}
if(hovered.length > 0){
closeObjectsListButton.className = "";
} else {
closeObjectsListButton.className = "hidden";
}
render();
}
}
}
}
function buildObjectsList(filter, sort){
function buildObjectsList(filter, sort){
if(entriesList.contains(moreEntriesButton)){
entriesList.removeChild(moreEntriesButton);
@ -422,6 +285,7 @@ function initView(){
value.name.toLowerCase().indexOf(filter) !== -1
|| value.description.toLowerCase().indexOf(filter) !== -1
|| value.subreddit && value.subreddit.toLowerCase().indexOf(filter) !== -1
|| value.id === filter
);
});
document.getElementById("atlasSize").innerHTML = "Found "+sortedAtlas.length+" entries.";
@ -630,9 +494,19 @@ function initView(){
moreEntriesButton.innerHTML = "Show "+Math.min(entriesLimit, sortedAtlas.length - entriesOffset)+" more";
entriesList.appendChild(moreEntriesButton);
}
}
}
async function render(){
function shuffle(){
//console.log("shuffled atlas");
for (var i = sortedAtlas.length - 1; i > 0; i--) {
var j = Math.floor(Math.random() * (i + 1));
var temp = sortedAtlas[i];
sortedAtlas[i] = sortedAtlas[j];
sortedAtlas[j] = temp;
}
}
async function render(){
context.clearRect(0, 0, canvas.width, canvas.height);
@ -737,25 +611,192 @@ function initView(){
context.stroke();
}
}
function updateHovering(e, tapped){
if(!dragging && (!fixed || tapped)){
var pos = [
(e.clientX - (container.clientWidth/2 - innerContainer.clientWidth/2 + zoomOrigin[0] + container.offsetLeft))/zoom
,(e.clientY - (container.clientHeight/2 - innerContainer.clientHeight/2 + zoomOrigin[1] + container.offsetTop))/zoom
];
var coords_p = document.getElementById("coords_p");
coords_p.innerText = Math.ceil(pos[0]) + ", " + Math.ceil(pos[1]);
if(pos[0] <= 2200 && pos[0] >= -100 && pos[0] <= 2200 && pos[0] >= -100){
var newHovered = [];
for(var i = 0; i < atlas.length; i++){
if(pointIsInPolygon(pos, atlas[i].path)){
newHovered.push(atlas[i]);
}
}
function toggleFixed(e, tapped){
if(!fixed && hovered.length == 0){
return 0;
var changed = false;
if(hovered.length == newHovered.length){
for(var i = 0; i < hovered.length; i++){
if(hovered[i].id != newHovered[i].id){
changed = true;
break;
}
fixed = !fixed;
if(!fixed){
updateHovering(e, tapped);
}
} else {
changed = true;
}
if(changed){
hovered = newHovered.sort(function(a, b){
return calcPolygonArea(a.path) - calcPolygonArea(b.path);
});
objectsContainer.innerHTML = "";
for(var i in hovered){
var element = createInfoBlock(hovered[i]);
objectsContainer.appendChild(element);
hovered[i].element = element;
}
if(hovered.length > 0){
closeObjectsListButton.className = "";
} else {
closeObjectsListButton.className = "hidden";
}
render();
}
}
}
}
window.addEventListener("resize", updateLines);
window.addEventListener("mousemove", updateLines);
window.addEventListener("dblClick", updateLines);
window.addEventListener("wheel", updateLines);
function highlightEntryFromUrl(){
var objectsContainer = document.getElementById("objectsList");
var id = 0;
var args = window.location.search;
if(args){
id = args.split("id=")[1];
if(id){
id = id.split("&")[0];
}
}
//var id = parseInt(window.location.hash.substring(3));
var entries = atlas.filter(function(e){
return e.id === id;
});
if (entries.length === 1){
let entry = entries[0];
document.title = entry.name + " on the 2022 /r/place Atlas";
var infoElement = createInfoBlock(entry);
objectsContainer.innerHTML = "";
objectsContainer.appendChild(infoElement);
//console.log(entry.center[0]);
//console.log(entry.center[1]);
zoom = 4;
renderBackground(atlas);
applyView();
zoomOrigin = [
innerContainer.clientWidth/2 - entry.center[0]* zoom// + container.offsetLeft
,innerContainer.clientHeight/2 - entry.center[1]* zoom// + container.offsetTop
];
scaleZoomOrigin = [
2000/2 - entry.center[0]// + container.offsetLeft
,2000/2 - entry.center[1]// + container.offsetTop
];
//console.log(zoomOrigin);
applyView();
hovered = [entry];
render();
hovered[0].element = infoElement;
closeObjectsListButton.className = "";
updateLines();
fixed = true;
}
}
function initView(){
buildObjectsList(null, null);
renderBackground(atlas);
render();
timeCallback = (tempAtlas) => {
renderBackground(tempAtlas);
render();
}
// parse linked atlas entry id from link hash
/*if (window.location.hash.substring(3)){
zoom = 4;
applyView();
highlightEntryFromUrl();
}*/
applyView();
render();
updateLines();
var args = window.location.search;
if(args){
id = args.split("id=")[1];
if(id){
highlightEntryFromUrl();
}
}
}
function initExplore(){
window.updateHovering = updateHovering
function updateHovering(e, tapped){
if(!dragging && (!fixed || tapped)){
var pos = [
(e.clientX - (container.clientWidth/2 - innerContainer.clientWidth/2 + zoomOrigin[0] + container.offsetLeft))/zoom
,(e.clientY - (container.clientHeight/2 - innerContainer.clientHeight/2 + zoomOrigin[1] + container.offsetTop))/zoom
];
var coords_p = document.getElementById("coords_p");
coords_p.innerText = Math.ceil(pos[0]) + ", " + Math.ceil(pos[1]);
}
}
renderBackground(atlas);
applyView();
}
function initGlobal() {
container.addEventListener("mousemove", function(e){
if(e.sourceCapabilities){
if(!e.sourceCapabilities.firesTouchEvents){
updateHovering(e);
}
} else {
updateHovering(e);
}
});
}
function initViewGlobal() {
container.addEventListener("mousedown", function(e){
lastPos = [
e.clientX
@ -798,33 +839,4 @@ function initView(){
}
}
});
objectsContainer.addEventListener("scroll", function(e){
updateLines();
});
window.addEventListener("resize", function(){
//console.log(document.documentElement.clientWidth, document.documentElement.clientHeight);
var viewportWidth = document.documentElement.clientWidth;
if(document.documentElement.clientWidth > 2000 && viewportWidth <= 2000){
entriesListShown = true;
wrapper.className = wrapper.className.replace(/ listHidden/g, "");
}
if(document.documentElement.clientWidth < 2000 && viewportWidth >= 2000){
entriesListShown = false;
wrapper.className += " listHidden";
}
updateHovering();
viewportWidth = document.documentElement.clientWidth;
applyView();
render();
updateLines();
});
}

View file

@ -1,22 +1,15 @@
<!--
========================================================================
The /r/place Atlas
The 2022 /r/place Atlas
An Atlas of Reddit's /r/place, with information to each
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>
Licensed under the GNU Affero General Public License Version 3
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
For more information, see:
http://place-atlas.stefanocoding.me/license.txt
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
========================================================================
-->
@ -34,7 +27,7 @@
<meta name="viewport" content="width=device-width, height=device-height, initial-scale=1">
<link href="./_css/style.css?version=1.0.33" rel="stylesheet" type="text/css" media="all">
<link href="./_css/style.css" rel="stylesheet" type="text/css" media="all">
</head>
<body>
<div id="wrapper">
@ -56,36 +49,35 @@ <h1>The 2022 /r/place Atlas</h1>
<div id="aboutContainer">
<a id="aboutBackButton" href="./">&lt; Back to the Atlas</a>
<div id="about">
<a href="https://www.netlify.com">
<a id="aboutBackButton" class="button" href="./">&lt; Back to the Atlas</a>
<a href="https://www.netlify.com" id="netlifyBadges">
<img src="https://www.netlify.com/img/global/badges/netlify-color-bg.svg" alt="Deploys by Netlify" />
<img src="https://api.netlify.com/api/v1/badges/1e7291ce-0680-45ed-9843-47a32a992bbb/deploy-status" alt="Deploys by Netlify" />
</a>
<br>
<h2 id="abouth2">The 2022 /r/place Atlas</h2>
<p>This is an Atlas aiming to chart all the artworks created during the <a href="https://www.reddit.com/r/place/">/r/place</a> April's fools event on <a href="https://www.reddit.com/" target="_blank">Reddit</a> in 2022.</p>
<p>The original code was developed by <a href="/" target="_blank" rel="author">Roland Rytz</a> (<a href="mailto:roland.rytz@gmail.com" target="_blank">mail</a>, <a href="https://reddit.com/user/draemmli/" target="_blank">reddit</a>) and is available under the free <a href="https://www.gnu.org/licenses/agpl-3.0.en.html" target="_blank">AGPL license</a> on <a target="_blank" href="https://github.com/RolandR/place-atlas">GitHub</a>.</p>
<p>This is an Atlas aiming to chart all the artworks created during the <a href="https://www.reddit.com/r/place/">/r/place</a> April Fools event on <a href="https://www.reddit.com/" target="_blank">Reddit</a> in 2022.</p>
<p>The original code was developed by <a href="https://draemm.li/various/place-atlas/" target="_blank" rel="author">Roland Rytz</a> (<a href="mailto:roland.rytz@gmail.com" target="_blank">mail</a>, <a href="https://reddit.com/user/draemmli/" target="_blank">reddit</a>) and is available under the free <a href="https://www.gnu.org/licenses/agpl-3.0.en.html" target="_blank">AGPL license</a> on <a target="_blank" href="https://github.com/RolandR/place-atlas">GitHub</a>.</p>
<br>
<p>The currently maintained version of the website is managed by <a href="/" target="_blank" rel="author">Stefano Haagmans</a> and is obtainable under the same license within a <a target="_blank" href="https://github.com/placeAtlas/atlas">Github Fork</a>.</p>. Image's provided by <a target="_blank" href="https://place.thatguyalex.com/">Alex Tsernoh</a></p>.
<p>Maintaining and updating the website takes work, but I enjoy doing it for free and giving this to people. But if you would like to support me, or the people who helped me with contributions to this project. You're free to support us though <a target="_blank" href="https://paypal.me/codixer">Paypal</a>. (I don't have bitcoin)</p>
<p>The currently maintained version of the website is managed by <a href="/" target="_blank" rel="author">Stefano Haagmans</a> and is obtainable under the same license within a <a target="_blank" href="https://github.com/placeAtlas/atlas">GitHub fork</a>. Images are provided by <a target="_blank" href="https://place.thatguyalex.com/">Alex Tsernoh</a>.</p>
<p>Maintaining and updating the website takes work, but I enjoy doing it for free and giving this to people. But if you would like to support me, or the people who helped me with contributions to this project. You're free to support us though <a target="_blank" href="https://paypal.me/placeAtlas/5">PayPal</a>, <a target="_blank" href="https://www.patreon.com/placeAtlas">Patreon</a>, or <a target="_blank" href="https://ko-fi.com/placeatlas">Ko-Fi</a>.</p>
<p>To maintain the same tradition, I will also be offering stickers to anyone donating more then 20$ (Due to the size increase). But, you're not forced to do anything! This only shows appreciation to us and the people who've worked on this project</p>
<br>
<p>Roland Rytz worked on the Atlas full-time (and more!) for over two weeks during the 2017 r/place event.</p>
<p>If you'd like to support Roland, you can do so by <a target="_blank" href="https://paypal.me/draemmli">PayPal</a>.</p>
<p>If you donate more than 10(€/$/CHF/mBTC), He'll (hopefully) send you a nice sticker of the Place canvas! (2017 one)</p>
<p>If you donate more than 10(€/$/CHF/mBTC), He'll (hopefully) send you a nice sticker of the 2017 Place canvas!</p>
<h2>How to contribute</h2>
<p>The /r/Place Atlas project relies on user contributions.</p>
<p>To contribute a label for an artwork, please read <a href="https://www.reddit.com/r/placeAtlas2/comments/tu203o/how_to_contribute/" target="_blank">this post on reddit</a> to learn how to submit a new entry.</p>
<p>To contribute a label for an artwork, please read <a href="https://www.reddit.com/r/placeAtlas2/comments/tu203o/how_to_contribute/" target="_blank">this post on Reddit</a> to learn how to submit a new entry.</p>
<p>Alternatively, contributions can be made directly on <a href="https://github.com/placeAtlas/atlas/blob/master/CONTRIBUTING.md">GitHub</a>.</p>
<p>The <a href="https://reddit.com/r/placeAtlas2/" target="_blank">/r/placeAtlas2</a> subreddit is also the place to submit all bug reports, feature requests or questions.</p>
<h2>r/placeAtlas2 (Current) Contributors and Maintainers</h2>
<div id="contributors">
<a href="https://reddit.com/user/TCOOfficiall" target="_blank">TCOOfficiall (Current Maintainer)</a> ·
<a href="https://reddit.com/user/prosto_sanja" target="_blank">prosto_sanja (Provided Images)</a> - <a href="https://place.thatguyalex.com/" target="_blank">Website</a> ·
<a href="https://reddit.com/user/TCOOfficiall" target="_blank">TCOOfficiall (current maintainer)</a> ·
<a href="https://reddit.com/user/prosto_sanja" target="_blank">prosto_sanja (images)</a> <a href="https://place.thatguyalex.com/" target="_blank">(website)</a> ·
<a href="https://reddit.com/user/electric-blue" target="_blank">electric-blue</a> ·
<a href="https://reddit.com/user/m654zy" target="_blank">m654zy</a> ·
<a href="https://reddit.com/user/xXLInkster17Xx" target="_blank">xXLInkster17Xx</a>
@ -103,14 +95,5 @@ <h2 id="contacth2">Contact?</h2>
</div>
</div>
</div>
<script type="text/javascript">
document.getElementById("closeBitcoinButton").addEventListener("click", function(e) {
document.getElementById("bitcoinOverlay").style.display = "none";
});
document.getElementById("bitcoinButton").addEventListener("click", function(e) {
document.getElementById("bitcoinOverlay").style.display = "flex";
});
</script>
</body>
</html>

File diff suppressed because it is too large Load diff

View file

@ -1,22 +1,15 @@
<!--
========================================================================
The /r/place Atlas
The 2022 /r/place Atlas
An Atlas of Reddit's /r/place, with information to each
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>
Licensed under the GNU Affero General Public License Version 3
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
For more information, see:
http://place-atlas.stefanocoding.me/license.txt
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
========================================================================
-->
@ -36,7 +29,7 @@
<meta name="viewport" content="width=device-width, height=device-height, initial-scale=1, minimum-scale=1, maximum-scale=1, shrink-to-fit=no"> <!-- user-scalable=no -->
<meta name="mobile-web-app-capable" content="yes">
<link href="./_css/style.css?version=1.0.33" rel="stylesheet" type="text/css" media="all">
<link href="./_css/style.css" rel="stylesheet" type="text/css" media="all">
<link rel="manifest" href="./manifest.webmanifest">
<script type="application/ld+json">
@ -60,7 +53,7 @@
},
"copyrightHolder": { "@id": "#RolandRytz" },
"copyrightYear": 2017,
"license": "http://place-atlas.stefanocoding.me/license.txt",
"license": "https://place-atlas.stefanocoding.me/license.txt",
"inLanguage": "English",
"isAccessibleForFree": true,
"keywords": "reddit, /r/place",
@ -106,14 +99,24 @@ <h1 id="title">The 2022 /r/place Atlas</h1>
</div>
<div id="entriesListContainer">
<nav>
<a id="aboutLink" href="./about.html">About</a>
<a id="drawLink" href="./index.html?mode=draw">Draw</a>
<a id="toggleMode" onclick="return changeOverlapMode()">Overlap</a>
<button title="Discord" onclick="window.location.href='https://discord.gg/pJkm23b2nA'">
<nav id="entriesListNav">
<a id="aboutLink" href="./about.html" class="button">About</a>
<a id="drawLink" href="./index.html?mode=draw" class="button">Draw</a>
<div class="dropdown button" id="viewModes">
<span>Modes</span>
<span class="buffer"></span>
<div class="dropdown-content">
<a href="./">Normal</a>
<a href="./?mode=explore">Explore</a>
<a href="./?mode=overlap">Overlap</a>
<a href="./?mode=diff" class="show-only-on-dev">With Diff</a>
<a href="./?mode=diffonly" class="show-only-on-dev">Diff Only</a>
</div>
</div>
<a title="Discord" href="https://discord.gg/pJkm23b2nA" class="button small" id="entriesListDiscord">
<img class="Discord" alt="Discord Logo" src="./_img/discord.svg">
</button>
<button title="Donate!" id="donateButton">
</a>
<button title="Donate!" id="entriesListDonate" class="small">
<img alt="Donate" src="data:image/svg+xml;utf8,%3Csvg%0A%20%20%20xmlns%3Adc%3D%22http%3A//purl.org/dc/elements/1.1/%22%0A%20%20%20xmlns%3Acc%3D%22http%3A//creativecommons.org/ns%23%22%0A%20%20%20xmlns%3Ardf%3D%22http%3A//www.w3.org/1999/02/22-rdf-syntax-ns%23%22%0A%20%20%20xmlns%3Asvg%3D%22http%3A//www.w3.org/2000/svg%22%0A%20%20%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%0A%20%20%20version%3D%221.1%22%0A%20%20%20width%3D%2263.97776%22%0A%20%20%20height%3D%2263.985764%22%0A%20%20%20id%3D%22svg2%22%3E%0A%20%20%3Cdefs%0A%20%20%20%20%20id%3D%22defs4%22%20/%3E%0A%20%20%3Cmetadata%0A%20%20%20%20%20id%3D%22metadata7%22%3E%0A%20%20%20%20%3Crdf%3ARDF%3E%0A%20%20%20%20%20%20%3Ccc%3AWork%0A%20%20%20%20%20%20%20%20%20rdf%3Aabout%3D%22%22%3E%0A%20%20%20%20%20%20%20%20%3Cdc%3Aformat%3Eimage/svg+xml%3C/dc%3Aformat%3E%0A%20%20%20%20%20%20%20%20%3Cdc%3Atype%0A%20%20%20%20%20%20%20%20%20%20%20rdf%3Aresource%3D%22http%3A//purl.org/dc/dcmitype/StillImage%22%20/%3E%0A%20%20%20%20%20%20%20%20%3Cdc%3Atitle%3E%3C/dc%3Atitle%3E%0A%20%20%20%20%20%20%3C/cc%3AWork%3E%0A%20%20%20%20%3C/rdf%3ARDF%3E%0A%20%20%3C/metadata%3E%0A%20%20%3Cg%0A%20%20%20%20%20transform%3D%22translate%28-239.44047%2C-363.22698%29%22%0A%20%20%20%20%20id%3D%22layer1%22%3E%0A%20%20%20%20%3Cpath%0A%20%20%20%20%20%20%20d%3D%22m%20290.96332%2C384.19885%20c%20-0.59424%2C-6.27896%20-6.01049%2C-8.39164%20-12.8518%2C-9.00126%20l%200.0128%2C-8.70824%20-5.30062%2C-0.007%20-0.0123%2C8.47872%20c%20-1.39346%2C-0.002%20-2.81788%2C0.0235%20-4.23308%2C0.0496%20l%200.0135%2C-8.53485%20-5.29778%2C-0.008%20-0.0149%2C8.70575%20c%20-1.14765%2C0.0217%20-2.27469%2C0.0414%20-3.3736%2C0.0405%20l%20-5.3e-4%2C-0.0271%20-7.31086%2C-0.0134%20-0.007%2C5.66124%20c%200%2C0%203.91442%2C-0.0688%203.84925%2C0.003%202.14703%2C0.004%202.84397%2C1.25133%203.04562%2C2.32724%20l%20-0.0143%2C9.92049%20c%200.14815%2C0.001%200.34143%2C0.008%200.56022%2C0.0378%20-0.17659%2C-3e-5%20-0.36561%2C-0.002%20-0.55995%2C-1.2e-4%20l%20-0.022%2C13.89765%20c%20-0.0952%2C0.67556%20-0.49402%2C1.75232%20-1.99407%2C1.75269%200.0678%2C0.0602%20-3.85316%2C-0.007%20-3.85316%2C-0.007%20l%20-1.06259%2C6.32874%206.89801%2C0.01%20c%201.28367%2C0.003%202.54669%2C0.0271%203.78665%2C0.0368%20l%20-0.0109%2C8.80736%205.29494%2C0.009%200.0128%2C-8.71427%20c%201.45379%2C0.0322%202.86073%2C0.0459%204.23429%2C0.0466%20l%20-0.0152%2C8.67412%205.30061%2C0.007%200.0147%2C-8.79173%20c%208.91219%2C-0.49805%2015.1527%2C-2.73385%2015.93965%2C-11.10113%200.63533%2C-6.73752%20-2.53%2C-9.74895%20-7.5868%2C-10.97123%203.07554%2C-1.56033%205.00104%2C-4.31475%204.55848%2C-8.90928%20z%20m%20-7.44387%2C18.82121%20c%20-0.007%2C6.58182%20-11.27551%2C5.81643%20-14.86789%2C5.81449%20l%200.0187%2C-11.66923%20c%203.59343%2C0.006%2014.85983%2C-1.01023%2014.84919%2C5.85474%20z%20m%20-2.44078%2C-16.46738%20c%20-0.0106%2C5.98811%20-9.40836%2C5.27536%20-12.40064%2C5.27116%20l%200.016%2C-10.58348%20c%202.99229%2C0.004%2012.39322%2C-0.93337%2012.38461%2C5.31232%20z%22%0A%20%20%20%20%20%20%20id%3D%22path3010%22%0A%20%20%20%20%20%20%20style%3D%22fill%3A%23ffffff%22%20/%3E%0A%20%20%3C/g%3E%0A%3C/svg%3E">
</button>
</nav>
@ -156,13 +159,13 @@ <h1 id="title">The 2022 /r/place Atlas</h1>
<div id="timeControls">
<input type="range" min="1" max="1" value="1" class="slider" id="timeControlsSlider">
</div>
<p><div id="author">Code owned by <a href="https://github.com/placeAtlas/atlas" target="_blank" rel="author">Place Atlas</a>.. Source on <a target="_blank" href="https://github.com/placeAtlas/atlas">GitHub</a>. This site is powered by <a href="https://www.netlify.com">Netlify</a>. Images provided by <a target="_blank" href="https://place.thatguyalex.com/">Alex Tsernoh</a>.</p>
<div id="author">
<p>Code owned by <a href="https://github.com/placeAtlas/atlas" target="_blank" rel="author">Place Atlas</a>. Source on <a target="_blank" href="https://github.com/placeAtlas/atlas">GitHub</a>. Site powered by <a href="https://www.netlify.com">Netlify</a>. Images provided by <a target="_blank" href="https://place.thatguyalex.com/">Alex Tsernoh</a>.</p>
</div>
</div>
<div id="drawControlsContainer">
<a id="drawBackButton" href="./">&lt; Back to the Atlas</a>
<a id="drawBackButton" class="button" href="./">&lt; Back to the Atlas</a>
<div id="drawControls">
<div>
<button id="undoButton" disabled>Undo</button>
@ -196,7 +199,7 @@ <h1 id="title">The 2022 /r/place Atlas</h1>
<p>You can then add more information about your object.</p>
<div style="background-color:#7289DA; padding:20px">
<p><b>Need Help?</b></p>
<b>You can ask for help on our discord server <a href="https://discord.gg/pJkm23b2nA">here</a>!</b><br>
<b>You can ask for help on <a href="https://discord.gg/pJkm23b2nA">our Discord server</a>!</b><br>
</div>
</div>
</div>
@ -209,7 +212,7 @@ <h1 id="title">The 2022 /r/place Atlas</h1>
<div id="exportWindow">
<p><b>Recommended:</b> Post directly after clicking this button. Don't forget to flair it with the "New Entry" tag. </p>
<div style="display:flex; flex-direction:column;align-items:center">
<a href="_blank" id="exportDirectPost">Post Direct to Reddit</a>
<a href="_blank" id="exportDirectPost" class="button">Post Direct to Reddit</a>
</div>
<hr style="border-bottom: solid black 1px"/>
<i>or...</i>
@ -228,30 +231,41 @@ <h1 id="title">The 2022 /r/place Atlas</h1>
<div id="donateWindow">
<h2>Donation Links</h2>
<p>Current 2022 Atlas Maintainers:</p>
<p> - <a target="_blank" href="https://paypal.me/placeAtlas/5">PayPal</a></p>
<p> - <a target="_blank" href="https://www.patreon.com/placeAtlas">Patreon</a></p>
<p> - <a target="_blank" href="https://ko-fi.com/placeatlas">Ko-Fi</a></p>
<a class="button" target="_blank" href="https://paypal.me/placeAtlas/5">
<svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>PayPal</title><path fill="white" d="M7.076 21.337H2.47a.641.641 0 0 1-.633-.74L4.944.901C5.026.382 5.474 0 5.998 0h7.46c2.57 0 4.578.543 5.69 1.81 1.01 1.15 1.304 2.42 1.012 4.287-.023.143-.047.288-.077.437-.983 5.05-4.349 6.797-8.647 6.797h-2.19c-.524 0-.968.382-1.05.9l-1.12 7.106zm14.146-14.42a3.35 3.35 0 0 0-.607-.541c-.013.076-.026.175-.041.254-.93 4.778-4.005 7.201-9.138 7.201h-2.19a.563.563 0 0 0-.556.479l-1.187 7.527h-.506l-.24 1.516a.56.56 0 0 0 .554.647h3.882c.46 0 .85-.334.922-.788.06-.26.76-4.852.816-5.09a.932.932 0 0 1 .923-.788h.58c3.76 0 6.705-1.528 7.565-5.946.36-1.847.174-3.388-.777-4.471z"/></svg>
PayPal
</a>
<a class="button" target="_blank" href="https://www.patreon.com/placeAtlas">
<svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>Patreon</title><path fill="white" d="M0 .48v23.04h4.22V.48zm15.385 0c-4.764 0-8.641 3.88-8.641 8.65 0 4.755 3.877 8.623 8.641 8.623 4.75 0 8.615-3.868 8.615-8.623C24 4.36 20.136.48 15.385.48z"/></svg>
Patreon
</a>
<a class="button" target="_blank" href="https://ko-fi.com/placeatlas">
<svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>Ko-fi</title><path fill="white" d="M23.881 8.948c-.773-4.085-4.859-4.593-4.859-4.593H.723c-.604 0-.679.798-.679.798s-.082 7.324-.022 11.822c.164 2.424 2.586 2.672 2.586 2.672s8.267-.023 11.966-.049c2.438-.426 2.683-2.566 2.658-3.734 4.352.24 7.422-2.831 6.649-6.916zm-11.062 3.511c-1.246 1.453-4.011 3.976-4.011 3.976s-.121.119-.31.023c-.076-.057-.108-.09-.108-.09-.443-.441-3.368-3.049-4.034-3.954-.709-.965-1.041-2.7-.091-3.71.951-1.01 3.005-1.086 4.363.407 0 0 1.565-1.782 3.468-.963 1.904.82 1.832 3.011.723 4.311zm6.173.478c-.928.116-1.682.028-1.682.028V7.284h1.77s1.971.551 1.971 2.638c0 1.913-.985 2.667-2.059 3.015z"/></svg>
Ko-Fi
</a>
<p>Original 2017 Atlas Developer (draemmli aka Roland Rytz): </p>
<p> - <a target="_blank" href="https://paypal.me/draemmli">PayPal</a></p>
<button id="closeBitcoinButton">Close</button>
<a class="button" target="_blank" href="https://paypal.me/draemmli">
<svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>PayPal</title><path fill="white" d="M7.076 21.337H2.47a.641.641 0 0 1-.633-.74L4.944.901C5.026.382 5.474 0 5.998 0h7.46c2.57 0 4.578.543 5.69 1.81 1.01 1.15 1.304 2.42 1.012 4.287-.023.143-.047.288-.077.437-.983 5.05-4.349 6.797-8.647 6.797h-2.19c-.524 0-.968.382-1.05.9l-1.12 7.106zm14.146-14.42a3.35 3.35 0 0 0-.607-.541c-.013.076-.026.175-.041.254-.93 4.778-4.005 7.201-9.138 7.201h-2.19a.563.563 0 0 0-.556.479l-1.187 7.527h-.506l-.24 1.516a.56.56 0 0 0 .554.647h3.882c.46 0 .85-.334.922-.788.06-.26.76-4.852.816-5.09a.932.932 0 0 1 .923-.788h.58c3.76 0 6.705-1.528 7.565-5.946.36-1.847.174-3.388-.777-4.471z"/></svg>
PayPal
</a>
<br>
<button id="closeDonateButton">Close</button>
</div>
</div>
</div>
<script type="text/javascript" src="./_js/time.js?version=1.0.3"></script>
<script type="text/javascript" src="./_js/infoblock.js?version=1.0"></script>
<script type="text/javascript" src="./_js/pointInPolygon.js?version=1.0"></script>
<script type="text/javascript" src="./_js/atlas.js?version=1.0.50"></script>
<script type="text/javascript" src="./_js/view.js?version=1.0.4"></script>
<script type="text/javascript" src="./_js/overlap.js?version=1.0.4"></script>
<script type="text/javascript" src="./_js/draw.js?version=1.0.3"></script>
<script type="text/javascript" src="./_js/main.js?version=1.0.3"></script>
<script type="text/javascript" src="./_js/time.js"></script>
<script type="text/javascript" src="./_js/infoblock.js"></script>
<script type="text/javascript" src="./_js/pointInPolygon.js"></script>
<script type="text/javascript" src="./_js/atlas.js"></script>
<script type="text/javascript" src="./_js/view.js"></script>
<script type="text/javascript" src="./_js/overlap.js"></script>
<script type="text/javascript" src="./_js/draw.js"></script>
<script type="text/javascript" src="./_js/main.js"></script>
<!--
<script type="text/javascript" src="./_js/stats.js?version=1.0.0"></script>
<script type="text/javascript" src="./_js/stats.js"></script>
<script type="text/javascript" src="./_js/minified.js?version=1.0.102"></script>
<script type="text/javascript" src="./_js/minified.js"></script>
-->
</body>
</html>