You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
ac-nh-turnip-prices/js/predictions.js

617 lines
18 KiB
JavaScript

// The reverse-engineered code is not perfectly accurate, especially as it's not
// 32-bit ARM floating point. So, be tolerant of slightly unexpected inputs
const FUDGE_FACTOR = 5;
const PATTERN = {
FLUCTUATING: 0,
LARGE_SPIKE: 1,
DECREASING: 2,
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,
[PATTERN.LARGE_SPIKE]: 0.30,
[PATTERN.DECREASING]: 0.15,
[PATTERN.SMALL_SPIKE]: 0.35,
},
[PATTERN.LARGE_SPIKE]: {
[PATTERN.FLUCTUATING]: 0.50,
[PATTERN.LARGE_SPIKE]: 0.05,
[PATTERN.DECREASING]: 0.20,
[PATTERN.SMALL_SPIKE]: 0.25,
},
[PATTERN.DECREASING]: {
[PATTERN.FLUCTUATING]: 0.25,
[PATTERN.LARGE_SPIKE]: 0.45,
[PATTERN.DECREASING]: 0.05,
[PATTERN.SMALL_SPIKE]: 0.25,
},
[PATTERN.SMALL_SPIKE]: {
[PATTERN.FLUCTUATING]: 0.45,
[PATTERN.LARGE_SPIKE]: 0.25,
[PATTERN.DECREASING]: 0.15,
[PATTERN.SMALL_SPIKE]: 0.15,
},
};
const RATE_MULTIPLIER = 10000;
function intceil(val) {
return Math.trunc(val + 0.99999);
}
function minimum_rate_from_given_and_base(given_price, buy_price) {
return RATE_MULTIPLIER * (given_price - 0.99999) / buy_price;
}
function maximum_rate_from_given_and_base(given_price, buy_price) {
return RATE_MULTIPLIER * (given_price + 0.00001) / buy_price;
}
function get_price(rate, basePrice) {
return intceil(rate * basePrice / RATE_MULTIPLIER);
}
/*
* This corresponds to the code:
* for (int i = start; i < start + length; i++)
* {
* sellPrices[work++] =
* intceil(randfloat(rate_min / RATE_MULTIPLIER, rate_max / RATE_MULTIPLIER) * basePrice);
* }
*
* Would modify the predicted_prices array.
* If the given_prices won't match, returns false, otherwise returns true
*/
function generate_individual_random_price(
given_prices, predicted_prices, start, length, rate_min, rate_max) {
rate_min *= RATE_MULTIPLIER;
rate_max *= RATE_MULTIPLIER;
const buy_price = given_prices[0];
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);
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;
}
min_pred = given_prices[i];
max_pred = given_prices[i];
}
predicted_prices.push({
min: min_pred,
max: max_pred,
});
}
return true;
}
/*
* This corresponds to the code:
* rate = randfloat(start_rate_min, start_rate_max);
* for (int i = start; i < start + length; i++)
* {
* sellPrices[work++] = intceil(rate * basePrice);
* rate -= randfloat(rate_decay_min, rate_decay_max);
* }
*
* Would modify the predicted_prices array.
* If the given_prices won't match, returns false, otherwise returns true
*/
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;
rate_decay_min *= RATE_MULTIPLIER;
rate_decay_max *= RATE_MULTIPLIER;
const buy_price = given_prices[0];
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);
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;
}
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);
}
min_pred = given_prices[i];
max_pred = given_prices[i];
}
predicted_prices.push({
min: min_pred,
max: max_pred,
});
rate_min -= rate_decay_max;
rate_max -= rate_decay_min;
}
return true;
}
/*
* This corresponds to the code:
* rate = randfloat(rate_min, rate_max);
* sellPrices[work++] = intceil(randfloat(rate_min, rate) * basePrice) - 1;
* sellPrices[work++] = intceil(rate * basePrice);
* sellPrices[work++] = intceil(randfloat(rate_min, rate) * basePrice) - 1;
*
* Would modify the predicted_prices array.
* If the given_prices won't match, returns false, otherwise returns true
*/
function generate_peak_price(
given_prices, predicted_prices, start, rate_min, rate_max) {
rate_min *= RATE_MULTIPLIER;
rate_max *= RATE_MULTIPLIER;
const buy_price = given_prices[0];
// 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[start] > 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];
}
predicted_prices.push({
min: min_pred,
max: max_pred,
});
// Main spike 2
min_pred = predicted_prices[start].min;
max_pred = intceil(2.0 * 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];
}
predicted_prices.push({
min: min_pred,
max: max_pred,
});
// Main spike 3
min_pred = intceil(1.4 * 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];
}
predicted_prices.push({
min: min_pred,
max: max_pred,
});
return true;
}
function*
generate_pattern_0_with_lengths(
given_prices, high_phase_1_len, dec_phase_1_len, high_phase_2_len,
dec_phase_2_len, high_phase_3_len) {
Squashed commit of the following: commit efffda8fc2ae9ebf5df051c33159fc4334075470 Author: Trevor Welch <welch.trevor@yahoo.com> Date: Wed Apr 8 19:03:49 2020 -0400 Fixed Reset Button Fingers crossed on last commit commit ff6b739533c20e1eb3f4942b06def9fdfcf58548 Author: Trevor Welch <welch.trevor@yahoo.com> Date: Wed Apr 8 18:49:54 2020 -0400 Copy Update + Radio Button Fix Changed the copy under "First-Time Buyer" and made the selected radio button a solid fill rather than only coloring the text. commit 95887a68b671dcf231e4e7aea6710bfe4e2eae29 Author: Trevor Welch <welch.trevor@yahoo.com> Date: Wed Apr 8 18:31:18 2020 -0400 Removed a Console Log commit 84f1ef8b96730818903aaa0e12ab12be642f8bd1 Author: Trevor Welch <welch.trevor@yahoo.com> Date: Wed Apr 8 18:27:03 2020 -0400 Added Probabilities Chart will now also display % chance of that pattern. commit d047d7749ca2809165068fe3f787c83ffba8b45e Author: Trevor Welch <welch.trevor@yahoo.com> Date: Wed Apr 8 18:08:35 2020 -0400 Added "First Buy" and "Previous Pattern" All CSS needed for these fields have also been included, as well as some Javascript updated to reflect the new radios. commit 95b60e1458df72c86cf91c2017cb8208e0829d9b Merge: 1d6046b be09f8e Author: Trevor Welch <welch.trevor@yahoo.com> Date: Wed Apr 8 13:51:53 2020 -0400 Merge branch 'front-end' commit be09f8e6085dccf90683c819a3deec44852a54b1 Author: Trevor Welch <welch.trevor@yahoo.com> Date: Wed Apr 8 13:51:43 2020 -0400 Requested changes This commit adds changes as requested in https://github.com/mikebryant/ac-nh-turnip-prices/pull/34 commit 1d6046bfe283e6a779e2e2f49edd12b6fdf128bd Author: Trevor Welch <welch.trevor@yahoo.com> Date: Wed Apr 8 02:34:12 2020 -0400 typo commit a414b8fdc22aaad82265d502601c0d2a67050f5d Author: Trevor Welch <welch.trevor@yahoo.com> Date: Wed Apr 8 02:22:36 2020 -0400 Update scripts.js commit fbc3878d831e0f9abeb2de40337dedb8ee20f794 Merge: d521944 3cad0d4 Author: Trevor Welch <welch.trevor@yahoo.com> Date: Wed Apr 8 02:18:57 2020 -0400 Merge branch 'master' of https://github.com/Trevor-Welch/ac-nh-turnip-prices commit d521944eae82eeb0644b13ffa75a23ec3d2f52ef Author: Trevor Welch <welch.trevor@yahoo.com> Date: Wed Apr 8 02:15:37 2020 -0400 Massive UI Rework This commit completely changes the UI of the app, giving it a more Animal Crossing touch and make it feel like an app on the Nook Phone. commit 3cad0d4f2a127ba46e946a9b0bebfc1cfb7001f2 Author: Trevor Welch <welch.trevor@yahoo.com> Date: Mon Apr 6 20:43:38 2020 -0400 Refactored scripts.js Scripts.JS was very hard to read initially. This commity cleans things up, abstracts functions, and makes it a bit more easier to read.
4 years ago
/*
// PATTERN 0: high, decreasing, high, decreasing, high
work = 2;
// high phase 1
for (int i = 0; i < hiPhaseLen1; i++)
{
sellPrices[work++] = intceil(randfloat(0.9, 1.4) * basePrice);
}
// decreasing phase 1
rate = randfloat(0.8, 0.6);
for (int i = 0; i < decPhaseLen1; i++)
{
sellPrices[work++] = intceil(rate * basePrice);
rate -= 0.04;
rate -= randfloat(0, 0.06);
}
// high phase 2
for (int i = 0; i < (hiPhaseLen2and3 - hiPhaseLen3); i++)
{
sellPrices[work++] = intceil(randfloat(0.9, 1.4) * basePrice);
}
// decreasing phase 2
rate = randfloat(0.8, 0.6);
for (int i = 0; i < decPhaseLen2; i++)
{
sellPrices[work++] = intceil(rate * basePrice);
rate -= 0.04;
rate -= randfloat(0, 0.06);
}
// high phase 3
for (int i = 0; i < hiPhaseLen3; i++)
{
sellPrices[work++] = intceil(randfloat(0.9, 1.4) * basePrice);
}
*/
const buy_price = given_prices[0];
const predicted_prices = [
{
min: buy_price,
max: buy_price,
},
{
min: buy_price,
max: buy_price,
},
];
// High Phase 1
if (!generate_individual_random_price(
given_prices, predicted_prices, 2, high_phase_1_len, 0.9, 1.4)) {
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)) {
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)) {
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)) {
return;
}
// High Phase 3
if (2 + high_phase_1_len + dec_phase_1_len + high_phase_2_len + dec_phase_2_len + high_phase_3_len != 14) {
throw new Error("Phase lengths don't add up");
}
const prev_length = 2 + high_phase_1_len + dec_phase_1_len +
high_phase_2_len + dec_phase_2_len;
if (!generate_individual_random_price(
given_prices, predicted_prices, prev_length, 14 - prev_length, 0.9,
1.4)) {
return;
}
yield {
pattern_description: "Fluctuating",
pattern_number: 0,
prices: predicted_prices
};
}
function* generate_pattern_0(given_prices) {
/*
decPhaseLen1 = randbool() ? 3 : 2;
decPhaseLen2 = 5 - decPhaseLen1;
hiPhaseLen1 = randint(0, 6);
hiPhaseLen2and3 = 7 - hiPhaseLen1;
hiPhaseLen3 = randint(0, hiPhaseLen2and3 - 1);
*/
for (var dec_phase_1_len = 2; dec_phase_1_len < 4; dec_phase_1_len++) {
for (var high_phase_1_len = 0; high_phase_1_len < 7; high_phase_1_len++) {
for (var high_phase_3_len = 0; high_phase_3_len < (7 - high_phase_1_len - 1 + 1); high_phase_3_len++) {
yield* 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);
}
}
}
}
function* generate_pattern_1_with_peak(given_prices, peak_start) {
/*
// PATTERN 1: decreasing middle, high spike, random low
peakStart = randint(3, 9);
rate = randfloat(0.9, 0.85);
for (work = 2; work < peakStart; work++)
{
sellPrices[work] = intceil(rate * basePrice);
rate -= 0.03;
rate -= randfloat(0, 0.02);
}
sellPrices[work++] = intceil(randfloat(0.9, 1.4) * basePrice);
sellPrices[work++] = intceil(randfloat(1.4, 2.0) * basePrice);
sellPrices[work++] = intceil(randfloat(2.0, 6.0) * basePrice);
sellPrices[work++] = intceil(randfloat(1.4, 2.0) * basePrice);
sellPrices[work++] = intceil(randfloat(0.9, 1.4) * basePrice);
for (; work < 14; work++)
{
sellPrices[work] = intceil(randfloat(0.4, 0.9) * basePrice);
}
*/
const buy_price = given_prices[0];
const predicted_prices = [
{
min: buy_price,
max: buy_price,
},
{
min: buy_price,
max: buy_price,
},
];
if (!generate_decreasing_random_price(
given_prices, predicted_prices, 2, peak_start - 2, 0.85, 0.9, 0.03,
0.05)) {
return;
}
// Now each day is independent of next
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])) {
return;
}
}
yield {
pattern_description: "Large spike",
pattern_number: 1,
prices: predicted_prices
};
}
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);
}
}
function* generate_pattern_2(given_prices) {
/*
// PATTERN 2: consistently decreasing
rate = 0.9;
rate -= randfloat(0, 0.05);
for (work = 2; work < 14; work++)
{
sellPrices[work] = intceil(rate * basePrice);
rate -= 0.03;
rate -= randfloat(0, 0.02);
}
break;
*/
const buy_price = given_prices[0];
const predicted_prices = [
{
min: buy_price,
max: buy_price,
},
{
min: buy_price,
max: buy_price,
},
];
if (!generate_decreasing_random_price(
given_prices, predicted_prices, 2, 14 - 2, 0.85, 0.9, 0.03, 0.05)) {
return;
}
yield {
pattern_description: "Decreasing",
pattern_number: 2,
prices: predicted_prices
};
}
function* generate_pattern_3_with_peak(given_prices, peak_start) {
/*
// PATTERN 3: decreasing, spike, decreasing
peakStart = randint(2, 9);
// decreasing phase before the peak
rate = randfloat(0.9, 0.4);
for (work = 2; work < peakStart; work++)
{
sellPrices[work] = intceil(rate * basePrice);
rate -= 0.03;
rate -= randfloat(0, 0.02);
}
sellPrices[work++] = intceil(randfloat(0.9, 1.4) * (float)basePrice);
sellPrices[work++] = intceil(randfloat(0.9, 1.4) * basePrice);
rate = randfloat(1.4, 2.0);
sellPrices[work++] = intceil(randfloat(1.4, rate) * basePrice) - 1;
sellPrices[work++] = intceil(rate * basePrice);
sellPrices[work++] = intceil(randfloat(1.4, rate) * basePrice) - 1;
// decreasing phase after the peak
if (work < 14)
{
rate = randfloat(0.9, 0.4);
for (; work < 14; work++)
{
sellPrices[work] = intceil(rate * basePrice);
rate -= 0.03;
rate -= randfloat(0, 0.02);
}
}
*/
const buy_price = given_prices[0];
const predicted_prices = [
{
min: buy_price,
max: buy_price,
},
{
min: buy_price,
max: buy_price,
},
];
let probability = 1;
if (!generate_decreasing_random_price(
given_prices, predicted_prices, 2, peak_start - 2, 0.4, 0.9, 0.03,
0.05)) {
return;
}
// The peak
if (!generate_individual_random_price(
given_prices, predicted_prices, peak_start, 2, 0.9, 1.4)) {
return;
}
if (!generate_peak_price(
given_prices, predicted_prices, peak_start + 2, 1.4, 2.0)) {
return;
}
Squashed commit of the following: commit efffda8fc2ae9ebf5df051c33159fc4334075470 Author: Trevor Welch <welch.trevor@yahoo.com> Date: Wed Apr 8 19:03:49 2020 -0400 Fixed Reset Button Fingers crossed on last commit commit ff6b739533c20e1eb3f4942b06def9fdfcf58548 Author: Trevor Welch <welch.trevor@yahoo.com> Date: Wed Apr 8 18:49:54 2020 -0400 Copy Update + Radio Button Fix Changed the copy under "First-Time Buyer" and made the selected radio button a solid fill rather than only coloring the text. commit 95887a68b671dcf231e4e7aea6710bfe4e2eae29 Author: Trevor Welch <welch.trevor@yahoo.com> Date: Wed Apr 8 18:31:18 2020 -0400 Removed a Console Log commit 84f1ef8b96730818903aaa0e12ab12be642f8bd1 Author: Trevor Welch <welch.trevor@yahoo.com> Date: Wed Apr 8 18:27:03 2020 -0400 Added Probabilities Chart will now also display % chance of that pattern. commit d047d7749ca2809165068fe3f787c83ffba8b45e Author: Trevor Welch <welch.trevor@yahoo.com> Date: Wed Apr 8 18:08:35 2020 -0400 Added "First Buy" and "Previous Pattern" All CSS needed for these fields have also been included, as well as some Javascript updated to reflect the new radios. commit 95b60e1458df72c86cf91c2017cb8208e0829d9b Merge: 1d6046b be09f8e Author: Trevor Welch <welch.trevor@yahoo.com> Date: Wed Apr 8 13:51:53 2020 -0400 Merge branch 'front-end' commit be09f8e6085dccf90683c819a3deec44852a54b1 Author: Trevor Welch <welch.trevor@yahoo.com> Date: Wed Apr 8 13:51:43 2020 -0400 Requested changes This commit adds changes as requested in https://github.com/mikebryant/ac-nh-turnip-prices/pull/34 commit 1d6046bfe283e6a779e2e2f49edd12b6fdf128bd Author: Trevor Welch <welch.trevor@yahoo.com> Date: Wed Apr 8 02:34:12 2020 -0400 typo commit a414b8fdc22aaad82265d502601c0d2a67050f5d Author: Trevor Welch <welch.trevor@yahoo.com> Date: Wed Apr 8 02:22:36 2020 -0400 Update scripts.js commit fbc3878d831e0f9abeb2de40337dedb8ee20f794 Merge: d521944 3cad0d4 Author: Trevor Welch <welch.trevor@yahoo.com> Date: Wed Apr 8 02:18:57 2020 -0400 Merge branch 'master' of https://github.com/Trevor-Welch/ac-nh-turnip-prices commit d521944eae82eeb0644b13ffa75a23ec3d2f52ef Author: Trevor Welch <welch.trevor@yahoo.com> Date: Wed Apr 8 02:15:37 2020 -0400 Massive UI Rework This commit completely changes the UI of the app, giving it a more Animal Crossing touch and make it feel like an app on the Nook Phone. commit 3cad0d4f2a127ba46e946a9b0bebfc1cfb7001f2 Author: Trevor Welch <welch.trevor@yahoo.com> Date: Mon Apr 6 20:43:38 2020 -0400 Refactored scripts.js Scripts.JS was very hard to read initially. This commity cleans things up, abstracts functions, and makes it a bit more easier to read.
4 years ago
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)) {
return;
}
}
yield {
pattern_description: "Small spike",
pattern_number: 3,
prices: predicted_prices
};
}
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);
}
}
function* generate_possibilities(sell_prices, first_buy) {
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);
}
}
} 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);
}
}
function row_probability(possibility, previous_pattern) {
return PROBABILITY_MATRIX[previous_pattern][possibility.pattern_number] / PATTERN_COUNTS[possibility.pattern_number];
}
4 years ago
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
}
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 = [];
for (let day of poss.prices.slice(2)) {
weekMins.push(day.min);
weekMaxes.push(day.max);
}
poss.weekGuaranteedMinimum = Math.max(...weekMins);
poss.weekMax = Math.max(...weekMaxes);
}
generated_possibilities.sort((a, b) => {
if (a.weekMax < b.weekMax) {
return 1;
} else if (a.weekMax > b.weekMax) {
return -1;
} else {
return 0;
}
});
global_min_max = [];
for (var day = 0; day < 14; day++) {
prices = {
min: 999,
max: 0,
}
for (let poss of generated_possibilities) {
if (poss.prices[day].min < prices.min) {
prices.min = poss.prices[day].min;
}
if (poss.prices[day].max > prices.max) {
prices.max = poss.prices[day].max;
}
}
global_min_max.push(prices);
}
generated_possibilities.unshift({
pattern_description: "All patterns",
pattern_number: 4,
prices: global_min_max,
weekGuaranteedMinimum: Math.min(...generated_possibilities.map(poss => poss.weekGuaranteedMinimum)),
weekMax: Math.max(...generated_possibilities.map(poss => poss.weekMax)),
});
return generated_possibilities;
}