removed fun-shit
|
@ -1,3 +0,0 @@
|
|||
github:
|
||||
- mikebryant
|
||||
- theRTC204
|
|
@ -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.
|
|
@ -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.
|
|
@ -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.
|
|
@ -1 +0,0 @@
|
|||
turnipprophet.io
|
|
@ -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.
|
|
@ -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.
|
|
@ -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
|
|
@ -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.
|
|
@ -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;
|
||||
}
|
||||
}
|
Before Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 14 KiB |
Before Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 16 KiB |
Before Width: | Height: | Size: 18 KiB |
Before Width: | Height: | Size: 18 KiB |
Before Width: | Height: | Size: 2.1 KiB |
Before Width: | Height: | Size: 48 KiB |
|
@ -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>
|
|
@ -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",
|
||||
});
|
||||
}
|
||||
}
|
|
@ -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));
|
|
@ -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 Kahan–Babuska 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;
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
};
|
|
@ -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();
|
||||
});
|
||||
});
|
|
@ -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);
|
||||
});
|
|
@ -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"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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é"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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"
|
||||
}
|
||||
}
|
|
@ -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>"
|
||||
}
|
||||
}
|
|
@ -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"
|
||||
}
|
||||
}
|
|
@ -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"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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"
|
||||
}
|
||||
}
|
|
@ -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"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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"
|
||||
}
|
||||
}
|
|
@ -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"
|
||||
}
|
||||
}
|
|
@ -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": "ダーク"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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": "언어"
|
||||
}
|
||||
}
|
|
@ -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"
|
||||
}
|
||||
}
|
|
@ -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"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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"
|
||||
}
|
||||
}
|
|
@ -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"
|
||||
}
|
||||
}
|
|
@ -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": "Язык"
|
||||
}
|
||||
}
|
|
@ -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": "ภาษา"
|
||||
}
|
||||
}
|
|
@ -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": "Темна"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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": "暗色"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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": "暗色"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -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);
|
||||
});
|
||||
}
|