Merge remote-tracking branch 'upstream/master'

master
David Corry 4 years ago
commit b306692d6f

@ -208,7 +208,8 @@ h2 {
outline: none; outline: none;
} }
.dialog-box p { .dialog-box p,
.dialog-box label {
font-family: 'Raleway', sans-serif; font-family: 'Raleway', sans-serif;
font-weight: 800; font-weight: 800;
font-size: 1rem; font-size: 1rem;

@ -121,7 +121,7 @@
<div class="form__row"> <div class="form__row">
<h6 data-i18n="weekdays.sunday"></h6> <h6 data-i18n="weekdays.sunday"></h6>
<div class="input__group"> <div class="input__group">
<label data-i18n="[html]prices.description"></label> <label data-i18n="[html]prices.description" for='buy'></label>
<input type="number" pattern="\d*" id="buy" placeholder="..." /> <input type="number" pattern="\d*" id="buy" placeholder="..." />
</div> </div>
@ -308,10 +308,10 @@
<p id="contributors"><span data-i18n="textbox.contributors"></span>: </p> <p id="contributors"><span data-i18n="textbox.contributors"></span>: </p>
<p data-i18n="[html]textbox.sponsor"></p> <p data-i18n="[html]textbox.sponsor"></p>
<div class="dialog-box-option"> <div class="dialog-box-option">
<p data-i18n="textbox.language"></p><p>:</p> <select id="language"></select> <p><label for='language' data-i18n="textbox.language"></label>:</p> <select id="language"></select>
</div> </div>
<div class="dialog-box-option"> <div class="dialog-box-option">
<p data-i18n="textbox.theme.title"></p><p>:</p> <select id="theme"></select> <p><label for='theme' data-i18n="textbox.theme.title"></label>:</p> <select id="theme"></select>
</div> </div>
</div> </div>

@ -657,7 +657,6 @@ class Predictor {
} }
yield { yield {
pattern_description: i18next.t("patterns.fluctuating"),
pattern_number: 0, pattern_number: 0,
prices: predicted_prices, prices: predicted_prices,
probability, probability,
@ -725,8 +724,8 @@ class Predictor {
} }
// Now each day is independent of next // 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 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] 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++) { for (let i = peak_start; i < 14; i++) {
probability *= this.generate_individual_random_price( probability *= this.generate_individual_random_price(
given_prices, predicted_prices, i, 1, min_randoms[i - peak_start], given_prices, predicted_prices, i, 1, min_randoms[i - peak_start],
@ -736,7 +735,6 @@ class Predictor {
} }
} }
yield { yield {
pattern_description: i18next.t("patterns.large-spike"),
pattern_number: 1, pattern_number: 1,
prices: predicted_prices, prices: predicted_prices,
probability, probability,
@ -783,7 +781,6 @@ class Predictor {
} }
yield { yield {
pattern_description: i18next.t("patterns.decreasing"),
pattern_number: 2, pattern_number: 2,
prices: predicted_prices, prices: predicted_prices,
probability, probability,
@ -864,7 +861,6 @@ class Predictor {
} }
yield { yield {
pattern_description: i18next.t("patterns.small-spike"),
pattern_number: 3, pattern_number: 3,
prices: predicted_prices, prices: predicted_prices,
probability, probability,
@ -909,11 +905,11 @@ class Predictor {
} else { } else {
// All buy prices are equal probability and we're at the outmost layer, // All buy prices are equal probability and we're at the outmost layer,
// so don't need to multiply_generator_probability here. // so don't need to multiply_generator_probability here.
yield* this.generate_all_patterns(temp_sell_prices, previous_pattern) yield* this.generate_all_patterns(temp_sell_prices, previous_pattern);
} }
} }
} else { } else {
yield* this.generate_all_patterns(sell_prices, previous_pattern) yield* this.generate_all_patterns(sell_prices, previous_pattern);
} }
} }
@ -921,7 +917,7 @@ class Predictor {
const sell_prices = this.prices; const sell_prices = this.prices;
const first_buy = this.first_buy; const first_buy = this.first_buy;
const previous_pattern = this.previous_pattern; const previous_pattern = this.previous_pattern;
let generated_possibilities = [] let generated_possibilities = [];
for (let i = 0; i < 6; i++) { for (let i = 0; i < 6; i++) {
this.fudge_factor = i; this.fudge_factor = i;
generated_possibilities = Array.from(this.generate_possibilities(sell_prices, first_buy, previous_pattern)); generated_possibilities = Array.from(this.generate_possibilities(sell_prices, first_buy, previous_pattern));
@ -958,7 +954,7 @@ class Predictor {
poss.weekMax = Math.max(...weekMaxes); poss.weekMax = Math.max(...weekMaxes);
} }
let category_totals = {} let category_totals = {};
for (let i of [0, 1, 2, 3]) { for (let i of [0, 1, 2, 3]) {
category_totals[i] = generated_possibilities category_totals[i] = generated_possibilities
.filter(value => value.pattern_number == i) .filter(value => value.pattern_number == i)
@ -979,7 +975,7 @@ class Predictor {
const prices = { const prices = {
min: 999, min: 999,
max: 0, max: 0,
} };
for (let poss of generated_possibilities) { for (let poss of generated_possibilities) {
if (poss.prices[day].min < prices.min) { if (poss.prices[day].min < prices.min) {
prices.min = poss.prices[day].min; prices.min = poss.prices[day].min;
@ -992,7 +988,6 @@ class Predictor {
} }
generated_possibilities.unshift({ generated_possibilities.unshift({
pattern_description: i18next.t("patterns.all"),
pattern_number: 4, pattern_number: 4,
prices: global_min_max, prices: global_min_max,
weekGuaranteedMinimum: Math.min(...generated_possibilities.map(poss => poss.weekGuaranteedMinimum)), weekGuaranteedMinimum: Math.min(...generated_possibilities.map(poss => poss.weekGuaranteedMinimum)),

@ -1,18 +1,18 @@
//Reusable Fields //Reusable Fields
const getSellFields = function () { const getSellFields = function () {
let fields = [] let fields = [];
for (var i = 2; i < 14; i++) { for (var i = 2; i < 14; i++) {
fields.push($("#sell_" + i)[0]) fields.push($("#sell_" + i)[0]);
} }
return fields return fields;
} };
const getFirstBuyRadios = function () { const getFirstBuyRadios = function () {
return [ return [
$("#first-time-radio-no")[0], $("#first-time-radio-no")[0],
$("#first-time-radio-yes")[0] $("#first-time-radio-yes")[0]
]; ];
} };
const getPreviousPatternRadios = function () { const getPreviousPatternRadios = function () {
return [ return [
@ -22,11 +22,11 @@ const getPreviousPatternRadios = function () {
$("#pattern-radio-large-spike")[0], $("#pattern-radio-large-spike")[0],
$("#pattern-radio-decreasing")[0] $("#pattern-radio-decreasing")[0]
]; ];
} };
const getCheckedRadio = function (radio_array) { const getCheckedRadio = function (radio_array) {
return radio_array.find(radio => radio.checked === true).value; return radio_array.find(radio => radio.checked === true).value;
} };
const checkRadioByValue = function (radio_array, value) { const checkRadioByValue = function (radio_array, value) {
if (value === null) { if (value === null) {
@ -34,15 +34,15 @@ const checkRadioByValue = function (radio_array, value) {
} }
value = value.toString(); value = value.toString();
radio_array.find(radio => radio.value == value).checked = true; radio_array.find(radio => radio.value == value).checked = true;
} };
const sell_inputs = getSellFields() const sell_inputs = getSellFields();
const buy_input = $("#buy") const buy_input = $("#buy");
const first_buy_radios = getFirstBuyRadios() const first_buy_radios = getFirstBuyRadios();
const previous_pattern_radios = getPreviousPatternRadios() const previous_pattern_radios = getPreviousPatternRadios();
const permalink_input = $('#permalink-input') const permalink_input = $('#permalink-input');
const permalink_button = $('#permalink-btn') const permalink_button = $('#permalink-btn');
const snackbar = $('#snackbar') const snackbar = $('#snackbar');
//Functions //Functions
const fillFields = function (prices, first_buy, previous_pattern) { const fillFields = function (prices, first_buy, previous_pattern) {
@ -50,21 +50,21 @@ const fillFields = function (prices, first_buy, previous_pattern) {
checkRadioByValue(previous_pattern_radios, previous_pattern); checkRadioByValue(previous_pattern_radios, previous_pattern);
buy_input.focus(); buy_input.focus();
buy_input.val(prices[0] || '') buy_input.val(prices[0] || '');
buy_input.blur(); buy_input.blur();
const sell_prices = prices.slice(2) const sell_prices = prices.slice(2);
sell_prices.forEach((price, index) => { sell_prices.forEach((price, index) => {
if (!price) { if (!price) {
return return;
} else { } else {
const element = $("#sell_" + (index + 2)); const element = $("#sell_" + (index + 2));
element.focus(); element.focus();
element.val(price); element.val(price);
element.blur(); element.blur();
} }
}) });
} };
const initialize = function () { const initialize = function () {
try { try {
@ -73,9 +73,9 @@ const initialize = function () {
const previous_pattern = previous[1]; const previous_pattern = previous[1];
const prices = previous[2]; const prices = previous[2];
if (prices === null) { if (prices === null) {
fillFields([], first_buy, previous_pattern) fillFields([], first_buy, previous_pattern);
} else { } else {
fillFields(prices, first_buy, previous_pattern) fillFields(prices, first_buy, previous_pattern);
} }
} catch (e) { } catch (e) {
console.error(e); console.error(e);
@ -83,32 +83,32 @@ const initialize = function () {
$(document).trigger("input"); $(document).trigger("input");
$("#permalink-btn").on("click", copyPermalink) $("#permalink-btn").on("click", copyPermalink);
$("#reset").on("click", function () { $("#reset").on("click", function () {
if (window.confirm(i18next.t("prices.reset-warning"))) { if (window.confirm(i18next.t("prices.reset-warning"))) {
sell_inputs.forEach(input => input.value = '') sell_inputs.forEach(input => input.value = '');
fillFields([], false, -1) fillFields([], false, -1);
update() update();
} }
}) });
} };
const updateLocalStorage = function (prices, first_buy, previous_pattern) { const updateLocalStorage = function (prices, first_buy, previous_pattern) {
try { try {
if (prices.length !== 14) throw "The data array needs exactly 14 elements to be valid" if (prices.length !== 14) throw "The data array needs exactly 14 elements to be valid";
localStorage.setItem("sell_prices", JSON.stringify(prices)) localStorage.setItem("sell_prices", JSON.stringify(prices));
localStorage.setItem("first_buy", JSON.stringify(first_buy)); localStorage.setItem("first_buy", JSON.stringify(first_buy));
localStorage.setItem("previous_pattern", JSON.stringify(previous_pattern)); localStorage.setItem("previous_pattern", JSON.stringify(previous_pattern));
} catch (e) { } catch (e) {
console.error(e) console.error(e);
} }
} };
const isEmpty = function (arr) { const isEmpty = function (arr) {
const filtered = arr.filter(value => value !== null && value !== '' && !isNaN(value)) const filtered = arr.filter(value => value !== null && value !== '' && !isNaN(value));
return filtered.length == 0 return filtered.length == 0;
} };
const getFirstBuyStateFromQuery = function (param) { const getFirstBuyStateFromQuery = function (param) {
try { try {
@ -131,15 +131,15 @@ const getFirstBuyStateFromQuery = function (param) {
} catch (e) { } catch (e) {
return null; return null;
} }
} };
const getFirstBuyStateFromLocalstorage = function () { const getFirstBuyStateFromLocalstorage = function () {
return JSON.parse(localStorage.getItem('first_buy')) return JSON.parse(localStorage.getItem('first_buy'));
} };
const getPreviousPatternStateFromLocalstorage = function () { const getPreviousPatternStateFromLocalstorage = function () {
return JSON.parse(localStorage.getItem('previous_pattern')) return JSON.parse(localStorage.getItem('previous_pattern'));
} };
const getPreviousPatternStateFromQuery = function (param) { const getPreviousPatternStateFromQuery = function (param) {
try { try {
@ -167,7 +167,7 @@ const getPreviousPatternStateFromQuery = function (param) {
} catch (e) { } catch (e) {
return null; return null;
} }
} };
const getPricesFromLocalstorage = function () { const getPricesFromLocalstorage = function () {
try { try {
@ -245,8 +245,8 @@ const getSellPrices = function () {
//Checks all sell inputs and returns an array with their values //Checks all sell inputs and returns an array with their values
return res = sell_inputs.map(function (input) { return res = sell_inputs.map(function (input) {
return parseInt(input.value || ''); return parseInt(input.value || '');
}) });
} };
const getPriceClass = function(buy_price, max) { const getPriceClass = function(buy_price, max) {
const priceBrackets = [200, 30, 0, -30, -99]; const priceBrackets = [200, 30, 0, -30, -99];
@ -257,7 +257,7 @@ const getPriceClass = function(buy_price, max) {
} }
} }
return ""; return "";
} };
const displayPercentage = function(fraction) { const displayPercentage = function(fraction) {
if (Number.isFinite(fraction)) { if (Number.isFinite(fraction)) {
@ -270,28 +270,29 @@ const displayPercentage = function(fraction) {
return '<0.01%'; return '<0.01%';
} }
} else { } else {
return '—' return '—';
} }
} };
const calculateOutput = function (data, first_buy, previous_pattern) { const calculateOutput = function (data, first_buy, previous_pattern) {
if (isEmpty(data)) { if (isEmpty(data)) {
$("#output").html(""); $("#output").html("");
return; return;
} }
let pat_desc = {0:"fluctuating", 1:"large-spike", 2:"decreasing", 3:"small-spike", 4:"all"};
let output_possibilities = ""; let output_possibilities = "";
let predictor = new Predictor(data, first_buy, previous_pattern); let predictor = new Predictor(data, first_buy, previous_pattern);
let analyzed_possibilities = predictor.analyze_possibilities(); let analyzed_possibilities = predictor.analyze_possibilities();
let buy_price = parseInt(buy_input.val()); let buy_price = parseInt(buy_input.val());
previous_pattern_number = "" previous_pattern_number = "";
for (let poss of analyzed_possibilities) { for (let poss of analyzed_possibilities) {
var out_line = "<tr><td class='table-pattern'>" + poss.pattern_description + "</td>"; 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; const style_price = buy_price || poss.prices[0].min;
if (previous_pattern_number != poss.pattern_number) { if (previous_pattern_number != poss.pattern_number) {
previous_pattern_number = poss.pattern_number previous_pattern_number = poss.pattern_number;
pattern_count = analyzed_possibilities pattern_count = analyzed_possibilities
.filter(val => val.pattern_number == poss.pattern_number) .filter(val => val.pattern_number == poss.pattern_number)
.length .length;
out_line += `<td rowspan=${pattern_count}>${displayPercentage(poss.category_total_probability)}</td>`; out_line += `<td rowspan=${pattern_count}>${displayPercentage(poss.category_total_probability)}</td>`;
} }
out_line += `<td>${displayPercentage(poss.probability)}</td>`; out_line += `<td>${displayPercentage(poss.probability)}</td>`;
@ -307,13 +308,13 @@ const calculateOutput = function (data, first_buy, previous_pattern) {
var min_class = getPriceClass(style_price, poss.weekGuaranteedMinimum); var min_class = getPriceClass(style_price, poss.weekGuaranteedMinimum);
var max_class = getPriceClass(style_price, poss.weekMax); 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>`; out_line += `<td class='${min_class}'>${poss.weekGuaranteedMinimum}</td><td class='${max_class}'>${poss.weekMax}</td></tr>`;
output_possibilities += out_line output_possibilities += out_line;
} }
$("#output").html(output_possibilities) $("#output").html(output_possibilities);
update_chart(data, analyzed_possibilities); update_chart(data, analyzed_possibilities);
} };
const generatePermalink = function (buy_price, sell_prices, first_buy, previous_pattern) { const generatePermalink = function (buy_price, sell_prices, first_buy, previous_pattern) {
let searchParams = new URLSearchParams(); let searchParams = new URLSearchParams();
@ -337,7 +338,7 @@ const generatePermalink = function (buy_price, sell_prices, first_buy, previous_
} }
return searchParams.toString() && window.location.origin.concat('?', searchParams.toString()); return searchParams.toString() && window.location.origin.concat('?', searchParams.toString());
} };
const copyPermalink = function () { const copyPermalink = function () {
let text = permalink_input[0]; let text = permalink_input[0];
@ -350,17 +351,17 @@ const copyPermalink = function () {
permalink_input.hide(); permalink_input.hide();
flashMessage(i18next.t("prices.permalink-copied")); flashMessage(i18next.t("prices.permalink-copied"));
} };
const flashMessage = function(message) { const flashMessage = function(message) {
snackbar.text(message); snackbar.text(message);
snackbar.addClass('show'); snackbar.addClass('show');
setTimeout(function () { setTimeout(function () {
snackbar.removeClass('show') snackbar.removeClass('show');
snackbar.text(''); snackbar.text('');
}, 3000); }, 3000);
} };
const update = function () { const update = function () {
const sell_prices = getSellPrices(); const sell_prices = getSellPrices();
@ -383,4 +384,4 @@ const update = function () {
} }
calculateOutput(prices, first_buy, previous_pattern); calculateOutput(prices, first_buy, previous_pattern);
} };

@ -3,7 +3,7 @@
"daisy-mae": "Daisy Mae" "daisy-mae": "Daisy Mae"
}, },
"welcome": { "welcome": {
"salutation": "Cześć, witam w aplikacji <b>Turnip Prophet</b> na Twoim Nook Phone.", "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.", "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" "conclusion": "Następnie aplikacja Turnip Prophet <b>w magiczny sposób</b> przewidzi jakie ceny rzep będziesz mieć przez resztę tygodnia"
}, },
@ -54,7 +54,7 @@
}, },
"times": { "times": {
"morning": "Rano", "morning": "Rano",
"afternoon": "Południe" "afternoon": "Popołudnie"
}, },
"output": { "output": {
"title": "Wyniki", "title": "Wyniki",
@ -73,9 +73,9 @@
"development": "Ta aplikacja wciąż jest w produkcji, lecz z czasem zostanie poprawiona!", "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.", "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>", "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'", "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": "Oh! I nie zapominajmy o tych, którzy dotychczas nas wspierali!", "contributors-text": "Aha! I nie zapominajmy o tych, którzy dotychczas nas wspierali!",
"contributors": "Fundatorzy", "contributors": "Współautorzy",
"language": "Język" "language": "Język"
} }
} }

@ -69,7 +69,7 @@
} }
}, },
"textbox": { "textbox": {
"description": "在你錄了一些大頭菜價格後Turnip Prophet 會預測,並顯示自己島上可能出現的不同模型。", "description": "在你錄了一些大頭菜價格後Turnip Prophet 會預測,並顯示自己島上可能出現的不同模型。",
"development": "此工具仍在開發中,但會隨著時間的推移而改善!", "development": "此工具仍在開發中,但會隨著時間的推移而改善!",
"thanks": "要不是 <a href=\"https://twitter.com/_Ninji/status/1244818665851289602?s=20\">Ninji</a> 協助釐清豆狸和粒狸的大頭菜估價方式,這一切都不可能實現。", "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> 取得支援、討論及貢獻。", "support": "可於 <a href=\"https://github.com/mikebryant/ac-nh-turnip-prices/issues\">GitHub</a> 取得支援、討論及貢獻。",

Loading…
Cancel
Save