Module:FetchItemStats

From Roat Pkz
Revision as of 03:07, 12 May 2022 by Wilderness>Theslamprogram (Add is members only prop to equipment stats)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search

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

-- Note: This module is not meant to be invoked directly, and instead is intended to be used from other modules.
local exchange = require('Module:Exchange')
local yesno = require('Module:Yesno')

local p = {}

-- Obtain information about which version of an item is the default version of the item
-- if no switch infoobox is present, the item name itself will be returned.
-- The second return value is the actual pagename of the page that is retrieved in the SMW call, taking redirects into account.
function p.defaultVersion(itemname)
	if not itemname or itemname == '' then
		return nil
	end
	local item = mw.smw.ask({"[[" .. itemname .. "]]", "?Default version"})
	if not item then
		return nil
	end
	item = item[1]
	local defver = item['Default version']
	if defver then
		return itemname .. '#' .. defver, item[1]
	else
		return itemname, item[1]
	end
end

-- Get item value from its page based on name.
-- If a switch infobox is present on the entered page, the price for the item version that is shown by default is fetched.
function p.value(itemname)
	if not itemname or itemname == '' then
		return 0
	end
	local item = mw.smw.ask({"[[" .. itemname .. "]]", "?Default version", "?Value"})
	if not item then
		return -1
	end
	item = item[1]
	local value = 0
	if item['Value'] == nil then
	    local itemversion = item['Default version']
	    if not itemversion then
	    	return 0
	    end
	    local default = mw.smw.ask({"[[" .. itemname .. "#" .. itemversion .. "]]", "?Value"})[1]
	    if default['Value'] ~= nil then
	        value = default['Value']
	    end
	else
	    value = item['Value']
	end
	return value
end

function undoSort(pages, statslist)
	local lookup = {}
	for i, page in ipairs(pages) do
		lookup[string.lower(page)] = i
	end
	local ret = {}
	for _, stats in ipairs(statslist) do
		local i = lookup[string.lower(stats[1])]
		-- if i==nil then an item was referred to by their redirect page; cannot undo sorting
		assert(i ~= nil, string.format("Cannot use `sort=no` for redirect pages. Ensure the item \"%s\" is a direct link to the page", stats[1]))
		ret[i] = stats
	end
	return ret
end

-- Fetches equipment stats, image, and weight for a list of pages. 
-- First argument: a list of pages
-- Second argument: the sort keys for the returned data (array of keys); if equal to {'no'} the order used in the first parameter is used.
-- Third argument: the order in which these sort keys should be (asc / desc / reverse / random)
function p.equipmentStats(pages, keys, orders)
	-- mw.logObject(keys)
	if keys == nil then
		keys = {}
		orders = {}
	elseif orders == nil then
		orders = {}
	end
    local prop = {
        astab  = 'Stab attack bonus',
        aslash = 'Slash attack bonus',
        acrush = 'Crush attack bonus',
        amagic = 'Magic attack bonus',
        arange = 'Range attack bonus',
        dstab  = 'Stab defence bonus',
        dslash = 'Slash defence bonus',
        dcrush = 'Crush defence bonus',
        dmagic = 'Magic defence bonus',
        drange = 'Range defence bonus',
        str    = 'Strength bonus',
        mdmg   = 'Magic Damage bonus',
        rstr   = 'Ranged Strength bonus',
        prayer = 'Prayer bonus',
        weight = 'Weight',
        image  = 'Image',
        subobj = 'Has subobject',
        membs  = "Is members only"
    }

    local query = {}

    -- Build query
    table.insert(query, string.format('[[%s]]', table.concat(pages, ' || ')))
    table.insert(query, '?=#-')
    for k, p in pairs(prop) do
        table.insert(query, string.format('?%s #- = %s', p, k))
    end
    if #keys > 0 and yesno(keys[1], true) then -- do not sort if keys[1] is 'no'
        local sprops = {}
        for _, k in ipairs(keys) do
            table.insert(sprops, prop[k])
        end
        query.sort = table.concat(sprops, ', ')
    end
    if #orders > 0 then
        query.order = table.concat(orders, ', ')
    end
    query.offset = 0
    query.limit = 500

    -- Fetch the data
    -- mw.logObject(query)
    local t1 = os.clock()
    local smwdata = mw.smw.ask(query)
    local t2 = os.clock()

    local smw_max_conditions = 16

    if not smwdata or #smwdata == 0 then
        if #pages > smw_max_conditions then
            error('smw query failed (your table probably have too many items)')
        end
    
        smwdata = {}
    end

    -- Post-process the data
    if keys[1] and not yesno(keys[1], true) then
    	smwdata = undoSort(pages, smwdata)
	end

    local data = {}

    for _, i in ipairs(smwdata) do 
        local dl = i
        dl.name = dl[1]
        dl[1] = nil
        if type(dl.image) == 'table' then
            dl.image = dl.image[1]
        end
        table.insert(data, dl)
    end

    -- Statistics
    local smwstats = {
        offset = query.offset,
        limit  = query.limit,
        found  = #smwdata,
        time   = (t2 - t1) * 1000
    }

    --[[ mw.log(string.format('SMW: Found %i, offset %i, limit %i, time elapsed %.3f ms.', 
        smwstats.found, smwstats.offset, smwstats.limit, smwstats.time))
        --]]

    return data
end

return p