Module:Calculate

local p = {} local expr = mw.ext.ParserFunctions.expr local getArgs = require('Module:Arguments').getArgs local split = require('Module:Split') local yesno = require('Module:Yesno')

local i18n = { value_separator = '/', error_no_expression = 'Enter an expression', }

function p.main(frame) local args = getArgs(frame, {   wrappers = {      'Template:Calculate'    }  }) return p._main(args) end

function p._main(args) local calculate = function(calc) -- Replaces percentage signs with /100 since #expr can't handle them. calc = string.gsub(calc, '%%', '/100') return expr(calc) end

assert(args and args[1], i18n.error_no_expression) if args['v1'] then -- Create a table that holds a table for each v argument. local v_values = {} local n = 1 while args['v'..n] do     -- Escape percentage signs to prevent them from escaping the / during the split. v = string.gsub(args['v'..n], '%%', '%%%%') -- Split the v into the individual values and add them to the v_values table. table.insert(v_values, split(v, i18n.value_separator)) n = n + 1 end

local output = {} -- Run once for each value in the v1 argument. for level=1,#v_values[1] do     local calc = args[1] -- Do a replacement for each v arg. for i,v in ipairs(v_values) do       calc = calc:gsub('v'..i, v[level]) end

-- Solve the calculation we just constructed and insert it into the output. -- args[2] is used to trigger special percentage handling. if yesno(args.percent) or args[2] then table.insert(output, calculate('('..calc..')*100') .. '%') else table.insert(output, calculate(calc)) end end

-- Return the values in the output table separated by a /. return table.concat(output, i18n.value_separator) else -- Just do a normal #expr if no v values are given. -- Still has percentage handling which normal #expr doesn't.   -- TODO: Remove the args[2] once all pages are transitioned. if yesno(args.percent) or args[2] then return calculate('('..args[1]..')*100') .. '%'   else return calculate(args[1]) end end end

return p