Документация
local util = {}local insert = table.insertlocal concat = table.concatlocal format = mw.ustring.format----- Add all entries in `arr` into `target`.-- An error is raised if `overwrite` is not true-- and any key in `arr` is already in `target`.function util.addAll(target, arr, overwrite)if type(target) ~= "table" thenerror("target is not a table")endfor key,value in pairs(arr) doif overwrite or target[key] == nil thentarget[key] = valueelseerror("Duplicate key: " .. tostring(key))endendendlocal function comp(e1, e2)local t1 = type(e1)local t2 = type(e2)if t1 ~= t2 then return t1 < t2 endif t1 == "function" thenerror("Unexpected function type")endreturn e1 < e2endlocal arrayToStringAuxarrayToStringAux = function(arr, indent)if type(arr) ~= "table" thenerror("arr is not a table")endif type(indent) ~= "number" thenerror("indent is not a number")endlocal result = {}local keys = {}for key in pairs(arr) do insert(keys, key) endtable.sort(keys, comp)for _,key in ipairs(keys) dolocal value = arr[key]local keyPrintif type(key) == "string" thenkeyPrint = format("\"%s\"", key)elsekeyPrint = tostring(key)endlocal valuePrintif type(value) == "table" thenvaluePrint = format("{\n%s\n%s}",arrayToStringAux(value, indent + 4),string.rep(" ", indent))elseif type(value) == "string" thenvaluePrint = format("\"%s\"", value)elsevaluePrint = tostring(value)endinsert(result, format("%s[%s] = %s",string.rep(" ", indent),keyPrint,valuePrint))endreturn concat(result, ", \n")end--- Return a string representation of `arr`.function util.arrayToString(arr, indent)return arrayToStringAux(arr, indent or 0)endlocal function convert(distance, multiplier, desiredPrec)if type(distance) ~= "string" thenerror("distance is not a string")endif type(multiplier) ~= "number" thenerror("multiplier is not a number")end-- Import math functions.local math = require "Module:Math"-- This function returns the precision of a given string representing a number.local precision = math._precision-- This function returns the order of magnitude of a given string representing a number.local order = math._order-- This function rounds a given number to the given number of digits.local round = math._precision_formatlocal prec = desiredPrec or precision(distance)if not desiredPrec thenlocal ord = order(distance)-- Adjust precision based on multiplier, as done in {{convert}}.prec = prec - order(multiplier / 0.2)endlocal converted = distance * multiplierlocal magnitude = order(converted)if prec <= -magnitude then-- Ensure the result has at least two significant digits.prec = -magnitude + 1endreturn round(converted, prec)end--[[-Convert length specified in one unit (mi or km) to length in the other unit.@param #map<#string, #string> lengthsa map from unit to distance (as a string) in that unit;may contain entry `prec` indicating desired conversion precision@param #string blank text to be used if length is unspecified@return #table a table containing the conversion result:orig = source unit;comp = target unit;mi = length in miles;ft = converted length in feet;km = length in kilometers;m = converted length in meters;error = error message, if any]]function util.convertLengths(lengths, blank)-- Import math functions.local math = require "Module:Math"-- In Lua, storing functions locally results in more efficient execution.-- This function rounds a given number to the given number of digits.local round = math._precision_format-- This function returns the precision of a given string representing a number.local precision = math._precisionlocal kmPerMile = 1.609344local ftPerMile = 5280-- The length in kilometers as passed to the function.local km = lengths.km-- The length in miles as passed to the function.local mi = lengths.mi-- Precision for the converted length.local prec = lengths.preclocal errMsg = {}-- Sanitize inputs.local km_ = tonumber(km)if km and not km_ theninsert(errMsg, util.err("km is not a number"))endlocal mi_ = tonumber(mi)if mi and not mi_ theninsert(errMsg, util.err("mi is not a number"))endlocal prec_ = tonumber(prec)if prec and not prec_ theninsert(errMsg, util.err("prec is not a number"))endprec = prec_local ftlocal mlocal orig = "mi"local comp = "km"if mi and km theninsert(errMsg, util.err("Both mi and km are specified"))elseif mi then-- Length in miles was passed.if mi_ then-- If `mi` is indeed a number, compute and round the length in kilometers.km = convert(mi, kmPerMile, prec)m = convert(mi, kmPerMile * 1000, prec)-- format mi (insert separators as in 1,000)mi = round(mi_, precision(mi))else-- `mi` is not a number.km = blankm = blankendelseif km then-- Length in kilometers was passed.-- Swap units.orig, comp = comp, origif km_ then-- If `km` is indeed a number, compute and round the length in miles.mi = convert(km, 1 / kmPerMile, prec)ft = convert(km, ftPerMile / kmPerMile, prec)-- format km (insert separators as in 1,000)km = round(km_, precision(km))else-- `km` is not a number.mi = blankft = blankendelsemi = blankft = blankkm = blankm = blankendlocal error = concat(errMsg)if error == "" then error = nil endreturn {mi = mi, ft = ft, km = km, m = m, orig = orig, comp = comp,error = error}end--- Generates wikitext error messages.function util.err(msg)if msg == nil thenerror("Unspecified error message")endreturn format('<strong class="error">Error: %s</strong>', msg)endreturn util