summaryrefslogtreecommitdiff
path: root/technic/helpers.lua
diff options
context:
space:
mode:
Diffstat (limited to 'technic/helpers.lua')
-rw-r--r--technic/helpers.lua63
1 files changed, 48 insertions, 15 deletions
diff --git a/technic/helpers.lua b/technic/helpers.lua
index 5780f27..5963b68 100644
--- a/technic/helpers.lua
+++ b/technic/helpers.lua
@@ -1,23 +1,56 @@
-local digit_sep_esc
-do
- local sep = technic.config:get("digit_separator")
- sep = tonumber(sep) and string.char(sep) or sep or " "
- -- Escape for gsub
- for magic in ("().%+-*?[^$"):gmatch(".") do
- if sep == magic then
- sep = "%"..sep
+local constant_digit_count = technic.config:get("constant_digit_count")
+
+-- converts a number to a readable string with SI prefix, e.g. 10000 → "10 k",
+-- 15 → "15 ", 0.1501 → "150.1 m"
+-- a non-breaking space (U+a0) instead of a usual one is put after number
+-- The precision is 4 digits
+local prefixes = {[-8] = "y", [-7] = "z", [-6] = "a", [-5] = "f", [-4] = "p",
+ [-3] = "n", [-2] = "µ", [-1] = "m", [0] = "", [1] = "k", [2] = "M",
+ [3] = "G", [4] = "T", [5] = "P", [6] = "E", [7] = "Z", [8] = "Y"}
+function technic.pretty_num(num)
+ -- the small number added is due to floating point inaccuracy
+ local b = math.floor(math.log10(math.abs(num)) +0.000001)
+ local pref_i
+ if b ~= 0 then
+ -- b is decremented by 1 to avoid a single digit with many decimals,
+ -- e.g. instead of 1.021 MEU, 1021 kEU is shown
+ pref_i = math.floor((b - 1) / 3)
+ else
+ -- as special case, avoid showing e.g. 1100 mEU instead of 1.1 EU
+ pref_i = 0
+ end
+ if not prefixes[pref_i] then
+ -- This happens for 0, nan, inf, very big values, etc.
+ if num == 0 then
+ -- handle 0 explicilty to avoid showing "-0"
+ if not constant_digit_count then
+ return "0 "
+ end
+ -- gives 0.000
+ return string.format("%.3f ", 0)
end
+ return string.format("%.4g ", num)
end
- digit_sep_esc = sep
+
+ num = num * 10 ^ (-3 * pref_i)
+ if constant_digit_count then
+ local comma_digits_cnt = 3 - (b - 3 * pref_i)
+ return string.format("%." .. comma_digits_cnt .. "f %s",
+ num, prefixes[pref_i])
+ end
+ return string.format("%.4g %s", num, prefixes[pref_i])
end
+-- some unittests
+assert(technic.pretty_num(-0) == "0 ")
+assert(technic.pretty_num(0) == "0 ")
+assert(technic.pretty_num(1234) == "1234 ")
+assert(technic.pretty_num(123456789) == "123.5 M")
-function technic.pretty_num(num)
- local str, k = tostring(num), nil
- repeat
- str, k = str:gsub("^(-?%d+)(%d%d%d)", "%1"..digit_sep_esc.."%2")
- until k == 0
- return str
+
+-- used to display power values
+function technic.EU_string(num)
+ return technic.pretty_num(num) .. "EU"
end