From 09e8e4e37ac5f8dd0d8fcda7a3959c495a61dbdc Mon Sep 17 00:00:00 2001 From: Pi-Hsun Shih Date: Wed, 15 Apr 2020 21:57:08 +0800 Subject: [PATCH 01/70] Make probability accurate by condition probability on the value. Tested that the result is same as the "should report" in #95. Fix #48, #95. --- js/predictions.js | 484 +++++++++++++++++++++++++++++++++++----------- 1 file changed, 368 insertions(+), 116 deletions(-) diff --git a/js/predictions.js b/js/predictions.js index 27b5e93..c5da355 100644 --- a/js/predictions.js +++ b/js/predictions.js @@ -9,13 +9,6 @@ const PATTERN = { SMALL_SPIKE: 3, }; -const PATTERN_COUNTS = { - [PATTERN.FLUCTUATING]: 56, - [PATTERN.LARGE_SPIKE]: 7, - [PATTERN.DECREASING]: 1, - [PATTERN.SMALL_SPIKE]: 8, -}; - const PROBABILITY_MATRIX = { [PATTERN.FLUCTUATING]: { [PATTERN.FLUCTUATING]: 0.20, @@ -57,10 +50,42 @@ function maximum_rate_from_given_and_base(given_price, buy_price) { return RATE_MULTIPLIER * (given_price + 0.00001) / buy_price; } +function rate_range_from_given_and_base(given_price, buy_price) { + return [ + minimum_rate_from_given_and_base(given_price, buy_price), + maximum_rate_from_given_and_base(given_price, buy_price) + ]; +} + function get_price(rate, basePrice) { return intceil(rate * basePrice / RATE_MULTIPLIER); } +function* multiply_generator_probability(generator, probability) { + for (const it of generator) { + yield {...it, probability: it.probability * probability}; + } +} + +function range_length(range) { + return range[1] - range[0]; +} + +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)); +} + + /* * This corresponds to the code: * for (int i = start; i < start + length; i++) @@ -69,8 +94,9 @@ function get_price(rate, basePrice) { * intceil(randfloat(rate_min / RATE_MULTIPLIER, rate_max / RATE_MULTIPLIER) * basePrice); * } * - * Would modify the predicted_prices array. - * If the given_prices won't match, returns false, otherwise returns true + * Would return the conditional probability given the given_prices, and modify + * the predicted_prices array. + * If the given_prices won't match, returns 0. */ function generate_individual_random_price( given_prices, predicted_prices, start, length, rate_min, rate_max) { @@ -78,6 +104,8 @@ function generate_individual_random_price( 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 = get_price(rate_min, buy_price); @@ -85,7 +113,14 @@ function generate_individual_random_price( if (!isNaN(given_prices[i])) { if (given_prices[i] < min_pred - FUDGE_FACTOR || given_prices[i] > max_pred + FUDGE_FACTOR) { // Given price is out of predicted range, so this is the wrong pattern - return false; + return 0; + } + if (given_prices[i] >= min_pred || given_prices[i] <= max_pred) { + // The value in the FUDGE_FACTOR range is ignored so that it don't give a probability 0. + const real_rate_range = + rate_range_from_given_and_base(given_prices[i], 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]; @@ -96,7 +131,144 @@ function generate_individual_random_price( max: max_pred, }); } - return true; + return prob; +} + +/* + * Probability Density Function of rates. + * Since the PDF is continuous*, we approximate it by a discrete probability function: + * the value in range [(x - 0.5), (x + 0.5)) 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. + */ + constructor(a, b, uniform = true) { + this.value_start = Math.round(a); + this.value_end = Math.round(b); + const range = [a, b]; + const total_length = range_length(range); + this.prob = Array(this.value_end - this.value_start + 1); + if (uniform) { + for (let i = 0; i < this.prob.length; i++) { + this.prob[i] = + range_intersect_length(this.range_of(i), range) / total_length; + } + } + } + + range_of(idx) { + // TODO: consider doing the "exclusive end" properly. + return [this.value_start + idx - 0.5, this.value_start + idx + 0.5 - 1e-9]; + } + + min_value() { + return this.value_start - 0.5; + } + + max_value() { + return this.value_end + 0.5 - 1e-9; + } + + normalize() { + const total_probability = this.prob.reduce((acc, it) => acc + it, 0); + for (let i = 0; i < this.prob.length; i++) { + this.prob[i] /= 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; + } + + let prob = 0; + const start_idx = Math.round(start) - this.value_start; + const end_idx = Math.round(end) - this.value_start; + for (let i = start_idx; i <= end_idx; i++) { + const bucket_prob = this.prob[i] * range_intersect_length(this.range_of(i), range); + this.prob[i] = bucket_prob; + prob += bucket_prob; + } + + this.prob = this.prob.slice(start_idx, end_idx + 1); + this.value_start = Math.round(start); + this.value_end = Math.round(end); + this.normalize(); + + return prob; + } + + /* + * 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. + */ + decay(rate_decay_min, rate_decay_max) { + const ret = new PDF( + this.min_value() - rate_decay_max, this.max_value() - rate_decay_min, false); + /* + // O(n^2) naive algorithm for reference, which would be too slow. + for (let i = this.value_start; i <= this.value_end; i++) { + const unit_prob = this.prob[i - this.value_start] / (rate_decay_max - rate_decay_min) / 2; + for (let j = rate_decay_min; j < rate_decay_max; j++) { + // ([i - 0.5, i + 0.5] uniform) - ([j, j + 1] uniform) + // -> [i - j - 1.5, i + 0.5 - j] with a triangular PDF + // -> approximate by + // [i - j - 1.5, i - j - 0.5] uniform & + // [i - j - 0.5, i - j + 0.5] uniform + ret.prob[i - j - 1 - ret.value_start] += unit_prob; // Part A + ret.prob[i - j - ret.value_start] += unit_prob; // Part B + } + } + */ + // Transform to "CDF" + for (let i = 1; i < this.prob.length; i++) { + this.prob[i] += this.prob[i - 1]; + } + // Return this.prob[l - this.value_start] + ... + this.prob[r - 1 - this.value_start]; + // This assume that this.prob is already transformed to "CDF". + const sum = (l, r) => { + l -= this.value_start; + r -= this.value_start; + if (l < 0) l = 0; + if (r > this.prob.length) r = this.prob.length; + if (l >= r) return 0; + return this.prob[r - 1] - (l == 0 ? 0 : this.prob[l - 1]); + }; + + for (let x = 0; x < ret.prob.length; x++) { + // i - j - 1 - ret.value_start == x (Part A) + // -> i = x + j + 1 + ret.value_start, j in [rate_decay_min, rate_decay_max) + ret.prob[x] = sum(x + rate_decay_min + 1 + ret.value_start, x + rate_decay_max + 1 + ret.value_start); + + // i - j - ret.value_start == x (Part B) + // -> i = x + j + ret.value_start, j in [rate_decay_min, rate_decay_max) + ret.prob[x] += sum(x + rate_decay_min + ret.value_start, x + rate_decay_max + ret.value_start); + } + this.prob = ret.prob; + this.value_start = ret.value_start; + this.value_end = ret.value_end; + this.normalize(); + } } /* @@ -108,33 +280,38 @@ function generate_individual_random_price( * rate -= randfloat(rate_decay_min, rate_decay_max); * } * - * Would modify the predicted_prices array. - * If the given_prices won't match, returns false, otherwise returns true + * Would return the conditional probability given the given_prices, and modify + * the predicted_prices array. + * If the given_prices won't match, returns 0. */ function generate_decreasing_random_price( - given_prices, predicted_prices, start, length, rate_min, - rate_max, rate_decay_min, rate_decay_max) { - rate_min *= RATE_MULTIPLIER; - rate_max *= RATE_MULTIPLIER; + 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 = get_price(rate_min, buy_price); - let max_pred = get_price(rate_max, buy_price); + let min_pred = get_price(rate_pdf.min_value(), buy_price); + let max_pred = get_price(rate_pdf.max_value(), buy_price); if (!isNaN(given_prices[i])) { if (given_prices[i] < min_pred - FUDGE_FACTOR || given_prices[i] > max_pred + FUDGE_FACTOR) { // Given price is out of predicted range, so this is the wrong pattern - return false; + return 0; } if (given_prices[i] >= min_pred || given_prices[i] <= max_pred) { - // The value in the FUDGE_FACTOR range is ignored so the rate range would not be empty. - const real_rate_min = minimum_rate_from_given_and_base(given_prices[i], buy_price); - const real_rate_max = maximum_rate_from_given_and_base(given_prices[i], buy_price); - rate_min = Math.max(rate_min, real_rate_min); - rate_max = Math.min(rate_max, real_rate_max); + // The value in the FUDGE_FACTOR range is ignored so that it don't give a probability 0. + const real_rate_range = + rate_range_from_given_and_base(given_prices[i], 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]; @@ -145,10 +322,9 @@ function generate_decreasing_random_price( max: max_pred, }); - rate_min -= rate_decay_max; - rate_max -= rate_decay_min; + rate_pdf.decay(rate_decay_min, rate_decay_max); } - return true; + return prob; } @@ -159,8 +335,9 @@ function generate_decreasing_random_price( * sellPrices[work++] = intceil(rate * basePrice); * sellPrices[work++] = intceil(randfloat(rate_min, rate) * basePrice) - 1; * - * Would modify the predicted_prices array. - * If the given_prices won't match, returns false, otherwise returns true + * Would return the conditional probability given the given_prices, and modify + * the predicted_prices array. + * If the given_prices won't match, returns 0. */ function generate_peak_price( given_prices, predicted_prices, start, rate_min, rate_max) { @@ -168,15 +345,83 @@ function generate_peak_price( 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 = get_price(rate_min, buy_price); + const max_pred = get_price(rate_max, buy_price); + if (middle_price < min_pred - FUDGE_FACTOR || middle_price > max_pred + FUDGE_FACTOR) { + // Given price is out of predicted range, so this is the wrong pattern + return 0; + } + if (middle_price >= min_pred || middle_price <= max_pred) { + // The value in the FUDGE_FACTOR range is ignored so that it don't give a probability 0. + const real_rate_range = + rate_range_from_given_and_base(middle_price, 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-A), Y-C->U(0,1)*(X-A), Y-C->U(0,1)*U(C-A,B-A), + // let Z=Y-C, Z1=C-A, Z2=B-A, 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/ZZ 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 = get_price(rate_min, buy_price) - 1; + const max_pred = get_price(rate_range[1], buy_price) - 1; + if (price < min_pred - FUDGE_FACTOR || price > max_pred + FUDGE_FACTOR) { + // Given price is out of predicted range, so this is the wrong pattern + return 0; + } + if (price >= min_pred || price <= max_pred) { + // The value in the FUDGE_FACTOR range is ignored so that it don't give a probability 0. + const rate2_range = rate_range_from_given_and_base(price + 1, buy_price); + const F = (t, ZZ) => (ZZ < t ? ZZ : t - t / ZZ * Math.log(t / ZZ)); + const [A, B] = rate_range; + const C = rate_min; + const Z1 = C - A; + const Z2 = B - A; + 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 min_pred = get_price(rate_min, buy_price) - 1; max_pred = get_price(rate_max, buy_price) - 1; if (!isNaN(given_prices[start])) { - if (given_prices[start] < min_pred - FUDGE_FACTOR || given_prices[peak_start + 2] > max_pred + FUDGE_FACTOR) { - // Given price is out of predicted range, so this is the wrong pattern - return false; - } min_pred = given_prices[start]; max_pred = given_prices[start]; } @@ -187,12 +432,8 @@ function generate_peak_price( // Main spike 2 min_pred = predicted_prices[start].min; - max_pred = intceil(2.0 * buy_price); + max_pred = get_price(rate_max, buy_price); if (!isNaN(given_prices[start + 1])) { - if (given_prices[start + 1] < min_pred - FUDGE_FACTOR || given_prices[start + 1] > max_pred + FUDGE_FACTOR) { - // Given price is out of predicted range, so this is the wrong pattern - return false; - } min_pred = given_prices[start + 1]; max_pred = given_prices[start + 1]; } @@ -202,13 +443,9 @@ function generate_peak_price( }); // Main spike 3 - min_pred = intceil(1.4 * buy_price) - 1; + min_pred = get_price(rate_min, buy_price) - 1; max_pred = predicted_prices[start + 1].max - 1; if (!isNaN(given_prices[start + 2])) { - if (given_prices[start + 2] < min_pred - FUDGE_FACTOR || given_prices[start + 2] > max_pred + FUDGE_FACTOR) { - // Given price is out of predicted range, so this is the wrong pattern - return false; - } min_pred = given_prices[start + 2]; max_pred = given_prices[start + 2]; } @@ -217,7 +454,7 @@ function generate_peak_price( max: max_pred, }); - return true; + return prob; } function* @@ -271,31 +508,36 @@ function* max: buy_price, }, ]; + let probability = 1; // High Phase 1 - if (!generate_individual_random_price( - given_prices, predicted_prices, 2, high_phase_1_len, 0.9, 1.4)) { + probability *= generate_individual_random_price( + given_prices, predicted_prices, 2, high_phase_1_len, 0.9, 1.4); + if (probability == 0) { return; } // Dec Phase 1 - if (!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)) { + probability *= 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 - if (!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)) { + probability *= 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 - if (!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)) { + probability *= 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; } @@ -306,16 +548,17 @@ function* const prev_length = 2 + high_phase_1_len + dec_phase_1_len + high_phase_2_len + dec_phase_2_len; - if (!generate_individual_random_price( - given_prices, predicted_prices, prev_length, 14 - prev_length, 0.9, - 1.4)) { + probability *= generate_individual_random_price( + given_prices, predicted_prices, prev_length, 14 - prev_length, 0.9, 1.4); + if (probability == 0) { return; } yield { pattern_description: "Fluctuating", pattern_number: 0, - prices: predicted_prices + prices: predicted_prices, + probability, }; } @@ -330,7 +573,9 @@ function* generate_pattern_0(given_prices) { 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* 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); + yield* multiply_generator_probability( + 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)); } } } @@ -369,10 +614,11 @@ function* generate_pattern_1_with_peak(given_prices, peak_start) { max: buy_price, }, ]; + let probability = 1; - if (!generate_decreasing_random_price( - given_prices, predicted_prices, 2, peak_start - 2, 0.85, 0.9, 0.03, - 0.05)) { + probability *= generate_decreasing_random_price( + given_prices, predicted_prices, 2, peak_start - 2, 0.85, 0.9, 0.03, 0.05); + if (probability == 0) { return; } @@ -380,22 +626,24 @@ function* generate_pattern_1_with_peak(given_prices, peak_start) { min_randoms = [0.9, 1.4, 2.0, 1.4, 0.9, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4] 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++) { - if (!generate_individual_random_price( - given_prices, predicted_prices, i, 1, min_randoms[i - peak_start], - max_randoms[i - peak_start])) { + probability *= 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_description: "Large spike", pattern_number: 1, - prices: predicted_prices + prices: predicted_prices, + probability, }; } function* generate_pattern_1(given_prices) { for (var peak_start = 3; peak_start < 10; peak_start++) { - yield* generate_pattern_1_with_peak(given_prices, peak_start); + yield* multiply_generator_probability(generate_pattern_1_with_peak(given_prices, peak_start), 1 / (10 - 3)); } } @@ -424,16 +672,19 @@ function* generate_pattern_2(given_prices) { max: buy_price, }, ]; + let probability = 1; - if (!generate_decreasing_random_price( - given_prices, predicted_prices, 2, 14 - 2, 0.85, 0.9, 0.03, 0.05)) { + probability *= 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_description: "Decreasing", pattern_number: 2, - prices: predicted_prices + prices: predicted_prices, + probability, }; } @@ -482,27 +733,30 @@ function* generate_pattern_3_with_peak(given_prices, peak_start) { ]; let probability = 1; - if (!generate_decreasing_random_price( - given_prices, predicted_prices, 2, peak_start - 2, 0.4, 0.9, 0.03, - 0.05)) { + probability *= 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 - if (!generate_individual_random_price( - given_prices, predicted_prices, peak_start, 2, 0.9, 1.4)) { + probability *= generate_individual_random_price( + given_prices, predicted_prices, peak_start, 2, 0.9, 1.4); + if (probability == 0) { return; } - if (!generate_peak_price( - given_prices, predicted_prices, peak_start + 2, 1.4, 2.0)) { + probability *= generate_peak_price( + given_prices, predicted_prices, peak_start + 2, 1.4, 2.0); + if (probability == 0) { return; } if (peak_start + 5 < 14) { - if (!generate_decreasing_random_price( - given_prices, predicted_prices, peak_start + 5, - 14 - (peak_start + 5), 0.4, 0.9, 0.03, 0.05)) { + probability *= 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; } } @@ -510,62 +764,60 @@ function* generate_pattern_3_with_peak(given_prices, peak_start) { yield { pattern_description: "Small spike", pattern_number: 3, - prices: predicted_prices + prices: predicted_prices, + probability, }; } function* generate_pattern_3(given_prices) { - for (var peak_start = 2; peak_start < 10; peak_start++) { - yield* generate_pattern_3_with_peak(given_prices, peak_start); + for (let peak_start = 2; peak_start < 10; peak_start++) { + yield* multiply_generator_probability(generate_pattern_3_with_peak(given_prices, peak_start), 1 / (10 - 2)); } } -function* generate_possibilities(sell_prices, first_buy) { +function get_transition_probability(previous_pattern) { + if (typeof previous_pattern === 'undefined' || Number.isNaN(previous_pattern) || previous_pattern === null || previous_pattern < 0 || previous_pattern > 3) { + // TODO: Fill the steady state pattern (https://github.com/mikebryant/ac-nh-turnip-prices/pull/90) here. + return [0.346278, 0.247363, 0.147607, 0.258752]; + } + + return PROBABILITY_MATRIX[previous_pattern]; +} + +function* generate_all_patterns(sell_prices, previous_pattern) { + const generate_pattern_fns = [generate_pattern_0, generate_pattern_1, generate_pattern_2, generate_pattern_3]; + const transition_probability = get_transition_probability(previous_pattern); + + for (let i = 0; i < 4; i++) { + yield* multiply_generator_probability(generate_pattern_fns[i](sell_prices), transition_probability[i]); + } +} + +function* 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++) { sell_prices[0] = sell_prices[1] = buy_price; if (first_buy) { yield* generate_pattern_3(sell_prices); } else { - yield* generate_pattern_0(sell_prices); - yield* generate_pattern_1(sell_prices); - yield* generate_pattern_2(sell_prices); - yield* generate_pattern_3(sell_prices); + // All buy prices are equal probability and we're at the outmost layer, + // so don't need to multiply_generator_probability here. + yield* generate_all_patterns(sell_prices, previous_pattern) } } } else { - yield* generate_pattern_0(sell_prices); - yield* generate_pattern_1(sell_prices); - yield* generate_pattern_2(sell_prices); - yield* generate_pattern_3(sell_prices); + yield* generate_all_patterns(sell_prices, previous_pattern) } } -function row_probability(possibility, previous_pattern) { - return PROBABILITY_MATRIX[previous_pattern][possibility.pattern_number] / PATTERN_COUNTS[possibility.pattern_number]; -} +function analyze_possibilities(sell_prices, first_buy, previous_pattern) { + const generated_possibilities = Array.from(generate_possibilities(sell_prices, first_buy, previous_pattern)); -function get_probabilities(possibilities, previous_pattern) { - if (typeof previous_pattern === 'undefined' || Number.isNaN(previous_pattern) || previous_pattern === null || previous_pattern < 0 || previous_pattern > 3) { - return possibilities + const total_probability = generated_possibilities.reduce((acc, it) => acc + it.probability, 0); + for (const it of generated_possibilities) { + it.probability /= total_probability; } - var max_percent = possibilities.map(function (poss) { - return row_probability(poss, previous_pattern); - }).reduce(function (prev, current) { - return prev + current; - }, 0); - - return possibilities.map(function (poss) { - poss.probability = row_probability(poss, previous_pattern) / max_percent; - return poss; - }); -} - -function analyze_possibilities(sell_prices, first_buy, previous_pattern) { - generated_possibilities = Array.from(generate_possibilities(sell_prices, first_buy)); - generated_possibilities = get_probabilities(generated_possibilities, previous_pattern); - for (let poss of generated_possibilities) { var weekMins = []; var weekMaxes = []; From e9e8327df510bcac0bd50433500e7b271c4a5e29 Mon Sep 17 00:00:00 2001 From: Pi-Hsun Shih Date: Wed, 15 Apr 2020 22:14:22 +0800 Subject: [PATCH 02/70] Fix a wrong comment. --- js/predictions.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/js/predictions.js b/js/predictions.js index c5da355..257334a 100644 --- a/js/predictions.js +++ b/js/predictions.js @@ -381,13 +381,13 @@ function generate_peak_price( // // => X->U(A,B), Y->U(C,X), Y-C->U(0,X-A), Y-C->U(0,1)*(X-A), Y-C->U(0,1)*U(C-A,B-A), // let Z=Y-C, Z1=C-A, Z2=B-A, Z->U(0,1)*U(Z1,Z2) - // Prob(Z>=t) = integral_{x=0}^{1} [min(t/x,Z2)-min(t/x,Z1)]/ (Z2-Z1) + // 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/ZZ log(t/ZZ) - // Prob(Z>=t) = (F(t, Z2) - F(t, Z1)) / (Z2 - Z1) - // Prob(Y>=t) = Prob(Z>=t-C) + // 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; From 26b753c7bdecf18c46ec4df8c33e47ead4a733e8 Mon Sep 17 00:00:00 2001 From: Pi-Hsun Shih Date: Wed, 15 Apr 2020 22:34:57 +0800 Subject: [PATCH 03/70] Fix probability calculation --- js/predictions.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/js/predictions.js b/js/predictions.js index 257334a..1a90f78 100644 --- a/js/predictions.js +++ b/js/predictions.js @@ -379,8 +379,8 @@ function generate_peak_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-A), Y-C->U(0,1)*(X-A), Y-C->U(0,1)*U(C-A,B-A), - // let Z=Y-C, Z1=C-A, Z2=B-A, Z->U(0,1)*U(Z1,Z2) + // => 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 @@ -404,8 +404,8 @@ function generate_peak_price( const F = (t, ZZ) => (ZZ < t ? ZZ : t - t / ZZ * Math.log(t / ZZ)); const [A, B] = rate_range; const C = rate_min; - const Z1 = C - A; - const Z2 = B - A; + 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) { From fc630a6e2b9e1c13f97dddc46324aee01a64cdf7 Mon Sep 17 00:00:00 2001 From: Pi-Hsun Shih Date: Wed, 15 Apr 2020 22:58:33 +0800 Subject: [PATCH 04/70] Fix stupid typo of && / ||, fix another probability boundary condition. --- js/predictions.js | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/js/predictions.js b/js/predictions.js index 1a90f78..69c3cf2 100644 --- a/js/predictions.js +++ b/js/predictions.js @@ -115,7 +115,7 @@ function generate_individual_random_price( // Given price is out of predicted range, so this is the wrong pattern return 0; } - if (given_prices[i] >= min_pred || given_prices[i] <= max_pred) { + if (given_prices[i] >= min_pred && given_prices[i] <= max_pred) { // The value in the FUDGE_FACTOR range is ignored so that it don't give a probability 0. const real_rate_range = rate_range_from_given_and_base(given_prices[i], buy_price); @@ -304,7 +304,7 @@ function generate_decreasing_random_price( // Given price is out of predicted range, so this is the wrong pattern return 0; } - if (given_prices[i] >= min_pred || given_prices[i] <= max_pred) { + if (given_prices[i] >= min_pred && given_prices[i] <= max_pred) { // The value in the FUDGE_FACTOR range is ignored so that it don't give a probability 0. const real_rate_range = rate_range_from_given_and_base(given_prices[i], buy_price); @@ -358,7 +358,7 @@ function generate_peak_price( // Given price is out of predicted range, so this is the wrong pattern return 0; } - if (middle_price >= min_pred || middle_price <= max_pred) { + if (middle_price >= min_pred && middle_price <= max_pred) { // The value in the FUDGE_FACTOR range is ignored so that it don't give a probability 0. const real_rate_range = rate_range_from_given_and_base(middle_price, buy_price); @@ -367,6 +367,7 @@ function generate_peak_price( if (prob == 0) { return 0; } + console.log(prob); rate_range = range_intersect(rate_range, real_rate_range); } @@ -398,10 +399,15 @@ function generate_peak_price( // Given price is out of predicted range, so this is the wrong pattern return 0; } - if (price >= min_pred || price <= max_pred) { + if (price >= min_pred && price <= max_pred) { // The value in the FUDGE_FACTOR range is ignored so that it don't give a probability 0. const rate2_range = rate_range_from_given_and_base(price + 1, buy_price); - const F = (t, ZZ) => (ZZ < t ? ZZ : t - t / ZZ * Math.log(t / ZZ)); + const F = (t, ZZ) => { + if (t <= 0) { + return 0; + } + return ZZ < t ? ZZ : t - t / ZZ * Math.log(t / ZZ); + }; const [A, B] = rate_range; const C = rate_min; const Z1 = A - C; @@ -812,6 +818,7 @@ function* generate_possibilities(sell_prices, first_buy, previous_pattern) { function analyze_possibilities(sell_prices, first_buy, previous_pattern) { const generated_possibilities = Array.from(generate_possibilities(sell_prices, first_buy, previous_pattern)); + console.log(generated_possibilities); const total_probability = generated_possibilities.reduce((acc, it) => acc + it.probability, 0); for (const it of generated_possibilities) { From b2aeb577077e5078bc72c17eb6c0098ac19880c6 Mon Sep 17 00:00:00 2001 From: Pi-Hsun Shih Date: Wed, 15 Apr 2020 23:06:44 +0800 Subject: [PATCH 05/70] More math error, integral is hard... T_T --- js/predictions.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/js/predictions.js b/js/predictions.js index 69c3cf2..5b9fe62 100644 --- a/js/predictions.js +++ b/js/predictions.js @@ -386,7 +386,7 @@ function generate_peak_price( // 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/ZZ log(t/ZZ) + // = 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]) { @@ -406,7 +406,7 @@ function generate_peak_price( if (t <= 0) { return 0; } - return ZZ < t ? ZZ : t - t / ZZ * Math.log(t / ZZ); + return ZZ < t ? ZZ : t - t * (Math.log(t) - Math.log(ZZ)); }; const [A, B] = rate_range; const C = rate_min; From 0cc1e80f6632d26686abbfade0bfab42d5627de1 Mon Sep 17 00:00:00 2001 From: Pi-Hsun Shih Date: Wed, 15 Apr 2020 23:16:12 +0800 Subject: [PATCH 06/70] Make the probability saner when FUDGE_FACTOR is in effect. --- js/predictions.js | 85 +++++++++++++++++++++++------------------------ 1 file changed, 42 insertions(+), 43 deletions(-) diff --git a/js/predictions.js b/js/predictions.js index 5b9fe62..51353e2 100644 --- a/js/predictions.js +++ b/js/predictions.js @@ -67,6 +67,10 @@ function* multiply_generator_probability(generator, probability) { } } +function clamp(x, min, max) { + return Math.min(Math.max(x, min), max); +} + function range_length(range) { return range[1] - range[0]; } @@ -115,13 +119,12 @@ function generate_individual_random_price( // Given price is out of predicted range, so this is the wrong pattern return 0; } - if (given_prices[i] >= min_pred && given_prices[i] <= max_pred) { - // The value in the FUDGE_FACTOR range is ignored so that it don't give a probability 0. - const real_rate_range = - rate_range_from_given_and_base(given_prices[i], buy_price); - prob *= range_intersect_length(rate_range, real_rate_range) / - range_length(rate_range); - } + // 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 = + 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]; } @@ -304,14 +307,13 @@ function generate_decreasing_random_price( // Given price is out of predicted range, so this is the wrong pattern return 0; } - if (given_prices[i] >= min_pred && given_prices[i] <= max_pred) { - // The value in the FUDGE_FACTOR range is ignored so that it don't give a probability 0. - const real_rate_range = - rate_range_from_given_and_base(given_prices[i], buy_price); - prob *= rate_pdf.range_limit(real_rate_range); - if (prob == 0) { - 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 = + 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]; @@ -358,19 +360,17 @@ function generate_peak_price( // Given price is out of predicted range, so this is the wrong pattern return 0; } - if (middle_price >= min_pred && middle_price <= max_pred) { - // The value in the FUDGE_FACTOR range is ignored so that it don't give a probability 0. - const real_rate_range = - rate_range_from_given_and_base(middle_price, buy_price); - prob *= range_intersect_length(rate_range, real_rate_range) / - range_length(rate_range); - if (prob == 0) { - return 0; - } - console.log(prob); - - rate_range = range_intersect(rate_range, real_rate_range); + // 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 = + 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]; @@ -399,24 +399,23 @@ function generate_peak_price( // Given price is out of predicted range, so this is the wrong pattern return 0; } - if (price >= min_pred && price <= max_pred) { - // The value in the FUDGE_FACTOR range is ignored so that it don't give a probability 0. - const rate2_range = rate_range_from_given_and_base(price + 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) { + // 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 = 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; } } From ea597d47617acd30b15d97c880f72f03f0bd9c10 Mon Sep 17 00:00:00 2001 From: Ryan Carbotte Date: Wed, 15 Apr 2020 18:24:37 -0500 Subject: [PATCH 07/70] feat: Updated the website favicon and PWA icon Credit to @ErinPeril for the icon work! Closes #71 --- favicon.ico | Bin 0 -> 1406 bytes img/192.png | Bin 11526 -> 0 bytes img/512.png | Bin 37849 -> 0 bytes img/favicon-128.png | Bin 0 -> 11429 bytes img/favicon-152.png | Bin 0 -> 13786 bytes img/favicon-167.png | Bin 0 -> 15297 bytes img/favicon-180.png | Bin 0 -> 16688 bytes img/favicon-192.png | Bin 0 -> 17981 bytes img/favicon-196.png | Bin 0 -> 18376 bytes img/favicon-32.png | Bin 0 -> 2135 bytes img/favicon-512.png | Bin 0 -> 49464 bytes index.html | 14 +++++++++++++- manifest.json | 4 ++-- 13 files changed, 15 insertions(+), 3 deletions(-) create mode 100644 favicon.ico delete mode 100644 img/192.png delete mode 100644 img/512.png create mode 100644 img/favicon-128.png create mode 100644 img/favicon-152.png create mode 100644 img/favicon-167.png create mode 100644 img/favicon-180.png create mode 100644 img/favicon-192.png create mode 100644 img/favicon-196.png create mode 100644 img/favicon-32.png create mode 100644 img/favicon-512.png diff --git a/favicon.ico b/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..b06b446dbb8d1eab70f08d319610d63bc24d397f GIT binary patch literal 1406 zcmeH{ZBUd|6vuzdzC8OZxa=;w&*Cnw*pl+52=W>xD2kW_7$TY=hFTKWYOaD9nd(Qvd zb7#&ybLN6dStb+8uBS;05|FG=36ZEU9FIUXWu|>a8;cz1imkZP-MI79(9AZVNi?7< zv>=p9h^6sp^UcJpb|Ngbp)XcgVnbYRM_*<~RA{JlAg*y>sB#ihoq%CO0?~CYgq0Hd zT4%%;x401N5-{$(7vrwE#CYam*_(<`9*=&lgB8^kl-Jc#zkM5x?JaCB2sMu^1DOnkml$B9gQ$tnFI`T`3SyfR9HZAH| zA`5aBp>~OAlw8exBS~o~D-5D59WDwhviMb;k`;jc9 zqghzGGO-`eMmm{;)RT+3HygWLfce8*r2YaN-U4QxU&3K;H=X@nPMwkII@^!;i*xj! z`*wIv7rDLgE#SwE1dk5;gJB}j^5a9piHF7MCYR`7t=g z)zBE%LP4%8yb+qK}sBm;ZPEs}9KT9)I<|Ma3`o$Wu6y zTC=`>+t%8=lT$it!>*_H@7sTHOZKTq;H7nKPkR&`eE6^|pXrlx8(NwUX(KJXSU ze8v6f_d`u+>9mEw|(%`M@C=Ql;=3(F*J_uNOe?|jB{ z;K`&JW=pI|BOgtxdu&I0qw-7GN|x!~kmWavlGEp@W8xmHT%PfExQ5eR$6lXrO<4U< zVx-2t`{y_vv&*aO`WGV=_GOl?S-YyNV(~k@5iP$qv-*MPS%$Z!lq~mlE-2_YboYJ# Hw(oxd58xWv literal 0 HcmV?d00001 diff --git a/img/192.png b/img/192.png deleted file mode 100644 index 68b4ae50f2b890946f87784820363b75ca6e247c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 11526 zcmc(F1yq!4+wRQJARSWDB|SqAEsd0P2@Eqs_s|kUhm;`FARyf(Aks*qpdumNigXBw zc*ec=xBu^)_5J_7{UXc;Zg`Tc{vst ze<((PE7BXr;_vF>hJyObvi%_!in;#%Scr|~4~Vz3ESutQg)FApdMrxrUPu-(L2&^% zSQNq{AteYF7nXvE^0PpM!4g8k5<*}R0bwvySR5)M#q!r58%CQK!VaphtooNO%$+Qo zgSWQ_R7l9r&ri@#M9|&KUI;8DB_$*b5rRMjFbDxufSWhWU%(B;{tpStNEF=5(Zk!( z-Hqk9M3}9+kGCuv#?n7saP|0GtQ+dDFku2Fsym`E*$eoqzYLI`e_gpaviwnqP#FAougJ2& zf9DyAVEgN_}&W3nj~D=jHCo0`u^2afHKur%%Y&4e=M5{ap|& z-tH{_QU3p_9t6_M@t-31&szRAf#v_9zW+8)|6Vu#|HzZj?+xY8783ejyX((;l?JiN;B!R ziAlh|w(%$eR_s(u3c>acORx3~{D6Imkan4k{1kvZg*u1;*f-^pfPT-19 zr0xr9S!^3TCftxX(*Q?XP@hmp++kw#rOGQDJwP>MPQE33bz=RUr*hSV1-1!7yq zi$2k3j;UFev4`o|hPR&z0>>4qNx|GLT5Bcbt0E%$X6jIEVZ5o{3LPagt~nL4KEJIO zm1sjE8~Q_tUjCYwR%3=&B&qiOH*XB?qMcT#wYDWR^1UL39GBwN(*eim?XZfwuewIa z#5HVTT{%RLUq6Mq1m>h^ma@HsIlaQ;pqB3Y)?=*>>zKf<<(WYGAjwa>^2QH0Sb!6S zisu(fGRtf0znJ%*b2CnT)~d;Rd|1O51{4tFAxYX&nm#c-~ z&$zj_8uGAU`wO22L?*hLXP?k>3|>R6e{q%DtE(al@}3HOXc zy6f|Q<>sZ=Ot!@CWoQ(a0N!Hne>e=}QVOan%q89y^D^#|UPX0VTJ*6Kebu)~-@m@K ziqa@FV(!7ZW}3Q@n2IHgNyOWp@ql@HRYkd%^C&zp`V``?$Izb;c4rkugzk#7Qm&$3 z*?!@W>)YsMUYkaIpFYj^hKG-j=yE2@taZ_r{?K~FQh^A_&mKn-H=@4fpZD7P{MM)_ z)2G)Rg}Ds8?;8jC^Qu)YRwC7n0qs3MHLUtKI0#*gLpq)($yhkC#a)jjX!4>O-MUsn zxZ0}t&43FLbP)yy`*}txaK>U8N@VuuUfD!5zp+xlcb$y^1hxm%;}OMn&aL%>%EzW6 zB|Mv(L8XmoA>-R+uX9CF41L^`Y;?fuTUct>qoVY(QVY_2!SHkWOtUwR?Plq?y?xlx ztK7WkU33Yh%nX7mM8=s=@cz{~_vRe`!lK@@m&fl1RC>+P>rLOMw$And zsNUm8DKo@@JM(P2L0Gr@LTvjbRYkF=QIk|0mFZ#vA2=4EVL0;h?s+YJ&l(H=;2QasUERA#5QByq|e zbhybKpGF2$SB_@4hp|N-Bx$?`#Xho}=8&V=kp2KY$-%GUBf9I0aKc?AA2?m~-&YW& zYl(}_HA}fTAN2MNd6E(8Fr4k7Gef~17AOO1qixunQfB9;;2#w^*A2ALCa9{??}msG z`;*DZ@E+l>@b0;QfgTndgw=yq>dt8#U9vT~?YO(;x+zsdS1e3G%fdodF7y!BdINpa z&rryRMUqcC0(}A%>&z}LgSpg92ZDxJ#PjpEYw1S(`bAB(goj**h3B|$R<`b{1U(w0 za`94qMgsVz>ze^M0bF;u&=;VKB@Lv$uy59A5e6t|3*krApcpg~dJu&W+z0iX6h?`*V z7z>3(C3t=gU2WEEf6KRh(lrKr?(2ud1La+e_W_Wt_x2MF<>XtNF?7q9)^`HaSs7*N zznIZoh00JGxdVg%o%loVuwLUIZGw11PpA()4DJZMd^#mAIqwlbR`;4x2}Wjxpkq~05P-`jvi$GQt`q|c1=x6ksmm&Ss|77G(0SXe-y0z zso-6r*MQCnX>93RkL`?TE1+^t@WtL|5}7cEr$?Y{pw)VuW>&vLY)rKf=Wl35cSBgJZUokKXEzQbO(a}3E!P{6jCH^c0nX8V zxd!}HxLfvCo9W&F*FMwLIMjPjH~%OP%UAAauhi?A2Ss1Lk0|^p=&r85Oje3fdg$lw z^d<}FO4}_1XEMi+$6?9n{ve2ni1{N6P!Rrh@+bPxJAv)wN*Pbcx0#5c?RM+!-}Wc6 zIp2=xNna$t9Ud9PFG%79{0yH)5cm>ooxePZxRcXv`h~J474%%2 zy3n#t2u(DwGk)>5j_uqp=vENv&b^PcQ(GS^hUB_tdL_kDD=z)w>a`>ryT+sXlI{96_G)+c1C?JsbOhMnpOK}RPEm%( z%0tzk<=B7YoPnn35vLe+6dNdp8Eu`)+}@_yguL5Dc!uS${irVxWq$fv z@uL+%wbGpr_5KBx1Ih<>1Dfg1blWB-DHhL+%w4+aoIu;FIWnLo38rzzxkp8s(EF3pE6SH9{945v%LE@0L)_ONt!|4c!s>O0VE%Bb3 z)`IHxYbs@tP~5f45|&7tG@EYF9&pF!Uec{|{9EV!6Jsk0_W_bLj2m&qd)Hq~Z!@3c zav$zBk$l;Z=`95eJ|A#Hnjr=G#vV(tFRSQ43h!O3t=NAL)5Xbn3=TC9*eUK!BY6^i zv#%l;7 zwCVU*Q=_jY&P@8YK_xQv)zD0@NODgCG*)Y+>`u*lx;;oLb|vARhc*O?ad$LndSCN8 zRL2x$y`G$(`1vCzphX0pAVA^kD1lyuNWMuT_^k==)DvlD&w^3Nkv^QWGVF zhWE<|7`}JE4f6)nX0U8!aF=Cy^n-xhjnDQ2%& zL$?3pZcsDMSB4(D`<-Mq<#UKIJ+dG<9^Pm(k(Hv7$Wp_T51j%F9S4%+KKct@1^_@) zCrOBCQ#{}MJNd7>nQyMS{ZEKJB%imL@{8#_KG7&rTKtTc_b{b^G{X{?+)jW0TI&HKjM|S7xGP1Ai6mvWy#gjU_6k_<&sUp-lt&MR@93fmN!)vnbln zpOq6m<~C0s2Hmxun;$4h_A7ZA6rA-MWNN;%xomF&Ugl|VyZU)J?|k^lVsep06T8pt za04xC&L>HxB#Xro6|;p?y_W7$!>X}1{ed{lipM$fq;8|@3KCMkOB*pa$B`WbIy6Px zEH5}2o6va&7rZ0g`wSaW#AggEU7y?sblh^{o+NStt^m!Vy5xEYtt86V&sYrys&f(> zVyuy@rRT=9dNywZUSDP*7upXbAN|BCE=X(F5(J92-MRLJ$u@OnHS+KSf;(4Q(Qj}^ zeQkuwQHnKq$vAR1v`jz5B2mwItUodq7lk8k2PfEwY;1&mW3&)$~ek(|ti&#^L$Xk#Z04vZ7x?pcisO2o5q0LQB$C23u!2swZ3=K| z@PGlgRsrNVyrn&1Gpp_0N6RNprpS+Sh7^c&0L|@yfS<2bjg9S=6X`LO+~YIWJ0o>f zp5lU2#&C1xJljZ2FLTIj9rNLBc&XA_<^z@IAaM`%$#!ZqX59AD@hvf!zzi=|U)L&B z&J4@$?xidrlvPy3{rvI$!@@%DGsw_Jbh2mgB+K8^Iww-4xUO6wv_JktRgFv(*&&UqFT2ZUC*VY-WdfU%(Zme1&5o3Xda=E| ziiSp;U#sfudc$!X?}i#~mDktYeqpN@BhYTlmSTb*le4nv<1uD_bhGD&-jwq{ao3Zk zd@)?n5{u14v*RdxWL(T0bD&+fVIfUYb|YO9mQV-84EqZoB*k3ccKhra=Rew)x(<=| z?YNUX6fy0z8FkxgvX!gNhTtQW;&?S$lLk<^-`wS8ZbfchDFTH@!no2f#KcZTxatj+3b;`=GI9}T zh=_o?%jTMJ&hOp~@3;o40Fw>Ii5cbF3D(2Y{qBWZ|HOBMv^Y3lnWg5PX zq25-kr)GmMn0F9%M%C|AD+|}MdR473n<&8eTx3AEdRq6RqZ=r(AL{3h*^2}@h_d4x zrkNR-n&&cYkMH6IBkC*(Zhu})60?2RCmB@Jbt_p6wQT{>0a#b@t)U!q(}T{YP3GEB+$AL? z%C;_6Pmoz2lGULi<^D{D)Aw3KzhzljVDp4$kh0ju=POS;U3}HG`E=yH)4TEfolDE_>QU%>AKfHa|l4VAONC0%{8T7@+ zpDIi4@9wUTa2H_rYfg4 z6X7DNiB2Hv34hJl^+8YWCXD`hC2#1@UF)MCKZ}zt2KqL=8r+xVemVnxi1OqRVgvxiw`A_LL4dx)u{_yv-ry^kXw z7^Rox2gXn2NEjH48y~+qs>2l6SQr-GY*%o{APtu~@{XjEFxff{A0gFN;WszMpFayk z@18#rDbvp?#fdYwaR5pRP_)jx=t50@`ZO3pDmPrJox>v}q?Y=kZT@F5s|JNtU53x@ zr>Uh{xZRnf*rXmPIBb^A%!t;T`nkA!c<)b*+ZKDxsCVPzBT9A-KuZhbl++Ru4Cf>z zk(isCn|6oDlFFWv)zs7&8X7*Y{2G}juc@O$^6=rqYKvCEFV5Pzn&m!ddHhc>2J52G z`xHEo^L)XLYux&2C;j8&;~=|jyFn(Ge!-ZR>KrY^x(}$J($YtlLCww0lhe~G!n6Z! ztsmy*G}P4ao~TFK2*(bs_wM;RZ&k+^=@}ajb_M_NUkSr&ySduEE1>PycZZ-fU2y|0 z32J*`fVIyH!B$cLIF?cx3n^7?7e0K}hB>roVP>4%2&@>W&sobb+Bk{9IU^`2tK=2x zzJ|n*+$kz6i@}teB;z2Yc@+H0W5TVKeGFn;C5F^>)JQ$N48pYaTiNfHTjN;~{i{9e zM+wpmrNj~SduINQ(%7zS_LQ-c+_j43RngJ5nR3it%>_1==SxgCt(_((yIdM}%2EEd z53o!!IOU2k(}Mfax2AV%XMvv3yjd6V4OrpChdF*sGh+N)K9Gl{jd2c+<>_!=US3At zW0hedeM}?Jw>uq}n8qvKUOv_K^_FYkg8@s0aguvpGK=5VQ3u@1b(5I}*fzsllUV^e zwLIEE8{8Ce^~fCnm9T5?6dVc zwB|p5*7XibOyVDFZfSX7VlvbhMKmPO8d0xKVO=TaHtN_>=PMuo#5w>2$2FLvfc?zJngb=T9E+(d3 zT?KBvE6{!PsACnIWekFah1LA>r5A<+PUhZ)i1QU(bDvar+pon@DiJ*YRI^9vakTcv z(AXFgddJMt6#lW(v$Lt?<#%T@*6)ZV7E;dMlGYa$p__;jTCIC%t-#8KN}tcznUZ7D z`Akv^3Upb>COf%OIO3L;tZ;F0O&e@+Fs1Q+I^UZOIFrHP-i@m#62 z+FHRyr?B!v%r+HYRPQv+Yxgd{=CMGaSFnm4jxRiMoX&}BHmm4o*ZmAZ%#x`77}B(y zoT{<5M}B@1#Kgq>7B98dvzEqTnn`&ggtFD{Iw2>C#eS*niA`^zL@ag=X@(fb z^YZdAJW%hoIjXUH{h;(w;xwu7Q$V~+MO8{=W#wUDr(+)LGmba~7WCNWT0CFvaAsV) zVdE?h9W+Kb0WexaaiZTA$Hquf%%f>8-4|a(b_=(Cr|5Ae1gSYcDh5IN-Y1+X;7WpF z>$x=Pt!plNtYGSOXMbO3HwDf?!OG1YgV}VO(;dARXy`h^obL7G_u%^LU-UCd``*$> z^`;}7*m~m@xAqiCNGwW$U<9gHFyMfu$aUL<(zzIkdXjd8B>YnvFFLnE>u78n@l;O;)Oexzq^ zu4!$(Ou)*aX{gQ>uA@?j67EES8)C%{_wn9Col!DRv%yy$k}~_0mZ=<=Wge1@h9)Kk zhK2*FocBFC7G35Vqgs~&A7gTjVG5EM_S*WmDSWDE{7h#uaU484{9P_Ix$dkfD3;t@ zQtZ|M;kNAWp>g;LJ5PN0gt(VMG=~OHyce7Br+8{U9wB)#vV(9OqD^LPHK`?G})$TRV?hemC)nEp5@zz%Cxh3?Vw)#y^3o}SkG9aynF87>b7bT8}b>XO>$ z`OwT*q9!t%T1a9dMBd4yH8w)5f{s*@?ntY8dVUyeO1pXMxIugliIZLn!c5%O02N)YR$9OuE1HkdYiV7zz%|0TK|}4D^0k*?egww?8%>S3EkZ`Kj8h zA49xf_V!9zTQe}eIypOM$pyb!+WIosiT8O&eTq>xoRRTHwVF%sIO_vf54z|$r_?wE z+F_o&md1r?Qs>(C=)u83%H3podU`IEjhLy6Hlg8SJmM6nv2b4*oWMpNI*yBVeWT88 zT`gELm6jD&#G#S>QTIBnecOhw7dwr(6konrbQdlbMx~IUB2D6WMV}FGKfj?yi=jk+Z^ z8{zkFQne;WTpC_8=l#vtEd_JB;SYl6>Olbimv4sPY7=xHwbl!j_Fm7qwNcl*C!b?Z za~(kEj_&ub7g}241Y`%b8{l5NIUPSP2Zv(L#Nm=Z&`QO@Wbd*gGMZaB!S~|(1elp# zxGH=%Q%>`o-6d^sI+4RQsIQjQ_>_32C2Ad<2=k@L${h{6AQYessZW%!Sizv@XPPmZQm9bo9W@IQyUz<-*MV6@)nzEPnIsiOopz6 znSj`6dodAi0^d{Iww1ky-|kOs1*8oGG_>SAUYbL0;C*Q7$;=z}pSkl(gTW$o+rtK} z`_q+_!Js*8i9^o(Uc^HCo^ZiZbFv#;Lc1XL4E7r2&vfS;FX2r?4BhmfcUwLY^+O2Ki~dSY>#%_^w<2Qv(X^nw^;r(m4riuPH@uZeCK&5vPA= zUq4c#VsdfXmOpQql(Lz9dE+n+^t~1OA#|F%J(H3g5W94$lAZaCjXuxKEzfwIn6urG zR#d{ZbP`O4`Hpl)#-lv_)3{ds2u>DfR6MKO--dQV}-N@N})q`<(a3d zWx*`t??{`Emhmj`U$7WzXSWgh!O(VF`B_gRWSPx_3%%8d4Q}*v@dF*W7QJ%^%YN_KS z6TmOv=b;#8(KN7-rE0Cb+P@#N^o8_D=QBVp=h1A*sR$49jZGhEoCv;8kr*KMNwENa z6jJn(hRFVQd*;3X;?-F1f+Z2BFHwm&kyVvvswBr_!sck)x#_ybl2CMi7{FbktDdu&Uz;Igy9fCPtA6q-M_3bRm8jw{vID=<;{`DD=U~<=+`e0;kXMeBq|4mVC#3dlVhT@Z z&_wI9k_ICW5QKfa?c{VFGf|6fDviS%G^1MS$Xtp@D(X7^shyG4g?psbBn(*b@sQJ? z#PSsO`y1SPRi`RcSJXIk1Xb9^W<^qx!*L`bJkc}Aabyzv*Z;pHk_wRW5A%IQY;^D{ndKV796J){2-14&>37bStg&mO}#wwri5r2+Dg^k{f%~0)Ru7?#E@7=Jq&P+;OJ zyMhc5n>4bSnTFt+_rzW`(C`V2N#g~g)zwho$<#iG78jlXzBRpAmp$Z#K7b`#F@wc; zCp%Lsk|vV0QviI?zPXH)7zpnC1(uSJ;3e z-FjMo_C#bhg3FyPXw#;WNV5!}@S?Jt(Vt^tGaEsY49H*&;@o^;0bsc|y%=xW=Tv(K z5(kMjH4o)mj}-YxA&X76nGs8p)E@tFgQci5H1rkGC(M!W0jLZs`KwDzT!>6OKK!_r zDQZ^$Kz6^v9VC}1Wi6cLfa|8P@MuwAlU@<<;081f3eg66KGcGc;CLq6!_l+)suY0O z9)ecj_H%=DhgAI~oVO|q>wmsEH+TXZ7tu=o-HB^$iB6ow zkqe(CK75Bq2uQ=SMK1b~!7Y_)G4@d-nIx%a-7WddCmNVTa8h!S5$ae6s!+uZ5pfM6 z;DCEKp{Gz6DCl{W3PI|ZxeZXPOua6^Y5-cSOWawy<6t6=!uI#vX-NY2W833q38K@! zs3h>I4LvJktz3H(JGYgkkT3WQDYzIL+{Vl@f5tG}*cOFw6pUzR0AJ^xiJZ*wqo*900y|5a?r`D4l%r`W u(?*m_lR#OS4&iqJX&QD! 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 TFm}mn0e*IbMzU+Sa&!L$Vtf22 diff --git a/img/favicon-128.png b/img/favicon-128.png new file mode 100644 index 0000000000000000000000000000000000000000..08a2116cff4c45a257ea3e840c02695a8a189566 GIT binary patch literal 11429 zcmZ`B~?&IDoYC8HMfL|q)B>;fh1mqV} z*pE4dxtzK(0N_LSp%(@KJpHGC2mrWq0074(0Dw?B0D$kD-Kr+?@dD0FQC14@{@<0~ zQJVDe1l~z@LD;`@yxc+c0cI4@6`DHOK9-uUqVagg4KA$K12`njOyP-Ur#fRPA8xOQrx9O1x*d5-1pFWb%3r zJiu}fy}>E52x;vcA_R5Cg-C1(Zb@um@_6dR(3R|Pw~3P|%W0Xiz>~mxKt&=2=3VO80;iB(m@ZBr zk3pYeT*DzyJWy^$_qUC?8I|XY9h3 zVg6u#X!n>;64$}SJy6xaHz)zm!q5ojD0hW5TsV)UzNn*BG*_g+&)>z!eh3q7qsx>% zs=;zYlEQu4k>yzL!p3n^p`q3QFRDDFO1`7E@jcGB$qJG5sav*Xy$3BCsZEPKLFk9 z%n`sG^S3|mMc@>Y9->NxMeksi?(H4j8lB>ATOf3BGS)1g%R0fO6v-?P!i%_TSm9qh zlRnttMmmoen#NBwBXJ$`rZT}HB^CCpDp=6elpH5O$4H5@M>=Ll+n=w6a6c)B(1E~Z z7rQl}L8KPfAGRHm38ENjK;t3*d)<{psbSsDE8C?jWzIe7Q-d3VWvUJSiKw= zW=h`(BZ7$&D2w~<{gQtrZ~sGrsZil+WhKxThh6TayiB31wXAEnkPb5qv()R`;oLdn zyL1K0WU2m>3lr10-1BKDIQ|NOP>t_Z)(`+c!@tn_>;O3IV3`AjRmKIailta9U2&xU zx_WaRp%}5DLo3a)V1{6Xq!af>3x=7BZ)w{GUgE+r$T^@Z#E^P#-Ad0HS(`R%{z`;q zgmvs;%_c8w6^X7#;d%zW1S3%$f>znd#8)v@m|5VUUbrrNW0$XO+DA%mZzmW7%aVK8 zonbexIh0^#c@)FU^yn_VNGM^A1o;y&&iRJO;)iZy)zTNqP3eHVU$av1u`*%$lUz_F zslsToCaCOi980?o7lJqpC4eWv0bAwL>65yq1&H~C&8RwtBsIrC!>)ZSJJLxoy_9LK zzZgZ*Fcy$9)zXaMNiA${4dP+%H%X7uXbN!#s$_K!?Ta&qzMa+sAF;t zcDvYzVR(6?vmco9D^}`t52fZC&~qS7x{+sMs1UR8K((Vj$UVC28=Xw~y_RpjMdv5? zjQUz|>xN-0H5p&)MkO%05YR3!5mz?AAsYaNthEbj7Po2qp#uV0AuHC5(Sv*+cHT2 zhRLc{G_joI&Vb?Pt-Vj;PTaCh!1)mp)HGcL*H~l**bZ|CF7*ArqD;srj7$C+1f9 zmWPkugaA$}^yiyd#m=8)7|KU;wP7X%y-Vbf#4=~s8IFObLZnI`iRUcRSg-KIC4jvi zL@s=HjoOt6lH;hl1T*c-($rSKC6o1lorx~+e}<~M=y zsMO?b^wCivFTip9)k*t`H?izUDQLH5c%>F?8{_jAQ}`L6;l z?FoL4V=}wVXm*<`Dt^lZuyE8XjV!}0sLE|zKEez^DGqcL+Z_55<4r%zc14woOaG;uJKWj*D zH4xG)rYwk<_yzq6zYClzy3G%t>rerQ7tXDKm&?+S|3%%2)(9H;@Lg|HY#37#Rr6ReRvo!uyYx8Wf|Mx2l{G?oQ~AqE^F*0#_BMx(-gj~F!7q>A!Sf|9uL(~T+tdy zfq>8p4MmV-uZxrEdw8%MZ1(BGWsB81C!dHP`dqdxsVmeYh8-;HQh*|XdEwE3j9aR! z?)g0&srx(uK?Zk(eJTW}SUheE=6lw0K+>hn1cpd) z#oJ^6CFJOG2t6klejj#B_6lQ4&*1ek{ngrXPj>L750Z*(HbymoYVV=K=mxn2Xny|Je(T9u6_Mqq;M|rrJ&Wn0FrJ?+)37>WWbLri;Py z*JBSYpOh3~hBt*ZA1v;T)IQvW9n17hmR>LeU~`v4@`nKqKEhge zq0(^VJC$w{Mcyd4kciObtCI8ETy`;0IEiO{v$UX+q@5!>Z-@Dc1K$<3&9hn5!a z+0Sue(GRCe^kX0uZYNq`*)26Yr>8Rb`?y4lKvcms#y_i#d+8XvTJRLfRzVN^4YZ#1 zS&OxR4ZwCPf~M#~xa)#YfiR5wOL7=Bzhk2(lLpn>HX8jM;plntvKF+=_aa}8#k&N7-iyedJ5w1CpfN8vwAj7BkN5=BiZzfDm$Pp><7fALmYXWg_W|kl7>QeRev6CX7?Y3FyLvh)XdVA zw?PW;M6fFycOa>mD?~(@$CwBaa1rteS_3iZ^4%BvK_)sWn|kKkxd*(>f0by0h7&=u zv>hqX2iPSPwKE_g>}5}h73c~TEIWSrd#@X@yn=laY;H9xPLc3r6`I|Tq)1h4;bxJ% z-M#Iy$+;6^qQlu*WoEpDb}C!iI!T-w`^796qr%I|1x(0LmeUiI>5iv{79Sucdp9+w zbkE5zBk2kgVUsBT^&^LorTqbzlS!90?pP_^c+~hR;Ac?=d>04;ii+#<{UA)E(bAW* zL;95ntkB}RNFLncCc8|5^BDa*XD-aAT&29!q|BF8)a7ZCol*;gwW^{aQ2Xhj;T+7@ zQ1{HeKWusv(+5>8$s9tP&Ra+GUK%o_E#+POC(v`BIY-a3h9#yXRVEu`{bce^A>j-r z!iLWL{U_R;P_t+a+=Mm})6=OT7$oJiemu3&V0jqyqq?Wd!J3va-YTU(1TCom?SXg% zR~)gC*q-#e2rj~fEY*xJj6(rR{`NOwZrv8P5}TQ|1t}IXNojC*XMwuFW4Xx!LRirE zw9u>jPZ4*xr!vB^`#6e}-=y>JADO32%?}Ffp4{^PxJVO=Pm|IR)Wcd#H-#BB^fVwZ zb*D=(#?i&w1=)?V6WQ@cyA#ZEH{#?dh$pH8d%-%ZOXob_*F$*|KRc-|Mwj zq|CSUKJ&h7SQ5k8A)tB<9s2ShiMeMw-gw(c^J4`jn@Cw(icS?#!B<*1P%vVXoKvqH zy;5ow)=~Nd=o%7E7X;UE{u~FnJ^Wm|L}J`45d&s(+maS{L$bMg?#!jE{|&0El1wXq6mYd*GGZXjhw(yh zZ5SDx;tkdlfQ3?EbOWamQ|CHI(;M!%r0I-JlZjA(RRrOsYoV;iHKMpbbsWPqF?sc|j-?ZF3>ne-FBT9s9ZLtJ6;YYbJ z5kfd9(ryU|$%^m2#AMM(&EGeAPd7c&sUs6Or^H0qq}z82XmwEGqBZF**}lj^<%Gp+ z03|06Mb;tNsX#-26~?t>byeq_>(GMZX4m>w3$z zYJ{a%Ix3Mq^1@;C6Qf8`aDA~RZ!=mRM4oiq%P8fmcYQWeFCPozXQWw*gBz}ASyRC_ z&I<}Wv$^vhlM7hwYgra`Ng>TTT%n4|rp$OtmjPkAG| zwCi5<;93L2s1@CPpT+~20e_K(WNMe86A|7Z>$yL{V4~UkX;Bl zR05}R=(GWrIP?SRRubgbaj44Je%&blRkg7{^K4NcT zFMPt)R!72h@A>-RK7P~g-mA+dza32@G0P4!OIUg1Tlc}01sd#1k!NlH)qP9f3eBZg z_CTr(%PLLQh>P1K;#IGnY+@=T>O__E*``UJ0|e@1FFd#-c}?)fo|hCs@`J6SQE8Fs zHoz3ezo3Wsmd_lsj{g0jd~kh2?g!7``48!s_;}xanm#oCAoQ)1GQejO`{h||z59C7 zk@RZ;HXMzX9?hcePmjl+9?x?6Q*Kq#gX}Fjw;^6sDz5t2-8DOh*wiEe7D3yemO*ay zpmZTN&IL;OYJT}#2dtAR@ImhM;%)qHjJtc?vXleO;?eN0d*G zb6!DR+59`@m2yWU6fddh%Pq-%u>5pue&eKq4ND(mKabbhr;$>)taa#4)ZZW-+bDw9A3yzB_$Bwn9A%Bb(R7>i0}{l~Lf&7!8fwQdkF*)nGnK zRq!$fL_g@aTIwzG)W&pA>HFVazf*KENL}?p`RVKdEOc;iI4uc@S}3!fixkP1C4wF) z3e0pjceii5%G%R&>XWIgzZ03z7osS9IeMzG``VO=^p1zgFV z4d{S+mT^kLO&jzF>OJNc*6#!3nq2m`^-{0dRihZ2j51gwzvy5_5)w>$Iy+}6ELj?k z@bL7p%W{f;G|O&BwDxPw!DqrA-%hQaj+~Rf#5$svojI2~{MznkCo#2_Ep{EO{61&A z_1UvJZnoqEORo{D!f1!*rY;ev8)Y|ehQXuNR$!6&nL_iwfzii`u6L9)1CNc6&RghcS`srVU7Z_Xs&is` z68jU)SG_hL+(m@BKWl?3zNJl|u5nmhny0L&KU(rU+v{ z`yBXdvrs~kdro5H&QU**uNnV%waSlGQw(E=9~-6 zI4B?3ojP;bU(QN(Iy?kTn>p%?%uHegsw;aj<&{jSIWg*|>{8Slc=%n>B&N~STwpYkY)#BVoGGPU_l0H zzIG8*Ya!S%3(@BAMQgGXtdnV+0N1S@F90iX)p_RNdt&%E_!Loh_g-afVBYf#ee9hj zD{|cf93H1yD6N@m>*0JVC?zx+S@w07Dg~8Hjlv$hCbi8SI9R8=S)<+d>?-6b12*+u;*_v4pdoyfWH3LKKB z#Z#S$!hx*m{l`hQ8UmFR7(WDuZD!1|NBnAZ$LEo+x-GwEv)}v4eNR}o$4++A7GxQ* zqJe3K9+<059X%Tz@B{I%;Uh&=`?2bCqh!dlxPRj#9;lIeF-e})a*M>qxa$Nd7O}sJ zmGn!!EiDZS7lf*Xs9ikaF8fnTPClcE9&x^yiE|WIcS& zz+3LG$4~IRy^+6b7`mU)nsr)sieq8xwdhBM|Bf&vuwSmrLHE1x^gh~iFu%7%B4T%s z`pxsz;hKE;n6rIeQjSTv9oE15SISDmDbko!cMd7O+?PQ4a4<#D1-xY4C(4hqz$3ytI`i;J6-FhjRSAS8L9d@9O=EQ?}T$*b*6~2Qy4IfN6tfU z?c`MKyZ4RE=a5tVsE3VWCcaRojnl=bTZ6KJi*V09n#kq|j*w}_8*#W1kN1QXYaOqa z52meChrM9xt|SrU)Q617YDo8ywLAGOE*Q!G%;xVKB#mvT=rY6l#OQ2s z(5*Quc z0x|n4qDD()?-}N-`EE-7L@pE$$AH~p<5q2@_{@RtiDWy$FPBa0(nedmhgGVKEm0}? zXRuzMW(F%AG1Mz!|S9U!eB-hQyErhm^H*8BnDj%$IXMy+{8JNKF_a-hs+Ac zBXn-KV2|NMkx9u}2&e;|y9){~eF^D?t0X!jz-kh2Z4FLYXNkT7Gw=`0tfQT2M}5O= zF{k|Kh?{De4j^~n&?~s`KpZ)S$WWrLklL0h0$G?g)>Y}LgYLhi#$l;8`|YcW^>`C6 zPOh#RCqF7ipQ!?SIS&8*+bKo=q+o2^U4|EogyR@lzE?k`EA{qS>YufoRiL;}Amjp> z%pctwMeICjgY<_Ft;L~W-ZU$e0-~9NI&<=OJZzPUzDisKSfpScWUx_bv?ev;4EXeW zkiBXU(rtW!&O@DjbcT-s}AexQR)T%_Q!KkUkkhXPGY}lC5(Y(n??SB^U&HmAaY?g9%RPaBdSrpLKf+$g0g}W)Tdq?R(I~jUM1MtAF{o@pJAc3=XRp{PF0)4 zF+er;y2R)r56-ao7m-vm&wk%zC3|8sjfhtfzR6N?Jxkh7@NwEP;eTFgl?|>}GHb>t zxpe}QbSo*eL;3p$$}I}>7*sJt==Kk3p;t)!IA^_8ZY6*4;e|?v1j4YfqS?1w!;nA! zeRf%YG#%&sPD5uakONL(C@%Z`yXd!5kSw`>9S_;weAt<71xEe}jf1TIo!uz;#z_Lg zEVvbU42(u6jeuM!6TGfo7Dr%hIq5hRX3|IVxRH3%8AMUck)$4z53?eXEJhS;#=cV5 zR+gAY7I?bso>XV2IponAeC$G|<7zQfZ{pnI{AHf!x~%Qhi&%L4@@Dki z@Mf?_nLpu~`a7mj;3dfjRoV3*^%}0supkenh0<2TakFHF1O}}5=K)NtkhSTc8>2iw z<1nPpBc<^Dp@&U>61u&Og8pBK&Y~I@^u85IKD0E;r7l$7e4M*#{pchm|@FRXO>X&bV{pkT$+Q6E;)>A?k z);fx^mQsf!VGz)Em}6-8X!3ZJHND(QYv6L*PxIqnc732?^OB-p8$YhpceB~Ow5jQ7 zBhj^>{leKJs^fx+hy)z?kmQ{u)hl3;?eX#V8Ipp1KlwA6XztFCVfRCw39ON>+RQqF zE-9*saQwVp1Lm(-N$GMEkKXt&YB;s+6-jXidHRo0tuAwJma9pS&^;Jx_QxAB(Q%qt zkTSJrvL<xzsQ-<$}pbDt}ft<2nDmSPEd&0$@v%43e2H{6rh*Hmn}aEEAu^d))M3uET~SGG$Ex@blcy+xH)e-n_pD0^)r^k{dV1As8AB&EU z2Gz#^x71~-;>~xPT}uH(JyN+PberWLEnvJyEs+Lr{3^o$7HF(MDb24ytoX8 zKSV_XgqIB4cZ2G7K&BX2z@uUuJC{uof?o;F0FXfF^`0z*q*nc9k75}OVvm4>|J$qtT~aw(#^{$j^>GY%#?im1v*BpPv%0Av`ppON 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�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 literal 0 HcmV?d00001 diff --git a/img/favicon-167.png b/img/favicon-167.png new file mode 100644 index 0000000000000000000000000000000000000000..cee09d82469e68218619de1cb9972c0425f55d14 GIT binary patch literal 15297 zcmZ`=Wl$VVw8h;$xVyUscXtT{cZbCnch}&q!8HWW;vqp63liLRk>IY6@6W4xKVD7E zbj?iN>YlFYbI-YbZ@iX)_R{LoFfgsD z=+Bmj@AuT!N;>K=FoBFPFkw+JFpuw#!k{oPKHM-cM;0(JqPZ|I#2$q`+T!mokgQY{ z4Mvsar1kt)|MmN2(HjRGyz~m0uJRfW z)YS)T-l?VfNu+!jwn0XGpbMcqweBnfeE z+^Pkg_4WYuSGoP(x{Mk5=<4fx+SL4(yfunN32{Gsz|&fv}9# z2h)c_E{E@nik`$5U5M0zbWgGM%|SHbNJo_R(1-=3CAcIkB<>Y5CvA6vM*_f4C_3G zFhrp&0GWLb>~`V~0pTG4q6pK607O)u8+-`uOT?~07da09A*VVew+w5i zHV4oyJT>G8_ppR7GXLE7+Pex^i-`T?f%>ex)9Mc?zc&on!a}scLP+Y{<9&`$ye&<= ztQQwX)hHN=L$74uf4~f9&X<*z#{U5(+p@1wzlB?cc_KJJk&(QP9y^qpCRmN@Dngaq zAHgJv_``C7CCQ~1A3k#vJs~L1* zesICJJubNEFn?2xqM#RsKr?cWuOFU0*-Zyq@mHMplcmk~#GKlpTOAkpk8sZs?f!W} zcA*I((eTeg*IsT0Cttufb@aqQOwe)nI~NOVq>!WOBOi=AoJ!qe3HFv4*OX|OP) zSmP&-caN}9@jd~|*O6v5=n7q||EkF!#{`O+|4|zE@saz> z-qz0w#(5SD%!B|`MtOF=}~4s@jRpggA*T?jO=Pk8Y)MizVS`jd#OkSk1{XDzrzH#K2EpgzF9HYqusN&3;-3clCjL( z6R0V8s%lHKhJ4K0^4M2gux74!)Z#7mHrgynMy#~eevkO{>(mdRSfcGXt6fSYoD8b4 z6iDJh_k;7aZ+f!O;uLNmVc8qqrj#orX-4iD5_`JBxGLZqX#2;A6r& zLZZIER2F}f@s6ihn(2z;z5w0q_#@E>3{-abl@&f;qIwY`B*UObJJ88QPr&{qZIwtg@S5jej*CLom6R))liY=@>n6AN7V~O zf?3YU`+SdeT^4zM(!msH5Ux(z%s$JWnd<^-9H)>+EJ2#zyUIXu!+ zEcD-D6}RIDWGN}y4>eW&c}fegRm~jTWpnqQ$Z&JL{ooNq8qifAo~$YtW=~pH)yeT>b?B&0c0;axCR<~bMo-yQ1=%0AgVokYDjo^D$ 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 literal 0 HcmV?d00001 diff --git a/img/favicon-192.png b/img/favicon-192.png new file mode 100644 index 0000000000000000000000000000000000000000..876941d150a16e1ec894c609c35e32709687cccb GIT binary patch literal 17981 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 literal 0 HcmV?d00001 diff --git a/img/favicon-196.png b/img/favicon-196.png new file mode 100644 index 0000000000000000000000000000000000000000..1d27fa5eb8858e3b91409163a312c77e7ebc25f0 GIT binary patch literal 18376 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 literal 0 HcmV?d00001 diff --git a/img/favicon-32.png b/img/favicon-32.png new file mode 100644 index 0000000000000000000000000000000000000000..764bb36692dd56b10692f473ffc3eb42a26f5459 GIT binary patch literal 2135 zcmV-d2&ngoP)004R>004l5008;`004mK004C`008P>0026e000+ooVrmw00006 zVoOIv0RI600RN!9r;`8x00(qQO+^Rf1P>852?55XGynhxTS-JgR9M5UmwRm8Wf{jm z&-?ytD;CSkcj?+Mq@-XO$3byF~keeL`@7= zAq2L_0D}^oTq0VS#dHhXx@DUyYdMAXwCB=u`(0lDI4!nG+1i9}a*}iMd*Ao@KF|02 zJiqq{3qt}}4=e@7fkB`Q*wfFa0DpmJ&4Dan%{I}pE0oqfI%cBYl&QISb3Aa(q}W6- zU_6che*#_ws-Gl*%XL&9>-=1DMc4I9AQDg*EiwL1m62y_#MfE0U2NmNry1+3Ri}m; zj{`pdCKpOTpW#^?_|>xO!&{eq-ob=@LNS|`Y?A0ojfwb7_Pbc8Jc>!UQW)^g z3u@*?U}7Nz)ER`iq-Coe4J}iMOs^EEHyY%}^4JlJu4^*XP6xOZALB!EolRS>eGae! zXaiDbli8X#z5?ST#xoQLJXBcFF+l{B4W45dck{IMv?B2|##AvufU*TAtpvDRg{0F2 zrea)v5Bw4EK0ep^u~tXqJ0@U*vdO5B#899d5#^Ay+f=Cag0L*_X~j!cNoHddawP^I zEFc=P*F}(u&50)p6ZJ9wOTa6OB`_mVoaP*e0cN^t=Kwpbn0znY8wuO3iqz^bc9%!# zm`kGDqO~)L+weH{hdjCG>rVoA0`6i=$aKJ9I;c#4&jW{nn2xD0Cc14~ETKHqpqBGU zZ+A#$5*Qz1ld=XGqR^P>J`mTfX9H!d<527mi5pTSM^-|^>5#yHf>o?IP72y7}F#zA}G7AuI`^ss&3zC^R6Lzz~f_xumy;(Uap096d<#LL21>$`R~@rhL?6?6n4kw>_#u z0q&SV$3=NXv%#;J{0xDcK6TOBA3pHQU3NOtMi7`e!6T9+ED2;D%NS#D9EXh?*YoD9 z`xzM@A=G9Ocm^GV_-c)nP`DFd>Vl3aw4(uRuM}i85Yt-S|IP1y<$^1&x|qNZW*sj? zBtcjbXYN&FNTpIlLSbIq{R)-Q2IZq}rFh8wu$Bv)^mfN;>$MRjR7ZS*Is^>@w-_8y zz^6M`v~S(9vllZfa{xyoge1;F;QKz?cU(sIxofBld5<>o!Dqdq*;XF(ev^BlhLwaR zJ1p974H3!;r6Y}DcOv+)0=BGOx3VqUzI2Z63Qbtz^OpVNs*qmN#+EG`0Zss~1IK~i z77u!diUS^^!AT40D{Ug}dMU6$0c$$WTdp0)o^zlrVKnxFg3mx}O?UTdfNuWZ;wOW; z*)#FBOW=YDz)lIN%~lAwO#$&(EP}|~Of8&61)o7nOA4h_in(L{^~#W6@yn)3OCY|+ zLWN|50?L(2^`k)pP3J4I78$w;x8V{5fy=CM3!HK%g7L;!fCzX+!(_ip&@d+~;P~mG zT;MibrL7s#vS96J!x+PRr-uQCMZ}+#)Tm!J2ZtW3c7)p%wc)^@I^q2j!!8ThKX~{= zK9?IycXVdw7;&+vR%;9#c-H^}vnvXeO~5zGN4?9-N9mwx&c6er3OI1;sD;r!uJD=X;z?NDrcO8B7%tU*O&Kk?~i^qIXPLl7kGD3(gEd4 zrFQ;AzL1W^qmoF(upJwv6-EWvDul-RXsn0`N-4C~6beNidGsmnx%Yt&hlWmnA9#wn z?RQqlEw^3E?x$Z`DZ=fUrAuyDbAH$Aj?QenwJoL6nN~itG zuK)l5C3HntbYx+4WjbwdWNBu305UK#FfA}NEipAzF*iCjG&(RjEig4YFffIQcoP5s N002ovPDHLkV1j`4;|Kr% literal 0 HcmV?d00001 diff --git a/img/favicon-512.png b/img/favicon-512.png new file mode 100644 index 0000000000000000000000000000000000000000..124adf7eea8bac6f5e533e80d19b26649a6033bb GIT binary patch literal 49464 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 literal 0 HcmV?d00001 diff --git a/index.html b/index.html index 0bfb4dd..4f664e7 100644 --- a/index.html +++ b/index.html @@ -10,8 +10,20 @@ + + + + + + + + + + + + + - diff --git a/manifest.json b/manifest.json index 94f06a7..b6763ed 100644 --- a/manifest.json +++ b/manifest.json @@ -8,11 +8,11 @@ "theme_color": "#def2d9", "icons": [ { - "src": "/img/192.png", + "src": "/img/favicon-192.png", "sizes": "192x192" }, { - "src": "/img/512.png", + "src": "/img/favicon-512.png", "sizes": "512x512" } ] From 90fb28b2128bfe2779432ca730535909c75e48c5 Mon Sep 17 00:00:00 2001 From: Ryan Carbotte Date: Thu, 16 Apr 2020 00:26:58 -0500 Subject: [PATCH 08/70] feat: Added confirm on reset all fields Closes #119 --- js/scripts.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/js/scripts.js b/js/scripts.js index 65cf904..f7534b6 100644 --- a/js/scripts.js +++ b/js/scripts.js @@ -80,9 +80,11 @@ const initialize = function () { } $("#reset").on("click", function () { - sell_inputs.forEach(input => input.value = '') - fillFields([], false, -1) - update() + if (window.confirm("Are you sure you want to reset all fields?\n\nThis cannot be undone!")) { + sell_inputs.forEach(input => input.value = '') + fillFields([], false, -1) + update() + } }) } From a3dc3d53c70788dbd511b44b1c5b928375b8e70d Mon Sep 17 00:00:00 2001 From: Ryan Carbotte Date: Wed, 15 Apr 2020 21:01:52 -0500 Subject: [PATCH 09/70] feat: Added button to generate a permalink Added a button to the UI near the Reset fields button and generate a URL that only contains the populated fields Closes #108 --- css/styles.css | 28 ++++++++++++++++++++++++---- index.html | 9 ++++++++- js/scripts.js | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 81 insertions(+), 5 deletions(-) diff --git a/css/styles.css b/css/styles.css index af322c6..60c9aa2 100644 --- a/css/styles.css +++ b/css/styles.css @@ -267,10 +267,10 @@ input[type=number] { color: #FFF; } -.reset-button { +.button { + color: #686868; font-family: inherit; font-weight: bold; - color: #FFBABA; padding: 8px 16px; border-width: 0px; border-radius: 40px; @@ -281,13 +281,16 @@ input[type=number] { margin: 16px auto; } -.reset-button:hover { +.button:hover { transform: scale(1.1); cursor: pointer; opacity: 1; box-shadow: 0 1px 6px rgba(0, 0, 0, 0.05), 0 3px 6px rgba(0, 0, 0, 0.09); } +.button.button--reset { + color: #E45B5B; +} .table-wrapper { display: inline-block; @@ -378,7 +381,6 @@ input[type=number] { justify-content: center; } - .waves { position: relative; width: 100%; @@ -388,6 +390,24 @@ input[type=number] { 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: #0AB5CD; +} /* Animation */ .parallax>use { diff --git a/index.html b/index.html index 0bfb4dd..d504ae0 100644 --- a/index.html +++ b/index.html @@ -182,7 +182,14 @@ - diff --git a/js/scripts.js b/js/scripts.js index 65cf904..817ddfb 100644 --- a/js/scripts.js +++ b/js/scripts.js @@ -40,6 +40,8 @@ const sell_inputs = getSellFields() const buy_input = $("#buy") const first_buy_radios = getFirstBuyRadios() const previous_pattern_radios = getPreviousPatternRadios() +const permalink_input = $('#permalink-input') +const permalink_button = $('#permalink-btn') //Functions const fillFields = function (prices, first_buy, previous_pattern) { @@ -79,6 +81,8 @@ const initialize = function () { console.error(e); } + $("#permalink-btn").on("click", copyPermalink) + $("#reset").on("click", function () { sell_inputs.forEach(input => input.value = '') fillFields([], false, -1) @@ -267,6 +271,43 @@ const calculateOutput = function (data, first_buy, previous_pattern) { 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(); + + alert('Copied!'); +} + const update = function () { const sell_prices = getSellPrices(); const buy_price = parseInt(buy_input.val()); @@ -276,6 +317,14 @@ const update = function () { buy_input[0].disabled = first_buy; buy_input[0].placeholder = first_buy ? '—' : '...' + 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) { From f89039454b58b2723f5946d04429ea00c1b5d04e Mon Sep 17 00:00:00 2001 From: Ryan Carbotte Date: Wed, 15 Apr 2020 21:32:59 -0500 Subject: [PATCH 10/70] feat: Add a flash message on permalink copy --- css/styles.css | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ index.html | 2 ++ js/scripts.js | 13 ++++++++++++- 3 files changed, 64 insertions(+), 1 deletion(-) diff --git a/css/styles.css b/css/styles.css index 60c9aa2..e50dc5f 100644 --- a/css/styles.css +++ b/css/styles.css @@ -409,6 +409,56 @@ input[type=number] { color: #0AB5CD; } +/* 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: #FFFAE5; /* Black background color */ + font-family: 'Raleway', sans-serif; + font-weight: 800; + font-size: 1rem; + color: #837865; + 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 rgba(0, 0, 0, 0.06), 0 1px 2px rgba(0, 0, 0, 0.08); +} + +/* 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;} +} + /* Animation */ .parallax>use { animation: move-forever 25s cubic-bezier(.55, .5, .45, .5) infinite; diff --git a/index.html b/index.html index d504ae0..72fe282 100644 --- a/index.html +++ b/index.html @@ -304,6 +304,8 @@

+
Some text some message...
+ diff --git a/js/scripts.js b/js/scripts.js index 817ddfb..3438a3a 100644 --- a/js/scripts.js +++ b/js/scripts.js @@ -42,6 +42,7 @@ 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) { @@ -305,7 +306,17 @@ const copyPermalink = function () { document.execCommand('copy'); permalink_input.hide(); - alert('Copied!'); + flashMessage("Permalink copied!"); +} + +const flashMessage = function(message) { + snackbar.text(message); + snackbar.addClass('show'); + + setTimeout(function () { + snackbar.removeClass('show') + snackbar.text(''); + }, 3000); } const update = function () { From 46f994c0ffba31f65a9f39dc30ed29c9b2de2f85 Mon Sep 17 00:00:00 2001 From: Mike Bryant Date: Thu, 16 Apr 2020 14:11:33 +0100 Subject: [PATCH 11/70] feat: Taking a first stab at implementing translations --- index.html | 19 ++++++++++++------- js/scripts.js | 4 ---- js/translations.js | 25 +++++++++++++++++++++++++ locales/en.json | 9 +++++++++ 4 files changed, 46 insertions(+), 11 deletions(-) create mode 100644 js/translations.js create mode 100644 locales/en.json diff --git a/index.html b/index.html index 4e72a73..8b8aee0 100644 --- a/index.html +++ b/index.html @@ -14,10 +14,10 @@ - + - + @@ -97,15 +97,15 @@
- + - + - + - + - +
@@ -319,8 +319,13 @@
Some text some message...
+ + + + + diff --git a/js/scripts.js b/js/scripts.js index 2a8e58e..242a2f2 100644 --- a/js/scripts.js +++ b/js/scripts.js @@ -346,7 +346,3 @@ const update = function () { calculateOutput(prices, first_buy, previous_pattern); } - -$(document).ready(initialize); -$(document).on("input", update); -$('input[type = radio]').on("change", update); diff --git a/js/translations.js b/js/translations.js new file mode 100644 index 0000000..66479bd --- /dev/null +++ b/js/translations.js @@ -0,0 +1,25 @@ +function updateContent() { + update(); + $("body").localize(); +} + +i18next + .use(i18nextXHRBackend) + .use(i18nextBrowserLanguageDetector) + .init({ + fallbackLng: 'en', + debug: true, + backend: { + loadPath: 'locales/{{lng}}.json', + }, + }, function(err, t) { + jqueryI18next.init(i18next, $); + i18next.on('languageChanged', () => { + updateContent(); + }); + + // init set content + $(document).ready(initialize); + $(document).on("input", updateContent); + $('input[type = radio]').on("change", updateContent); + }); diff --git a/locales/en.json b/locales/en.json new file mode 100644 index 0000000..3304359 --- /dev/null +++ b/locales/en.json @@ -0,0 +1,9 @@ +{ + "patterns": { + "decreasing": "Decreasing", + "fluctuating": "Fluctuating", + "unknown": "I don't know", + "large-spike": "Large Spike", + "small-spike": "Small Spike" + } +} From 2270fba253cc7afdbda82678e8c9b6af30e181bf Mon Sep 17 00:00:00 2001 From: Pi-Hsun Shih Date: Thu, 16 Apr 2020 21:41:58 +0800 Subject: [PATCH 12/70] Change service worker to fetch from internet first. This makes the page less likely to be in a broken state due to updated content. --- service-worker.js | 49 ++++++++++++++++------------------------------- 1 file changed, 17 insertions(+), 32 deletions(-) diff --git a/service-worker.js b/service-worker.js index e68b22d..fb26b82 100644 --- a/service-worker.js +++ b/service-worker.js @@ -33,38 +33,23 @@ self.addEventListener("fetch", function (event) { if (event.request.method !== "GET") return; event.respondWith( - fromCache(event.request).then( - (response) => { - // The response was found in the cache so we responde with it and update the entry - - // This is where we call the server to get the newest version of the - // file to use the next time we show view - event.waitUntil( - fetch(event.request).then(function (response) { - return updateCache(event.request, response); - }) - ); - - return response; - }, - () => { - // The response was not found in the cache so we look for it on the server - return fetch(event.request) - .then(function (response) { - // If request was success, add or update it in the cache - event.waitUntil( - updateCache(event.request, response.clone()) - ); - - return response; - }) - .catch(function (error) { - console.log( - "[PWA] Network request failed and no cache." + error - ); - }); - } - ) + (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; + })() ); }); From 53d2d1bf87741b6b74beecda520de04ae47ea64d Mon Sep 17 00:00:00 2001 From: Mike Bryant Date: Thu, 16 Apr 2020 14:42:36 +0100 Subject: [PATCH 13/70] feat: Localise some more strings --- index.html | 48 ++++++++++++++++++++++++------------------------ locales/en.json | 4 ++++ 2 files changed, 28 insertions(+), 24 deletions(-) diff --git a/index.html b/index.html index 8b8aee0..0dff9cb 100644 --- a/index.html +++ b/index.html @@ -125,11 +125,11 @@
Monday
- +
- +
@@ -137,11 +137,11 @@
Tuesday
- +
- +
@@ -149,11 +149,11 @@
Wednesday
- +
- +
@@ -161,11 +161,11 @@
Thursday
- +
- +
@@ -173,11 +173,11 @@
Friday
- +
- +
@@ -185,11 +185,11 @@
Saturday
- +
- +
@@ -224,45 +224,45 @@
Monday
- AM - PM + +
Tuesday
- AM - PM + +
Wednesday
- AM - PM + +
Thursday
- AM - PM + +
Friday
- AM - PM + +
Saturday
- AM - PM + +
Guaranteed Minimum diff --git a/locales/en.json b/locales/en.json index 3304359..ccbb406 100644 --- a/locales/en.json +++ b/locales/en.json @@ -5,5 +5,9 @@ "unknown": "I don't know", "large-spike": "Large Spike", "small-spike": "Small Spike" + }, + "times": { + "morning": "AM", + "afternoon": "PM" } } From d0fcd18184b48d168bf4407505c05fc06df9e742 Mon Sep 17 00:00:00 2001 From: Pi-Hsun Shih Date: Thu, 16 Apr 2020 21:43:04 +0800 Subject: [PATCH 14/70] Update cache name to invalidate old cache. --- service-worker.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/service-worker.js b/service-worker.js index fb26b82..f64945b 100644 --- a/service-worker.js +++ b/service-worker.js @@ -1,5 +1,5 @@ // PWA Code adapted from https://github.com/pwa-builder/PWABuilder -const CACHE = "pwa-precache"; +const CACHE = "pwa-precache-v1"; const precacheFiles = [ "/index.html", "/js/predictions.js", From 0ef2e3998985e720597eafd8a251ffe4d4904f0e Mon Sep 17 00:00:00 2001 From: Pi-Hsun Shih Date: Thu, 16 Apr 2020 21:44:25 +0800 Subject: [PATCH 15/70] Change tab -> 2 space To align with all other .js files. --- service-worker.js | 66 +++++++++++++++++++++++------------------------ 1 file changed, 33 insertions(+), 33 deletions(-) diff --git a/service-worker.js b/service-worker.js index f64945b..499d0ca 100644 --- a/service-worker.js +++ b/service-worker.js @@ -1,38 +1,38 @@ // 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", + "/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] Install Event processing"); - console.log("[PWA] Skip waiting on install"); - self.skipWaiting(); + 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); - }) - ); + 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()); + 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; + if (event.request.method !== "GET") return; - event.respondWith( + event.respondWith( (async () => { let response; try { @@ -50,26 +50,26 @@ self.addEventListener("fetch", function (event) { } 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"); - } + // 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; - }); - }); + return matching; + }); + }); } function updateCache(request, response) { - return caches.open(CACHE).then(function (cache) { - return cache.put(request, response); - }); + return caches.open(CACHE).then(function (cache) { + return cache.put(request, response); + }); } From 4200c9d09dd21d0d86daf76c8ce5f2e12a89f82e Mon Sep 17 00:00:00 2001 From: Tekaoh <45337851+Tekaoh@users.noreply.github.com> Date: Wed, 15 Apr 2020 16:38:00 -0400 Subject: [PATCH 16/70] Future prices for minimum and maximum columns Closes mikebryant/ac-nh-turnip-prices#43 --- js/predictions.js | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/js/predictions.js b/js/predictions.js index f1410a6..01595b9 100644 --- a/js/predictions.js +++ b/js/predictions.js @@ -570,8 +570,15 @@ function analyze_possibilities(sell_prices, first_buy, previous_pattern) { var weekMins = []; var weekMaxes = []; for (let day of poss.prices.slice(2)) { - weekMins.push(day.min); - weekMaxes.push(day.max); + // 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 = []; + } } poss.weekGuaranteedMinimum = Math.max(...weekMins); poss.weekMax = Math.max(...weekMaxes); @@ -609,7 +616,7 @@ function analyze_possibilities(sell_prices, first_buy, previous_pattern) { 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)), + weekMax: Math.max(...generated_possibilities.map(poss => poss.weekMax)) }); return generated_possibilities; From 2ba5ce01856e7056ea4eef7677e42e1f6e914e4d Mon Sep 17 00:00:00 2001 From: Marcel Deglau Date: Thu, 16 Apr 2020 17:48:20 +0200 Subject: [PATCH 17/70] Added i18n keys to source code --- index.html | 99 ++++++++++++++++++++--------------------------- js/chart.js | 8 ++-- js/predictions.js | 10 ++--- js/scripts.js | 6 +-- locales/en.json | 67 ++++++++++++++++++++++++++++++++ 5 files changed, 121 insertions(+), 69 deletions(-) diff --git a/index.html b/index.html index 0dff9cb..4fe9532 100644 --- a/index.html +++ b/index.html @@ -45,17 +45,14 @@
-

Daisy Mae

-

Hello, and welcome to the Turnip Prophet app on your Nook Phone.

-

This app lets you track your island's turnip prices daily, but you'll have to put the prices in yourself! -

-

After that, the Turnip Prophet app will magically predict the turnip prices you'll have for the rest of - the week. -

+

+

+

+

-

Turnip Prophet

+

-
First-Time Buyer
+
- +
- + - +
-
Previous Pattern
+
- +
@@ -111,19 +107,18 @@
-
Sunday
+
- +
- AM - 8:00 am to 11:59 am - PM - 12:00 pm to 10:00 pm + +
-
Monday
+
@@ -135,7 +130,7 @@
-
Tuesday
+
@@ -147,7 +142,7 @@
-
Wednesday
+
@@ -159,7 +154,7 @@
-
Thursday
+
@@ -171,7 +166,7 @@
-
Friday
+
@@ -183,7 +178,7 @@
-
Saturday
+
@@ -196,19 +191,17 @@
- + -

Output

+

@@ -218,18 +211,18 @@ - - - + + + - - + + @@ -293,24 +286,16 @@
-

Daisy Mae

-

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.

-

This app is still in development, but will improve over time!

+

+

+

-

Daisy Mae

-

- None of this would have been possible without Ninji's work figuring out just how Timmy - and Tommy value their turnips. -

-

- Support, comments and contributions are available through Github -

-

Oh! And let's not forget to thank those who have contributed so far!

+

+

+

+

Contributors:

diff --git a/js/chart.js b/js/chart.js index 9ea48c5..ee635ab 100644 --- a/js/chart.js +++ b/js/chart.js @@ -22,17 +22,17 @@ function update_chart(input_data, possibilities) { datasets = [ { - label: "Input Price", + label: i18next.t("output.chart.input"), data: input_data.slice(1), fill: false, }, { - label: "Minimum", + label: i18next.t("output.chart.minimum"), data: possibilities[0].prices.slice(1).map(day => day.min), fill: false, }, { - label: "Maximum", + label: i18next.t("output.chart.maximum"), data: possibilities[0].prices.slice(1).map(day => day.max), fill: "-1", }, @@ -45,7 +45,7 @@ function update_chart(input_data, possibilities) { chart_instance = new Chart(ctx, { data: { datasets: datasets, - labels: ["Sunday", "Mon AM", "Mon PM", "Tue AM", "Tue PM", "Wed AM", "Wed PM", "Thu AM", "Thu PM", "Fri AM", "Fri PM", "Sat AM", "Sat PM"], + labels: [i18next.t("weekdays.sunday"), i18next.t("weekdays.abr.monday") + i18next.t("times.morning"), i18next.t("weekdays.abr.monday") + i18next.t("times.afternoon"), i18next.t("weekdays.abr.tuesday") + i18next.t("times.morning"), i18next.t("weekdays.abr.tuesday") + i18next.t("times.afternoon"), i18next.t("weekdays.abr.wednesday") + i18next.t("times.morning"), i18next.t("weekdays.abr.wednesday") + i18next.t("times.afternoon"), i18next.t("weekdays.abr.thursday") + i18next.t("times.morning"), i18next.t("weekdays.abr.thursday") + i18next.t("times.afternoon"), i18next.t("weekdays.abr.friday") + i18next.t("times.morning"), i18next.t("weekdays.abr.friday") + i18next.t("times.afternoon"), i18next.t("weekdays.abr.saturday") + i18next.t("times.morning"), i18next.t("weekdays.abr.saturday") + i18next.t("times.afternoon")], }, options: chart_options, type: "line", diff --git a/js/predictions.js b/js/predictions.js index 51353e2..52acd2c 100644 --- a/js/predictions.js +++ b/js/predictions.js @@ -560,7 +560,7 @@ function* } yield { - pattern_description: "Fluctuating", + pattern_description: i18next.t("patterns.fluctuating"), pattern_number: 0, prices: predicted_prices, probability, @@ -639,7 +639,7 @@ function* generate_pattern_1_with_peak(given_prices, peak_start) { } } yield { - pattern_description: "Large spike", + pattern_description: i18next.t("patterns.large-spike"), pattern_number: 1, prices: predicted_prices, probability, @@ -686,7 +686,7 @@ function* generate_pattern_2(given_prices) { } yield { - pattern_description: "Decreasing", + pattern_description: i18next.t("patterns.decreasing"), pattern_number: 2, prices: predicted_prices, probability, @@ -767,7 +767,7 @@ function* generate_pattern_3_with_peak(given_prices, peak_start) { } yield { - pattern_description: "Small spike", + pattern_description: i18next.t("patterns.small-spike"), pattern_number: 3, prices: predicted_prices, probability, @@ -863,7 +863,7 @@ function analyze_possibilities(sell_prices, first_buy, previous_pattern) { } generated_possibilities.unshift({ - pattern_description: "All patterns", + pattern_description: i18next.t("patterns.all"), pattern_number: 4, prices: global_min_max, weekGuaranteedMinimum: Math.min(...generated_possibilities.map(poss => poss.weekGuaranteedMinimum)), diff --git a/js/scripts.js b/js/scripts.js index 242a2f2..f9c834f 100644 --- a/js/scripts.js +++ b/js/scripts.js @@ -85,7 +85,7 @@ const initialize = function () { $("#permalink-btn").on("click", copyPermalink) $("#reset").on("click", function () { - if (window.confirm("Are you sure you want to reset all fields?\n\nThis cannot be undone!")) { + if (window.confirm(i18next.t("prices.reset-warning"))) { sell_inputs.forEach(input => input.value = '') fillFields([], false, -1) update() @@ -260,7 +260,7 @@ const calculateOutput = function (data, first_buy, previous_pattern) { out_line += `
`; for (let day of poss.prices.slice(1)) { if (day.min !== day.max) { - out_line += ``; + out_line += ``; } else { out_line += ``; } @@ -308,7 +308,7 @@ const copyPermalink = function () { document.execCommand('copy'); permalink_input.hide(); - flashMessage("Permalink copied!"); + flashMessage(i18next.t("prices.permalink-copied")); } const flashMessage = function(message) { diff --git a/locales/en.json b/locales/en.json index ccbb406..b31cefd 100644 --- a/locales/en.json +++ b/locales/en.json @@ -1,13 +1,80 @@ { + "general": { + "name": "Turnip Prophet", + "daisymae": "Daisy Mae" + }, + "welcome": { + "salutation": "Hello, and welcome to the Turnip Prophet 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 magically predict the turnip prices you'll have for the rest of the week." + }, + "firsttime": { + "title": "First-Time Buyer", + "description": "Is this your first time buying turnips from Daisy Mae on your island?(This affects your pattern)", + "yes": "Yes", + "no": "No" + }, "patterns": { + "title": "Previous Pattern", + "description": "What was last week's turnip price pattern?(This affects your pattern)", + "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? (If this is your first time buying turnips, this field will be disabled)", + "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": "Guaranteed Maximum", + "chart": { + "input": "Input Price", + "minimum": "Minimum", + "maximum": "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 Ninji's work figuring out just how Timmy and Tommy value their turnips.", + "support": "Support, comments and contributions are available through Github", + "contributors-text": "Oh! And let's not forget to thank those who have contributed so far!", + "contributors": "Contributors" } } From 56b4d1d8056e4f962848031da0823845a0e3c89e Mon Sep 17 00:00:00 2001 From: Marcel Deglau Date: Thu, 16 Apr 2020 17:52:52 +0200 Subject: [PATCH 18/70] Fixed typo --- index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.html b/index.html index 4fe9532..9200cfb 100644 --- a/index.html +++ b/index.html @@ -115,7 +115,7 @@ - +
From 4c5d91be0e921e2101b3aab93da981bf27b44985 Mon Sep 17 00:00:00 2001 From: Marcel Deglau Date: Thu, 16 Apr 2020 18:10:57 +0200 Subject: [PATCH 19/70] Done changes request by @theRTC204 --- index.html | 14 +++++++------- locales/en.json | 10 +++++----- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/index.html b/index.html index 9200cfb..e531c82 100644 --- a/index.html +++ b/index.html @@ -45,7 +45,7 @@
-

+

@@ -75,14 +75,14 @@
-
+
- +
- + - +
@@ -286,13 +286,13 @@
-

+

-

+

diff --git a/locales/en.json b/locales/en.json index b31cefd..1985f5e 100644 --- a/locales/en.json +++ b/locales/en.json @@ -1,14 +1,14 @@ { "general": { "name": "Turnip Prophet", - "daisymae": "Daisy Mae" + "daisy-mae": "Daisy Mae" }, "welcome": { "salutation": "Hello, and welcome to the Turnip Prophet 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 magically predict the turnip prices you'll have for the rest of the week." }, - "firsttime": { + "first-time": { "title": "First-Time Buyer", "description": "Is this your first time buying turnips from Daisy Mae on your island?(This affects your pattern)", "yes": "Yes", @@ -62,11 +62,11 @@ "chance": "% Chance", "to": "to", "minimum": "Guaranteed Minimum", - "maximum": "Guaranteed Maximum", + "maximum": "Potential Maximum", "chart": { "input": "Input Price", - "minimum": "Minimum", - "maximum": "Maximum" + "minimum": "Guaranteed Minimum", + "maximum": "Potential Maximum" } }, "textbox": { From cbb944874ee5b056b2522b7277204ce228756707 Mon Sep 17 00:00:00 2001 From: Marcel Deglau Date: Thu, 16 Apr 2020 18:16:08 +0200 Subject: [PATCH 20/70] Moved white spaced to source code (@mikebryant) --- js/chart.js | 2 +- locales/en.json | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/js/chart.js b/js/chart.js index ee635ab..83e408c 100644 --- a/js/chart.js +++ b/js/chart.js @@ -45,7 +45,7 @@ function update_chart(input_data, possibilities) { chart_instance = new Chart(ctx, { data: { datasets: datasets, - labels: [i18next.t("weekdays.sunday"), i18next.t("weekdays.abr.monday") + i18next.t("times.morning"), i18next.t("weekdays.abr.monday") + i18next.t("times.afternoon"), i18next.t("weekdays.abr.tuesday") + i18next.t("times.morning"), i18next.t("weekdays.abr.tuesday") + i18next.t("times.afternoon"), i18next.t("weekdays.abr.wednesday") + i18next.t("times.morning"), i18next.t("weekdays.abr.wednesday") + i18next.t("times.afternoon"), i18next.t("weekdays.abr.thursday") + i18next.t("times.morning"), i18next.t("weekdays.abr.thursday") + i18next.t("times.afternoon"), i18next.t("weekdays.abr.friday") + i18next.t("times.morning"), i18next.t("weekdays.abr.friday") + i18next.t("times.afternoon"), i18next.t("weekdays.abr.saturday") + i18next.t("times.morning"), i18next.t("weekdays.abr.saturday") + i18next.t("times.afternoon")], + labels: [i18next.t("weekdays.sunday"), i18next.t("weekdays.abr.monday") + " " + i18next.t("times.morning"), i18next.t("weekdays.abr.monday") + " " + i18next.t("times.afternoon"), i18next.t("weekdays.abr.tuesday") + " " + i18next.t("times.morning"), i18next.t("weekdays.abr.tuesday") + " " + i18next.t("times.afternoon"), i18next.t("weekdays.abr.wednesday") + " " + i18next.t("times.morning"), i18next.t("weekdays.abr.wednesday") + " " + i18next.t("times.afternoon"), i18next.t("weekdays.abr.thursday") + " " + i18next.t("times.morning"), i18next.t("weekdays.abr.thursday") + " " + i18next.t("times.afternoon"), i18next.t("weekdays.abr.friday") + " " + i18next.t("times.morning"), i18next.t("weekdays.abr.friday") + " " + i18next.t("times.afternoon"), i18next.t("weekdays.abr.saturday") + " " + i18next.t("times.morning"), i18next.t("weekdays.abr.saturday") + " " + i18next.t("times.afternoon")], }, options: chart_options, type: "line", diff --git a/locales/en.json b/locales/en.json index 1985f5e..9b1e703 100644 --- a/locales/en.json +++ b/locales/en.json @@ -45,12 +45,12 @@ "saturday" : "Saturday", "sunday": "Sunday", "abr": { - "monday": "Mon ", - "tuesday": "Tue ", - "wednesday": "Wed ", - "thursday": "Thu ", - "friday": "Fri ", - "saturday" : "Sat " + "monday": "Mon", + "tuesday": "Tue", + "wednesday": "Wed", + "thursday": "Thu", + "friday": "Fri", + "saturday" : "Sat" } }, "times": { From ae47ca7be868acfb05b7e65f18c14e520e477295 Mon Sep 17 00:00:00 2001 From: Tekaoh <45337851+Tekaoh@users.noreply.github.com> Date: Thu, 16 Apr 2020 17:26:11 -0400 Subject: [PATCH 21/70] Fix a math issue Infinity was being returned as the min and max when the price for Saturday PM was entered. Instead, we should just return the Saturday PM price for both since that sort of reflects the rest of the week, even if it's just a few more hours. --- js/predictions.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/js/predictions.js b/js/predictions.js index 43051ae..cc2ba44 100644 --- a/js/predictions.js +++ b/js/predictions.js @@ -204,8 +204,8 @@ class PDF { } let prob = 0; - const start_idx = Math.round(start) - this.value_start; - const end_idx = Math.round(end) - this.value_start; + const start_idx = Math.round(start) - this.value_start; + const end_idx = Math.round(end) - this.value_start; for (let i = start_idx; i <= end_idx; i++) { const bucket_prob = this.prob[i] * range_intersect_length(this.range_of(i), range); this.prob[i] = bucket_prob; @@ -838,6 +838,10 @@ function analyze_possibilities(sell_prices, first_buy, previous_pattern) { 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); } From 98bda3d8c614f34b6fb259b5f106de52c182534c Mon Sep 17 00:00:00 2001 From: Pupu Date: Fri, 17 Apr 2020 09:48:10 +0800 Subject: [PATCH 22/70] Add language support for zh-TW ,Chinese (Taiwan) --- locales/zh-TW.json | 80 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) create mode 100644 locales/zh-TW.json diff --git a/locales/zh-TW.json b/locales/zh-TW.json new file mode 100644 index 0000000..76a9efb --- /dev/null +++ b/locales/zh-TW.json @@ -0,0 +1,80 @@ +{ + "general": { + "name": "大頭菜價格預測", + "daisy-mae": "曹賣" + }, + "welcome": { + "salutation": "你好,歡迎使用Nook手機上的 大頭菜價格預測機 程式。", + "description": "這個程式可以讓你每天追蹤你島上的大頭菜價格,但你必須自己記錄價格!", + "conclusion": "之後,大頭菜價格預測程式將 神奇地 預測本週剩餘時間的大頭菜價格。" + }, + "first-time": { + "title": "首次購買", + "description": "這是您第一次從島上的曹賣購買大頭菜嗎?(這會影響您這次的模型)", + "yes": "是", + "no": "否" + }, + "patterns": { + "title": "上次的模型", + "description": "上週的大頭菜價格模型如何?(這會影響您這次的模型)", + "pattern": "模型", + "all": "所有模型", + "decreasing": "遞減型", + "fluctuating": "波型", + "unknown": "不知道", + "large-spike": "第三期型", + "small-spike": "第四期型" + }, + "prices": { + "description": "本週大頭菜的購買價格是多少?(如果這是您第一次購買大頭菜,則此欄位會被停用)", + "open": { + "am": "上午 - 08:00 to 11:59", + "pm": "下午 - 12:00 to 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": "如果沒有Ninji 的幫忙來弄清楚豆狸和粒狸如何對他們的大頭菜的估價,那麼這一切都是不可能的。", + "support": "可透過 Github獲得支援, 討論及貢獻", + "contributors-text": "哦!讓我們不要忘記感謝那些迄今為止作出貢獻的人!", + "contributors": "貢獻者" + } +} From 2f489b6753019f3ed4ff2b2705228aee39cf122e Mon Sep 17 00:00:00 2001 From: Splash Date: Fri, 17 Apr 2020 10:37:21 +0800 Subject: [PATCH 23/70] Add Simplified Chinese localization file. --- locales/zh-CN | 80 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) create mode 100644 locales/zh-CN diff --git a/locales/zh-CN b/locales/zh-CN new file mode 100644 index 0000000..325e8d7 --- /dev/null +++ b/locales/zh-CN @@ -0,0 +1,80 @@ +{ + "general": { + "name": "大头菜预测工具", + "daisy-mae": "曹卖" + }, + "welcome": { + "salutation": "大家好,欢迎使用Nook手机上的大头菜预测工具。", + "description": "这个APP可以让你每天跟踪自己岛上大头菜的价格,但你得自己把价格填写进去!", + "conclusion": "之后,大头菜预测工具会神奇地预测出本周剩余时间的大头菜价格。" + }, + "first-time": { + "title": "首次购买", + "description": "你是第一次在自己岛上购买大头菜吗?(将影响预测趋势)", + "yes": "是", + "no": "否" + }, + "patterns": { + "title": "上周趋势", + "description": "上周大头菜的价格趋势是?(将影响预测趋势)", + "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": "如果不是Ninji发现豆狸和粒狸如何给大头菜定价的,这一切将不可能实现。", + "support": "可以在Github获得支持,或讨论和贡献", + "contributors-text": "哦!别忘记感谢那些至今为止做出过贡献的人。", + "contributors": "贡献者" + } +} From d75bfb107f547ac32a035f76e104bcd7cd2a0b7c Mon Sep 17 00:00:00 2001 From: Splash Date: Fri, 17 Apr 2020 10:43:32 +0800 Subject: [PATCH 24/70] Rename zh-CN to zh-CN.json --- locales/{zh-CN => zh-CN.json} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename locales/{zh-CN => zh-CN.json} (100%) diff --git a/locales/zh-CN b/locales/zh-CN.json similarity index 100% rename from locales/zh-CN rename to locales/zh-CN.json From d119c2968999e2c1a9546cd764d985d0d05eac92 Mon Sep 17 00:00:00 2001 From: Pupu Date: Fri, 17 Apr 2020 10:48:23 +0800 Subject: [PATCH 25/70] fixed zh-TW,Chinese (Taiwan) wording --- locales/zh-TW.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/locales/zh-TW.json b/locales/zh-TW.json index 76a9efb..84436a7 100644 --- a/locales/zh-TW.json +++ b/locales/zh-TW.json @@ -10,7 +10,7 @@ }, "first-time": { "title": "首次購買", - "description": "這是您第一次從島上的曹賣購買大頭菜嗎?(這會影響您這次的模型)", + "description": "這是您第一次從自己的島上和曹賣購買大頭菜嗎?(這會影響您這次的模型)", "yes": "是", "no": "否" }, @@ -70,10 +70,10 @@ } }, "textbox": { - "description": "在您紀錄了一些大頭菜價格之後,預測程式會運行運算, 並顯示你所在島嶼可能出現的不同模型。", + "description": "在您紀錄了一些大頭菜價格之後,預測程式會運行運算,並顯示你所在島嶼可能出現的不同模型。", "development": "此程式仍在開發中,但會隨著時間的推移而改善!", "thanks": "如果沒有Ninji 的幫忙來弄清楚豆狸和粒狸如何對他們的大頭菜的估價,那麼這一切都是不可能的。", - "support": "可透過 Github獲得支援, 討論及貢獻", + "support": "可透過 Github獲得支援、討論及貢獻", "contributors-text": "哦!讓我們不要忘記感謝那些迄今為止作出貢獻的人!", "contributors": "貢獻者" } From bec1c4f61b296c26f8140fafe410a2b3ee1e06e0 Mon Sep 17 00:00:00 2001 From: Pupu Date: Fri, 17 Apr 2020 11:01:07 +0800 Subject: [PATCH 26/70] fixed zh-TW,Chinese (Taiwan) wording --- locales/zh-TW.json | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/locales/zh-TW.json b/locales/zh-TW.json index 84436a7..7004b9d 100644 --- a/locales/zh-TW.json +++ b/locales/zh-TW.json @@ -1,22 +1,22 @@ { "general": { - "name": "大頭菜價格預測", + "name": "大頭菜預測工具", "daisy-mae": "曹賣" }, "welcome": { - "salutation": "你好,歡迎使用Nook手機上的 大頭菜價格預測機 程式。", + "salutation": "你好,歡迎使用Nook手機上的 大頭菜預測工具 。", "description": "這個程式可以讓你每天追蹤你島上的大頭菜價格,但你必須自己記錄價格!", - "conclusion": "之後,大頭菜價格預測程式將 神奇地 預測本週剩餘時間的大頭菜價格。" + "conclusion": "接下來,大頭菜預測工具將 神奇地 預測本週剩餘時間的大頭菜價格。" }, "first-time": { "title": "首次購買", - "description": "這是您第一次從自己的島上和曹賣購買大頭菜嗎?(這會影響您這次的模型)", + "description": "這是您第一次從自己的島上和曹賣購買大頭菜嗎?(將影響您這次的模型)", "yes": "是", "no": "否" }, "patterns": { "title": "上次的模型", - "description": "上週的大頭菜價格模型如何?(這會影響您這次的模型)", + "description": "上週的大頭菜價格模型如何?(將影響您這次的模型)", "pattern": "模型", "all": "所有模型", "decreasing": "遞減型", @@ -31,8 +31,8 @@ "am": "上午 - 08:00 to 11:59", "pm": "下午 - 12:00 to 22:00" }, - "copy-permalink": "產生此資料的網址", - "permalink-copied": "網址已複製!", + "copy-permalink": "複製價格分享網址", + "permalink-copied": "網址已複製!", "reset": "清除資料", "reset-warning": "是否確定要清除所有資料?\n\n此動作無法復原!" }, @@ -61,18 +61,18 @@ "title": "結果", "chance": "機率(%)", "to": "~", - "minimum": "最低保證", - "maximum": "最高可能", + "minimum": "保底價格", + "maximum": "最高價格", "chart": { "input": "輸入價格", - "minimum": "最低保證", - "maximum": "最高可能" + "minimum": "保底價格", + "maximum": "最高價格" } }, "textbox": { - "description": "在您紀錄了一些大頭菜價格之後,預測程式會運行運算,並顯示你所在島嶼可能出現的不同模型。", - "development": "此程式仍在開發中,但會隨著時間的推移而改善!", - "thanks": "如果沒有Ninji 的幫忙來弄清楚豆狸和粒狸如何對他們的大頭菜的估價,那麼這一切都是不可能的。", + "description": "在您紀錄了一些大頭菜價格後,大頭菜預測工具會預測,並顯示你島上可能出現的不同模型。", + "development": "此工具仍在開發中,但會隨著時間的推移而改善!", + "thanks": "如果沒有Ninji 的幫忙來弄清楚豆狸和粒狸如何對他們的大頭菜的估價,這一切都是不可能實現的。", "support": "可透過 Github獲得支援、討論及貢獻", "contributors-text": "哦!讓我們不要忘記感謝那些迄今為止作出貢獻的人!", "contributors": "貢獻者" From a65bd7ef2a46e043724b5b8f5cbc9373b87aa1a4 Mon Sep 17 00:00:00 2001 From: Pupu Date: Fri, 17 Apr 2020 11:27:41 +0800 Subject: [PATCH 27/70] fixed zh-TW,Chinese (Taiwan) wording --- locales/zh-TW.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/locales/zh-TW.json b/locales/zh-TW.json index 7004b9d..2aea09b 100644 --- a/locales/zh-TW.json +++ b/locales/zh-TW.json @@ -22,8 +22,8 @@ "decreasing": "遞減型", "fluctuating": "波型", "unknown": "不知道", - "large-spike": "第三期型", - "small-spike": "第四期型" + "large-spike": "三期型", + "small-spike": "四期型" }, "prices": { "description": "本週大頭菜的購買價格是多少?(如果這是您第一次購買大頭菜,則此欄位會被停用)", From b4d7eb0156894412357ee56cdf49d800a09e92fd Mon Sep 17 00:00:00 2001 From: Splash Date: Fri, 17 Apr 2020 15:14:56 +0800 Subject: [PATCH 28/70] Fix #156 Fix https://github.com/mikebryant/ac-nh-turnip-prices/issues/156 --- index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.html b/index.html index e531c82..cd0d3ed 100644 --- a/index.html +++ b/index.html @@ -189,7 +189,7 @@
- +
Some text some message...
From b34a5c20f62a6b06188cd1fa498b64b61defd348 Mon Sep 17 00:00:00 2001 From: Davide Aversa Date: Fri, 17 Apr 2020 10:10:34 +0200 Subject: [PATCH 30/70] Add Italian translation --- locales/it.json | 80 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) create mode 100644 locales/it.json diff --git a/locales/it.json b/locales/it.json new file mode 100644 index 0000000..712c322 --- /dev/null +++ b/locales/it.json @@ -0,0 +1,80 @@ +{ + "general": { + "name": "Profeta delle Rape", + "daisy-mae": "Brunella" + }, + "welcome": { + "salutation": "Ciao e benvenuto all'app Profeta delle Rape 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 il Profeta delle Rape predirrà magicamente i prezzi delle rape che avrai per il resto della settimana." + }, + "first-time": { + "title": "Primo Acquisto", + "description": "È la prima volta che acquisti rape da Brunella?(influisce sul comportamento dei prezzi)", + "yes": "Sì", + "no": "No" + }, + "patterns": { + "title": "Comportamento Precedente", + "description": "Qual'è stato il comportamento dei prezzi delle rape nella scorsa settimana?(influisce sul comportamento dei prezzi)", + "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 questa settimana? (Se è la prima volta che le compri questo campo è disabilitato)", + "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 il Profeta delle Rape", + "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 Gatantito", + "maximum": "Massimo Potenziale" + } + }, + "textbox": { + "description": "Dopo aver inserito alcuni prezzi, il Profeta delle Rape 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 il lavoro di Ninji nello scoprire come Mirko e Marco valutano le rape.", + "support": "Chiedi supporto o lascia commenti e contributi su Github", + "contributors-text": "Oh! Non dimentichiamoci di ringraziare chi ha contribuito fin'ora!", + "contributors": "Collaboratori" + } +} From f6afb113ee6fad03bdf6c9a52f4504de32019282 Mon Sep 17 00:00:00 2001 From: Mike Bryant Date: Fri, 17 Apr 2020 11:19:42 +0100 Subject: [PATCH 31/70] fix: Move input trigger out of local storage block, so it still loads the UI even if we have no storage Fixes #161 --- js/scripts.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/js/scripts.js b/js/scripts.js index f9c834f..e13b254 100644 --- a/js/scripts.js +++ b/js/scripts.js @@ -77,11 +77,12 @@ const initialize = function () { } else { fillFields(prices, first_buy, previous_pattern) } - $(document).trigger("input"); } catch (e) { console.error(e); } + $(document).trigger("input"); + $("#permalink-btn").on("click", copyPermalink) $("#reset").on("click", function () { From 897aac27bba6fea223b62514858ba7ed017a1039 Mon Sep 17 00:00:00 2001 From: blaaaakuu Date: Fri, 17 Apr 2020 22:34:37 +1200 Subject: [PATCH 32/70] Add files via upload --- locales/jp.json | 80 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) create mode 100644 locales/jp.json diff --git a/locales/jp.json b/locales/jp.json new file mode 100644 index 0000000..e8ecf63 --- /dev/null +++ b/locales/jp.json @@ -0,0 +1,80 @@ +{ + "general": { + "name": "カブ預言者", + "daisy-mae": "ウリ" + }, + "welcome": { + "salutation": "こんにちは!タヌキ開発特製のスマホの最新アプリカブ預言者へようこそ。", + "description": "このアプリは無人島のカブ価を毎日予測することができます。でも、まず自分でデータを入力することが必要です!", + "conclusion": "そうしたら、カブ預言者は魔法のように、あなたのこの一周間のカブ価を予測できます。" + }, + "first-time": { + "title": "はじめての購入", + "description": "これはあなたがはじめてウリからカブを購入することですか?(答えによってデータパターンは異なります)", + "yes": "はい", + "no": "いいえ" + }, + "patterns": { + "title": "先週のパターン", + "description": "先週のカブ価変化パターンを選んでください。(答えによってデータパターンは異なります)", + "pattern": "パターン", + "all": "全部のパターン", + "decreasing": "ジリ貧型", + "fluctuating": "波型", + "unknown": "わかりません", + "large-spike": "3期型", + "small-spike": "4期型" + }, + "prices": { + "description": "今週のカブ価は? (初めてカブを購入する際は、この入力欄は無効にされています)", + "open": { + "am": "午前 - 8:00 am to 11:59 am", + "pm": "午後 - 12:00 pm to 10:00 pm" + }, + "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": "このアプリの作成は、タヌキ商店のカブ定価パターンを解析したNinji様のおかげです。ありがとうございます!Ninji's work", + "support": "疑問、コメント、提案などはGithubにお願い致します。", + "contributors-text": "そしてこのアプリの作成をてつだった方々に感謝します!", + "contributors": "貢献者" + } +} \ No newline at end of file From 0798d09646959d83b644a188b697b53a0130fd1b Mon Sep 17 00:00:00 2001 From: blaaaakuu Date: Fri, 17 Apr 2020 22:39:10 +1200 Subject: [PATCH 33/70] Update jp.json --- locales/jp.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/locales/jp.json b/locales/jp.json index e8ecf63..d80dbe4 100644 --- a/locales/jp.json +++ b/locales/jp.json @@ -34,7 +34,7 @@ "copy-permalink": "パーマリンクをコピーする", "permalink-copied": "パーマリンクはコピーされました!", "reset": "カブ預言者をリセットします", - "reset-warning": "本当に全部をリセットしますか?\n\n後戻りはできませんよ!" + "reset-warning": "本当に全部をリセットしますか?\n\nリセットしたら後戻りはできませんよ!" }, "weekdays": { "monday": "月曜日", @@ -77,4 +77,4 @@ "contributors-text": "そしてこのアプリの作成をてつだった方々に感謝します!", "contributors": "貢献者" } -} \ No newline at end of file +} From 4c9a382a30f37fa5bed311b9f85052f7972de2f6 Mon Sep 17 00:00:00 2001 From: blaaaakuu Date: Fri, 17 Apr 2020 22:44:14 +1200 Subject: [PATCH 34/70] Update jp.json --- locales/jp.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/locales/jp.json b/locales/jp.json index d80dbe4..67913a3 100644 --- a/locales/jp.json +++ b/locales/jp.json @@ -70,10 +70,10 @@ } }, "textbox": { - "description": "複数のカブ価を入力したら、カブ預言者はデータを計算して、可能な変動モードを表示します。", - "development": "このアプリはまだ発展中で、完璧のデータを提供するようにがんばります!",  + "description": "複数のカブ価を入力したら、カブ預言者はデータを計算して、可能な変動パターンを表示します。", + "development": "このアプリはまだ開発中で、完璧のデータを提供するようにがんばります!",  "thanks": "このアプリの作成は、タヌキ商店のカブ定価パターンを解析したNinji様のおかげです。ありがとうございます!Ninji's work", - "support": "疑問、コメント、提案などはGithubにお願い致します。", + "support": "疑問·コメント·提案などはGithubにお願い致します。", "contributors-text": "そしてこのアプリの作成をてつだった方々に感謝します!", "contributors": "貢献者" } From 7479e431bf1f18d4f4d3b90ca572bd46451d7fa5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=99=BD=E6=9C=88=E7=A7=8B=E8=A7=81=E5=BF=83?= Date: Fri, 17 Apr 2020 18:52:30 +0800 Subject: [PATCH 35/70] Update zh-CN.json for more easier to understand. --- locales/zh-CN.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/locales/zh-CN.json b/locales/zh-CN.json index 325e8d7..18b1c1e 100644 --- a/locales/zh-CN.json +++ b/locales/zh-CN.json @@ -20,10 +20,10 @@ "pattern": "趋势", "all": "所有趋势", "decreasing": "递减型", - "fluctuating": "波型", + "fluctuating": "波动型", "unknown": "不知道", - "large-spike": "三期型", - "small-spike": "四期型" + "large-spike": "大幅上涨型", + "small-spike": "小幅上涨型" }, "prices": { "description": "本周你的岛上大头菜的购买价格是多少?(如果你是第一次购买大头菜,这个字段不可用)", From 70b8c8fc5584d15937e2849d6e6daa3f3f29424e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=99=BD=E6=9C=88=E7=A7=8B=E8=A7=81=E5=BF=83?= Date: Fri, 17 Apr 2020 18:58:53 +0800 Subject: [PATCH 36/70] Update zh-CN.json --- locales/zh-CN.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/locales/zh-CN.json b/locales/zh-CN.json index 18b1c1e..5910c84 100644 --- a/locales/zh-CN.json +++ b/locales/zh-CN.json @@ -22,8 +22,8 @@ "decreasing": "递减型", "fluctuating": "波动型", "unknown": "不知道", - "large-spike": "大幅上涨型", - "small-spike": "小幅上涨型" + "large-spike": "大幅上涨(四期型)", + "small-spike": "小幅上涨(三期型)" }, "prices": { "description": "本周你的岛上大头菜的购买价格是多少?(如果你是第一次购买大头菜,这个字段不可用)", From 5075bb500e0e4d842b2889e0eb77216ff054d82b Mon Sep 17 00:00:00 2001 From: Peter Shih Date: Fri, 17 Apr 2020 19:39:55 +0800 Subject: [PATCH 37/70] Update zh-CN.json MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Part of the large-spike / small-spike translation is swapped. (The "small-spike" is called "四期型" because the price would increase four (四) times in the week, and "large-spike" == "三期型" because the price would increase three (三) times in the week.) --- locales/zh-CN.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/locales/zh-CN.json b/locales/zh-CN.json index 5910c84..435c715 100644 --- a/locales/zh-CN.json +++ b/locales/zh-CN.json @@ -22,8 +22,8 @@ "decreasing": "递减型", "fluctuating": "波动型", "unknown": "不知道", - "large-spike": "大幅上涨(四期型)", - "small-spike": "小幅上涨(三期型)" + "large-spike": "大幅上涨(三期型)", + "small-spike": "小幅上涨(四期型)" }, "prices": { "description": "本周你的岛上大头菜的购买价格是多少?(如果你是第一次购买大头菜,这个字段不可用)", From a1491fda1038806503c129d64c9972b56c6f8f0b Mon Sep 17 00:00:00 2001 From: Marcel Deglau Date: Fri, 17 Apr 2020 15:41:11 +0200 Subject: [PATCH 38/70] Hard-code app name --- index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.html b/index.html index b30dbc4..ac1931a 100644 --- a/index.html +++ b/index.html @@ -52,7 +52,7 @@
-

+

Turnip Prophet

Date: Fri, 17 Apr 2020 22:39:07 +0800 Subject: [PATCH 39/70] Add a simple language selector. --- css/styles.css | 8 +++++++ index.html | 3 +++ js/translations.js | 54 ++++++++++++++++++++++++++++++---------------- locales/en.json | 3 ++- locales/zh-CN.json | 9 ++++---- locales/zh-TW.json | 5 +++-- 6 files changed, 57 insertions(+), 25 deletions(-) diff --git a/css/styles.css b/css/styles.css index e50dc5f..5e30c01 100644 --- a/css/styles.css +++ b/css/styles.css @@ -65,6 +65,14 @@ h2 { box-shadow: 0 1px 3px rgba(0, 0, 0, 0.06), 0 1px 2px rgba(0, 0, 0, 0.08); } +.dialog-box-lng { + text-align: center; +} + +.dialog-box-lng p,.dialog-box-lng select{ + display: inline; +} + .dialog-box p { font-family: 'Raleway', sans-serif; font-weight: 800; diff --git a/index.html b/index.html index b30dbc4..aaa16a6 100644 --- a/index.html +++ b/index.html @@ -297,6 +297,9 @@

:

+
+

: +
Some text some message...
diff --git a/js/translations.js b/js/translations.js index 66479bd..a87ff30 100644 --- a/js/translations.js +++ b/js/translations.js @@ -4,22 +4,40 @@ function updateContent() { } i18next - .use(i18nextXHRBackend) - .use(i18nextBrowserLanguageDetector) - .init({ - fallbackLng: 'en', - debug: true, - backend: { - loadPath: 'locales/{{lng}}.json', - }, - }, function(err, t) { - jqueryI18next.init(i18next, $); - i18next.on('languageChanged', () => { - updateContent(); - }); - - // init set content - $(document).ready(initialize); - $(document).on("input", updateContent); - $('input[type = radio]').on("change", updateContent); +.use(i18nextXHRBackend) +.use(i18nextBrowserLanguageDetector) +.init({ + fallbackLng: 'en', + debug: true, + backend: { + loadPath: 'locales/{{lng}}.json', + }, +}, (err, t) => { + const languages = [ + ["en", "English"], + ["zh-CN", "简体中文"], + ["zh-TW", "繁體中文"], + ], + languageSelector = $('#language'); + languages.map(([code, name]) => { + languageSelector.append(``); + }); + languageSelector.on('change', function () { + if (this.value == i18next.language) + return; + i18next.changeLanguage(this.value); + }); + jqueryI18next.init(i18next, $); + i18next.on('languageChanged', lng => { + if (!languageSelector.find(`[value=${lng}]`).length) { + i18next.changeLanguage('en'); + return; + } + languageSelector.val(lng); + updateContent(); }); + // init set content + $(document).ready(initialize); + $(document).on("input", updateContent); + $('input[type = radio]').on("change", updateContent); +}); diff --git a/locales/en.json b/locales/en.json index 9b1e703..b9445c4 100644 --- a/locales/en.json +++ b/locales/en.json @@ -75,6 +75,7 @@ "thanks": "None of this would have been possible without Ninji's work figuring out just how Timmy and Tommy value their turnips.", "support": "Support, comments and contributions are available through Github", "contributors-text": "Oh! And let's not forget to thank those who have contributed so far!", - "contributors": "Contributors" + "contributors": "Contributors", + "language": "Language" } } diff --git a/locales/zh-CN.json b/locales/zh-CN.json index 5910c84..2a4a62e 100644 --- a/locales/zh-CN.json +++ b/locales/zh-CN.json @@ -22,8 +22,8 @@ "decreasing": "递减型", "fluctuating": "波动型", "unknown": "不知道", - "large-spike": "大幅上涨(四期型)", - "small-spike": "小幅上涨(三期型)" + "large-spike": "大幅上涨(三期型)", + "small-spike": "小幅上涨(四期型)" }, "prices": { "description": "本周你的岛上大头菜的购买价格是多少?(如果你是第一次购买大头菜,这个字段不可用)", @@ -73,8 +73,9 @@ "description": "在填写一些大头菜价格后,大头菜预测工具将预测大头菜的价格并显示本周可能的趋势。", "development": "APP仍在开发中,但会随着时间的推移不断完善!", "thanks": "如果不是Ninji发现豆狸和粒狸如何给大头菜定价的,这一切将不可能实现。", - "support": "可以在Github获得支持,或讨论和贡献", + "support": "可以在Github获得支持,或是讨论和贡献。", "contributors-text": "哦!别忘记感谢那些至今为止做出过贡献的人。", - "contributors": "贡献者" + "contributors": "贡献者", + "language": "语言" } } diff --git a/locales/zh-TW.json b/locales/zh-TW.json index 2aea09b..119be38 100644 --- a/locales/zh-TW.json +++ b/locales/zh-TW.json @@ -73,8 +73,9 @@ "description": "在您紀錄了一些大頭菜價格後,大頭菜預測工具會預測,並顯示你島上可能出現的不同模型。", "development": "此工具仍在開發中,但會隨著時間的推移而改善!", "thanks": "如果沒有Ninji 的幫忙來弄清楚豆狸和粒狸如何對他們的大頭菜的估價,這一切都是不可能實現的。", - "support": "可透過 Github獲得支援、討論及貢獻", + "support": "可透過 Github獲得支援、討論及貢獻。", "contributors-text": "哦!讓我們不要忘記感謝那些迄今為止作出貢獻的人!", - "contributors": "貢獻者" + "contributors": "貢獻者", + "language": "語言" } } From 8a8fd475e0a57f541b6466d8f0f87f9f1ce010f1 Mon Sep 17 00:00:00 2001 From: Marcel Deglau Date: Fri, 17 Apr 2020 16:45:40 +0200 Subject: [PATCH 40/70] Added German translation (#21) --- css/styles.css | 2 +- locales/de.json | 80 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 81 insertions(+), 1 deletion(-) create mode 100644 locales/de.json diff --git a/css/styles.css b/css/styles.css index e50dc5f..2946cae 100644 --- a/css/styles.css +++ b/css/styles.css @@ -351,7 +351,7 @@ input[type=number] { #turnipTable td { white-space: nowrap; - max-width: 100px; + max-width: 150px; padding: 6px 4px; text-align: center; border-right: 1px solid rgba(0, 0, 0, 0.03); diff --git a/locales/de.json b/locales/de.json new file mode 100644 index 0000000..18ec06c --- /dev/null +++ b/locales/de.json @@ -0,0 +1,80 @@ +{ + "general": { + "name": "Turnip Prophet", + "daisy-mae": "Jorna" + }, + "welcome": { + "salutation": "Hallo, und Willkommen bei der Turnip Prophet 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 magisch 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? (Dies beeinflusst dein Verkaufsmuster)", + "yes": "Ja", + "no": "Nein" + }, + "patterns": { + "title": "Vorheriges Verkaufsmuster", + "description": "Wie war das Verkaufsmuster der letzten Woche? (Dies beeinflusst dein Verkaufsmuster)", + "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? (Wenn du zum ersten Mal Rüben kaufst, wird dieses Feld deaktiviert)", + "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 Ninji herausgefunden hätte, wie Nepp und Schlepp ihre Rübenpreise kalkulieren.", + "support": "Hilfe, Kommentare und Beiträge sind auffindbar über GitHub.com (nur in Englisch).", + "contributors-text": "Oh! Und vergessen wir nicht, denen zu danken, die bis jetzt dazu beigetragen haben!", + "contributors": "Mitwirkende" + } +} From 7249856c3f9c0ea8b6d6019ac5abfd3540627d28 Mon Sep 17 00:00:00 2001 From: Splash Date: Fri, 17 Apr 2020 22:48:48 +0800 Subject: [PATCH 41/70] Update --- js/translations.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/js/translations.js b/js/translations.js index a87ff30..2bedd6b 100644 --- a/js/translations.js +++ b/js/translations.js @@ -1,6 +1,6 @@ function updateContent() { update(); - $("body").localize(); + $('body').localize(); } i18next @@ -14,9 +14,9 @@ i18next }, }, (err, t) => { const languages = [ - ["en", "English"], - ["zh-CN", "简体中文"], - ["zh-TW", "繁體中文"], + ['en', 'English'], + ['zh-CN', '简体中文'], + ['zh-TW', '繁體中文'], ], languageSelector = $('#language'); languages.map(([code, name]) => { @@ -38,6 +38,6 @@ i18next }); // init set content $(document).ready(initialize); - $(document).on("input", updateContent); - $('input[type = radio]').on("change", updateContent); + $(document).on('input', updateContent); + $('input[type = radio]').on('change', updateContent); }); From 09d2bcf6a8c9e1a4c6ae6a907bafda9cbd418010 Mon Sep 17 00:00:00 2001 From: Marcel Deglau Date: Fri, 17 Apr 2020 16:53:39 +0200 Subject: [PATCH 42/70] Add support for PR #168 --- locales/de.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/locales/de.json b/locales/de.json index 18ec06c..dbcb892 100644 --- a/locales/de.json +++ b/locales/de.json @@ -75,6 +75,7 @@ "thanks": "Nichts von all dem wäre möglich gewesen, ohne das Ninji herausgefunden hätte, wie Nepp und Schlepp ihre Rübenpreise kalkulieren.", "support": "Hilfe, Kommentare und Beiträge sind auffindbar über GitHub.com (nur in Englisch).", "contributors-text": "Oh! Und vergessen wir nicht, denen zu danken, die bis jetzt dazu beigetragen haben!", - "contributors": "Mitwirkende" + "contributors": "Mitwirkende", + "language": "Sprache" } } From f3314902bfcdc6cd3b6fe3e5106c6f94c88e088d Mon Sep 17 00:00:00 2001 From: Splash Date: Fri, 17 Apr 2020 22:59:56 +0800 Subject: [PATCH 43/70] Update --- css/styles.css | 3 ++- js/translations.js | 11 +++++++---- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/css/styles.css b/css/styles.css index 5e30c01..6f643eb 100644 --- a/css/styles.css +++ b/css/styles.css @@ -69,7 +69,8 @@ h2 { text-align: center; } -.dialog-box-lng p,.dialog-box-lng select{ +.dialog-box-lng p, +.dialog-box-lng select { display: inline; } diff --git a/js/translations.js b/js/translations.js index 2bedd6b..52b9f37 100644 --- a/js/translations.js +++ b/js/translations.js @@ -2,26 +2,29 @@ function updateContent() { update(); $('body').localize(); } - +const defaultLanguage = 'en'; i18next .use(i18nextXHRBackend) .use(i18nextBrowserLanguageDetector) .init({ - fallbackLng: 'en', + fallbackLng: defaultLanguage, debug: true, backend: { loadPath: 'locales/{{lng}}.json', }, }, (err, t) => { const languages = [ + ['de', 'Deutsch'], ['en', 'English'], ['zh-CN', '简体中文'], - ['zh-TW', '繁體中文'], + ['zh-TW', '繁體中文'] ], languageSelector = $('#language'); languages.map(([code, name]) => { languageSelector.append(``); }); + if (!languageSelector.find('[selected]').length) + languageSelector.val(defaultLanguage); languageSelector.on('change', function () { if (this.value == i18next.language) return; @@ -30,7 +33,7 @@ i18next jqueryI18next.init(i18next, $); i18next.on('languageChanged', lng => { if (!languageSelector.find(`[value=${lng}]`).length) { - i18next.changeLanguage('en'); + i18next.changeLanguage(defaultLanguage); return; } languageSelector.val(lng); From ef8e4dd59ba8cdb80491551b8fea9a63a98dbef3 Mon Sep 17 00:00:00 2001 From: Davide Aversa Date: Fri, 17 Apr 2020 17:07:21 +0200 Subject: [PATCH 44/70] Fix maintainer comments --- locales/it.json | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/locales/it.json b/locales/it.json index 712c322..a6c2112 100644 --- a/locales/it.json +++ b/locales/it.json @@ -1,22 +1,22 @@ { "general": { - "name": "Profeta delle Rape", + "name": "Turnip Prophet", "daisy-mae": "Brunella" }, "welcome": { - "salutation": "Ciao e benvenuto all'app Profeta delle Rape del tuo Nook Phone.", + "salutation": "Ciao e benvenuto nell'app Turnip Prophet 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 il Profeta delle Rape predirrà magicamente i prezzi delle rape che avrai per il resto della settimana." + "conclusion": "Se lo fai Turnip Prophet predirrà magicamente i prezzi delle rape che avrai per il resto della settimana." }, "first-time": { "title": "Primo Acquisto", - "description": "È la prima volta che acquisti rape da Brunella?(influisce sul comportamento dei prezzi)", + "description": "È la prima volta che acquisti sulla tua isola le rape da Brunella?(influisce sul comportamento dei prezzi)", "yes": "Sì", "no": "No" }, "patterns": { "title": "Comportamento Precedente", - "description": "Qual'è stato il comportamento dei prezzi delle rape nella scorsa settimana?(influisce sul comportamento dei prezzi)", + "description": "Qual è stato il comportamento dei prezzi delle rape nella scorsa settimana?(influisce sul comportamento dei prezzi)", "pattern": "Comportamento", "all": "Tutti i comportamenti", "decreasing": "Decrescente", @@ -26,14 +26,14 @@ "small-spike": "Piccolo picco" }, "prices": { - "description": "Qual'era il prezzo di acquisto delle rape questa settimana? (Se è la prima volta che le compri questo campo è disabilitato)", + "description": "Qual era il prezzo di acquisto delle rape sulla tua isola questa settimana? (Se è la prima volta che le compri questo campo è disabilitato)", "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 il Profeta delle Rape", + "reset": "Resetta Turnip Prophet", "reset-warning": "Sei sicuro di voler resettare tutti i campi?\n\nNon può essere annullato!" }, "weekdays": { @@ -70,7 +70,7 @@ } }, "textbox": { - "description": "Dopo aver inserito alcuni prezzi, il Profeta delle Rape calcolerà e mostrerà i possibili comportamenti del prezzo delle rape nella tua isola.", + "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 il lavoro di Ninji nello scoprire come Mirko e Marco valutano le rape.", "support": "Chiedi supporto o lascia commenti e contributi su Github", From 5cbd41cc603c63f1496afc6a6da7eee6a61ff97c Mon Sep 17 00:00:00 2001 From: blaaaakuu Date: Sat, 18 Apr 2020 04:02:17 +1200 Subject: [PATCH 45/70] Update jp.json --- locales/jp.json | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/locales/jp.json b/locales/jp.json index 67913a3..f0b4882 100644 --- a/locales/jp.json +++ b/locales/jp.json @@ -6,11 +6,11 @@ "welcome": { "salutation": "こんにちは!タヌキ開発特製のスマホの最新アプリカブ預言者へようこそ。", "description": "このアプリは無人島のカブ価を毎日予測することができます。でも、まず自分でデータを入力することが必要です!", - "conclusion": "そうしたら、カブ預言者は魔法のように、あなたのこの一周間のカブ価を予測できます。" + "conclusion": "そうしたら、カブ預言者は魔法のように、あなたのこの一週間のカブ価を予測できます。" }, "first-time": { "title": "はじめての購入", - "description": "これはあなたがはじめてウリからカブを購入することですか?(答えによってデータパターンは異なります)", + "description": "あなたが自分の島でカブを購入したのは今回が初めてですか?(答えによってデータパターンは異なります)", "yes": "はい", "no": "いいえ" }, @@ -61,12 +61,12 @@ "title": "結果", "chance": "% チャンス", "to": "~", - "minimum": "保証の最小収入", - "maximum": "可能な最大収入", + "minimum": "保証される最小の収入", + "maximum": "予測される限界の収入", "chart": { "input": "カブ価を入力", - "minimum": "保証の最小収入", - "maximum": "可能な最大収入" + "minimum": "保証される最小の収入", + "maximum": "予測される限界の収入" } }, "textbox": { @@ -74,7 +74,7 @@ "development": "このアプリはまだ開発中で、完璧のデータを提供するようにがんばります!",  "thanks": "このアプリの作成は、タヌキ商店のカブ定価パターンを解析したNinji様のおかげです。ありがとうございます!Ninji's work", "support": "疑問·コメント·提案などはGithubにお願い致します。", - "contributors-text": "そしてこのアプリの作成をてつだった方々に感謝します!", + "contributors-text": "そしてこのアプリの作成を手伝っていただいた方々に感謝します!", "contributors": "貢献者" } } From 291deb43e59b4cecae084216aff857382e7f8cec Mon Sep 17 00:00:00 2001 From: Marcel Deglau Date: Fri, 17 Apr 2020 20:00:16 +0200 Subject: [PATCH 46/70] Closes #173 --- locales/en.json | 1 - locales/jp.json | 1 - locales/zh-CN.json | 1 - locales/zh-TW.json | 1 - 4 files changed, 4 deletions(-) diff --git a/locales/en.json b/locales/en.json index 9b1e703..17eaccc 100644 --- a/locales/en.json +++ b/locales/en.json @@ -1,6 +1,5 @@ { "general": { - "name": "Turnip Prophet", "daisy-mae": "Daisy Mae" }, "welcome": { diff --git a/locales/jp.json b/locales/jp.json index f0b4882..386be3f 100644 --- a/locales/jp.json +++ b/locales/jp.json @@ -1,6 +1,5 @@ { "general": { - "name": "カブ預言者", "daisy-mae": "ウリ" }, "welcome": { diff --git a/locales/zh-CN.json b/locales/zh-CN.json index 435c715..b2c8e31 100644 --- a/locales/zh-CN.json +++ b/locales/zh-CN.json @@ -1,6 +1,5 @@ { "general": { - "name": "大头菜预测工具", "daisy-mae": "曹卖" }, "welcome": { diff --git a/locales/zh-TW.json b/locales/zh-TW.json index 2aea09b..4f8f49e 100644 --- a/locales/zh-TW.json +++ b/locales/zh-TW.json @@ -1,6 +1,5 @@ { "general": { - "name": "大頭菜預測工具", "daisy-mae": "曹賣" }, "welcome": { From 14e18f0dcb0e8f148fe6d462e66ab278a90186c4 Mon Sep 17 00:00:00 2001 From: Marcel Deglau Date: Fri, 17 Apr 2020 20:00:49 +0200 Subject: [PATCH 47/70] Fixes #173 --- locales/de.json | 1 - 1 file changed, 1 deletion(-) diff --git a/locales/de.json b/locales/de.json index dbcb892..d0f45cd 100644 --- a/locales/de.json +++ b/locales/de.json @@ -1,6 +1,5 @@ { "general": { - "name": "Turnip Prophet", "daisy-mae": "Jorna" }, "welcome": { From 9136f579f40891b859c842ef5aa38e6624b859ab Mon Sep 17 00:00:00 2001 From: Kazubu Date: Sat, 18 Apr 2020 01:41:11 +0900 Subject: [PATCH 48/70] rename to ja.json and improve japanese --- locales/ja.json | 79 +++++++++++++++++++++++++++++++++++++++++++++++++ locales/jp.json | 79 ------------------------------------------------- 2 files changed, 79 insertions(+), 79 deletions(-) create mode 100644 locales/ja.json delete mode 100644 locales/jp.json diff --git a/locales/ja.json b/locales/ja.json new file mode 100644 index 0000000..22e5e4d --- /dev/null +++ b/locales/ja.json @@ -0,0 +1,79 @@ +{ + "general": { + "daisy-mae": "ウリ" + }, + "welcome": { + "salutation": "こんにちは!タヌキ開発特製スマホの最新アプリ Turnip Prophet へようこそ。", + "description": "このアプリは、無人島のカブ価を毎日予測することができます。そのためには、まず自分でデータを入力することが必要です!", + "conclusion": "そうすれば、カブ預言者は魔法のように、あなたのこの一週間のカブ価を予測します。" + }, + "first-time": { + "title": "はじめての購入", + "description": "あなたが自分の島でカブを購入したのは今回が初めてですか?(答えによってパターンが変化します)", + "yes": "はい", + "no": "いいえ" + }, + "patterns": { + "title": "先週のパターン", + "description": "先週のカブ価変化パターンを選んでください。(答えによってパターンが変化します)", + "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": "このアプリが作成できたのは、タヌキ商店のカブ価パターンを解析したNinji氏の成果のおかげです。ありがとうございます!", + "support": "疑問·コメント·提案などは、Githubまでお願いします。", + "contributors-text": "そして、このアプリの作成を手伝っていただいた方々に感謝します!", + "contributors": "貢献者" + } +} diff --git a/locales/jp.json b/locales/jp.json deleted file mode 100644 index 386be3f..0000000 --- a/locales/jp.json +++ /dev/null @@ -1,79 +0,0 @@ -{ - "general": { - "daisy-mae": "ウリ" - }, - "welcome": { - "salutation": "こんにちは!タヌキ開発特製のスマホの最新アプリカブ預言者へようこそ。", - "description": "このアプリは無人島のカブ価を毎日予測することができます。でも、まず自分でデータを入力することが必要です!", - "conclusion": "そうしたら、カブ預言者は魔法のように、あなたのこの一週間のカブ価を予測できます。" - }, - "first-time": { - "title": "はじめての購入", - "description": "あなたが自分の島でカブを購入したのは今回が初めてですか?(答えによってデータパターンは異なります)", - "yes": "はい", - "no": "いいえ" - }, - "patterns": { - "title": "先週のパターン", - "description": "先週のカブ価変化パターンを選んでください。(答えによってデータパターンは異なります)", - "pattern": "パターン", - "all": "全部のパターン", - "decreasing": "ジリ貧型", - "fluctuating": "波型", - "unknown": "わかりません", - "large-spike": "3期型", - "small-spike": "4期型" - }, - "prices": { - "description": "今週のカブ価は? (初めてカブを購入する際は、この入力欄は無効にされています)", - "open": { - "am": "午前 - 8:00 am to 11:59 am", - "pm": "午後 - 12:00 pm to 10:00 pm" - }, - "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": "このアプリの作成は、タヌキ商店のカブ定価パターンを解析したNinji様のおかげです。ありがとうございます!Ninji's work", - "support": "疑問·コメント·提案などはGithubにお願い致します。", - "contributors-text": "そしてこのアプリの作成を手伝っていただいた方々に感謝します!", - "contributors": "貢献者" - } -} From 17474a9f7966f9441886c6550f0d67f3a16d99b7 Mon Sep 17 00:00:00 2001 From: Kazubu Date: Sat, 18 Apr 2020 04:28:52 +0900 Subject: [PATCH 49/70] translated app name lingered in ja.json. --- locales/ja.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/locales/ja.json b/locales/ja.json index 22e5e4d..074f78b 100644 --- a/locales/ja.json +++ b/locales/ja.json @@ -5,7 +5,7 @@ "welcome": { "salutation": "こんにちは!タヌキ開発特製スマホの最新アプリ Turnip Prophet へようこそ。", "description": "このアプリは、無人島のカブ価を毎日予測することができます。そのためには、まず自分でデータを入力することが必要です!", - "conclusion": "そうすれば、カブ預言者は魔法のように、あなたのこの一週間のカブ価を予測します。" + "conclusion": "そうすれば、Turnip Prophetは魔法のように、あなたのこの一週間のカブ価を予測します。" }, "first-time": { "title": "はじめての購入", From ef6af33fdbdb71ee7ee6f5b8a3beaa3b7475ced8 Mon Sep 17 00:00:00 2001 From: Splash Date: Sat, 18 Apr 2020 11:29:21 +0800 Subject: [PATCH 50/70] Remove some changes --- locales/zh-CN.json | 6 +++--- locales/zh-TW.json | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/locales/zh-CN.json b/locales/zh-CN.json index 2a4a62e..04ccd71 100644 --- a/locales/zh-CN.json +++ b/locales/zh-CN.json @@ -22,8 +22,8 @@ "decreasing": "递减型", "fluctuating": "波动型", "unknown": "不知道", - "large-spike": "大幅上涨(三期型)", - "small-spike": "小幅上涨(四期型)" + "large-spike": "大幅上涨(四期型)", + "small-spike": "小幅上涨(三期型)" }, "prices": { "description": "本周你的岛上大头菜的购买价格是多少?(如果你是第一次购买大头菜,这个字段不可用)", @@ -73,7 +73,7 @@ "description": "在填写一些大头菜价格后,大头菜预测工具将预测大头菜的价格并显示本周可能的趋势。", "development": "APP仍在开发中,但会随着时间的推移不断完善!", "thanks": "如果不是Ninji发现豆狸和粒狸如何给大头菜定价的,这一切将不可能实现。", - "support": "可以在Github获得支持,或是讨论和贡献。", + "support": "可以在Github获得支持,或讨论和贡献", "contributors-text": "哦!别忘记感谢那些至今为止做出过贡献的人。", "contributors": "贡献者", "language": "语言" diff --git a/locales/zh-TW.json b/locales/zh-TW.json index 119be38..039e256 100644 --- a/locales/zh-TW.json +++ b/locales/zh-TW.json @@ -73,7 +73,7 @@ "description": "在您紀錄了一些大頭菜價格後,大頭菜預測工具會預測,並顯示你島上可能出現的不同模型。", "development": "此工具仍在開發中,但會隨著時間的推移而改善!", "thanks": "如果沒有Ninji 的幫忙來弄清楚豆狸和粒狸如何對他們的大頭菜的估價,這一切都是不可能實現的。", - "support": "可透過 Github獲得支援、討論及貢獻。", + "support": "可透過 Github獲得支援、討論及貢獻", "contributors-text": "哦!讓我們不要忘記感謝那些迄今為止作出貢獻的人!", "contributors": "貢獻者", "language": "語言" From 0d11405c7d4d14d288d5b8b7aab85732965ca8ab Mon Sep 17 00:00:00 2001 From: Splash Date: Sat, 18 Apr 2020 11:42:08 +0800 Subject: [PATCH 51/70] Add some style for language selector. --- css/styles.css | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/css/styles.css b/css/styles.css index 6f643eb..01513da 100644 --- a/css/styles.css +++ b/css/styles.css @@ -74,6 +74,27 @@ h2 { display: inline; } +.dialog-box-lng select { + font-size: 1rem; + padding: 4px; + font-weight: bold; + border-radius: 4px; + border-color: #DEF2D9; + color: #837865; + cursor: pointer; + transition: 0.2s all; +} + +.dialog-box-lng select:hover { + background-color: #EBFEFD; + border-color: #5ECEDB; + box-shadow: 0 2px 4px rgba(0, 0, 0, 0.16); +} + +.dialog-box-lng select:focus { + outline: none; +} + .dialog-box p { font-family: 'Raleway', sans-serif; font-weight: 800; From 0808d7d52e40088b3e79bed70b5cb2a16098a821 Mon Sep 17 00:00:00 2001 From: Splash Date: Sat, 18 Apr 2020 11:47:30 +0800 Subject: [PATCH 52/70] Add Italian and Japanese to the language list --- js/translations.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/js/translations.js b/js/translations.js index 52b9f37..c8c4b49 100644 --- a/js/translations.js +++ b/js/translations.js @@ -16,6 +16,8 @@ i18next const languages = [ ['de', 'Deutsch'], ['en', 'English'], + ['it', 'Italiano'], + ['ja', '日本語'], ['zh-CN', '简体中文'], ['zh-TW', '繁體中文'] ], From 2218c10d7767e84d8bae1bd7fca30dfdd9485499 Mon Sep 17 00:00:00 2001 From: Nathan Abel Date: Thu, 16 Apr 2020 16:00:38 +0100 Subject: [PATCH 53/70] Squashed commit of the following: commit 4d46f7cfbda7d1818c5c07d22dce160fc5893ff4 Author: Nathan Abel Date: Wed Apr 15 12:43:30 2020 -0400 Delete launch.json This is a vscode config file. I forgot to remove it :) commit 96341d0030224d612fbd9bd20ca7c82405f817a9 Author: Nathan Abel Date: Wed Apr 15 12:40:15 2020 -0400 Handle Missing Patterns commit 7d995d5695861f81b1500ea63cbd0233530c9dea Author: Nathan Abel Date: Wed Apr 15 12:27:29 2020 -0400 Line break added commit a0b5f13db7504e2d3793cab7527b84cbe2b192c4 Author: Nathan Abel Date: Wed Apr 15 12:25:33 2020 -0400 Merge results into one col commit 6576eb1a55cdb978aca73cb16547fd87a41477c2 Author: Nathan Abel Date: Wed Apr 15 12:13:44 2020 -0400 Fix Sorting and Add Category Row commit c9b257cf6f7487c271be5d3801399cc7cd92e67b Merge: 511ef3c 8f49882 Author: Nathan Abel Date: Wed Apr 15 12:11:04 2020 -0400 Merge branch 'master' of https://github.com/mikebryant/ac-nh-turnip-prices into category_total_chance commit 511ef3caad223a4da0cd7f6ce4e68c5d108cbadd Author: Nathan Abel Date: Mon Apr 13 11:49:58 2020 -0400 Fix it better :) commit fcb0429fa1711534ffe875b94fddfb54c33a75df Author: Nathan Abel Date: Mon Apr 13 11:42:45 2020 -0400 Fix sort function --- js/predictions.js | 20 +++++++++++++------- js/scripts.js | 11 ++++++++++- 2 files changed, 23 insertions(+), 8 deletions(-) diff --git a/js/predictions.js b/js/predictions.js index 0a280cc..9a50b9e 100644 --- a/js/predictions.js +++ b/js/predictions.js @@ -845,15 +845,21 @@ function analyze_possibilities(sell_prices, first_buy, previous_pattern) { poss.weekGuaranteedMinimum = Math.max(...weekMins); poss.weekMax = Math.max(...weekMaxes); } + category_totals = {} + for (let i of ["Fluctuating", "Decreasing", "Small spike", "Large spike"]) { + category_totals[i] = generated_possibilities + .filter(value => value.pattern_description == i) + .map(value => value.probability) + .reduce((previous, current) => previous + current, 0) + console.log(category_totals[i]) + } + + for (let pos of generated_possibilities) { + pos.category_total_probability = category_totals[pos.pattern_description] + } generated_possibilities.sort((a, b) => { - if (a.weekMax < b.weekMax) { - return 1; - } else if (a.weekMax > b.weekMax) { - return -1; - } else { - return 0; - } + return b.category_total_probability - a.category_total_probability }); global_min_max = []; diff --git a/js/scripts.js b/js/scripts.js index e13b254..e4812a7 100644 --- a/js/scripts.js +++ b/js/scripts.js @@ -256,9 +256,18 @@ const calculateOutput = function (data, first_buy, previous_pattern) { } let output_possibilities = ""; let analyzed_possibilities = analyze_possibilities(data, first_buy, previous_pattern); + previous_pattern_description = "" for (let poss of analyzed_possibilities) { var out_line = "
" - out_line += ``; + if (previous_pattern_description != poss.pattern_description) { + previous_pattern_description = poss.pattern_description + pattern_count = analyzed_possibilities + .filter(val => val.pattern_description == poss.pattern_description) + .length + percentage_display = percent => Number.isFinite(percent) ? ((percent * 100).toPrecision(3) + '%') : '—' + out_line += `` : ""; + } for (let day of poss.prices.slice(1)) { if (day.min !== day.max) { out_line += ``; From 4c2f738a6b61e5209997cbac4dad4ec6ead3f4b0 Mon Sep 17 00:00:00 2001 From: Mike Bryant Date: Thu, 16 Apr 2020 20:00:35 +0100 Subject: [PATCH 54/70] feat: Allow for row probabilities Also change to use number not description, to work with translations --- index.html | 1 + js/predictions.js | 12 ++++++------ js/scripts.js | 12 ++++++------ 3 files changed, 13 insertions(+), 12 deletions(-) diff --git a/index.html b/index.html index c64963f..af325bc 100644 --- a/index.html +++ b/index.html @@ -213,6 +213,7 @@ + " - if (previous_pattern_description != poss.pattern_description) { - previous_pattern_description = poss.pattern_description + if (previous_pattern_number != poss.pattern_number) { + previous_pattern_number = poss.pattern_number pattern_count = analyzed_possibilities - .filter(val => val.pattern_description == poss.pattern_description) + .filter(val => val.pattern_number == poss.pattern_number) .length percentage_display = percent => Number.isFinite(percent) ? ((percent * 100).toPrecision(3) + '%') : '—' - out_line += `` : ""; + out_line += ``; } + out_line += ``; for (let day of poss.prices.slice(1)) { if (day.min !== day.max) { out_line += ``; From a68ba675a638c9a25854040119cbbd9e9b6e95f6 Mon Sep 17 00:00:00 2001 From: Mike Bryant Date: Sat, 18 Apr 2020 15:33:37 +0100 Subject: [PATCH 55/70] fix: Make Chance a colspan instead of duplicated labels --- index.html | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/index.html b/index.html index af325bc..a14990c 100644 --- a/index.html +++ b/index.html @@ -212,8 +212,7 @@ - - +
Pattern% ChanceSunday -
Monday
+
-
Tuesday
+
@@ -237,7 +230,7 @@
-
Wednesday
+
@@ -245,28 +238,28 @@
-
Thursday
+
-
Friday
+
-
Saturday
+
Guaranteed MinimumPotential Maximum
${Number.isFinite(poss.probability) ? ((poss.probability * 100).toPrecision(3) + '%') : '—'}${day.min} to ${day.max}${day.min} ${i18next.t("output.to")} ${day.max}${day.min}
" + poss.pattern_description + "${Number.isFinite(poss.probability) ? ((poss.probability * 100).toPrecision(3) + '%') : '—'}${percentage_display(poss.category_total_probability)}
`; + out_line += Number.isFinite(poss.probability) ? `(${pattern_count} @ ${percentage_display(poss.probability)})
${day.min} ${i18next.t("output.to")} ${day.max}
diff --git a/js/predictions.js b/js/predictions.js index 9a50b9e..a6d00d2 100644 --- a/js/predictions.js +++ b/js/predictions.js @@ -845,21 +845,21 @@ function analyze_possibilities(sell_prices, first_buy, previous_pattern) { poss.weekGuaranteedMinimum = Math.max(...weekMins); poss.weekMax = Math.max(...weekMaxes); } + category_totals = {} - for (let i of ["Fluctuating", "Decreasing", "Small spike", "Large spike"]) { + for (let i of [0, 1, 2, 3]) { category_totals[i] = generated_possibilities - .filter(value => value.pattern_description == i) + .filter(value => value.pattern_number == i) .map(value => value.probability) - .reduce((previous, current) => previous + current, 0) - console.log(category_totals[i]) + .reduce((previous, current) => previous + current, 0); } for (let pos of generated_possibilities) { - pos.category_total_probability = category_totals[pos.pattern_description] + pos.category_total_probability = category_totals[pos.pattern_number]; } generated_possibilities.sort((a, b) => { - return b.category_total_probability - a.category_total_probability + return b.category_total_probability - a.category_total_probability || b.probability - a.probability; }); global_min_max = []; diff --git a/js/scripts.js b/js/scripts.js index e4812a7..a60bc60 100644 --- a/js/scripts.js +++ b/js/scripts.js @@ -256,18 +256,18 @@ const calculateOutput = function (data, first_buy, previous_pattern) { } let output_possibilities = ""; let analyzed_possibilities = analyze_possibilities(data, first_buy, previous_pattern); - previous_pattern_description = "" + previous_pattern_number = "" for (let poss of analyzed_possibilities) { var out_line = "
" + poss.pattern_description + "${percentage_display(poss.category_total_probability)}
`; - out_line += Number.isFinite(poss.probability) ? `(${pattern_count} @ ${percentage_display(poss.probability)})
${percentage_display(poss.category_total_probability)}${percentage_display(poss.probability)}${day.min} ${i18next.t("output.to")} ${day.max}
From 6336961dd14d253833c3d4315b556f71fcf8f4f7 Mon Sep 17 00:00:00 2001 From: KeruWolf <63780753+KeruWolf@users.noreply.github.com> Date: Sat, 18 Apr 2020 17:21:12 +0200 Subject: [PATCH 56/70] Create es.json Here's my proposed translation for the Turnip Prophet page for Spanish! --- locales/es.json | 80 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) create mode 100644 locales/es.json diff --git a/locales/es.json b/locales/es.json new file mode 100644 index 0000000..feaee67 --- /dev/null +++ b/locales/es.json @@ -0,0 +1,80 @@ + + "general": { + "daisy-mae": "Juliana" + }, + "welcome": { + "salutation": "¡Hola! Te damos la bienvenida a la aplicación Turnip Prophet 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á mágicamente el precio que tendrán los nabos el resto de la semana." + }, + "first-time": { + "title": "Comprador(a) primerizo(a)", + "description": "¿Es esta la primera vez que has comprado nabos?(Esta información afectará a tu patrón)", + "yes": "Sí", + "no": "No" + }, + "patterns": { + "title": "Patrón anterior", + "description": "¿Qué patrón describió el precio de los nabos la semana pasada?(Esta información afectará a tu patrón)", + "pattern": "Pattern", + "all": "All patterns", + "decreasing": "Decreciente", + "fluctuating": "Fluctuante", + "unknown": "No lo sé", + "large-spike": "Pico alto", + "small-spike": "Pico moderado" + }, + "prices": { + "description": "¿Cuál fue el precio más alto que alcanzaron los nabos en tu isla durante la semana? (Si esta es tu primera vez comprando nabos, este campo se desactivará)", + "open": { + "am": "AM - De 8:00 a 11:59", + "pm": "PM - De 12:00 a 10: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, el 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 trabajo de Ninji para averiguar cómo Tendo y Nendo valoran los nabos.", + "support": "Para asistencia, comentarios y contribuciones, no dudes en pasarte por Github.", + "contributors-text": "¡Ah! ¡Y no nos olvidemos de todos los que han puesto su granito de arena hasta ahora!", + "contributors": "Contribuidores", + "language": "Language" + } +} From 360ca57681e4272b6bf4c916f484e8cfe5f47100 Mon Sep 17 00:00:00 2001 From: Matthew Callis Date: Sat, 18 Apr 2020 13:34:24 -0700 Subject: [PATCH 57/70] Change script ordering to fir iOS & Safari Due to the missing `initialize` variable in `translations.js` which lives in `scipts.js` there is a `ReferenceError: Can't find variable: initialize` breaking iOS & Safari. --- index.html | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/index.html b/index.html index a14990c..2b93582 100644 --- a/index.html +++ b/index.html @@ -311,9 +311,9 @@ - + - From 874f6f8e9bc2fe4c5fe0a7e5d24dab112e7dd08e Mon Sep 17 00:00:00 2001 From: arctco <43727772+arctco@users.noreply.github.com> Date: Sat, 18 Apr 2020 19:05:28 -0300 Subject: [PATCH 58/70] Add files via upload --- locales/pt-BR.json | 80 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) create mode 100644 locales/pt-BR.json diff --git a/locales/pt-BR.json b/locales/pt-BR.json new file mode 100644 index 0000000..1ab4484 --- /dev/null +++ b/locales/pt-BR.json @@ -0,0 +1,80 @@ +{ + "general": { + "daisy-mae": "Daisy Mae" + }, + "welcome": { + "salutation": "Olá, e bem-vindo ao aplicativo Turnip Prophet 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á magicamente 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? (Isso afeta seu padrão)", + "yes": "Sim", + "no": "Não" + }, + "patterns": { + "title": "Padrão Anterior", + "description": "Qual foi o padrão de preços de nabo da semana passada? (Isso afeta seu padrão)", + "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? (Se esta é a primeira vez que compra nabos, este campo ficará desativado)", + "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": "í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 trabalho de Ninji's descobrindo como Timmy e Tommy valorizam seus nabos.", + "support": "Suporte, comentários e contribuições estão disponíveis através do Github", + "contributors-text": "Oh! E não vamos nos esquecer de agradecer àqueles que contribuíram até agora!", + "contributors": "Contribuidores", + "language": "Linguagem" + } +} \ No newline at end of file From 97000c58e22fdf714ddae4ee28be2c7f16421639 Mon Sep 17 00:00:00 2001 From: arctco <43727772+arctco@users.noreply.github.com> Date: Sat, 18 Apr 2020 22:52:36 -0300 Subject: [PATCH 59/70] Update translations.js --- js/translations.js | 1 + 1 file changed, 1 insertion(+) diff --git a/js/translations.js b/js/translations.js index c8c4b49..84a69e2 100644 --- a/js/translations.js +++ b/js/translations.js @@ -18,6 +18,7 @@ i18next ['en', 'English'], ['it', 'Italiano'], ['ja', '日本語'], + ['pt-BR', 'Português'] ['zh-CN', '简体中文'], ['zh-TW', '繁體中文'] ], From 3045fe2e9c80c9e2f532ebf7563e1f3494539832 Mon Sep 17 00:00:00 2001 From: arctco <43727772+arctco@users.noreply.github.com> Date: Sat, 18 Apr 2020 22:56:07 -0300 Subject: [PATCH 60/70] Update pt-BR.json --- locales/pt-BR.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/locales/pt-BR.json b/locales/pt-BR.json index 1ab4484..6b81af8 100644 --- a/locales/pt-BR.json +++ b/locales/pt-BR.json @@ -64,7 +64,7 @@ "maximum": "Potencial Máximo", "chart": { "input": "Preço de entrada", - "minimum": "ínimo Garantido", + "minimum": "Mínimo Garantido", "maximum": "Potencial Máximo" } }, @@ -77,4 +77,4 @@ "contributors": "Contribuidores", "language": "Linguagem" } -} \ No newline at end of file +} From e416b779efd8907aee97d3d01c7febfad1b66b3d Mon Sep 17 00:00:00 2001 From: captaincurls <63938599+captaincurls@users.noreply.github.com> Date: Sun, 19 Apr 2020 11:30:11 +0900 Subject: [PATCH 61/70] Create ru.json Hello! I made a Russian translation for this project, would appreciate it being added to the app :) --- locales/ru.json | 80 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) create mode 100644 locales/ru.json diff --git a/locales/ru.json b/locales/ru.json new file mode 100644 index 0000000..8d3849d --- /dev/null +++ b/locales/ru.json @@ -0,0 +1,80 @@ +{ + "general": { + "daisy-mae": "Дейзи Мэй" + }, + "welcome": { + "salutation": "Добрый день! Добро пожаловать в приложение Препсказатель на Вашем Нукофоне.", + "description": "Это приложение позволяет Вам ежедневно отслеживать стоимость репы на Вашем острове. Будьте внимательны, Вам придется вводить ее вручную!", + "conclusion": "После этого приложение Препсказатель как по волшебству/b> предскажет стоимость репы в Вашем магазине на этой неделе." + }, + "first-time": { + "title": "Новичок рынка репы", + "description": "Вы впервые приобретаете репу у Дейзи Мэй на своем острове?(Это влияет на модель стоимости)", + "yes": "Да", + "no": "Нет" + }, + "patterns": { + "title": "Предыдущая модель", + "description": "Какая модель стоимости репы была у Вас на прошлой неделе?(Это влияет на модель стоимости)", + "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": "Если бы Ninji не смог разузнать, как Тимми и Томми определяют стоимость репы, данного приложения могло бы и не быть!", + "support": "Поддержать нас, прокомментировать, а также внести свой вклад Вы можете на Github", + "contributors-text": "Точно! Нельзя забывать тех, кто уже помог проекту!", + "contributors": "Вклад внесли:", + "language": "Язык" + } +} From 13d0cd69377dd2a8a9beea7382fde066184ffb92 Mon Sep 17 00:00:00 2001 From: Mike Bryant Date: Sun, 19 Apr 2020 13:53:46 +0100 Subject: [PATCH 62/70] fix: Add missing comma --- js/translations.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/translations.js b/js/translations.js index 84a69e2..75870df 100644 --- a/js/translations.js +++ b/js/translations.js @@ -18,7 +18,7 @@ i18next ['en', 'English'], ['it', 'Italiano'], ['ja', '日本語'], - ['pt-BR', 'Português'] + ['pt-BR', 'Português'], ['zh-CN', '简体中文'], ['zh-TW', '繁體中文'] ], From 2df3330e7d967606c27940a71d6974a898a37ee0 Mon Sep 17 00:00:00 2001 From: Adri1 Date: Thu, 16 Apr 2020 23:17:30 +0200 Subject: [PATCH 63/70] French Localization File Added --- locales/fr.json | 80 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) create mode 100644 locales/fr.json diff --git a/locales/fr.json b/locales/fr.json new file mode 100644 index 0000000..35ca5a8 --- /dev/null +++ b/locales/fr.json @@ -0,0 +1,80 @@ +{ + "general": { + "daisy-mae": "Porcelette" + }, + "welcome": { + "salutation": "Bonjour et bienvenue sur l'application du Turnip Prophet 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 magiquement 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 ?(Cela influencera le type de ta courbe actuelle)", + "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 ?(Cela influencera le type de ta courbe actuelle)", + "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 ?(Si c'est la première fois que t'en achètes, ce champ sera desactivé)", + "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 le travail de Ninji et son analyse sur comment Méli et Mélo déterminent la valeur des Navets.", + "support": "Aide, commentaires et contributions sont disponibles via Github", + "contributors-text": "Oh ! Et n'oublions pas de remercier toutes les personnes ayant contribué jusqu'à maintenant !", + "contributors": "Contributeurs" + "language": "Langue" + } +} \ No newline at end of file From 3dd96711951529502c86f8c5b6bafcdecde3dd1c Mon Sep 17 00:00:00 2001 From: Aymeric Giraudet Date: Sun, 19 Apr 2020 15:46:07 +0200 Subject: [PATCH 64/70] Added french language option in select Fixed json formatting and comma removed trailing return --- js/translations.js | 1 + locales/fr.json | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/js/translations.js b/js/translations.js index 75870df..d2658dc 100644 --- a/js/translations.js +++ b/js/translations.js @@ -16,6 +16,7 @@ i18next const languages = [ ['de', 'Deutsch'], ['en', 'English'], + ['fr', 'Français'], ['it', 'Italiano'], ['ja', '日本語'], ['pt-BR', 'Português'], diff --git a/locales/fr.json b/locales/fr.json index 35ca5a8..d9e527f 100644 --- a/locales/fr.json +++ b/locales/fr.json @@ -74,7 +74,7 @@ "thanks": "Rien de tout ça n'aurait pu être possible sans le travail de Ninji et son analyse sur comment Méli et Mélo déterminent la valeur des Navets.", "support": "Aide, commentaires et contributions sont disponibles via Github", "contributors-text": "Oh ! Et n'oublions pas de remercier toutes les personnes ayant contribué jusqu'à maintenant !", - "contributors": "Contributeurs" - "language": "Langue" + "contributors": "Contributeurs", + "language": "Langue" } } \ No newline at end of file From 399dd80580406a677099b9da7e7c78d3a4b38860 Mon Sep 17 00:00:00 2001 From: Dmitrii <63938599+captaincurls@users.noreply.github.com> Date: Mon, 20 Apr 2020 00:16:21 +0900 Subject: [PATCH 65/70] Update translations.js --- js/translations.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/js/translations.js b/js/translations.js index c8c4b49..47e6ed9 100644 --- a/js/translations.js +++ b/js/translations.js @@ -16,8 +16,11 @@ i18next const languages = [ ['de', 'Deutsch'], ['en', 'English'], + ['fr', 'Français'], ['it', 'Italiano'], + ['ru', 'Русский'], ['ja', '日本語'], + ['pt-BR', 'Português'], ['zh-CN', '简体中文'], ['zh-TW', '繁體中文'] ], From 41c4251184e213904354fe2e813bfa8bc0e6cd57 Mon Sep 17 00:00:00 2001 From: KeruWolf <63780753+KeruWolf@users.noreply.github.com> Date: Sun, 19 Apr 2020 17:28:54 +0200 Subject: [PATCH 66/70] Update es.json MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit I translated the lines I previously missed (thanks @mauriciabad) and reviewed a couple of lines didn't sound as natural. Thanks ♥ --- locales/es.json | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/locales/es.json b/locales/es.json index feaee67..be99e72 100644 --- a/locales/es.json +++ b/locales/es.json @@ -9,15 +9,15 @@ }, "first-time": { "title": "Comprador(a) primerizo(a)", - "description": "¿Es esta la primera vez que has comprado nabos?(Esta información afectará a tu patrón)", + "description": "¿Ha sido esta la primera vez que compras nabos?(Esta información afectará a tu patrón)", "yes": "Sí", "no": "No" }, "patterns": { "title": "Patrón anterior", "description": "¿Qué patrón describió el precio de los nabos la semana pasada?(Esta información afectará a tu patrón)", - "pattern": "Pattern", - "all": "All patterns", + "pattern": "Patrón", + "all": "Todos los patrones", "decreasing": "Decreciente", "fluctuating": "Fluctuante", "unknown": "No lo sé", @@ -25,7 +25,7 @@ "small-spike": "Pico moderado" }, "prices": { - "description": "¿Cuál fue el precio más alto que alcanzaron los nabos en tu isla durante la semana? (Si esta es tu primera vez comprando nabos, este campo se desactivará)", + "description": "¿Cuál fue el precio más alto que alcanzaron los nabos en tu isla durante la semana? (Si esta ha sido tu primera vez comprando nabos, este campo se desactivará)", "open": { "am": "AM - De 8:00 a 11:59", "pm": "PM - De 12:00 a 10:00" @@ -75,6 +75,6 @@ "support": "Para asistencia, comentarios y contribuciones, no dudes en pasarte por Github.", "contributors-text": "¡Ah! ¡Y no nos olvidemos de todos los que han puesto su granito de arena hasta ahora!", "contributors": "Contribuidores", - "language": "Language" + "language": "Idioma" } } From cc5311cc27131cf63cb3d4d44e2260436e11dc2a Mon Sep 17 00:00:00 2001 From: KeruWolf <63780753+KeruWolf@users.noreply.github.com> Date: Sun, 19 Apr 2020 17:33:40 +0200 Subject: [PATCH 67/70] Add Spanish to language selection MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Hi! Could Spanish be added to the language selection option? Thanks ♥ --- js/translations.js | 1 + 1 file changed, 1 insertion(+) diff --git a/js/translations.js b/js/translations.js index d2658dc..6809506 100644 --- a/js/translations.js +++ b/js/translations.js @@ -16,6 +16,7 @@ i18next const languages = [ ['de', 'Deutsch'], ['en', 'English'], + ['es-ES', 'Español'], ['fr', 'Français'], ['it', 'Italiano'], ['ja', '日本語'], From baa9e8188bc23d63619c173958b22908575149cd Mon Sep 17 00:00:00 2001 From: Dmitrii <63938599+captaincurls@users.noreply.github.com> Date: Mon, 20 Apr 2020 01:23:21 +0900 Subject: [PATCH 68/70] Update translations.js --- js/translations.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/js/translations.js b/js/translations.js index 47e6ed9..8b0391c 100644 --- a/js/translations.js +++ b/js/translations.js @@ -16,11 +16,9 @@ i18next const languages = [ ['de', 'Deutsch'], ['en', 'English'], - ['fr', 'Français'], ['it', 'Italiano'], ['ru', 'Русский'], ['ja', '日本語'], - ['pt-BR', 'Português'], ['zh-CN', '简体中文'], ['zh-TW', '繁體中文'] ], From 5094cc4a66a81f5da05669653e95fe9c706c74f8 Mon Sep 17 00:00:00 2001 From: Mike Bryant Date: Sun, 19 Apr 2020 17:24:57 +0100 Subject: [PATCH 69/70] fix: Fix json format for es localisation --- locales/es.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/locales/es.json b/locales/es.json index be99e72..4538693 100644 --- a/locales/es.json +++ b/locales/es.json @@ -1,4 +1,4 @@ - +{ "general": { "daisy-mae": "Juliana" }, From c663792f38e9005285dcd25dde9d28ebdbdda949 Mon Sep 17 00:00:00 2001 From: Dmitrii <63938599+captaincurls@users.noreply.github.com> Date: Mon, 20 Apr 2020 01:53:41 +0900 Subject: [PATCH 70/70] Update ru.json I'm so sorry I noticed a typo in the beginning right after the site went live :( --- locales/ru.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/locales/ru.json b/locales/ru.json index 8d3849d..ce67a7e 100644 --- a/locales/ru.json +++ b/locales/ru.json @@ -5,7 +5,7 @@ "welcome": { "salutation": "Добрый день! Добро пожаловать в приложение Препсказатель на Вашем Нукофоне.", "description": "Это приложение позволяет Вам ежедневно отслеживать стоимость репы на Вашем острове. Будьте внимательны, Вам придется вводить ее вручную!", - "conclusion": "После этого приложение Препсказатель как по волшебству/b> предскажет стоимость репы в Вашем магазине на этой неделе." + "conclusion": "После этого Препсказатель как по волшебству предскажет стоимость репы в Вашем магазине на этой неделе." }, "first-time": { "title": "Новичок рынка репы", @@ -74,7 +74,7 @@ "thanks": "Если бы Ninji не смог разузнать, как Тимми и Томми определяют стоимость репы, данного приложения могло бы и не быть!", "support": "Поддержать нас, прокомментировать, а также внести свой вклад Вы можете на Github", "contributors-text": "Точно! Нельзя забывать тех, кто уже помог проекту!", - "contributors": "Вклад внесли:", + "contributors": "Вклад внесли", "language": "Язык" } }