Merge branch 'cleanup' of https://github.com/placeAtlas/atlas into cleanup

This commit is contained in:
Cheng Hann Gan 2023-08-07 13:12:21 -04:00
commit 0631a07abf
38 changed files with 1351 additions and 1116 deletions

View File

@ -92,9 +92,27 @@
"design",
"doc"
]
},
{
"login": "Hans5958",
"name": "Hans5958",
"avatar_url": "https://avatars.githubusercontent.com/u/11584103?v=4",
"profile": "https://github.com/Hans5958",
"contributions": [
"a11y",
"bug",
"code",
"content",
"data",
"doc",
"design",
"maintenance",
"projectManagement",
"tool"
]
}
],
"contributorsPerLine": 7,
"contributorsPerLine": 4,
"skipCi": true,
"repoType": "github",
"repoHost": "https://github.com",

View File

@ -1,11 +1,11 @@
name: Entry edit submission
description: Edit an existing entry after using the website
labels: ["entry update"]
name: Patch submission
description: Make changes to the Atlas data after using the website
labels: ["atlas data: patch"]
body:
- type: markdown
attributes:
value: |
Make sure you have prepared your JSON data that you get after editing. If you haven't, [CONTRIBUTING.md](https://github.com/placeAtlas/atlas/blob/master/CONTRIBUTING.md) has a guide for editing an existing entry.
Make sure you have prepared your JSON data that you get after editing. If you haven't, [CONTRIBUTING.md](https://github.com/placeAtlas/atlas-2022/blob/master/CONTRIBUTING.md) has a guide for editing an existing entry.
- type: textarea
id: description
attributes:
@ -14,8 +14,8 @@ body:
- type: textarea
id: json
attributes:
label: Entry data
description: Upon editing, please copy the exported JSON-formatted data. This will be automatically formatted into code, so no need for backticks.
label: Patch
description: Upon editing, please copy the exported JSON-formatted patch. This will be automatically formatted into code, so no need for backticks.
render: json
validations:
required: true

View File

@ -1,6 +1,6 @@
name: Edit request
description: Request for edits of the Atlas data
labels: ["entry update"]
description: Request for changes to the Atlas data
labels: ["atlas data: request"]
body:
- type: textarea
id: description

3
.github/labeler-pr.yml vendored Normal file
View File

@ -0,0 +1,3 @@
staging merge:
- 'cleanup'
- 'staging/*'

5
.github/labeler.yml vendored Normal file
View File

@ -0,0 +1,5 @@
'atlas data: patch':
- data/patches/**
'atlas data: direct':
- web/atlas.json

13
.github/workflows/pr-labeler.yml vendored Normal file
View File

@ -0,0 +1,13 @@
name: "PR Labeler"
on:
- pull_request_target
jobs:
triage:
name: Triage
permissions:
contents: read
pull-requests: write
runs-on: ubuntu-latest
steps:
- uses: actions/labeler@v4

View File

@ -20,6 +20,12 @@ jobs:
qodana:
name: Qodana
runs-on: ubuntu-latest
if: github.repository_owner == 'placeAtlas'
permissions:
contents: write
pull-requests: write
checks: write
security-events: write
steps:
- name: Checkout code
uses: actions/checkout@v3

View File

@ -1,14 +1,18 @@
name: Validate Atlas data
name: Validate JSON files
on:
push:
paths:
- web/atlas.json
- data/patches/*.json
pull_request:
paths:
- web/atlas.json
- data/patches/*.json
jobs:
validate:
name: Validate
permissions:
contents: read
runs-on: ubuntu-latest
steps:
- name: Checkout code
@ -17,7 +21,7 @@ jobs:
uses: actions/cache@v3
with:
path: ~/.cache/pip
key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }}
key: ${{ runner.os }}-pip-${{ hashFiles('tools/ci/requirements.txt') }}
restore-keys: |
${{ runner.os }}-pip-
- name: Validate

View File

@ -1,36 +1,38 @@
# Contributing
This project is open source, and contributions are welcome. In fact, the Atlas relies on user contributions.
This project is open-source, and contributions are welcome. In fact, the Atlas relies on user contributions.
You may contribute to the project by submitting a Pull Request on the GitHub repo or sending your submissions through [Reddit](https://www.reddit.com/r/placeAtlas2). Other than that, you can get help from [Discord](https://discord.gg/pJkm23b2nA) or [Reddit](https://www.reddit.com/r/placeAtlas2).
## New Atlas entries
To contribute to the map, we require a certain format for artwork region and labels. This can be generated on [the drawing mode](https://place-atlas.stefanocoding.me?mode=draw) on the website.
To contribute to the map, we require a certain format for artwork region and labels. This can be generated on [the drawing mode](https://2022.place-atlas.stefanocoding.me?mode=draw) on the website.
To add a new entry, go to [the drawing mode](https://place-atlas.stefanocoding.me?mode=draw) and draw a shape/polygon around the region you'd like to describe. You can use the <kbd>Undo</kbd>, <kbd>Redo</kbd>, and <kbd>Reset</kbd> buttons to help you creating a good polygon. Make sure that the lines you're drawing don't form a [self-intersecting polygon](https://upload.wikimedia.org/wikipedia/commons/thumb/0/0f/Complex_polygon.svg/288px-Complex_polygon.svg.png).
To add a new entry, go to [the drawing mode](https://2022.place-atlas.stefanocoding.me?mode=draw) and draw a shape/polygon around the region you'd like to describe. You can use the <kbd>Undo</kbd>, <kbd>Redo</kbd>, and <kbd>Reset</kbd> buttons to help you creating a good polygon. Make sure that the lines you're drawing don't form a [self-intersecting polygon](https://upload.wikimedia.org/wikipedia/commons/thumb/0/0f/Complex_polygon.svg/288px-Complex_polygon.svg.png).
Multiple periods can be added to represent the changing state of the artwork on different times. You can set the start and end period, as well as chosing the appropriate canvas variations. You can also copy the polygon from one period to the other, duplicating a period to be edited later, as well as deleting a period (if there is more than one). An alert is also shown if there are errors for assistance.
If you want to see which areas of the canvas do not have entries yet, select "Highlight Empty" to hide areas that already have entries.
When you're happy with the shape you've drawn, press <kbd>Finish</kbd>. You will now be able to enter some information about the highlighted region:
Multiple periods can be added to represent the changing state of the artwork on different times. You can set the start and end period, as well as chosing the appropriate canvas variations. You can also copy the polygon from one period to the other, duplicating a period to be edited later, as well as deleting a period (if there is more than one). An alert is also shown if there are errors that needed attention.
When you're happy with the shape you've drawn, press <kbd>Finish</kbd>. You will now be able to enter some information about the entry:
- **Name**: A short, descriptive name.
- **Description**: A short description that will also be understood by somebody not familiar with the topic. Usually, the first sentence on Wikipedia is a good example.
- **Links**: Some links that's either most relevant to the topic, or that was responsible for creating the artwork.
- **Description**: A short description that can be understood by somebody not familiar with the topic. If you were involved in drawing this artwork, you may include the meta, describing the process of drawing the artwork in the event. To include lengthy, additional information, consider creating a page on [the r/place Wiki](https://place-wiki.stefanocoding.me/).
- **Links**: Some links that are most relevant to the topic, and/or regarding the process of the drawing the artwork in the event.
- **Website**: If you're describing a project, the project's main website would be suitable here.
- **Subreddit**: Format it like `r/subreddit`.
- **Discord**: Write the invite code, that the invite link without the `discord.gg/` part.
- **Wiki**: The page title of [The r/place Wiki](https://place-wiki.stefanocoding.me/).
- **Wiki**: The page title of [the r/place Wiki](https://place-wiki.stefanocoding.me/).
All fields but the name are optional. For example, a country flag doesn't necessarily need a description.
Once you've entered all the information, you'll be presented with a pop-up window containing some [JSON](https://en.wikipedia.org/wiki/JSON)-formatted submission data. Depending on the method, there are two preferred methods.
Once you've entered all the information, you'll be presented with a pop-up window containing some [JSON](https://en.wikipedia.org/wiki/JSON)-formatted data. This is the patch that you are going to submit. Depending on the method, there are two preferred methods.
### Through Reddit
You can press the <kbd>Post Direct to Reddit</kbd> button, which will open a page with the title and body already been filled for you. You don't need to change anything what has been prepared.
If that didn't work, copy the entire JSON text and [create a new text post on the subreddit](https://www.reddit.com/r/placeAtlas2/submit). You don't need to add any other text; just directly send the data.
If that didn't work, copy the entire JSON text and [create a new text post on the subreddit](https://www.reddit.com/r/placeAtlas2/submit). You don't need to add any other text; just directly send the patch.
Remember to flair your post with <kbd>New Entry</kbd>. On New Reddit, click the <kbd>Flair</kbd> button on the bottom part, and select <kbd>New Entry</kbd>. On Old Reddit, click the <kbd>select</kbd> button on the "choose a flair" section instead.
@ -38,7 +40,14 @@ Remember to flair your post with <kbd>New Entry</kbd>. On New Reddit, click the
If you know about Git and how to create a pull request on GitHub, you can try create a patch that will be merged, along with other patches, by one of the members.
You can try pressing the <kbd>Submit Direct to GitHub</kbd> button, which will open a page with the patch file already been prepared to you. If you haven't forked the repository, you would need to fork it with the provided instruction shown on the page. You may add attribution by adding an `_author` key, explained in the next paragraphs. After that, you can press <kbd>Submit changes</kbd>, add follow the steps to create a pull request within GitHub.
You can try pressing the <kbd>Submit Direct to GitHub</kbd> button, which will open a page with the patch file already been prepared to you.
If that didn't work, copy the entire JSON text and [create a new patch file to the repository through GitHub](https://github.com/placeAtlas/atlas-2022/new/cleanup/data/patches?filename=gh-0000-ENTRY-NAME-HERE.json
). Upon opening, replace the `ENTRY-NAME-HERE` into the name of the entry (with the slug format, if possible, e.g. `foo-bar`). You don't need to add any other text; just directly send the patch.
If you haven't forked the repository, you would need to fork it with the provided instruction shown on the page. You may add attribution by adding an `_author` key, explained in the next paragraphs. After that, you can press <kbd>Submit changes</kbd>, add follow the steps to create a pull request within GitHub.
The commit message and description doesn't matter, but you may change it into something more descriptive to make it easier for checking (e.g. <kbd>Add Foo Bar</kbd> or <kbd>Edit Foo Bar</kbd> for the commit message). However, we suggest you to edit the title (at least) and the description of the pull request, containing the changes that you want to do (something like <kbd>Add Foo Bar</kbd> or <kbd>Edit Foo Bar</kbd> for the title, similar to the commit message, is also sufficient).
If you can fork and clone the repository, you can use the provided `tools/create_patch.py` script. This script helps you to create a working patch, along with additional data such as your name for attribution sakes. Simply run the script inside the `tools/` folder and follow the given instructions.
@ -46,15 +55,15 @@ If you want to do this manually (e.g. you don't have Python), you can create a p
```json5
{
"id": 0,
"id": -1, // -1 signififies a new entry.
// ...
"_author": "Hans5958_",
// or...
"_author": "gh:Hans5958",
// Choose one of the folllowing:
"_author": "Hans5958_", // Links to https://reddit.com/user/Hans5958_
"_author": "gh:Hans5958", // Links to https://github.com/Hans5958
}
```
Once you have successfully created the patch, the file can be committed, and a pull request towards the `cleanup` branch can be created. A member will merge the pull request if it is adequate.
Once you have successfully created the patch, the file can be committed, and a pull request towards the `cleanup` branch can be created. A member will merge the pull request if it is adequate.
## Edits to Atlas entries
@ -66,25 +75,25 @@ You can use the website to edit single entries easily. On the website, click <kb
Upon submitting, if you use Reddit, please flair it as <kbd>Edit Entry</kbd> instead. The method stays the same if you use GitHub.
As an alternative, you can also submit an issue on GitHub using [this form](https://github.com/placeAtlas/atlas/issues/new?assignees=&labels=entry+update&template=edit-entry.yml) or report it on our Discord server.
As an alternative, you can also submit an issue on GitHub using [this form](https://github.com/placeAtlas/atlas-2022/issues/new?assignees=&labels=entry+update&template=edit-entry.yml) or report it on our Discord server.
### Manually
### Manually by direct edits
Edits are also welcome on this repository using Git through GitHub. You may use Git or GitHub for bulk or large-scale changes, such as removing duplicates.
Direct edits to the `web/atlas.json` are also welcome on this repository using Git through GitHub. You may use Git or GitHub for bulk or large-scale changes, such as removing duplicates, or doing those that are not possible by using patches, such as removing an entry. Keep in mind that this may causes conflicts, so only do it when necessary.
`web/atlas.json` is where the Atlas data is located, in which you can edit on GitHub. The next section includes an example of an entry.
Upon creating a fork of this repository and pushing the changes, create a pull request towards the `cleanup` branch. A member will merge the pull request if it is adequate.
To help find duplicates, [use the Overlap mode](https://place-atlas.stefanocoding.me?mode=overlap).
To help find duplicates, [use the Overlap mode](https://2022.place-atlas.stefanocoding.me?mode=overlap).
### Example
Hereforth is an example of the structured data. The example has been expanded, but please save it in the way so each line is an entry which is minified. The `aformatter.py` script can help you with this.
Hereforth is an example of the structured entry data. The example has been expanded, but when editing directly, please save it in the way so each line is an entry that is minified. The `tools/aformatter.py` script can help you with this.
```json5
{
"id": "tu203o",
"id": 1,
"name": "An entry",
"description": "This is an entry, it is remarkable.",
"links": {
@ -107,8 +116,8 @@ Hereforth is an example of the structured data. The example has been expanded, b
```
`109-166, T:0-1` has this meaning.
- `109-166`: Default canvas variation (r/place), period [109](https://place-atlas.stefanocoding.me/#/109) to [166](https://place-atlas.stefanocoding.me/#/166).
- `T:0-1`: "The Final Clean" canvas variation, period [0](https://place-atlas.stefanocoding.me/#/T:0) (The Final Clean) to [1](https://place-atlas.stefanocoding.me/#/T:1) (Unofficial Corrections).
- `109-166`: Default canvas variation (r/place), period [109](https://2022.place-atlas.stefanocoding.me/#/109) to [166](https://2022.place-atlas.stefanocoding.me/#/166).
- `T:0-1`: "The Final Clean" canvas variation, period [0](https://2022.place-atlas.stefanocoding.me/#/T:0) (The Final Clean) to [1](https://2022.place-atlas.stefanocoding.me/#/T:1) (Unofficial Corrections).
## Development
@ -124,15 +133,11 @@ Opening the HTML file on your browser is adequate enough to edit. If it doesn't
# Run it inside the web/ folder.
cd web
# Choose one of the following.
# Python 2
python -m SimpleHTTPServer 8000
# Python 3
python -m http.server 8000
# Node.js (http-server)
npx http-server
# Node.js (serve)
npx serve
# Choose one of the following:
python -m SimpleHTTPServer 8000 # Python 2
python -m http.server 8000 # Python 3
npx http-server # Node.js (http-server)
npx serve # Node.js (serve)
```
### Tools
@ -143,4 +148,4 @@ The `tools` folder have various scripts for the maintainance of the project, suc
- Formatting/tidying up the data
- Building the site for production
The tools are built using either Node.js and/or Python (3).
The tools may built with various programming languages, but mostly it is made in Python (3).

View File

@ -1,10 +1,10 @@
[![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)
[![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://2022.place-atlas.stefanocoding.me/)
![Commit activity](https://img.shields.io/github/commit-activity/w/placeAtlas/atlas-2022)
[![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)
[![License](https://img.shields.io/github/license/placeAtlas/atlas-2022)](https://github.com/placeAtlas/atlas-2022/blob/master/LICENSE)
[![Discord](https://img.shields.io/discord/960791635342524496?color=%235865F2&logo=discord&logoColor=white)](https://discord.gg/pJkm23b2nA)
[![Subreddit subscribers](https://img.shields.io/reddit/subreddit-subscribers/placeAtlas2?color=%23FF4500&label=r%2FplaceAtlas2&logo=reddit&logoColor=white)](https://www.reddit.com/r/placeAtlas2/)
[![Website](https://img.shields.io/static/v1?label=website&message=place-atlas.stefanocoding.me&color=blue)](https://place-atlas.stefanocoding.me/)
[![Website](https://img.shields.io/static/v1?label=website&message=2022.place-atlas.stefanocoding.me&color=blue)](https://2022.place-atlas.stefanocoding.me/)
# The 2022 r/place Atlas
@ -14,7 +14,7 @@ This project was established by Roland Rytz for the event in 2017, and further d
This project is licensed under the [GNU Affero General Public License v3.0](LICENSE).
You can check out the website by visiting [place-atlas.stefanocoding.me](https://place-atlas.stefanocoding.me/). If you want to keep distance from GitHub, you may visit [r/placeAtlas2](https://www.reddit.com/r/placeAtlas2/).
You can check out the website by visiting [2022.place-atlas.stefanocoding.me](https://2022.place-atlas.stefanocoding.me/). If you want to keep distance from GitHub, you may visit [r/placeAtlas2](https://www.reddit.com/r/placeAtlas2/).
## Contributing
@ -27,7 +27,7 @@ Please read [CONTRIBUTING.md](CONTRIBUTING.md) to learn how to submit a new entr
## Contributors
<!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section -->
[![All Contributors](https://img.shields.io/badge/all_contributors-6-orange.svg?style=flat)](#contributors)
[![All Contributors](https://img.shields.io/badge/all_contributors-7-orange.svg?style=flat)](#contributors)
<!-- ALL-CONTRIBUTORS-BADGE:END -->
Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key))):
@ -38,12 +38,15 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
<table>
<tbody>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://stefanocoding.me"><img src="https://avatars.githubusercontent.com/u/25939526?v=4?s=100" width="100px;" alt="Stefano"/><br /><sub><b>Stefano</b></sub></a><br /><a href="#business-Codixer" title="Business development">💼</a> <a href="https://github.com/placeAtlas/atlas/commits?author=Codixer" title="Code">💻</a> <a href="#content-Codixer" title="Content">🖋</a> <a href="#data-Codixer" title="Data">🔣</a> <a href="#design-Codixer" title="Design">🎨</a> <a href="#fundingFinding-Codixer" title="Funding Finding">🔍</a> <a href="#infra-Codixer" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a> <a href="#maintenance-Codixer" title="Maintenance">🚧</a> <a href="#projectManagement-Codixer" title="Project Management">📆</a> <a href="#question-Codixer" title="Answering Questions">💬</a> <a href="#security-Codixer" title="Security">🛡️</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/ab-gh"><img src="https://avatars.githubusercontent.com/u/18347932?v=4?s=100" width="100px;" alt="ash"/><br /><sub><b>ash</b></sub></a><br /><a href="#business-ab-gh" title="Business development">💼</a> <a href="#content-ab-gh" title="Content">🖋</a> <a href="#data-ab-gh" title="Data">🔣</a> <a href="#projectManagement-ab-gh" title="Project Management">📆</a> <a href="https://github.com/placeAtlas/atlas/pulls?q=is%3Apr+reviewed-by%3Aab-gh" title="Reviewed Pull Requests">👀</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://linktr.ee/aeywoo"><img src="https://avatars.githubusercontent.com/u/65846594?v=4?s=100" width="100px;" alt="Aeywoo"/><br /><sub><b>Aeywoo</b></sub></a><br /><a href="#business-Aeywoo" title="Business development">💼</a> <a href="https://github.com/placeAtlas/atlas/issues?q=author%3AAeywoo" title="Bug reports">🐛</a> <a href="#blog-Aeywoo" title="Blogposts">📝</a> <a href="#content-Aeywoo" title="Content">🖋</a> <a href="#maintenance-Aeywoo" title="Maintenance">🚧</a> <a href="#research-Aeywoo" title="Research">🔬</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/AnonymousRandomPerson"><img src="https://avatars.githubusercontent.com/u/6516839?v=4?s=100" width="100px;" alt="AnonymousRandomPerson"/><br /><sub><b>AnonymousRandomPerson</b></sub></a><br /><a href="#data-AnonymousRandomPerson" title="Data">🔣</a> <a href="#content-AnonymousRandomPerson" title="Content">🖋</a> <a href="#research-AnonymousRandomPerson" title="Research">🔬</a> <a href="https://github.com/placeAtlas/atlas/commits?author=AnonymousRandomPerson" title="Code">💻</a> <a href="https://github.com/placeAtlas/atlas/pulls?q=is%3Apr+reviewed-by%3AAnonymousRandomPerson" title="Reviewed Pull Requests">👀</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/mxdanger"><img src="https://avatars.githubusercontent.com/u/32040254?v=4?s=100" width="100px;" alt="mxdanger"/><br /><sub><b>mxdanger</b></sub></a><br /><a href="https://github.com/placeAtlas/atlas/commits?author=mxdanger" title="Code">💻</a> <a href="#a11y-mxdanger" title="Accessibility">️️️️♿️</a> <a href="https://github.com/placeAtlas/atlas/issues?q=author%3Amxdanger" title="Bug reports">🐛</a> <a href="#design-mxdanger" title="Design">🎨</a> <a href="#ideas-mxdanger" title="Ideas, Planning, & Feedback">🤔</a> <a href="#infra-mxdanger" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a> <a href="#maintenance-mxdanger" title="Maintenance">🚧</a> <a href="#tool-mxdanger" title="Tools">🔧</a> <a href="#userTesting-mxdanger" title="User Testing">📓</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/artillect"><img src="https://avatars.githubusercontent.com/u/8906201?v=4?s=100" width="100px;" alt="Riley"/><br /><sub><b>Riley</b></sub></a><br /><a href="#data-artillect" title="Data">🔣</a> <a href="#design-artillect" title="Design">🎨</a> <a href="https://github.com/placeAtlas/atlas/commits?author=artillect" title="Documentation">📖</a></td>
<td align="center" valign="top" width="25%"><a href="https://stefanocoding.me"><img src="https://avatars.githubusercontent.com/u/25939526?v=4?s=100" width="100px;" alt="Stefano"/><br /><sub><b>Stefano</b></sub></a><br /><a href="#business-Codixer" title="Business development">💼</a> <a href="https://github.com/placeAtlas/atlas/commits?author=Codixer" title="Code">💻</a> <a href="#content-Codixer" title="Content">🖋</a> <a href="#data-Codixer" title="Data">🔣</a> <a href="#design-Codixer" title="Design">🎨</a> <a href="#fundingFinding-Codixer" title="Funding Finding">🔍</a> <a href="#infra-Codixer" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a> <a href="#maintenance-Codixer" title="Maintenance">🚧</a> <a href="#projectManagement-Codixer" title="Project Management">📆</a> <a href="#question-Codixer" title="Answering Questions">💬</a> <a href="#security-Codixer" title="Security">🛡️</a></td>
<td align="center" valign="top" width="25%"><a href="https://github.com/ab-gh"><img src="https://avatars.githubusercontent.com/u/18347932?v=4?s=100" width="100px;" alt="ash"/><br /><sub><b>ash</b></sub></a><br /><a href="#business-ab-gh" title="Business development">💼</a> <a href="#content-ab-gh" title="Content">🖋</a> <a href="#data-ab-gh" title="Data">🔣</a> <a href="#projectManagement-ab-gh" title="Project Management">📆</a> <a href="https://github.com/placeAtlas/atlas/pulls?q=is%3Apr+reviewed-by%3Aab-gh" title="Reviewed Pull Requests">👀</a></td>
<td align="center" valign="top" width="25%"><a href="https://linktr.ee/aeywoo"><img src="https://avatars.githubusercontent.com/u/65846594?v=4?s=100" width="100px;" alt="Aeywoo"/><br /><sub><b>Aeywoo</b></sub></a><br /><a href="#business-Aeywoo" title="Business development">💼</a> <a href="https://github.com/placeAtlas/atlas/issues?q=author%3AAeywoo" title="Bug reports">🐛</a> <a href="#blog-Aeywoo" title="Blogposts">📝</a> <a href="#content-Aeywoo" title="Content">🖋</a> <a href="#maintenance-Aeywoo" title="Maintenance">🚧</a> <a href="#research-Aeywoo" title="Research">🔬</a></td>
<td align="center" valign="top" width="25%"><a href="https://github.com/AnonymousRandomPerson"><img src="https://avatars.githubusercontent.com/u/6516839?v=4?s=100" width="100px;" alt="AnonymousRandomPerson"/><br /><sub><b>AnonymousRandomPerson</b></sub></a><br /><a href="#data-AnonymousRandomPerson" title="Data">🔣</a> <a href="#content-AnonymousRandomPerson" title="Content">🖋</a> <a href="#research-AnonymousRandomPerson" title="Research">🔬</a> <a href="https://github.com/placeAtlas/atlas/commits?author=AnonymousRandomPerson" title="Code">💻</a> <a href="https://github.com/placeAtlas/atlas/pulls?q=is%3Apr+reviewed-by%3AAnonymousRandomPerson" title="Reviewed Pull Requests">👀</a></td>
</tr>
<tr>
<td align="center" valign="top" width="25%"><a href="https://github.com/mxdanger"><img src="https://avatars.githubusercontent.com/u/32040254?v=4?s=100" width="100px;" alt="mxdanger"/><br /><sub><b>mxdanger</b></sub></a><br /><a href="https://github.com/placeAtlas/atlas/commits?author=mxdanger" title="Code">💻</a> <a href="#a11y-mxdanger" title="Accessibility">️️️️♿️</a> <a href="https://github.com/placeAtlas/atlas/issues?q=author%3Amxdanger" title="Bug reports">🐛</a> <a href="#design-mxdanger" title="Design">🎨</a> <a href="#ideas-mxdanger" title="Ideas, Planning, & Feedback">🤔</a> <a href="#infra-mxdanger" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a> <a href="#maintenance-mxdanger" title="Maintenance">🚧</a> <a href="#tool-mxdanger" title="Tools">🔧</a> <a href="#userTesting-mxdanger" title="User Testing">📓</a></td>
<td align="center" valign="top" width="25%"><a href="https://github.com/artillect"><img src="https://avatars.githubusercontent.com/u/8906201?v=4?s=100" width="100px;" alt="Riley"/><br /><sub><b>Riley</b></sub></a><br /><a href="#data-artillect" title="Data">🔣</a> <a href="#design-artillect" title="Design">🎨</a> <a href="https://github.com/placeAtlas/atlas/commits?author=artillect" title="Documentation">📖</a></td>
<td align="center" valign="top" width="25%"><a href="https://github.com/Hans5958"><img src="https://avatars.githubusercontent.com/u/11584103?v=4?s=100" width="100px;" alt="Hans5958"/><br /><sub><b>Hans5958</b></sub></a><br /><a href="#a11y-Hans5958" title="Accessibility">️️️️♿️</a> <a href="https://github.com/placeAtlas/atlas/issues?q=author%3AHans5958" title="Bug reports">🐛</a> <a href="https://github.com/placeAtlas/atlas/commits?author=Hans5958" title="Code">💻</a> <a href="#content-Hans5958" title="Content">🖋</a> <a href="#data-Hans5958" title="Data">🔣</a> <a href="https://github.com/placeAtlas/atlas/commits?author=Hans5958" title="Documentation">📖</a> <a href="#design-Hans5958" title="Design">🎨</a> <a href="#maintenance-Hans5958" title="Maintenance">🚧</a> <a href="#projectManagement-Hans5958" title="Project Management">📆</a> <a href="#tool-Hans5958" title="Tools">🔧</a></td>
</tr>
</tbody>
</table>
@ -53,4 +56,4 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
<!-- ALL-CONTRIBUTORS-LIST:END -->
This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. This section only includes GitHub contributions. Other credits are shown on [the About page](https://place-atlas.stefanocoding.me/about).
This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. This section only includes GitHub contributions. Other credits are shown on [the About page](https://2022.place-atlas.stefanocoding.me/about).

View File

@ -12726,3 +12726,6 @@ zznclm
147stk6
147spg0
147ktca
15fw1j9
15cwuqe
15d6x9i

View File

@ -1,11 +1,11 @@
[build]
publish = "dist/"
command = "FILE=tools/ci/build-prod.sh; rm -rf dist/; if [ -f $FILE ]; then bash $FILE; else cp -r web/ dist/; fi"
ignore = "git diff --quiet $CACHED_COMMIT_REF $COMMIT_REF web/ .parcelrc netlify.toml package-lock.json package.json postcss.config.js"
ignore = "git diff --quiet $CACHED_COMMIT_REF $COMMIT_REF web/ tools/ .parcelrc netlify.toml package-lock.json package.json postcss.config.js"
[build.environment]
PYTHON_VERSION = "3.8"
[context.deploy-preview]
command = "FILE=tools/ci/build-preview.sh; rm -rf dist/; if [ -f $FILE ]; then bash $FILE; else cp -r web/ dist/; fi"
ignore = "git diff --quiet $CACHED_COMMIT_REF $COMMIT_REF data/patches/ web/ .parcelrc netlify.toml package-lock.json package.json postcss.config.js"
ignore = "git diff --quiet $CACHED_COMMIT_REF $COMMIT_REF data/patches/ web/ tools/ .parcelrc netlify.toml package-lock.json package.json postcss.config.js"

89
package-lock.json generated
View File

@ -1926,9 +1926,9 @@
}
},
"node_modules/all-contributors-cli": {
"version": "6.24.0",
"resolved": "https://registry.npmjs.org/all-contributors-cli/-/all-contributors-cli-6.24.0.tgz",
"integrity": "sha512-7oSKr2PnqxsOotuSwciltcFTS1eVRdjR0cn99hbElfff7gRQBShVhsf/XBprY41sLcgqTk0l0MKgKv6QNgZdMg==",
"version": "6.26.1",
"resolved": "https://registry.npmjs.org/all-contributors-cli/-/all-contributors-cli-6.26.1.tgz",
"integrity": "sha512-Ymgo3FJACRBEd1eE653FD1J/+uD0kqpUNYfr9zNC1Qby0LgbhDBzB3EF6uvkAbYpycStkk41J+0oo37Lc02yEw==",
"dev": true,
"dependencies": {
"@babel/runtime": "^7.7.6",
@ -1947,6 +1947,9 @@
},
"engines": {
"node": ">=4"
},
"optionalDependencies": {
"prettier": "^2"
}
},
"node_modules/all-contributors-cli/node_modules/ansi-styles": {
@ -3759,10 +3762,16 @@
"dev": true
},
"node_modules/nanoid": {
"version": "3.3.4",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz",
"integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==",
"version": "3.3.6",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz",
"integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==",
"dev": true,
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/ai"
}
],
"bin": {
"nanoid": "bin/nanoid.cjs"
},
@ -3965,9 +3974,9 @@
}
},
"node_modules/parcel-resolver-ignore": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/parcel-resolver-ignore/-/parcel-resolver-ignore-2.1.3.tgz",
"integrity": "sha512-C8uLvR4o7SPRSsQ/Nylm1/PdsLwn/Z9bzCs66qT3XIebJC7ojaFFF3MDl/mie5audngjcFF8wzU0AoEQkZq2pA==",
"version": "2.1.5",
"resolved": "https://registry.npmjs.org/parcel-resolver-ignore/-/parcel-resolver-ignore-2.1.5.tgz",
"integrity": "sha512-/2zgQw3J/2YA7L6JXg4XKBWT/SXDZx+PfweWcCsllchNVwFvK7jDJhG6h+puy+e15Rm9A/ubuuHYwANQHVXp2A==",
"dev": true,
"engines": {
"parcel": ">=2.0.0"
@ -4128,9 +4137,9 @@
}
},
"node_modules/postcss": {
"version": "8.4.21",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.21.tgz",
"integrity": "sha512-tP7u/Sn/dVxK2NnruI4H9BG+x+Wxz6oeZ1cJ8P6G/PZY0IKk4k/63TDsQf2kQq3+qoJeLm2kIBUNlZe3zgb4Zg==",
"version": "8.4.26",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.26.tgz",
"integrity": "sha512-jrXHFF8iTloAenySjM/ob3gSj7pCu0Ji49hnjqzsgSRa50hkWCKD0HQ+gMNJkW38jBI68MpAAg7ZWwHwX8NMMw==",
"dev": true,
"funding": [
{
@ -4140,10 +4149,14 @@
{
"type": "tidelift",
"url": "https://tidelift.com/funding/github/npm/postcss"
},
{
"type": "github",
"url": "https://github.com/sponsors/ai"
}
],
"dependencies": {
"nanoid": "^3.3.4",
"nanoid": "^3.3.6",
"picocolors": "^1.0.0",
"source-map-js": "^1.0.2"
},
@ -4678,6 +4691,22 @@
"node": ">=12"
}
},
"node_modules/prettier": {
"version": "2.8.8",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz",
"integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==",
"dev": true,
"optional": true,
"bin": {
"prettier": "bin-prettier.js"
},
"engines": {
"node": ">=10.13.0"
},
"funding": {
"url": "https://github.com/prettier/prettier?sponsor=1"
}
},
"node_modules/purgecss": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/purgecss/-/purgecss-5.0.0.tgz",
@ -6521,9 +6550,9 @@
"dev": true
},
"all-contributors-cli": {
"version": "6.24.0",
"resolved": "https://registry.npmjs.org/all-contributors-cli/-/all-contributors-cli-6.24.0.tgz",
"integrity": "sha512-7oSKr2PnqxsOotuSwciltcFTS1eVRdjR0cn99hbElfff7gRQBShVhsf/XBprY41sLcgqTk0l0MKgKv6QNgZdMg==",
"version": "6.26.1",
"resolved": "https://registry.npmjs.org/all-contributors-cli/-/all-contributors-cli-6.26.1.tgz",
"integrity": "sha512-Ymgo3FJACRBEd1eE653FD1J/+uD0kqpUNYfr9zNC1Qby0LgbhDBzB3EF6uvkAbYpycStkk41J+0oo37Lc02yEw==",
"dev": true,
"requires": {
"@babel/runtime": "^7.7.6",
@ -6535,6 +6564,7 @@
"lodash": "^4.11.2",
"node-fetch": "^2.6.0",
"pify": "^5.0.0",
"prettier": "^2",
"yargs": "^15.0.1"
},
"dependencies": {
@ -7823,9 +7853,9 @@
"dev": true
},
"nanoid": {
"version": "3.3.4",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz",
"integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==",
"version": "3.3.6",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz",
"integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==",
"dev": true
},
"node-addon-api": {
@ -8015,9 +8045,9 @@
}
},
"parcel-resolver-ignore": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/parcel-resolver-ignore/-/parcel-resolver-ignore-2.1.3.tgz",
"integrity": "sha512-C8uLvR4o7SPRSsQ/Nylm1/PdsLwn/Z9bzCs66qT3XIebJC7ojaFFF3MDl/mie5audngjcFF8wzU0AoEQkZq2pA==",
"version": "2.1.5",
"resolved": "https://registry.npmjs.org/parcel-resolver-ignore/-/parcel-resolver-ignore-2.1.5.tgz",
"integrity": "sha512-/2zgQw3J/2YA7L6JXg4XKBWT/SXDZx+PfweWcCsllchNVwFvK7jDJhG6h+puy+e15Rm9A/ubuuHYwANQHVXp2A==",
"dev": true,
"requires": {}
},
@ -8073,12 +8103,12 @@
"dev": true
},
"postcss": {
"version": "8.4.21",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.21.tgz",
"integrity": "sha512-tP7u/Sn/dVxK2NnruI4H9BG+x+Wxz6oeZ1cJ8P6G/PZY0IKk4k/63TDsQf2kQq3+qoJeLm2kIBUNlZe3zgb4Zg==",
"version": "8.4.26",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.26.tgz",
"integrity": "sha512-jrXHFF8iTloAenySjM/ob3gSj7pCu0Ji49hnjqzsgSRa50hkWCKD0HQ+gMNJkW38jBI68MpAAg7ZWwHwX8NMMw==",
"dev": true,
"requires": {
"nanoid": "^3.3.4",
"nanoid": "^3.3.6",
"picocolors": "^1.0.0",
"source-map-js": "^1.0.2"
}
@ -8443,6 +8473,13 @@
"is-json": "^2.0.1"
}
},
"prettier": {
"version": "2.8.8",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz",
"integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==",
"dev": true,
"optional": true
},
"purgecss": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/purgecss/-/purgecss-5.0.0.tgz",

View File

@ -8,8 +8,10 @@ rm -rf .parcel-cache
cp -r web/ dist-temp/
npm i
pip install -r tools/ci/requirements.txt
python tools/ci/cdn_to_local.py
python tools/ci/merge_out.py # On previews, attempt to merge patches
python tools/merge_out.py # On previews, attempt to merge patches
npx parcel build dist-temp/index.html dist-temp/**.html --dist-dir "dist" --no-source-maps --no-content-hash
rm -rf dist-temp
@ -18,5 +20,6 @@ cp -r web/_img/ dist/
cp web/atlas.json dist/
cp web/*.txt dist/
cp web/_headers dist/
cp web/_redirects dist/
cp web/favicon.ico dist/
cp web/sw.js dist/

View File

@ -8,6 +8,8 @@ rm -rf .parcel-cache
cp -r web/ dist-temp/
npm i
pip install -r tools/ci/requirements.txt
python tools/ci/cdn_to_local.py
npx parcel build dist-temp/index.html dist-temp/**.html --dist-dir "dist" --no-source-maps --no-content-hash
@ -17,5 +19,6 @@ cp -r web/_img/ dist/
cp web/atlas.json dist/
cp web/*.txt dist/
cp web/_headers dist/
cp web/_redirects dist/
cp web/favicon.ico dist/
cp web/sw.js dist/

View File

@ -1 +1,2 @@
jsonschema
jsonschema
tqdm

View File

@ -2,6 +2,7 @@ import json
import os
import secrets
from pathlib import Path
import re
while not os.path.exists('README.md'):
os.chdir('..')
@ -32,8 +33,11 @@ author = input("Author: ")
if author:
entry['_author'] = author
filename = f'gh-{secrets.token_hex(2)}-{"-".join(entry["name"].split()).lower()}.json'
with open(f'{patches_dir}gh-{secrets.token_hex(2)}-{"-".join(entry["name"].split()).lower()}.json', 'w', encoding='utf-8') as out_file:
slug_name = re.sub('\s+', ' ', entry['name'])
slug_name = re.sub('[^a-zA-Z0-9 ]', '', slug_name)
slug_name = "-".join(slug_name.split(' ')).lower()
filename = f'gh-{secrets.token_hex(2)}-{slug_name}.json'
with open(f'{patches_dir}{filename}', 'w', encoding='utf-8') as out_file:
out_file.write(json.dumps(entry, ensure_ascii=False))
print("Patch created as " + filename + "!")

View File

@ -2,8 +2,11 @@ import json
import os
from aformatter import format_all_entries, per_line_entries
import traceback
import scale_back
from scale_back import ScaleConfig
IS_DEPLOY_PREVIEW = False
if os.getenv('NETLIFY') == 'true' and os.getenv('CONTEXT') == 'deploy-preview':
IS_DEPLOY_PREVIEW = True
out_ids = []
atlas_ids = {}
@ -23,11 +26,14 @@ with open('web/atlas.json', 'r', encoding='utf-8') as atlas_file:
last_id = 0
for i, entry in enumerate(atlas_data):
atlas_ids[entry['id']] = i
id = entry['id']
if id.isnumeric() and int(id) > last_id and int(id) - last_id < 100:
last_id = int(id)
if not IS_DEPLOY_PREVIEW:
for i, entry in enumerate(atlas_data):
atlas_ids[entry['id']] = i
id = entry['id']
if type(id) is str and id.isnumeric():
id = id.isnumeric()
if type(id) is int and id > last_id and id - last_id < 100:
last_id = int(id)
patches_dir = "data/patches/"
permanent_patch_file = "tools/temp-atlas.json"
@ -69,6 +75,8 @@ for filename in filenames:
scale_back.scale_back_entries(entries)
for entry in entries:
if entry is None:
continue
if '_reddit_id' in entry:
reddit_id = entry['_reddit_id']
if reddit_id in out_ids:
@ -90,12 +98,15 @@ for filename in filenames:
del entry['_author']
if isinstance(entry['id'], int) and entry['id'] < 1 or entry['id'] == '0':
last_id += 1
if IS_DEPLOY_PREVIEW:
last_id -= 1
else:
last_id += 1
print(f"{filename}: Entry is new, assigned ID {last_id}")
entry['id'] = str(last_id)
elif isinstance(entry['id'], int):
entry['id'] = str(entry['id'])
elif not is_permanent_file and entry['id'] not in out_ids:
entry['id'] = last_id
elif isinstance(entry['id'], str) and entry['id'].isnumeric():
entry['id'] = int(entry['id'])
elif not is_permanent_file and type(entry['id']) is str and len(entry['id']) > 5 and entry['id'] not in out_ids:
out_ids.append(entry['id'])
if entry['id'] in atlas_ids:
@ -106,8 +117,8 @@ for filename in filenames:
print(f"{filename}: Added {entry['id']}.")
atlas_data.append(entry)
if not is_permanent_file:
os.remove(f)
if not is_permanent_file:
os.remove(f)
except:
print(f"{filename}: Something went wrong; patch couldn't be implemented. Skipping.")

View File

@ -26,14 +26,12 @@ Running:
from praw import Reddit
from praw.models import Submission
import json
import time
import re
import traceback
from aformatter import format_all, validate
from pathlib import Path
import humanize
from datetime import datetime
import secrets
import os
while not os.path.exists('README.md'):
@ -104,7 +102,7 @@ with open('temp-atlas-manual.txt', 'w', encoding='utf-8') as FAIL_FILE:
print(f"{submission.id}: Processing...")
if submission.link_flair_text == "New Entry" or submission.link_flair_text == "Edit Entry" or True:
if submission.link_flair_text == "New Entry" or submission.link_flair_text == "Edit Entry":
try:
@ -122,9 +120,9 @@ with open('temp-atlas-manual.txt', 'w', encoding='utf-8') as FAIL_FILE:
if submission_json:
if submission.link_flair_text == "Edit Entry":
assert submission_json["id"] > 0, "Edit invalid because ID is tampered, it must not be 0 or -1!"
assert submission_json["id"] != -1, "Edit invalid because ID is tampered, it must not be -1!"
else:
assert submission_json["id"] <= 0, "Addition invalid because ID is tampered, it must be 0 or -1!"
assert submission_json["id"] == -1, "Addition invalid because ID is tampered, it must be -1!"
submission_json_dummy = {"id": submission_json["id"], "_reddit_id": submission.id, "_author": submission.author.name}
@ -137,7 +135,7 @@ with open('temp-atlas-manual.txt', 'w', encoding='utf-8') as FAIL_FILE:
assert validation_status < 3, \
"Submission invalid after validation. This may be caused by not enough points on the path."
with open(f'{patches_dir}reddit-{submission.id}-{"-".join(submission["name"].split()).lower()}.json', 'w', encoding='utf-8') as out_file:
with open(f'{patches_dir}reddit-{submission.id}-{"-".join(submission.name.split()).lower()}.json', 'w', encoding='utf-8') as out_file:
out_file.write(json.dumps(submission_json, ensure_ascii=False))
count_success += 1

View File

@ -151,7 +151,7 @@
sodipodi:role="line"
id="tspan3904"
x="721.92651"
y="511.92819">http://place-atlas.stefanocoding.me/</tspan></text>
y="511.92819">http://2022.place-atlas.stefanocoding.me/</tspan></text>
<g
id="g3927"
transform="translate(-80.812204,0)">
@ -178,7 +178,7 @@
y="810.95184"
x="940.96014"
id="tspan3904-9"
sodipodi:role="line">http://place-atlas.stefanocoding.me/</tspan></text>
sodipodi:role="line">http://2022.place-atlas.stefanocoding.me/</tspan></text>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 34 KiB

After

Width:  |  Height:  |  Size: 34 KiB

View File

@ -3,7 +3,7 @@
The 2022 r/place Atlas
Copyright (c) 2017 Roland Rytz <roland@draemm.li>
Copyright (c) 2022 Place Atlas contributors
Licensed under AGPL-3.0 (https://place-atlas.stefanocoding.me/license.txt)
Licensed under AGPL-3.0 (https://2022.place-atlas.stefanocoding.me/license.txt)
-->
<!--

View File

@ -2,7 +2,7 @@
* The 2022 r/place Atlas
* Copyright (c) 2017 Roland Rytz <roland@draemm.li>
* Copyright (c) 2022 Place Atlas contributors
* Licensed under AGPL-3.0 (https://place-atlas.stefanocoding.me/license.txt)
* Licensed under AGPL-3.0 (https://2022.place-atlas.stefanocoding.me/license.txt)
*/
/* purgecss start ignore */
@ -30,6 +30,7 @@ svg.icon {
body[data-mode] {
overflow: hidden;
background-color: #111;
touch-action: none;
}
#wrapper {
@ -82,7 +83,6 @@ body[data-mode]:not([data-mode="draw"]) #drawNavButtons, [data-mode="draw"] #def
width: calc(100% - 400px);
height: 100%;
margin-left: 400px;
touch-action: manipulation;
overflow: hidden;
}
@ -435,6 +435,11 @@ body:not([data-dev]) .show-only-on-dev {
display: none !important;
}
[data-mode="explore"] #entriesListControls,
[data-mode="explore"] #entriesList {
display: none !important
}
/* about.html */
#credits a {

View File

@ -2,7 +2,7 @@
* The 2022 r/place Atlas
* Copyright (c) 2017 Roland Rytz <roland@draemm.li>
* Copyright (c) 2022 Place Atlas contributors
* Licensed under AGPL-3.0 (https://place-atlas.stefanocoding.me/license.txt)
* Licensed under AGPL-3.0 (https://2022.place-atlas.stefanocoding.me/license.txt)
*/
const contributorsEl = document.querySelector('#contributors-wrapper')
@ -17,7 +17,7 @@ fetch('all-authors.txt')
.then(text => text.trim().split('\n').sort((a, b) => {
const aSplit = a.split(':')
const bSplit = b.split(':')
return aSplit[aSplit.length - 1] > bSplit[bSplit.length - 1]
return aSplit[aSplit.length - 1].localeCompare(bSplit[bSplit.length - 1])
}))
.then(contributors => {
document.querySelector('#contributors-count').textContent = contributors.length
@ -28,7 +28,8 @@ fetch('all-authors.txt')
const contributor1 = contributorSplit[1]
userEl.href = 'https://github.com/' + contributor1
userEl.appendChild(gitHubEl.cloneNode())
userEl.appendChild(document.createTextNode(' ' + contributor1))
userEl.appendChild(document.createTextNode('' + contributor1))
// punctuation space ^
} else {
userEl.href = 'https://reddit.com/user/' + contributor
userEl.textContent = contributor

View File

@ -1,8 +1,8 @@
// This script only applies to this instance of the Atlas.
// Please also check code indicated with "@instance-only" outside this file.
// Please also check code indicated with "@instanceonly" outside this file.
// TODO: Avoid having instance-only code inside the main scripts to make updating easier.
const prodDomain = "place-atlas.stefanocoding.me"
const prodDomain = "2022.place-atlas.stefanocoding.me"
window.prodDomain = prodDomain
const instanceId = "2022"
@ -11,7 +11,7 @@ window.instanceId = instanceId
const instanceSubreddit = "placeAtlas2"
window.instanceSubreddit = instanceSubreddit
const instanceRepo = "https://github.com/placeAtlas/atlas"
const instanceRepo = "https://github.com/placeAtlas/atlas-2022"
window.instanceRepo = instanceRepo
const pageTitle = "The 2022 r/place Atlas"
@ -23,9 +23,15 @@ const canvasSize = {
}
window.canvasSize = canvasSize
const canvasOffset = {
x: 0,
y: 0
}
window.canvasOffset = canvasOffset
const canvasCenter = {
x: canvasSize.x/2,
y: canvasSize.y/2
x: canvasSize.x/2 + canvasOffset.x,
y: canvasSize.y/2 + canvasOffset.y
}
window.canvasCenter = canvasCenter
@ -254,18 +260,18 @@ window.defaultVariation = defaultVariation
let defaultPeriod = variationsConfig[defaultVariation].default
window.defaultPeriod = defaultPeriod
const useNumericalId = false
const useNumericalId = true
window.useNumericalId = useNumericalId
console.info(`%cThe 2022 r/place Atlas
%cCopyright (c) 2017 Roland Rytz <roland@draemm.li>
Copyright (c) 2022 Place Atlas contributors
Licensed under AGPL-3.0 (https://place-atlas.stefanocoding.me/license.txt)
Licensed under AGPL-3.0 (https://2022.place-atlas.stefanocoding.me/license.txt)
https://place-atlas.stefanocoding.me/
https://2022.place-atlas.stefanocoding.me/
https://discord.gg/pJkm23b2nA
https://reddit.com/r/placeatlas2
https://github.com/placeAtlas/atlas
https://github.com/placeAtlas/atlas-2022
To get the image of the canvas, use downloadCanvas().
`, 'font-size: 150%; line-height: 150%', '')

View File

@ -42,3 +42,4 @@ function pointIsInPolygon(point, polygon) {
return inside;
}
window.pointIsInPolygon = pointIsInPolygon

View File

@ -2,7 +2,7 @@
* The 2022 r/place Atlas
* Copyright (c) 2017 Roland Rytz <roland@draemm.li>
* Copyright (c) 2022 Place Atlas contributors
* Licensed under AGPL-3.0 (https://place-atlas.stefanocoding.me/license.txt)
* Licensed under AGPL-3.0 (https://2022.place-atlas.stefanocoding.me/license.txt)
*/
window.addEventListener("error", e => {

View File

@ -2,13 +2,14 @@
* The 2022 r/place Atlas
* Copyright (c) 2017 Roland Rytz <roland@draemm.li>
* Copyright (c) 2022 Place Atlas contributors
* Licensed under AGPL-3.0 (https://place-atlas.stefanocoding.me/license.txt)
* Licensed under AGPL-3.0 (https://2022.place-atlas.stefanocoding.me/license.txt)
*/
const finishButton = document.getElementById("finishButton")
const resetButton = document.getElementById("resetButton")
const undoButton = document.getElementById("undoButton")
const redoButton = document.getElementById("redoButton")
const highlightUnchartedEl = document.getElementById("highlightUncharted")
const highlightUnchartedLabel = document.getElementById("highlightUnchartedLabel")
const drawControlsBody = document.getElementById("offcanvasDraw-drawControls")
@ -122,7 +123,7 @@ function initDraw() {
let lShiftPressed = false
let shiftPressed = false
let highlightUncharted = false
let highlightUncharted = highlightUnchartedEl.checked
renderBackground(atlas)
applyView()
@ -143,8 +144,8 @@ function initDraw() {
y -= container.offsetTop
const pos = [
~~((x - (container.clientWidth / 2 - innerContainer.clientWidth / 2 + zoomOrigin[0])) / zoom) + 0.5,
~~((y - (container.clientHeight / 2 - innerContainer.clientHeight / 2 + zoomOrigin[1])) / zoom) + 0.5
~~((x - (container.clientWidth / 2 - innerContainer.clientWidth / 2 + zoomOrigin[0])) / zoom) + 0.5 + canvasOffset.x,
~~((y - (container.clientHeight / 2 - innerContainer.clientHeight / 2 + zoomOrigin[1])) / zoom) + 0.5 + canvasOffset.y
]
if (shiftPressed && path.length > 0) {
@ -266,7 +267,7 @@ function initDraw() {
}
})
document.getElementById("highlightUncharted").addEventListener("click", function () {
highlightUnchartedEl.addEventListener("click", function () {
highlightUncharted = this.checked
render(path)
})
@ -336,7 +337,7 @@ function initDraw() {
let redditPostJsonString = " " + prettyJsonString.split("\n").join("\n ")
let redditPostUrl = `https://www.reddit.com/r/${instanceSubreddit}/submit?selftext=true&title=`
if (exportObject.id === 0) redditPostUrl += `✨%20${encodeURIComponent(exportObject.name ?? entry.name)}`
if (exportObject.id === -1) redditPostUrl += `✨%20${encodeURIComponent(exportObject.name ?? entry.name)}`
else redditPostUrl += `✏%20${encodeURIComponent(exportObject.name ?? entry.name)}`
redditPostUrl += "&text="
@ -358,7 +359,7 @@ function initDraw() {
}
redditPostButton.href = redditPostUrl
if (exportObject.id === 0) document.getElementById("redditFlair").textContent = "New Entry"
if (exportObject.id === -1) document.getElementById("redditFlair").textContent = "New Entry"
else document.getElementById("redditFlair").textContent = "Edit Entry"
// GitHub
@ -496,11 +497,11 @@ function initDraw() {
backgroundContext.beginPath()
if (path[0]) {
backgroundContext.moveTo(path[0][0], path[0][1])
backgroundContext.moveTo(path[0][0] - canvasOffset.x, path[0][1] - canvasOffset.y)
}
for (let p = 1; p < path.length; p++) {
backgroundContext.lineTo(path[p][0], path[p][1])
backgroundContext.lineTo(path[p][0] - canvasOffset.x, path[p][1] - canvasOffset.y)
}
backgroundContext.closePath()
@ -528,11 +529,11 @@ function initDraw() {
highlightContext.beginPath()
if (path[0]) {
highlightContext.moveTo(path[0][0], path[0][1])
highlightContext.moveTo(path[0][0] - canvasOffset.x, path[0][1] - canvasOffset.y)
}
for (let i = 1; i < path.length; i++) {
highlightContext.lineTo(path[i][0], path[i][1])
highlightContext.lineTo(path[i][0] - canvasOffset.x, path[i][1] - canvasOffset.y)
}
highlightContext.closePath()
@ -549,26 +550,13 @@ function initDraw() {
function updateHovering(e, tapped) {
if (dragging || (fixed && !tapped)) return
const 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
]
const coordsEl = document.getElementById("coords_p")
// Displays coordinates as zero instead of NaN
if (isNaN(pos[0])) {
coordsEl.textContent = "0, 0"
} else {
coordsEl.textContent = Math.ceil(pos[0]) + ", " + Math.ceil(pos[1])
}
updateCoordsDisplay(e)
}
const getEntry = id => {
if (!id) return
const entries = atlasAll.filter(entry => entry.id.toString() === id.toString())
if (entries.length === 1) return entries[0]
return
}
function addFieldButton(inputButton, inputGroup, array, index, name) {
@ -727,7 +715,7 @@ function initDraw() {
function addWikiFields(link, index, array) {
const inputGroup = baseInputGroup.cloneNode()
wikiGroup.appendChild(inputGroup)
// wikiGroup.appendChild(inputGroup)
const inputField = baseInputField.cloneNode()
inputField.id = "wikiField" + index
@ -813,10 +801,15 @@ function initDraw() {
initPeriodGroups()
zoom = 4
setView(center[0], center[1])
const hash = window.location.hash.substring(1)
const [,, hashX, hashY, hashZoom] = hash.split('/')
setView(
(isNaN(hashX) || hashX === '') ? center[0] : Number(hashX),
(isNaN(hashY) || hashY === '') ? center[1] : Number(hashY),
(isNaN(hashZoom) || hashZoom === '') ? 4 : Number(hashZoom)
)
document.addEventListener('timeupdate', () => {
renderBackground(atlas)
updatePeriodGroups()
@ -827,7 +820,7 @@ function initDraw() {
initPeriodGroups()
})
drawBackButton.href = "./" + formatHash(entry?.id, currentPeriod, currentPeriod, currentVariation)
drawBackButton.href = "./" + formatHash(entry?.id)
document.addEventListener('timeupdate', event => {
drawBackButton.href = "./" + formatHash(entry?.id, event.detail.period, event.detail.period, event.detail.variation)
@ -921,17 +914,6 @@ function initPeriodGroups() {
if (pathWithPeriods.length === 1) periodDeleteEl.disabled = true
startPeriodEl.addEventListener('input', () => {
if (path.length >= 3) {
periodCenter = calculateCenter(path)
// @instance-only
if ((periodCenter[1] > 1000) && (startPeriodEl.valueAsNumber <= variationsConfig[getCurrentVariation()].expansions[1])) {
// Second expansion
startPeriodEl.value = variationsConfig[getCurrentVariation()].expansions[1];
} else if ((periodCenter[0] > 1000) && (startPeriodEl.valueAsNumber <= variationsConfig[getCurrentVariation()].expansions[0])) {
// First expansion
startPeriodEl.value = variationsConfig[getCurrentVariation()].expansions[0];
}
}
startPeriodUpdate(startPeriodEl.value)
})
startPeriodLeftEl.addEventListener('click', () => {
@ -971,37 +953,15 @@ function initPeriodGroups() {
startPeriodLeftEl.disabled = false
startPeriodRightEl.disabled = true
} else {
if (path.length >= 3) {
periodCenter = calculateCenter(path)
// @instance-only
if ((periodCenter[1] > 1000) && (startPeriodEl.valueAsNumber <= variationsConfig[getCurrentVariation()].expansions[1])) {
// Second expansion
startPeriodLeftEl.disabled = true
startPeriodRightEl.disabled = false
} else if ((periodCenter[0] > 1000) && (startPeriodEl.valueAsNumber <= variationsConfig[getCurrentVariation()].expansions[0])) {
// First expansion
startPeriodLeftEl.disabled = true
startPeriodRightEl.disabled = false
} else {
// Starting area
startPeriodLeftEl.disabled = false
startPeriodRightEl.disabled = false
}
}
// Starting area
startPeriodLeftEl.disabled = false
startPeriodRightEl.disabled = false
}
}
endPeriodEl.addEventListener('input', () => {
if (path.length >= 3) {
periodCenter = calculateCenter(path)
// @instance-only
if ((periodCenter[1] > 1000) && (endPeriodEl.valueAsNumber <= variationsConfig[getCurrentVariation()].expansions[1])) {
// Second expansion
endPeriodEl.value = variationsConfig[getCurrentVariation()].expansions[1];
} else if ((periodCenter[0] > 1000) && (endPeriodEl.valueAsNumber <= variationsConfig[getCurrentVariation()].expansions[0])) {
// First expansion
endPeriodEl.value = variationsConfig[getCurrentVariation()].expansions[0];
}
}
endPeriodUpdate(endPeriodEl.value)
})
@ -1037,23 +997,8 @@ function initPeriodGroups() {
endPeriodLeftEl.disabled = false
endPeriodRightEl.disabled = true
} else {
if (path.length >= 3) {
periodCenter = calculateCenter(path)
// @instance-only
if (periodCenter && (periodCenter[1] > 1000) && (endPeriodEl.valueAsNumber <= variationsConfig[getCurrentVariation()].expansions[1])) {
// Second expansion
endPeriodLeftEl.disabled = true
endPeriodRightEl.disabled = false
} else if (periodCenter && (periodCenter[0] > 1000) && (endPeriodEl.valueAsNumber <= variationsConfig[getCurrentVariation()].expansions[0])) {
// First expansion
endPeriodLeftEl.disabled = true
endPeriodRightEl.disabled = false
} else {
// Starting area
endPeriodLeftEl.disabled = false
endPeriodRightEl.disabled = false
}
}
endPeriodLeftEl.disabled = false
endPeriodRightEl.disabled = false
}
}
@ -1216,7 +1161,6 @@ function updatePeriodGroups() {
else periodDeleteEl.disabled = false
// Set start incremental button disabled states
// @instance-only
if (startPeriodEl.value === startPeriodEl.min) {
startPeriodLeftEl.disabled = true
startPeriodRightEl.disabled = false
@ -1224,23 +1168,11 @@ function updatePeriodGroups() {
startPeriodLeftEl.disabled = false
startPeriodRightEl.disabled = true
} else {
if (periodCenter && (periodCenter[1] > 1000) && (startPeriodEl.valueAsNumber <= variationsConfig[periodVariationEl.value].expansions[1])) {
// Second expansion
startPeriodLeftEl.disabled = true
startPeriodRightEl.disabled = false
} else if (periodCenter && (periodCenter[0] > 1000) && (startPeriodEl.valueAsNumber <= variationsConfig[periodVariationEl.value].expansions[0])) {
// First expansion
startPeriodLeftEl.disabled = true
startPeriodRightEl.disabled = false
} else {
// Starting area
startPeriodLeftEl.disabled = false
startPeriodRightEl.disabled = false
}
startPeriodLeftEl.disabled = false
startPeriodRightEl.disabled = false
}
// Set end incremental button disabled states
// @instance-only
if (endPeriodEl.value === endPeriodEl.min) {
endPeriodLeftEl.disabled = true
endPeriodRightEl.disabled = false
@ -1248,19 +1180,8 @@ function updatePeriodGroups() {
endPeriodLeftEl.disabled = false
endPeriodRightEl.disabled = true
} else {
if (periodCenter && (periodCenter[1] > 1000) && (endPeriodEl.valueAsNumber <= variationsConfig[periodVariationEl.value].expansions[1])) {
// Second expansion
endPeriodLeftEl.disabled = true
endPeriodRightEl.disabled = false
} else if (periodCenter && (periodCenter[0] > 1000) && (endPeriodEl.valueAsNumber <= variationsConfig[periodVariationEl.value].expansions[0])) {
// First expansion
endPeriodLeftEl.disabled = true
endPeriodRightEl.disabled = false
} else {
// Starting area
endPeriodLeftEl.disabled = false
endPeriodRightEl.disabled = false
}
endPeriodLeftEl.disabled = false
endPeriodRightEl.disabled = false
}
}
})
@ -1316,7 +1237,7 @@ function updateErrors() {
periodsStatus.textContent = "No paths available on this period!"
}
const { conflicts, insufficientPaths } = getErrors()
const { conflicts, insufficientPaths, outOfBounds, periodOutOfBounds } = getErrors()
let errorCount = 0
// console.log(conflicts, invalidPaths, allErrors)
@ -1324,10 +1245,16 @@ function updateErrors() {
const { periodStatusEl, startPeriodViewEl, endPeriodViewEl, periodGroupEl } = el
periodStatusEl.textContent = ""
periodStatusEl.classList.add("d-none")
if (conflicts[index] !== undefined) {
if (conflicts?.[index]) {
periodStatusEl.textContent += `Period conflicts with path${conflicts[index].length === 1 ? "" : "s"} ${conflicts[index].join(", ")}.\n`
}
if (insufficientPaths[index] !== undefined) {
if (outOfBounds?.[index]) {
periodStatusEl.textContent += `A point is placed out of bounds.\n`
}
if (periodOutOfBounds?.[index]) {
periodStatusEl.textContent += `The period is out of bounds for editing.\n`
}
if (insufficientPaths?.[index] !== undefined) {
periodStatusEl.textContent += `Insufficient paths. Got ${insufficientPaths[index]}, need at least 3.\n`
startPeriodViewEl.disabled = true
endPeriodViewEl.disabled = true
@ -1394,8 +1321,54 @@ function getConflicts() {
}
function getOutOfBounds() {
const outOfBounds = {}
pathCheck: for (const i in pathWithPeriods) {
const [period, path] = pathWithPeriods[i]
const [start, end, variation] = parsePeriod(period)
const checkedRefPeriods = []
for (let j = start; j <= end; j++) {
for (const [refPeriod, refRegion] of variationsConfig[variation]?.drawableRegions) {
if (!isOnPeriod(refPeriod[0], refPeriod[1], variation, j, variation) || checkedRefPeriods.includes(refPeriod)) continue
checkedRefPeriods.push(refPeriod)
const [ refX1, refY1, refX2, refY2 ] = refRegion
for (const point of path) {
const isOutOfBounds = !pointIsInPolygon(point, [[refX1 - 2, refY1 - 2], [refX2 + 2, refY1 - 2], [refX2 + 2, refY2 + 2], [refX1 - 2, refY2 + 2]])
if (!isOutOfBounds) continue
outOfBounds[i] = true
continue pathCheck
}
}
}
}
return outOfBounds
}
function getPeriodOutOfBounds() {
const outOfBounds = {}
pathCheck: for (const i in pathWithPeriods) {
const [period] = pathWithPeriods[i]
// console.log(i)
const [start, end, variation] = parsePeriod(period)
for (let j = start; j <= end; j++) {
const [refStart, refEnd] = variationsConfig[variation]?.drawablePeriods
if (isOnPeriod(refStart, refEnd, variation, j, variation)) continue
outOfBounds[i] = true
continue pathCheck
}
}
return outOfBounds
}
function getErrors() {
const conflicts = getConflicts()
const insufficientPaths = {}
pathWithPeriods.forEach(([period, path], i) => {
@ -1406,8 +1379,10 @@ function getErrors() {
// console.info('invalid paths', invalidPaths)
return {
conflicts,
conflicts: getConflicts(),
insufficientPaths,
outOfBounds: getOutOfBounds(),
periodOutOfBounds: getPeriodOutOfBounds()
}
}

View File

@ -2,7 +2,7 @@
* The 2022 r/place Atlas
* Copyright (c) 2017 Roland Rytz <roland@draemm.li>
* Copyright (c) 2022 Place Atlas contributors
* Licensed under AGPL-3.0 (https://place-atlas.stefanocoding.me/license.txt)
* Licensed under AGPL-3.0 (https://2022.place-atlas.stefanocoding.me/license.txt)
*/
const baseLinkElement = document.createElement("a")
@ -42,10 +42,10 @@ function createInfoBlock(entry, isPreview) {
linkElement.className = "text-decoration-none d-flex justify-content-between text-body"
if (isPreview) linkElement.href = "#"
else {
linkElement.href = formatHash(entry.id)
linkElement.href = formatHash(entry.id, null, null, null, false, false, false)
linkElement.addEventListener('click', e => {
e.preventDefault()
location.hash = formatHash(entry.id)
location.hash = formatHash(entry.id, null, null, null, false, false, false)
window.dispatchEvent(new HashChangeEvent("hashchange"))
})
}
@ -155,7 +155,7 @@ function createInfoBlock(entry, isPreview) {
if (!link) return
const wikiLinkElement = baseLinkElement.cloneNode()
wikiLinkElement.href = "https://place-wiki.stefanocoding.me/wiki/" + link.replace(/ /g, '_')
wikiLinkElement.innerHTML = `<i class="bi bi-book" aria-hidden="true"></i>r/place Wiki Article`
wikiLinkElement.innerHTML = `<i class="bi bi-book" aria-hidden="true"></i> r/place Wiki Article`
wikiGroupElement.appendChild(wikiLinkElement)
})
}
@ -174,7 +174,7 @@ function createInfoBlock(entry, isPreview) {
const editElement = document.createElement("a")
editElement.textContent = "Edit"
editElement.className = "btn btn-sm btn-outline-primary"
editElement.href = "./?mode=draw&id=" + entry.id + formatHash(undefined)
editElement.href = "./?mode=draw&id=" + entry.id + formatHash(false)
editElement.title = "Edit " + entry.name
idElementContainer.appendChild(editElement)
}

View File

@ -2,7 +2,7 @@
* The 2022 r/place Atlas
* Copyright (c) 2017 Roland Rytz <roland@draemm.li>
* Copyright (c) 2022 Place Atlas contributors
* Licensed under AGPL-3.0 (https://place-atlas.stefanocoding.me/license.txt)
* Licensed under AGPL-3.0 (https://2022.place-atlas.stefanocoding.me/license.txt)
*/
const innerContainer = document.getElementById("innerContainer")
@ -23,7 +23,7 @@ if (window.devicePixelRatio) {
}
const maxZoom = 128
const minZoom = 0.1
const minZoom = 0.125
let zoomOrigin = [0, 0]
let scaleZoomOrigin = [0, 0]
@ -39,30 +39,39 @@ function applyView() {
//console.log(zoomOrigin, scaleZoomOrigin)
//console.log(scaleZoomOrigin[0])
scaleZoomOrigin[0] = Math.max(-canvasCenter.x, Math.min(canvasCenter.x, scaleZoomOrigin[0]))
scaleZoomOrigin[1] = Math.max(-canvasCenter.y, Math.min(canvasCenter.y, scaleZoomOrigin[1]))
scaleZoomOrigin[0] = Math.max(-canvasCenter.x + canvasOffset.x, Math.min(canvasCenter.x - canvasOffset.x, scaleZoomOrigin[0]))
scaleZoomOrigin[1] = Math.max(-canvasCenter.y + canvasOffset.y, Math.min(canvasCenter.y - canvasOffset.y, scaleZoomOrigin[1]))
zoom = Math.max(minZoom, Math.min(maxZoom, zoom))
zoomOrigin = [scaleZoomOrigin[0] * zoom, scaleZoomOrigin[1] * zoom]
innerContainer.style.height = (~~(zoom * canvasSize.x)) + "px"
innerContainer.style.width = (~~(zoom * canvasSize.y)) + "px"
innerContainer.style.width = (~~(zoom * canvasSize.x)) + "px"
innerContainer.style.height = (~~(zoom * canvasSize.y)) + "px"
innerContainer.style.left = ~~(container.clientWidth / 2 - innerContainer.clientWidth / 2 + zoomOrigin[0] + container.offsetLeft) + "px"
innerContainer.style.top = ~~(container.clientHeight / 2 - innerContainer.clientHeight / 2 + zoomOrigin[1] + container.offsetTop) + "px"
}
function setView(x, y, zoomN = zoom) {
zoom = zoomN
scaleZoomOrigin = [
canvasCenter.x - x,
canvasCenter.y - y
]
function setView(targetX, targetY, targetZoom) {
if (isNaN(targetX)) targetX = null
if (isNaN(targetY)) targetY = null
zoom = targetZoom ?? zoom
if ((targetX ?? null) !== null) scaleZoomOrigin[0] = canvasCenter.x - targetX
if ((targetY ?? null) !== null) scaleZoomOrigin[1] = canvasCenter.y - targetY
applyView()
}
function updateHash(...args) {
const newLocation = new URL(window.location)
newLocation.hash = formatHash(...args)
if (location.hash !== newLocation.hash) history.replaceState({}, "", newLocation)
}
let atlas = null
window.atlas = atlas
let atlasAll = null
@ -77,15 +86,6 @@ async function init() {
const args = window.location.search
const params = new URLSearchParams(args)
// For Reviewing Reddit Changes
// const atlasRef = '../tools/temp-atlas.json'
const atlasRef = params.get('atlas') || './atlas.json'
const atlasResp = await fetch(atlasRef)
atlas = await atlasResp.json()
atlas.sort((a, b) => a.center[1] - b.center[1])
atlasAll = updateAtlasAll(atlas)
let mode = "view"
if (args) {
@ -102,11 +102,19 @@ async function init() {
}
}
const hash = window.location.hash.substring(1)
const [, period] = hash.split('/')
if (mode === "about") window.location.replace("./about.html")
if (period) {
const [, targetPeriod, targetVariation] = parsePeriod(period)
// For Reviewing Reddit Changes
// const atlasRef = '../tools/temp-atlas.json'
const atlasRef = params.get('atlas') || './atlas.json'
const atlasResp = await fetch(atlasRef)
atlasAll = updateAtlasAll(await atlasResp.json())
const hash = window.location.hash.substring(1)
const [, hashPeriod, hashX, hashY, hashZoom] = hash.split('/')
if (hashPeriod) {
const [, targetPeriod, targetVariation] = parsePeriod(hashPeriod)
await updateTime(targetPeriod, targetVariation, true)
} else {
await updateTime(currentPeriod, currentVariation, true)
@ -114,15 +122,18 @@ async function init() {
//console.log(document.documentElement.clientWidth, document.documentElement.clientHeight)
zoomOrigin = [0, 0]
applyView()
setView(
(isNaN(hashX) || hashX === '') ? canvasCenter.x : Number(hashX),
(isNaN(hashY) || hashY === '') ? canvasCenter.y : Number(hashY),
(isNaN(hashZoom) || hashZoom === '') ? zoom : Number(hashZoom)
)
let initialPinchDistance = 0
let initialPinchZoom = 0
let initialPinchZoomOrigin = [0, 0]
let desiredZoom
let zoomAnimationFrame
// let desiredZoom
// let zoomAnimationFrame
document.body.dataset.mode = mode
@ -131,12 +142,8 @@ async function init() {
if (mode === "draw") {
initDraw()
} else if (mode === "about") {
window.location = "./about.html"
} else if (mode === "overlap") {
if (initOverlap) {
initOverlap()
}
if (initOverlap) initOverlap()
} else if (mode === "explore") {
initExplore()
} else if (mode.startsWith("diff")) {
@ -146,13 +153,15 @@ async function init() {
let liveAtlas = await liveAtlasResp.json()
liveAtlas = updateAtlasAll(liveAtlas)
const liveAtlasReduced = liveAtlas.reduce(function (a, c) {
a[c.id] = c
return a
const liveAtlasReduced = liveAtlas.reduce((atlas, entry) => {
delete entry._index
atlas[entry.id] = entry
return atlas
}, {})
// Mark added/edited entries
atlasAll = atlasAll.map(function (entry) {
if (liveAtlasReduced[entry.id] === undefined) {
delete entry._index
if (!liveAtlasReduced[entry.id]) {
entry.diff = "add"
} else if (JSON.stringify(entry) !== JSON.stringify(liveAtlasReduced[entry.id])) {
entry.diff = "edit"
@ -161,24 +170,24 @@ async function init() {
})
// Mark removed entries
const atlasReduced = atlasAll.reduce(function (a, c) {
a[c.id] = c
return a
const atlasReduced = atlasAll.reduce((atlas, entry) => {
delete entry._index
atlas[entry.id] = entry
return atlas
}, {})
const removedEntries = liveAtlas.filter(entry =>
atlasReduced[entry.id] === undefined
).map(entry => {
const removedEntries = liveAtlas.filter(entry => !atlasReduced[entry.id]).map(entry => {
delete entry._index
entry.diff = "delete"
return entry
})
atlasAll.push(...removedEntries)
if (mode.includes("only")) {
atlasAll = atlasAll.filter(function (entry) {
return typeof entry.diff === "string"
})
atlasAll = atlasAll.filter(entry => entry.diff)
}
atlas = generateAtlasForPeriod()
} catch (error) {
console.warn("Diff mode failed to load, reverting to normal view.", error)
} finally {
@ -309,6 +318,7 @@ async function init() {
zoom = Math.max(minZoom, Math.min(maxZoom, zoom))
applyZoom(x, y, zoom)
updateHash()
}, { passive: true })
/*function setDesiredZoom(x, y, target){
@ -365,8 +375,8 @@ async function init() {
]
mousedown(
(e.touches[0].clientX + e.touches[1].clientX) / 2,
(e.touches[0].clientY + e.touches[1].clientY) / 2
(e.touches[0].clientX + e.touches[1].clientX) / 2 - container.offsetLeft,
(e.touches[0].clientY + e.touches[1].clientY) / 2 - container.offsetTop
)
}
@ -374,12 +384,13 @@ async function init() {
}
window.addEventListener("mousemove", e => {
updateLines()
// updateLines()
mousemove(e.clientX, e.clientY)
if (dragging) {
e.preventDefault()
}
})
window.addEventListener("touchmove", e => {
if (e.touches.length === 2 || e.scale > 1) {
@ -412,8 +423,6 @@ async function init() {
function touchmove(e) {
updateLines()
if (e.touches.length === 1) {
mousemove(e.touches[0].clientX, e.touches[0].clientY)
@ -470,17 +479,15 @@ async function init() {
window.addEventListener("touchend", touchend)
function mouseup(x, y) {
if (dragging) {
dragging = false
}
dragging = false
updateHash()
}
function touchend(e) {
if (e.touches.length === 0) {
mouseup()
setTimeout(() => updateLines(), 0)
dragging = false
} else if (e.touches.length === 1) {
initialPinchZoom = zoom
@ -523,4 +530,20 @@ function updateAtlasAll(atlas = atlasAll) {
entry.center = currentCenter
}
return atlas
}
}
// Announcement system
const announcementEl = document.querySelector("#headerAnnouncement")
const announcementButton = announcementEl.querySelector('[role=button]')
const announcementText = announcementEl.querySelector('p').textContent.trim()
if (announcementText && announcementText !== window.localStorage.getItem('announcement-closed')) {
announcementButton.click()
document.querySelector('#objectsList').style.marginTop = '2.8rem'
}
announcementEl.querySelector('[role=button]').addEventListener('click', () => {
window.localStorage.setItem('announcement-closed', announcementText)
document.querySelector('#objectsList').style.marginTop = '0'
})

View File

@ -2,7 +2,7 @@
* The 2022 r/place Atlas
* Copyright (c) 2017 Roland Rytz <roland@draemm.li>
* Copyright (c) 2022 Place Atlas contributors
* Licensed under AGPL-3.0 (https://place-atlas.stefanocoding.me/license.txt)
* Licensed under AGPL-3.0 (https://2022.place-atlas.stefanocoding.me/license.txt)
*/
function initOverlap() {
@ -11,13 +11,13 @@ function initOverlap() {
// const hovered = []
buildObjectsList(null, null)
resetEntriesList()
renderBackground(atlas)
render()
document.addEventListener('timeupdate', () => {
atlasDisplay = atlas.slice()
resetEntriesList(null, null)
resetEntriesList()
renderBackground(atlasDisplay)
render()
})
@ -27,7 +27,7 @@ function initOverlap() {
updateLines()
if (window.location.hash) {
highlightEntryFromUrl()
updateViewFromHash()
}
function renderBackground(atlas) {
@ -44,11 +44,11 @@ function initOverlap() {
backgroundContext.beginPath()
if (path[0]) {
backgroundContext.moveTo(path[0][0], path[0][1])
backgroundContext.moveTo(path[0][0] - canvasOffset.x, path[0][1] - canvasOffset.y)
}
for (let p = 1; p < path.length; p++) {
backgroundContext.lineTo(path[p][0], path[p][1])
backgroundContext.lineTo(path[p][0] - canvasOffset.x, path[p][1] - canvasOffset.y)
}
backgroundContext.closePath()

View File

@ -2,7 +2,7 @@
* The 2022 r/place Atlas
* Copyright (c) 2017 Roland Rytz <roland@draemm.li>
* Copyright (c) 2022 Place Atlas contributors
* Licensed under AGPL-3.0 (https://place-atlas.stefanocoding.me/license.txt)
* Licensed under AGPL-3.0 (https://2022.place-atlas.stefanocoding.me/license.txt)
*/
let areasSum = 0
@ -203,7 +203,7 @@ 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")
outstring += ((i + 1) + "|[" + atlas[atlas.length - i - 1].name + "](http://2022.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)

View File

@ -2,7 +2,7 @@
* The 2022 r/place Atlas
* Copyright (c) 2017 Roland Rytz <roland@draemm.li>
* Copyright (c) 2022 Place Atlas contributors
* Licensed under AGPL-3.0 (https://place-atlas.stefanocoding.me/license.txt)
* Licensed under AGPL-3.0 (https://2022.place-atlas.stefanocoding.me/license.txt)
*/
const codeReference = {}
@ -79,7 +79,8 @@ const dispatchTimeUpdateEvent = (period = currentPeriod, variation = currentVari
async function updateBackground(newPeriod = currentPeriod, newVariation = currentVariation) {
abortController.abort()
abortController = new AbortController()
myAbortController = new AbortController()
abortController = myAbortController
currentUpdateIndex++
const myUpdateIndex = currentUpdateIndex
const variationConfig = variationsConfig[newVariation]
@ -109,6 +110,7 @@ async function updateBackground(newPeriod = currentPeriod, newVariation = curren
layers.length = layerUrls.length
await Promise.all(layerUrls.map(async (url, i) => {
const imageBlob = await (await fetch(url, { signal: myAbortController.signal })).blob()
const imageLayer = new Image()
await new Promise(resolve => {
imageLayer.onload = () => {
@ -117,10 +119,14 @@ async function updateBackground(newPeriod = currentPeriod, newVariation = curren
layers[i] = imageLayer
resolve()
}
imageLayer.src = url
imageLayer.src = URL.createObjectURL(imageBlob)
})
}))
if (myAbortController.signal.aborted || newPeriod !== currentPeriod || newVariation !== currentVariation) {
return
}
for (const imageLayer of layers) {
context.drawImage(imageLayer, 0, 0)
}
@ -137,7 +143,7 @@ async function updateTime(newPeriod = currentPeriod, newVariation = currentVaria
}
document.body.dataset.canvasLoading = ""
const oldPeriod = currentPeriod
// const oldPeriod = currentPeriod
const oldVariation = currentVariation
if (!variationsConfig[newVariation]) newVariation = defaultVariation
@ -163,7 +169,21 @@ async function updateTime(newPeriod = currentPeriod, newVariation = currentVaria
await updateBackground(newPeriod, newVariation)
atlas = []
atlas = generateAtlasForPeriod(newPeriod, newVariation)
dispatchTimeUpdateEvent(newPeriod, newVariation, atlas)
delete document.body.dataset.canvasLoading
tooltip.dataset.forceVisible = ""
clearTimeout(tooltipDelayHide)
tooltipDelayHide = setTimeout(() => {
delete tooltip.dataset.forceVisible
}, 1000)
}
function generateAtlasForPeriod(newPeriod = currentPeriod, newVariation = currentVariation) {
const atlas = []
for (const entry of atlasAll) {
let chosenIndex
@ -194,13 +214,7 @@ async function updateTime(newPeriod = currentPeriod, newVariation = currentVaria
})
}
dispatchTimeUpdateEvent(newPeriod, newVariation, atlas)
delete document.body.dataset.canvasLoading
tooltip.dataset.forceVisible = ""
clearTimeout(tooltipDelayHide)
tooltipDelayHide = setTimeout(() => {
delete tooltip.dataset.forceVisible
}, 1000)
return atlas
}
@ -233,6 +247,7 @@ function isOnPeriod(start, end, variation, currentPeriod, currentVariation) {
if (start > end) [start, end] = [end, start]
return currentPeriod >= start && currentPeriod <= end && variation === currentVariation
}
window.isOnPeriod = isOnPeriod
function parsePeriod(periodString) {
let variation = defaultVariation
@ -256,36 +271,52 @@ function parsePeriod(periodString) {
}
}
function formatPeriod(start, end, variation) {
start ??= currentPeriod
end ??= currentPeriod
variation ??= currentVariation
function formatPeriod(targetStart, targetEnd, targetVariation, forUrl = false) {
targetStart ??= currentPeriod
targetEnd ??= currentPeriod
targetVariation ??= currentVariation
let periodString, variationString
variationString = variationsConfig[variation].code
if (start > end) [start, end] = [end, start]
if (start === end) {
if (start === variationsConfig[variation].default && variation !== defaultVariation) {
variationString = variationsConfig[targetVariation].code
if (targetStart > targetEnd) [targetStart, targetEnd] = [targetEnd, targetStart]
if (targetStart === targetEnd) {
if (forUrl && targetVariation === defaultVariation && targetStart === variationsConfig[defaultVariation].default) {
periodString = ""
}
else periodString = start
else periodString = targetStart
}
else periodString = start + "-" + end
if (periodString && variationString) return variationsConfig[variation].code + ":" + periodString
else periodString = targetStart + "-" + targetEnd
if (periodString && variationString) return variationsConfig[targetVariation].code + ":" + periodString
if (variationString) return variationString
return periodString
}
function formatHash(id, start, end, variation) {
start ??= currentPeriod
end ??= currentPeriod
variation ??= currentVariation
function setReferenceVal(reference, newValue) {
if (reference === false || reference === "") return null
else return reference ?? newValue
}
function formatHash(targetEntry, targetPeriodStart, targetPeriodEnd, targetVariation, targetX, targetY, targetZoom) {
let hashData = window.location.hash.substring(1).split('/')
targetEntry = setReferenceVal(targetEntry, hashData[0])
targetPeriodStart = setReferenceVal(targetPeriodStart, currentPeriod)
targetPeriodEnd = setReferenceVal(targetPeriodEnd, currentPeriod)
targetVariation = setReferenceVal(targetVariation, currentVariation)
targetX = setReferenceVal(targetX, canvasCenter.x - scaleZoomOrigin[0])
targetY = setReferenceVal(targetY, canvasCenter.y - scaleZoomOrigin[1])
targetZoom = setReferenceVal(targetZoom, zoom)
const result = [id]
const targetPeriod = formatPeriod(start, end, variation)
if (targetPeriod && targetPeriod !== defaultPeriod) result.push(targetPeriod)
if (targetX) targetX = Math.round(targetX)
if (targetY) targetY = Math.round(targetY)
if (targetZoom) targetZoom = targetZoom.toFixed(3).replace(/\.?0+$/, '')
const result = [targetEntry]
const targetPeriod = formatPeriod(targetPeriodStart, targetPeriodEnd, targetVariation, true)
result.push(targetPeriod, targetX, targetY, targetZoom)
if (!result.some(el => el || el === 0)) return ''
return '#' + result.join('/')
return '#' + result.join('/').replace(/\/+$/, '')
}
function downloadCanvas() {

View File

@ -2,7 +2,7 @@
* The 2022 r/place Atlas
* Copyright (c) 2017 Roland Rytz <roland@draemm.li>
* Copyright (c) 2022 Place Atlas contributors
* Licensed under AGPL-3.0 (https://place-atlas.stefanocoding.me/license.txt)
* Licensed under AGPL-3.0 (https://2022.place-atlas.stefanocoding.me/license.txt)
*/
const linesCanvas = document.getElementById("linesCanvas")
@ -31,10 +31,10 @@ const objectsContainer = document.getElementById("objectsList")
const closeObjectsListButton = document.getElementById("closeObjectsListButton")
const objectsListOverflowNotice = document.getElementById("objectsListOverflowNotice")
const filterInput = document.getElementById("searchList")
const searchInput = document.getElementById("searchList")
const sortInput = document.getElementById("sort")
const entriesList = document.getElementById("entriesList")
let entriesListShown = false
const drawButton = document.getElementById("drawLink")
@ -47,56 +47,36 @@ let atlasDisplay
const entriesLimit = 50
let entriesOffset = 0
const moreEntriesButton = document.createElement("button")
moreEntriesButton.innerHTML = "Show " + entriesLimit + " more"
moreEntriesButton.type = "button"
moreEntriesButton.className = "btn btn-primary d-block mb-2 mx-auto"
moreEntriesButton.id = "moreEntriesButton"
moreEntriesButton.addEventListener('click', () => {
buildObjectsList(null, null)
renderBackground(atlas)
render()
})
let showMoreEntries = () => {}
const moreEntriesObserver = new IntersectionObserver((entries, observer) => {
const moreEntriesObserver = new IntersectionObserver(entries => {
for (const entry of entries) {
if (!entry.isIntersecting) continue
moreEntriesButton.click()
showMoreEntries()
break
}
})
moreEntriesObserver.observe(moreEntriesButton)
let defaultSort = "shuffle"
document.getElementById("sort").value = defaultSort
let defaultSort = sortInput.value
let lastPos = [0, 0]
let fixed = false; // Fix hovered items in place, so that clicking on links is possible
filterInput.addEventListener("input", function () {
entriesOffset = 0
entriesList.replaceChildren()
entriesList.appendChild(moreEntriesButton)
if (this.value === "") {
document.getElementById("relevantOption").disabled = true
atlasDisplay = atlas.slice(0)
buildObjectsList(null, null)
} else {
document.getElementById("relevantOption").disabled = false
buildObjectsList(this.value.toLowerCase(), "relevant")
}
searchInput.addEventListener("input", function () {
resetEntriesList()
})
document.getElementById("sort").addEventListener("input", function () {
if (this.value !== "relevant") {
defaultSort = this.value
}
resetEntriesList(filterInput.value.toLowerCase(), this.value)
sortInput.addEventListener("input", function () {
resetEntriesList()
})
offcanvasDraw.addEventListener('show.bs.offcanvas', () => {
@ -167,6 +147,7 @@ function clearObjectsList() {
fixed = false
render()
objectEditNav.remove()
updateHash(false)
document.title = pageTitle
}
@ -229,8 +210,8 @@ function updateLines() {
)
}
linesContext.lineTo(
~~(hovered[i].center[0] * zoom) + innerContainer.offsetLeft,
~~(hovered[i].center[1] * zoom) + innerContainer.offsetTop
~~((hovered[i].center[0] - canvasOffset.x) * zoom) + innerContainer.offsetLeft,
~~((hovered[i].center[1] - canvasOffset.y) * zoom) + innerContainer.offsetTop
)
linesContext.stroke()
}
@ -259,8 +240,8 @@ function updateLines() {
)
}
linesContext.lineTo(
~~(hovered[i].center[0] * zoom) + innerContainer.offsetLeft,
~~(hovered[i].center[1] * zoom) + innerContainer.offsetTop
~~((hovered[i].center[0] - canvasOffset.x) * zoom) + innerContainer.offsetLeft,
~~((hovered[i].center[1] - canvasOffset.y) * zoom) + innerContainer.offsetTop
)
linesContext.stroke()
}
@ -287,12 +268,12 @@ function renderBackground(atlas) {
if (path[0]) {
//backgroundContext.moveTo(path[0][0]*zoom, path[0][1]*zoom)
backgroundContext.moveTo(path[0][0], path[0][1])
backgroundContext.moveTo(path[0][0] - canvasOffset.x, path[0][1] - canvasOffset.y)
}
for (let p = 1; p < path.length; p++) {
//backgroundContext.lineTo(path[p][0]*zoom, path[p][1]*zoom)
backgroundContext.lineTo(path[p][0], path[p][1])
backgroundContext.lineTo(path[p][0] - canvasOffset.x, path[p][1] - canvasOffset.y)
}
backgroundContext.closePath()
@ -321,13 +302,9 @@ function renderBackground(atlas) {
}
}
function buildObjectsList(filter, sort = defaultSort) {
function buildObjectsList(filter, sort) {
if (entriesList.contains(moreEntriesButton)) {
entriesList.removeChild(moreEntriesButton)
}
atlasDisplay ||= atlas.slice()
atlasDisplay = atlas.slice()
if (filter) {
atlasDisplay = atlas.filter(entry => {
@ -335,7 +312,7 @@ function buildObjectsList(filter, sort = defaultSort) {
entry.name.toLowerCase().includes(filter.toLowerCase())
|| entry.description?.toLowerCase().includes(filter.toLowerCase())
|| Object.values(entry.links).flat().some(str => str.toLowerCase().includes(filter))
|| entry.id === filter
|| entry.id.toString() === filter
)
})
document.getElementById("atlasSize").innerHTML = "Found " + atlasDisplay.length + " entries."
@ -343,11 +320,10 @@ function buildObjectsList(filter, sort = defaultSort) {
document.getElementById("atlasSize").innerHTML = "The Atlas contains " + atlasDisplay.length + " entries."
}
sort ||= defaultSort
renderBackground(atlasDisplay)
render()
sort ||= defaultSort
document.getElementById("sort").value = sort
//console.log(sort)
@ -397,60 +373,72 @@ function buildObjectsList(filter, sort = defaultSort) {
atlasDisplay.sort(sortFunction)
}
for (let i = entriesOffset; i < entriesOffset + entriesLimit; i++) {
moreEntriesButton.removeEventListener('click', showMoreEntries)
showMoreEntries = () => {
if (i >= atlasDisplay.length) break
if (entriesList.contains(moreEntriesButton)) {
entriesList.removeChild(moreEntriesButton)
}
const element = createInfoBlock(atlasDisplay[i])
const entry = atlasDisplay[i]
element.addEventListener("mouseenter", function () {
if (fixed || dragging) return
objectsContainer.replaceChildren()
previousScaleZoomOrigin ??= [...scaleZoomOrigin]
previousZoom ??= zoom
setView(entry.center[0], entry.center[1], setZoomByPath(entry.path))
hovered = [entry]
render()
hovered[0].element = this
updateLines()
})
element.addEventListener("click", e => {
toggleFixed(e)
if (!fixed) return
previousScaleZoomOrigin ??= [...scaleZoomOrigin]
previousZoom ??= zoom
applyView()
})
element.addEventListener("mouseleave", () => {
if (fixed || dragging) return
scaleZoomOrigin = [...previousScaleZoomOrigin]
zoom = previousZoom
previousScaleZoomOrigin = undefined
previousZoom = undefined
applyView()
hovered = []
updateLines()
render()
})
entriesList.appendChild(element)
for (let i = entriesOffset; i < entriesOffset + entriesLimit; i++) {
if (i >= atlasDisplay.length) break
const element = createInfoBlock(atlasDisplay[i])
const entry = atlasDisplay[i]
element.addEventListener("mouseenter", function () {
if (fixed || dragging) return
objectsContainer.replaceChildren()
previousScaleZoomOrigin ??= [...scaleZoomOrigin]
previousZoom ??= zoom
setView(entry.center[0], entry.center[1], setZoomByPath(entry.path))
hovered = [entry]
render()
hovered[0].element = this
updateLines()
})
element.addEventListener("click", e => {
toggleFixed(e)
if (!fixed) return
previousScaleZoomOrigin ??= [...scaleZoomOrigin]
previousZoom ??= zoom
applyView()
})
element.addEventListener("mouseleave", () => {
if (fixed || dragging) return
scaleZoomOrigin = [...previousScaleZoomOrigin]
zoom = previousZoom
previousScaleZoomOrigin = undefined
previousZoom = undefined
applyView()
hovered = []
updateLines()
render()
})
entriesList.appendChild(element)
}
entriesOffset += entriesLimit
if (atlasDisplay.length > entriesOffset) {
moreEntriesButton.innerHTML = "Show " + Math.min(entriesLimit, atlasDisplay.length - entriesOffset) + " more"
entriesList.appendChild(moreEntriesButton)
}
}
moreEntriesButton.addEventListener('click', showMoreEntries)
showMoreEntries()
entriesOffset += entriesLimit
if (atlasDisplay.length > entriesOffset) {
moreEntriesButton.innerHTML = "Show " + Math.min(entriesLimit, atlasDisplay.length - entriesOffset) + " more"
entriesList.appendChild(moreEntriesButton)
}
}
function shuffle() {
@ -468,8 +456,10 @@ function resetEntriesList() {
entriesList.replaceChildren()
entriesList.appendChild(moreEntriesButton)
buildObjectsList(filter = null, sort = null)
const sort = sortInput.value || defaultSort
const search = searchInput?.value.toLowerCase()
buildObjectsList(search, sort)
}
async function render() {
@ -498,12 +488,12 @@ async function render() {
if (path[0]) {
//context.moveTo(path[0][0]*zoom, path[0][1]*zoom)
highlightContext.moveTo(path[0][0], path[0][1])
highlightContext.moveTo(path[0][0] - canvasOffset.x, path[0][1] - canvasOffset.y)
}
for (let p = 1; p < path.length; p++) {
//context.lineTo(path[p][0]*zoom, path[p][1]*zoom)
highlightContext.lineTo(path[p][0], path[p][1])
highlightContext.lineTo(path[p][0] - canvasOffset.x, path[p][1] - canvasOffset.y)
}
highlightContext.closePath()
@ -547,12 +537,12 @@ async function render() {
if (path[0]) {
//context.moveTo(path[0][0]*zoom, path[0][1]*zoom)
highlightContext.moveTo(path[0][0], path[0][1])
highlightContext.moveTo(path[0][0] - canvasOffset.x, path[0][1] - canvasOffset.y)
}
for (let p = 1; p < path.length; p++) {
//context.lineTo(path[p][0]*zoom, path[p][1]*zoom)
highlightContext.lineTo(path[p][0], path[p][1])
highlightContext.lineTo(path[p][0] - canvasOffset.x, path[p][1] - canvasOffset.y)
}
highlightContext.closePath()
@ -578,13 +568,10 @@ async function render() {
}
function updateHovering(e, tapped) {
if (dragging || (fixed && !tapped)) return
function updateCoordsDisplay(e) {
const 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
(e.clientX - (container.clientWidth / 2 - innerContainer.clientWidth / 2 + zoomOrigin[0] + container.offsetLeft)) / zoom + canvasOffset.x,
(e.clientY - (container.clientHeight / 2 - innerContainer.clientHeight / 2 + zoomOrigin[1] + container.offsetTop)) / zoom + canvasOffset.y
]
const coordsEl = document.getElementById("coords_p")
@ -592,11 +579,19 @@ function updateHovering(e, tapped) {
if (isNaN(pos[0])) {
coordsEl.textContent = "0, 0"
} else {
coordsEl.textContent = Math.ceil(pos[0]) + ", " + Math.ceil(pos[1])
coordsEl.textContent = Math.floor(pos[0]) + ", " + Math.floor(pos[1])
}
if (!(pos[0] <= 2200 && pos[0] >= -100 && pos[0] <= 2200 && pos[0] >= -100)) return
return pos
}
function updateHovering(e, tapped) {
if (dragging || (fixed && !tapped)) return
const pos = updateCoordsDisplay(e)
if (!(pos[0] <= canvasSize.x + canvasOffset.x + 200 && pos[0] >= canvasOffset.x - 200 && pos[1] <= canvasSize.y + canvasOffset.y + 200 && pos[1] >= canvasOffset.x - 200)) return
const newHovered = []
for (const entry of atlasDisplay) {
if (pointIsInPolygon(pos, entry.path)) newHovered.push(entry)
@ -647,36 +642,44 @@ function updateHovering(e, tapped) {
render()
}
window.addEventListener("hashchange", highlightEntryFromUrl)
window.addEventListener("hashchange", updateViewFromHash)
function highlightEntryFromUrl() {
function updateViewFromHash() {
const hash = window.location.hash.substring(1); //Remove hash prefix
let [id, period] = hash.split('/')
let [hashEntryId, hashPeriod, hashX, hashY, hashZoom] = hash.split('/')
// Handle zzz and 0.. prefix
let newId = id.replace(/^zzz([a-z0-9]{8,})$/g, "$1").replace(/^0+/, '')
if (id !== newId) {
id = newId
let newId = hashEntryId.replace(/^zzz([a-z0-9]{8,})$/g, "$1").replace(/^0+/, '')
if (hashEntryId !== newId) {
hashEntryId = newId
const newLocation = new URL(window.location)
newLocation.hash = '#' + [newId, period].join('/')
newLocation.hash = '#' + [newId, hashPeriod, hashX, hashY, hashZoom].join('/')
history.replaceState({}, "", newLocation)
}
let targetPeriod, targetVariation
if (period) {
[targetPeriod, , targetVariation] = parsePeriod(period)
if (hashPeriod) {
[targetPeriod, , targetVariation] = parsePeriod(hashPeriod)
} else {
targetPeriod = defaultPeriod
targetVariation = defaultVariation
}
updateTime(targetPeriod, targetVariation, true)
if (!id) return
setView(
(isNaN(hashX) || hashX === '') ? undefined : Number(hashX),
(isNaN(hashY) || hashY === '') ? undefined : Number(hashY),
(isNaN(hashZoom) || hashZoom === '') ? undefined : Number(hashZoom)
)
if (!hashEntryId) return
// Highlight entry from hash
const entries = atlas.filter(e => {
return e.id === id
return e.id.toString() === hashEntryId
})
if (entries.length !== 1) return
@ -686,7 +689,7 @@ function highlightEntryFromUrl() {
document.title = entry.name + " on " + pageTitle
if ((!entry.diff || entry.diff !== "delete")) {
objectEditNav.href = "./?mode=draw&id=" + id
objectEditNav.href = "./?mode=draw&id=" + hashEntryId
objectEditNav.title = "Edit " + entry.name
if (!objectEditNav.isConnected) {
showListButton.parentElement.appendChild(objectEditNav)
@ -700,8 +703,11 @@ function highlightEntryFromUrl() {
objectsContainer.appendChild(infoElement)
renderBackground(atlas)
applyView()
setView(entry.center[0], entry.center[1], setZoomByPath(entry.path))
setView(
(isNaN(hashX) || hashX === '') ? entry.center[0] : Number(hashX),
(isNaN(hashY) || hashY === '') ? entry.center[1] : Number(hashY),
(isNaN(hashZoom) || hashZoom === '') ? setZoomByPath(entry.path) : Number(hashZoom)
)
closeObjectsListButton.classList.remove("d-none")
entriesList.classList.add("disableHover")
@ -714,7 +720,7 @@ function highlightEntryFromUrl() {
function setZoomByPath(path) {
let boundingBox = [canvasSize.x, 0, canvasSize.y, 0]
let boundingBox = [canvasSize.x + canvasOffset.x, canvasOffset.x, canvasSize.y + canvasOffset.y, canvasOffset.y]
path?.forEach(([x, y]) => {
boundingBox[0] = Math.min(boundingBox[0], x)
boundingBox[1] = Math.max(boundingBox[1], x)
@ -729,6 +735,8 @@ function setZoomByPath(path) {
zoom = Math.min(clientSize[0] / boundingBoxSize[0], clientSize[1] / boundingBoxSize[1])
zoom = Math.min(4, zoom/2)
return zoom
}
function initView() {
@ -739,14 +747,14 @@ function initView() {
document.addEventListener('timeupdate', () => {
atlasDisplay = atlas.slice()
resetEntriesList(null, null)
resetEntriesList()
})
// parse linked atlas entry id from link hash
/*if (window.location.hash.substring(3)){
zoom = 4
applyView()
highlightEntryFromUrl()
updateViewFromHash()
}*/
applyView()
@ -762,17 +770,7 @@ function initExplore() {
function updateHovering(e, tapped) {
if (dragging || (fixed && !tapped)) return
const 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
]
const coordsEl = document.getElementById("coords_p")
// Displays coordinates as zero instead of NaN
if (isNaN(pos[0])) {
coordsEl.textContent = "0, 0"
} else {
coordsEl.textContent = Math.ceil(pos[0]) + ", " + Math.ceil(pos[1])
}
updateCoordsDisplay(e)
}
renderBackground(atlas)
@ -793,10 +791,7 @@ function initGlobal() {
})
document.addEventListener('timeupdate', event => {
let hashData = window.location.hash.substring(1).split('/')
const newLocation = new URL(window.location)
newLocation.hash = formatHash(hashData[0], event.detail.period, event.detail.period, event.detail.variation)
if (location.hash !== newLocation.hash) history.replaceState({}, "", newLocation)
updateHash()
})
}
@ -826,26 +821,22 @@ function initViewGlobal() {
container.addEventListener("touchend", e => {
e.preventDefault()
//console.log(e)
//console.log(e.changedTouches[0].clientX)
if (e.changedTouches.length !== 1) return
e = e.changedTouches[0]
//console.log(lastPos[0] - e.clientX)
if (Math.abs(lastPos[0] - e.clientX) + Math.abs(lastPos[1] - e.clientY) > 4)
if (Math.sqrt(Math.pow(lastPos[0] - e.clientX, 2) + Math.pow(lastPos[1] - e.clientY, 2)) < 10)
setTimeout(() => updateHovering(e, true), 0)
//console.log("Foo!!")
dragging = false
fixed = false
setTimeout(() => updateHovering(e, true), 0)
})
if (window.location.hash) { // both "/" and just "/#" will be an empty hash string
highlightEntryFromUrl()
updateViewFromHash()
}
document.addEventListener('timeupdate', event => {
drawButton.href = "./?mode=draw" + formatHash(undefined, event.detail.period, event.detail.period, event.detail.variation)
drawButton.href = "./?mode=draw" + formatHash(null, event.detail.period, event.detail.period, event.detail.variation)
})
}

2
web/_redirects Normal file
View File

@ -0,0 +1,2 @@
https://place-atlas.stefanocoding.me/* https://2022.place-atlas.stefanocoding.me/:splat 301!
http://place-atlas.stefanocoding.me/* https://2022.place-atlas.stefanocoding.me/:splat 301!

View File

@ -2,7 +2,7 @@
The 2022 r/place Atlas
Copyright (c) 2017 Roland Rytz <roland@draemm.li>
Copyright (c) 2022 Place Atlas contributors
Licensed under AGPL-3.0 (https://place-atlas.stefanocoding.me/license.txt)
Licensed under AGPL-3.0 (https://2022.place-atlas.stefanocoding.me/license.txt)
-->
<!DOCTYPE html>
@ -17,14 +17,22 @@
<meta property="og:title" content="About - The 2022 r/place Atlas">
<meta property="og:type" content="website">
<meta property="og:url" content="https://place-atlas.stefanocoding.me/">
<meta property="og:image" content="https://place-atlas.stefanocoding.me/_img/logo.png">
<meta property="og:url" content="https://2022.place-atlas.stefanocoding.me/">
<meta property="og:image" content="https://2022.place-atlas.stefanocoding.me/_img/logo.png">
<meta property="og:image:type" content="image/png">
<meta property="og:image:width" content="512">
<meta property="og:image:height" content="512">
<meta property="og:image:alt" content="The r/place Atlas logo">
<meta property="og:description" content="This is an atlas aiming to chart all the artworks created during the r/place April Fools event on Reddit in 2022. It is made with information to each artwork of the canvas provided by the community.">
<meta name="twitter:card" content="summary">
<meta name="twitter:creator" content="Place Atlas contributors (original by Roland Rytz)">
<meta name="twitter:url" content="https://2022.place-atlas.stefanocoding.me/">
<meta name="twitter:title" content="About - The 2022 r/place Atlas">
<meta name="twitter:description" content="This is an atlas aiming to chart all the artworks created during the r/place April Fools event on Reddit in 2022. It is made with information to each artwork of the canvas provided by the community.">
<meta name="twitter:image" content="https://2022.place-atlas.stefanocoding.me/_img/logo.png">
<meta name="twitter:image:alt" content="The 2022 r/place Atlas logo">
<meta name="viewport" content="width=device-width, height=device-height, initial-scale=1, viewport-fit=cover">
<meta name="color-scheme" content="light dark">
@ -53,12 +61,19 @@
</button>
<div class="navbar-collapse collapse" id="navbarCollapse">
<ul class="navbar-nav ms-auto pt-2 pt-md-0">
<li class="nav-item">
<a class="nav-link" href="./">Atlas Map</a>
</li>
<li class="nav-item">
<a class="nav-link" href="https://place-wiki.stefanocoding.me/">Wiki</a>
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false" aria-current="page">
Atlas Map
</a>
<ul class="dropdown-menu">
<li><a class="dropdown-item" href="https://2017.place-atlas.stefanocoding.me/">2017</a></li>
<li><a class="dropdown-item" href="/">2022</a></li>
<li><a class="dropdown-item" href="https://2023.place-atlas.stefanocoding.me/">2023</a></li>
</ul>
</li>
<li class="nav-item col-6 col-md-auto">
<a class="nav-link" href="https://place-wiki.stefanocoding.me/">Place Wiki</a>
</li>
<li class="nav-item">
<a class="nav-link active" href="#" aria-current="page">About</a>
</li>
@ -74,14 +89,14 @@
<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 Reddit in 2022. It is made with information to each artwork of the canvas provided by the community.</p>
<p>The original code was developed by <a href="https://draemm.li/various/place-atlas/">Roland Rytz</a> <a href="mailto:roland.rytz@gmail.com"><i aria-label="Mail" class="bi bi-envelope"></i></a> <a href="https://reddit.com/user/draemmli/"><i aria-label="Reddit" class="bi bi-reddit"></i></a> and is available under the free <a href="https://www.gnu.org/licenses/agpl-3.0.en.html">AGPL license</a> on <a href="https://github.com/RolandR/place-atlas">GitHub</a>.</p>
<hr>
<p>The currently maintained version of the website is managed by <a href="https://github.com/placeAtlas">the Place Atlas team</a>, led by Stefano Haagmans and is obtainable under the same license within a <a href="https://github.com/placeAtlas/atlas">GitHub fork</a>. Initial images are provided by <a href="https://place.thatguyalex.com/">Alex Tsernoh</a>.</p>
<p>The currently maintained version of the website is managed by <a href="https://github.com/placeAtlas">the Place Atlas team</a>, led by Stefano Haagmans and is obtainable under the same license within a <a href="https://github.com/placeAtlas/atlas-2022">GitHub fork</a>. Initial images are provided by <a 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 href="https://paypal.me/placeAtlas/5">PayPal</a>, <a href="https://www.patreon.com/placeAtlas">Patreon</a>, or <a 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>
<p>Roland Rytz worked on the Atlas full-time (and more!) for over two weeks during the 2017 r/place event. If you'd like to support Roland, you can do so by <a href="https://paypal.me/draemmli">PayPal</a>. If you donate more than 10(€/$/CHF/mBTC), He'll (hopefully) send you a nice sticker of the 2017 Place canvas!</p>
<h2>Contributing</h2>
<p>This project is open source, and contributions are welcome. In fact, the Atlas relies on user contributions.</p>
<p>To contribute a label for an artwork, please read <a href="https://github.com/placeAtlas/atlas/blob/master/CONTRIBUTING.md">this guide</a> to learn how to submit a new entry, edit existing entries, or contribute to the development of the codebase.</p>
<p>To contribute a label for an artwork, please read <a href="https://github.com/placeAtlas/atlas-2022/blob/master/CONTRIBUTING.md">this guide</a> to learn how to submit a new entry, edit existing entries, or contribute to the development of the codebase.</p>
<p><a href="https://reddit.com/r/placeAtlas2/">The r/placeAtlas2 subreddit</a> and <a href="https://discord.gg/pJkm23b2nA">the Discord server</a> is also the place to submit all bug reports, feature requests, or questions.</p>
<div id="credits">
@ -176,7 +191,7 @@
<li>Others:
<ul>
<li>"The Final Clean" canvas: r/TheFinalClean community</li>
<li>Everyone who contributes from <a href="https://github.com/placeAtlas/atlas/graphs/contributors">GitHub</a>, <a href="https://discord.gg/pJkm23b2nA">Discord</a>, or other channels.</li>
<li>Everyone who contributes from <a href="https://github.com/placeAtlas/atlas-2022/graphs/contributors">GitHub</a>, <a href="https://discord.gg/pJkm23b2nA">Discord</a>, or other channels.</li>
</ul>
</li>
</ul>
@ -220,7 +235,7 @@
</div>
</div>
<footer class="pt-3 mt-4 text-muted border-top">
Original by <a href="https://draemm.li/various/place-atlas/" target="_blank" rel="noopener noreferrer author">Roland Rytz</a> (<a href="https://github.com/RolandR/place-atlas">source</a>). Maintained by <a href="https://github.com/placeAtlas/atlas/contributors">Place Atlas contributors</a> (<a href="https://github.com/placeAtlas/atlas">source</a>).
Original by <a href="https://draemm.li/various/place-atlas/" target="_blank" rel="noopener noreferrer author">Roland Rytz</a> (<a href="https://github.com/RolandR/place-atlas">source</a>). Maintained by <a href="https://github.com/placeAtlas/atlas-2022/contributors">Place Atlas contributors</a> (<a href="https://github.com/placeAtlas/atlas-2022">source</a>).
</footer>
</div>
</main>

View File

@ -5560,3 +5560,9 @@ GDJosef
eri531
-Yox-
gh:Slymeball
Annilee_Rose2
gh:GeoDash897
wiev0
realzezo
_squizzle
DasHeroTill

File diff suppressed because it is too large Load Diff

View File

@ -2,7 +2,7 @@
The 2022 r/place Atlas
Copyright (c) 2017 Roland Rytz <roland@draemm.li>
Copyright (c) 2022 Place Atlas contributors
Licensed under AGPL-3.0 (https://place-atlas.stefanocoding.me/license.txt)
Licensed under AGPL-3.0 (https://2022.place-atlas.stefanocoding.me/license.txt)
-->
<!DOCTYPE html>
@ -17,14 +17,22 @@
<meta property="og:title" content="The 2022 r/place Atlas">
<meta property="og:type" content="website">
<meta property="og:url" content="https://place-atlas.stefanocoding.me/">
<meta property="og:image" content="https://place-atlas.stefanocoding.me/_img/logo.png">
<meta property="og:url" content="https://2022.place-atlas.stefanocoding.me/">
<meta property="og:image" content="https://2022.place-atlas.stefanocoding.me/_img/logo.png">
<meta property="og:image:type" content="image/png">
<meta property="og:image:width" content="512">
<meta property="og:image:height" content="512">
<meta property="og:image:alt" content="The r/place Atlas logo">
<meta property="og:description" content="An interactive map of Reddit's 2022 r/place, with information to each artwork of the canvas provided by the community.">
<meta name="twitter:card" content="summary">
<meta name="twitter:creator" content="Place Atlas contributors (original by Roland Rytz)">
<meta name="twitter:url" content="https://2022.place-atlas.stefanocoding.me/">
<meta name="twitter:title" content="The 2022 r/place Atlas">
<meta name="twitter:description" content="An interactive map of Reddit's 2022 r/place, with information to each artwork of the canvas provided by the community.">
<meta name="twitter:image" content="https://2022.place-atlas.stefanocoding.me/_img/logo.png">
<meta name="twitter:image:alt" content="The 2022 r/place Atlas logo">
<!-- <meta name="google-site-verification" content="gZGHpBSMzffAbIn0qB8b00We6EwSGkDTfDoQVv-NWss"/> -->
<meta name="viewport" content="width=device-width, height=device-height, initial-scale=1, minimum-scale=1, maximum-scale=1, shrink-to-fit=no, viewport-fit=cover"> <!-- user-scalable=no -->
@ -49,7 +57,7 @@
"@context": "https://schema.org",
"@type": "WebSite",
"name": "The 2022 r/place Atlas",
"url": "https://place-atlas.stefanocoding.me/",
"url": "https://2022.place-atlas.stefanocoding.me/",
"author": [
{
"@type": "Person",
@ -78,7 +86,7 @@
"name": "Place Atlas",
"alternateName": "r/placeatlas2",
"url": "https://github.com/placeAtlas",
"image": "http://place-atlas.stefanocoding.me/_img/logo.png",
"image": "http://2022.place-atlas.stefanocoding.me/_img/logo.png",
"founder": {
"@type": "Person",
"@id": "#Codixer",
@ -94,58 +102,74 @@
}
],
"copyrightYear": 2017,
"license": "https://place-atlas.stefanocoding.me/license.txt",
"license": "https://2022.place-atlas.stefanocoding.me/license.txt",
"inLanguage": "English",
"isAccessibleForFree": true,
"keywords": "reddit, r/place, place, experiment",
"thumbnailUrl": "https://place-atlas.stefanocoding.me/_img/logo.png",
"image": "https://place-atlas.stefanocoding.me/_img/logo.png",
"thumbnailUrl": "https://2022.place-atlas.stefanocoding.me/_img/logo.png",
"image": "https://2022.place-atlas.stefanocoding.me/_img/logo.png",
"description": "An interactive map of Reddit's 2022 r/place, with information to each artwork of the canvas."
}
</script>
</head>
<body>
<div id="wrapper" class="listHidden">
<nav id="main-navbar" class="navbar navbar-expand-md fixed-top bg-body border-bottom">
<div class="container-fluid">
<a class="navbar-brand text-body d-flex align-items-center" href="./">
<picture>
<source srcset="./_img/favicon-dark.svg" media="(prefers-color-scheme: dark)">
<img class="d-block me-2" height="32" width="32" src="./_img/favicon.svg" alt="">
</picture>
The 2022 r/place Atlas
</a>
<button class="navbar-toggler text-body collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#navbarCollapse" aria-controls="navbarCollapse" aria-expanded="false" aria-label="Toggle navigation">
<i class="bi bi-list" aria-hidden="true"></i>
</button>
<div class="collapse navbar-collapse" id="navbarCollapse">
<ul class="navbar-nav me-auto my-2 my-md-0">
<li class="nav-item">
<div class="btn-group" role="group">
<button id="showListButton" class="btn btn-outline-primary" type="button" data-bs-toggle="offcanvas" data-bs-target="#offcanvasList" aria-controls="offcanvasList">Entries List</button>
</div>
</li>
</ul>
<ul class="navbar-nav mx-auto d-block d-md-none d-lg-block">
<li class="nav-item d-flex align-items-center gap-2">
<span class="p-2">Coordinates: <span class="badge bg-secondary" id="coords_p">0, 0</span></span>
</li>
</ul>
<hr class="d-md-none">
<ul class="navbar-nav flex-row flex-wrap ms-auto">
<li class="nav-item col-6 col-md-auto">
<a class="nav-link active" href="./" aria-current="page">Atlas Map</a>
</li>
<li class="nav-item col-6 col-md-auto">
<a class="nav-link" href="https://place-wiki.stefanocoding.me/">Wiki</a>
</li>
<li class="nav-item col-6 col-md-auto">
<a class="nav-link" href="./about.html">About</a>
</li>
</ul>
<header class="fixed-top">
<aside class="container-fluid alert-primary collapse" id="headerAnnouncement">
<div class="d-flex w-100 py-2 align-items-center">
<i class="bi bi-info-circle-fill fs-5"></i>
<p class="mb-0 flex-grow-1 px-2"> The 2023 edition of r/place is currently underway, and we are back! Check out <a class="alert-link" href="https://2023.place-atlas.stefanocoding.me">The 2023 r/place Atlas</a>!</p>
<a class="fs-5" data-bs-toggle="collapse" href="#headerAnnouncement" role="button" aria-expanded="false" aria-controls="headerAnnouncement"><i class="bi bi-x-lg"></i></a>
</div>
</div>
</nav>
</aside>
<nav id="main-navbar" class="navbar navbar-expand-md bg-body border-bottom">
<div class="container-fluid">
<a class="navbar-brand text-body d-flex align-items-center" href="./">
<picture>
<source srcset="./_img/favicon-dark.svg" media="(prefers-color-scheme: dark)">
<img class="d-block me-2" height="32" width="32" src="./_img/favicon.svg" alt="">
</picture>
The 2022 r/place Atlas
</a>
<button class="navbar-toggler text-body collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#navbarCollapse" aria-controls="navbarCollapse" aria-expanded="false" aria-label="Toggle navigation">
<i class="bi bi-list" aria-hidden="true"></i>
</button>
<div class="collapse navbar-collapse" id="navbarCollapse">
<ul class="navbar-nav me-auto my-2 my-md-0">
<li class="nav-item">
<div class="btn-group" role="group">
<button id="showListButton" class="btn btn-outline-primary" type="button" data-bs-toggle="offcanvas" data-bs-target="#offcanvasList" aria-controls="offcanvasList">Entries List</button>
</div>
</li>
</ul>
<ul class="navbar-nav mx-auto d-block d-md-none d-lg-block">
<li class="nav-item d-flex align-items-center gap-2">
<span class="p-2">Coordinates: <span class="badge bg-secondary" id="coords_p">0, 0</span></span>
</li>
</ul>
<hr class="d-md-none">
<ul class="navbar-nav flex-row flex-wrap ms-auto">
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle active" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false" aria-current="page">
Atlas Map
</a>
<ul class="dropdown-menu">
<li><a class="dropdown-item" href="https://2017.place-atlas.stefanocoding.me/">2017</a></li>
<li><a class="dropdown-item" href="#" aria-current="page">2022</a></li>
<li><a class="dropdown-item" href="https://2023.place-atlas.stefanocoding.me/">2023</a></li>
</ul>
</li>
<li class="nav-item col-6 col-md-auto">
<a class="nav-link" href="https://place-wiki.stefanocoding.me/">Place Wiki</a>
</li>
<li class="nav-item col-6 col-md-auto">
<a class="nav-link" href="./about.html">About</a>
</li>
</ul>
</div>
</div>
</nav>
</header>
<div id="container">
<div id="loading" class="d-flex justify-content-center">
<div id="loadingContent" class="my-auto mx-3 text-center text-white">
@ -156,7 +180,7 @@
<noscript>
<p>Sorry, you need JavaScript to view the Atlas.</p>
<p>All JavaScript on this site is licensed under either the MIT or AGPL license.</p>
<p><a href="https://github.com/placeAtlas/atlas">See the source on GitHub</a></p>
<p><a href="https://github.com/placeAtlas/atlas-2022">See the source on GitHub</a></p>
</noscript>
</div>
</div>
@ -248,7 +272,7 @@
</datalist>
</div>
<div id="author" class="bg-body d-flex align-items-center justify-content-center py-1 px-2 rounded shadow" style="--bs-bg-opacity: .9;">
<span style="font-size: 0.7rem;">Code by <a href="https://github.com/placeAtlas" target="_blank" rel="noopener noreferrer">Place Atlas</a>. Source on <a href="https://github.com/placeAtlas/atlas" target="_blank" rel="noopener noreferrer">GitHub</a>. Site powered by <a href="https://www.netlify.com" target="_blank" rel="noopener noreferrer">Netlify</a>.</span>
<span style="font-size: 0.7rem;">Code by <a href="https://github.com/placeAtlas" target="_blank" rel="noopener noreferrer">Place Atlas</a>. Source on <a href="https://github.com/placeAtlas/atlas-2022" target="_blank" rel="noopener noreferrer">GitHub</a>. Site powered by <a href="https://www.netlify.com" target="_blank" rel="noopener noreferrer">Netlify</a>.</span>
</div>
</div>
<div class="offcanvas offcanvas-start bg-body" data-bs-scroll="true" data-bs-backdrop="false" tabindex="-1" id="offcanvasDraw" aria-labelledby="offcanvasDrawLabel">
@ -288,7 +312,7 @@
<button type="button" class="btn btn-primary d-block mx-auto" id="periodsAdd">Add Period</button>
</div>
<div id="hint">
<p class="text-center">Please read <a href="https://github.com/placeAtlas/atlas/blob/master/CONTRIBUTING.md" target="_blank" rel="noopener noreferrer">this guide</a> for instructions.</p>
<p class="text-center">Please read <a href="https://github.com/placeAtlas/atlas-2022/blob/master/CONTRIBUTING.md" target="_blank" rel="noopener noreferrer">this guide</a> for instructions.</p>
<hr>
<p>You can suggest new entries to the Atlas for art that isn't mapped yet, or update entries by editing it.</p>
<p>Click anywhere on the image to start drawing a shape. Switch between periods by adding a period, and/or seek through the timeline.</p>
@ -349,7 +373,7 @@
If you want to use Reddit, use the <span class="badge bg-primary">Post Direct to Reddit</span> button or manually copy the text below and submit it as a new text post to <a href="https://www.reddit.com/r/placeAtlas2/" target="_blank" rel="noopener noreferrer">r/placeAtlas2</a> on Reddit.
Don't forget to flair it with the <span class="badge rounded-pill bg-primary"><i class="bi bi-tag" aria-hidden="true"></i> <span id="redditFlair">New Entry</span></span> flair.</p>
<p>
If you want to use GitHub, use the <span class="badge bg-primary">Submit Direct to GitHub</span> button, or read <a href="https://github.com/placeAtlas/atlas/blob/master/CONTRIBUTING.md#through-github" target="_blank" rel="noopener noreferrer">the contributing guide</a> to submit a patch.
If you want to use GitHub, use the <span class="badge bg-primary">Submit Direct to GitHub</span> button, or read <a href="https://github.com/placeAtlas/atlas-2022/blob/master/CONTRIBUTING.md#through-github" target="_blank" rel="noopener noreferrer">the contributing guide</a> to submit a patch.
</p>
<p>We will then check it and add it to the Atlas.</p>
<textarea class="form-control flex-grow-1" cols="40" rows="20" id="exportString" title="Raw JSON string" readonly></textarea>