Module:Briskmetal007/ap

-- local p = {} local lib      	= require('Module:Feature') local fd_get   	= require('Module:fd').get local fd_getmulti	= require('Module:fd').getmulti local mw_expr			= mw.ext.ParserFunctions.expr local gsub,find,sub,len = string.gsub,string.find,string.sub,string.len local abs,floor,ceil = math.abs,math.floor,math.ceil local concat = table.concat local tostring,tonumber,match,pcall = tostring,tonumber,match,pcall

local function expr(val) if find(val,"..",1,true) then error("not calculable") else return mw_expr(val) end end

local function fd(val) return fd_get{args = {val}} end

local function fdmulti(val) return fd_getmulti{args = {val}} end

local function rounding(val, decimals) if decimals == nil or find(val, "[0-9]") == nil or find(val, "<span", 1, true) or find(val, ".", 1, true) == nil then return val end local a, b, c, d = tostring(val):match"([^0-9]*)([0-9]*)%.([0-9]*)(.*)" val = tonumber(b .. "." .. c)	local round = (		decimals == "abs" and abs(val)		or decimals == "floor" and floor(val)		or decimals == "ceil" and ceil(val)		or decimals == "trunc" and sub(val, 1, (find(val, ".", 1, true) or 0) - 1)		or floor(val * 10 ^ (decimals) + 0.5) / (10 ^ (decimals))		) val = a .. round .. d   if tonumber(val) then return tonumber(val) end

return val end

local function string_to_formula(args) local val = gsub(args," ","")

while find(val, "to", 1, true) do       local to       		= sub(val, 1, find(val, "to", 1, true) - 1) local para        	= lib.split(to, "(",true)		local para_len 		= #para        local j             = para_len		local total_times   = 0

while j >= 2 do           local _, times = gsub(para[j], "%)", "")            total_times = total_times + times

if para_len - j >= total_times then break end

j = j - 1 end

local start = concat(para,"(",j)

if pcall(expr, start .. "*2") == false then return args end

to	      		= sub(val, find(val, "to", 1, true) + 2) para			= lib.split(to, ")", true)		para_len		= #para		j 				= 1		total_times		= 0

while j < para_len do           local _, times = gsub(para[j], "%(", "")            total_times = total_times + times

if j > total_times then break end

j = j + 1 end

local finish = concat(para,")",1,j)		local post_finish

if find(finish,"to",1,true) then post_finish = string_to_formula(finish)

if post_finish == finish then return args end elseif pcall(expr, finish .. "*2") == false then return args end

start = gsub(start, "([%-%+%*%/%^%(%)])", "%%%1") finish = gsub(finish, "([%-%+%*%/%^%(%)])", "%%%1") val   = gsub(val, start .. "to" .. finish, "(" .. start .. ")" .. "+(" .. "(" .. (post_finish or finish) .. ")" .. "-" .. "(" .. start .. ")" .. ")/(times-1)*(x-1)") end

return val end

local function gsub_x(val1,val2) if val1 == "" and val2 == "" then return 1 end end

function p.pp(frame) local args = (frame.args[1] and frame.args) or frame:getParent.args local userError 	= require('Dev:User error')

do --There're multiple user errors throught the function, which are used to hopefully impede users --from inserting junk inside the template. Can also be helpful in case the user mistypes and doesn't notice (i.e debug purpose) local accepted_args = mw.loadData("Module:Ability_progression/parameters") for i in pairs(args) do	   	if accepted_args[i] == nil then return userError("Parameter '" .. i .. "' is not accepted", "LuaError") end end if args["changedisplay"] and args["changedisplay"] ~= "true" then return userError("Invalid value for changedisplay. Can only be 'true'", "LuaError") end if args["showtype"] and args["showtype"] ~= "false" then return userError("Invalid value for showtype. Can only be 'false'", "LuaError") end end

local nowiki		= mw.text.nowiki local function gsub_nowiki(val1,val2,val3) --Currently used for "<" and ">" when necessary to not break the tooltip if val1 == "" and val3 == "" then return nowiki(val2) end end

local count, countstatic           = {30,30}, 30 local default_fill                 = 18

local displayformula               = args["formula"]

local key                          = args["key"] or "" local key1                         = args["key1"] local round                        = { (args["round"] ~= "false" and (args["round"] or 2)) or nil, (args["round1"] ~= "false" and (args["round1"] or 2)) or nil }

local label                        = args["label"] local label1                       = args["label1"] or args["type"]

local origtable                    = {lib.split(args[1] or "", ";", true), lib.split(args[2] or "", ";", true)} --saves values necessary for autogenerating / displaying the formula local save_formula_variables       = {{},{}}

local resulttable                  = {{},{}}

for orig_index = 1, 2 do		local orig = origtable[orig_index] local last_value = "" local i = 1 local len_resulttable = 0

while orig[i] and orig[i] ~= "" do       	orig[i] = gsub(orig[i],"([^%d ]?)([<>])([^%d ]?)",gsub_nowiki) local temp_find_to = find(orig[i], "to", 1, true) local temp_find_x = find(orig[i], "x", 1, true)

if (temp_find_to or temp_find_x) and find(orig[i], "<", 1, true) == nil then local start, finish, times local temp_find_by = find(orig[i], "by", 1, true) local temp_find_for = find(orig[i], "for", 1, true)

if temp_find_to then start = sub(orig[i], 1, temp_find_to - 1) if temp_find_by then finish, times = orig[i]:match".* *to *([^ ]*) *by *([^ ]*)$" elseif temp_find_for then finish, times = orig[i]:match".* *to *([^ ]*) *for *([^ ]*)$" else finish = orig[i]:match".* *to *([^ ]*)" end end start, finish, times = start or "", finish or "", times or "" local check_for_valid_input = true if temp_find_x == nil and pcall(expr, start .. "*2") and pcall(expr, finish .. "*2") and (pcall(expr, times .. "*2") or times == "") then start = expr(start) finish = expr(finish)

if times == "" then if save_formula_variables[orig_index].linear_filling or save_formula_variables[orig_index].x_filling then check_for_valid_input = false else save_formula_variables[orig_index] = {linear_filling = len_resulttable + 1, start = start, finish = finish, last_value = last_value} last_value = finish end else if save_formula_variables[orig_index].start == nil then save_formula_variables[orig_index] = {start = start, finish = finish} end

times = expr(times)

if temp_find_by then times = rounding(abs(finish - start) / times + 1, 0) if last_value == start then times = times - 1 end end

count[orig_index] = count[orig_index] - times

if count[orig_index] < 0 then return userError("Maximum size exceeded", "LuaError") end if last_value ~= start then len_resulttable = len_resulttable + 1 resulttable[orig_index][len_resulttable] = rounding(start, round[orig_index]) times = times - 1 end

for x = 1, times do                           local result = start + (finish-start) * x / times len_resulttable = len_resulttable + 1 resulttable[orig_index][len_resulttable] = rounding(result, round[orig_index]) end last_value = finish end else times = nil local useformula

if temp_find_for then useformula, times = orig[i]:match"(.*) *for *([^ ]*)$" end useformula, times = useformula or orig[i], times or "" if pcall(expr, times .. "*2") then times = expr(times) elseif times ~= "" then check_for_valid_input = false end

if check_for_valid_input and last_value ~= "" then useformula = gsub(useformula, "then", last_value,1) end

if check_for_valid_input and temp_find_to then useformula = string_to_formula(useformula) if times ~= "" then useformula = gsub(useformula, "times", tostring(times)) end end

if check_for_valid_input and pcall(expr, gsub(gsub(useformula, "([%.%d]?)x([%.%d]?)", gsub_x), "times", "2") .. "*2") then if times == "" then if save_formula_variables[orig_index].linear_filling or save_formula_variables[orig_index].x_filling then check_for_valid_input = false else save_formula_variables[orig_index] = {x_filling = len_resulttable + 1, useformula = useformula} last_value = "" end else if save_formula_variables[orig_index].useformula == nil then save_formula_variables[orig_index].useformula = useformula end count[orig_index] = count[orig_index] - times

if count[orig_index] < 0 then return userError("Maximum size exceeded", "LuaError") end

for x = 1, times do                               last_value = expr(gsub(useformula, "x", x)) len_resulttable = len_resulttable + 1 resulttable[orig_index][len_resulttable] = rounding(last_value, round[orig_index]) end end else check_for_valid_input = false end end

if check_for_valid_input == false then last_value = "" count[orig_index] = count[orig_index] - 1

if count[orig_index] < 0 then return userError("Maximum size exceeded", "LuaError") end len_resulttable = len_resulttable + 1 resulttable[orig_index][len_resulttable] = orig[i] end else count[orig_index] = count[orig_index] - 1

if count[orig_index] < 0 then return userError("Maximum size exceeded", "LuaError") end

local value = (last_value == "" and orig[i]) or gsub(orig[i], "then", last_value,1)

if pcall(expr, value .. "*2") then value = expr(value)

if find(orig[i+1] or "", "to",1,true) then last_value = "" else last_value = value end

value = rounding(value, round[orig_index]) elseif last_value ~= "" then last_value = "" value = orig[i] end len_resulttable = len_resulttable + 1 resulttable[orig_index][len_resulttable] = value end

i = i + 1 end end

local fill = {default_fill - #resulttable[1], default_fill - #resulttable[2]}

if default_fill - fill[1] >= default_fill - fill[2] then if save_formula_variables[1].linear_filling == nil and save_formula_variables[1].x_filling == nil then fill[2] = fill[2] - fill[1] end elseif save_formula_variables[2].linear_filling == nil and save_formula_variables[2].x_filling == nil then fill[1] = fill[1] - fill[2] end if fill[1] < 0 then fill[1] = 0 end if fill[2] < 0 then fill[2] = 0 end local insert = table.insert

for orig_index = 1, #save_formula_variables do		local to = save_formula_variables[orig_index] local times = fill[orig_index]

if times > 0 and (to.linear_filling or to.x_filling) then count[orig_index] = count[orig_index] - times

if count[orig_index] < 0 then return userError("Maximum size exceeded", "LuaError") end local len_resulttable = #resulttable[orig_index] local spaces_to_move = len_resulttable - (to.linear_filling or to.x_filling) + 1

for i = 0, spaces_to_move - 1 do	           --moving the latest values forward to leave space for the filled ones resulttable[orig_index][len_resulttable+times-i] = resulttable[orig_index][len_resulttable-i] end

if to.linear_filling then local start, finish, last_value = to.start, to.finish, to.last_value local fill_index = to.linear_filling-1

if last_value ~= start then fill_index = fill_index + 1 resulttable[orig_index][fill_index] = rounding(start, round[orig_index]) times = times - 1 end for x = 1, times do	               local result = start + (finish-start) * x / times fill_index = fill_index + 1 resulttable[orig_index][fill_index] = rounding(result, round[orig_index]) end elseif to.x_filling then local useformula = gsub(to.useformula, "times", times)

for x = 1, times do	               resulttable[orig_index][to.x_filling + x - 1] = rounding(expr(gsub(useformula, "x", x)), round[orig_index]) end end end end if #resulttable[2] ~= 0 and #resulttable[1] ~= #resulttable[2] then return userError("Variables are unmatched", "LuaError") end

local s = {} local s_len = 1 s[s_len] = '<span class="pp-tooltip" style="position:relative; border-bottom:1px dotted; cursor:help;'   if args["color"] then        s_len = s_len + 1        s[s_len] = " color:" .. require('Module:Color').keyword{args["color"]} .. ";"    end    s_len = s_len + 1    s[s_len] = '"' if label then s_len = s_len + 1 s[s_len] = ' data-bot_label="' .. label .. '"' end if label1 then s_len = s_len + 1 s[s_len] = ' data-top_label="' .. gsub(gsub(label1, "'", ""), "", "") .. '"' end

if displayformula then s_len = s_len + 1 s[s_len] = ' data-displayformula="' .. displayformula .. '"' elseif origtable[1][2] == nil then if save_formula_variables[1].useformula and resulttable[2][1] == nil then s_len = s_len + 1 s[s_len] = ' data-useformula="' .. save_formula_variables[1].useformula .. '"' elseif save_formula_variables[1].start and (resulttable[2][1] == nil or (save_formula_variables[2].start and origtable[2][2] == nil)) then s_len = s_len + 1 s[s_len] = (	           ' data-start="' .. (save_formula_variables[1].start or "") .. ";" .. (save_formula_variables[2].start or "") .. '"' .. 	            ' data-finish="' .. (save_formula_variables[1].finish or "") .. ";" .. (save_formula_variables[2].finish or "") .. '"') end end

if resulttable[1] then s_len = s_len + 1 s[s_len] = ' data-bot_values="' .. concat(resulttable[1],";") .. '"' end if resulttable[2] then s_len = s_len + 1 s[s_len] = ' data-top_values="' .. concat(resulttable[2],";") .. '"' end if key ~= "" then s_len = s_len + 1 s[s_len] = ' data-bot_key="' .. key .. '"' end if key1 then s_len = s_len + 1 s[s_len] = ' data-top_key="' .. key1 .. '"' end

s_len = s_len + 1 s[s_len] = ">"

if (countstatic - count[1] > 5 and args["changedisplay"] ~= "true") or (countstatic - count[1] <= 5 and args["changedisplay"] == "true") then s_len = s_len + 1 s[s_len] = fd(resulttable[1][1] or "NULL") .. key .. " &minus; " .. fd(resulttable[1][#resulttable[1]] or "NULL") .. key else s_len = s_len + 1 s[s_len] = fdmulti(concat(resulttable[1]," / ")) .. key end if args["showtype"] ~= "false" then s_len = s_len + 1 s[s_len] = " (based on " .. (args["type"] or args["label1"] or "level") .. ")" end s_len = s_len + 1 s[s_len] = " " return concat(s) end

function p.pptooltip(frame) local args = frame.args[1] and frame.args or frame:getParent.args

local label            = (args["bot_label"] == "" and "value") or args["bot_label"] local label1           = (args["top_label"] == "" and "level") or args["top_label"] local key              = args["bot_key"] local key1             = args["top_key"] local displayformula   = args["displayformula"] local useformula       = args["useformula"] local start 			= lib.split(args["start"], ";", true) start					= {(tonumber(start[1]) or ""), (tonumber(start[2]) or "")} local finish 			= lib.split(args["finish"], ";", true) finish					= {(tonumber(finish[1]) or ""), (tonumber(finish[2]) or "")}

local formulalabel1 	= gsub(label1, "[%[%]]", "") local orig 			= lib.split(args["bot_values"], ";", true) local orig1 			= lib.split(args["top_values"], ";", true) local s = {} local s_len = 0 local i = 1

while (orig1[i] and orig1[i] ~= "") or (orig[i] and orig[i] ~= "") do       s_len = s_len + 1 s[s_len] = ' ' if orig1[1] == "" then s_len = s_len + 1 s[s_len] = i       else s_len = s_len + 1 s[s_len] = fd(orig1[i] or "") if pcall(expr, (orig1[i] or "") .. "*2") then s_len = s_len + 1 s[s_len] = key1 end end

i = i + 1 end

s_len = s_len + 1 s[s_len] = '  ' .. mw.ustring.gsub(label, "^.", mw.ustring.upper) .. ' '   i = 1

while orig[i] and orig[i] ~= "" do       s_len = s_len + 1 s[s_len] = ' ' .. fd(orig[i])

if pcall(expr, orig[i] .. "*2") then s_len = s_len + 1 s[s_len] = key end

s_len = s_len + 1 s[s_len] = ' ' i = i + 1 end s_len = s_len + 1 s[s_len] = ' ' s = concat(s)

local formula = {} local len_formula = 0 local len_orig = #orig

if displayformula ~= "" then len_formula = len_formula + 1 formula[len_formula] = "Formula: " .. displayformula elseif orig1[1] ~= "" then if start[1] ~= "" and start[2] ~= "" then local scale = (finish[1] - start[1]) / (len_orig - 1) local scale1 = (finish[2] - start[2]) / (len_orig - 1)

len_formula = len_formula + 1 formula[len_formula] = "Formula: "

if start[1] ~= 0 then len_formula = len_formula + 1 formula[len_formula] = start[1] .. key

if scale >= 0 then len_formula = len_formula + 1 formula[len_formula] = "+" end end

if label1 == "level" then len_formula = len_formula + 1 formula[len_formula] = scale .. key .. " for every "

if abs(scale1) ~= 1 then len_formula = len_formula + 1 formula[len_formula] = scale1 end

len_formula = len_formula + 1 formula[len_formula] = key1 .. " " .. label1

if scale1 > 1 then len_formula = len_formula + 1 formula[len_formula] = "s" end

if start[2] ~= 0 and start[2] ~= 1 then len_formula = len_formula + 1 formula[len_formula] = " starting from " .. label1 .. " " .. start[2] .. key1 .. " and" else len_formula = len_formula + 1 formula[len_formula] = "," end

len_formula = len_formula + 1 formula[len_formula] = " capped at " .. label1 .. " " .. finish[2] .. key1 else local label1_len = #label1

len_formula = len_formula + 1 formula[len_formula] = scale .. key .. " for every "

if abs(scale1) ~= 1 then len_formula = len_formula + 1 formula[len_formula] = scale1 end

len_formula = len_formula + 1 formula[len_formula] = key1 .. " "

if scale1 ~= 1 then len_formula = len_formula + 1 formula[len_formula] = label1 elseif sub(formulalabel1, -1) == "s" then if sub(label1, -1) == "s" then len_formula = len_formula + 1 formula[len_formula] = sub(label1, 1, label1_len - 1) else len_formula = len_formula + 1 formula[len_formula] = sub(label1, 1, label1_len - 3) end else len_formula = len_formula + 1 formula[len_formula] = label1 end

if start[2] ~= 0 and start[2] ~= 1 then len_formula = len_formula + 1 formula[len_formula] = " starting from " .. start[2] .. key1 .. " "

if start[2] ~= 1 then len_formula = len_formula + 1 formula[len_formula] = label1 elseif sub(formulalabel1, -1) == "s" then if sub(label1, -1) == "s" then len_formula = len_formula + 1 formula[len_formula] = sub(label1, 1, label1_len - 1) else len_formula = len_formula + 1 formula[len_formula] = sub(label1, 1, label1_len - 3) end else len_formula = len_formula + 1 formula[len_formula] = label1 end

len_formula = len_formula + 1 formula[len_formula] = " and" else len_formula = len_formula + 1 formula[len_formula] = "," end

len_formula = len_formula + 1 formula[len_formula] = " capped at " .. finish[2] .. key1 .. " "

if finish[2] ~= 1 then len_formula = len_formula + 1 formula[len_formula] = label1 elseif sub(formulalabel1, -1) == "s" then if sub(label1, -1) == "s" then len_formula = len_formula + 1 formula[len_formula] = sub(label1, 1, label1_len - 1) else len_formula = len_formula + 1 formula[len_formula] = sub(label1, 1, label1_len - 3) end else len_formula = len_formula + 1 formula[len_formula] = label1 end end end else if start[1] ~= "" then local scale = (finish[1] - start[1]) / (len_orig - 1) len_formula = len_formula + 1 formula[len_formula] = "Formula: "

if tonumber(tostring(start[1])) == tonumber(tostring(scale)) then len_formula = len_formula + 1 formula[len_formula] = start[1] .. key .. "&#42;" .. label1 elseif len(sub(scale,find(scale,".",1,true) or 1)) <= 4 then len_formula = len_formula + 1 formula[len_formula] = (start[1] - scale) .. key

if scale >= 0 then len_formula = len_formula + 1 formula[len_formula] = "+"

if scale == 1 then len_formula = len_formula + 1 formula[len_formula] = label1 else len_formula = len_formula + 1 formula[len_formula] = scale .. key .. "&#42;" .. label1 end elseif scale == -1 then len_formula = len_formula + 1 formula[len_formula] = "-" .. label1 else len_formula = len_formula + 1 formula[len_formula] = scale .. key .. "&#42;" .. label1 end else len_formula = len_formula + 1 formula[len_formula] = start[1] .. key if finish[1] - start[1] >= 0 then len_formula = len_formula + 1 formula[len_formula] = "+" end

len_formula = len_formula + 1 formula[len_formula] = (finish[1] - start[1]) .. key .. "/" .. (len_orig - 1) .. "&#42;(" .. label1 .. "-1)" end elseif useformula ~= "" then len_formula = len_formula + 1 formula[len_formula] = "Formula: " .. useformula end end formula = concat(formula) if displayformula == "" then formula = gsub(gsub(gsub(gsub(gsub(formula, "%/", " &divide; "), "%*", "&#42;"), "&#42;", " &times; "), "%+", " + "), "%-", " &minus; ")

if useformula ~= "" then formula = gsub(formula, "x", label1) end else formula = gsub(gsub(gsub(gsub(gsub(formula, "%/", "&divide;"), "%*", "&#42;"), "&#42;", "&times;"), "%+", "+"), "%-", "&minus;") end formula = fdmulti(formula)

return (		'' .. formula ..        ' ' ..         ' ' .. mw.ustring.gsub(label1, "^.", mw.ustring.upper) ..        s .. " "    ) end

function p.ap(frame) local args = lib.frameArguments(frame)

local userError = require('Dev:User error') local orig 	= args local count 	= 6 local round 	= args["round"] or nil local fill		= (args["skill"] ~= "R" and 5) or 3

local resulttable = {} local len_resulttable = 0 local i = 1

while orig[i] and orig[i] ~= "" do   	local temp_find_to = find(orig[i], "to", 1, true) local temp_find_x = find(orig[i], "x", 1, true)

if (temp_find_to or temp_find_x) and find(orig[i], "<", 1, true) == nil then local start, finish, times if temp_find_to then start = sub(orig[i], 1, temp_find_to - 1) finish, times = orig[i]:match".* *to *([^ ]*) *([^ ]*)$" end

start, finish, times = start or "", finish or "", times or "" local check_for_times = false if temp_find_x == nil and pcall(expr, start .. "*2") and pcall(expr, finish .. "*2") and (pcall(expr, times .. "*2") or times == "") then check_for_times = true start = expr(start) finish = expr(finish)

if times == "" then if fill ~= 0 then times = fill fill = 0 else check_for_times = false end else times = expr(times) end if check_for_times then count = count - times

if count < 0 then return userError("Maximum size exceeded", "LuaError") end local scale = (finish - start) / (times - 1) local formula = start - scale

for x = 1, times do                       formula = formula + scale len_resulttable = len_resulttable + 1 resulttable[len_resulttable] = rounding(formula, round) end end else local useformula,times = orig[i]:match"(.*[0-9x%)]) +([^ ]*)$"				useformula, times = useformula or orig[i], times or ""				if pcall(expr, times .. "*2") then					check_for_times = true					times = expr(times)				elseif times == "" and fill ~= 0 then					check_for_times = true                   times = fill                    fill = 0	            end

local _,occurences = gsub(orig[i],"to","")

if check_for_times and occurences > 0 then useformula = gsub(string_to_formula(useformula),"times",tostring(times)) end

if check_for_times and pcall(expr, gsub(useformula, "([%.%d]?)x([%.%d]?)", gsub_x) .. "*2") then count = count - times

if count < 0 then return userError("Maximum size exceeded", "LuaError") end

for x = 1, times do                   	len_resulttable = len_resulttable + 1 resulttable[len_resulttable] = rounding(expr(gsub(useformula, "x", x)), round) end else check_for_times = false end end

if check_for_times == false then count = count - 1

if count < 0 then return userError("Maximum size exceeded", "LuaError") end len_resulttable = len_resulttable + 1 resulttable[len_resulttable] = orig[i] end else count = count - 1

if count < 0 then return userError("Maximum size exceeded", "LuaError") end

local value = (pcall(expr, orig[i] .. "*2") and rounding(orig[i], round)) or orig[i]

len_resulttable = len_resulttable + 1 resulttable[len_resulttable] = value end

i = i + 1 end

return fdmulti(concat(resulttable," / ")) end

return p

-- --