Module:Airs Table
From Fallen London Wiki
Documentation for this module may be created at Module:Airs Table/doc
local p = {}
local function pairs_cmp(pair1, pair2)
if pair1[1] < pair2[1] then
return true
elseif pair1[1] == pair2[1] and pair1[2] < pair2[2] then
return true
else
return false
end
end
--[[
Iterate through the arguments passed to the parent template to extract known levels.
Input parameters:
@args: the table of args to search
@arg_prefix: the base name of the args to search
@max_value: ranges higher than this number will be diregarded, the first range beyond it will be converted down to match this
Returns a sorted list of integer pairs, representing the start and end of a known range.
If a range contains only one number, it will be used for both numbers in the pair.
]]
local function level_ranges(args, arg_prefix, arg_max_value)
local pattern = arg_prefix .. '%s*(%d+)%D*(%d*)'
local max_value = tonumber(arg_max_value)
local ranges = {}
for k in pairs(args) do
start_level, end_level = string.match(k, pattern)
if end_level == '' then
end_level = start_level
end
if start_level then
if tonumber(start_level) <= max_value and tonumber(end_level) <= max_value then
table.insert(ranges, {tonumber(start_level), tonumber(end_level)})
end
if tonumber(start_level) <= max_value and tonumber(end_level) > max_value then
table.insert(ranges, {tonumber(start_level), max_value})
end
end
end
table.sort(ranges, pairs_cmp)
return ranges
end
--[[
Generates the Wiki Note listing unaccounted numbers.
Input parameters:
@ranges: a sorted list of integer pairs, the ranges of accounted numbers
@max_value: an integer denoting the maximum value (100 for most Airs)
@min_value: an integer denoting the maximum value (1 for most Airs)
If any numbers are unaccounted for, returns a string of a formatted Wiki Note
containing an ordered list of unaccounted numbers.
Otherwise returns an empty string.
]]
local function find_unaccounted(ranges, min_value, max_value)
local all_present = true
local output = '<i><b>Wiki note:</b> Numbers unaccounted for: '
local next_level = min_value
table.insert(ranges, {max_value+1, max_value+1})
for i,range in ipairs(ranges) do
if next_level < range[1] then
if not all_present then
output = output .. ', '
end
all_present = false
if next_level == range[1] - 1 then
output = output .. next_level
else
output = output .. next_level .. ' – ' .. range[1] - 1
end
end
next_level = range[2] + 1
end
if all_present then
return ''
else
return output .. '</i>[[Category:Pages with missing variant text]]'
end
end
--[[
Generate a Wiki Note listing numbers not yet accounted for in the table.
May have strange and unexpected behaviour if a row contains non-contiguous
values or if multiple rows have intersecting ranges.
]]
function p.unaccounted_airs_values(frame)
local args = frame.args
local parent_args = frame:getParent().args
local arg_prefix = args.prefix or 'Level'
local arg_min_value = tonumber(args.min_value) or 0
local arg_max_value = tonumber(args.max_value) or 100
local ranges = level_ranges(parent_args, arg_prefix, arg_max_value)
return find_unaccounted(ranges, arg_min_value, arg_max_value)
end
return p