Module:Item infobox
From Space Station 14 Wiki
Module documentation
|
---|
View or edit this documentation • (about module documentation) |
Contains partial implementation for {{Item infobox}}.
Edible by params
Edible by parameters are implemented in this module, entrypoint generate_edible_by
.
List of edible by params is defined by edible_by_display_tbl
.
Tests
Module:Item infobox/testcases/edible by
❌ 6 tests failed.
Name | Expected | Actual | |
---|---|---|---|
❌ | test_empty | Module:Item_infobox/testcases/edible_by:10: Failed to assert that nil equals expected | |
❌ | test_everyone | Lua error -- Module:Item_infobox:131: assign to undeclared variable 'find_edible_by_order' | |
❌ | test_everyone_except_other_options | Lua error -- Module:Item_infobox:131: assign to undeclared variable 'find_edible_by_order' | |
❌ | test_everyone_except_reptilians | Lua error -- Module:Item_infobox:131: assign to undeclared variable 'find_edible_by_order' | |
❌ | test_moth | Lua error -- Module:Item_infobox:131: assign to undeclared variable 'find_edible_by_order' | |
❌ | test_reptilian | Lua error -- Module:Item_infobox:131: assign to undeclared variable 'find_edible_by_order' |
local p = {}
local getArgs = require('Module:Arguments').getArgs
local yesNo = require('Module:Yesno')
-- ==========================
local edible_by_rest_param_name_lc = "edible by rest"
-- A list of edible by parameters along with the texts to display for each.
-- Param names defined here must be lowercase.
--
-- "edible by rest" is a special case, hence the table format.
-- * If all options are selected, including "edible by rest" (ie food is edible by everyone),
-- then the first form will be used.
-- * If only some options are selected, including "edible by rest",
-- then the second form will be used, following by a list of unselected options.
local edible_by_display_tbl = {
{ param = "edible by reptilians", display = "Reptilians" },
{ param = "edible by moths", display = "Moth people" },
{ param = edible_by_rest_param_name_lc, display = { "Everyone", "Everyone, except:" } },
}
-- ==========================
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 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_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
-- ==========================
function p.generate_edible_by(frame)
local args = getArgs(frame)
local edible_by_args = table_filter(args, function(value, key)
return starts_with_insensitive(key, "edible by")
end)
if table_length(edible_by_args) == 0 then
return
end
local edible_by_rest_key = table_find_key(edible_by_args, function(value, key)
return ends_with_insensitive(key, "rest")
end)
-- save the edible by rest value to use later
local is_edible_by_rest = yesNo(edible_by_args[edible_by_rest_key])
-- generate a temp table made up only of numerical params to make it sortable.
-- get rid of unselected "edible by"s.
local selected_params_lc = {}
for key, value in pairs(edible_by_args) do
-- iterate over each key except edible by rest
if key ~= edible_by_rest_key then
-- check if its selected
if yesNo(value) then
table.insert(selected_params_lc, string.lower(key))
end
end
end
-- searches for a param name in the params table,
-- returns the index ("order") of that entry.
-- throws if no param was found (ie not defined in the table).
function find_edible_by_order(param_name_lc)
local index = table_find_index(edible_by_display_tbl, function(value)
return value.param == param_name_lc
end)
if index == nil then
error("failed to find edible by order: param name '" ..
param_name_lc .. "' if not defined in the edible by params table")
end
return index
end
-- sort the temp table based on predefine order
table.sort(selected_params_lc, function(a, b)
return find_edible_by_order(a) > find_edible_by_order(b)
end)
-- render out the params
local edible_by_rest_entry = is_edible_by_rest
and table_find(edible_by_display_tbl, function(value)
return value.param == edible_by_rest_param_name_lc
end)
if is_edible_by_rest and edible_by_rest_entry == nil then
error(
"failed to generate edible by: edible by rest param is enabled, but it is not defined in the display table")
end
local selected_params_lc_len = numeric_table_length(selected_params_lc)
-- count total selected "edible by" params, including the edible by rest
local total_selected_params = selected_params_lc_len + (is_edible_by_rest and 1 or 0)
local display_table_len = numeric_table_length(edible_by_display_tbl)
local list_el = mw.html.create('ul')
function append_li(text)
list_el
:tag("li")
:wikitext(text) -- relates to the li el, not the list el
end
function append_li_and_subli(li_text, subli_els)
local li_el = mw.html.create("li")
:wikitext(li_text)
local subli_ul = mw.html.create('ul')
for _, node in ipairs(subli_els) do
subli_ul
:node(node)
end
li_el:
node(subli_ul)
list_el
:node(li_el)
end
if total_selected_params == display_table_len then
-- all params selected, edible by everyone
-- edible by rest is assumed to be on implicitly, cz otherwise the count won't match.
append_li(edible_by_rest_entry.display[1])
else
-- some params selected
for _, key_lc in ipairs(selected_params_lc) do
local entry = table_find(edible_by_display_tbl, function(value)
return value.param == key_lc
end)
if entry == nil then
error("failed to generate edible by param: param '" ..
key_lc .. "' (lowercase) is not defined in the edible by display table")
end
append_li(entry.display)
end
if is_edible_by_rest then
-- edible by all, except those unselected
local display_unselected_entries = table_filter(edible_by_display_tbl, function(edible_by_display_entry)
local is_selected = table_contains(selected_params_lc, function(selected)
return selected == edible_by_display_entry.param
end)
local is_rest_param = edible_by_display_entry.param == edible_by_rest_param_name_lc
if is_selected or is_rest_param then
return false
end
return true
end)
local display_unselected_as_li_els = table_map(display_unselected_entries, function(value)
return mw.html.create("li")
:wikitext(value.display)
end)
append_li_and_subli(edible_by_rest_entry.display[2], display_unselected_as_li_els)
end
end
return list_el
end
return p