Modul:Expr: Unterschied zwischen den Versionen

2022-09-04
(2022-08-28)
(2022-09-04)
Zeile 1: Zeile 1:
local Expr = { suite  = "Expr",
local Expr = { suite  = "Expr",
               serial = "2022-08-28",
               serial = "2022-09-04",
               item  = 54991461 }
               item  = 54991461 }
--[==[
--[==[
Zeile 23: Zeile 23:
* TemplateMin
* TemplateMin
* TemplateSum
* TemplateSum
* booland
* boolor
]==]
]==]
local Failsafe = Expr
local Failsafe = Expr
if mw.site.server:find( ".beta.wmflabs.org", 4, true ) then
    require( "Module:No Globals" )
end




Zeile 69: Zeile 61:
                                                         0x202F, 93 )
                                                         0x202F, 93 )
                     }
                     }
Expr.signMinus = mw.ustring.char( 0x2212 )




Zeile 83: Zeile 76:
     --    mw.language.getContentLanguage()
     --    mw.language.getContentLanguage()
     --    mw.message.new()
     --    mw.message.new()
     local c = mw.language.getContentLanguage():getCode()
     local slang = mw.language.getContentLanguage():getCode()
     local m = mw.message.new( Expr.messagePrefix .. say )
     local msg = mw.message.new( Expr.messagePrefix .. say )
     local r = false
     local r = false
     if m:isBlank() then
     if msg:isBlank() then
         local l10n = Expr.l10nDef[ c ]
         local def = Expr.l10nDef[ slang ]
         if not l10n then
         if not def then
             l10n = Expr.l10nDef[ "en" ]
             def = Expr.l10nDef[ "en" ]
         end
         end
         r = l10n[ say ]
         r = def[ say ]
     else
     else
         m:inLanguage( c )
         msg:inLanguage( slang )
         r = m:plain()
         r = msg:plain()
     end
     end
     if not r then
     if not r then
Zeile 133: Zeile 126:
                 if r == "falsch"  or  r == "nein" then
                 if r == "falsch"  or  r == "nein" then
                     r = false
                     r = false
                    --    error( "faculty@Expr", 0 )
                 else
                 else
                     r = true
                     r = true
Zeile 150: Zeile 144:




local function eval( source )
local function expr( source, show )
    -- Evaluate expression
    -- Precondition:
    --    source  -- string, mathematical expression
    return mw.ext.ParserFunctions.expr( source )
end -- eval()
 
 
 
local function expr( source, frame, show )
     -- Safe evaluation of presumable expression
     -- Safe evaluation of presumable expression
     -- Precondition:
     -- Precondition:
     --    source  -- string, mathematical expression
     --    source  -- string, mathematical expression
    --    frame  -- object
     --    show    -- string, details about source
     --    show    -- string, details about source
     -- Postcondition:
     -- Postcondition:
Zeile 170: Zeile 154:
     -- Uses:
     -- Uses:
     --    factory()
     --    factory()
     local lucky, r = pcall( eval, source )
     local lucky, r = pcall( mw.ext.ParserFunctions.expr, source )
     local n = tonumber( r, 10 )
     local n = tonumber( r, 10 )
     if not ( lucky and n ) then
     if not ( lucky and n ) then
Zeile 234: Zeile 218:




local function minmax( params, frame, low, lazy  )
local function minmax( params, low, lazy  )
     -- Find extremum of unnamed params values
     -- Find extremum of unnamed params values
     -- Precondition:
     -- Precondition:
Zeile 240: Zeile 224:
     --                      .minus
     --                      .minus
     --                      .zeroBlank
     --                      .zeroBlank
    --    frame  -- object
     --    low    -- true: minimum,  false: maximum
     --    low    -- true: minimum,  false: maximum
     --    lazy    -- true: try numeric result,  false: return string
     --    lazy    -- true: try numeric result,  false: return string
Zeile 249: Zeile 232:
     --            false if no data provided
     --            false if no data provided
     -- Uses:
     -- Uses:
    --    >  Expr.signMinus
     --    expr()
     --    expr()
    local k, v, n, scope
     local light  = ( params.minus ~= "-" )
     local light  = ( params.minus ~= "-" )
     local luxury = ( params.minus and light )
     local luxury = ( params.minus and light )
    local c      = mw.ustring.char( 8722 )    -- minus
    local scan  = "^%s*%-?[0-9]*%.?[0-9]*%s*$"
     local r      = false
     local r      = false
    local n, scope
     for k, v in pairs( params ) do
     for k, v in pairs( params ) do
         if type( k ) == "number" then
         if type( k ) == "number" then
             scope = type( v )
             scope = type( v )
             if scope == "string" then
             if scope == "string" then
                 if v:match( "^%s*$" ) then
                v = mw.text.trim( v )
                 if v == "" then
                     n = false
                     n = false
                 else
                 else
                     if mw.ustring.match( v, c ) then
                     if mw.ustring.sub( v, 1, 1 ) == Expr.signMinus then
                         luxury = light
                         luxury = light
                         v      = mw.ustring.gsub( v, c, "-" )
                         v      = "-" .. mw.ustring.sub( v, 2 )
                     end
                     end
                     if not mw.ustring.match( v, scan ) then
                     n = Expr.figure( v, ".", true )
                    if not n then
                         if low then
                         if low then
                             scope = "min()#"
                             scope = "min()#"
Zeile 274: Zeile 258:
                         end
                         end
                         scope = scope .. tostring( k )
                         scope = scope .. tostring( k )
                         v    = expr( v, frame, scope )
                         expr( v, scope )
                     end
                     end
                    n = tonumber( v )
                 end
                 end
             elseif scope == "number" then
             elseif scope == "number" then
Zeile 302: Zeile 285:
     if r then
     if r then
         if luxury and r < 0 then
         if luxury and r < 0 then
             r = c .. tostring( -1 * r )
             r = Expr.signMinus .. tostring( -1 * r )
         elseif not lazy then
         elseif not lazy then
             if r == 0 then
             if r == 0 then
Zeile 408: Zeile 391:
         end
         end
         s = tostring( math.floor( s ) )
         s = tostring( math.floor( s ) )
         for i = 1, #s do
         if s:match( "^%d+$" ) then
            r = r  +  tonumber( s:sub( i, i ) )
            for i = 1, #s do
        end -- for i
                r = r  +  tonumber( s:sub( i, i ) )
            end -- for i
        end
     end
     end
     return r
     return r
Zeile 417: Zeile 402:




Expr.decimal2minsec = function ( amount, align, ask )
Expr.decimal2minsec = function ( amount, align, ask, allow, frame )
     -- Format coordinate value in degree, minutes, seconds
     -- Format coordinate value in degree, minutes, seconds
     -- Precondition:
     -- Precondition:
     --    amount  -- string or number, with decimal coordinate
     --    amount  -- string or number, with decimal coordinate
     --    align  -- string, number, nil, with number of decimal digits
     --    align  -- string, number, nil, with number of decimal digits
     --    ask   -- string or not, with figure format
     --    ask     -- string or not, with figure format
    --    allow  -- true, if unformatted result
    --    frame  -- object, if available
     -- Postcondition:
     -- Postcondition:
     --    returns  mw.html  -- with formatted data, or
     --    returns  mw.html  -- with formatted data, or
     --              string  -- with "0" if any problem
     --              string  -- with "0" if any problem
    -- Uses:
    --    >  Expr.signMinus
     local r = Expr.figure( amount, ask )
     local r = Expr.figure( amount, ask )
     if r then
     if r then
         local d = tonumber( align )
         local d = tonumber( align )
         local e = mw.html.create( "span" )
         local e = mw.html.create( "span" )
         local kd, km, low
         local kd, km, low, sd
         if r < 0 then
         if r < 0 then
             low = true
             low = true
Zeile 440: Zeile 429:
             kd = kd  -  math.floor( kd / 360 )  *  360
             kd = kd  -  math.floor( kd / 360 )  *  360
         end
         end
        sd = tostring( kd )
         if low then
         if low then
             kd = -1 * kd
             sd = Expr.signMinus .. sd
         end
         end
         km = math.floor( r )
         km = math.floor( r )
         r  = ( r - km )  *  60
         r  = ( r - km )  *  60
         if d  and  d >= 1  and  d < 10 then
         if d  and  d >= 1  and  d < 10 then
             local s = string.format( "%%.%df", math.floor( d ) )
             local n = math.floor( r )
            local n
            r = string.format( s, r )
            n = math.floor( r )
             if r == n then
             if r == n then
                 r = tostring( n )
                 r = tostring( n )
             else
             else
                 r = r:gsub( "^(-?%d+%.%d*[1-9])0+$", "%1" )
                 local s = string.format( "%%.%df", math.floor( d ) )
                r = tonumber( string.format( s, r ) )
                if allow then
                    r = tostring( r )
                else
                    if not Expr.frame then
                        Expr.frame = frame or mw.getCurrentFrame()
                    end
                    r = Expr.frame:callParserFunction( "formatnum", r )
                end
             end
             end
         else
         else
Zeile 459: Zeile 455:
         end
         end
         if not Expr.degminsec then
         if not Expr.degminsec then
             Expr.degminsec = string.format( "%%d%s %%d%s %%s%s",
             Expr.degminsec = string.format( "%%s%s %%d%s %%s%s",
                                             mw.ustring.char( 0xB0 ),
                                             mw.ustring.char( 0xB0 ),
                                             mw.ustring.char( 0x2032 ),
                                             mw.ustring.char( 0x2032 ),
                                             mw.ustring.char( 0x2033 ) )
                                             mw.ustring.char( 0x2033 ) )
         end
         end
         r = string.format( Expr.degminsec, kd, km, r )
         r = string.format( Expr.degminsec, sd, km, r )
         e:css( "white-space", "nowrap" )
         e:css( "white-space", "nowrap" )
         :addClass( "coordinate-deg-min-sec" )
         :addClass( "coordinate-deg-min-sec" )
Zeile 477: Zeile 473:




Expr.figure = function ( amount, ask )
Expr.figure = function ( amount, ask, advance, area )
     -- Convert number from various formats
     -- Convert number from various formats
     -- Precondition:
     -- Precondition:
     --    amount -- string (or number), with number
     --    amount   -- string (or number), with number
     --    ask     -- string, with permitted formatting, defaults to "."
     --    ask     -- string, with permitted formatting, defaults to "."
    --    advance  -- true, if expressions permitted
    --    area    -- string, or not, with permitted set
     -- Postcondition:
     -- Postcondition:
     --    returns  number, or false
     --    returns  number, or false
    -- Uses:
    --    >  Expr.signMinus
    --    >  Expr.breakFigures
     -- 2022-08-08
     -- 2022-08-08
     local seek = type( amount )
     local seek = type( amount )
     local r
     local r
     if seek == "string" then
     if seek == "string" then
        local scan = mw.text.trim( amount )
         seek = ask or "."
         seek = ask or "."
        if scan == "" then
            seek = false
        elseif advance  and  not tonumber( scan ) then
            local lucky
            lucky, r = pcall( mw.ext.ParserFunctions.expr, scan )
            if lucky then
                seek = false
                r    = tonumber( r )
            else
                r = false
            end
        end
         if type( seek ) == "string" then
         if type( seek ) == "string" then
            local scan = mw.text.trim( amount )
             if scan:find( "[Ee]" ) then
             if scan:find( "[Ee]" ) then
                 scan = scan:match( "^[+%-]?([%.%d]+)[Ee][+%-]?%d+$" )
                 scan = scan:match( "^[+%-]?([%.%d]+)[Ee][+%-]?%d+$" )
Zeile 509: Zeile 522:
                     seek = seek:sub( 2 )
                     seek = seek:sub( 2 )
                     if mw.ustring.sub( scan, 1, 1 )
                     if mw.ustring.sub( scan, 1, 1 )
                                        == mw.ustring.char( 0x2212 ) then
                      == Expr.signMinus then
                         low  = true
                         low  = true
                         scan = mw.ustring.sub( scan, 2 )
                         scan = mw.ustring.sub( scan, 2 )
Zeile 586: Zeile 599:
     elseif seek == "number" then
     elseif seek == "number" then
         r = amount
         r = amount
    end
    if r  and  type( area ) == "string" then
        local set = mw.text.trim( area )
        if set == "" then
        elseif set == "N"  or  set == "Z+" then
            if r < 0  or
              r ~= math.floor( r ) then
                r = false
            end
        elseif set == "Z" then
            if r ~= math.floor( r ) then
                r = false
            end
        elseif set == "Z-" then
            if r > 0  or
              r ~= math.floor( r ) then
                r = false
            end
        elseif set == "R+" then
            if r < 0 then
                r = false
            end
        elseif set == "R-" then
            if r > 0 then
                r = false
            end
        end
     end
     end
     return r or false
     return r or false
Zeile 672: Zeile 712:
     --    after  -- true, if trailing zeroes shall be kept
     --    after  -- true, if trailing zeroes shall be kept
     --    ask    -- string or not, with figure format
     --    ask    -- string or not, with figure format
     --    allow  -- true, if unformatted
     --    allow  -- true, if unformatted result
     --    frame  -- object, if available
     --    frame  -- object, if available
     -- Postcondition:
     -- Postcondition:
Zeile 726: Zeile 766:
     if type( array ) == "table" then
     if type( array ) == "table" then
         for k, v in pairs( array ) do
         for k, v in pairs( array ) do
             v = Expr.figure( v, ask )
             v = Expr.figure( v, ask, true )
             if v then
             if v then
                 r1 = r1 + v
                 r1 = r1 + v
Zeile 839: Zeile 879:
     return  tostring( Expr.decimal2minsec( frame.args[ 1 ],
     return  tostring( Expr.decimal2minsec( frame.args[ 1 ],
                                           frame.args[ 2 ],
                                           frame.args[ 2 ],
                                           frame.args.parse ) )
                                           frame.args.parse,
                                          faculty( frame.args.low ),
                                          frame ) )
end
end


p.figure = function ( frame )
p.figure = function ( frame )
     return Expr.figure( frame.args[ 1 ], frame.args[ 2 ] ) or  ""
     local r = Expr.figure( frame.args[ 1 ],
                          frame.args.parse,
                          faculty( frame.args.expr ),
                          frame.args.set )
    if r then
        r = tostring( r )
    else
        r = ""
    end
    return r
end -- p.figure
end -- p.figure


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


function p.min( frame )
function p.min( frame )
     local lucky, r = pcall( minmax, frame.args, frame, true, false )
     local lucky, r = pcall( minmax, frame.args, true, false )
     return r or ""
     return r or ""
end
end
Zeile 872: Zeile 923:
function p.percent( frame )
function p.percent( frame )
     local base = frame.args[ 2 ]
     local base = frame.args[ 2 ]
     local leave, low, pars
     local pars
     if base then
     if base then
         pars = frame.args
         pars = frame.args
Zeile 879: Zeile 930:
         base = pars[ 2 ]
         base = pars[ 2 ]
     end
     end
    leave = pars[ 4 ]
     return Expr.percent( pars[ 1 ],
    if leave then
                        base,
        leave = mw.text.trim( leave )
                        pars[ 3 ],
        if leave == ""  or  leave == "0" then
                        faculty( pars[ 4 ] ),
            leave = false
                         pars.parse,
        end
                        faculty( pars.low ),
    end
                        frame )
    low = pars.low
    if low == ""  or  low == "0" then
        low = false
    end
     return Expr.percent( pars[ 1 ], base, pars[ 3 ], leave,
                         pars.parse, low, frame )
end
end


Zeile 950: Zeile 995:
function p.TemplateSum( frame )
function p.TemplateSum( frame )
     return p.sum( frame:getParent() )
     return p.sum( frame:getParent() )
end
function p.booland( frame )
    return logicaland( frame:getParent().args )
end
function p.boolor( frame )
    return logicalor( frame:getParent().args )
end
end


Anonymer Benutzer