//Reusable Fields const getSellFields = function () { let fields = [] for (var i = 2; i < 14; i++) { fields.push($("#sell_" + i)[0]) } return fields } const getFirstBuyRadios = function () { return [ $("#first-time-radio-no")[0], $("#first-time-radio-yes")[0] ]; } const getPreviousPatternRadios = function () { return [ $("#pattern-radio-unknown")[0], $("#pattern-radio-fluctuating")[0], $("#pattern-radio-small-spike")[0], $("#pattern-radio-large-spike")[0], $("#pattern-radio-decreasing")[0] ]; } const getCheckedRadio = function (radio_array) { return radio_array.find(radio => radio.checked === true).value; } const checkRadioByValue = function (radio_array, value) { if (value === null) { return; } value = value.toString(); radio_array.find(radio => radio.value == value).checked = true; } const sell_inputs = getSellFields() const buy_input = $("#buy") const first_buy_radios = getFirstBuyRadios() const previous_pattern_radios = getPreviousPatternRadios() //Functions const fillFields = function (prices, first_buy, previous_pattern) { checkRadioByValue(first_buy_radios, first_buy); checkRadioByValue(previous_pattern_radios, previous_pattern); buy_input.focus(); buy_input.val(prices[0] || '') buy_input.blur(); const sell_prices = prices.slice(2) sell_prices.forEach((price, index) => { if (!price) { return } else { const element = $("#sell_" + (index + 2)); element.focus(); element.val(price); element.blur(); } }) } const initialize = function () { try { const previous = getPrevious(); const first_buy = previous[0]; const previous_pattern = previous[1]; const prices = previous[2]; if (prices === null) { fillFields([], first_buy, previous_pattern) } else { fillFields(prices, first_buy, previous_pattern) } $(document).trigger("input"); } catch (e) { console.error(e); } $("#reset").on("click", function () { sell_inputs.forEach(input => input.value = '') fillFields([], false, -1) update() }) } const updateLocalStorage = function (prices, first_buy, previous_pattern) { try { if (prices.length !== 14) throw "The data array needs exactly 14 elements to be valid" localStorage.setItem("sell_prices", JSON.stringify(prices)) localStorage.setItem("first_buy", JSON.stringify(first_buy)); localStorage.setItem("previous_pattern", JSON.stringify(previous_pattern)); } catch (e) { console.error(e) } } const isEmpty = function (arr) { const filtered = arr.filter(value => value !== null && value !== '' && !isNaN(value)) return filtered.length == 0 } const getFirstBuyStateFromQuery = function (param) { try { const params = new URLSearchParams(window.location.search.substr(1)); const firstbuy_str = params.get(param); if (firstbuy_str == null) { return null; } firstbuy = null; if (firstbuy_str == "1" || firstbuy_str == "yes" || firstbuy_str == "true") { firstbuy = true; } else if (firstbuy_str == "0" || firstbuy_str == "no" || firstbuy_str == "false") { firstbuy = false; } return firstbuy; } catch (e) { return null; } } const getFirstBuyStateFromLocalstorage = function () { return JSON.parse(localStorage.getItem('first_buy')) } const getPreviousPatternStateFromLocalstorage = function () { return JSON.parse(localStorage.getItem('previous_pattern')) } const getPreviousPatternStateFromQuery = function (param) { try { const params = new URLSearchParams(window.location.search.substr(1)); const pattern_str = params.get(param); if (pattern_str == null) { return null; } if (pattern_str == "0" || pattern_str == "fluctuating") { pattern = 0; } else if (pattern_str == "1" || pattern_str == "large-spike") { pattern = 1; } else if (pattern_str == "2" || pattern_str == "decreasing") { pattern = 2; } else if (pattern_str == "3" || pattern_str == "small-spike") { pattern = 3; } else { pattern = -1; } return pattern; } catch (e) { return null; } } const getPricesFromLocalstorage = function () { try { const sell_prices = JSON.parse(localStorage.getItem("sell_prices")); if (!Array.isArray(sell_prices) || sell_prices.length !== 14) { return null; } return sell_prices; } catch (e) { return null; } }; const getPricesFromQuery = function (param) { try { const params = new URLSearchParams(window.location.search.substr(1)); const sell_prices = params.get(param).split(".").map((x) => parseInt(x, 10)); if (!Array.isArray(sell_prices)) { return null; } // Parse the array which is formatted like: [price, M-AM, M-PM, T-AM, T-PM, W-AM, W-PM, Th-AM, Th-PM, F-AM, F-PM, S-AM, S-PM, Su-AM, Su-PM] // due to the format of local storage we need to double up the price at the start of the array. sell_prices.unshift(sell_prices[0]); // This allows us to fill out the missing fields at the end of the array for (let i = sell_prices.length; i < 14; i++) { sell_prices.push(0); } return sell_prices; } catch (e) { return null; } }; const getPreviousFromQuery = function () { /* Check if valid prices are entered. Exit immediately if not. */ prices = getPricesFromQuery("prices"); if (prices == null) { return null; } console.log("Using data from query."); window.populated_from_query = true; return [ getFirstBuyStateFromQuery("first"), getPreviousPatternStateFromQuery("pattern"), prices ]; }; const getPreviousFromLocalstorage = function () { return [ getFirstBuyStateFromLocalstorage(), getPreviousPatternStateFromLocalstorage(), getPricesFromLocalstorage() ]; }; /** * Gets previous values. First tries to parse parameters, * if none of them match then it looks in local storage. * @return {[first time, previous pattern, prices]} */ const getPrevious = function () { return getPreviousFromQuery() || getPreviousFromLocalstorage(); }; const getSellPrices = function () { //Checks all sell inputs and returns an array with their values return res = sell_inputs.map(function (input) { return parseInt(input.value || ''); }) } const calculateOutput = function (data, first_buy, previous_pattern) { if (isEmpty(data)) { $("#output").html(""); return; } let output_possibilities = ""; let analyzed_possibilities = analyze_possibilities(data, first_buy, previous_pattern); for (let poss of analyzed_possibilities) { var out_line = "" + poss.pattern_description + "" out_line += `${Number.isFinite(poss.probability) ? ((poss.probability * 100).toPrecision(3) + '%') : '—'}`; for (let day of poss.prices.slice(1)) { if (day.min !== day.max) { out_line += `${day.min} to ${day.max}`; } else { out_line += `${day.min}`; } } out_line += `${poss.weekGuaranteedMinimum}${poss.weekMax}`; output_possibilities += out_line } $("#output").html(output_possibilities) update_chart(data, analyzed_possibilities); } const update = function () { const sell_prices = getSellPrices(); const buy_price = parseInt(buy_input.val()); const first_buy = getCheckedRadio(first_buy_radios) == 'true'; const previous_pattern = parseInt(getCheckedRadio(previous_pattern_radios)); buy_input[0].disabled = first_buy; buy_input[0].placeholder = first_buy ? '—' : '...' const prices = [buy_price, buy_price, ...sell_prices]; if (!window.populated_from_query) { updateLocalStorage(prices, first_buy, previous_pattern); } calculateOutput(prices, first_buy, previous_pattern); } $(document).ready(initialize); $(document).on("input", update); $('input[type = radio]').on("change", update);