Zum Inhalt springen
Willkommen in der InkluPedia
Wenn dir dieses Wiki geholfen hat, würde sich die InkluPedia über eine Trustpilot-Bewertung hierüber als Dankeschön freuen. Feedback zu diesem Wiki ist über das Kontaktformular oder nach eine Anmeldung möglich. Für die Mitarbeit ist eine Anmeldung (ohne Angaben persönlicher Daten) erforderlich. Wegen Attacken von weltweit aktiven SPAM-Bots [1] ist das derzeit nur über ein Formular möglich.

Modul:Expr

Aus InkluPedia
  • Dieses Modul enthält Code in der Programmiersprache Lua.
  • Module werden über #invoke in Vorlagen eingebunden.
  • Dieses Modul wird über Vorlagen auf folgenden Seiten verwendet: Seiten anzeigen

--[=[ 2016-05-26
Expr
* max
* min
* TemplateMax
* TemplateMin
* booland
]=]



local messagePrefix = "lua-module-Expr-"
local l10nDef = {}
l10nDef[ "en" ] = {
    ErrorExpr  = "Error in mathematical expression, function#parameter"
}
l10nDef[ "de" ]  = {
    ErrorExpr  = "Fehler in mathematischem Ausdruck, Funktion#Parameter"
}


local function factory( say )
    -- Retrieve localized message string in content language
    -- Precondition:
    --     say  -- string; message ID
    -- Postcondition:
    --     Return some message string
    -- Uses:
    --     >  messagePrefix
    --     >  l10nDef
    --     mw.language.getContentLanguage()
    --     mw.message.new()
    local c = mw.language.getContentLanguage():getCode()
    local m = mw.message.new( messagePrefix .. say )
    local r = false
    if m:isBlank() then
        local l10n = l10nDef[ c ]
        if not l10n then
            l10n = l10nDef[ "en" ]
        end
        r = l10n[ say ]
    else
        m:inLanguage( c )
        r = m:plain()
    end
    if not r then
        r = "(((" .. say .. ")))"
    end
    return r
end -- factory()

local function eval( source, frame )
    -- Evaluate expression
    -- Precondition:
    --     source  -- string; mathematical expression
    --     frame   -- object
    return frame:callParserFunction( "#expr", source )
end -- eval()


local function expr( source, frame, show )
    -- Safe evaluation of presumable expression
    -- Precondition:
    --     source  -- string; mathematical expression
    --     frame   -- object
    --     show    -- string; details about source
    -- Postcondition:
    --     throws error, if expression failed
    --     returns number with resulting figure
    -- Uses:
    --     factory()
    local lucky, r = pcall( eval, source, frame )
    local n = tonumber( r, 10 )
    if not lucky or n == nil then
        r = r .. " " .. factory( "ErrorExpr" )
            .. " ''" .. show .. "'' (" .. source .. ")"
        error( r, 0 )
    else
        r = n
    end
    return r
end -- expr()


local function base62( value )
    -- Convert number from and to base62 encoding
    -- Precondition:
    --     value  -- number or string to be converted
    --               number: to base62
    --               string: base62 to number
    --     Lua limitation at 10^53; larger numbers are less precise
    -- Postcondition:
    --     returns string, or number, or false
    local r = false
    local state = type( value )
    if state == "number" then
        local k = math.floor( value )
        if k == value  and  value > 0 then
            local m
            r = ""
            while k > 0 do
                m = k % 62
                k = ( k - m ) / 62
                if m >= 36 then
                    m = m + 61
                elseif m >= 11 then
                    m = m + 55
                else
                    m = m + 48
                end
                r = string.char( m ) .. r
            end
        elseif value == 0 then
            r = "0"
        end
    elseif state == "string" then
        if value:match( "^%w+$" ) then
            local n = #value
            local k = 1
            local c
            r = 0
            for i = n, 1, -1 do
                c = value:byte( i, i )
                if c >= 48  and  c <= 57 then
                    c = c - 48
                elseif c >= 65  and  c <= 90 then
                    c = c - 55
                elseif c >= 97  and  c <= 122 then
                    c = c - 61
                else    -- How comes?
                    r = nil
                    break    -- for i
                end
                r = r + c * k
                k = k * 62
            end -- for i
        end
    end
    return r
end -- base62()

function logicaland(args)
	local r = true;
	local k, v, s
	local b
	for k, v in pairs(args) do
		s = mw.text.trim(v)
		b = (s or '') ~= ''
		r = r and b
	end
    return r
end

function logicalor(args)
	local r = false;
	local k, v, s
	local b
	for k, v in pairs(args) do
		s = mw.ustring.lower(mw.text.trim(v) or '');
		if s == '' then
			b = false;
		elseif s=='0' then
			b = false;
		elseif s=='false' then
			b = false;
		elseif s=='falsch' then
			b = false;
		elseif s=='nein' then
			b = false;
		else
			b = true;
		end
		if b then
			r = true;
		end
	end
    return r
end

local function minmax( params, frame, low, lazy  )
    -- Find extremum of unnamed params values
    -- Precondition:
    --     params  -- table; like args
    --                       .minus
    --                       .zeroBlank
    --     frame   -- object
    --     low     -- true: minimum;  false: maximum
    --     lazy    -- true: try numeric result;  false: return string
    -- Postcondition:
    --     throws error, if expression failed
    --     returns number, or
    --             string if formatting required, or
    --             false if no data provided
    -- Uses:
    --     expr()
    local k, v, n, scope
    local light  = ( params.minus ~= "-" )
    local luxury = ( params.minus and light )
    local c      = mw.ustring.char( 8722 )    -- minus
    local scan   = "^%s*%-?[0-9]*%.?[0-9]*%s*$"
    local r      = false
    for k, v in pairs( params ) do
        if type( k ) == "number" then
            scope  = type( v )
            if scope == "string" then
                if v:match( "^%s*$" ) then
                    n = false
                else
                    if mw.ustring.match( v, c ) then
                        luxury = light
                        v      = mw.ustring.gsub( v, c, "-" )
                    end
                    if not mw.ustring.match( v, scan ) then
                        if low then
                            scope = "min()#"
                        else
                            scope = "max()#"
                        end
                        scope = scope .. tostring( k )
                        v     = expr( v, frame, scope )
                    end
                    n = tonumber( v )
                end
            elseif scope == "number" then
                n = v
            else
                n = false
            end
            if n then
                if r then
                    if low then
                        if n < r then
                            r = n
                        end
                    else
                        if n > r then
                            r = n
                        end
                    end
                else
                    r = n
                end
            end
        end
    end -- for k, v
    if r then
        if luxury and r < 0 then
            r = c .. tostring( -1 * r )
        elseif not lazy then
            if r == 0 then
                if params.zeroBlank then
                    r = ""
                else
                    r = "0"
                end
            else
                r = tostring( r )
            end
        end
    end
    return r
end -- minmax()



-- Export
local p = {}

function p.base62( frame )
    local r
    local s = frame.args[ 1 ]
    if s then
        local s2 = frame.args[ 2 ]
        if s2 then
            s2 = mw.text.trim( s2 )
        end
        if s2 == "D2B" then
            s = tonumber( s )
        else
            s = mw.text.trim( s )
            s2 = false
        end
        r = base62( s )
        if r  and  not s2 then
            r =  string.format( "%17d", r )
        end
    end
    return r or ""
end

function p.max( frame )
    local lucky, r = pcall( minmax, frame.args, frame, false, false )
    return r or ""
end

function p.min( frame )
    local lucky, r = pcall( minmax, frame.args, frame, true, false )
    return r or ""
end

function p.TemplateMax( frame )
    return p.max( frame:getParent() )
end

function p.TemplateMin( frame )
    return p.min( frame:getParent() )
end

function p.booland(frame)
	local fr=frame:getParent()
	return logicaland(fr.args)
end

function p.boolor(frame)
	local fr=frame:getParent()
	return logicalor(fr.args)
end

function p.Expr( f, a )
    local r = false
    if f == "min"  or  f == "max" then
        local frame = mw.getCurrentFrame()
        local low = ( f == "min" )
        local lucky
        lucky, r = pcall( minmax, a, frame, low, true )
    elseif f == "base62" then
        r = base62( a )
    end
    return r
end -- .Expr()

return p -- Expr