Modul:Expr: Unterschied zwischen den Versionen
K (Änderte den Schutz von „Modul:Expr“: Entsperrwunsch: Spezial:Permalink/135673840#MediaWiki et al. ([Bearbeiten=Nur angemeldete, nicht neue Benutzer] (unbeschränkt) [Verschieben=Nur Administratoren] (unbeschränkt))) |
(+ base62) |
||
Zeile 1: | Zeile 1: | ||
--[=[ | --[=[ 2014-09-24 | ||
Expr | Expr | ||
* max | * max | ||
Zeile 45: | Zeile 45: | ||
end | end | ||
if not r then | if not r then | ||
r = "(((".. say .. ")))" | r = "(((" .. say .. ")))" | ||
end | end | ||
return r | return r | ||
Zeile 84: | Zeile 84: | ||
return r | return r | ||
end -- expr() | 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() | |||
Zeile 133: | Zeile 192: | ||
elseif scope == "number" then | elseif scope == "number" then | ||
n = v | n = v | ||
else | |||
n = false | |||
end | end | ||
if n then | if n then | ||
Zeile 173: | Zeile 234: | ||
-- Export | -- Export | ||
local p = {} | 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 ) | function p.max( frame ) | ||
Zeile 193: | Zeile 276: | ||
function p.Expr( f, a ) | function p.Expr( f, a ) | ||
local r = false | local r = false | ||
if f == "min" or f == "max" then | if f == "min" or f == "max" then | ||
local frame = mw.getCurrentFrame() | |||
local low = ( f == "min" ) | |||
local lucky | local lucky | ||
lucky, r = pcall( minmax, a, frame, low, true ) | lucky, r = pcall( minmax, a, frame, low, true ) | ||
elseif f == "base62" then | |||
r = base62( a ) | |||
end | end | ||
return r | return r |
Version vom 10. November 2014, 00:39 Uhr
Die Dokumentation für dieses Modul kann unter Modul:Expr/doc erstellt werden
--[=[ 2014-09-24 Expr * max * min * TemplateMax * TemplateMin ]=] 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() 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.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