Module:RecursiveExchange

From WIDEVERSE Wiki
Jump to navigation Jump to search

Documentation for this module may be created at Module:RecursiveExchange/doc

-- <nowiki>
-- Calculates the exchange price of an item recursively:
-- If the item is tradeable return the GE price
-- If it is not and can be made from other items return the sum of the price of the ingredients

local recipes = require("Module:Recipes/Data")

local price = require("Module:ExchangeLite").price
local addcommas = require("Module:Addcommas")._add
local yesno = require( 'Module:Yesno' )

local p = {}

-- See p._price in [[Module:Exchange]]
-- Returns 0 if the item doesn't have any known combinations or if it isn't tradeable
function p._price(item, multi, format, return_nan, is_potion_guess)
	multi = type(multi) == "number" and multi or 1
    format = type(format) == "boolean" and format or false

    -- Note: We can't use and & or when we default to true
    if type(return_nan) ~= "boolean" then
    	return_nan = true
    end

    is_potion_guess = type(is_potion_guess) == "boolean" and is_potion_guess or false

    local ge_price = price(item)
	if ge_price then
        ge_price = ge_price * multi
        if format then
            return addcommas(ge_price)
        end
		return ge_price
	end

	local recipe = recipes[item]

	if recipe == nil then
		if is_potion_guess then
			return 0/0
		elseif item:match(" %(%d%)$") then
			local potion_name = item:sub(1, -4)
			local doses = tonumber(item:sub(-2, -2))
			for i=1, 6 do
				local name = potion_name .. "(" .. i .. ")"
				local result = p._price(name, multi, false, false, true)

				if result == result then
					mw.log("Calculated price of " .. item .. " based on the price of " .. name)
					return result * (doses / i)
				end
			end
		end

		mw.log("Couldn't get price of " .. item)
		return return_nan and 0/0 or 0
	end

	local amount_created = recipe[1]
	local ingredients = recipe[2]

	local sum = 0
	for _, ingredient in ipairs(ingredients) do
		local n = ingredient[1]
		local name = ingredient[2]

		sum = sum + p._price(name, n, false, false)
	end

	local ret = (sum * multi) / amount_created

	if format then
		ret = addcommas(ret)
	end

	return ret
end

--
-- {{GEPR}}
--
-- @example {{GEPR|<item>|<multi>}}
--d
function p.price( frame )
    -- usage: {{GEPR|item|format|multi}} or {{GEPR|item|multi}}
    local args = frame.args
    local pargs = frame:getParent().args
    local item = pargs[1]

    if item then
        item = mw.text.trim( item )
    else
        error( '"item" argument not specified', 0 )
    end

    -- default to formatted for backwards compatibility with old GE templates
    local format = true
    local multi = 1

    -- format is set with #invoke
    -- so set it first to allow it to be overridden by template args
    if args.format ~= nil then
        format = yesno( args.format )
    end

    if tonumber( pargs[2] ) ~= nil then
        multi = tonumber( pargs[2] )

    -- indicated someone is trying to pass an equation as a mulitplier
    -- known use cases are fractions, but pass it to #expr to make sure it's handled correctly
    elseif pargs[2] ~= nil and mw.ustring.find( pargs[2], '[/*+-]' ) then
        multi = tonumber( frame:preprocess( '{{#expr:' .. pargs[2] .. '}}' ) )

    -- uses elseif to prevent something like {{GEP|Foo|1}}
    -- causing a formatted output, as 1 casts to true when passed to yesno
    elseif type( yesno( pargs[2] ) ) == 'boolean' then
        format = yesno( pargs[2] )

        if tonumber( pargs[3] ) ~= nil then
            multi = tonumber( pargs[3] )
        end
    end

    return p._price( item, multi, format )
end

return p
-- </nowiki>