Op den Inhalt sprangen

Modul:Zuelen

Vu Wikipedia
Dokumentatioun vum Modul:Zuelen [liesen] [änneren] [Versioune weisen]

D'Dokumentatioun fir dëst Modul steet hei ënnendrënner an ass vun der Säit Modul:Zuelen/doc hei agebonne ginn. All Froe sollen och op där hirer Diskussiounssäit gestallt ginn. Kuckt och: Hëllef:Moduler.

-- Inspiréiert un [https://www.wikifunctions.org/view/lb/Z23864]
-- vum [[wikifunctions:User:Volvox]]
local p = {}

local small_ordinals = {
    "st", "éischt", "zweet", "drëtt", "véiert", "fënneft", "sechst", "siwent",
    "aacht", "néngt", "zéngt", "eeleft", "zwieleft", "dräizéngt", "véierzéngt",
    "fofzéngt", "siechzéngt", "siwwenzéngt", "uechzéngt", "nonzéngt"
}

local small_numbers = {
    "", "eent", "zwee", "dräi", "véier", "fënnef", "sechs", "siwen",
    "aacht", "néng", "zéng", "eelef", "zwielef", "dräizéng", "véierzéng",
    "fofzéng", "siechzéng", "siwwenzéng", "uechzéng", "nonzéng"
}

local tens = {
    "", "", "zwanzeg", "drësseg", "véierzeg", "fofzeg", "sechzeg",
    "siwwenzeg", "achtzeg", "nonzeg"
}

local large_numbers = {
    "", "", "millioun", "milliard", "billioun", "billiard", "trillioun",
    "trilliard", "quadrillioun", "quadrilliard", "quintillioun",
    "quintilliard", "sextillioun", "sextilliard", "septillioun",
    "septilliard", "oktillioun", "oktilliard", "nonillioun", "nonilliard",
    "dezillioun"
}

local non_removal_start_chars = {
    d=true, h=true, n=true, t=true, z=true,
    a=true, ["ä"]=true, ["à"]=true, ["â"]=true,
    e=true, ["é"]=true, ["ë"] = true, ["è"]=true, ["ê"]=true,
    i=true, ["î"]=true,
    o=true, ["ö"]=true, ["ô"]=true,
    u=true, ["ü"]=true, ["û"]=true
}

local function simplified_eifel_rule(word1, word2)
    local firstChar = mw.ustring.lower(mw.ustring.sub(word2, 1, 1))
    if (word1 == "an" or mw.ustring.sub(word1, -2) == "en") and not non_removal_start_chars[firstChar] then
        return mw.ustring.sub(word1, 1, -2)
    end
    return word1
end

local function apply_simplified_eifel_rule_to_string(s)
    local words = mw.text.split(s, " ")
    if #words < 2 then
        return s
    end

    local result = {}
    for i = 1, #words - 1 do
        table.insert(result, simplified_eifel_rule(words[i], words[i + 1]))
    end
    table.insert(result, words[#words])
    return table.concat(result, " ")
end

local function convert_two_digit_number(n, block_index)
    if n < 20 then
        return (block_index == 0) and small_ordinals[n + 1] or small_numbers[n + 1]
    end

    local quotient = math.floor(n / 10)
    local remainder = n % 10
    local part1 = ""
    local part2 = ""
    local part3 = tens[quotient + 1]

    if remainder >= 1 then
        part1 = (remainder == 1) and "een" or small_numbers[remainder + 1]
        part2 = simplified_eifel_rule("an", part3)
    end

    return part1 .. part2 .. part3 .. (block_index == 0 and "st" or "")
end

local function convert_three_digit_number(n, block_index)
    if n < 100 then
        return convert_two_digit_number(n, block_index)
    end

    local quotient = math.floor(n / 100)
    local remainder = n % 100
    local prefix = (quotient == 1) and "" or small_numbers[quotient + 1]
    return prefix .. "honnert" .. convert_two_digit_number(remainder, block_index)
end

local function convert_large_number(n)
    local num_str = tostring(math.abs(n))
    if #num_str > 23 then
        return "FEELER: D'Inputzuel ass ze grouss fir dës Funktioun"
    end

    if n < 1000 then
        return convert_three_digit_number(n, 0)
    end

    local result = ""
    local block_index = 0

    while n > 0 do
        local remainder = n % 1000
        n = math.floor(n / 1000)

        if block_index == 0 then
            result = convert_three_digit_number(remainder, block_index)
        elseif block_index == 1 and remainder >= 1 then
            local prefix = (remainder == 1) and "" or convert_three_digit_number(remainder, block_index)
            result = prefix .. "dausend" .. result
        elseif remainder >= 1 then
            local prefix
            if remainder == 1 then
                prefix = "eng"
            elseif remainder == 2 then
                prefix = "zwou"
            else
                prefix = convert_three_digit_number(remainder, block_index)
            end
            local ending = (remainder == 1) and "" or "en"
            local suffix = (result == "st") and "" or ending
            result = prefix .. large_numbers[block_index + 1] .. suffix .. result
        end

        block_index = block_index + 1
    end

    return result
end

function p.isSafeNumber(numberStr)
	-- Iwwerpréift, ob den Inputstring eng ganz Zuel duerstellt, déi innerhalb
	-- vun de Limitten ass, déi Scribunto-Lua korrekt duerstelle kann.
	-- Experimentéieren ergëtt Limitte vun [-99999999999999,99999999999999]
	-- (dat si jeeweils 14 9en).
	local s = numberStr:gsub("^%-", "")
    return s:match("^%d+$") and #s < 15
end

function p.ordinalLb(frame)
    local s = frame.args[1]
    if not p.isSafeNumber(s) then
    	return nil
    end
    local n = tonumber(s)
    if n == 0 then
    	return "nullt"
    end
    return apply_simplified_eifel_rule_to_string(convert_large_number(n))
end

return p