モジュール:Road data/util

local util = {}
local insert = table.insert
local concat = table.concat
local 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" then
		error("target is not a table")
	end
	for key,value in pairs(arr) do
		if overwrite or targetkey == nil then
			targetkey = value
		else
			error("Duplicate key: " .. tostring(key))
		end
	end
end
local function comp(e1, e2)
	local t1 = type(e1)
	local t2 = type(e2)
	if t1 ~= t2 then return t1  lengths
	a 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._precision
	local kmPerMile = 1.609344
	local 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.prec
	local errMsg = {}
	-- Sanitize inputs.
	local km_ = tonumber(km)
	if km and not km_ then
		insert(errMsg, util.err("km is not a number"))
	end
	local mi_ = tonumber(mi)
	if mi and not mi_ then
		insert(errMsg, util.err("mi is not a number"))
	end
	local prec_ = tonumber(prec)
	if prec and not prec_ then
		insert(errMsg, util.err("prec is not a number"))
	end
	prec = prec_
	local ft
	local m
	local orig = "mi"
	local comp = "km"
	if mi and km then
		insert(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_ = mi_ * kmPerMile
			km = round(km_, prec or convertedPrecision(mi, kmPerMile))
			m = round(km_ * 1000,
				prec or convertedPrecision(mi, kmPerMile * 1000))
			-- format mi (insert separators as in 1,000)
			mi = round(mi_, precision(mi))
		else
			-- `mi` is not a number.
			km = blank
			m = blank
		end
	elseif km then
		-- Length in kilometers was passed.
		-- Swap units.
		orig, comp = comp, orig
		if km_ then
			-- If `km` is indeed a number, compute and round the length in miles.
			mi = round(km_ / kmPerMile,
				prec or convertedPrecision(km, 1 / kmPerMile))
			ft = round(km_ * ftPerMile / kmPerMile,
				prec or convertedPrecision(km, ftPerMile / kmPerMile))
			-- format km (insert separators as in 1,000)
			km = round(km_, precision(km))
		else
			-- `km` is not a number.
			mi = blank
			ft = blank
		end
	else
		mi = blank
		ft = blank
		km = blank
		m = blank
	end
	local error = concat(errMsg)
	if error == "" then error = nil end
	return {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 then
		error("Unspecified error message")
	end
	return format('Error: %s', msg)
end
return util