Перейти к содержимому страницы
Переключить меню
Переключить меню настроек
Переключить персональное меню
Вы не представились системе
Ваш IP-адрес будет виден всем, если вы внесёте какие-либо изменения.
Сообщество «Повелителя Тайн»Telegram — новости, дунхуа, игры и мерчDiscord — обсуждение книг и теорий, вопросы по вики

Модуль:Height: различия между версиями

Материал из проекта «Повелитель Тайн Вики»
imported>Import
Импорт с англ. вики (CC BY-SA)
fix: Height robust
Строка 7: Строка 7:
     s = mw.text.trim(tostring(s)):gsub(',', '.')
     s = mw.text.trim(tostring(s)):gsub(',', '.')
     return tonumber(s)
     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('&frasl;', '/'):gsub('⁄', '/'):gsub('&#8260;', '/')
    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
end


Строка 53: Строка 72:
         vals = parseRange(cm); unit = 'cm'
         vals = parseRange(cm); unit = 'cm'
     elseif ft or inch then
     elseif ft or inch then
         local mtr = ((num(ft) or 0) * 12 + (num(inch) or 0)) * 0.0254
         local f, i = inum(ft), inum(inch)
         local imp = (ft and (num(ft) .. ' фт') or '') .. ((inch and num(inch) and num(inch) ~= 0) and (' ' .. num(inch) .. ' дюйм.') or '')
        -- 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) .. ')'
         return fmt(mtr, 2) .. ' м (' .. mw.text.trim(imp) .. ')'
     else
     else
Строка 71: Строка 96:


return p
return p

Версия от 03:18, 1 ноября 2026

-- [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('&frasl;', '/'):gsub('⁄', '/'):gsub('&#8260;', '/')
    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