Module:Reward

local List = require 'Module:ListUtil' local Hash = require 'Module:HashUtil' local parseArgs = require 'Module:ObjectArg'.parse

local normalizeReward = function (reward) if type(reward) ~= 'table' then return nil, 'Reward definition must be a hash or a list of hashes.' end if (reward.kind or reward.hero or reward.rarity or reward.seal or reward.accessory or reward.fbrank) and not reward[1] then reward = {reward} end for _, v in ipairs(reward) do		if type(v) ~= 'table' then return nil, 'Reward definition must be a hash or a list of hashes.' end if v.hero and v.fbrank then v.kind = 'Forging Bonds conversation' v.count = 1 elseif v.hero and v.rarity then v.kind = 'Hero' v.count = 1 elseif v.seal then v.kind = 'Sacred Seal' v.count = 1 elseif v.accessory then v.kind = 'Accessory' v.count = 1 elseif v.kind then v.count = v.count or 1 else return nil, "Missing 'kind' parameter." end end return reward, nil end

local parseReward = function (objstr) local reward, err = objstr, nil if type(reward) ~= 'table' then reward, err = parseArgs(tostring(objstr or '')) if not reward then return nil, err end reward, err = normalizeReward(reward) end return reward, err end

local defineReward = function (reward, subtemplate, opts, frame) if mw.title.getCurrentTitle.namespace ~= 0 then return end

opts = opts or {} frame = frame or mw.getCurrentFrame

for _, r in ipairs(reward) do		local args = { count = r.count, unit = r.hero, rarity = r.rarity, seal = r.seal, accessory = r.accessory, fbrank = r.fbrank, item = not (r.hero or r.rarity or r.fbrank or r.seal or r.accessory) and r.kind or nil, }		for k, v in pairs(opts) do			args[k] = v		end frame:expandTemplate {title = 'RewardDefinition/' .. subtemplate, args = args} end end

local itemKey = function (r) return r.kind .. '\0' .. (		r.hero and (r.rarity and (r.hero .. '\0' .. r.rarity) or r.fbrank and (r.hero .. '\0' .. r.fbrank)) or		r.seal or r.accessory or '') end

local compareRewards = function (x, y)	local counts = {}

for _, v in ipairs(x) do		local k = itemKey(v) counts[k] = (counts[k] or 0) + (v.count or 1) end

for _, v in ipairs(y) do		local k = itemKey(v) counts[k] = (counts[k] or 0) - (v.count or 1) end

if Hash.all(counts, function (v) return v == 0 end) then return 0 elseif Hash.all(counts, function (v) return v <= 0 end) then return -1 elseif Hash.all(counts, function (v) return v >= 0 end) then return 1 end end

local bestReward = function (t) local best = {}

for _, r in ipairs(t) do		List.keep_if(best, function (v) local cmp = compareRewards(v, r); return not (cmp and cmp < 0) end) if List.none(best, function (v) local cmp = compareRewards(v, r); return cmp and cmp >= 0 end) then best[#best + 1] = r		end end

if #best == 1 then return best[1] end end

return { normalize = normalizeReward, parse = parseReward, define = defineReward, compare = compareRewards, best = bestReward, }