Module:FetchItemStats

From RuneRealm Wiki
Jump to navigation Jump to search
Module documentation
This documentation is transcluded from Module:FetchItemStats/doc. [edit] [history] [purge]
Module:FetchItemStats requires Module:Exchange.
Module:FetchItemStats requires Module:Yesno.
Module:FetchItemStats is required by Module:Equipment.

This module provides three functions that make obtaining an item's information easier.

This module is a helper module to be used by other modules; it may not designed to be invoked directly. See RuneScape:Lua/Helper modules for a full list and more information. For a full list of modules using this helper click here

FunctionTypeUse
defaultVersion(pagename)String, StringReturns a string of the default version (format: Pagename#Versionname) that can be used for further SMW searches. Also returns a wikilink to the matched page name (following redirects from the given pagename, as the second return value.
value(item_smwname)NumberReturns the item value for either the specified SMW version (if the given name links to a specific item), or the version that is shown on the page by default (the same version as returned by defaultVersion.
equipmentStats(
{item1_smwname, ...},
{sort_key1, ...},
{sort_order1, ...}
)
{ Table1, Table2, ... }Fetches all item stats for a list of given SMW names. If an ambiguous item name is given anywhere in this list (i.e. one that has different versions), this function will not automatically pick the one that would otherwise be chosen by defaultVersion. A specific SMW name needs to be entered for this function.

Sort keys and sort orders may be provided as optional second and third arguments. No custom sorting will be applied if these arrays are empty or nil. Note that Semantic MediaWiki queries automatically sort the output pages based on alphabetical pagename order. If no sorting should be applied whatsoever, set sort_key1 to something recognised as being falsy (e.g. {'no'}).

Possible sorting orders are: 'ascending', 'asc', 'descending', 'desc', 'reverse', 'random' and 'rand'.

The returned stats are formatted as a Table containing a single Table for each of the items, in the order given by the sort keys, or the default SMW sorting. The stats that are returned in each of these Tables are:

{
    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'
}

-- 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