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- | serial = "2022-09-04", | ||
item = 54991461 } | item = 54991461 } | ||
--[==[ | --[==[ | ||
| Zeile 23: | Zeile 23: | ||
* TemplateMin | * TemplateMin | ||
* TemplateSum | * TemplateSum | ||
]==] | ]==] | ||
local Failsafe = Expr | local Failsafe = Expr | ||
| 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 | local slang = mw.language.getContentLanguage():getCode() | ||
local | local msg = mw.message.new( Expr.messagePrefix .. say ) | ||
local r = false | local r = false | ||
if | if msg:isBlank() then | ||
local | local def = Expr.l10nDef[ slang ] | ||
if not | if not def then | ||
def = Expr.l10nDef[ "en" ] | |||
end | end | ||
r = | r = def[ say ] | ||
else | else | ||
msg:inLanguage( slang ) | |||
r = | 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 expr( source, show ) | |||
local function expr( source | |||
-- Safe evaluation of presumable expression | -- Safe evaluation of presumable expression | ||
-- Precondition: | -- Precondition: | ||
-- source -- string, mathematical expression | -- source -- string, mathematical expression | ||
-- show -- string, details about source | -- show -- string, details about source | ||
-- Postcondition: | -- Postcondition: | ||
| Zeile 170: | Zeile 154: | ||
-- Uses: | -- Uses: | ||
-- factory() | -- factory() | ||
local lucky, r = pcall( | 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 | 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 | ||
-- 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 light = ( params.minus ~= "-" ) | local light = ( params.minus ~= "-" ) | ||
local luxury = ( params.minus and light ) | local luxury = ( params.minus and light ) | ||
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 | scope = type( v ) | ||
if scope == "string" then | if scope == "string" then | ||
if v | v = mw.text.trim( v ) | ||
if v == "" then | |||
n = false | n = false | ||
else | else | ||
if mw.ustring. | if mw.ustring.sub( v, 1, 1 ) == Expr.signMinus then | ||
luxury = light | luxury = light | ||
v = mw.ustring. | v = "-" .. mw.ustring.sub( v, 2 ) | ||
end | end | ||
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 ) | ||
expr( v, scope ) | |||
end | end | ||
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 = | 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 | ||
for i = 1, #s do | |||
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 | -- 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 | ||
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 | local n = math.floor( r ) | ||
if r == n then | if r == n then | ||
r = tostring( n ) | r = tostring( n ) | ||
else | else | ||
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( "%% | 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, | 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 | -- amount -- string (or number), with number | ||
-- ask | -- 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 | ||
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 ) | ||
== 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 ) | ||
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 | 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 | 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 | 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 | ||
return Expr.percent( pars[ 1 ], | |||
base, | |||
pars[ 3 ], | |||
faculty( pars[ 4 ] ), | |||
pars.parse, | |||
faculty( pars.low ), | |||
frame ) | |||
return Expr.percent( pars[ 1 ], base, pars[ 3 ], | |||
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 | end | ||