removed fun-shit

This commit is contained in:
Donnie 2020-12-06 10:23:39 -06:00
parent 6935d30b07
commit 4d309d951f
49 changed files with 0 additions and 4898 deletions

View File

@ -1,3 +0,0 @@
github:
- mikebryant
- theRTC204

View File

@ -1,49 +0,0 @@
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: bug
assignees: ''
---
**Things to check**
- Have you forced a refresh in your browser (e.g. ctrl+F5 in Chrome/Firefox)?
- yes/no
- Have you made sure the first time buyer option is correct? If you're unsure, try it both ways
- yes/no
- Have you time-travelled this week? Travelling backwards resets the prices, and therefore you must not put prices in from both before & after the time-travel
- yes/no
**Describe the bug**
A clear and concise description of what the bug is.
**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
**Permalink to your prices**
Please click the `Copy Permalink` button and paste it here
**Expected behavior**
A clear and concise description of what you expected to happen.
**Screenshots**
If applicable, add screenshots to help explain your problem.
**Desktop (please complete the following information):**
- OS: [e.g. iOS]
- Browser [e.g. chrome, safari]
- Version [e.g. 22]
**Smartphone (please complete the following information):**
- Device: [e.g. iPhone6]
- OS: [e.g. iOS8.1]
- Browser [e.g. stock browser, safari]
- Version [e.g. 22]
**Additional context**
Add any other context about the problem here.

View File

@ -1,20 +0,0 @@
---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: enhancement
assignees: ''
---
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Additional context**
Add any other context or screenshots about the feature request here.

View File

@ -1,10 +0,0 @@
# Configuration for probot-no-response - https://github.com/probot/no-response
daysUntilClose: 7
responseRequiredLabel: more information required
closeComment: >
This issue has been automatically closed because there has been no response
to our request for more information from the original author. With only the
information that is currently in the issue, we don't have enough information
to take action. Please reach out if you have or find the answers we need so
that we can investigate further.

View File

@ -1 +0,0 @@
turnipprophet.io

View File

@ -1,13 +0,0 @@
Copyright 2020 Mike Bryant
Licensed under the Apache License, Version 2.0 (the "License");
you may not files from this repository except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View File

@ -1,201 +0,0 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View File

@ -1,3 +0,0 @@
Originally developed by Mike Bryant, with great thanks to Ninji
Original project location: https://github.com/mikebryant/ac-nh-turnip-prices

View File

@ -1,66 +0,0 @@
# Animal Crossing New Horizons: Turnip Prophet
[![discord](https://img.shields.io/badge/discord-join-7289DA.svg?logo=discord&longCache=true&style=for-the-badge)](https://discord.gg/bRh74X8)
[![issues](https://img.shields.io/github/issues/mikebryant/ac-nh-turnip-prices?style=for-the-badge)](https://github.com/mikebryant/ac-nh-turnip-prices/issues)
[![pull requests](https://img.shields.io/github/issues-pr/mikebryant/ac-nh-turnip-prices?style=for-the-badge)](https://github.com/mikebryant/ac-nh-turnip-prices/pulls)
[![contributors](https://img.shields.io/github/contributors/mikebryant/ac-nh-turnip-prices?style=for-the-badge)](https://github.com/mikebryant/ac-nh-turnip-prices/graphs/contributors)
Turnip Prophet is a price calculator/price predictor for Animal Crossing: New Horizons turnip prices.
## Support
If you have any questions, feel free to join our [Discord server](https://discord.gg/bRh74X8) to ask or [open a new issue](https://github.com/mikebryant/ac-nh-turnip-prices/issues).
If you have a prediction issue, please open an issue describing your problem and give the permalink to your prediction. Otherwise, please search the issues before opening a new one to make sure you are not opening a duplicate issue.
Please create issues in English language only.
## What about feature X?
At first please have a look at our current project scope:
| Turnip Prophet is | Turnip Prophet is not |
|----|----|
| A predictor for future prices that week | A calculator for how much money you'll make |
| Able to calculate probabilities for different futures | A way to count your turnips |
| Able to show data from a query string | A way to store multiple people's islands |
| A single page web-based app | Something with a backend |
If your idea, suggestion or improvement is anything out of the above named, feel free to [open a new issue](https://github.com/mikebryant/ac-nh-turnip-prices/issues) or contribute by a [new pull request](https://github.com/mikebryant/ac-nh-turnip-prices/pulls).
## How to run the project locally?
To run the project locally you will have to clone it and then, from the folder you just cloned, you will have to execute a command. There are multiple options, listed below:
### Using Python
For Python 2.7:
```python -m SimpleHTTPServer```
For Python 3:
```python3 -m http.server```
### Using Node.js
```npx serve```
### Using Chrome
```google-chrome --allow-file-access-from-files```
## Adding a new language
Turnip Prophet is already available in some languages. If your local language is not listed you may go on to create a JSON file corresponding to your language in the folder [locales](https://github.com/mikebryant/ac-nh-turnip-prices/tree/master/locales). You may copy the [English localisation](https://github.com/mikebryant/ac-nh-turnip-prices/blob/master/locales/en.json) and translate it.
Please make sure **not to translate** "Turnip Prophet" and include the new language in the selector inside [js/translations.js](https://github.com/mikebryant/ac-nh-turnip-prices/blob/master/js/translations.js).
If you have any remaining questions, feel free to stop by the Discord server and ask.
## Final statement
A special thanks to all who [contribute](https://github.com/mikebryant/ac-nh-turnip-prices/graphs/contributors) to this project, helping to improve it and spend their time.
Stay awesome guys.

View File

@ -1,670 +0,0 @@
@import url('https://fonts.googleapis.com/css2?family=Raleway:wght@800&family=Varela+Round&display=swap');
/* - Variables - */
:root {
--color-blue: #0AB5CD;
--color-light-blue: #5ECEDB;
--bg-color: #DEF2D9;
--bg-dot-color: #FFF;
--shadow-3: rgba(0, 0, 0, 0.03);
--shadow-5: rgba(0, 0, 0, 0.05);
--shadow-6: rgba(0, 0, 0, 0.06);
--shadow-8: rgba(0, 0, 0, 0.08);
--shadow-9: rgba(0, 0, 0, 0.09);
--shadow-10: rgba(0, 0, 0, 0.10);
--shadow-15: rgba(0, 0, 0, 0.16);
--shadow-16: rgba(0, 0, 0, 0.16);
--shadow-20: rgba(0, 0, 0, 0.20);
--center-bg-color: #FFF;
--wave-1: rgba(255, 255, 255, 0);
--wave-2: rgba(255, 255, 255, 0.2);
--wave-3: rgba(255, 255, 255, 0.4);
--wave-4: rgba(255, 255, 255, 0.6);
--nook-phone-bg-color: #F5F8FF;
--nook-phone-text-color: #686868;
--dialog-bg-color: #FFFAE5;
--dialog-text-color: #837865;
--dialog-name-bg-color: #FF9A40;
--dialog-name-text-color: #BA3B1F;
--chart-fill-color: var(--bg-color);
--chart-line-color: rgba(0, 0, 0, 0.1);
--chart-point-color: rgba(0, 0, 0, 0.1);
--select-text-color: var(--dialog-text-color);
--select-border-color: var(--bg-color);
--select-bg-color-hover: #EBFEFD;
--italic-color: #AAA;
--form-h6-text-color: #845E44;
--radio-hover-bg-color: var(--nook-phone-bg-color);
--radio-checked-text-color: #FFF;
--input-bg-color: #F3F3F3;
--input-focus-bg-color: white;
--input-focus-text-color: var(--color-blue);
--input-now-bg-color: var(--dialog-name-bg-color);
--input-now-text-color: var(--dialog-name-text-color);
--button-text-color: var(--nook-phone-text-color);
--button-reset-text-color: #E45B5B;
--table-range0: hsl(140, 80%, 85%);
--table-range1: hsl(90, 80%, 85%);
--table-range2: hsl(60, 80%, 85%);
--table-range3: hsl(30, 80%, 85%);
--table-range4: hsl(0, 80%, 85%);
}
[data-theme="dark"] {
--bg-color: #1A1A1A;
--bg-dot-color: #222;
--shadow-3: rgba(255, 255, 255, 0.03);
--shadow-15: rgba(255, 255, 255, 0.03);
--center-bg-color: #101010;
--wave-1: rgba(16, 16, 16, 0);
--wave-2: rgba(16, 16, 16, 0.2);
--wave-3: rgba(16, 16, 16, 0.4);
--wave-4: rgba(16, 16, 16, 0.6);
--nook-phone-bg-color: #000F33;
--nook-phone-text-color: #CCC;
--dialog-bg-color: #252422;
--dialog-text-color: #BCB5A9;
--dialog-name-bg-color: #BA3B1F;
--dialog-name-text-color: #FF9A40;
--chart-fill-color: #2D5F21;
--chart-line-color: rgba(200, 200, 200, 0.4);
--chart-point-color: rgba(200, 200, 200, 0.6);
--select-text-color: #837865;
--select-border-color: var(--bg-color);
--select-bg-color-hover: #EBFEFD;
--italic-color: #666;
--form-h6-text-color: #E18B51;
--radio-hover-bg-color: #00174D;
--radio-checked-text-color: #FFF;
--input-bg-color: #333;
--input-focus-bg-color: #999;
--input-focus-text-color: var(--radio-hover-bg-color);
--button-text-color: var(--nook-phone-text-color);
--button-reset-text-color: #E45B5B;
--table-range0: hsl(140, 80%, 27%);
--table-range1: hsl(90, 80%, 20%);
--table-range2: hsl(60, 80%, 20%);
--table-range3: hsl(30, 80%, 20%);
--table-range4: hsl(0, 80%, 22%);
}
/* - Global Styles - */
html {
font-size: 14px;
background: var(--bg-color);
background-image:
radial-gradient(var(--bg-dot-color) 20%, transparent 0),
radial-gradient(var(--bg-dot-color) 20%, transparent 0);
background-size: 30px 30px;
background-position: 0 0, 15px 15px;
}
body {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
font-family: 'Varela Round', sans-serif;
}
h1 {
text-align: center;
font-size: 1.8rem;
}
h2 {
text-align: center;
font-size: 1.6rem;
}
.nook-phone {
width: 100%;
max-width: 1400px;
box-sizing: border-box;
margin: 16px auto;
border-radius: 40px;
padding: 16px 0px;
padding-bottom: 16px;
background: var(--nook-phone-bg-color);
color: var(--nook-phone-text-color);
overflow: hidden;
box-shadow: 0 1px 3px var(--shadow-6), 0 1px 2px var(--shadow-8);
}
.nook-phone-center {
background: var(--center-bg-color);
display: flex;
flex-direction: column;
align-items: center;
}
.dialog-box {
background: var(--dialog-bg-color);
box-sizing: border-box;
padding: 16px 24px;
margin: 32px auto;
position: relative;
border-radius: 40px;
max-width: 800px;
box-shadow: 0 1px 3px var(--shadow-6), 0 1px 2px var(--shadow-8);
}
.dialog-box-option {
text-align: center;
}
.dialog-box-option p,
.dialog-box-option select {
display: inline;
}
.dialog-box-option select {
font-size: 1rem;
padding: 4px;
font-weight: bold;
border-radius: 4px;
border-color: var(--select-border-color);
color: var(--select-text-color);
cursor: pointer;
transition: 0.2s all;
}
.dialog-box-option select:hover {
background-color: var(--select-bg-color-hover);
border-color: var(--color-light-blue);
box-shadow: 0 2px 4px var(--shadow-16);
}
.dialog-box-option select:focus {
outline: none;
}
.dialog-box p,
.dialog-box label {
font-family: 'Raleway', sans-serif;
font-weight: 800;
font-size: 1rem;
color: var(--dialog-text-color);
letter-spacing: 0.2px;
line-height: 1.8rem;
}
.dialog-box b,
.dialog-box a {
color: var(--color-blue);
transition: 0.2s all;
}
.dialog-box i {
font-style: normal;
color: var(--italic-color);
}
.dialog-box a:hover {
color: var(--color-light-blue);
}
.dialog-box .dialog-box__name {
position: absolute;
left: 16px;
top: -28px;
font-size: 1rem;
color: var(--dialog-name-text-color);
padding: 4px 16px;
background: var(--dialog-name-bg-color);
border-radius: 40px;
}
.dialog-box.error {
display: none;
}
.input__form {
background: var(--center-bg-color);
display: flex;
flex-direction: column;
padding: 16px;
align-items: center;
}
.form__row {
display: flex;
flex-wrap: wrap;
margin-bottom: 16px;
justify-content: center;
align-items: center;
}
.form__row h6 {
width: 100%;
display: block;
font-weight: 800;
font-size: 1.25rem;
margin: 8px auto;
color: var(--form-h6-text-color);
text-align: center;
}
.form__flex-wrap {
margin-top: 8px;
display: flex;
flex-wrap: wrap;
width: 100%;
max-width: 1080px;
justify-content: center;
}
.input__group {
display: flex;
flex-direction: column;
margin: 8px;
align-items: center;
}
.input__group label {
font-size: 1rem;
font-weight: bold;
margin-bottom: 8px;
opacity: 0.7;
text-align: center;
}
.form__flex-wrap .input__group label {
margin-left: 0px;
margin-bottom: 8px;
}
.input__form i {
text-align: center;
display: block;
font-style: normal;
color: var(--italic-color);
font-size: 0.9rem;
margin: 8px auto;
}
.input__form>.form__row input {
margin: 0px auto;
}
input {
border: 0px solid white;
border-radius: 40px;
padding: 8px 16px;
font-size: 1.25rem;
font-family: inherit;
color: inherit;
font-weight: bold;
transition: 0.2s all;
margin: 8px 0px;
}
input[type=number]:placeholder-shown {
background: var(--input-bg-color);
}
input[type=number]:not(:placeholder-shown) {
background: transparent;
color: var(--color-blue);
}
input[type=number]:placeholder-shown:hover {
cursor: pointer;
background: var(--radio-hover-bg-color);
transform: scale(1.1);
box-shadow: 0 1px 6px var(--shadow-5), 0 3px 6px var(--shadow-9);
}
input[type=number]:focus {
outline: none;
transform: scale(1.1);
color: var(--input-focus-text-color);
background: var(--input-focus-bg-color);
box-shadow: 0 1px 6px var(--shadow-5), 0 3px 6px var(--shadow-9);
}
input[type=number]:focus::placeholder {
opacity: 0;
}
input[type=number] {
width: 60px;
text-align: center;
}
input[type=number]:disabled {
background: inherit;
}
input[type=number]:disabled:hover {
box-shadow: none;
transform: none;
cursor: default;
}
input::-webkit-outer-spin-button,
input::-webkit-inner-spin-button {
-webkit-appearance: none;
margin: 0;
}
input[type=number] {
-moz-appearance: textfield;
}
.input__radio-buttons {
display: flex;
flex-wrap: wrap;
justify-content: center;
margin-top: 8px;
}
.input__radio-buttons input[type=radio] {
display: none;
}
.input__radio-buttons input[type="radio"]+label {
opacity: 1;
border: none;
border-radius: 40px;
background: var(--input-bg-color);
padding: 8px 16px;
font-size: 1.25rem;
font-family: inherit;
font-weight: bold;
transition: 0.2s all;
margin: 8px;
}
.input__radio-buttons input[type="radio"]:not(:checked)+label:hover {
cursor: pointer;
background: var(--radio-hover-bg-color);
transform: scale(1.1);
box-shadow: 0 1px 6px var(--shadow-5), 0 3px 6px var(--shadow-9);
}
.input__radio-buttons input[type="radio"]:checked+label {
background: var(--color-blue);
color: var(--radio-checked-text-color);
}
input[class=now]:placeholder-shown {
background: var(--input-now-bg-color);
}
input[class=now]:placeholder-shown::placeholder {
color: var(--input-now-text-color);
}
.button {
color: var(--button-text-color);
font-family: inherit;
font-weight: bold;
padding: 8px 16px;
border-width: 0px;
border-radius: 40px;
background: var(--input-bg-color);
font-size: 1.2rem;
transition: 0.2s all;
position: relative;
margin: 16px auto;
}
.button:hover {
transform: scale(1.1);
cursor: pointer;
background: var(--radio-hover-bg-color);
opacity: 1;
box-shadow: 0 1px 6px var(--shadow-5), 0 3px 6px var(--shadow-9);
}
.button.button--reset {
color: var(--button-reset-text-color);
}
.table-wrapper {
display: inline-block;
max-width: 98%;
padding: 16px;
margin: 0px auto;
box-sizing: border-box;
overflow-x: auto;
scrollbar-width: thin;
}
@media only screen and (max-width: 1440px) and (pointer: fine) {
.table-wrapper {
max-height: calc(75vh - 40px);
}
}
.table-wrapper::-webkit-scrollbar {
height: 8px;
width: 5px;
}
.table-wrapper::-webkit-scrollbar-track {
height: 8px;
width: 5px;
box-shadow: inset 0 0 6px var(--shadow-20);
-webkit-box-shadow: inset 0 0 6px var(--shadow-20);
}
.table-wrapper::-webkit-scrollbar-thumb {
height: 8px;
width: 5px;
background: var(--shadow-20);
box-shadow: inset 0 0 6px var(--shadow-20);
-webkit-box-shadow: inset 0 0 6px var(--shadow-10);
}
.table-wrapper::-webkit-scrollbar-thumb:window-inactive {
height: 8px;
width: 5px;
background: var(--shadow-20);
}
#turnipTable {
border-collapse: collapse;
}
#turnipTable th div:nth-of-type(1) {
margin-bottom: 2px;
}
#turnipTable th div:nth-of-type(2) {
display: flex;
justify-content: space-around;
opacity: 0.4;
}
#turnipTable td {
white-space: nowrap;
max-width: 150px;
padding: 6px 4px;
text-align: center;
border-right: 1px solid var(--shadow-3);
border-bottom: 1px solid var(--shadow-15);
}
#turnipTable tbody tr {
opacity: 0.8;
}
#turnipTable tbody tr:hover {
cursor: default;
opacity: 1;
}
#turnipTable .table-pattern {
white-space: nowrap;
}
#turnipTable td.range4 {
background-color: var(--table-range4);
}
#turnipTable td.range3{
background-color: var(--table-range3);
}
#turnipTable td.range2 {
background-color: var(--table-range2);
}
#turnipTable td.range1 {
background-color: var(--table-range1);
}
#turnipTable td.range0 {
background-color: var(--table-range0);
}
.chart-wrapper {
margin-top: 8px;
display: flex;
flex-wrap: wrap;
height: 400px;
width: 100%;
max-width: 1080px;
justify-content: center;
}
.waves {
position: relative;
width: 100%;
height: 5vh;
margin-bottom: -7px;
/*Fix for safari gap*/
max-height: 150px;
}
#permalink-input {
display: none;
position: fixed;
}
.permalink {
display: none;
white-space: nowrap;
font-size: 18px;
user-select: none;
cursor: pointer;
}
.permalink .fa-copy {
margin: 0 8px;
height: 20px;
color: var(--color-blue);
}
/* The snackbar - position it at the bottom and in the middle of the screen */
#snackbar {
visibility: hidden; /* Hidden by default. Visible on click */
min-width: 250px; /* Set a default minimum width */
background-color: var(--dialog-bg-color); /* Black background color */
font-family: 'Raleway', sans-serif;
font-weight: 800;
font-size: 1rem;
color: var(--dialog-text-color);
letter-spacing: 0.2px;
line-height: 1.8rem;
text-align: center; /* Centered text */
border-radius: 40px; /* Rounded borders */
padding: 16px 24px; /* Padding */
position: fixed; /* Sit on top of the screen */
z-index: 1; /* Add a z-index if needed */
bottom: 30px; /* 30px from the bottom */
box-shadow: 0 1px 3px var(--shadow-6), 0 1px 2px var(--shadow-8);
}
/* Show the snackbar when clicking on a button (class added with JavaScript) */
#snackbar.show {
visibility: visible; /* Show the snackbar */
/* Add animation: Take 0.5 seconds to fade in and out the snackbar.
However, delay the fade out process for 2.5 seconds */
-webkit-animation: fadein 0.5s, fadeout 0.5s 2.5s;
animation: fadein 0.5s, fadeout 0.5s 2.5s;
}
/* Animations to fade the snackbar in and out */
@-webkit-keyframes fadein {
from {bottom: 0; opacity: 0;}
to {bottom: 30px; opacity: 1;}
}
@keyframes fadein {
from {bottom: 0; opacity: 0;}
to {bottom: 30px; opacity: 1;}
}
@-webkit-keyframes fadeout {
from {bottom: 30px; opacity: 1;}
to {bottom: 0; opacity: 0;}
}
@keyframes fadeout {
from {bottom: 30px; opacity: 1;}
to {bottom: 0; opacity: 0;}
}
/* Cloud SVG placement */
.parallax>use:nth-child(1) {
transform: translate3d(-30px, 0, 0);
fill: var(--wave-4);
}
.parallax>use:nth-child(2) {
transform: translate3d(-90px, 0, 0);
fill: var(--wave-3);
}
.parallax>use:nth-child(3) {
transform: translate3d(45px, 0, 0);
fill: var(--wave-2);
}
.parallax>use:nth-child(4) {
transform: translate3d(20px, 0, 0);
fill: var(--wave-1);
}
/*Shrinking for mobile*/
@media (max-width: 768px) {
.waves {
height: 40px;
min-height: 40px;
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 48 KiB

View File

@ -1,361 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Animal Crossing - Turnip Prophet</title>
<meta name="description" content="Animal Crossing - Turnip Prophet">
<meta name="author" content="Mike Bryant">
<meta name="theme-color" content="#def2d9">
<!-- generics -->
<link rel="icon" href="img/favicon-32.png" sizes="32x32">
<link rel="icon" href="img/favicon-128.png" sizes="128x128">
<link rel="icon" href="img/favicon-192.png" sizes="192x192">
<!-- Android -->
<link rel="shortcut icon" href="img/favicon-196.png" sizes="196x196">
<!-- iOS -->
<link rel="apple-touch-icon" href="img/favicon-152.png" sizes="152x152">
<link rel="apple-touch-icon" href="img/favicon-167.png" sizes="167x167">
<link rel="apple-touch-icon" href="img/favicon-180.png" sizes="180x180">
<link rel="manifest" href="/manifest.json">
<link rel="stylesheet" href="css/styles.css">
<!-- Global site tag (gtag.js) - Google Analytics -->
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-162470902-1"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag() {
dataLayer.push(arguments);
}
gtag('js', new Date());
gtag('config', 'UA-162470902-1');
</script>
<script>
function detectTheme() {
let systemTheme = window.matchMedia && window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
let preferredTheme = localStorage.getItem("theme");
if (preferredTheme == "dark" || (systemTheme == "dark" && preferredTheme != "light")) {
document.documentElement.setAttribute("data-theme", "dark");
}
}
detectTheme();
</script>
</head>
<body>
<div class="dialog-box">
<h2 class="dialog-box__name" data-i18n="general.daisy-mae"></h2>
<p data-i18n="[html]welcome.salutation"></p>
<p data-i18n="welcome.description"></p>
<p data-i18n="[html]welcome.conclusion"></p>
</div>
<div class="nook-phone">
<h1>Turnip Prophet</h1>
<div>
<svg class="waves" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
viewBox="0 24 150 28" preserveAspectRatio="none" shape-rendering="auto">
<defs>
<path id="gentle-wave" d="M-160 44c30 0 58-18 88-18s 58 18 88 18 58-18 88-18 58 18 88 18 v44h-352z" />
</defs>
<g class="parallax">
<use xlink:href="#gentle-wave" x="48" y="0" />
<use xlink:href="#gentle-wave" x="48" y="3" />
<use xlink:href="#gentle-wave" x="48" y="5" />
<use xlink:href="#gentle-wave" x="48" y="7" />
</g>
</svg>
</div>
<div class="nook-phone-center">
<form class="input__form">
<div class="form__row">
<h6 data-i18n="first-time.title"></h6>
<div class="input__group">
<label data-i18n="[html]first-time.description"></label>
<div class="input__radio-buttons">
<input type="radio" id="first-time-radio-no" name="first-time" value="false" checked>
<label for="first-time-radio-no" data-i18n="first-time.no"></label>
<input type="radio" id="first-time-radio-yes" name="first-time" value="true">
<label for="first-time-radio-yes" data-i18n="first-time.yes"></label>
</div>
</div>
</div>
<div class="form__row">
<h6 data-i18n="patterns.title"></h6>
<div class="input__group">
<label for="" data-i18n="[html]patterns.description"></label>
<div class="input__radio-buttons">
<input type="radio" id="pattern-radio-unknown" name="pattern" value="-1" checked>
<label data-i18n="patterns.unknown" for="pattern-radio-unknown"></label>
<input type="radio" id="pattern-radio-fluctuating" name="pattern" value="0">
<label data-i18n="patterns.fluctuating" for="pattern-radio-fluctuating"></label>
<input type="radio" id="pattern-radio-small-spike" name="pattern" value="3">
<label data-i18n="patterns.small-spike" for="pattern-radio-small-spike"></label>
<input type="radio" id="pattern-radio-large-spike" name="pattern" value="1">
<label data-i18n="patterns.large-spike" for="pattern-radio-large-spike"></label>
<input type="radio" id="pattern-radio-decreasing" name="pattern" value="2">
<label data-i18n="patterns.decreasing" for="pattern-radio-decreasing"></label>
</div>
</div>
</div>
<div class="form__row">
<h6 data-i18n="weekdays.sunday"></h6>
<div class="input__group">
<label data-i18n="[html]prices.description" for='buy'></label>
<input type="number" pattern="\d*" id="buy" placeholder="..." />
</div>
</div>
<i data-i18n="prices.open.am"></i>
<i data-i18n="prices.open.pm"></i>
<div class="form__flex-wrap">
<div class="form__row">
<h6 data-i18n="weekdays.monday"></h6>
<div class="input__group">
<label data-i18n="times.morning" for="sell_2"></label>
<input type="number" pattern="\d*" id="sell_2" placeholder="..." />
</div>
<div class="input__group">
<label data-i18n="times.afternoon" for="sell_3"></label>
<input type="number" pattern="\d*" id="sell_3" placeholder="..." />
</div>
</div>
<div class="form__row">
<h6 data-i18n="weekdays.tuesday"></h6>
<div class="input__group">
<label data-i18n="times.morning" for="sell_4"></label>
<input type="number" pattern="\d*" id="sell_4" placeholder="..." />
</div>
<div class="input__group">
<label data-i18n="times.afternoon" for="sell_5"></label>
<input type="number" pattern="\d*" id="sell_5" placeholder="..." />
</div>
</div>
<div class="form__row">
<h6 data-i18n="weekdays.wednesday"></h6>
<div class="input__group">
<label data-i18n="times.morning" for="sell_6"></label>
<input type="number" pattern="\d*" id="sell_6" placeholder="..." />
</div>
<div class="input__group">
<label data-i18n="times.afternoon" for="sell_7"></label>
<input type="number" pattern="\d*" id="sell_7" placeholder="..." />
</div>
</div>
<div class="form__row">
<h6 data-i18n="weekdays.thursday"></h6>
<div class="input__group">
<label data-i18n="times.morning" for="sell_8"></label>
<input type="number" pattern="\d*" id="sell_8" placeholder="..." />
</div>
<div class="input__group">
<label data-i18n="times.afternoon" for="sell_9"></label>
<input type="number" pattern="\d*" id="sell_9" placeholder="..." />
</div>
</div>
<div class="form__row">
<h6 data-i18n="weekdays.friday"></h6>
<div class="input__group">
<label data-i18n="times.morning" for="sell_10"></label>
<input type="number" pattern="\d*" id="sell_10" placeholder="..." />
</div>
<div class="input__group">
<label data-i18n="times.afternoon" for="sell_11"></label>
<input type="number" pattern="\d*" id="sell_11" placeholder="..." />
</div>
</div>
<div class="form__row">
<h6 data-i18n="weekdays.saturday"></h6>
<div class="input__group">
<label data-i18n="times.morning" for="sell_12"></label>
<input type="number" pattern="\d*" id="sell_12" placeholder="..." />
</div>
<div class="input__group">
<label data-i18n="times.afternoon" for="sell_13"></label>
<input type="number" pattern="\d*" id="sell_13" placeholder="..." />
</div>
</div>
</div>
<input id="permalink-input" type="text" readOnly />
<div id="permalink-btn" class="button permalink">
<span data-i18n="prices.copy-permalink"></span>
<svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="copy" class="svg-inline--fa fa-copy fa-w-14" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512">
<path fill="currentColor" d="M320 448v40c0 13.255-10.745 24-24 24H24c-13.255 0-24-10.745-24-24V120c0-13.255 10.745-24 24-24h72v296c0 30.879 25.121 56 56 56h168zm0-344V0H152c-13.255 0-24 10.745-24 24v368c0 13.255 10.745 24 24 24h272c13.255 0 24-10.745 24-24V128H344c-13.2 0-24-10.8-24-24zm120.971-31.029L375.029 7.029A24 24 0 0 0 358.059 0H352v96h96v-6.059a24 24 0 0 0-7.029-16.97z"></path>
</svg>
</div>
<button type="button" id="reset" class="button button--reset" name="action" data-i18n="prices.reset"></button>
</form>
<h2 data-i18n="output.title"></h2>
<div class="dialog-box error">
<h2 class="dialog-box__name" data-i18n="general.daisy-mae"></h2>
<p data-i18n="errors.impossible-values"></p>
<p data-i18n="[html]errors.github"></p>
</div>
<div class="chart-wrapper">
<canvas id="chart" width="100%" height="100"></canvas>
</div>
<div class="table-wrapper">
<table id="turnipTable">
<thead>
<tr>
<th valign="bottom" data-i18n="patterns.pattern"></th>
<th colspan="2" valign="bottom" data-i18n="output.chance"></th>
<th colspan="2">
<div data-i18n="weekdays.monday"></div>
<div>
<span data-i18n="times.morning"></span>
<span data-i18n="times.afternoon"></span>
</div>
</th>
<th colspan="2">
<div data-i18n="weekdays.tuesday"></div>
<div>
<span data-i18n="times.morning"></span>
<span data-i18n="times.afternoon"></span>
</div>
</th>
<th colspan="2">
<div data-i18n="weekdays.wednesday"></div>
<div>
<span data-i18n="times.morning"></span>
<span data-i18n="times.afternoon"></span>
</div>
</th>
<th colspan="2">
<div data-i18n="weekdays.thursday"></div>
<div>
<span data-i18n="times.morning"></span>
<span data-i18n="times.afternoon"></span>
</div>
</th>
<th colspan="2">
<div data-i18n="weekdays.friday"></div>
<div>
<span data-i18n="times.morning"></span>
<span data-i18n="times.afternoon"></span>
</div>
</th>
<th colspan="2">
<div data-i18n="weekdays.saturday"></div>
<div>
<span data-i18n="times.morning"></span>
<span data-i18n="times.afternoon"></span>
</div>
</th>
<th valign="bottom" data-i18n="output.minimum"></th>
<th valign="bottom" data-i18n="output.maximum"></th>
</tr>
</thead>
<tbody id="output"></tbody>
</table>
</div>
</div>
<div style="transform:rotate(180deg)">
<svg class="waves" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
viewBox="0 24 150 28" preserveAspectRatio="none" shape-rendering="auto">
<defs>
<path id="gentle-wave" d="M-160 44c30 0 58-18 88-18s 58 18 88 18 58-18 88-18 58 18 88 18 v44h-352z" />
</defs>
<g class="parallax">
<use xlink:href="#gentle-wave" x="48" y="0" />
<use xlink:href="#gentle-wave" x="48" y="3" />
<use xlink:href="#gentle-wave" x="48" y="5" />
<use xlink:href="#gentle-wave" x="48" y="7" />
</g>
</svg>
</div>
</div>
</div>
<div class="dialog-box">
<h2 class="dialog-box__name" data-i18n="general.daisy-mae"></h2>
<p data-i18n="textbox.description"></p>
<p data-i18n="textbox.development"></p>
</div>
<div class="dialog-box">
<h2 class="dialog-box__name" data-i18n="general.daisy-mae"></h2>
<p data-i18n="[html]textbox.thanks"></p>
<p data-i18n="[html]textbox.support"></p>
<p data-i18n="textbox.contributors-text"></p>
<p id="contributors"><span data-i18n="textbox.contributors"></span>: </p>
<p data-i18n="[html]textbox.sponsor"></p>
<div class="dialog-box-option">
<p><label for='language' data-i18n="textbox.language"></label>:</p> <select id="language"></select>
</div>
<div class="dialog-box-option">
<p><label for='theme' data-i18n="textbox.theme.title"></label>:</p> <select id="theme"></select>
</div>
</div>
<div id="snackbar">Some text some message...</div>
<script src="https://code.jquery.com/jquery-3.4.1.min.js" integrity="sha384-vk5WoKIaW/vJyUAd9n/wmopsmNhiy+L2Z+SBxGYnUkunIxVxAv/UtMOhba/xskxh" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/i18next/19.4.2/i18next.min.js" integrity="sha384-heKFZqp863HDEF6obW4Nvk9hF5pRjZThVwrDiV+tSCKPBTnu6vf5lu8QJGDwGv0X" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.min.js" integrity="sha384-i+dHPTzZw7YVZOx9lbH5l6lP74sLRtMtwN2XjVqjf3uAGAREAF4LMIUDTWEVs4LI" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/i18next-xhr-backend/3.2.2/i18nextXHRBackend.min.js" integrity="sha384-E1yZPo675XVLefQp/3MbG3T1eRDvW41iRKovK3OCHS2dWMrcF/F3/+74qwmoX1jX" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/i18next-browser-languagedetector/4.0.2/i18nextBrowserLanguageDetector.min.js" integrity="sha384-FYlRD8WE3hzVKyoaW6rmqYtUfv1ajxElK/c9bKM1NUnbsJ/VUiUv2YFEQP1AJdOQ" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-i18next/1.2.1/jquery-i18next.min.js" integrity="sha384-fLTSt6zHOb152KeFkj7kSiXdkyjKf6fjk5bdzWYLDPDo9evwd9PVs3TKoYYaaxdl" crossorigin="anonymous"></script>
<script src="js/chart.js"></script>
<script src="js/predictions.js"></script>
<script src="js/scripts.js"></script>
<script src="js/translations.js"></script>
<script src="js/contributors.js"></script>
<script src="js/themes.js"></script>
<script>
// Check compatibility for the browser we're running this in
if ("serviceWorker" in navigator) {
if (navigator.serviceWorker.controller) {
console.log(
"[PWA] Service Worker already found, skipping register"
);
} else {
// Register the service worker
navigator.serviceWorker
.register("/service-worker.js", {
scope: "./",
})
.then(function (reg) {
console.log(
"[PWA] Service worker has been registered for scope: " +
reg.scope
);
});
}
}
</script>
</body>
</html>

View File

@ -1,69 +0,0 @@
let chart_instance = null;
Chart.defaults.global.defaultFontFamily = "'Varela Round', sans-serif";
const chart_options = {
elements: {
line: {
get backgroundColor() {
return getComputedStyle(document.documentElement).getPropertyValue('--chart-fill-color');
},
get borderColor() {
return getComputedStyle(document.documentElement).getPropertyValue('--chart-line-color');
},
cubicInterpolationMode: "monotone",
},
},
maintainAspectRatio: false,
tooltips: {
intersect: false,
mode: "index",
},
};
function update_chart(input_data, possibilities) {
let ctx = $("#chart"),
datasets = [{
label: i18next.t("output.chart.input"),
get pointBorderColor() {
return getComputedStyle(document.documentElement).getPropertyValue('--chart-point-color');
},
data: input_data.slice(1),
fill: false,
}, {
label: i18next.t("output.chart.minimum"),
get pointBorderColor() {
return getComputedStyle(document.documentElement).getPropertyValue('--chart-point-color');
},
data: possibilities[0].prices.slice(1).map(day => day.min),
fill: false,
}, {
label: i18next.t("output.chart.maximum"),
get pointBorderColor() {
return getComputedStyle(document.documentElement).getPropertyValue('--chart-point-color');
},
data: possibilities[0].prices.slice(1).map(day => day.max),
fill: "-1",
},
],
labels = [i18next.t("weekdays.sunday")].concat(...[i18next.t("weekdays.abr.monday"), i18next.t("weekdays.abr.tuesday"), i18next.t("weekdays.abr.wednesday"), i18next.t("weekdays.abr.thursday"), i18next.t("weekdays.abr.friday"), i18next.t("weekdays.abr.saturday")].map(
day => [i18next.t("times.morning"),
i18next.t("times.afternoon")].map(
time => `${day} ${time}`)));
if (chart_instance) {
chart_instance.data.datasets = datasets;
chart_instance.data.labels = labels;
chart_instance.options = chart_options;
chart_instance.update();
} else {
chart_instance = new Chart(ctx, {
data: {
datasets: datasets,
labels: labels
},
options: chart_options,
type: "line",
});
}
}

View File

@ -1,26 +0,0 @@
function getContributors(page) {
const PER_PAGE = 100
if (window.jQuery) {
const container = $('#contributors');
jQuery.ajax(`https://api.github.com/repos/mikebryant/ac-nh-turnip-prices/contributors?page=${page}&per_page=${PER_PAGE}`, {})
.done(function (data) {
const contributorList = [];
data.forEach((contributor, idx) => {
if (idx === 0 && page > 1) {
contributorList.push(', ');
}
contributorList.push(`<a href="${contributor.html_url}">${contributor.login}</a>`);
if (idx < data.length - 1) {
contributorList.push(', ');
}
});
container.append(contributorList.join(''));
// If the length of the data is < PER_PAGE, we know we are processing the last page of data.
if (data.length < PER_PAGE) return;
getContributors(page + 1);
});
}
}
$(document).ready(getContributors(1));

View File

@ -1,999 +0,0 @@
const PATTERN = {
FLUCTUATING: 0,
LARGE_SPIKE: 1,
DECREASING: 2,
SMALL_SPIKE: 3,
};
const PROBABILITY_MATRIX = {
[PATTERN.FLUCTUATING]: {
[PATTERN.FLUCTUATING]: 0.20,
[PATTERN.LARGE_SPIKE]: 0.30,
[PATTERN.DECREASING]: 0.15,
[PATTERN.SMALL_SPIKE]: 0.35,
},
[PATTERN.LARGE_SPIKE]: {
[PATTERN.FLUCTUATING]: 0.50,
[PATTERN.LARGE_SPIKE]: 0.05,
[PATTERN.DECREASING]: 0.20,
[PATTERN.SMALL_SPIKE]: 0.25,
},
[PATTERN.DECREASING]: {
[PATTERN.FLUCTUATING]: 0.25,
[PATTERN.LARGE_SPIKE]: 0.45,
[PATTERN.DECREASING]: 0.05,
[PATTERN.SMALL_SPIKE]: 0.25,
},
[PATTERN.SMALL_SPIKE]: {
[PATTERN.FLUCTUATING]: 0.45,
[PATTERN.LARGE_SPIKE]: 0.25,
[PATTERN.DECREASING]: 0.15,
[PATTERN.SMALL_SPIKE]: 0.15,
},
};
const RATE_MULTIPLIER = 10000;
function range_length(range) {
return range[1] - range[0];
}
function clamp(x, min, max) {
return Math.min(Math.max(x, min), max);
}
function range_intersect(range1, range2) {
if (range1[0] > range2[1] || range1[1] < range2[0]) {
return null;
}
return [Math.max(range1[0], range2[0]), Math.min(range1[1], range2[1])];
}
function range_intersect_length(range1, range2) {
if (range1[0] > range2[1] || range1[1] < range2[0]) {
return 0;
}
return range_length(range_intersect(range1, range2));
}
/**
* Accurately sums a list of floating point numbers.
* See https://en.wikipedia.org/wiki/Kahan_summation_algorithm#Further_enhancements
* for more information.
* @param {number[]} input
* @returns {number} The sum of the input.
*/
function float_sum(input) {
// Uses the improved KahanBabuska algorithm introduced by Neumaier.
let sum = 0;
// The "lost bits" of sum.
let c = 0;
for (let i = 0; i < input.length; i++) {
const cur = input[i];
const t = sum + cur;
if (Math.abs(sum) >= Math.abs(cur)) {
c += (sum - t) + cur;
} else {
c += (cur - t) + sum;
}
sum = t;
}
return sum + c;
}
/**
* Accurately returns the prefix sum of a list of floating point numbers.
* See https://en.wikipedia.org/wiki/Kahan_summation_algorithm#Further_enhancements
* for more information.
* @param {number[]} input
* @returns {[number, number][]} The prefix sum of the input, such that
* output[i] = [sum of first i integers, error of the sum].
* The "true" prefix sum is equal to the sum of the pair of numbers, but it is
* explicitly returned as a pair of numbers to ensure that the error portion
* isn't lost when subtracting prefix sums.
*/
function prefix_float_sum(input) {
const prefix_sum = [[0, 0]];
let sum = 0;
let c = 0;
for (let i = 0; i < input.length; i++) {
const cur = input[i];
const t = sum + cur;
if (Math.abs(sum) >= Math.abs(cur)) {
c += (sum - t) + cur;
} else {
c += (cur - t) + sum;
}
sum = t;
prefix_sum.push([sum, c]);
}
return prefix_sum;
}
/*
* Probability Density Function of rates.
* Since the PDF is continuous*, we approximate it by a discrete probability function:
* the value in range [x, x + 1) has a uniform probability
* prob[x - value_start];
*
* Note that we operate all rate on the (* RATE_MULTIPLIER) scale.
*
* (*): Well not really since it only takes values that "float" can represent in some form, but the
* space is too large to compute directly in JS.
*/
class PDF {
/**
* Initialize a PDF in range [a, b], a and b can be non-integer.
* if uniform is true, then initialize the probability to be uniform, else initialize to a
* all-zero (invalid) PDF.
* @param {number} a - Left end-point.
* @param {number} b - Right end-point end-point.
* @param {boolean} uniform - If true, initialise with the uniform distribution.
*/
constructor(a, b, uniform = true) {
// We need to ensure that [a, b] is fully contained in [value_start, value_end].
/** @type {number} */
this.value_start = Math.floor(a);
/** @type {number} */
this.value_end = Math.ceil(b);
const range = [a, b];
const total_length = range_length(range);
/** @type {number[]} */
this.prob = Array(this.value_end - this.value_start);
if (uniform) {
for (let i = 0; i < this.prob.length; i++) {
this.prob[i] =
range_intersect_length(this.range_of(i), range) / total_length;
}
}
}
/**
* Calculates the interval represented by this.prob[idx]
* @param {number} idx - The index of this.prob
* @returns {[number, number]} The interval representing this.prob[idx].
*/
range_of(idx) {
// We intentionally include the right end-point of the range.
// The probability of getting exactly an endpoint is zero, so we can assume
// the "probability ranges" are "touching".
return [this.value_start + idx, this.value_start + idx + 1];
}
min_value() {
return this.value_start;
}
max_value() {
return this.value_end;
}
/**
* @returns {number} The sum of probabilities before normalisation.
*/
normalize() {
const total_probability = float_sum(this.prob);
for (let i = 0; i < this.prob.length; i++) {
this.prob[i] /= total_probability;
}
return total_probability;
}
/*
* Limit the values to be in the range, and return the probability that the value was in this
* range.
*/
range_limit(range) {
let [start, end] = range;
start = Math.max(start, this.min_value());
end = Math.min(end, this.max_value());
if (start >= end) {
// Set this to invalid values
this.value_start = this.value_end = 0;
this.prob = [];
return 0;
}
start = Math.floor(start);
end = Math.ceil(end);
const start_idx = start - this.value_start;
const end_idx = end - this.value_start;
for (let i = start_idx; i < end_idx; i++) {
this.prob[i] *= range_intersect_length(this.range_of(i), range);
}
this.prob = this.prob.slice(start_idx, end_idx);
this.value_start = start;
this.value_end = end;
// The probability that the value was in this range is equal to the total
// sum of "un-normalised" values in the range.
return this.normalize();
}
/**
* Subtract the PDF by a uniform distribution in [rate_decay_min, rate_decay_max]
*
* For simplicity, we assume that rate_decay_min and rate_decay_max are both integers.
* @param {number} rate_decay_min
* @param {number} rate_decay_max
* @returns {void}
*/
decay(rate_decay_min, rate_decay_max) {
// In case the arguments aren't integers, round them to the nearest integer.
rate_decay_min = Math.round(rate_decay_min);
rate_decay_max = Math.round(rate_decay_max);
// The sum of this distribution with a uniform distribution.
// Let's assume that both distributions start at 0 and X = this dist,
// Y = uniform dist, and Z = X + Y.
// Let's also assume that X is a "piecewise uniform" distribution, so
// x(i) = this.prob[Math.floor(i)] - which matches our implementation.
// We also know that y(i) = 1 / max(Y) - as we assume that min(Y) = 0.
// In the end, we're interested in:
// Pr(i <= Z < i+1) where i is an integer
// = int. x(val) * Pr(i-val <= Y < i-val+1) dval from 0 to max(X)
// = int. x(floor(val)) * Pr(i-val <= Y < i-val+1) dval from 0 to max(X)
// = sum val from 0 to max(X)-1
// x(val) * f_i(val) / max(Y)
// where f_i(val) =
// 0.5 if i-val = 0 or max(Y), so val = i-max(Y) or i
// 1.0 if 0 < i-val < max(Y), so i-max(Y) < val < i
// as x(val) is "constant" for each integer step, so we can consider the
// integral in integer steps.
// = sum val from max(0, i-max(Y)) to min(max(X)-1, i)
// x(val) * f_i(val) / max(Y)
// for example, max(X)=1, max(Y)=10, i=5
// = sum val from max(0, 5-10)=0 to min(1-1, 5)=0
// x(val) * f_i(val) / max(Y)
// = x(0) * 1 / 10
// Get a prefix sum / CDF of this so we can calculate sums in O(1).
const prefix = prefix_float_sum(this.prob);
const max_X = this.prob.length;
const max_Y = rate_decay_max - rate_decay_min;
const newProb = Array(this.prob.length + max_Y);
for (let i = 0; i < newProb.length; i++) {
// Note that left and right here are INCLUSIVE.
const left = Math.max(0, i - max_Y);
const right = Math.min(max_X - 1, i);
// We want to sum, in total, prefix[right+1], -prefix[left], and subtract
// the 0.5s if necessary.
// This may involve numbers of differing magnitudes, so use the float sum
// algorithm to sum these up.
const numbers_to_sum = [
prefix[right + 1][0], prefix[right + 1][1],
-prefix[left][0], -prefix[left][1],
];
if (left === i-max_Y) {
// Need to halve the left endpoint.
numbers_to_sum.push(-this.prob[left] / 2);
}
if (right === i) {
// Need to halve the right endpoint.
// It's guaranteed that we won't accidentally "halve" twice,
// as that would require i-max_Y = i, so max_Y = 0 - which is
// impossible.
numbers_to_sum.push(-this.prob[right] / 2);
}
newProb[i] = float_sum(numbers_to_sum) / max_Y;
}
this.prob = newProb;
this.value_start -= rate_decay_max;
this.value_end -= rate_decay_min;
// No need to normalise, as it is guaranteed that the sum of this.prob is 1.
}
}
class Predictor {
constructor(prices, first_buy, previous_pattern) {
// The reverse-engineered code is not perfectly accurate, especially as it's not
// 32-bit ARM floating point. So, be tolerant of slightly unexpected inputs
this.fudge_factor = 0;
this.prices = prices;
this.first_buy = first_buy;
this.previous_pattern = previous_pattern;
}
intceil(val) {
return Math.trunc(val + 0.99999);
}
minimum_rate_from_given_and_base(given_price, buy_price) {
return RATE_MULTIPLIER * (given_price - 0.99999) / buy_price;
}
maximum_rate_from_given_and_base(given_price, buy_price) {
return RATE_MULTIPLIER * (given_price + 0.00001) / buy_price;
}
rate_range_from_given_and_base(given_price, buy_price) {
return [
this.minimum_rate_from_given_and_base(given_price, buy_price),
this.maximum_rate_from_given_and_base(given_price, buy_price)
];
}
get_price(rate, basePrice) {
return this.intceil(rate * basePrice / RATE_MULTIPLIER);
}
* multiply_generator_probability(generator, probability) {
for (const it of generator) {
yield {...it, probability: it.probability * probability};
}
}
/*
* This corresponds to the code:
* for (int i = start; i < start + length; i++)
* {
* sellPrices[work++] =
* intceil(randfloat(rate_min / RATE_MULTIPLIER, rate_max / RATE_MULTIPLIER) * basePrice);
* }
*
* Would return the conditional probability given the given_prices, and modify
* the predicted_prices array.
* If the given_prices won't match, returns 0.
*/
generate_individual_random_price(
given_prices, predicted_prices, start, length, rate_min, rate_max) {
rate_min *= RATE_MULTIPLIER;
rate_max *= RATE_MULTIPLIER;
const buy_price = given_prices[0];
const rate_range = [rate_min, rate_max];
let prob = 1;
for (let i = start; i < start + length; i++) {
let min_pred = this.get_price(rate_min, buy_price);
let max_pred = this.get_price(rate_max, buy_price);
if (!isNaN(given_prices[i])) {
if (given_prices[i] < min_pred - this.fudge_factor || given_prices[i] > max_pred + this.fudge_factor) {
// Given price is out of predicted range, so this is the wrong pattern
return 0;
}
// TODO: How to deal with probability when there's fudge factor?
// Clamp the value to be in range now so the probability won't be totally biased to fudged values.
const real_rate_range =
this.rate_range_from_given_and_base(clamp(given_prices[i], min_pred, max_pred), buy_price);
prob *= range_intersect_length(rate_range, real_rate_range) /
range_length(rate_range);
min_pred = given_prices[i];
max_pred = given_prices[i];
}
predicted_prices.push({
min: min_pred,
max: max_pred,
});
}
return prob;
}
/*
* This corresponds to the code:
* rate = randfloat(start_rate_min, start_rate_max);
* for (int i = start; i < start + length; i++)
* {
* sellPrices[work++] = intceil(rate * basePrice);
* rate -= randfloat(rate_decay_min, rate_decay_max);
* }
*
* Would return the conditional probability given the given_prices, and modify
* the predicted_prices array.
* If the given_prices won't match, returns 0.
*/
generate_decreasing_random_price(
given_prices, predicted_prices, start, length, start_rate_min,
start_rate_max, rate_decay_min, rate_decay_max) {
start_rate_min *= RATE_MULTIPLIER;
start_rate_max *= RATE_MULTIPLIER;
rate_decay_min *= RATE_MULTIPLIER;
rate_decay_max *= RATE_MULTIPLIER;
const buy_price = given_prices[0];
let rate_pdf = new PDF(start_rate_min, start_rate_max);
let prob = 1;
for (let i = start; i < start + length; i++) {
let min_pred = this.get_price(rate_pdf.min_value(), buy_price);
let max_pred = this.get_price(rate_pdf.max_value(), buy_price);
if (!isNaN(given_prices[i])) {
if (given_prices[i] < min_pred - this.fudge_factor || given_prices[i] > max_pred + this.fudge_factor) {
// Given price is out of predicted range, so this is the wrong pattern
return 0;
}
// TODO: How to deal with probability when there's fudge factor?
// Clamp the value to be in range now so the probability won't be totally biased to fudged values.
const real_rate_range =
this.rate_range_from_given_and_base(clamp(given_prices[i], min_pred, max_pred), buy_price);
prob *= rate_pdf.range_limit(real_rate_range);
if (prob == 0) {
return 0;
}
min_pred = given_prices[i];
max_pred = given_prices[i];
}
predicted_prices.push({
min: min_pred,
max: max_pred,
});
rate_pdf.decay(rate_decay_min, rate_decay_max);
}
return prob;
}
/*
* This corresponds to the code:
* rate = randfloat(rate_min, rate_max);
* sellPrices[work++] = intceil(randfloat(rate_min, rate) * basePrice) - 1;
* sellPrices[work++] = intceil(rate * basePrice);
* sellPrices[work++] = intceil(randfloat(rate_min, rate) * basePrice) - 1;
*
* Would return the conditional probability given the given_prices, and modify
* the predicted_prices array.
* If the given_prices won't match, returns 0.
*/
generate_peak_price(
given_prices, predicted_prices, start, rate_min, rate_max) {
rate_min *= RATE_MULTIPLIER;
rate_max *= RATE_MULTIPLIER;
const buy_price = given_prices[0];
let prob = 1;
let rate_range = [rate_min, rate_max];
// * Calculate the probability first.
// Prob(middle_price)
const middle_price = given_prices[start + 1];
if (!isNaN(middle_price)) {
const min_pred = this.get_price(rate_min, buy_price);
const max_pred = this.get_price(rate_max, buy_price);
if (middle_price < min_pred - this.fudge_factor || middle_price > max_pred + this.fudge_factor) {
// Given price is out of predicted range, so this is the wrong pattern
return 0;
}
// TODO: How to deal with probability when there's fudge factor?
// Clamp the value to be in range now so the probability won't be totally biased to fudged values.
const real_rate_range =
this.rate_range_from_given_and_base(clamp(middle_price, min_pred, max_pred), buy_price);
prob *= range_intersect_length(rate_range, real_rate_range) /
range_length(rate_range);
if (prob == 0) {
return 0;
}
rate_range = range_intersect(rate_range, real_rate_range);
}
const left_price = given_prices[start];
const right_price = given_prices[start + 2];
// Prob(left_price | middle_price), Prob(right_price | middle_price)
//
// A = rate_range[0], B = rate_range[1], C = rate_min, X = rate, Y = randfloat(rate_min, rate)
// rate = randfloat(A, B); sellPrices[work++] = intceil(randfloat(C, rate) * basePrice) - 1;
//
// => X->U(A,B), Y->U(C,X), Y-C->U(0,X-C), Y-C->U(0,1)*(X-C), Y-C->U(0,1)*U(A-C,B-C),
// let Z=Y-C, Z1=A-C, Z2=B-C, Z->U(0,1)*U(Z1,Z2)
// Prob(Z<=t) = integral_{x=0}^{1} [min(t/x,Z2)-min(t/x,Z1)]/ (Z2-Z1)
// let F(t, ZZ) = integral_{x=0}^{1} min(t/x, ZZ)
// 1. if ZZ < t, then min(t/x, ZZ) = ZZ -> F(t, ZZ) = ZZ
// 2. if ZZ >= t, then F(t, ZZ) = integral_{x=0}^{t/ZZ} ZZ + integral_{x=t/ZZ}^{1} t/x
// = t - t log(t/ZZ)
// Prob(Z<=t) = (F(t, Z2) - F(t, Z1)) / (Z2 - Z1)
// Prob(Y<=t) = Prob(Z>=t-C)
for (const price of [left_price, right_price]) {
if (isNaN(price)) {
continue;
}
const min_pred = this.get_price(rate_min, buy_price) - 1;
const max_pred = this.get_price(rate_range[1], buy_price) - 1;
if (price < min_pred - this.fudge_factor || price > max_pred + this.fudge_factor) {
// Given price is out of predicted range, so this is the wrong pattern
return 0;
}
// TODO: How to deal with probability when there's fudge factor?
// Clamp the value to be in range now so the probability won't be totally biased to fudged values.
const rate2_range = this.rate_range_from_given_and_base(clamp(price, min_pred, max_pred)+ 1, buy_price);
const F = (t, ZZ) => {
if (t <= 0) {
return 0;
}
return ZZ < t ? ZZ : t - t * (Math.log(t) - Math.log(ZZ));
};
const [A, B] = rate_range;
const C = rate_min;
const Z1 = A - C;
const Z2 = B - C;
const PY = (t) => (F(t - C, Z2) - F(t - C, Z1)) / (Z2 - Z1);
prob *= PY(rate2_range[1]) - PY(rate2_range[0]);
if (prob == 0) {
return 0;
}
}
// * Then generate the real predicted range.
// We're doing things in different order then how we calculate probability,
// since forward prediction is more useful here.
//
// Main spike 1
let min_pred = this.get_price(rate_min, buy_price) - 1;
let max_pred = this.get_price(rate_max, buy_price) - 1;
if (!isNaN(given_prices[start])) {
min_pred = given_prices[start];
max_pred = given_prices[start];
}
predicted_prices.push({
min: min_pred,
max: max_pred,
});
// Main spike 2
min_pred = predicted_prices[start].min;
max_pred = this.get_price(rate_max, buy_price);
if (!isNaN(given_prices[start + 1])) {
min_pred = given_prices[start + 1];
max_pred = given_prices[start + 1];
}
predicted_prices.push({
min: min_pred,
max: max_pred,
});
// Main spike 3
min_pred = this.get_price(rate_min, buy_price) - 1;
max_pred = predicted_prices[start + 1].max - 1;
if (!isNaN(given_prices[start + 2])) {
min_pred = given_prices[start + 2];
max_pred = given_prices[start + 2];
}
predicted_prices.push({
min: min_pred,
max: max_pred,
});
return prob;
}
* generate_pattern_0_with_lengths(
given_prices, high_phase_1_len, dec_phase_1_len, high_phase_2_len,
dec_phase_2_len, high_phase_3_len) {
/*
// PATTERN 0: high, decreasing, high, decreasing, high
work = 2;
// high phase 1
for (int i = 0; i < hiPhaseLen1; i++)
{
sellPrices[work++] = intceil(randfloat(0.9, 1.4) * basePrice);
}
// decreasing phase 1
rate = randfloat(0.8, 0.6);
for (int i = 0; i < decPhaseLen1; i++)
{
sellPrices[work++] = intceil(rate * basePrice);
rate -= 0.04;
rate -= randfloat(0, 0.06);
}
// high phase 2
for (int i = 0; i < (hiPhaseLen2and3 - hiPhaseLen3); i++)
{
sellPrices[work++] = intceil(randfloat(0.9, 1.4) * basePrice);
}
// decreasing phase 2
rate = randfloat(0.8, 0.6);
for (int i = 0; i < decPhaseLen2; i++)
{
sellPrices[work++] = intceil(rate * basePrice);
rate -= 0.04;
rate -= randfloat(0, 0.06);
}
// high phase 3
for (int i = 0; i < hiPhaseLen3; i++)
{
sellPrices[work++] = intceil(randfloat(0.9, 1.4) * basePrice);
}
*/
const buy_price = given_prices[0];
const predicted_prices = [
{
min: buy_price,
max: buy_price,
},
{
min: buy_price,
max: buy_price,
},
];
let probability = 1;
// High Phase 1
probability *= this.generate_individual_random_price(
given_prices, predicted_prices, 2, high_phase_1_len, 0.9, 1.4);
if (probability == 0) {
return;
}
// Dec Phase 1
probability *= this.generate_decreasing_random_price(
given_prices, predicted_prices, 2 + high_phase_1_len, dec_phase_1_len,
0.6, 0.8, 0.04, 0.1);
if (probability == 0) {
return;
}
// High Phase 2
probability *= this.generate_individual_random_price(given_prices, predicted_prices,
2 + high_phase_1_len + dec_phase_1_len, high_phase_2_len, 0.9, 1.4);
if (probability == 0) {
return;
}
// Dec Phase 2
probability *= this.generate_decreasing_random_price(
given_prices, predicted_prices,
2 + high_phase_1_len + dec_phase_1_len + high_phase_2_len,
dec_phase_2_len, 0.6, 0.8, 0.04, 0.1);
if (probability == 0) {
return;
}
// High Phase 3
if (2 + high_phase_1_len + dec_phase_1_len + high_phase_2_len + dec_phase_2_len + high_phase_3_len != 14) {
throw new Error("Phase lengths don't add up");
}
const prev_length = 2 + high_phase_1_len + dec_phase_1_len +
high_phase_2_len + dec_phase_2_len;
probability *= this.generate_individual_random_price(
given_prices, predicted_prices, prev_length, 14 - prev_length, 0.9, 1.4);
if (probability == 0) {
return;
}
yield {
pattern_number: 0,
prices: predicted_prices,
probability,
};
}
* generate_pattern_0(given_prices) {
/*
decPhaseLen1 = randbool() ? 3 : 2;
decPhaseLen2 = 5 - decPhaseLen1;
hiPhaseLen1 = randint(0, 6);
hiPhaseLen2and3 = 7 - hiPhaseLen1;
hiPhaseLen3 = randint(0, hiPhaseLen2and3 - 1);
*/
for (var dec_phase_1_len = 2; dec_phase_1_len < 4; dec_phase_1_len++) {
for (var high_phase_1_len = 0; high_phase_1_len < 7; high_phase_1_len++) {
for (var high_phase_3_len = 0; high_phase_3_len < (7 - high_phase_1_len - 1 + 1); high_phase_3_len++) {
yield* this.multiply_generator_probability(
this.generate_pattern_0_with_lengths(given_prices, high_phase_1_len, dec_phase_1_len, 7 - high_phase_1_len - high_phase_3_len, 5 - dec_phase_1_len, high_phase_3_len),
1 / (4 - 2) / 7 / (7 - high_phase_1_len));
}
}
}
}
* generate_pattern_1_with_peak(given_prices, peak_start) {
/*
// PATTERN 1: decreasing middle, high spike, random low
peakStart = randint(3, 9);
rate = randfloat(0.9, 0.85);
for (work = 2; work < peakStart; work++)
{
sellPrices[work] = intceil(rate * basePrice);
rate -= 0.03;
rate -= randfloat(0, 0.02);
}
sellPrices[work++] = intceil(randfloat(0.9, 1.4) * basePrice);
sellPrices[work++] = intceil(randfloat(1.4, 2.0) * basePrice);
sellPrices[work++] = intceil(randfloat(2.0, 6.0) * basePrice);
sellPrices[work++] = intceil(randfloat(1.4, 2.0) * basePrice);
sellPrices[work++] = intceil(randfloat(0.9, 1.4) * basePrice);
for (; work < 14; work++)
{
sellPrices[work] = intceil(randfloat(0.4, 0.9) * basePrice);
}
*/
const buy_price = given_prices[0];
const predicted_prices = [
{
min: buy_price,
max: buy_price,
},
{
min: buy_price,
max: buy_price,
},
];
let probability = 1;
probability *= this.generate_decreasing_random_price(
given_prices, predicted_prices, 2, peak_start - 2, 0.85, 0.9, 0.03, 0.05);
if (probability == 0) {
return;
}
// Now each day is independent of next
let min_randoms = [0.9, 1.4, 2.0, 1.4, 0.9, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4];
let max_randoms = [1.4, 2.0, 6.0, 2.0, 1.4, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9];
for (let i = peak_start; i < 14; i++) {
probability *= this.generate_individual_random_price(
given_prices, predicted_prices, i, 1, min_randoms[i - peak_start],
max_randoms[i - peak_start]);
if (probability == 0) {
return;
}
}
yield {
pattern_number: 1,
prices: predicted_prices,
probability,
};
}
* generate_pattern_1(given_prices) {
for (var peak_start = 3; peak_start < 10; peak_start++) {
yield* this.multiply_generator_probability(this.generate_pattern_1_with_peak(given_prices, peak_start), 1 / (10 - 3));
}
}
* generate_pattern_2(given_prices) {
/*
// PATTERN 2: consistently decreasing
rate = 0.9;
rate -= randfloat(0, 0.05);
for (work = 2; work < 14; work++)
{
sellPrices[work] = intceil(rate * basePrice);
rate -= 0.03;
rate -= randfloat(0, 0.02);
}
break;
*/
const buy_price = given_prices[0];
const predicted_prices = [
{
min: buy_price,
max: buy_price,
},
{
min: buy_price,
max: buy_price,
},
];
let probability = 1;
probability *= this.generate_decreasing_random_price(
given_prices, predicted_prices, 2, 14 - 2, 0.85, 0.9, 0.03, 0.05);
if (probability == 0) {
return;
}
yield {
pattern_number: 2,
prices: predicted_prices,
probability,
};
}
* generate_pattern_3_with_peak(given_prices, peak_start) {
/*
// PATTERN 3: decreasing, spike, decreasing
peakStart = randint(2, 9);
// decreasing phase before the peak
rate = randfloat(0.9, 0.4);
for (work = 2; work < peakStart; work++)
{
sellPrices[work] = intceil(rate * basePrice);
rate -= 0.03;
rate -= randfloat(0, 0.02);
}
sellPrices[work++] = intceil(randfloat(0.9, 1.4) * (float)basePrice);
sellPrices[work++] = intceil(randfloat(0.9, 1.4) * basePrice);
rate = randfloat(1.4, 2.0);
sellPrices[work++] = intceil(randfloat(1.4, rate) * basePrice) - 1;
sellPrices[work++] = intceil(rate * basePrice);
sellPrices[work++] = intceil(randfloat(1.4, rate) * basePrice) - 1;
// decreasing phase after the peak
if (work < 14)
{
rate = randfloat(0.9, 0.4);
for (; work < 14; work++)
{
sellPrices[work] = intceil(rate * basePrice);
rate -= 0.03;
rate -= randfloat(0, 0.02);
}
}
*/
const buy_price = given_prices[0];
const predicted_prices = [
{
min: buy_price,
max: buy_price,
},
{
min: buy_price,
max: buy_price,
},
];
let probability = 1;
probability *= this.generate_decreasing_random_price(
given_prices, predicted_prices, 2, peak_start - 2, 0.4, 0.9, 0.03, 0.05);
if (probability == 0) {
return;
}
// The peak
probability *= this.generate_individual_random_price(
given_prices, predicted_prices, peak_start, 2, 0.9, 1.4);
if (probability == 0) {
return;
}
probability *= this.generate_peak_price(
given_prices, predicted_prices, peak_start + 2, 1.4, 2.0);
if (probability == 0) {
return;
}
if (peak_start + 5 < 14) {
probability *= this.generate_decreasing_random_price(
given_prices, predicted_prices, peak_start + 5, 14 - (peak_start + 5),
0.4, 0.9, 0.03, 0.05);
if (probability == 0) {
return;
}
}
yield {
pattern_number: 3,
prices: predicted_prices,
probability,
};
}
* generate_pattern_3(given_prices) {
for (let peak_start = 2; peak_start < 10; peak_start++) {
yield* this.multiply_generator_probability(this.generate_pattern_3_with_peak(given_prices, peak_start), 1 / (10 - 2));
}
}
get_transition_probability(previous_pattern) {
if (typeof previous_pattern === 'undefined' || Number.isNaN(previous_pattern) || previous_pattern === null || previous_pattern < 0 || previous_pattern > 3) {
// Use the steady state probabilities of PROBABILITY_MATRIX if we don't
// know what the previous pattern was.
// See https://github.com/mikebryant/ac-nh-turnip-prices/issues/68
// and https://github.com/mikebryant/ac-nh-turnip-prices/pull/90
// for more information.
return [4530/13082, 3236/13082, 1931/13082, 3385/13082];
}
return PROBABILITY_MATRIX[previous_pattern];
}
* generate_all_patterns(sell_prices, previous_pattern) {
const generate_pattern_fns = [this.generate_pattern_0, this.generate_pattern_1, this.generate_pattern_2, this.generate_pattern_3];
const transition_probability = this.get_transition_probability(previous_pattern);
for (let i = 0; i < 4; i++) {
yield* this.multiply_generator_probability(generate_pattern_fns[i].bind(this)(sell_prices), transition_probability[i]);
}
}
* generate_possibilities(sell_prices, first_buy, previous_pattern) {
if (first_buy || isNaN(sell_prices[0])) {
for (var buy_price = 90; buy_price <= 110; buy_price++) {
const temp_sell_prices = sell_prices.slice();
temp_sell_prices[0] = temp_sell_prices[1] = buy_price;
if (first_buy) {
yield* this.generate_pattern_3(temp_sell_prices);
} else {
// All buy prices are equal probability and we're at the outmost layer,
// so don't need to multiply_generator_probability here.
yield* this.generate_all_patterns(temp_sell_prices, previous_pattern);
}
}
} else {
yield* this.generate_all_patterns(sell_prices, previous_pattern);
}
}
analyze_possibilities() {
const sell_prices = this.prices;
const first_buy = this.first_buy;
const previous_pattern = this.previous_pattern;
let generated_possibilities = [];
for (let i = 0; i < 6; i++) {
this.fudge_factor = i;
generated_possibilities = Array.from(this.generate_possibilities(sell_prices, first_buy, previous_pattern));
if (generated_possibilities.length > 0) {
console.log("Generated possibilities using fudge factor %d: ", i, generated_possibilities);
break;
}
}
const total_probability = generated_possibilities.reduce((acc, it) => acc + it.probability, 0);
for (const it of generated_possibilities) {
it.probability /= total_probability;
}
for (let poss of generated_possibilities) {
var weekMins = [];
var weekMaxes = [];
for (let day of poss.prices.slice(2)) {
// Check for a future date by checking for a range of prices
if(day.min !== day.max){
weekMins.push(day.min);
weekMaxes.push(day.max);
} else {
// If we find a set price after one or more ranged prices, the user has missed a day. Discard that data and start again.
weekMins = [];
weekMaxes = [];
}
}
if (!weekMins.length && !weekMaxes.length) {
weekMins.push(poss.prices[poss.prices.length -1].min);
weekMaxes.push(poss.prices[poss.prices.length -1].max);
}
poss.weekGuaranteedMinimum = Math.max(...weekMins);
poss.weekMax = Math.max(...weekMaxes);
}
let category_totals = {};
for (let i of [0, 1, 2, 3]) {
category_totals[i] = generated_possibilities
.filter(value => value.pattern_number == i)
.map(value => value.probability)
.reduce((previous, current) => previous + current, 0);
}
for (let pos of generated_possibilities) {
pos.category_total_probability = category_totals[pos.pattern_number];
}
generated_possibilities.sort((a, b) => {
return b.category_total_probability - a.category_total_probability || b.probability - a.probability;
});
let global_min_max = [];
for (let day = 0; day < 14; day++) {
const prices = {
min: 999,
max: 0,
};
for (let poss of generated_possibilities) {
if (poss.prices[day].min < prices.min) {
prices.min = poss.prices[day].min;
}
if (poss.prices[day].max > prices.max) {
prices.max = poss.prices[day].max;
}
}
global_min_max.push(prices);
}
generated_possibilities.unshift({
pattern_number: 4,
prices: global_min_max,
weekGuaranteedMinimum: Math.min(...generated_possibilities.map(poss => poss.weekGuaranteedMinimum)),
weekMax: Math.max(...generated_possibilities.map(poss => poss.weekMax))
});
return generated_possibilities;
}
}

View File

@ -1,418 +0,0 @@
//Reusable Fields
const getSellFields = function () {
let fields = [];
var now = new Date();
for (var i = 2; i < 14; i++) {
fields.push($("#sell_" + i)[0]);
if (i == now.getDay() * 2 + (now.getHours() >= 12 ? 1 : 0)) {
fields[fields.length - 1].classList.add("now");
}
}
if (now.getDay() == 0) {
buy_input[0].classList.add("now");
}
return fields;
};
const getFirstBuyRadios = function () {
return [
$("#first-time-radio-no")[0],
$("#first-time-radio-yes")[0]
];
};
const getPreviousPatternRadios = function () {
return [
$("#pattern-radio-unknown")[0],
$("#pattern-radio-fluctuating")[0],
$("#pattern-radio-small-spike")[0],
$("#pattern-radio-large-spike")[0],
$("#pattern-radio-decreasing")[0]
];
};
const getCheckedRadio = function (radio_array) {
return radio_array.find(radio => radio.checked === true).value;
};
const checkRadioByValue = function (radio_array, value) {
if (value === null) {
return;
}
value = value.toString();
radio_array.find(radio => radio.value == value).checked = true;
};
const state = {
initialized: false,
};
const buy_input = $("#buy");
const sell_inputs = getSellFields();
const first_buy_radios = getFirstBuyRadios();
const previous_pattern_radios = getPreviousPatternRadios();
const permalink_input = $('#permalink-input');
const permalink_button = $('#permalink-btn');
const snackbar = $('#snackbar');
//Functions
const fillFields = function (prices, first_buy, previous_pattern) {
checkRadioByValue(first_buy_radios, first_buy);
checkRadioByValue(previous_pattern_radios, previous_pattern);
buy_input.focus();
buy_input.val(prices[0] || '');
buy_input.blur();
const sell_prices = prices.slice(2);
sell_prices.forEach((price, index) => {
if (!price) {
return;
} else {
const element = $("#sell_" + (index + 2));
element.focus();
element.val(price);
element.blur();
}
});
};
const initialize = function () {
try {
const previous = getPrevious();
const first_buy = previous[0];
const previous_pattern = previous[1];
const prices = previous[2];
if (prices === null) {
fillFields([], first_buy, previous_pattern);
} else {
fillFields(prices, first_buy, previous_pattern);
}
} catch (e) {
console.error(e);
}
$(document).trigger("input");
$("#permalink-btn").on("click", copyPermalink);
$("#reset").on("click", function () {
if (window.confirm(i18next.t("prices.reset-warning"))) {
sell_inputs.forEach(input => input.value = '');
fillFields([], false, -1);
update();
}
});
console.log('finished initializing');
state.initialized = true;
};
const updateLocalStorage = function (prices, first_buy, previous_pattern) {
try {
if (prices.length !== 14) throw "The data array needs exactly 14 elements to be valid";
localStorage.setItem("sell_prices", JSON.stringify(prices));
localStorage.setItem("first_buy", JSON.stringify(first_buy));
localStorage.setItem("previous_pattern", JSON.stringify(previous_pattern));
} catch (e) {
console.error(e);
}
};
const isEmpty = function (arr) {
const filtered = arr.filter(value => value !== null && value !== '' && !isNaN(value));
return filtered.length == 0;
};
const getFirstBuyStateFromQuery = function (param) {
try {
const params = new URLSearchParams(window.location.search.substr(1));
const firstbuy_str = params.get(param);
if (firstbuy_str == null) {
return null;
}
firstbuy = null;
if (firstbuy_str == "1" || firstbuy_str == "yes" || firstbuy_str == "true") {
firstbuy = true;
} else if (firstbuy_str == "0" || firstbuy_str == "no" || firstbuy_str == "false") {
firstbuy = false;
}
return firstbuy;
} catch (e) {
return null;
}
};
const getFirstBuyStateFromLocalstorage = function () {
return JSON.parse(localStorage.getItem('first_buy'));
};
const getPreviousPatternStateFromLocalstorage = function () {
return JSON.parse(localStorage.getItem('previous_pattern'));
};
const getPreviousPatternStateFromQuery = function (param) {
try {
const params = new URLSearchParams(window.location.search.substr(1));
const pattern_str = params.get(param);
if (pattern_str == null) {
return null;
}
if (pattern_str == "0" || pattern_str == "fluctuating") {
pattern = 0;
} else if (pattern_str == "1" || pattern_str == "large-spike") {
pattern = 1;
} else if (pattern_str == "2" || pattern_str == "decreasing") {
pattern = 2;
} else if (pattern_str == "3" || pattern_str == "small-spike") {
pattern = 3;
} else {
pattern = -1;
}
return pattern;
} catch (e) {
return null;
}
};
const getPricesFromLocalstorage = function () {
try {
const sell_prices = JSON.parse(localStorage.getItem("sell_prices"));
if (!Array.isArray(sell_prices) || sell_prices.length !== 14) {
return null;
}
return sell_prices;
} catch (e) {
return null;
}
};
const getPricesFromQuery = function (param) {
try {
const params = new URLSearchParams(window.location.search.substr(1));
const sell_prices = params.get(param).split(".").map((x) => parseInt(x, 10));
if (!Array.isArray(sell_prices)) {
return null;
}
// Parse the array which is formatted like: [price, M-AM, M-PM, T-AM, T-PM, W-AM, W-PM, Th-AM, Th-PM, F-AM, F-PM, S-AM, S-PM, Su-AM, Su-PM]
// due to the format of local storage we need to double up the price at the start of the array.
sell_prices.unshift(sell_prices[0]);
// This allows us to fill out the missing fields at the end of the array
for (let i = sell_prices.length; i < 14; i++) {
sell_prices.push(0);
}
return sell_prices;
} catch (e) {
return null;
}
};
const getPreviousFromQuery = function () {
/* Check if valid prices are entered. Exit immediately if not. */
const prices = getPricesFromQuery("prices");
if (prices == null) {
return null;
}
console.log("Using data from query.");
window.populated_from_query = true;
return [
getFirstBuyStateFromQuery("first"),
getPreviousPatternStateFromQuery("pattern"),
prices
];
};
const getPreviousFromLocalstorage = function () {
return [
getFirstBuyStateFromLocalstorage(),
getPreviousPatternStateFromLocalstorage(),
getPricesFromLocalstorage()
];
};
/**
* Gets previous values. First tries to parse parameters,
* if none of them match then it looks in local storage.
* @return {[first time, previous pattern, prices]}
*/
const getPrevious = function () {
return getPreviousFromQuery() || getPreviousFromLocalstorage();
};
const getSellPrices = function () {
//Checks all sell inputs and returns an array with their values
return res = sell_inputs.map(function (input) {
return parseInt(input.value || '');
});
};
const getPriceClass = function(buy_price, max) {
const priceBrackets = [200, 30, 0, -30, -99];
let diff = max - buy_price;
for(var i=0; i<priceBrackets.length; i++) {
if(diff >= priceBrackets[i]) {
return "range" + i;
}
}
return "";
};
const displayPercentage = function(fraction) {
if (Number.isFinite(fraction)) {
let percent = fraction * 100;
if (percent >= 1) {
return percent.toPrecision(3) + '%';
} else if (percent >= 0.01) {
return percent.toFixed(2) + '%';
} else {
return '<0.01%';
}
} else {
return '—';
}
};
const hideChart = function() {
$("#output").html("");
$(".chart-wrapper").hide()
}
const calculateOutput = function (data, first_buy, previous_pattern) {
if (isEmpty(data)) {
hideChart()
return;
}
let pat_desc = {0:"fluctuating", 1:"large-spike", 2:"decreasing", 3:"small-spike", 4:"all"};
let output_possibilities = "";
let predictor = new Predictor(data, first_buy, previous_pattern);
let analyzed_possibilities = predictor.analyze_possibilities();
if (analyzed_possibilities[0].weekGuaranteedMinimum === Number.POSITIVE_INFINITY) {
hideChart()
$(".error:hidden").show()
return;
}
$(".error:visible").hide()
$(".chart-wrapper:hidden").show()
let buy_price = parseInt(buy_input.val());
previous_pattern_number = "";
for (let poss of analyzed_possibilities) {
var out_line = "<tr><td class='table-pattern'>" + i18next.t("patterns." + pat_desc[poss.pattern_number]) + "</td>";
const style_price = buy_price || poss.prices[0].min;
if (previous_pattern_number != poss.pattern_number) {
previous_pattern_number = poss.pattern_number;
pattern_count = analyzed_possibilities
.filter(val => val.pattern_number == poss.pattern_number)
.length;
out_line += `<td rowspan=${pattern_count}>${displayPercentage(poss.category_total_probability)}</td>`;
}
out_line += `<td>${displayPercentage(poss.probability)}</td>`;
for (let day of poss.prices.slice(2)) {
let price_class = getPriceClass(style_price, day.max);
if (day.min !== day.max) {
out_line += `<td class='${price_class}'>${day.min} ${i18next.t("output.to")} ${day.max}</td>`;
} else {
out_line += `<td class='${price_class}'>${day.min}</td>`;
}
}
var min_class = getPriceClass(style_price, poss.weekGuaranteedMinimum);
var max_class = getPriceClass(style_price, poss.weekMax);
out_line += `<td class='${min_class}'>${poss.weekGuaranteedMinimum}</td><td class='${max_class}'>${poss.weekMax}</td></tr>`;
output_possibilities += out_line;
}
$("#output").html(output_possibilities);
update_chart(data, analyzed_possibilities);
};
const generatePermalink = function (buy_price, sell_prices, first_buy, previous_pattern) {
let searchParams = new URLSearchParams();
let pricesParam = buy_price ? buy_price.toString() : '';
if (!isEmpty(sell_prices)) {
const filtered = sell_prices.map(price => isNaN(price) ? '' : price).join('.');
pricesParam = pricesParam.concat('.', filtered);
}
if (pricesParam) {
searchParams.append('prices', pricesParam);
}
if (first_buy) {
searchParams.append('first', true);
}
if (previous_pattern !== -1) {
searchParams.append('pattern', previous_pattern);
}
return searchParams.toString() && window.location.origin.concat('?', searchParams.toString());
};
const copyPermalink = function () {
let text = permalink_input[0];
permalink_input.show();
text.select();
text.setSelectionRange(0, 99999); /* for mobile devices */
document.execCommand('copy');
permalink_input.hide();
flashMessage(i18next.t("prices.permalink-copied"));
};
const flashMessage = function(message) {
snackbar.text(message);
snackbar.addClass('show');
setTimeout(function () {
snackbar.removeClass('show');
snackbar.text('');
}, 3000);
};
const update = function () {
if(!state.initialized){
console.log('update function called before initial data load');
// calls to update before the previous data has been initialized / loaded will reset the data.
return;
}
const sell_prices = getSellPrices();
const buy_price = parseInt(buy_input.val());
const first_buy = getCheckedRadio(first_buy_radios) == 'true';
const previous_pattern = parseInt(getCheckedRadio(previous_pattern_radios));
const permalink = generatePermalink(buy_price, sell_prices, first_buy, previous_pattern);
if (permalink) {
permalink_button.show();
} else {
permalink_button.hide();
}
permalink_input.val(permalink);
const prices = [buy_price, buy_price, ...sell_prices];
if (!window.populated_from_query) {
updateLocalStorage(prices, first_buy, previous_pattern);
}
calculateOutput(prices, first_buy, previous_pattern);
};

View File

@ -1,58 +0,0 @@
function updateTheme(theme) {
if (theme == "auto") {
theme = (window.matchMedia && window.matchMedia("(prefers-color-scheme: dark)").matches) ? "dark" : "light";
}
if (theme != "light") {
document.documentElement.setAttribute("data-theme", theme);
} else {
document.documentElement.removeAttribute("data-theme");
}
if (chart_instance && chart_options) {
chart_instance.options = chart_options;
chart_instance.update();
}
}
function setupTheming() {
const themeSelector = $("#theme");
const supportsAutoTheming = (window.matchMedia && window.matchMedia("(prefers-color-scheme)").matches);
let preferredTheme = localStorage.getItem("theme");
let selectorVal = preferredTheme ? preferredTheme :
supportsAutoTheming ? "auto" : "light";
// Build theme option menu.
if (supportsAutoTheming) {
themeSelector.append(`<option value="auto">${i18next.t('textbox.theme.auto')}</option>`);
}
themeSelector.append(`<option value="light">${i18next.t('textbox.theme.light')}</option>`);
themeSelector.append(`<option value="dark">${i18next.t('textbox.theme.dark')}</option>`);
themeSelector.val(selectorVal);
// Listen to system changes in theme
window.matchMedia("(prefers-color-scheme: dark)").addListener(() => {
if (preferredTheme && preferredTheme != "auto") { return; }
updateTheme("auto");
});
// Preference listener
themeSelector.on('change', function () {
preferredTheme = this.value;
updateTheme(preferredTheme);
if ((preferredTheme != "light" && !supportsAutoTheming) ||
(preferredTheme != "auto" && supportsAutoTheming)) {
localStorage.setItem("theme", preferredTheme);
} else {
localStorage.removeItem("theme");
}
});
}
$(document).ready(function() {
i18next.init((err, t) => {
setupTheming();
});
});

View File

@ -1,75 +0,0 @@
function updateContent() {
update();
$('body').localize();
}
const defaultLanguage = 'en';
const LANGUAGES = {
'ca': 'Català',
'cs': 'Česky',
'de': 'Deutsch',
'en': 'English',
'es': 'Español',
'fr': 'Français',
'gl': 'Galego',
'hu': 'magyar',
'id': 'Bahasa Indonesia',
'it': 'Italiano',
'ja': '日本語',
'ko': '한국어',
'nl': 'Nederlands',
'ph': 'Filipino',
'pl': 'Polski',
'pt-BR': 'Português',
'ru': 'Русский',
'ua': 'Українська',
'th': 'ไทย',
'zh-CN': '简体中文',
'zh-TW': '繁體中文'
};
i18next
.use(i18nextXHRBackend)
.use(i18nextBrowserLanguageDetector)
.init({
fallbackLng: defaultLanguage,
debug: true,
backend: {
loadPath: 'locales/{{lng}}.json',
},
}, (err, t) => {
languageSelector = $('#language');
for (let [code, name] of Object.entries(LANGUAGES)) {
languageSelector.append(`<option value="${code}">${name}</option>`);
}
for (let code of i18next.languages) {
if (code in LANGUAGES) {
languageSelector.val(code);
$('html').attr('lang', code);
break;
}
}
languageSelector.on('change', function () {
if (this.value == i18next.language)
return;
i18next.changeLanguage(this.value);
$('html').attr('lang', this.value);
});
jqueryI18next.init(i18next, $);
i18next.on('languageChanged', lng => {
updateContent();
});
// init set content
$(document).ready(initialize);
let delayTimer;
$(document).on('input', function(event) {
//prevent radio input from updating content twice per input change
if(event.target.type === 'radio'){ return }
// adding short delay after input to help mitigate potential lag after keystrokes
clearTimeout(delayTimer);
delayTimer = setTimeout(function() {
updateContent();
}, 500);
});
$('input[type = radio]').on('change', updateContent);
});

View File

@ -1,87 +0,0 @@
{
"general": {
"daisy-mae": "Juliana"
},
"welcome": {
"salutation": "Hola! Et donem la benvinguda a l'app <b>Turnip Prophet</b> pel teu Nookòfon.",
"description": "Aquesta app et permet predir els preus dels naps a la teva illa, però hauràs d'introduir-hi tu els preus passats!",
"conclusion": "Fet això, l'app Turnip Prophet <b>endevinarà</b> els preus que tindràs durant la resta de la setmana."
},
"first-time": {
"title": "Primer cop que compres",
"description": "És la primera vegada que li compres naps a la Juliana a la <b>teva</b> illa?<i>(Afecta al patró de preus)</i>",
"yes": "Sí",
"no": "No"
},
"patterns": {
"title": "Patró anterior",
"description": "Quin patró tenien els teus preus la setmana passada?<i>(Afecta al patró actual)</i>",
"pattern": "Patró",
"all": "Tots els patrons",
"decreasing": "Decreixent",
"fluctuating": "Fluctuant",
"unknown": "No ho sé",
"large-spike": "Pic gran",
"small-spike": "Pic petit"
},
"prices": {
"description": "Quin ha sigut el preu de compra de naps a la teva illa aquesta setmana?",
"open": {
"am": "AM - De les 8:00 am a les 11:59 am",
"pm": "PM - De les 12:00 pm a les 10:00 pm"
},
"copy-permalink": "Copiar permalink",
"permalink-copied": "Permalink copiat!",
"reset": "Reiniciar Turnip Prophet",
"reset-warning": "Segur que vols reiniciar tots els camps?\n\nNo pots desfer aquesta acció!"
},
"weekdays": {
"monday": "Dilluns",
"tuesday": "Dimarts",
"wednesday": "Dimecres",
"thursday": "Dijous",
"friday": "Divendres",
"saturday" : "Dissabte",
"sunday": "Diumenge",
"abr": {
"monday": "Dl",
"tuesday": "Dm",
"wednesday": "Dc",
"thursday": "Dj",
"friday": "Dv",
"saturday" : "Ds"
}
},
"times": {
"morning": "AM",
"afternoon": "PM"
},
"output": {
"title": "Resultat",
"chance": "Probabilitat (%)",
"to": "a",
"minimum": "Mínim garantit",
"maximum": "Màxim potencial",
"chart": {
"input": "Preu d'entrada",
"minimum": "Mínim garantit",
"maximum": "Màxim potencial"
}
},
"textbox": {
"description": "Quan hagis posat els preus dels naps, el Turnip Prophet farà comptes i et mostrarà els possibles patrons que puguin haver a la teva illa.",
"development": "L'app encara està en desenvolupament, però l'anirem millorant!",
"thanks": "Aquest projecte ha estat possible gràcies a en <a href=\"https://twitter.com/_Ninji/status/1244818665851289602?s=20\">Ninji</a>, que va descobrir com calculen en Tendo i en Nendo els preus dels naps.",
"support": "A <a href=\"https://github.com/mikebryant/ac-nh-turnip-prices/issues\">GitHub</a> hi trobaràs suport, comentaris, i contribucions.",
"sponsor": "Vols patrocinar als desenvolupadors del projecte? Ves a <a href=\"https://github.com/mikebryant/ac-nh-turnip-prices#sponsor-button-repo\">GitHub</a> i clica damunt de '❤ Sponsor'",
"contributors-text": "Ah! I no ens oblidem dels que ja han ajudat amb les seves contribucions!",
"contributors": "Contribuidors",
"language": "Llenguatge",
"theme": {
"title": "Tema",
"auto": "Automàtic",
"light": "Clar",
"dark": "Fosc"
}
}
}

View File

@ -1,87 +0,0 @@
{
"general": {
"daisy-mae": "Daisy Mae"
},
"welcome": {
"salutation": "Ahoj, vítej v aplikaci <b>Turnip Prophet</b> tvého Nook Phone.",
"description": "Tahle aplikace by ti měla pomoct sledovat vývoj cen tuřínů na tvém ostrově. Musíš si ale sám zadávat ceny, které už znáš!",
"conclusion": "Po zadání Turnip Prophet <b>kouzelným způsobem</b> předpoví, jak by se ceny měly vyvíjet v průběhu týdne."
},
"first-time": {
"title": "Poprvé kupující",
"description": "Je to poprvé, co kupuješ tuříny od Daisy <b>na vlastním</b> ostrově?<i>(Ovlivňuje model vývoje cen)</i>",
"yes": "Ano",
"no": "Ne"
},
"patterns": {
"title": "Předchozí model",
"description": "Jaký byl model vývoje cen tuřínů na tvém ostrově minulý týden?<i>(Ovlivňuje model vývoje cen)</i>",
"pattern": "Model",
"all": "Všechny modely",
"decreasing": "Klesající",
"fluctuating": "Kolísavý",
"unknown": "Nevím",
"large-spike": "S velkou špicí",
"small-spike": "S malou špicí"
},
"prices": {
"description": "Jaké byly ceny tuřínů v průběhu tohoto týdne?",
"open": {
"am": "dop. - od 8:00 do 11:59",
"pm": "odp. - od 12:00 do 22:00"
},
"copy-permalink": "Kopírovat permalink",
"permalink-copied": "Permalink zkopírován!",
"reset": "Resetovat Turnip Prophet",
"reset-warning": "Opravdu chceš resetovat všechny pole?\n\nNejde to vrátit zpět!"
},
"weekdays": {
"monday": "Pondělí",
"tuesday": "Úterý",
"wednesday": "Středa",
"thursday": "Čtvrtek",
"friday": "Pátek",
"saturday" : "Sobota",
"sunday": "Neděle",
"abr": {
"monday": "Po",
"tuesday": "Út",
"wednesday": "St",
"thursday": "Čt",
"friday": "Pá",
"saturday" : "So"
}
},
"times": {
"morning": "dop.",
"afternoon": "odp."
},
"output": {
"title": "Výstup",
"chance": "Šance %",
"to": "až",
"minimum": "Jisté Minimum",
"maximum": "Možné Maximum",
"chart": {
"input": "Vstupní cena",
"minimum": "Jisté Minimum",
"maximum": "Možné Maximum"
}
},
"textbox": {
"description": "Po zadání několika cen tuřínů, Turnip Prophet provede nějaké výpočty a zobrazí všechny možné modely vývoje cen, které mohou na tvém ostrově nastat.",
"development": "Aplikace je pořád ve vývoji, časem se stále zlepšuje!",
"thanks": "Nic z toho by nebylo možné bez <a href=\"https://twitter.com/_Ninji/status/1244818665851289602?s=20\">Ninjiho výzkumu</a>, jak vlastně Timmy a Tommy hodnotí cenu tuřínů.",
"support": "Podpora, komentáře a příspěvky jsou možné přes <a href=\"https://github.com/mikebryant/ac-nh-turnip-prices/issues\">GitHub</a>",
"sponsor": "Chceš podpořit vývojáře stojící za tímto projektem? Jdi na <a href=\"https://github.com/mikebryant/ac-nh-turnip-prices#sponsor-button-repo\">GitHub</a> a klikni na tlačítko '❤ Sponsor'",
"contributors-text": "Jo! A nesmíme zapomínat poděkovat těm, kteří se na vývoji tohoto projektu zatím podíleli!",
"contributors": "Na projektu se podílí",
"language": "Jazyk",
"theme": {
"title": "Barevné schéma",
"auto": "Automaticky",
"light": "Světlé",
"dark": "Tmavé"
}
}
}

View File

@ -1,81 +0,0 @@
{
"general": {
"daisy-mae": "Jorna"
},
"welcome": {
"salutation": "Hallo, und Willkommen bei der <b>Turnip Prophet</b> App auf deinem Nook Phone.",
"description": "Mit dieser App kannst du die Rübenpreise deiner Insel täglich verfolgen, aber du musst die Preise selbst eingeben!",
"conclusion": "Danach wird die Turnip Prophet App <b>magisch</b> deine Rübenpreise vorhersagen, welche du den Rest der Woche haben wirst."
},
"first-time": {
"title": "Erstmaliger Einkäufer",
"description": "Kaufst du zum ersten Mal Rüben von Jorna auf deiner Insel? <i>(Dies beeinflusst dein Verkaufsmuster)</i>",
"yes": "Ja",
"no": "Nein"
},
"patterns": {
"title": "Vorheriges Verkaufsmuster",
"description": "Wie war das Verkaufsmuster der letzten Woche? <i>(Dies beeinflusst dein Verkaufsmuster)</i>",
"pattern": "Verkaufsmuster",
"all": "Alle Verkaufsmuster",
"decreasing": "Absteigend",
"fluctuating": "Schwankend",
"unknown": "Ich weiß nicht",
"large-spike": "Stark Ansteigend",
"small-spike": "Leicht Ansteigend"
},
"prices": {
"description": "Wie hoch war der Preis für Rüben diese Woche auf deiner Insel?",
"open": {
"am": "Vorm. (Vormittag) - 8:00 Uhr bis 11:59 Uhr",
"pm": "Nachm. (Nachmittag) - 12:00 Uhr bis 22:00 Uhr"
},
"copy-permalink": "Seite teilen",
"permalink-copied": "Seitenlink kopiert!",
"reset": "Eingegebene Daten zurücksetzen",
"reset-warning": "Bist du sicher, dass du deine eingegebenen Daten zurücksetzen möchtest?\n\nDies kann nicht rückgängig gemacht werden!"
},
"weekdays": {
"monday": "Montag",
"tuesday": "Dienstag",
"wednesday": "Mittwoch",
"thursday": "Donnerstag",
"friday": "Freitag",
"saturday" : "Samstag",
"sunday": "Sonntag",
"abr": {
"monday": "Mo",
"tuesday": "Di",
"wednesday": "Mi",
"thursday": "Do",
"friday": "Fr",
"saturday" : "Sa"
}
},
"times": {
"morning": "Vorm.",
"afternoon": "Nachm."
},
"output": {
"title": "Berechnung",
"chance": "% Chance",
"to": "bis",
"minimum": "Garantiertes Minimum",
"maximum": "Potentielles Maximum",
"chart": {
"input": "Eingegebener Preis",
"minimum": "Garantiertes Minimum",
"maximum": "Potentielles Maximum"
}
},
"textbox": {
"description": "Nachdem du einige Rübenpreise eingegeben hast, macht der Turnip Prophet etwas Magie und zeigt dir die verschiedenen möglichen Verkaufsmuster an, die auf deiner Insel auftreten können.",
"development": "Diese App befindet sich noch in der Entwicklung, wird sich aber mit der Zeit verbessern!",
"thanks": "Nichts von all dem wäre möglich gewesen, ohne das <a href=\"https://twitter.com/_Ninji/status/1244818665851289602?s=20\">Ninji</a> herausgefunden hätte, wie Nepp und Schlepp ihre Rübenpreise kalkulieren.",
"support": "Hilfe, Kommentare und Beiträge sind auffindbar über <a href=\"https://github.com/mikebryant/ac-nh-turnip-prices/issues\">GitHub.com</a> (nur in Englisch).",
"sponsor": "Möchtest du die Entwickler hinter diesem Projekt unterstützen? Gehe zu <a href=\"https://github.com/mikebryant/ac-nh-turnip-prices#sponsor-button-repo\">GitHub.com</a> und klicke auf den '❤ Sponsor' Button für mehr Informationen.",
"contributors-text": "Oh! Und vergessen wir nicht, denen zu danken, die bis jetzt dazu beigetragen haben!",
"contributors": "Mitwirkende",
"language": "Sprache"
}
}

View File

@ -1,91 +0,0 @@
{
"general": {
"daisy-mae": "Daisy Mae"
},
"welcome": {
"salutation": "Hello, and welcome to the <b>Turnip Prophet</b> app on your Nook Phone.",
"description": "This app lets you track your island's turnip prices daily, but you'll have to put the prices in yourself!",
"conclusion": "After that, the Turnip Prophet app will <b>magically</b> predict the turnip prices you'll have for the rest of the week."
},
"first-time": {
"title": "First-Time Buyer",
"description": "Is this the first time a resident is buying turnips from Daisy Mae on <b>your own</b> island?<i>(This affects your pattern)</i>",
"yes": "Yes",
"no": "No"
},
"patterns": {
"title": "Previous Pattern",
"description": "What was last week's turnip price pattern?<i>(This affects your pattern)</i>",
"pattern": "Pattern",
"all": "All patterns",
"decreasing": "Decreasing",
"fluctuating": "Fluctuating",
"unknown": "I don't know",
"large-spike": "Large Spike",
"small-spike": "Small Spike"
},
"prices": {
"description": "What was the price of turnips this week on your island?",
"open": {
"am": "AM - 8:00 am to 11:59 am",
"pm": "PM - 12:00 pm to 10:00 pm"
},
"copy-permalink": "Copy permalink",
"permalink-copied": "Permalink copied!",
"reset": "Reset Turnip Prophet",
"reset-warning": "Are you sure you want to reset all fields?\n\nThis cannot be undone!"
},
"weekdays": {
"monday": "Monday",
"tuesday": "Tuesday",
"wednesday": "Wednesday",
"thursday": "Thursday",
"friday": "Friday",
"saturday" : "Saturday",
"sunday": "Sunday",
"abr": {
"monday": "Mon",
"tuesday": "Tue",
"wednesday": "Wed",
"thursday": "Thu",
"friday": "Fri",
"saturday" : "Sat"
}
},
"times": {
"morning": "AM",
"afternoon": "PM"
},
"output": {
"title": "Output",
"chance": "% Chance",
"to": "to",
"minimum": "Guaranteed Minimum",
"maximum": "Potential Maximum",
"chart": {
"input": "Input Price",
"minimum": "Guaranteed Minimum",
"maximum": "Potential Maximum"
}
},
"textbox": {
"description": "After you've listed some turnip prices, the Turnip Prophet will run some numbers and display the different possible patterns that your island may experience.",
"development": "This app is still in development, but will improve over time!",
"thanks": "None of this would have been possible without <a href=\"https://twitter.com/_Ninji/status/1244818665851289602?s=20\">Ninji's work</a> figuring out just how Timmy and Tommy value their turnips.",
"support": "Support, comments and contributions are available through <a href=\"https://github.com/mikebryant/ac-nh-turnip-prices/issues\">GitHub</a>",
"sponsor": "Want to sponsor the developers behind this project? Go to the <a href=\"https://github.com/mikebryant/ac-nh-turnip-prices#sponsor-button-repo\">GitHub</a> page and click '❤ Sponsor'",
"contributors-text": "Oh! And let's not forget to thank those who have contributed so far!",
"contributors": "Contributors",
"language": "Language",
"theme": {
"title": "Theme",
"auto": "Automatic",
"light": "Light",
"dark": "Dark"
}
},
"errors": {
"impossible-values": "Oops! There seems to be an error with your turnip predictions. Please check your inputs.",
"github": "If your turnip prices are correct and you have not time traveled, please <a href=\"https://github.com/mikebryant/ac-nh-turnip-prices/issues\">submit a report.</a>"
}
}

View File

@ -1,80 +0,0 @@
{
"general": {
"daisy-mae": "Juliana"
},
"welcome": {
"salutation": "¡Hola! Te damos la bienvenida a la aplicación <b>Turnip Prophet</b> para tu Nookófono.",
"description": "Esta aplicación te permite monitorizar la fluctuación del precio de los nabos en tu isla, ¡pero tendrás que introducir tú manualmente los precios diarios!",
"conclusion": "Una vez hecho, la aplicación Turnip Prophet predecirá <b>mágicamente</b> el precio que tendrán los nabos el resto de la semana."
},
"first-time": {
"title": "Comprador(a) primerizo(a)",
"description": "¿Ha sido esta la primera vez que compras nabos?<i>(Esta información afectará a tu patrón)</i>",
"yes": "Sí",
"no": "No"
},
"patterns": {
"title": "Patrón anterior",
"description": "¿Qué patrón describió el precio de los nabos la semana pasada?<i>(Esta información afectará a tu patrón)</i>",
"pattern": "Patrón",
"all": "Todos los patrones",
"decreasing": "Decreciente",
"fluctuating": "Fluctuante",
"unknown": "No lo sé",
"large-spike": "Pico alto",
"small-spike": "Pico moderado"
},
"prices": {
"description": "¿Cuál fue el precio de los nabos en tu isla esta semana?",
"open": {
"am": "AM - De 8:00 a 11:59",
"pm": "PM - De 12:00 a 22:00"
},
"copy-permalink": "Copiar permalink",
"permalink-copied": "¡Permalink copiado!",
"reset": "Reiniciar Turnip Prophet",
"reset-warning": "¿Seguro que quieres reiniciar todos los campos?\n\n¡Esto no se puede deshacer!"
},
"weekdays": {
"monday": "Lunes",
"tuesday": "Martes",
"wednesday": "Miércoles",
"thursday": "Jueves",
"friday": "Viernes",
"saturday" : "Sábado",
"sunday": "Domingo",
"abr": {
"monday": "LU",
"tuesday": "MA",
"wednesday": "MI",
"thursday": "JU",
"friday": "VI",
"saturday" : "SA"
}
},
"times": {
"morning": "AM",
"afternoon": "PM"
},
"output": {
"title": "Predicción",
"chance": "Probabilidad (%)",
"to": "a",
"minimum": "Mínimo garantizado",
"maximum": "Máximo potencial",
"chart": {
"input": "Precio de entrada",
"minimum": "Mínimo garantizado",
"maximum": "Máximo potencial"
}
},
"textbox": {
"description": "Cuando introduzcas algunos precios, Turnip Prophet empezará a hacer sus cálculos y te mostrará algunos posibles patrones para el precio de los nabos en tu isla.",
"development": "Esta aplicación está aún en desarrollo, ¡pero la seguiremos mejorando!",
"thanks": "Nada de esto habría sido posible sin el <a href=\"https://twitter.com/_Ninji/status/1244818665851289602?s=20\">trabajo de Ninji</a> para averiguar cómo Tendo y Nendo valoran los nabos.",
"support": "Para asistencia, comentarios y contribuciones, no dudes en pasarte por <a href=\"https://github.com/mikebryant/ac-nh-turnip-prices/issues\">GitHub</a>.",
"contributors-text": "¡Ah! ¡Y no nos olvidemos de todos los que han puesto su granito de arena hasta ahora!",
"contributors": "Contribuidores",
"language": "Idioma"
}
}

View File

@ -1,87 +0,0 @@
{
"general": {
"daisy-mae": "Porcelette"
},
"welcome": {
"salutation": "Bonjour et bienvenue sur l'application du <b>Turnip Prophet</b> de ton Nook Phone.",
"description": "Cette appli te permet de garder un œil quotidien sur le cours du navet de ton île, en le renseignant ici par toi-même !",
"conclusion": "Une fois les prix renseignés, l'appli du Turnip Prophet va <b>magiquement</b> prédire le cours du navet de ton île pour le reste de la semaine."
},
"first-time": {
"title": "Premier Achat",
"description": "Est-ce la toute première fois que t'achètes des navets à Porcelette sur ton île ?<i>(Cela influencera le type de ta courbe actuelle)</i>",
"yes": "Oui",
"no": "Non"
},
"patterns": {
"title": "Courbe du cours précédent",
"description": "De quel type était la courbe de ton cours du navet la semaine dernière ?<i>(Cela influencera le type de ta courbe actuelle)</i>",
"pattern": "Type de Courbe",
"all": "Tous les types",
"decreasing": "Décroissante",
"fluctuating": "Variable",
"unknown": "Je ne sais pas",
"large-spike": "Grand Pic",
"small-spike": "Petit Pic"
},
"prices": {
"description": "À quel prix Porcelette vendait ses navets sur ton île cette semaine ?",
"open": {
"am": "Matin (AM) - de 8:00 à 11:59",
"pm": "Après-midi (PM) - de 12:00 à 22:00"
},
"copy-permalink": "Copier le permalien",
"permalink-copied": "Permalien copié !",
"reset": "Réinitialiser les données",
"reset-warning": "Es-tu sûr·e de vouloir réinitialiser tous les champs ?\n\nCe choix est définitif !"
},
"weekdays": {
"monday": "Lundi",
"tuesday": "Mardi",
"wednesday": "Mercredi",
"thursday": "Jeudi",
"friday": "Vendredi",
"saturday" : "Samedi",
"sunday": "Dimanche",
"abr": {
"monday": "Lun",
"tuesday": "Mar",
"wednesday": "Mer",
"thursday": "Jeu",
"friday": "Ven",
"saturday" : "Sam"
}
},
"times": {
"morning": "AM",
"afternoon": "PM"
},
"output": {
"title": "Résultats",
"chance": "% Chance",
"to": "à",
"minimum": "Minimum Garanti",
"maximum": "Maximum Potentiel",
"chart": {
"input": "Prix renseigné",
"minimum": "Minimum Garanti",
"maximum": "Maximum Potentiel"
}
},
"textbox": {
"description": "Après avoir renseigné quelques prix, le Turnip Prophet fera des calculs et affichera les différents types possibles pour les courbes que ton île pourrait avoir.",
"development": "Cette appli est en développement, mais elle s'améliore jour après jour !",
"thanks": "Rien de tout ça n'aurait pu être possible sans <a href=\"https://twitter.com/_Ninji/status/1244818665851289602?s=20\">le travail de Ninji</a> et son analyse sur comment Méli et Mélo déterminent la valeur des Navets.",
"support": "Aide, commentaires et contributions sont disponibles via <a href=\"https://github.com/mikebryant/ac-nh-turnip-prices/issues\">GitHub</a>",
"sponsor": "T'aimerais sponsoriser les développeurs derrière ce projet ? Alors va sur la page <a href=\"https://github.com/mikebryant/ac-nh-turnip-prices#sponsor-button-repo\">GitHub</a> du projet et clique sur '❤ Sponsor'",
"contributors-text": "Oh ! Et n'oublions pas de remercier toutes les personnes ayant contribué jusqu'à maintenant !",
"contributors": "Contributeurs",
"language": "Langue",
"theme": {
"title": "Thème",
"auto": "Automatique",
"light": "Clair",
"dark": "Sombre"
}
}
}

View File

@ -1,80 +0,0 @@
{
"general": {
"daisy-mae": "Juliana"
},
"welcome": {
"salutation": "Ola, estás no aplicativo <b>Turnip Prophet</b> no teu Nookófono.",
"description": "Este aplicativo permíteche facer un seguemento do prezo dos nabos na túa illa. Porén, tes que introducir os prezos manualmente.",
"conclusion": "Depois, o aplicativo predirá <b>maxicamente</b> os prezos dos nabos na túa illa para o resto da semana."
},
"first-time": {
"title": "Primeira compra",
"description": "É a primeira vez que compras nabos a Juliana na túa illa? <i>(Isto afecta aos prezos)</i>",
"yes": "Si",
"no": "Non"
},
"patterns": {
"title": "Tendencia anterior",
"description": "Cal foi a tendencia de prezos na túa illa a semana pasada? <i>(Isto afecta aos prezos)</i>",
"pattern": "Tendencia",
"all": "Todas as tendencias",
"decreasing": "Decrecente",
"fluctuating": "Fluctuante",
"unknown": "Descoñecido",
"large-spike": "Pico grande",
"small-spike": "Pico pequeno"
},
"prices": {
"description": "Que prezos tiveron os nabos esta semana na túa illa?",
"open": {
"am": "Mañá - 8:00 a 11:59",
"pm": "Tarde - 12:00 a 22:00"
},
"copy-permalink": "Copiar ligazón permanente",
"permalink-copied": "Ligazón permanente copiada!",
"reset": "Restablecer Turnip Prophet",
"reset-warning": "Seguro que desexas restablecer todos os campos?\n\nIsto non se pode desfacer!"
},
"weekdays": {
"monday": "Luns",
"tuesday": "Martes",
"wednesday": "Mércores",
"thursday": "Xoves",
"friday": "Venres",
"saturday" : "Sábado",
"sunday": "Domingo",
"abr": {
"monday": "Lun",
"tuesday": "Mar",
"wednesday": "Mér",
"thursday": "Xov",
"friday": "Venr",
"saturday" : "Sáb"
}
},
"times": {
"morning": "Mañá",
"afternoon": "Tarde"
},
"output": {
"title": "Resultado",
"chance": "% Probabilidade",
"to": "a",
"minimum": "Mínimo garantido",
"maximum": "Máximo potencial",
"chart": {
"input": "Prezo introducido",
"minimum": "Mínimo garantido",
"maximum": "Máximo potencial"
}
},
"textbox": {
"description": "Despois de introducir algúns prezos, o Turnip Prophet calculará que prezos poden ter no futuro.",
"development": "Este aplicativo aínda está en desenvolvemento, mais mellorará co tempo!",
"thanks": "Nada disto sería posible sen o traballo de <a href=\"https://twitter.com/_Ninji/status/1244818665851289602?s=20\">Ninji</a> achando como se calculan os prezos.",
"support": "Soporte, comentarios e contribucións están dispoñibles en <a href=\"https://github.com/mikebryant/ac-nh-turnip-prices/issues\">GitHub</a>",
"contributors-text": "Oh! E non esqueceremos dar as grazas aos que xa contribuíron.",
"contributors": "Contribuidores",
"language": "Lingua"
}
}

View File

@ -1,87 +0,0 @@
{
"general": {
"daisy-mae": "Daisy Mae"
},
"welcome": {
"salutation": "Üdvözöllek a Nookfonod <b>Turnip Prophet</b> alkalmazásában!",
"description": "Ezzel az alkalmazással követheted a szigeted naponta változó retekárait, viszont az árakat Neked kell megadnod!",
"conclusion": "Az árak megadása után a Turnip Prophet <b>varázslatosan</b> megjósolja a hét elkövetkezendő árait."
},
"first-time": {
"title": "Első vásárlás",
"description": "Most vásárol valaki először retket Daisy Mae-től a <b>Te szigeteden</b>?<i>(Ez hatással van a mintádra)</i>",
"yes": "Igen",
"no": "Nem"
},
"patterns": {
"title": "Előző minta",
"description": "Milyen volt az előző hét mintája?<i>(Ez hatással van a mintádra)</i>",
"pattern": "Minta",
"all": "Minden minta",
"decreasing": "Csökkenő",
"fluctuating": "Ingadozó",
"unknown": "Nem tudom",
"large-spike": "Nagy kiugrás",
"small-spike": "Kis kiugrás"
},
"prices": {
"description": "Mennyiért vettél ezen a héten retket?",
"open": {
"am": "Délelőtt - 08:00-tól 11:59-ig",
"pm": "Délután - 12:00-től 22:00-ig"
},
"copy-permalink": "Árak megosztása",
"permalink-copied": "Hivatkozás kimásolva!",
"reset": "Mezők kiürítése",
"reset-warning": "Biztosan ki akarsz üríteni minden mezőt?\n\nEz a művelet nem vonható vissza!"
},
"weekdays": {
"monday": "Hétfő",
"tuesday": "Kedd",
"wednesday": "Szerda",
"thursday": "Csütörtök",
"friday": "Péntek",
"saturday" : "Szombat",
"sunday": "Vasárnap",
"abr": {
"monday": "H",
"tuesday": "K",
"wednesday": "Sze",
"thursday": "Cs",
"friday": "P",
"saturday" : "Szo"
}
},
"times": {
"morning": "de.",
"afternoon": "du."
},
"output": {
"title": "Eredmény",
"chance": "% Esély",
"to": "-",
"minimum": "Garantált minimum",
"maximum": "Lehetséges maximum",
"chart": {
"input": "Megadott ár",
"minimum": "Garantált minimum",
"maximum": "Lehetséges maximum"
}
},
"textbox": {
"description": "Miután megadtál néhány árat, a Turnip Prophet kiszámolja és megjeleníti az összes lehetséges mintát ami a héten megjelenhet.",
"development": "Ez az alkalmazás fejlesztés alatt áll, de idővel javulni fog!",
"thanks": "Ez nem lett volna lehetséges <a href=\"https://twitter.com/_Ninji/status/1244818665851289602?s=20\">Ninji munkája</a> nélkül, aki megfejtette, hogy Timmy és Tommy hogyan árazzák a retket.",
"support": "Minden hibajelentést, megjegyzést és hozzájárulást a <a href=\"https://github.com/mikebryant/ac-nh-turnip-prices/issues\">GitHub-on</a> várunk.",
"sponsor": "Szeretnéd szponzorálni a projekt fejlesztőit? Menj a <a href=\"https://github.com/mikebryant/ac-nh-turnip-prices#sponsor-button-repo\">GitHub</a> oldalra és nyomd meg a „❤ Sponsor” gombot!",
"contributors-text": "Ó, és ne felejtsünk el köszönetet mondani az eddigi hozzájárulóknak!",
"contributors": "Hozzájárulók",
"language": "Nyelv",
"theme": {
"title": "Téma",
"auto": "Automatikus",
"light": "Világos",
"dark": "Sötét"
}
}
}

View File

@ -1,81 +0,0 @@
{
"general": {
"daisy-mae": "Daisy Mae"
},
"welcome": {
"salutation": "Halo, dan selamat datang di aplikasi <b>Turnip Prophet</b> pada Nook Phone kalian.",
"description": "Aplikasi ini dapat digunakan untuk mencatat harga turnip harian di pulau kalian, tapi kalian harus memasukkan harganya sendiri!",
"conclusion": "Setelah itu, aplikasi Turnip Prophet akan <b>secara ajaib</b> memprediksi harga turnip kalian selama satu minggu ke depan."
},
"first-time": {
"title": "Pertama Kali Beli",
"description": "Apakah ini pertama kalinya seorang penduduk membeli turnip dari Daisy Mae di pulau <b>kalian sendiri</b>?<i>(Akan memengaruhi pola harga)</i>",
"yes": "Iya",
"no": "Tidak"
},
"patterns": {
"title": "Pola Sebelumnya",
"description": "Bagaimana bentuk pola harga turnip pada minggu sebelumnya?<i>(Akan memengaruhi pola harga)</i>",
"pattern": "Pola",
"all": "Semua pola",
"decreasing": "Menurun",
"fluctuating": "Fluktuatif",
"unknown": "Tidak tahu",
"large-spike": "Peningkatan Tajam",
"small-spike": "Peningkatan Kecil"
},
"prices": {
"description": "Berapa harga turnip di pulau kalian minggu ini?",
"open": {
"am": "AM - 8.00 pagi sampai 11:59 siang",
"pm": "PM - 12.00 siang sampai 22.00 malam"
},
"copy-permalink": "Salin tautan",
"permalink-copied": "Tautan telah disalin!",
"reset": "Reset Turnip Prophet",
"reset-warning": "Apakah kamu yakin ingin me-reset semua kolom?\n\nSetelah di-reset, tidak dapat dikembalikan lagi!"
},
"weekdays": {
"monday": "Senin",
"tuesday": "Selasa",
"wednesday": "Rabu",
"thursday": "Kamis",
"friday": "Jumat",
"saturday" : "Sabtu",
"sunday": "Minggu",
"abr": {
"monday": "Sen",
"tuesday": "Sel",
"wednesday": "Rab",
"thursday": "Kam",
"friday": "Jum",
"saturday" : "Sab"
}
},
"times": {
"morning": "AM",
"afternoon": "PM"
},
"output": {
"title": "Output",
"chance": "% Peluang",
"to": "-",
"minimum": "Jaminan Minimal",
"maximum": "Potensi Maksimal",
"chart": {
"input": "Input Harga",
"minimum": "Jaminan Minimal",
"maximum": "Potensi Maksimal"
}
},
"textbox": {
"description": "Setelah kalian mendaftarkan harga turnip-nya, Turnip Prophet akan melakukan perhitungan dan menampilkan beberapa kemungkinan dengan pola yang berbeda yang mungkin terjadi di pulau kalian.",
"development": "Aplikasi ini masih dalam tahap pengembangan, tapi akan selalu bertambah baik seiring dengan berjalannya waktu!",
"thanks": "Aplikasi ini tidak akan terwujud tanpa adanya <a href=\"https://twitter.com/_Ninji/status/1244818665851289602?s=20\">hasil kerja Ninji</a> yang menemukan cara bagaimana Timmy dan Tommy menentukan harga turnip.",
"support": "Dukungan, komentar, dan kontribusi dapat dilakukan melalui <a href=\"https://github.com/mikebryant/ac-nh-turnip-prices/issues\">GitHub</a>",
"sponsor": "Ingin mensponsori pengembang di balik proyek ini? Silakan menuju halaman <a href=\"https://github.com/mikebryant/ac-nh-turnip-prices#sponsor-button-repo\">GitHub</a> dan klik '❤ Sponsor'",
"contributors-text": "Oh! Jangan lupa juga untuk berterima kasih pada semuanya yang telah berkontribusi sejauh ini!",
"contributors": "Kontributor",
"language": "Bahasa"
}
}

View File

@ -1,82 +0,0 @@
{
"general": {
"name": "Turnip Prophet",
"daisy-mae": "Brunella"
},
"welcome": {
"salutation": "Ciao e benvenuto nell'app <b>Turnip Prophet</b> del tuo Nook Phone.",
"description": "Questa applicazione ti permetterà di tenere traccia del prezzo giornaliero delle rape. Ma dovrai inserire i prezzi da te!",
"conclusion": "Se lo fai Turnip Prophet predirrà <b>magicamente</b> i prezzi delle rape che avrai per il resto della settimana."
},
"first-time": {
"title": "Primo Acquisto",
"description": "È la prima volta che acquisti sulla tua isola le rape da Brunella?<i>(influisce sul comportamento dei prezzi)</i>",
"yes": "Sì",
"no": "No"
},
"patterns": {
"title": "Comportamento Precedente",
"description": "Qual è stato il comportamento dei prezzi delle rape nella scorsa settimana?<i>(influisce sul comportamento dei prezzi)</i>",
"pattern": "Comportamento",
"all": "Tutti i comportamenti",
"decreasing": "Decrescente",
"fluctuating": "Oscillante",
"unknown": "Non lo so!",
"large-spike": "Grande picco",
"small-spike": "Piccolo picco"
},
"prices": {
"description": "Qual era il prezzo di acquisto delle rape sulla tua isola questa settimana?",
"open": {
"am": "Mattina - dalle 8:00 alle 11:59",
"pm": "Pomeriggio - dalle 12:00 alle 22:00"
},
"copy-permalink": "Copia permalink",
"permalink-copied": "Permalink copiato!",
"reset": "Resetta Turnip Prophet",
"reset-warning": "Sei sicuro di voler resettare tutti i campi?\n\nNon può essere annullato!"
},
"weekdays": {
"monday": "Lunedì",
"tuesday": "Martedì",
"wednesday": "Mercoledì",
"thursday": "Giovedì",
"friday": "Venerdì",
"saturday": "Sabato",
"sunday": "Domenica",
"abr": {
"monday": "Lun",
"tuesday": "Mar",
"wednesday": "Mer",
"thursday": "Gio",
"friday": "Ven",
"saturday": "Sab"
}
},
"times": {
"morning": "AM",
"afternoon": "PM"
},
"output": {
"title": "Risultati",
"chance": "Probabilità %",
"to": "a",
"minimum": "Minimo Garantito",
"maximum": "Massimo Potenziale",
"chart": {
"input": "Prezzo Iniziale",
"minimum": "Minimo Garantito",
"maximum": "Massimo Potenziale"
}
},
"textbox": {
"description": "Dopo aver inserito alcuni prezzi, Turnip Prophet calcolerà e mostrerà i possibili comportamenti del prezzo delle rape nella tua isola.",
"development": "Quest'applicazione è in ancora in sviluppo ma migliorerà col tempo!",
"thanks": "Niente di questo sarebbe possibile senza <a href=\"https://twitter.com/_Ninji/status/1244818665851289602?s=20\">il lavoro di Ninji</a> nello scoprire come Mirko e Marco valutano le rape.",
"support": "Chiedi supporto o lascia commenti e contributi su <a href=\"https://github.com/mikebryant/ac-nh-turnip-prices/issues\">GitHub</a>",
"sponsor": "Vuoi sponsorizzare gli sviluppatori di questo progetto? Vai nella pagina <a href=\"https://github.com/mikebryant/ac-nh-turnip-prices#sponsor-button-repo\">GitHub</a> e clicca '❤ Sponsor'",
"contributors-text": "Oh! Non dimentichiamoci di ringraziare chi ha contribuito fin'ora!",
"contributors": "Collaboratori",
"language": "Lingua"
}
}

View File

@ -1,87 +0,0 @@
{
"general": {
"daisy-mae": "ウリ"
},
"welcome": {
"salutation": "こんにちは!タヌキ開発特製スマホの最新アプリ <b>Turnip Prophet</b> へようこそ。",
"description": "このアプリは、無人島のカブ価を毎日予測することができます。そのためには、まず自分でデータを入力することが必要です!",
"conclusion": "そうすれば、Turnip Prophetは<b>魔法</b>のように、あなたのこの一週間のカブ価を予測します。"
},
"first-time": {
"title": "はじめての購入",
"description": "あなたが自分の島でカブを購入したのは今回が初めてですか?<i>(答えによってパターンが変化します)</i>",
"yes": "はい",
"no": "いいえ"
},
"patterns": {
"title": "先週のパターン",
"description": "先週のカブ価変化パターンを選んでください。<i>(答えによってパターンが変化します)</i>",
"pattern": "パターン",
"all": "全てのパターン",
"decreasing": "ジリ貧型",
"fluctuating": "波型",
"unknown": "わかりません",
"large-spike": "跳ね大型(3期型)",
"small-spike": "跳ね小型(4期型)"
},
"prices": {
"description": "今週のカブ価は?",
"open": {
"am": "午前 - AM 8:00 AM 11:59",
"pm": "午後 - PM 12:00 PM 10:00"
},
"copy-permalink": "パーマリンクをコピー",
"permalink-copied": "パーマリンクがコピーされました!",
"reset": "Turnip Prophetをリセット",
"reset-warning": "本当に全てをリセットしますか?\n\nリセットしたら後戻りはできませんよ"
},
"weekdays": {
"monday": "月曜日",
"tuesday": "火曜日",
"wednesday": "水曜日",
"thursday": "木曜日",
"friday": "金曜日",
"saturday" : "土曜日",
"sunday": "日曜日",
"abr": {
"monday": "月",
"tuesday": "火",
"wednesday": "水",
"thursday": "木",
"friday": "金",
"saturday" : "土"
}
},
"times": {
"morning": "午前",
"afternoon": "午後"
},
"output": {
"title": "結果",
"chance": "% 確率",
"to": "",
"minimum": "保証される最小の収入",
"maximum": "予測される限界の収入",
"chart": {
"input": "カブ価",
"minimum": "保証される最小の収入",
"maximum": "予測される限界の収入"
}
},
"textbox": {
"description": "複数のカブ価を入力すると、Turnip Prophetはそれをもとに、可能性のある変動パターンを計算して表示します。",
"development": "このアプリはまだ開発中ですが、より良いデータを提供できるようにがんばっています!",
"thanks": "このアプリが作成できたのは、タヌキ商店のカブ価パターンを解析した<a href=\"https://twitter.com/_Ninji/status/1244818665851289602?s=20\">Ninji氏の成果</a>のおかげです。ありがとうございます!",
"support": "疑問·コメント·提案などは、<a href=\"https://github.com/mikebryant/ac-nh-turnip-prices/issues\">GitHub</a>までお願いします。",
"sponsor": "このプロジェクトに関わったソフトウェア開発者をスポンサーしたい場合、<a href=\"https://github.com/mikebryant/ac-nh-turnip-prices#sponsor-button-repo\">GitHub</a>のページで「❤ Sponsor」をクリックしてください",
"contributors-text": "そして、このアプリの作成を手伝っていただいた方々に感謝します!",
"contributors": "貢献者",
"language": "言語",
"theme": {
"title": "テーマ",
"auto": "自動",
"light": "ライト",
"dark": "ダーク"
}
}
}

View File

@ -1,80 +0,0 @@
{
"general": {
"daisy-mae": "무파니"
},
"welcome": {
"salutation": "안녕하세요, Nook Inc. 스마트폰의 <b>Turnip Prophet</b>앱을 사용해주셔서 감사합니다.",
"description": "이 앱은 당신의 섬의 매일의 무 가격을 추적 할 수 있게 도와줍니다. 하지만 가격은 직접 입력해야 합니다!",
"conclusion": "가격을 입력하고 나면, 이번 주 동안의 무 가격을 <b>마법처럼</b> 예측해줍니다."
},
"first-time": {
"title": "첫 구매",
"description": "당신의 섬에 방문한 무파니에게서 처음으로 무를 샀습니까?<i>(패턴에 영향을 끼칩니다)</i>",
"yes": "예",
"no": "아니오"
},
"patterns": {
"title": "이전 패턴",
"description": "저번 주의 무 가격 패턴이 어떻게 됩니까?<i>(패턴에 영향을 끼칩니다)</i>",
"pattern": "패턴",
"all": "모든 패턴",
"decreasing": "감소",
"fluctuating": "파동형",
"unknown": "모름",
"large-spike": "큰 급등",
"small-spike": "작은 급등"
},
"prices": {
"description": "이번 주에 당신의 섬에서 무를 샀을 때의 가격이 어떻게 됩니까?",
"open": {
"am": "오전 - 오전 8:00 ~ 오전 11:59",
"pm": "오후 - 오후 12:00 ~ 오후 10:00"
},
"copy-permalink": "고유주소 복사",
"permalink-copied": "고유주소가 복사되었습니다!",
"reset": "Turnip Prophet 초기화",
"reset-warning": "정말로 모든 입력한 값을 지우겠습니까?\n\n되돌릴 수 없습니다!"
},
"weekdays": {
"monday": "월요일",
"tuesday": "화요일",
"wednesday": "수요일",
"thursday": "목요일",
"friday": "금요일",
"saturday" : "토요일",
"sunday": "일요일",
"abr": {
"monday": "월",
"tuesday": "화",
"wednesday": "수",
"thursday": "목",
"friday": "금",
"saturday" : "토"
}
},
"times": {
"morning": "오전",
"afternoon": "오후"
},
"output": {
"title": "결과",
"chance": "% 확률",
"to": "~",
"minimum": "최저 보장 가격",
"maximum": "가능한 최고 가격",
"chart": {
"input": "입력된 가격",
"minimum": "최저 보장 가격",
"maximum": "가능한 최고 가격"
}
},
"textbox": {
"description": "지금까지의 무 가격을 입력하고 나면, Turnip Prophet이 당신의 섬에서 일어날 수 있는 가격 패턴을 보여줍니다.",
"development": "이 앱은 아직 개발 중입니다. 앞으로도 계속해서 개선될 겁니다!",
"thanks": "콩돌이와 밤돌이가 무 가격을 어떻게 결정하는지 알아낸 <a href=\"https://twitter.com/_Ninji/status/1244818665851289602?s=20\">Ninji의 연구</a>가 있었기에 이 앱이 만들어질 수 있었습니다.",
"support": "<a href=\"https://github.com/mikebryant/ac-nh-turnip-prices/issues\">GitHub</a>을 통해서 문의, 의견 제시, 기여가 가능합니다",
"contributors-text": "그리고 기여를 해주신 분들에게 감사를 표합니다!",
"contributors": "기여해 주신 분들",
"language": "언어"
}
}

View File

@ -1,81 +0,0 @@
{
"general": {
"daisy-mae": "Daisy Mae"
},
"welcome": {
"salutation": "Hallo, en welkom bij de <b>Turnip Prophet</b> app op je Nook Phone.",
"description": "Deze app laat je toe de knol-prijzen op je eiland dagelijks bij te houden, maar je moet ze zelf ingeven!",
"conclusion": "Daarna zal de Turnip Prophet app op <b>magische</b> wijze de knol-prijzen berekenen die je de rest van de week zal krijgen."
},
"first-time": {
"title": "Beginnende Koper",
"description": "Is dit de eerste keer dat je knollen koopt van Daisy Mae op je eiland?<i>(Dit beïnvloedt je patroon)</i>",
"yes": "Ja",
"no": "Nee"
},
"patterns": {
"title": "Vorige Patroon",
"description": "Wat was het patroon van je knol-prijzen vorige week?<i>(Dit beïnvloedt je patroon)</i>",
"pattern": "Patroon",
"all": "Alle patronen",
"decreasing": "Dalend",
"fluctuating": "Schommelend",
"unknown": "Ik weet het niet",
"large-spike": "Grote Piek",
"small-spike": "Kleine Piek"
},
"prices": {
"description": "Wat was de prijs van knollen op je eiland deze week?",
"open": {
"am": "Voormiddag - 8:00 tot 11:59",
"pm": "Namiddag - 12:00 tot 22:00"
},
"copy-permalink": "Kopieer deelbare link",
"permalink-copied": "Deelbare link gekopieerd!",
"reset": "Maak Turnip Prophet leeg",
"reset-warning": "Ben je zeker dat je alle velden wil leegmaken?\n\nDit kan niet ongedaan gemaakt worden!"
},
"weekdays": {
"monday": "Maandag",
"tuesday": "Dinsdag",
"wednesday": "Woensdag",
"thursday": "Donderdag",
"friday": "Vrijdag",
"saturday" : "Zaterdag",
"sunday": "Zondag",
"abr": {
"monday": "Ma",
"tuesday": "Di",
"wednesday": "Woe",
"thursday": "Do",
"friday": "Vr",
"saturday" : "Za"
}
},
"times": {
"morning": "VM",
"afternoon": "NM"
},
"output": {
"title": "Resultaat",
"chance": "% Kans",
"to": "tot",
"minimum": "Gegarandeerd Minimum",
"maximum": "Potentieel Maximum",
"chart": {
"input": "Ingevoerde prijs",
"minimum": "Gegarandeerd Minimum",
"maximum": "Potentieel Maximum"
}
},
"textbox": {
"description": "Nadat je wat knol-prijzen hebt ingevoerd, zal de Turnip Prophet wat berekeningen doen en de verschillende mogelijke patronen voorstellen die je eiland kan vertonen.",
"development": "Deze applicatie is nog in ontwikkeling, en zal met de tijd beter worden!",
"thanks": "Dit alles zou niet mogelijk zijn zonder het <a href=\"https://twitter.com/_Ninji/status/1244818665851289602\">werk van Ninji</a> om uit te zoeken hoe Timmy en Tommy de waarde van knollen bepalen.",
"support": "Ondersteuning, feedback en bijdrages zijn mogelijk via <a href=\"https://github.com/mikebryant/ac-nh-turnip-prices/issues\">GitHub</a>",
"sponsor": "Wil je de ontwikkelaars van dit project sponsoren? Ga naar de <a href=\"https://github.com/mikebryant/ac-nh-turnip-prices#sponsor-button-repo\">GitHub</a> pagina en klik op '❤ Sponsor'",
"contributors-text": "Oh! En laten we degenen die tot nu toe bijgedragen hebben niet vergeten te bedanken!",
"contributors": "Bijdragers",
"language": "Taal"
}
}

View File

@ -1,87 +0,0 @@
{
"general": {
"daisy-mae": "Daisy Mae"
},
"welcome": {
"salutation": "Kumusta, at maligayang pagdating sa <b>Turnip Prophet</b> app sa iyong Nook Phone.",
"description": "Sa pamamagitan ng app na ito, puwede mo na subaybayan ang mga presyo ng turnip ng iyong isla araw-araw, ngunit kailangan mong ilagay ang mga presyo sa iyong sarili!",
"conclusion": "Pagkatapos nito, ang Turnip Prophet app ay huhulaan ang magiging presyo ng singil sa iyo para sa natitirang linggo, sa pamamagitan ng <b>mahika</b>!"
},
"first-time": {
"title": "Unang beses na Mamimili",
"description": "Ito ba ang unang pagkakataon na ang isang residente ay namimili ng mga turnip mula kay Daisy Mae <b>sa iyong sariling</b> isla?<i>(Nakakaapekto ito sa iyong pattern)</i>",
"yes": "Oo",
"no": "Hindi"
},
"patterns": {
"title": "Nakaraang Pattern",
"description": "Ano ang pattern ng presyo ng turnip noong nakaraang linggo?<i>(Nakakaapekto ito sa iyong pattern)</i>",
"pattern": "Pattern",
"all": "Lahat ng mga pattern",
"decreasing": "Pababa",
"fluctuating": "Taas-Baba",
"unknown": "Hindi ko alam",
"large-spike": "Malaki na Pag-taas",
"small-spike": "Maliit na Pag-taas"
},
"prices": {
"description": "Ano ang presyo ng mga turnip sa linggong ito sa iyong isla?",
"open": {
"am": "AM - 8:00 am - 11:59 am",
"pm": "PM - 12:00 pm - 10:00 pm"
},
"copy-permalink": "Kopyahin ang permalink",
"permalink-copied": "Nakopya ang permalink!",
"reset": "I-reset ang Turnip Prophet",
"reset-warning": "Sigurado ka bang nais mong i-reset ang lahat ng mga patlang?\n\nHindi na ito maibabalik sa dati!"
},
"weekdays": {
"monday": "Lunes",
"tuesday": "Martes",
"wednesday": "Miyerkules",
"thursday": "Huwebes",
"friday": "Biyernes",
"saturday" : "Sabado",
"sunday": "Linggo",
"abr": {
"monday": "Lunes",
"tuesday": "Martes",
"wednesday": "Miyerkules",
"thursday": "Huwebes",
"friday": "Biyernes",
"saturday" : "Sabado"
}
},
"times": {
"morning": "AM",
"afternoon": "PM"
},
"output": {
"title": "Resulta",
"chance": "% ng Tiyansa",
"to": "-",
"minimum": "Garantisadong Minimum",
"maximum": "Potensyal na Maximum",
"chart": {
"input": "Na-input na Presyo",
"minimum": "Garantisadong Minimum",
"maximum": "Potensyal na Maximum"
}
},
"textbox": {
"description": "Pagkatapos mong mailista ang ilang mga presyo ng turnip, kakalkulahin ng Turnip Prophet ang mga numero at lilitaw ang iba't ibang mga posibleng pattern na maaaring maranasan ng iyong isla.",
"development": "Ang app na ito ay nasa pag-unlad pa rin, ngunit mapapabuti sa paglipas ng panahon!",
"thanks": "Lahat nang ito ay hindi posible kung wala ang tulong ni <a href=\"https://twitter.com/_Ninji/status/1244818665851289602?s=20\">Ninji</a> sa pag-alam kung paano pinepresyuhan ni Timmy at Tommy ang kanilang mga turnip.",
"support": "Pumunta lamang sa <a href=\"https://github.com/mikebryant/ac-nh-turnip-prices/issues\">GitHub</a> para sa suporta, puna, at kontribusyon.",
"sponsor": "Nais mo ba i-sponsor ang mga developer sa likod ng proyektong ito? Pumunta lamang sa <a href=\"https://github.com/mikebryant/ac-nh-turnip-prices#sponsor-button-repo\">GitHub</a> page at i-click ang '❤ Sponsor'",
"contributors-text": "Siya nga pala! Huwag din natin kalimutan na pasalamatan ang mga nag-bigay ng kanilang kontribusyon sa ngayon!",
"contributors": "Contributors",
"language": "Wika",
"theme": {
"title": "Tema",
"auto": "Automatic",
"light": "Light",
"dark": "Dark"
}
}
}

View File

@ -1,81 +0,0 @@
{
"general": {
"daisy-mae": "Daisy Mae"
},
"welcome": {
"salutation": "Cześć, witaj w aplikacji <b>Turnip Prophet</b> na Twoim Nook Phone.",
"description": "Ta aplikacja pozwoli Ci codziennie śledzić ceny rzep na twojej wyspie, jednak będziesz musiał uzupełniać je samodzielnie.",
"conclusion": "Następnie aplikacja Turnip Prophet <b>w magiczny sposób</b> przewidzi jakie ceny rzep będziesz mieć przez resztę tygodnia"
},
"first-time": {
"title": "Kupujący po raz pierwszy",
"description": "Czy jest to pierwszy raz gdy kupujesz rzepy od Daisy Mae na <b>własnej</b> wyspie?<i>(Ta opcja wpłynie na Twój schemat)</i>",
"yes": "Tak",
"no": "Nie"
},
"patterns": {
"title": "Poprzedni schemat",
"description": "Jaka była tendencja cen rzep w poprzednim tygodniu?<i>(Ta opcja wpłynie na Twój wzór)</i>",
"pattern": "Wzór",
"all": "Wszystkie wzory",
"decreasing": "Malejąca",
"fluctuating": "Zmienna",
"unknown": "Nie pamiętam",
"large-spike": "Duży wzrost",
"small-spike": "Mały wzrost"
},
"prices": {
"description": "Jakie ceny za rzepy były w tym tygodniu na Twojej wyspie?",
"open": {
"am": "Przed południem - 8:00 do 11:59 ",
"pm": "Po południu - 12:00 do 22:00 "
},
"copy-permalink": "Skopiuj permalink",
"permalink-copied": "Permalink skopiowany!",
"reset": "Wyzeruj Turnip Prophet",
"reset-warning": "Czy jesteś pewien, że chcesz wyzerować wszystkie pola?\n\nTej opcji nie można cofnąć!"
},
"weekdays": {
"monday": "Poniedziałek",
"tuesday": "Wtorek",
"wednesday": "Środa",
"thursday": "Czwartek",
"friday": "Piątek",
"saturday" : "Sobota",
"sunday": "Niedziela",
"abr": {
"monday": "Pon",
"tuesday": "Wt",
"wednesday": "Śr",
"thursday": "Czw",
"friday": "Pt",
"saturday" : "Sob"
}
},
"times": {
"morning": "Rano",
"afternoon": "Popołudnie"
},
"output": {
"title": "Wyniki",
"chance": "Szansa %",
"to": "do",
"minimum": "Gwarantowana cena minimalna",
"maximum": "Potencjalna najwyższa cena",
"chart": {
"input": "Cena wejściowa",
"minimum": "Gwarantowana cena minimalna",
"maximum": "Potencjalna najwyższa cena"
}
},
"textbox": {
"description": "Po tym jak wprowadzisz kilka cen rzep, Turnip Prophet dokona obliczeń i wyświetli różne prawdopodobne szablony cen, których może doświadczyć Twoja wyspa",
"development": "Ta aplikacja wciąż jest w produkcji, lecz z czasem zostanie poprawiona!",
"thanks": "Nie udałoby nam się to bez <a href=\"https://twitter.com/_Ninji/status/1244818665851289602?s=20\">pracy Ninji</a>, który dowiedział się jak Timmy and Tommy wyceniają rzepy.",
"support": "Wsparcie, komentarze i wpłaty są możliwe pod adresem <a href=\"https://github.com/mikebryant/ac-nh-turnip-prices/issues\">GitHub</a>",
"sponsor": "Chcesz wesprzeć twórców tego projektu? Wejdź na stronę <a href=\"https://github.com/mikebryant/ac-nh-turnip-prices#sponsor-button-repo\">GitHub</a> i wciśnij '❤ Sponsor'",
"contributors-text": "Aha! I nie zapominajmy o tych, którzy dotychczas nas wspierali!",
"contributors": "Współautorzy",
"language": "Język"
}
}

View File

@ -1,80 +0,0 @@
{
"general": {
"daisy-mae": "Daisy Mae"
},
"welcome": {
"salutation": "Olá, e bem-vindo ao aplicativo <b>Turnip Prophet</b> em seu Nook Phone.",
"description": "Este aplicativo lhe permite acompanhar os preços diários de nabo em sua ilha, porém você terá que colocar os preços você mesmo!",
"conclusion": "Depois disso, o aplicativo Turnip Prophet irá <b>magicamente</b> prever os preços dos nabos que você terá pelo resto da semana."
},
"first-time": {
"title": "Comprador de primeira viagem",
"description": "Esta é a primeira vez que você compra nabos de Daisy Mae em sua ilha? <i>(Isso afeta seu padrão)</i>",
"yes": "Sim",
"no": "Não"
},
"patterns": {
"title": "Padrão Anterior",
"description": "Qual foi o padrão de preços de nabo da semana passada? <i>(Isso afeta seu padrão)</i>",
"pattern": "Padrão",
"all": "Todos padrões",
"decreasing": "Diminuindo",
"fluctuating": "Flutuante",
"unknown": "Eu não sei",
"large-spike": "Grande Pico",
"small-spike": "Pequeno Pico"
},
"prices": {
"description": "Qual foi o preço dos nabos esta semana em sua ilha?",
"open": {
"am": "AM - 8:00 am até 11:59 am",
"pm": "PM - 12:00 pm até 10:00 pm"
},
"copy-permalink": "Copiar permalink",
"permalink-copied": "Permalink copiado!",
"reset": "Redefinir Turnip Prophet",
"reset-warning": "Tem certeza de que deseja redefinir todos os campos?\n\nIsso não pode ser desfeito!"
},
"weekdays": {
"monday": "Segunda-feira",
"tuesday": "Terça-feira",
"wednesday": "Quarta-feira",
"thursday": "Quinta-feira",
"friday": "Sexta-feira",
"saturday" : "Sábado",
"sunday": "Domingo",
"abr": {
"monday": "Seg",
"tuesday": "Ter",
"wednesday": "Qua",
"thursday": "Qui",
"friday": "Sex",
"saturday" : "Sab"
}
},
"times": {
"morning": "AM",
"afternoon": "PM"
},
"output": {
"title": "Resultado",
"chance": "% Chance",
"to": "to",
"minimum": "Mínimo Garantido",
"maximum": "Potencial Máximo",
"chart": {
"input": "Preço de entrada",
"minimum": "Mínimo Garantido",
"maximum": "Potencial Máximo"
}
},
"textbox": {
"description": "Depois de listar alguns preços de nabo, o Turnip Prophet irá calcular alguns números e exibirá os diferentes padrões possíveis que sua ilha pode experienciar.",
"development": "Este aplicativo ainda está em desenvolvimento, mas melhorará com o tempo!",
"thanks": "Nada disso seria possível sem o <a href=\"https://twitter.com/_Ninji/status/1244818665851289602?s=20\">trabalho de Ninji's</a> descobrindo como Timmy e Tommy valorizam seus nabos.",
"support": "Suporte, comentários e contribuições estão disponíveis através do <a href=\"https://github.com/mikebryant/ac-nh-turnip-prices/issues\">GitHub</a>",
"contributors-text": "Oh! E não vamos nos esquecer de agradecer àqueles que contribuíram até agora!",
"contributors": "Contribuidores",
"language": "Linguagem"
}
}

View File

@ -1,81 +0,0 @@
{
"general": {
"daisy-mae": "Дейзи Мэй"
},
"welcome": {
"salutation": "Добрый день! Добро пожаловать в приложение <b>Препсказатель</b> на Вашем Нукофоне.",
"description": "Это приложение позволяет Вам ежедневно отслеживать стоимость репы на Вашем острове. Будьте внимательны, Вам придется вводить ее вручную!",
"conclusion": "После этого Препсказатель <b>как по волшебству</b> предскажет стоимость репы в Вашем магазине на этой неделе."
},
"first-time": {
"title": "Новичок рынка репы",
"description": "Вы впервые приобретаете репу у Дейзи Мэй на своем острове?<i>(Это влияет на модель стоимости)</i>",
"yes": "Да",
"no": "Нет"
},
"patterns": {
"title": "Предыдущая модель",
"description": "Какая модель стоимости репы была у Вас на прошлой неделе?<i>(Это влияет на модель стоимости)</i>",
"pattern": "Модель",
"all": "Все модели",
"decreasing": "Постоянное снижение",
"fluctuating": "Колебание стоимости",
"unknown": "Не могу сказать точно",
"large-spike": "Большой скачок",
"small-spike": "Малый скачок"
},
"prices": {
"description": "Какова была стоимость репы у Дейзи Мэй на Вашем острове на этой неделе?",
"open": {
"am": "Утро - 8:00 - 11:59",
"pm": "День - 12:00 - 22:00"
},
"copy-permalink": "Скопировать постоянную ссылку",
"permalink-copied": "Постоянная ссылка скопирована!",
"reset": "Перезагрузить Препсказателя",
"reset-warning": "Вы уверены, что хотите обнулить все поля?\n\nДанное действие необратимо!"
},
"weekdays": {
"monday": "Понедельник",
"tuesday": "Вторник",
"wednesday": "Среда",
"thursday": "Четверг",
"friday": "Пятница",
"saturday" : "Суббота",
"sunday": "Воскресенье",
"abr": {
"monday": "Пн",
"tuesday": "Вт",
"wednesday": "Ср",
"thursday": "Чт",
"friday": "Пт",
"saturday" : "Сб"
}
},
"times": {
"morning": "Утро",
"afternoon": "День"
},
"output": {
"title": "Вывод модели",
"chance": "Вероятность в %",
"to": "-",
"minimum": "Гарантированный минимум",
"maximum": "Возможный максимум",
"chart": {
"input": "Введенная стоимость",
"minimum": "Гарантированный минимум",
"maximum": "Возможный максимум"
}
},
"textbox": {
"description": "После того, как Вы введете уже известную Вам стоимость репы, Препсказатель посчитает и покажет различные вероятные для Вашего острова модели стоимости репы.",
"development": "Это приложение пока еще в разработке, но со временем обязательно станет лучше!",
"thanks": "Если бы <a href=\"https://twitter.com/_Ninji/status/1244818665851289602?s=20\">Ninji</a> не смог разузнать, как Тимми и Томми определяют стоимость репы, данного приложения могло бы и не быть!",
"support": "Поддержать нас, прокомментировать, а также внести свой вклад Вы можете на <a href=\"https://github.com/mikebryant/ac-nh-turnip-prices/issues\">GitHub</a>",
"sponsor": "Хотели бы поддержать разработчиков проекта? Для этого Вы можете перейти на <a href=\"https://github.com/mikebryant/ac-nh-turnip-prices#sponsor-button-repo\">GitHub</a> и нажать '❤ Sponsor'",
"contributors-text": "Точно! Нельзя забывать тех, кто уже помог проекту!",
"contributors": "Вклад внесли",
"language": "Язык"
}
}

View File

@ -1,81 +0,0 @@
{
"general": {
"daisy-mae": "Daisy Mae"
},
"welcome": {
"salutation": "สวัสดีจ้า ยินดีต้อนรับสู่โปรแกรม <b>Turnip Prophet</b> บน Nook Phone ของคุณ",
"description": "โปรแกรมนี้จะช่วยให้คุณสามารถจดบันทึกราคาหัวผักกาดรายวันบนเกาะของคุณ แต่ต้องจดเองนะ!",
"conclusion": "หลังจากนั้น Turnip Prophet จะทำการ<b>พยากรณ์</b>ราคาหัวผักกาดตลอดทั้งสัปดาห์ที่เป็นไปได้ให้คุณ"
},
"first-time": {
"title": "ซื้อครั้งแรก",
"description": "นี่เป็นครั้งแรกที่คุณซื้อหัวผักกาดจากน้องหมูอู๊ดๆ Daisy Mae บนเกาะ<b>ของคุณรีเปล่า</b>?<i>(มีผลกับการคำนวณรูปแบบราคา)</i>",
"yes": "ใช่",
"no": "ไม่"
},
"patterns": {
"title": "รูปแบบก่อนหน้า",
"description": "รูปแบบของราคาสัปดาห์ที่แล้ว?<i>(มีผลกับการคำนวณรูปแบบราคา)</i>",
"pattern": "รูปแบบ",
"all": "รูปแบบทั้งหมด",
"decreasing": "ลดลง",
"fluctuating": "ผันผวน",
"unknown": "ไม่รู้สิ!",
"large-spike": "พุ่งขึ้นสูงมาก",
"small-spike": "พุ่งขึ้นเล็กน้อย"
},
"prices": {
"description": "ราคาหัวผักกาดบนเกาะของคุณสัปดาห์นี้?",
"open": {
"am": "เช้า - 08.00 นาฬิกา ถึง 11.59 นาฬิกา",
"pm": "บ่าย - 12:00 นาฬิกา to 22:00 นาฬิกา"
},
"copy-permalink": "คัดลอก Permalink",
"permalink-copied": "Permalink คัดลอกแล้วจ้า!",
"reset": "รีเซ็ต Turnip Prophet",
"reset-warning": "แน่ใจนะว่าจะล้างข้อมูลทั้งหมด?\n\nแก้ไขอีกไม่ได้แล้วนา!"
},
"weekdays": {
"monday": "วันจันทร์",
"tuesday": "วันอังคาร",
"wednesday": "วันพุธ",
"thursday": "วันพฤหัสบดี",
"friday": "วันศุกร์",
"saturday" : "วันเสาร์",
"sunday": "วันอาทิตย์",
"abr": {
"monday": "จันทร์",
"tuesday": "อังคาร",
"wednesday": "พุธ",
"thursday": "พฤหัส",
"friday": "ศุกร์",
"saturday" : "เสาร์"
}
},
"times": {
"morning": "เช้า",
"afternoon": "บ่าย"
},
"output": {
"title": "ผลลัพธ์",
"chance": "โอกาส %",
"to": "ถึง",
"minimum": "การันตีต่ำสุด",
"maximum": "เป็นไปได้สูงสุด",
"chart": {
"input": "ราคา",
"minimum": "การันตีต่ำสุด",
"maximum": "เป็นไปได้สูงสุด"
}
},
"textbox": {
"description": "หลังจากใส่ราคาหัวผักกาดไปได้บางส่วน โปรแกรม Turnip Prophet จะทำการแสดงตัวเลขราคาและความเป็นไปได้ของรูปแบบต่าง ๆ ที่เกาะของคุณจะเจอ",
"development": "โปรแกรมนี้ยังอยู่ในขั้นตอนพัฒนา แต่จะค่อยๆปรับปรุงขึ้นเรื่อยๆ!",
"thanks": "ทั้งหมดนี้ไม่อาจเกิดขึ้นได้เลยถ้าปราศจากผลงานของ <a href=\"https://twitter.com/_Ninji/status/1244818665851289602?s=20\">Ninji</a> ที่ค้นพบวิธีการให้ราคาหัวผักกาดของทานุกิน้อย Timmy และ Tommy",
"support": "สนับสนุน, แสดงความเห็นและช่วยพัฒนาได้ที่ <a href=\"https://github.com/mikebryant/ac-nh-turnip-prices/issues\">GitHub</a>",
"sponsor": "ต้องการเป็นสปอนเซอร์แก่นักพัฒนา? ไปที่ <a href=\"https://github.com/mikebryant/ac-nh-turnip-prices#sponsor-button-repo\">GitHub</a> และเลือก '❤ Sponsor'",
"contributors-text": "อ้อ! และต้องไม่ลืมที่จะขอบคุณผู้ที่ช่วยร่วมพัฒนามาจนถึงตอนนี้!",
"contributors": "ผู้ร่วมพัฒนา",
"language": "ภาษา"
}
}

View File

@ -1,87 +0,0 @@
{
"general": {
"daisy-mae": "Дейзі Мей"
},
"welcome": {
"salutation": "Добрий день! Вітаємо в додатку <b>Turnip Prophet</b> на Вашому Нукофоні.",
"description": "Цей додаток дозволяє Вам відслідковувати ціни ріпи на Вашому острові щоденно, але Вам доведеться вписати ціни власноруч!",
"conclusion": "Після цього, додаток Turnip Prophet <b>магічним способом</b> передбачить ціни ріпи на Вашому острові на решту тижня."
},
"first-time": {
"title": "Перша покупка ріпи",
"description": "Ви купуєте ріпу від Дейзі Мей на <b>своєму</b> острові вперше?<i>(Це має вплив на модель ціни)</i>",
"yes": "Так",
"no": "Ні"
},
"patterns": {
"title": "Попередня модель ціни",
"description": "Яка модель ціни була попереднього тижня?<i>(Це має вплив на модель ціни)</i>",
"pattern": "Модель",
"all": "Всі моделі",
"decreasing": "Спадаюча",
"fluctuating": "Нестабільна",
"unknown": "Не знаю",
"large-spike": "Великий скачок",
"small-spike": "Малий скачок"
},
"prices": {
"description": "Які ціни ріпи були на Вашому острові цього тижня?",
"open": {
"am": "Перед обідом - від 8:00 до 11:59",
"pm": "Після обіду - від 12:00 до 22:00"
},
"copy-permalink": "Копіювати посилання",
"permalink-copied": "Посилання скопійоване!",
"reset": "Перезапустити Turnip Prophet",
"reset-warning": "Ви впевнені що хочете стерти всі поля?\n\nВтрачені дані неможливо повернути!"
},
"weekdays": {
"monday": "Понеділок",
"tuesday": "Вівторок",
"wednesday": "Середа",
"thursday": "Четвер",
"friday": "П'ятниця",
"saturday" : "Субота",
"sunday": "Неділя",
"abr": {
"monday": "Пон.",
"tuesday": "Вівт.",
"wednesday": "Сер.",
"thursday": "Четв.",
"friday": "П'ятн.",
"saturday" : "Суб."
}
},
"times": {
"morning": "Перед обідом",
"afternoon": "Після обіду"
},
"output": {
"title": "Результат",
"chance": "% Шансу",
"to": "до",
"minimum": "Гарантований мінімум",
"maximum": "Можливий максимум",
"chart": {
"input": "Вхідна ціна",
"minimum": "Гарантований мінімум",
"maximum": "Можливий максимум"
}
},
"textbox": {
"description": "Після того, як Ви запишете делілька цін на ріпу, додаток Turnip Prophet підрахує і покаже різні можливі моделі цін на Вашому острові.",
"development": "Цей додаток ще в розробці, але напевно з часом покращиться!",
"thanks": "Цей додаток не був би можливий без <a href=\"https://twitter.com/_Ninji/status/1244818665851289602?s=20\">праці Ninji</a>, котрий дізнався як саме Тіммі і Томмі оцінюють їх ріпу.",
"support": "Ви можете підтримати, зробити коментар, або внесок до проекту на сторінці <a href=\"https://github.com/mikebryant/ac-nh-turnip-prices/issues\">GitHub</a>",
"sponsor": "Хочете заспонсорувати розробників проекту? Відвідайте сторінку <a href=\"https://github.com/mikebryant/ac-nh-turnip-prices#sponsor-button-repo\">GitHub</a> і натисніть '❤ Sponsor'",
"contributors-text": "До речі! Не забудьмо подякувати людям, які зробили внесок до проекту!",
"contributors": "Зробили внесок",
"language": "Мова",
"theme": {
"title": "Тема",
"auto": "Автоматична",
"light": "Світла",
"dark": "Темна"
}
}
}

View File

@ -1,87 +0,0 @@
{
"general": {
"daisy-mae": "曹卖"
},
"welcome": {
"salutation": "大家好欢迎使用Nook手机上的<b>大头菜预测工具</b>。",
"description": "这个APP可以让你每天跟踪自己岛上大头菜的价格但你得自己把价格填写进去",
"conclusion": "之后,大头菜预测工具会<b>神奇地</b>预测出本周剩余时间的大头菜价格。"
},
"first-time": {
"title": "首次购买",
"description": "你是第一次在自己岛上购买大头菜吗?<i>(将影响预测趋势)</i>",
"yes": "是",
"no": "否"
},
"patterns": {
"title": "上周趋势",
"description": "上周大头菜的价格趋势是?<i>(将影响预测趋势)</i>",
"pattern": "趋势",
"all": "所有趋势",
"decreasing": "递减型",
"fluctuating": "波动型",
"unknown": "不知道",
"large-spike": "大幅上涨(三期型)",
"small-spike": "小幅上涨(四期型)"
},
"prices": {
"description": "本周你的岛上大头菜的购买价格是多少?",
"open": {
"am": "上午 - 8:00 ~ 11:59",
"pm": "下午 - 12:00 ~ 22:00"
},
"copy-permalink": "复制价格分享链接",
"permalink-copied": "链接已复制!",
"reset": "重置大头菜预测工具",
"reset-warning": "你确定要重置所有字段吗?\n\n此操作不可撤销"
},
"weekdays": {
"monday": "周一",
"tuesday": "周二",
"wednesday": "周三",
"thursday": "周四",
"friday": "周五",
"saturday" : "周六",
"sunday": "周日",
"abr": {
"monday": "周一",
"tuesday": "周二",
"wednesday": "周三",
"thursday": "周四",
"friday": "周五",
"saturday" : "周六"
}
},
"times": {
"morning": "上午",
"afternoon": "下午"
},
"output": {
"title": "结果",
"chance": "几率(%)",
"to": "~",
"minimum": "保底价格",
"maximum": "最高价格",
"chart": {
"input": "输入价格",
"minimum": "保底价格",
"maximum": "最高价格"
}
},
"textbox": {
"description": "在填写一些大头菜价格后,大头菜预测工具将预测大头菜的价格并显示本周可能的趋势。",
"development": "APP仍在开发中但会随着时间的推移不断完善",
"thanks": "如果不是 <a href=\"https://twitter.com/_Ninji/status/1244818665851289602?s=20\">Ninji</a> 发现豆狸和粒狸如何给大头菜定价的,这一切将不可能实现。",
"support": "可以在 <a href=\"https://github.com/mikebryant/ac-nh-turnip-prices/issues\">GitHub</a> 获得支持,或讨论和贡献",
"sponsor": "想要赞助这个项目的开发者?进入 <a href=\"https://github.com/mikebryant/ac-nh-turnip-prices#sponsor-button-repo\">GitHub</a> 并点击 ❤ Sponsor",
"contributors-text": "哦!别忘记感谢那些至今为止做出过贡献的人。",
"contributors": "贡献者",
"language": "语言",
"theme": {
"title": "主题",
"auto": "自动",
"light": "亮色",
"dark": "暗色"
}
}
}

View File

@ -1,87 +0,0 @@
{
"general": {
"daisy-mae": "曹賣"
},
"welcome": {
"salutation": "你好,歡迎使用 Nook 手機上的 <b>Turnip Prophet</b>。",
"description": "這個工具可以讓你每天追蹤自己島上的大頭菜價格,但你必須自己輸入價格!",
"conclusion": "接下來Turnip Prophet 將 <b>神奇地</b> 預測本週剩餘時間的大頭菜價格。"
},
"first-time": {
"title": "首次購買",
"description": "這是你第一次從自己島上和曹賣購買大頭菜嗎?<i>(將影響這次的模型)</i>",
"yes": "是",
"no": "否"
},
"patterns": {
"title": "上次的模型",
"description": "上週大頭菜的價格模型是什麼?<i>(將影響這次的模型)</i>",
"pattern": "模型",
"all": "所有模型",
"decreasing": "遞減型",
"fluctuating": "波型",
"unknown": "不知道",
"large-spike": "三期型",
"small-spike": "四期型"
},
"prices": {
"description": "本週自己島上的大頭菜買價?",
"open": {
"am": "上午 - 08:00 到 11:59",
"pm": "下午 - 12:00 到 22:00"
},
"copy-permalink": "複製價格分享網址",
"permalink-copied": "網址已複製!",
"reset": "清除資料",
"reset-warning": "是否確定要清除所有資料?\n\n此動作無法復原"
},
"weekdays": {
"monday": "星期一",
"tuesday": "星期二",
"wednesday": "星期三",
"thursday": "星期四",
"friday": "星期五",
"saturday" : "星期六",
"sunday": "星期日",
"abr": {
"monday": "週一",
"tuesday": "週二",
"wednesday": "週三",
"thursday": "週四",
"friday": "週五",
"saturday" : "週六"
}
},
"times": {
"morning": "上午",
"afternoon": "下午"
},
"output": {
"title": "結果",
"chance": "機率(%)",
"to": "~",
"minimum": "保底價格",
"maximum": "最高價格",
"chart": {
"input": "輸入價格",
"minimum": "保底價格",
"maximum": "最高價格"
}
},
"textbox": {
"description": "在你記錄了一些大頭菜價格後Turnip Prophet 會預測,並顯示自己島上可能出現的不同模型。",
"development": "此工具仍在開發中,但會隨著時間的推移而改善!",
"thanks": "要不是 <a href=\"https://twitter.com/_Ninji/status/1244818665851289602?s=20\">Ninji</a> 協助釐清豆狸和粒狸的大頭菜估價方式,這一切都不可能實現。",
"support": "可於 <a href=\"https://github.com/mikebryant/ac-nh-turnip-prices/issues\">GitHub</a> 取得支援、討論及貢獻。",
"sponsor": "想要贊助這個專案的開發者?進入 <a href=\"https://github.com/mikebryant/ac-nh-turnip-prices#sponsor-button-repo\">GitHub</a> 並按下 ❤ Sponsor",
"contributors-text": "嘿!別忘了感謝那些迄今為止作出貢獻的人!",
"contributors": "貢獻者",
"language": "語言",
"theme": {
"title": "主題",
"auto": "自動",
"light": "亮色",
"dark": "暗色"
}
}
}

View File

@ -1,19 +0,0 @@
{
"name": "Turnip Prophet - ACNH Turnip Tracker",
"short_name": "Turnip Prophet",
"description": "An app to track your Animal Crossing: New Horizons turnip prices daily!",
"start_url": "index.html",
"display": "standalone",
"background_color": "#def2d9",
"theme_color": "#def2d9",
"icons": [
{
"src": "/img/favicon-192.png",
"sizes": "192x192"
},
{
"src": "/img/favicon-512.png",
"sizes": "512x512"
}
]
}

View File

@ -1,75 +0,0 @@
// PWA Code adapted from https://github.com/pwa-builder/PWABuilder
const CACHE = "pwa-precache-v1";
const precacheFiles = [
"/index.html",
"/js/predictions.js",
"/js/scripts.js",
"/css/styles.css",
"https://code.jquery.com/jquery-3.4.1.min.js",
];
self.addEventListener("install", function (event) {
console.log("[PWA] Install Event processing");
console.log("[PWA] Skip waiting on install");
self.skipWaiting();
event.waitUntil(
caches.open(CACHE).then(function (cache) {
console.log("[PWA] Caching pages during install");
return cache.addAll(precacheFiles);
})
);
});
// Allow sw to control of current page
self.addEventListener("activate", function (event) {
console.log("[PWA] Claiming clients for current page");
event.waitUntil(self.clients.claim());
});
// If any fetch fails, it will look for the request in the cache and serve it from there first
self.addEventListener("fetch", function (event) {
if (event.request.method !== "GET") return;
event.respondWith(
(async () => {
let response;
try {
// Fetch from network first.
response = await fetch(event.request);
event.waitUntil(updateCache(event.request, response.clone()));
} catch (error) {
try {
// Try if there's locally cached version.
response = await fromCache(event.request);
} catch (error) {
console.log("[PWA] Network request failed and no cache." + error);
throw error;
}
}
return response;
})()
);
});
function fromCache(request) {
// Check to see if you have it in the cache
// Return response
// If not in the cache, then return
return caches.open(CACHE).then(function (cache) {
return cache.match(request).then(function (matching) {
if (!matching || matching.status === 404) {
return Promise.reject("no-match");
}
return matching;
});
});
}
function updateCache(request, response) {
return caches.open(CACHE).then(function (cache) {
return cache.put(request, response);
});
}