diff options
-rw-r--r-- | UI/TrajanPro-Bold.otf | bin | 0 -> 65848 bytes | |||
-rw-r--r-- | UI/TrajanPro-Bold.otf.import | 34 | ||||
-rw-r--r-- | UI/TrajanPro-Regular.ttf | bin | 0 -> 519584 bytes | |||
-rw-r--r-- | UI/TrajanPro-Regular.ttf.import | 34 | ||||
-rw-r--r-- | UI/darksouls.tres | 8 | ||||
-rw-r--r-- | libs/Big.gd | 902 | ||||
-rw-r--r-- | libs/Big_LICENSE | 21 | ||||
-rw-r--r-- | scenes/stockticker/Stock Ticker.tscn | 92 | ||||
-rw-r--r-- | scenes/stockticker/buy_n_sell.gd | 25 | ||||
-rw-r--r-- | scenes/stockticker/fishe/gar.png | bin | 0 -> 64014 bytes | |||
-rw-r--r-- | scenes/stockticker/fishe/gar.png.import | 34 | ||||
-rw-r--r-- | scenes/stockticker/stonks.gd | 161 |
12 files changed, 1233 insertions, 78 deletions
diff --git a/UI/TrajanPro-Bold.otf b/UI/TrajanPro-Bold.otf Binary files differnew file mode 100644 index 0000000..c27f189 --- /dev/null +++ b/UI/TrajanPro-Bold.otf diff --git a/UI/TrajanPro-Bold.otf.import b/UI/TrajanPro-Bold.otf.import new file mode 100644 index 0000000..107ee7b --- /dev/null +++ b/UI/TrajanPro-Bold.otf.import @@ -0,0 +1,34 @@ +[remap] + +importer="font_data_dynamic" +type="FontFile" +uid="uid://qcnw15tljlaw" +path="res://.godot/imported/TrajanPro-Bold.otf-645b7b6de76ea350aa9387e1c544393e.fontdata" + +[deps] + +source_file="res://UI/TrajanPro-Bold.otf" +dest_files=["res://.godot/imported/TrajanPro-Bold.otf-645b7b6de76ea350aa9387e1c544393e.fontdata"] + +[params] + +Rendering=null +antialiasing=1 +generate_mipmaps=false +disable_embedded_bitmaps=true +multichannel_signed_distance_field=false +msdf_pixel_range=8 +msdf_size=48 +allow_system_fallback=true +force_autohinter=false +hinting=1 +subpixel_positioning=1 +oversampling=0.0 +Fallbacks=null +fallbacks=[] +Compress=null +compress=true +preload=[] +language_support={} +script_support={} +opentype_features={} diff --git a/UI/TrajanPro-Regular.ttf b/UI/TrajanPro-Regular.ttf Binary files differnew file mode 100644 index 0000000..b53d6c0 --- /dev/null +++ b/UI/TrajanPro-Regular.ttf diff --git a/UI/TrajanPro-Regular.ttf.import b/UI/TrajanPro-Regular.ttf.import new file mode 100644 index 0000000..7d08576 --- /dev/null +++ b/UI/TrajanPro-Regular.ttf.import @@ -0,0 +1,34 @@ +[remap] + +importer="font_data_dynamic" +type="FontFile" +uid="uid://cqbvonuv72tu4" +path="res://.godot/imported/TrajanPro-Regular.ttf-92a4010dc4d10444d1337e1e88061245.fontdata" + +[deps] + +source_file="res://UI/TrajanPro-Regular.ttf" +dest_files=["res://.godot/imported/TrajanPro-Regular.ttf-92a4010dc4d10444d1337e1e88061245.fontdata"] + +[params] + +Rendering=null +antialiasing=1 +generate_mipmaps=false +disable_embedded_bitmaps=true +multichannel_signed_distance_field=false +msdf_pixel_range=8 +msdf_size=48 +allow_system_fallback=true +force_autohinter=false +hinting=1 +subpixel_positioning=1 +oversampling=0.0 +Fallbacks=null +fallbacks=[] +Compress=null +compress=true +preload=[] +language_support={} +script_support={} +opentype_features={} diff --git a/UI/darksouls.tres b/UI/darksouls.tres new file mode 100644 index 0000000..f12f77c --- /dev/null +++ b/UI/darksouls.tres @@ -0,0 +1,8 @@ +[gd_resource type="Theme" load_steps=2 format=3 uid="uid://duy8w6dc8ebi3"] + +[ext_resource type="FontFile" uid="uid://cqbvonuv72tu4" path="res://UI/TrajanPro-Regular.ttf" id="1_fpdu3"] + +[resource] +Label/colors/font_color = Color(1, 0.75, 0, 0.780392) +Label/font_sizes/font_size = 126 +Label/fonts/font = ExtResource("1_fpdu3") diff --git a/libs/Big.gd b/libs/Big.gd new file mode 100644 index 0000000..747bae3 --- /dev/null +++ b/libs/Big.gd @@ -0,0 +1,902 @@ +class_name Big +extends RefCounted +## Big number class for use in idle / incremental games and other games that needs very large numbers +## +## Can format large numbers using a variety of notation methods:[br] +## AA notation like AA, AB, AC etc.[br] +## Metric symbol notation k, m, G, T etc.[br] +## Metric name notation kilo, mega, giga, tera etc.[br] +## Long names like octo-vigin-tillion or millia-nongen-quin-vigin-tillion (based on work by Landon Curt Noll)[br] +## Scientic notation like 13e37 or 42e42[br] +## Long strings like 4200000000 or 13370000000000000000000000000000[br][br] +## Please note that this class has limited precision and does not fully support negative exponents[br] + +## Big Number Mantissa +var mantissa: float +## Big Number Exponent +var exponent: int + +## Metric Symbol Suffixes +const suffixes_metric_symbol: Dictionary = { + "0": "", + "1": "k", + "2": "M", + "3": "G", + "4": "T", + "5": "P", + "6": "E", + "7": "Z", + "8": "Y", + "9": "R", + "10": "Q", +} +## Metric Name Suffixes +const suffixes_metric_name: Dictionary = { + "0": "", + "1": "kilo", + "2": "mega", + "3": "giga", + "4": "tera", + "5": "peta", + "6": "exa", + "7": "zetta", + "8": "yotta", + "9": "ronna", + "10": "quetta", +} + +# HACK: This dictionary is inefficient, along with toAA(). +# Replace with better, ideally utilizing alphabet_aa system +## AA Suffixes +## @deprecated +static var suffixes_aa: Dictionary = { + "0": "", + "1": "k", + "2": "m", + "3": "b", + "4": "t", + "5": "aa", + "6": "ab", + "7": "ac", + "8": "ad", + "9": "ae", + "10": "af", + "11": "ag", + "12": "ah", + "13": "ai", + "14": "aj", + "15": "ak", + "16": "al", + "17": "am", + "18": "an", + "19": "ao", + "20": "ap", + "21": "aq", + "22": "ar", + "23": "as", + "24": "at", + "25": "au", + "26": "av", + "27": "aw", + "28": "ax", + "29": "ay", + "30": "az", + "31": "ba", + "32": "bb", + "33": "bc", + "34": "bd", + "35": "be", + "36": "bf", + "37": "bg", + "38": "bh", + "39": "bi", + "40": "bj", + "41": "bk", + "42": "bl", + "43": "bm", + "44": "bn", + "45": "bo", + "46": "bp", + "47": "bq", + "48": "br", + "49": "bs", + "50": "bt", + "51": "bu", + "52": "bv", + "53": "bw", + "54": "bx", + "55": "by", + "56": "bz", + "57": "ca" +} + +## AA Alphabet +const alphabet_aa: Array[String] = [ + "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", + "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z" +] + +## Latin Ones Prefixes +const latin_ones: Array[String] = [ + "", "un", "duo", "tre", "quattuor", "quin", "sex", "septen", "octo", "novem" +] +## Latin Tens Prefixes +const latin_tens: Array[String] = [ + "", "dec", "vigin", "trigin", "quadragin", "quinquagin", "sexagin", "septuagin", "octogin", "nonagin" +] +## Latin Hundreds Prefixes +const latin_hundreds: Array[String] = [ + "", "cen", "duocen", "trecen", "quadringen", "quingen", "sescen", "septingen", "octingen", "nongen" +] +## Latin Special Prefixes +const latin_special: Array[String] = [ + "", "mi", "bi", "tri", "quadri", "quin", "sex", "sept", "oct", "non" +] + +## Various options to control the string presentation of Big Numbers +static var options = { + "dynamic_decimals": false, + "dynamic_numbers": 4, + "small_decimals": 3, + "thousand_decimals": 1, + "big_decimals": 1, + "scientific_decimals": 3, + "logarithmic_decimals": 4, + "thousand_separator": ",", + "decimal_separator": ".", + "suffix_separator": "", + "reading_separator": "", + "thousand_name": "thousand" +} + +## Maximum Big Number Mantissa +const MANTISSA_MAX: float = 1209600.0 +## Big Number Mantissa floating-point precision +const MANTISSA_PRECISION: float = 0.0000001 + +## int (signed 64-bit) minimum value +const INT_MIN: int = -9223372036854775808 +## int (signed 64-bit) maximum value +const INT_MAX: int = 9223372036854775807 + +func _init(m: Variant = 1.0, e: int = 0) -> void: + if m is Big: + mantissa = m.mantissa + exponent = m.exponent + elif typeof(m) == TYPE_STRING: + var scientific: PackedStringArray = m.split("e") + mantissa = float(scientific[0]) + exponent = int(scientific[1]) if scientific.size() > 1 else 0 + else: + if typeof(m) != TYPE_INT and typeof(m) != TYPE_FLOAT: + printerr("Big Error: Unknown data type passed as a mantissa!") + mantissa = m + exponent = e + Big._sizeCheck(mantissa) + Big.normalize(self) + +## Verifies (or converts) an argument into a Big number +static func _typeCheck(n) -> Big: + if n is Big: + return n + var result := Big.new(n) + return result + +## Warns if Big number's mantissa exceeds max +static func _sizeCheck(m: float) -> void: + if m > MANTISSA_MAX: + printerr("Big Error: Mantissa \"" + str(m) + "\" exceeds MANTISSA_MAX. Use exponent or scientific notation") + + +## [url=https://en.wikipedia.org/wiki/Normalized_number]Normalize[/url] a Big number +static func normalize(big: Big) -> void: + # Store sign if negative + var is_negative := false + if big.mantissa < 0: + is_negative = true + big.mantissa *= -1 + + if big.mantissa < 1.0 or big.mantissa >= 10.0: + var diff: int = floor(log10(big.mantissa)) + if diff > -10 and diff < 248: + var div = 10.0 ** diff + if div > MANTISSA_PRECISION: + big.mantissa /= div + big.exponent += diff + while big.exponent < 0: + big.mantissa *= 0.1 + big.exponent += 1 + while big.mantissa >= 10.0: + big.mantissa *= 0.1 + big.exponent += 1 + if big.mantissa == 0: + big.mantissa = 0.0 + big.exponent = 0 + big.mantissa = snapped(big.mantissa, MANTISSA_PRECISION) + + # Return sign if negative + if (is_negative): + big.mantissa *= -1 + + +## Returns the absolute value of a number in Big format +static func absolute(x) -> Big: + var result := Big.new(x) + result.mantissa = abs(result.mantissa) + return result + + +## Adds two numbers and returns the Big number result [br][br] +static func add(x, y) -> Big: + x = Big._typeCheck(x) + y = Big._typeCheck(y) + var result := Big.new(x) + + var exp_diff: float = y.exponent - x.exponent + + if exp_diff < 248.0: + var scaled_mantissa: float = y.mantissa * 10 ** exp_diff + result.mantissa = x.mantissa + scaled_mantissa + elif x.isLessThan(y): # When difference between values is too big, discard the smaller number + result.mantissa = y.mantissa + result.exponent = y.exponent + Big.normalize(result) + return result + + +## Subtracts two numbers and returns the Big number result +static func subtract(x, y) -> Big: + var negated_y := Big.new(-y.mantissa, y.exponent) + return add(negated_y, x) + + +## Multiplies two numbers and returns the Big number result +static func multiply(x, y) -> Big: + x = Big._typeCheck(x) + y = Big._typeCheck(y) + var result := Big.new() + + var new_exponent: int = y.exponent + x.exponent + var new_mantissa: float = y.mantissa * x.mantissa + while new_mantissa >= 10.0: + new_mantissa /= 10.0 + new_exponent += 1 + result.mantissa = new_mantissa + result.exponent = new_exponent + Big.normalize(result) + return result + + +## Divides two numbers and returns the Big number result +static func divide(x, y) -> Big: + x = Big._typeCheck(x) + y = Big._typeCheck(y) + var result := Big.new(x) + + if y.mantissa > -MANTISSA_PRECISION and y.mantissa < MANTISSA_PRECISION: + printerr("Big Error: Divide by zero or less than " + str(MANTISSA_PRECISION)) + return x + var new_exponent = x.exponent - y.exponent + var new_mantissa = x.mantissa / y.mantissa + while new_mantissa > 0.0 and new_mantissa < 1.0: + new_mantissa *= 10.0 + new_exponent -= 1 + result.mantissa = new_mantissa + result.exponent = new_exponent + Big.normalize(result) + return result + + +## Raises a Big number to the nth power and returns the Big number result +static func power(x: Big, y) -> Big: + var result := Big.new(x) + if typeof(y) == TYPE_INT: + if y <= 0: + if y < 0: + printerr("Big Error: Negative exponents are not supported!") + result.mantissa = 1.0 + result.exponent = 0 + return result + + var y_mantissa: float = 1.0 + var y_exponent: int = 0 + + while y > 1: + Big.normalize(result) + if y % 2 == 0: + result.exponent *= 2 + result.mantissa **= 2 + y = y / 2 + else: + y_mantissa = result.mantissa * y_mantissa + y_exponent = result.exponent + y_exponent + result.exponent *= 2 + result.mantissa **= 2 + y = (y - 1) / 2 + + result.exponent = y_exponent + result.exponent + result.mantissa = y_mantissa * result.mantissa + Big.normalize(result) + return result + elif typeof(y) == TYPE_FLOAT: + if result.mantissa == 0: + return result + + # fast track + var temp: float = result.exponent * y + var newMantissa = result.mantissa ** y + if (round(y) == y + and temp <= INT_MAX + and temp >= INT_MIN + and is_finite(temp) + ): + if is_finite(newMantissa): + result.mantissa = newMantissa + result.exponent = int(temp) + Big.normalize(result) + return result + + # a bit slower, still supports floats + var newExponent: int = int(temp) + var residue: float = temp - newExponent + newMantissa = 10 ** (y * Big.log10(result.mantissa) + residue) + if newMantissa != INF and newMantissa != -INF: + result.mantissa = newMantissa + result.exponent = newExponent + Big.normalize(result) + return result + + if round(y) != y: + printerr("Big Error: Power function does not support large floats, use integers!") + + return power(x, int(y)) + else: + printerr("Big Error: Unknown/unsupported data type passed as an exponent in power function!") + return x + + +## Square Roots a given Big number and returns the Big number result +static func root(x: Big) -> Big: + var result := Big.new(x) + + if result.exponent % 2 == 0: + result.mantissa = sqrt(result.mantissa) + @warning_ignore("integer_division") + result.exponent = result.exponent / 2 + else: + result.mantissa = sqrt(result.mantissa * 10) + @warning_ignore("integer_division") + result.exponent = (result.exponent - 1) / 2 + Big.normalize(result) + return result + + +## Modulos a number and returns the Big number result +static func modulo(x, y) -> Big: + var result := Big.new(x.mantissa, x.exponent) + y = Big._typeCheck(y) + var big = { "mantissa": x.mantissa, "exponent": x.exponent } + Big.divide(result, y) + Big.roundDown(result) + Big.multiply(result, y) + Big.subtract(result, big) + result.mantissa = abs(result.mantissa) + return result + + +## Rounds down a Big number +static func roundDown(x: Big) -> Big: + if x.exponent == 0: + x.mantissa = floor(x.mantissa) + else: + var precision := 1.0 + for i in range(min(8, x.exponent)): + precision /= 10.0 + if precision < MANTISSA_PRECISION: + precision = MANTISSA_PRECISION + x.mantissa = floor(x.mantissa / precision) * precision + return x + + +## Equivalent of [code]min(Big, Big)[/code] +static func minValue(m, n) -> Big: + m = Big._typeCheck(m) + if m.isLessThan(n): + return m + else: + return n + + +## Equivalent of [code]max(Big, Big)[/code] +static func maxValue(m, n) -> Big: + m = Big._typeCheck(m) + if m.isGreaterThan(n): + return m + else: + return n + + +## Equivalent of [code]Big + n[/code] +func plus(n) -> Big: + return Big.add(self, n) + + +## Equivalent of [code]Big += n[/code] +func plusEquals(n) -> Big: + var new_value = Big.add(self, n) + mantissa = new_value.mantissa + exponent = new_value.exponent + return self + +## Equivalent of [code]Big - n[/code] +func minus(n) -> Big: + return Big.subtract(self, n) + + +## Equivalent of [code]Big -= n[/code] +func minusEquals(n) -> Big: + var new_value: Big = Big.subtract(self, n) + mantissa = new_value.mantissa + exponent = new_value.exponent + return self + + +## Equivalent of [code]Big * n[/code] +func times(n) -> Big: + return Big.multiply(self, n) + + +## Equivalent of [code]Big *= n[/code] +func timesEquals(n) -> Big: + var new_value: Big = Big.multiply(self, n) + mantissa = new_value.mantissa + exponent = new_value.exponent + return self + + +## Equivalent of [code]Big / n[/code] +func dividedBy(n) -> Big: + return Big.divide(self, n) + + +## Equivalent of [code]Big /= n[/code] +func dividedByEquals(n) -> Big: + var new_value: Big = Big.divide(self, n) + mantissa = new_value.mantissa + exponent = new_value.exponent + return self + + +## Equivalent of [code]Big % n[/code] +func mod(n) -> Big: + return Big.modulo(self, n) + + +## Equivalent of [code]Big %= n[/code] +func modEquals(n) -> Big: + var new_value := Big.modulo(self, n) + mantissa = new_value.mantissa + exponent = new_value.exponent + return self + + +## Equivalent of [code]Big ** n[/code] +func toThePowerOf(n) -> Big: + return Big.power(self, n) + + +## Equivalent of [code]Big **= n[/code] +func toThePowerOfEquals(n) -> Big: + var new_value: Big = Big.power(self, n) + mantissa = new_value.mantissa + exponent = new_value.exponent + return self + + +## Equivalent of [code]sqrt(Big)[/code] +func squareRoot() -> Big: + var new_value := Big.root(self) + mantissa = new_value.mantissa + exponent = new_value.exponent + return self + + +## Equivalent of [code]Big == n[/code] +func isEqualTo(n) -> bool: + n = Big._typeCheck(n) + Big.normalize(n) + return n.exponent == exponent and is_equal_approx(n.mantissa, mantissa) + + +## Equivalent of [code]Big > n[/code] +func isGreaterThan(n) -> bool: + return !isLessThanOrEqualTo(n) + + +## Equivalent of [code]Big >== n[/code] +func isGreaterThanOrEqualTo(n) -> bool: + return !isLessThan(n) + + +## Equivalent of [code]Big < n[/code] +func isLessThan(n) -> bool: + n = Big._typeCheck(n) + Big.normalize(n) + if (mantissa == 0 + and (n.mantissa > MANTISSA_PRECISION or mantissa < MANTISSA_PRECISION) + and n.mantissa == 0 + ): + return false + if exponent < n.exponent: + if exponent == n.exponent - 1 and mantissa > 10*n.mantissa: + return false #9*10^3 > 0.1*10^4 + return true + elif exponent == n.exponent: + if mantissa < n.mantissa: + return true + return false + else: + if exponent == n.exponent + 1 and mantissa * 10 < n.mantissa: + return true + return false + + +## Equivalent of [code]Big <= n[/code] +func isLessThanOrEqualTo(n) -> bool: + n = Big._typeCheck(n) + Big.normalize(n) + if isLessThan(n): + return true + if n.exponent == exponent and is_equal_approx(n.mantissa, mantissa): + return true + return false + + +static func log10(x) -> float: + return log(x) * 0.4342944819032518 + + +func absLog10() -> float: + return exponent + Big.log10(abs(mantissa)) + + +func ln() -> float: + return 2.302585092994045 * logN(10) + + +func logN(base) -> float: + return (2.302585092994046 / log(base)) * (exponent + Big.log10(mantissa)) + + +func pow10(value: int) -> void: + mantissa = 10 ** (value % 1) + exponent = int(value) + + +## Sets the Thousand name option +static func setThousandName(name: String) -> void: + options.thousand_name = name + + +## Sets the Thousand Separator option +static func setThousandSeparator(separator: String) -> void: + options.thousand_separator = separator + + +## Sets the Decimal Separator option +static func setDecimalSeparator(separator: String) -> void: + options.decimal_separator = separator + + +## Sets the Suffix Separator option +static func setSuffixSeparator(separator: String) -> void: + options.suffix_separator = separator + + +## Sets the Reading Separator option +static func setReadingSeparator(separator: String) -> void: + options.reading_separator = separator + + +## Sets the Dynamic Decimals option +static func setDynamicDecimals(d: bool) -> void: + options.dynamic_decimals = d + + +## Sets the Dynamic numbers digits option +static func setDynamicNumbers(d: int) -> void: + options.dynamic_numbers = d + + +## Sets the small decimal digits option +static func setSmallDecimals(d: int) -> void: + options.small_decimals = d + + +## Sets the thousand decimal digits option +static func setThousandDecimals(d: int) -> void: + options.thousand_decimals = d + + +## Sets the big decimal digits option +static func setBigDecimals(d: int) -> void: + options.big_decimals = d + + +## Sets the scientific notation decimal digits option +static func setScientificDecimals(d: int) -> void: + options.scientific_decimals = d + + +## Sets the logarithmic notation decimal digits option +static func setLogarithmicDecimals(d: int) -> void: + options.logarithmic_decimals = d + + +## Converts the Big Number into a string +func toString() -> String: + var mantissa_decimals := 0 + if str(mantissa).find(".") >= 0: + mantissa_decimals = str(mantissa).split(".")[1].length() + if mantissa_decimals > exponent: + if exponent < 248: + return str(mantissa * 10 ** exponent) + else: + return toPlainScientific() + else: + var mantissa_string := str(mantissa).replace(".", "") + for _i in range(exponent-mantissa_decimals): + mantissa_string += "0" + return mantissa_string + + +## Converts the Big Number into a string (in plain Scientific format) +func toPlainScientific() -> String: + return str(mantissa) + "e" + str(exponent) + + +## Converts the Big Number into a string (in Scientific format) +func toScientific(no_decimals_on_small_values = false, force_decimals = false) -> String: + if exponent < 3: + var decimal_increments: float = 1 / (10 ** options.scientific_decimals / 10) + var value := str(snappedf(mantissa * 10 ** exponent, decimal_increments)) + var split := value.split(".") + if no_decimals_on_small_values: + return split[0] + if split.size() > 1: + for i in range(options.logarithmic_decimals): + if split[1].length() < options.scientific_decimals: + split[1] += "0" + return split[0] + options.decimal_separator + split[1].substr(0,min(options.scientific_decimals, options.dynamic_numbers - split[0].length() if options.dynamic_decimals else options.scientific_decimals)) + else: + return value + else: + var split := str(mantissa).split(".") + if split.size() == 1: + split.append("") + if force_decimals: + for i in range(options.scientific_decimals): + if split[1].length() < options.scientific_decimals: + split[1] += "0" + return split[0] + options.decimal_separator + split[1].substr(0,min(options.scientific_decimals, options.dynamic_numbers-1 - str(exponent).length() if options.dynamic_decimals else options.scientific_decimals)) + "e" + str(exponent) + + +## Converts the Big Number into a string (in Logarithmic format) +func toLogarithmic(no_decimals_on_small_values = false) -> String: + var decimal_increments: float = 1 / (10 ** options.logarithmic_decimals / 10) + if exponent < 3: + var value := str(snappedf(mantissa * 10 ** exponent, decimal_increments)) + var split := value.split(".") + if no_decimals_on_small_values: + return split[0] + if split.size() > 1: + for i in range(options.logarithmic_decimals): + if split[1].length() < options.logarithmic_decimals: + split[1] += "0" + return split[0] + options.decimal_separator + split[1].substr(0,min(options.logarithmic_decimals, options.dynamic_numbers - split[0].length() if options.dynamic_decimals else options.logarithmic_decimals)) + else: + return value + var dec := str(snappedf(abs(log(mantissa) / log(10) * 10), decimal_increments)) + dec = dec.replace(".", "") + for i in range(options.logarithmic_decimals): + if dec.length() < options.logarithmic_decimals: + dec += "0" + var formated_exponent := formatExponent(exponent) + dec = dec.substr(0, min(options.logarithmic_decimals, options.dynamic_numbers - formated_exponent.length() if options.dynamic_decimals else options.logarithmic_decimals)) + return "e" + formated_exponent + options.decimal_separator + dec + + +## Formats an exponent for string format +func formatExponent(value) -> String: + if value < 1000: + return str(value) + var string := str(value) + var string_mod := string.length() % 3 + var output := "" + for i in range(0, string.length()): + if i != 0 and i % 3 == string_mod: + output += options.thousand_separator + output += string[i] + return output + + +## Converts the Big Number into a float +func toFloat() -> float: + return snappedf(float(str(mantissa) + "e" + str(exponent)),0.01) + + +func toPrefix(no_decimals_on_small_values = false, use_thousand_symbol=true, force_decimals=true, scientic_prefix=false) -> String: + var number: float = mantissa + if not scientic_prefix: + var hundreds = 1 + for _i in range(exponent % 3): + hundreds *= 10 + number *= hundreds + + var split := str(number).split(".") + if split.size() == 1: + split.append("") + if force_decimals: + var max_decimals = max(max(options.small_decimals, options.thousand_decimals), options.big_decimals) + for i in range(max_decimals): + if split[1].length() < max_decimals: + split[1] += "0" + + if no_decimals_on_small_values and exponent < 3: + return split[0] + elif exponent < 3: + if options.small_decimals == 0 or split[1] == "": + return split[0] + else: + return split[0] + options.decimal_separator + split[1].substr(0,min(options.small_decimals, options.dynamic_numbers - split[0].length() if options.dynamic_decimals else options.small_decimals)) + elif exponent < 6: + if options.thousand_decimals == 0 or (split[1] == "" and use_thousand_symbol): + return split[0] + else: + if use_thousand_symbol: # when the prefix is supposed to be using with a K for thousand + for i in range(3): + if split[1].length() < 3: + split[1] += "0" + return split[0] + options.decimal_separator + split[1].substr(0,min(3, options.dynamic_numbers - split[0].length() if options.dynamic_decimals else 3)) + else: + for i in range(3): + if split[1].length() < 3: + split[1] += "0" + return split[0] + options.thousand_separator + split[1].substr(0,3) + else: + if options.big_decimals == 0 or split[1] == "": + return split[0] + else: + return split[0] + options.decimal_separator + split[1].substr(0,min(options.big_decimals, options.dynamic_numbers - split[0].length() if options.dynamic_decimals else options.big_decimals)) + + +func _latinPower(european_system) -> int: + if european_system: + @warning_ignore("integer_division") + return int(exponent / 3) / 2 + @warning_ignore("integer_division") + return int(exponent / 3) - 1 + + +func _latinPrefix(european_system) -> String: + var ones := _latinPower(european_system) % 10 + var tens := int(_latinPower(european_system) / floor(10)) % 10 + @warning_ignore("integer_division") + var hundreds := int(_latinPower(european_system) / 100) % 10 + @warning_ignore("integer_division") + var millias := int(_latinPower(european_system) / 1000) % 10 + + var prefix := "" + if _latinPower(european_system) < 10: + prefix = latin_special[ones] + options.reading_separator + latin_tens[tens] + options.reading_separator + latin_hundreds[hundreds] + else: + prefix = latin_hundreds[hundreds] + options.reading_separator + latin_ones[ones] + options.reading_separator + latin_tens[tens] + + for _i in range(millias): + prefix = "millia" + options.reading_separator + prefix + + return prefix.lstrip(options.reading_separator).rstrip(options.reading_separator) + + +func _tillionOrIllion(european_system) -> String: + if exponent < 6: + return "" + var powerKilo := _latinPower(european_system) % 1000 + if powerKilo < 5 and powerKilo > 0 and _latinPower(european_system) < 1000: + return "" + if ( + powerKilo >= 7 and powerKilo <= 10 + or int(powerKilo / floor(10)) % 10 == 1 + ): + return "i" + return "ti" + + +func _llionOrLliard(european_system) -> String: + if exponent < 6: + return "" + if int(exponent/floor(3)) % 2 == 1 and european_system: + return "lliard" + return "llion" + + +func getLongName(european_system = false, prefix="") -> String: + if exponent < 6: + return "" + else: + return prefix + _latinPrefix(european_system) + options.reading_separator + _tillionOrIllion(european_system) + _llionOrLliard(european_system) + + +## Converts the Big Number into a string (in American Long Name format) +func toAmericanName(no_decimals_on_small_values = false) -> String: + return toLongName(no_decimals_on_small_values, false) + + +## Converts the Big Number into a string (in European Long Name format) +func toEuropeanName(no_decimals_on_small_values = false) -> String: + return toLongName(no_decimals_on_small_values, true) + + +## Converts the Big Number into a string (in Latin Long Name format) +func toLongName(no_decimals_on_small_values = false, european_system = false) -> String: + if exponent < 6: + if exponent > 2: + return toPrefix(no_decimals_on_small_values) + options.suffix_separator + options.thousand_name + else: + return toPrefix(no_decimals_on_small_values) + + var suffix = _latinPrefix(european_system) + options.reading_separator + _tillionOrIllion(european_system) + _llionOrLliard(european_system) + + return toPrefix(no_decimals_on_small_values) + options.suffix_separator + suffix + + +## Converts the Big Number into a string (in Metric Symbols format) +func toMetricSymbol(no_decimals_on_small_values = false) -> String: + @warning_ignore("integer_division") + var target := int(exponent / 3) + + if not suffixes_metric_symbol.has(str(target)): + return toScientific() + else: + return toPrefix(no_decimals_on_small_values) + options.suffix_separator + suffixes_metric_symbol[str(target)] + + +## Converts the Big Number into a string (in Metric Name format) +func toMetricName(no_decimals_on_small_values = false) -> String: + @warning_ignore("integer_division") + var target := int(exponent / 3) + + if not suffixes_metric_name.has(str(target)): + return toScientific() + else: + return toPrefix(no_decimals_on_small_values) + options.suffix_separator + suffixes_metric_name[str(target)] + +# HACK: This function is wasteful and requires remaking. +# It adds new entries to the dictionary suffixes_aa instead of generating the suffixes +# like the other functions +## Converts the Big Number into a string (in AA format) +## @deprecated +func toAA(no_decimals_on_small_values = false, use_thousand_symbol = true, force_decimals=false) -> String: + @warning_ignore("integer_division") + var target := int(exponent / 3) + var aa_index := str(target) + var suffix := "" + + if not suffixes_aa.has(aa_index): + var offset := target + 22 + var base := alphabet_aa.size() + while offset > 0: + offset -= 1 + var digit := offset % base + suffix = alphabet_aa[digit] + suffix + offset /= base + suffixes_aa[aa_index] = suffix + else: + suffix = suffixes_aa[aa_index] + + if not use_thousand_symbol and target == 1: + suffix = "" + + var prefix = toPrefix(no_decimals_on_small_values, use_thousand_symbol, force_decimals) + + return prefix + options.suffix_separator + suffix diff --git a/libs/Big_LICENSE b/libs/Big_LICENSE new file mode 100644 index 0000000..b953d07 --- /dev/null +++ b/libs/Big_LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2020 ChronoDK + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/scenes/stockticker/Stock Ticker.tscn b/scenes/stockticker/Stock Ticker.tscn index 9352ef8..f3abfc7 100644 --- a/scenes/stockticker/Stock Ticker.tscn +++ b/scenes/stockticker/Stock Ticker.tscn @@ -1,20 +1,21 @@ -[gd_scene load_steps=9 format=3 uid="uid://g2veoq55y14i"] +[gd_scene load_steps=10 format=3 uid="uid://g2veoq55y14i"] [ext_resource type="Texture2D" uid="uid://voruypgyi77e" path="res://scenes/stockticker/UI-Background-Colour.png" id="1_wbfee"] [ext_resource type="Script" path="res://scenes/stockticker/stonks.gd" id="2_pan4m"] [ext_resource type="Theme" uid="uid://ve18rbkeiwti" path="res://UI/text.tres" id="3_dv3dr"] -[ext_resource type="Script" path="res://scenes/stockticker/buy_n_sell.gd" id="4_l8sru"] [ext_resource type="Texture2D" uid="uid://vie3nmimge1t" path="res://scenes/stockticker/BuyButton.png" id="5_mpf30"] [ext_resource type="Texture2D" uid="uid://dvidbk3clx6dn" path="res://scenes/stockticker/BuyButtonPressed.png" id="6_styy2"] [ext_resource type="Texture2D" uid="uid://dw8wpd47me7wu" path="res://scenes/stockticker/SellButton.png" id="7_h6hir"] [ext_resource type="Texture2D" uid="uid://b773rtpy6rtx5" path="res://scenes/stockticker/SellButtonPressed.png" id="8_essj7"] +[ext_resource type="Theme" uid="uid://duy8w6dc8ebi3" path="res://UI/darksouls.tres" id="8_yqn4n"] +[ext_resource type="Texture2D" uid="uid://dpp7abs35p6i5" path="res://scenes/stockticker/fishe/gar.png" id="9_bv8iw"] [node name="Node2D" type="Node2D"] [node name="Background" type="Sprite2D" parent="."] modulate = Color(0.796078, 0.796078, 0.796078, 1) -position = Vector2(576.25, 323.75) -scale = Vector2(1153.5, 648.5) +position = Vector2(639.75, 359.75) +scale = Vector2(1280.5, 720.5) texture = ExtResource("1_wbfee") [node name="Timer" type="Timer" parent="."] @@ -23,7 +24,15 @@ autostart = true [node name="Stonks" type="Node2D" parent="."] script = ExtResource("2_pan4m") -[node name="Sprite2D" type="Sprite2D" parent="Stonks"] +[node name="SellButton" type="TextureButton" parent="Stonks"] +offset_left = 439.0 +offset_top = 565.0 +offset_right = 794.0 +offset_bottom = 694.0 +texture_normal = ExtResource("7_h6hir") +texture_pressed = ExtResource("8_essj7") + +[node name="StonkWindow" type="Sprite2D" parent="Stonks"] position = Vector2(582, 205) scale = Vector2(1062.25, 337) texture = ExtResource("1_wbfee") @@ -79,44 +88,67 @@ text = "0" horizontal_alignment = 1 [node name="Stonks" type="Line2D" parent="Stonks"] +width = 2.0 +default_color = Color(1, 0, 0, 1) [node name="Price Label" type="Label" parent="Stonks"] -offset_left = 387.0 -offset_top = 387.0 -offset_right = 1112.0 -offset_bottom = 452.0 +offset_left = 26.0 +offset_top = 476.0 +offset_right = 751.0 +offset_bottom = 541.0 theme = ExtResource("3_dv3dr") text = "Price: $" -[node name="BuyNSell" type="Node2D" parent="."] -script = ExtResource("4_l8sru") - -[node name="BuyButton" type="TextureButton" parent="BuyNSell"] +[node name="BuyButton" type="TextureButton" parent="Stonks"] offset_left = 54.0 -offset_top = 475.0 +offset_top = 563.0 offset_right = 409.0 -offset_bottom = 604.0 +offset_bottom = 692.0 texture_normal = ExtResource("5_mpf30") texture_pressed = ExtResource("6_styy2") -[node name="SellButton" type="TextureButton" parent="BuyNSell"] -offset_left = 441.0 -offset_top = 477.0 -offset_right = 796.0 -offset_bottom = 606.0 -texture_normal = ExtResource("7_h6hir") -texture_pressed = ExtResource("8_essj7") - -[node name="Shares Held Label" type="Label" parent="BuyNSell"] -offset_left = 6.0 -offset_top = 390.0 -offset_right = 336.0 -offset_bottom = 455.0 +[node name="Shares Held Label" type="Label" parent="Stonks"] +offset_left = 29.0 +offset_top = 388.0 +offset_right = 359.0 +offset_bottom = 453.0 theme = ExtResource("3_dv3dr") text = "Shares Held:" +[node name="DarkSoulsTextBox" type="Sprite2D" parent="Stonks"] +visible = false +self_modulate = Color(0, 0, 0, 0.721569) +position = Vector2(639.937, 355.875) +scale = Vector2(1279.88, 260.25) +texture = ExtResource("1_wbfee") + +[node name="DarkSoulsLabel" type="Label" parent="Stonks"] +visible = false +offset_left = 64.0 +offset_top = 258.0 +offset_right = 1209.0 +offset_bottom = 450.0 +theme = ExtResource("8_yqn4n") +text = "Stock Bankrupt" +horizontal_alignment = 1 + +[node name="Sprite2D" type="Sprite2D" parent="."] +position = Vector2(1036, 555) +scale = Vector2(0.671875, 0.622) +texture = ExtResource("9_bv8iw") + +[node name="Label" type="Label" parent="."] +offset_left = 823.0 +offset_top = 588.0 +offset_right = 1082.0 +offset_bottom = 785.0 +theme = ExtResource("3_dv3dr") +theme_override_colors/font_color = Color(0, 0, 0, 1) +theme_override_font_sizes/font_size = 82 +text = "GAR" + [connection signal="timeout" from="Timer" to="Stonks" method="_on_timer_timeout"] -[connection signal="button_up" from="BuyNSell/BuyButton" to="BuyNSell" method="_on_buy_button_button_up"] -[connection signal="button_up" from="BuyNSell/SellButton" to="BuyNSell" method="_on_sell_button_button_up"] +[connection signal="button_up" from="Stonks/SellButton" to="Stonks" method="_on_sell_button_button_up"] +[connection signal="button_up" from="Stonks/BuyButton" to="Stonks" method="_on_buy_button_button_up"] diff --git a/scenes/stockticker/buy_n_sell.gd b/scenes/stockticker/buy_n_sell.gd deleted file mode 100644 index be0e777..0000000 --- a/scenes/stockticker/buy_n_sell.gd +++ /dev/null @@ -1,25 +0,0 @@ -extends Node2D - -var stonks = 0 - -# Called when the node enters the scene tree for the first time. -func _ready() -> void: - var label = $"Shares Held Label" - label.text = "Shares\nHeld:%d" % stonks - -# Called every frame. 'delta' is the elapsed time since the previous frame. -func _process(delta: float) -> void: - pass - - -func _on_buy_button_button_up() -> void: - if stonks < 100: - stonks += 1 - var label = $"Shares Held Label" - label.text = "Shares\nHeld:%d" % stonks - -func _on_sell_button_button_up() -> void: - if stonks > 0: - stonks -= 1 - var label = $"Shares Held Label" - label.text = "Shares\nHeld:%d" % stonks diff --git a/scenes/stockticker/fishe/gar.png b/scenes/stockticker/fishe/gar.png Binary files differnew file mode 100644 index 0000000..658fa5e --- /dev/null +++ b/scenes/stockticker/fishe/gar.png diff --git a/scenes/stockticker/fishe/gar.png.import b/scenes/stockticker/fishe/gar.png.import new file mode 100644 index 0000000..428ca58 --- /dev/null +++ b/scenes/stockticker/fishe/gar.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://dpp7abs35p6i5" +path="res://.godot/imported/gar.png-de723b6b5530a2f3aa7ae68d1173ed75.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://scenes/stockticker/fishe/gar.png" +dest_files=["res://.godot/imported/gar.png-de723b6b5530a2f3aa7ae68d1173ed75.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/scenes/stockticker/stonks.gd b/scenes/stockticker/stonks.gd index fefc340..508fb82 100644 --- a/scenes/stockticker/stonks.gd +++ b/scenes/stockticker/stonks.gd @@ -1,52 +1,167 @@ extends Node2D +const MAX_PRICES = 15 + +const Y_START = 60 +const Y_END = 356 +const X_START = 50 +const X_END = 1000 + +var price_label +var shares_label +var top_label +var mid_label +var bottom_label +var darksouls_background: Sprite2D +var darksouls_text: Label + var price_history = [] -var max_prices = 15 -var max_up_multiplier = 2 -var max_down_multiplier = 2 +var base_pos_mult = 0.5 # no size limit +var base_neg_mult = 0.5 # probably keep this below 1 + +var hype_mult = 1.0 +var hype_decr = 0.1 +var hype_inc = 0.05 +var panic_mult = 1.0 +var panic_decr = 0.1 +var panic_inc = 0.01 + var bailout_counter = 0 var bailout_time = 1 -var bailout_price = 5 -var start_val = 5 +var bailout_price = Big.new(5) +var start_val = Big.new(5) var prev_price = start_val +var shares = 0 + +func handle_bailout(new_price: Big) -> Big: + if bailout_counter < bailout_time: + new_price = Big.new(0) + bailout_counter += 1 + else: + darksouls_background.visible = true + darksouls_text.visible = true + darksouls_text.text = "Bailed Out" + new_price = bailout_price + bailout_counter = 0 + bailout_time *= 2 + panic_mult = 1.0 + hype_mult = 1.0 + + return new_price + +func draw_stonks(minval: Big, maxval: Big) -> void: + var stonks: Line2D = $Stonks + stonks.clear_points() + + var index = 0 + var x_delta = (X_END - X_START)/float(len(price_history)-1) + var y_range = Big.new(Y_END - Y_START) + var price_range = maxval.minus(minval) + for price: Big in price_history: + var x_pos = x_delta * index + X_START + var y_pos = Y_END + if price_range.isGreaterThan(0.001): + var price_ratio = (price.minus(minval)).dividedBy(price_range) + y_pos = float(Big.new(Y_END).minus(y_range.times(price_ratio)).toString()) + var pos = Vector2(x_pos, y_pos) + stonks.add_point(pos, index) + index += 1 + +func get_min_price() -> Big: + var minval = Big.new(-1) + for price in price_history: + if price.isLessThan(minval) or minval.isLessThan(0): + minval = price + return minval + +func get_max_price() -> Big: + var maxval = Big.new(-1) + for price in price_history: + if price.isGreaterThan(maxval): + maxval = price + return maxval + # Called when the node enters the scene tree for the first time. func _ready() -> void: - print(start_val) - var label = $"Price Label" - label.text = "Price:\n$%f" % start_val + price_label = $"Price Label" + shares_label = $"Shares Held Label" + top_label = $Top + mid_label = $Middle + bottom_label = $Bottom + darksouls_background = $DarkSoulsTextBox + darksouls_text = $DarkSoulsLabel + + price_label.text = "Price:\n$%s" % start_val.toString() price_history.push_front(start_val) + + shares_label.text = "Shares\nHeld:%d" % shares # Called every frame. 'delta' is the elapsed time since the previous frame. -func _process(delta: float) -> void: +func _process(_delta: float) -> void: pass func _on_timer_timeout() -> void: + darksouls_background.visible = false + darksouls_text.visible = false var new_price = prev_price - if prev_price <= 0: - if bailout_counter < bailout_time: - new_price = 0 - bailout_counter += 1 - else: - new_price = bailout_price - bailout_counter = 0 + hype_mult -= hype_decr + if hype_mult < 1: hype_mult = 1.0 + + panic_mult -= panic_decr + if panic_mult < 1: panic_mult = 1.0 + + if prev_price.isLessThanOrEqualTo(0): + new_price = handle_bailout(new_price) elif randf() < 0.5: - new_price += 1 * max_up_multiplier * randf() + var mult = Big.new(1).plus(Big.new(base_pos_mult * hype_mult * randf())) + new_price = new_price.times(mult) else: - new_price -= 1 * max_down_multiplier * randf() + var mult = Big.new(1).minus(Big.new(base_neg_mult * panic_mult * randf())) + new_price = new_price.times(mult) - if new_price < 0: new_price = 0 + if new_price.isLessThan(1) or new_price.toString()[0] == '-': + print(bailout_counter) + print(new_price.toString()) + if bailout_counter == 0: + darksouls_background.visible = true + darksouls_text.visible = true + darksouls_text.text = "Stock Bankrupt" + new_price = Big.new(0) + shares = 0 + shares_label.text = "Shares\nHeld:%d" % shares - if len(price_history) >= max_prices: + if len(price_history) >= MAX_PRICES: price_history.pop_front() price_history.push_back(new_price) prev_price = new_price - var label = $"Price Label" - label.text = "Price:\n$%f" % new_price + price_label.text = "Price:\n$%s" % new_price.toString() + + var min_price = get_min_price() + var max_price = get_max_price() + var mean_price = min_price.plus(max_price).dividedBy(2) - print(new_price) + top_label.text = "%s" % max_price.toScientific() + mid_label.text = "%s" % mean_price.toScientific() + bottom_label.text = "%s" % min_price.toScientific() + + draw_stonks(min_price, max_price) + + +func _on_buy_button_button_up() -> void: + if shares < 100 and prev_price.isGreaterThan(0): + shares += 1 + shares_label.text = "Shares\nHeld:%d" % shares + hype_mult += hype_inc + + +func _on_sell_button_button_up() -> void: + if shares > 0: + shares -= 1 + shares_label.text = "Shares\nHeld:%d" % shares + panic_mult += panic_inc |