# Module:Change

-- This implements
local p = {}  
local function ntsh(outvalue)
local sortkey = '0000000000000000000'
if outvalue == nil then
return '<span data-sort-value="' .. sortkey .. '♠"></span>'
end  
-- This code was copied from Template:Convert
if outvalue == 0 then
sortkey = '5000000000000000000'
else
local mag = math.floor(math.log10(math.abs(outvalue)) + 1e-14)
local prefix
if outvalue > 0 then
prefix = 7000 + mag
else
prefix = 2999 - mag
outvalue = outvalue + 10^(mag+1)
end
sortkey = string.format('%d', prefix) .. string.format('%015.0f', math.floor(outvalue * 10^(14-mag)))
end
return '<span data-sort-value="' .. sortkey .. '♠"></span>'
end  
local function trim(s)
return s:match('^%s*(.-)%s*$')
end  
local function isnotempty(s)
return s and trim(s) ~= ''
end  
function change(args)
local rnd = require('Module:Math')._round
local prec_format = require('Module:Math')._precision_format
local lang = mw.getContentLanguage
local function formatnum(num)
return lang:parseFormattedNumber(num) and lang:formatNum(lang:parseFormattedNumber(num)) or num
end  
local errorflag = nil  
local dsp = args['disp'] or 'row'
local inv = args['invert'] or 'off'
local srt = args['sort'] or ((isnotempty(args['pre']) or isnotempty(args['sort'])) and 'on' or 'off')
local n1 = (inv == 'on') and tonumber(lang:parseFormattedNumber(args['2'])) or tonumber(lang:parseFormattedNumber(args['1']))
local n2 = (inv == 'on') and tonumber(lang:parseFormattedNumber(args['1'])) or tonumber(lang:parseFormattedNumber(args['2']))
local dec = args['dec'] or '2'
local s = ((args['italics'] or 'off') == 'on' and "''" or "")
.. ((args['bold'] or 'off') == 'on' and "'''" or "")  
local pc, pcr, pcrf = 'NA', 'NA'  
if n1 and n2 and n1 ~= 0 then
pc = 100*(n2/n1 - 1)
pcr = rnd(pc, dec)
if pcr > 0 then
pcrf = '<span>' ..
s .. '+' .. prec_format(pc, dec) .. '%' .. s .. '</span>'
elseif pcr < 0 then
pcrf = '<span>' ..
s .. prec_format(pc, dec) .. '%' .. s .. '</span>'
else
pcrf = s .. prec_format(0, dec) .. '%' .. s
end
pcrf = ntsh(pcr) .. pcrf
else
pcrf = ntsh(nil) .. s .. 'NA' .. s
if n1 == nil or n2 == nil then
errorflag = 1
end
end  
if dsp == 'out' then
return pcrf, errorflag
else
local pre1 = args['pre1'] or args['pre'] or ''
local pre2 = args['pre2'] or args['pre'] or ''
local suf1 = args['suf1'] or args['suf'] or ''
local suf2 = args['suf2'] or args['suf'] or ''  
local rspn = 'rowspan'] or '1') .. ' '
local algn = 'text-align:' .. (args['align'] or '') .. ';'
local bg = 'background-color:' .. (args['bgcolour'] or args['bgcolor'] or 'inherit') .. ';'  
if rspn == 'rowspan=1 ' then rspn = '' end
if bg == 'background-color:inherit;' then bg = '' end
local style = rspn .. ''  
local sk1, sk2 = *, *  
if srt == 'on' then
sk1 = ntsh(n1)
sk2 = ntsh(n2)
end  
if n1 ~= nil then
if n1 < 0 then
n1 = '−' .. formatnum(-1*n1)
else
n1 = formatnum(n1)
end
else
n1 = (inv == 'on') and (args['2'] or *) or (args['1'] or *)
end  
if n2 ~= nil then
if n2 < 0 then
n2 = '−' .. formatnum(-1*n2)
else
n2 = formatnum(n2)
end
else
n2 = (inv == 'on') and (args['1'] or *) or (args['2'] or *)
end  
if dsp == 'row2' then
return style .. '|' .. s .. pre2 .. n2 .. suf2 .. s
.. '\n|' .. style .. '|' .. pcrf, errorflag
else
if inv == 'off' then
return style .. '|' .. s .. pre1 .. n1 .. suf1 .. s
.. '\n|' .. style .. '|' .. s .. pre2 .. n2 .. suf2 .. s
.. '\n|' .. style .. '|' .. pcrf, errorflag
else
return style .. '|' .. s .. pre1 .. n2 .. suf1 .. s
.. '\n|' .. style .. '|' .. s .. pre2 .. n1 .. suf2 .. s
.. '\n|' .. style .. '|' .. pcrf, errorflag
end
end
end
end  
function p.main
local res, eflag = change((.args[1] or .args[2]) and .args or :getParent.args)
if eflag then
res = res .. :expandTemplate{title = 'change/error'}
end
return res
end  
return p