Модуль:Height
Материал из проекта «Повелитель Тайн Вики»
Дополнительные действия
-- [ru] Height formatting for {{Height}}: metric first, imperial in brackets, Russian units.
-- {{Height|m=1.73}} -> 1,73 м (5 фт 8 дюйм.) {{Height|m=1.8 to 1.9}} -> 1,8–1,9 м (5 фт 11 дюйм. – 6 фт 3 дюйм.)
local p = {}
local function num(s)
if s == nil then return nil end
s = mw.text.trim(tostring(s)):gsub(',', '.')
return tonumber(s)
end
-- Imperial value with optional fraction: "7", "7.5", "7+1/2", "7 1/2", "7_1/2", "7-1/2", "7½", "1/2", {{frac}} output.
local vulgar = { ['½'] = 0.5, ['¼'] = 0.25, ['¾'] = 0.75, ['⅓'] = 1/3, ['⅔'] = 2/3, ['⅛'] = 0.125, ['⅜'] = 0.375, ['⅝'] = 0.625, ['⅞'] = 0.875 }
local function inum(s)
if s == nil then return nil end
s = mw.text.trim(tostring(s))
s = s:gsub('<[^>]*>', ''):gsub('⁄', '/'):gsub('⁄', '/'):gsub('⁄', '/')
s = mw.text.trim(s)
local v = num(s)
if v then return v end
for ch, val in pairs(vulgar) do
local u = s:match('^(%d*)%s*' .. ch .. '$')
if u then return (tonumber(u) or 0) + val end
end
local u, n, d = s:match('^(%d+)%s*[%+%s_%-]%s*(%d+)%s*/%s*(%d+)$')
if not u then n, d = s:match('^(%d+)%s*/%s*(%d+)$'); u = 0 end
if n and tonumber(d) and tonumber(d) ~= 0 then return tonumber(u) + tonumber(n) / tonumber(d) end
return nil
end
local function fmt(x, digits)
local s
if digits then s = string.format('%.' .. digits .. 'f', x) else s = tostring(x) end
if s:find('%.') then s = s:gsub('0+$', ''):gsub('%.$', '') end
return (s:gsub('%.', ','))
end
local function ftin(meters)
local inches = meters / 0.0254
local ft = math.floor(inches / 12)
local inch = math.floor(inches - ft * 12 + 0.5)
if inch == 12 then ft = ft + 1; inch = 0 end
if inch == 0 then return ft .. ' фт' end
return ft .. ' фт ' .. inch .. ' дюйм.'
end
local function parseRange(s)
if s == nil or mw.text.trim(s) == '' then return nil end
local a, b = s:match('^%s*([%d%.,]+)%s*to%s*([%d%.,]+)%s*$')
if not a then a, b = s:match('^%s*([%d%.,]+)%s*[%-–—]%s*([%d%.,]+)%s*$') end
if a then return { num(a), num(b) } end
local v = num(s)
if v then return { v } end
return nil
end
function p.height(frame)
local args = frame:getParent().args
local function g(...)
for _, k in ipairs({...}) do
local v = args[k]
if v and mw.text.trim(v) ~= '' then return v end
end
end
local m = g('meter', 'meters', 'metre', 'metres', 'm')
local cm = g('centimeter', 'centimeters', 'centimetre', 'centimetres', 'cm')
local ft = g('foot', 'feet', 'ft')
local inch = g('inch', 'inches', 'in')
local vals, unit
if m then
vals = parseRange(m); unit = 'm'
elseif cm then
vals = parseRange(cm); unit = 'cm'
elseif ft or inch then
local f, i = inum(ft), inum(inch)
-- unparseable input (e.g. template/doc page without values): return it as is instead of a Lua error
if (ft and f == nil) or (inch and i == nil) then
return mw.text.trim((ft and (ft .. ' фт') or '') .. ' ' .. (inch and (inch .. ' дюйм.') or ''))
end
local mtr = ((f or 0) * 12 + (i or 0)) * 0.0254
local imp = (f and (fmt(f) .. ' фт') or '') .. ((i and i ~= 0) and (' ' .. fmt(i, 2) .. ' дюйм.') or '')
if args.out == 'cm' then return fmt(mtr * 100, 0) .. ' см (' .. mw.text.trim(imp) .. ')' end
return fmt(mtr, 2) .. ' м (' .. mw.text.trim(imp) .. ')'
else
return ''
end
if vals == nil then return m or cm end
local metric, imp = {}, {}
for i, v in ipairs(vals) do
local meters = unit == 'cm' and v / 100 or v
metric[i] = unit == 'cm' and fmt(v) or fmt(v)
imp[i] = ftin(meters)
end
local u = unit == 'cm' and ' см' or ' м'
return table.concat(metric, '–') .. u .. ' (' .. table.concat(imp, ' – ') .. ')'
end
return p