Module:Weight table
From Space Station 14 Wiki
Module documentation
|
---|
View or edit this documentation • (about module documentation) |
Implements {{Weight table}}.
local p = {}
local getArgs = require('Module:Arguments').getArgs
local yesNo = require('Module:Yesno')
-- ==========================
local table_paths = {
["xeno triggers"] = "Module:Weight table/data/xeno triggers.json",
["xeno effects"] = "Module:Weight table/data/xeno effects.json",
}
-- ==========================
local tables = {}
-- ==========================
local function assert_not_nil(value, error_message)
if value == nil then
if error_message == nil then
error("value is nil")
else
error(error_message)
end
end
end
local function starts_with(str, substr)
return string.sub(str, 1, string.len(substr)) == substr
end
local function ends_with(str, substr)
local substr_length = string.len(substr)
return string.sub(str, string.len(str) - substr_length + 1, string.len(str)) == substr
end
local function starts_with_insensitive(str, substr)
return starts_with(string.lower(str), string.lower(substr))
end
local function ends_with_insensitive(str, substr)
return ends_with(string.lower(str), string.lower(substr))
end
local function table_filter(tbl, filterFn)
local out = {}
for k, v in pairs(tbl) do
if filterFn(v, k, tbl) then out[k] = v end
end
return out
end
local function num_table_reduce(tbl, reduceFn, initial_value)
local out = initial_value
for i, v in ipairs(tbl) do
out = reduceFn(out, v, i, tbl)
end
return out
end
local function table_find(tbl, findFn)
for k, v in pairs(tbl) do
if findFn(v, k, tbl) then return v end
end
end
local function table_contains(tbl, findFn)
return table_find(tbl, findFn) ~= nil
end
local function table_contains_value(tbl, value)
return table_find(tbl, function(iter_value)
return iter_value == value
end) ~= nil
end
local function table_find_key(tbl, findFn)
for k, v in pairs(tbl) do
if findFn(v, k, tbl) then return k end
end
end
local function table_find_index(tbl, findFn)
for i, v in ipairs(tbl) do
if findFn(v, i, tbl) then return i end
end
end
local function table_map(tbl, mapFn)
local res = {}
for k, v in pairs(tbl) do
table.insert(res, mapFn(v, k, tbl))
end
return res
end
local function numeric_table_length(t)
local count = 0
for _ in ipairs(t) do count = count + 1 end
return count
end
local function table_length(t)
local count = 0
for _ in pairs(t) do count = count + 1 end
return count
end
-- Sorts a table into a new table.
-- An alternative to cases such as when table.sort is not working,
-- like when trying to sort JSON tables (thanks fuckass lua).
function table_to_sorted(tbl, sortfn)
local keys = {}
for key, _ in pairs(tbl) do
table.insert(keys, key)
end
table.sort(keys, function(keyA, keyB) return sortfn(tbl[keyA], tbl[keyB]) end)
local t2 = {}
for _, key in ipairs(keys) do
table.insert(t2, tbl[key])
end
return t2
end
-- ==========================
local function find_weight_entry_by_weight_id_or_name(table, query)
local query_lc = string.lower(query)
for _, entry in ipairs(table) do
local id = entry.id
if string.lower(id) == query_lc then
return entry
end
local display = entry.display
if string.lower(display) == query_lc then
return entry
end
end
end
local function sort_by_weight_comparator(a, b)
assert_not_nil(a.weight, "failed to sort a weight table: encountered an entry without a 'weight' property")
assert_not_nil(b.weight, "failed to sort a weight table: encountered an entry without a 'weight' property")
return a.weight > b.weight;
end
-- ==========================
function p.main(frame)
local args = getArgs(frame)
local table_name = args[1]
assert_not_nil(table_name, "table not provided")
local percentage_round = args.percentage_round or 3
-- ============
local tbl = tables[table_name]
if tbl == nil then
local table_path = table_paths[table_name]
assert_not_nil(table_path, "unknown table '" .. table_name .. "'")
tbl = mw.loadJsonData(table_path)
tables[table_name] = tbl
tbl = table_to_sorted(tbl, sort_by_weight_comparator)
end
local total_weight = num_table_reduce(tbl, function(accum, value, i)
local weight = value.weight;
assert_not_nil("failed to calculate a total weight for a table '" ..
table_name .. "': encountered an entry without a 'weight' property (index " .. i .. ")")
return accum + weight
end, 0)
local tbl_el = mw.html.create("table")
:addClass("wikitable")
:addClass("weight-table")
-- local th = tbl_el:tag("th")
local header = tbl_el:tag("tr")
header:tag("th"):wikitext("Name")
header:tag("th"):wikitext("ID")
header:tag("th"):wikitext("Weight")
header:tag("th"):wikitext("Chance")
for i, entry in ipairs(tbl) do
local id = entry.id
assert_not_nil(id,
"failed to generate a weight table: encountered an entry without an 'id' property (index " .. i .. ")")
local name = entry.display
assert_not_nil(name,
"failed to generate a weight table: encountered an entry without an 'name' property (index " .. i .. ")")
local weight = entry.weight
assert_not_nil(weight,
"failed to generate a weight table: encountered an entry without an 'weight' property (index " .. i .. ")")
local percentage = weight / total_weight * 100
local percentage_rounded_str = string.format("%." .. percentage_round .. "f", percentage)
local was_percentage_rounded = tostring(percentage) ~= percentage_rounded_str
local percentage_display = (was_percentage_rounded and "≈" or "") .. percentage_rounded_str .. "%"
local tr = tbl_el:tag("tr")
tr:tag("td"):wikitext(name)
tr:tag("td"):wikitext("<code>" .. id .. "</code>")
tr:tag("td"):wikitext(weight)
tr:tag("td"):wikitext(percentage_display)
end
return tbl_el
end
return p