<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://wiki.runerealm.org/index.php?action=history&amp;feed=atom&amp;title=Module%3ABestiary</id>
	<title>Module:Bestiary - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.runerealm.org/index.php?action=history&amp;feed=atom&amp;title=Module%3ABestiary"/>
	<link rel="alternate" type="text/html" href="https://wiki.runerealm.org/index.php?title=Module:Bestiary&amp;action=history"/>
	<updated>2026-04-30T17:19:31Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.41.1</generator>
	<entry>
		<id>https://wiki.runerealm.org/index.php?title=Module:Bestiary&amp;diff=34035&amp;oldid=prev</id>
		<title>Alex: Created page with &quot;require(&#039;strict&#039;)  local p = {}  local yesno = require(&#039;Module:Yesno&#039;) local pt = require(&#039;Module:Paramtest&#039;) local arr = require(&#039;Module:Array&#039;) local pagelisttools = require(&#039;Module:PageListTools&#039;) local pageswithcats = pagelisttools.pageswithcats  local smwstats = {}  -- Formats a table header function p.header(tbl, verbose)     local tr = tbl:tag(&#039;tr&#039;)         :tag(&#039;th&#039;):attr(&#039;colspan&#039;, &#039;2&#039;):wikitext(&#039;Monster&#039;):done()         :tag(&#039;th&#039;):wikitext(&#039;Members&#039;):done()...&quot;</title>
		<link rel="alternate" type="text/html" href="https://wiki.runerealm.org/index.php?title=Module:Bestiary&amp;diff=34035&amp;oldid=prev"/>
		<updated>2024-10-15T17:20:02Z</updated>

		<summary type="html">&lt;p&gt;Created page with &amp;quot;require(&amp;#039;strict&amp;#039;)  local p = {}  local yesno = require(&amp;#039;Module:Yesno&amp;#039;) local pt = require(&amp;#039;Module:Paramtest&amp;#039;) local arr = require(&amp;#039;Module:Array&amp;#039;) local pagelisttools = require(&amp;#039;Module:PageListTools&amp;#039;) local pageswithcats = pagelisttools.pageswithcats  local smwstats = {}  -- Formats a table header function p.header(tbl, verbose)     local tr = tbl:tag(&amp;#039;tr&amp;#039;)         :tag(&amp;#039;th&amp;#039;):attr(&amp;#039;colspan&amp;#039;, &amp;#039;2&amp;#039;):wikitext(&amp;#039;Monster&amp;#039;):done()         :tag(&amp;#039;th&amp;#039;):wikitext(&amp;#039;Members&amp;#039;):done()...&amp;quot;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;require(&amp;#039;strict&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
local p = {}&lt;br /&gt;
&lt;br /&gt;
local yesno = require(&amp;#039;Module:Yesno&amp;#039;)&lt;br /&gt;
local pt = require(&amp;#039;Module:Paramtest&amp;#039;)&lt;br /&gt;
local arr = require(&amp;#039;Module:Array&amp;#039;)&lt;br /&gt;
local pagelisttools = require(&amp;#039;Module:PageListTools&amp;#039;)&lt;br /&gt;
local pageswithcats = pagelisttools.pageswithcats&lt;br /&gt;
&lt;br /&gt;
local smwstats = {}&lt;br /&gt;
&lt;br /&gt;
-- Formats a table header&lt;br /&gt;
function p.header(tbl, verbose)&lt;br /&gt;
    local tr = tbl:tag(&amp;#039;tr&amp;#039;)&lt;br /&gt;
        :tag(&amp;#039;th&amp;#039;):attr(&amp;#039;colspan&amp;#039;, &amp;#039;2&amp;#039;):wikitext(&amp;#039;Monster&amp;#039;):done()&lt;br /&gt;
        :tag(&amp;#039;th&amp;#039;):wikitext(&amp;#039;Members&amp;#039;):done()&lt;br /&gt;
        :tag(&amp;#039;th&amp;#039;):wikitext(&amp;#039;[[File:Attack style icon.png|link=|Combat level]]&amp;#039;):done()&lt;br /&gt;
        :tag(&amp;#039;th&amp;#039;):wikitext(&amp;#039;[[File:Hitpoints icon.png|link=|Hitpoints]]&amp;#039;):done()&lt;br /&gt;
        :tag(&amp;#039;th&amp;#039;):wikitext(&amp;#039;[[File:Attack icon.png|link=|Attack level]]&amp;#039;):done()&lt;br /&gt;
        :tag(&amp;#039;th&amp;#039;):wikitext(&amp;#039;[[File:Defence icon.png|link=|Defence level]]&amp;#039;):done()&lt;br /&gt;
        :tag(&amp;#039;th&amp;#039;):wikitext(&amp;#039;[[File:Magic icon.png|link=|Magic level]]&amp;#039;):done()&lt;br /&gt;
        :tag(&amp;#039;th&amp;#039;):wikitext(&amp;#039;[[File:Ranged icon.png|link=|Ranged level]]&amp;#039;):done()&lt;br /&gt;
        :tag(&amp;#039;th&amp;#039;):wikitext(&amp;#039;[[File:White dagger.png|link=|Stab defence]][[File:Defence icon.png|link=|alt=]]&amp;#039;):done()&lt;br /&gt;
        :tag(&amp;#039;th&amp;#039;):wikitext(&amp;#039;[[File:White scimitar.png|link=|Slash defence]][[File:Defence icon.png|link=|alt=]]&amp;#039;):done()&lt;br /&gt;
        :tag(&amp;#039;th&amp;#039;):wikitext(&amp;#039;[[File:White warhammer.png|link=|Crush defence]][[File:Defence icon.png|link=|alt=]]&amp;#039;):done()&lt;br /&gt;
        :tag(&amp;#039;th&amp;#039;):wikitext(&amp;#039;[[File:Magic icon.png|link=|Magic defence]][[File:Defence icon.png|link=|alt=]]&amp;#039;):done()&lt;br /&gt;
        :tag(&amp;#039;th&amp;#039;):wikitext(&amp;#039;[[File:Steel dart.png|link=|Light Ranged defence]][[File:Defence icon.png|link=|alt=]]&amp;#039;):done()&lt;br /&gt;
        :tag(&amp;#039;th&amp;#039;):wikitext(&amp;#039;[[File:Steel arrow.png|link=|Standard Ranged defence]][[File:Defence icon.png|link=|alt=]]&amp;#039;):done()&lt;br /&gt;
        :tag(&amp;#039;th&amp;#039;):wikitext(&amp;#039;[[File:Steel bolts.png|link=|Heavy Ranged defence]][[File:Defence icon.png|link=|alt=]]&amp;#039;):done()&lt;br /&gt;
        &lt;br /&gt;
    if verbose then&lt;br /&gt;
        tr:tag(&amp;#039;th&amp;#039;):wikitext(&amp;#039;[[File:Slayer icon.png|link=|Slayer level]]&amp;#039;):done()&lt;br /&gt;
          :tag(&amp;#039;th&amp;#039;):wikitext(&amp;#039;&amp;lt;abbr title=&amp;quot;Slayer experience&amp;quot;&amp;gt;XP&amp;lt;/span&amp;gt;&amp;#039;):done()&lt;br /&gt;
          :tag(&amp;#039;th&amp;#039;):css(&amp;#039;text-align&amp;#039;, &amp;#039;left&amp;#039;):wikitext(&amp;#039;Slayer categories&amp;#039;):done()&lt;br /&gt;
          :tag(&amp;#039;th&amp;#039;):css(&amp;#039;text-align&amp;#039;, &amp;#039;left&amp;#039;):wikitext(&amp;#039;Assigned by&amp;#039;):done()&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Main entrypoint&lt;br /&gt;
function p.main(frame)&lt;br /&gt;
    local args = frame:getParent().args&lt;br /&gt;
    return p._main(args)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p._main(args)&lt;br /&gt;
    local mambo = {&amp;#039;Members&amp;#039;, &amp;#039;F2P&amp;#039;, &amp;#039;All&amp;#039;}&lt;br /&gt;
    local slayer_masters = { &amp;#039;Spria&amp;#039;, &amp;#039;Turael&amp;#039;, &amp;#039;Krystilia&amp;#039;, &amp;#039;Mazchna&amp;#039;, &amp;#039;Vannaka&amp;#039;, &amp;#039;Chaeldar&amp;#039;, &amp;#039;Konar quo Maten&amp;#039;, &amp;#039;Nieve&amp;#039;, &amp;#039;Steve&amp;#039;, &amp;#039;Duradel&amp;#039; }&lt;br /&gt;
    local pattern_alpha = &amp;#039;^%a$&amp;#039;&lt;br /&gt;
&lt;br /&gt;
    -- Fetch and validate all input parameters&lt;br /&gt;
    local fromlevel = tonumber(pt.default_to(args[&amp;#039;fromlevel&amp;#039;], &amp;#039;1&amp;#039;))&lt;br /&gt;
    local tolevel = tonumber(pt.default_to(args[&amp;#039;tolevel&amp;#039;], &amp;#039;1&amp;#039;))&lt;br /&gt;
    local fromletter = string.upper(pt.default_to(args[&amp;#039;fromletter&amp;#039;], &amp;#039;A&amp;#039;))&lt;br /&gt;
    local toletter = string.upper(pt.default_to(args[&amp;#039;toletter&amp;#039;], &amp;#039;A&amp;#039;))&lt;br /&gt;
    local mems = pt.default_to(args[&amp;#039;mems&amp;#039;], &amp;#039;All&amp;#039;)&lt;br /&gt;
    local assignedby = pt.default_to(args[&amp;#039;assignedby&amp;#039;], &amp;#039;&amp;#039;)&lt;br /&gt;
    local onlycat = pt.default_to(args[&amp;#039;onlycat&amp;#039;], &amp;#039;&amp;#039;)&lt;br /&gt;
    local attribute = pt.default_to(args[&amp;#039;attribute&amp;#039;], &amp;#039;&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
    local ba = {&lt;br /&gt;
        levelselect = true,&lt;br /&gt;
        levelsort   = true,&lt;br /&gt;
        slayeronly  = false,&lt;br /&gt;
        verbose     = false,&lt;br /&gt;
        showstats   = false,&lt;br /&gt;
        disco       = false,&lt;br /&gt;
        quest       = true,&lt;br /&gt;
        dmm         = true,&lt;br /&gt;
        cache       = false&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    for k, b in pairs(ba) do&lt;br /&gt;
        if pt.has_content(args[k]) then&lt;br /&gt;
            ba[k] = yesno(args[k])&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    if pt.has_content(args[&amp;#039;mems&amp;#039;]) and not arr.contains(mambo, mw.text.trim(args[&amp;#039;mems&amp;#039;])) then&lt;br /&gt;
        error(&amp;#039;mems parameter has invalid value&amp;#039;)&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    if pt.has_content(args[&amp;#039;assignedby&amp;#039;]) and not arr.contains(slayer_masters, mw.text.trim(args[&amp;#039;assignedby&amp;#039;])) then&lt;br /&gt;
        error(&amp;#039;assignedby parameter has invalid value&amp;#039;)&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    if ba[&amp;#039;levelselect&amp;#039;] then&lt;br /&gt;
        if pt.is_empty(args[&amp;#039;fromlevel&amp;#039;]) or not fromlevel then&lt;br /&gt;
            error(&amp;#039;parameter fromlevel is invalid&amp;#039;)&lt;br /&gt;
        end&lt;br /&gt;
&lt;br /&gt;
        if pt.is_empty(args[&amp;#039;tolevel&amp;#039;]) or not tolevel then&lt;br /&gt;
            error(&amp;#039;parameter tolevel is invalid&amp;#039;)&lt;br /&gt;
        end&lt;br /&gt;
&lt;br /&gt;
        assert(tolevel &amp;gt;= fromlevel, &amp;#039;parameter tolevel must be greater than or equal to fromlevel&amp;#039;)&lt;br /&gt;
    else&lt;br /&gt;
        if pt.is_empty(args[&amp;#039;fromletter&amp;#039;]) or not fromletter:match(pattern_alpha) then&lt;br /&gt;
            error(&amp;#039;parameter fromletter is invalid&amp;#039;)&lt;br /&gt;
        end&lt;br /&gt;
&lt;br /&gt;
        if pt.is_empty(args[&amp;#039;toletter&amp;#039;]) or not toletter:match(pattern_alpha) then&lt;br /&gt;
            error(&amp;#039;parameter toletter is invalid&amp;#039;)&lt;br /&gt;
        end&lt;br /&gt;
&lt;br /&gt;
        assert(toletter &amp;gt;= fromletter, &amp;#039;parameter toletter must be greater than or equal to fromletter&amp;#039;)&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    -- Gather the data&lt;br /&gt;
    local fulldata = p.loadData(fromlevel, tolevel, fromletter, toletter, ba[&amp;#039;levelselect&amp;#039;], mems, ba[&amp;#039;slayeronly&amp;#039;], onlycat, attribute, assignedby, ba[&amp;#039;verbose&amp;#039;])&lt;br /&gt;
	mw.logObject(fulldata)&lt;br /&gt;
    local data = p.filterData(fulldata, ba[&amp;#039;disco&amp;#039;], ba[&amp;#039;quest&amp;#039;], ba[&amp;#039;dmm&amp;#039;], ba[&amp;#039;cache&amp;#039;])&lt;br /&gt;
    mw.logObject(data)&lt;br /&gt;
    local fulldata = nil&lt;br /&gt;
	&lt;br /&gt;
    if ba[&amp;#039;levelsort&amp;#039;] then&lt;br /&gt;
		pcall(function()&lt;br /&gt;
        	table.sort(data, function(a, b)&lt;br /&gt;
        		return a[&amp;#039;level&amp;#039;] &amp;lt; b[&amp;#039;level&amp;#039;]&lt;br /&gt;
        		-- example fix in case you were directed to the line above by an error:&lt;br /&gt;
				-- [[Special:Diff/14325110]]&lt;br /&gt;
        	end)&lt;br /&gt;
        end)&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    -- Format the output page&lt;br /&gt;
    local div = mw.html.create(&amp;#039;div&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
    if #data == 0 then&lt;br /&gt;
        div:wikitext(&amp;#039;Search yielded no results.&amp;#039;)&lt;br /&gt;
        return div&lt;br /&gt;
    elseif ba[&amp;#039;showstats&amp;#039;] then&lt;br /&gt;
        div:wikitext(string.format(&amp;#039;Search yielded %i results.&amp;#039;, #data))&lt;br /&gt;
        if smwstats[&amp;#039;found&amp;#039;] == smwstats[&amp;#039;limit&amp;#039;] then&lt;br /&gt;
            div:wikitext(string.format(&amp;#039; Your search might have been too large and have been truncated as a result.&amp;#039;))&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    local tbl = div:tag(&amp;#039;table&amp;#039;):addClass(&amp;#039;wikitable sortable&amp;#039;)&lt;br /&gt;
        :addClass(&amp;#039;align-center-1 align-left-2 align-left-3 align-center-4 align-center-5&amp;#039;)&lt;br /&gt;
        :addClass(&amp;#039;align-center-6 align-center-7 align-center-8 align-center-9&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
    if ba[&amp;#039;verbose&amp;#039;] then&lt;br /&gt;
        tbl:addClass(&amp;#039;align-center-10 align-center-11 align-left-12 align-left-13&amp;#039;)&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    p.header(tbl, ba[&amp;#039;verbose&amp;#039;])&lt;br /&gt;
&lt;br /&gt;
    -- Render rows&lt;br /&gt;
    &lt;br /&gt;
    local function makeRow(entry)&lt;br /&gt;
        local name = mw.text.split(entry[&amp;#039;name&amp;#039;], &amp;#039;#&amp;#039;, true)&lt;br /&gt;
        if name[2] then&lt;br /&gt;
        	name[2] = name[2]:gsub(&amp;#039;_&amp;#039;, &amp;#039; &amp;#039;)&lt;br /&gt;
        end&lt;br /&gt;
        local tr = mw.html.create(&amp;#039;tr&amp;#039;)&lt;br /&gt;
            :tag(&amp;#039;td&amp;#039;):css(&amp;#039;height&amp;#039;, &amp;#039;64px&amp;#039;):wikitext(entry[&amp;#039;image&amp;#039;] and string.format(&amp;#039;[[%s|link=|64x64px|%s%s]]&amp;#039;, entry[&amp;#039;image&amp;#039;], name[1], (name[2] and &amp;#039; - &amp;#039; .. name[2]) or &amp;#039;&amp;#039;) or &amp;#039;&amp;#039; ):done()&lt;br /&gt;
            :tag(&amp;#039;td&amp;#039;):wikitext( string.format(&amp;#039;[[%s|%s]]%s&amp;#039;, entry[&amp;#039;name&amp;#039;], name[1], name[2] and &amp;#039;&amp;lt;br/&amp;gt;&amp;lt;i&amp;gt;&amp;#039; .. name[2] .. &amp;#039;&amp;lt;/i&amp;gt;&amp;#039; or &amp;#039;&amp;#039;) ):done()&lt;br /&gt;
            :tag(&amp;#039;td&amp;#039;):wikitext(entry[&amp;#039;members&amp;#039;] and &amp;#039;[[File:Member icon.png|center|link=Members|alt=Members]]&amp;#039; or &amp;#039;[[File:Free-to-play icon.png|center|link=Free-to-play|alt=Free-to-play]]&amp;#039;):done()&lt;br /&gt;
            :tag(&amp;#039;td&amp;#039;):wikitext(entry[&amp;#039;level&amp;#039;]):done()&lt;br /&gt;
            :tag(&amp;#039;td&amp;#039;):wikitext(entry[&amp;#039;hitpoints&amp;#039;]):done()&lt;br /&gt;
            :tag(&amp;#039;td&amp;#039;):wikitext(entry[&amp;#039;attack&amp;#039;]):done()&lt;br /&gt;
            :tag(&amp;#039;td&amp;#039;):wikitext(entry[&amp;#039;defence&amp;#039;]):done()&lt;br /&gt;
            :tag(&amp;#039;td&amp;#039;):wikitext(entry[&amp;#039;magic&amp;#039;]):done()&lt;br /&gt;
            :tag(&amp;#039;td&amp;#039;):wikitext(entry[&amp;#039;ranged&amp;#039;]):done()&lt;br /&gt;
            :tag(&amp;#039;td&amp;#039;):wikitext(entry[&amp;#039;stab defence&amp;#039;]):done()&lt;br /&gt;
            :tag(&amp;#039;td&amp;#039;):wikitext(entry[&amp;#039;slash defence&amp;#039;]):done()&lt;br /&gt;
            :tag(&amp;#039;td&amp;#039;):wikitext(entry[&amp;#039;crush defence&amp;#039;]):done()&lt;br /&gt;
            :tag(&amp;#039;td&amp;#039;):wikitext(entry[&amp;#039;magic defence&amp;#039;]):done()&lt;br /&gt;
            :tag(&amp;#039;td&amp;#039;):wikitext(entry[&amp;#039;light ranged defence&amp;#039;]):done()&lt;br /&gt;
            :tag(&amp;#039;td&amp;#039;):wikitext(entry[&amp;#039;standard ranged defence&amp;#039;]):done()&lt;br /&gt;
            :tag(&amp;#039;td&amp;#039;):wikitext(entry[&amp;#039;heavy ranged defence&amp;#039;]):done()&lt;br /&gt;
&lt;br /&gt;
        if ba[&amp;#039;verbose&amp;#039;] then&lt;br /&gt;
            tr:tag(&amp;#039;td&amp;#039;):wikitext(entry[&amp;#039;slaylvl&amp;#039;] or &amp;#039;1&amp;#039;):done()&lt;br /&gt;
              :tag(&amp;#039;td&amp;#039;):wikitext(entry[&amp;#039;slayxp&amp;#039;]):done()&lt;br /&gt;
              :tag(&amp;#039;td&amp;#039;):wikitext(entry[&amp;#039;slaycat&amp;#039;]):done()&lt;br /&gt;
&lt;br /&gt;
            local td = tr:tag(&amp;#039;td&amp;#039;)&lt;br /&gt;
            local slaymtbl = {}&lt;br /&gt;
            for a, ab in ipairs(entry[&amp;#039;assignedby&amp;#039;]) do&lt;br /&gt;
                if arr.contains(slayer_masters, ab) then&lt;br /&gt;
                    table.insert(slaymtbl, ab)&lt;br /&gt;
                else&lt;br /&gt;
                    mw.log(string.format(&amp;#039;Unknown Slayer master: %s&amp;#039;, ab))&lt;br /&gt;
                end&lt;br /&gt;
            end&lt;br /&gt;
            td:wikitext(mw.text.listToText( slaymtbl, &amp;#039;, &amp;#039;, &amp;#039;, and &amp;#039; ))&lt;br /&gt;
        end&lt;br /&gt;
        return tr&lt;br /&gt;
	end&lt;br /&gt;
    &lt;br /&gt;
    local errors = {}&lt;br /&gt;
    for e, entry in ipairs(data) do&lt;br /&gt;
    	local isnoterr, ret = pcall(makeRow, entry)&lt;br /&gt;
    	if isnoterr then&lt;br /&gt;
    		tbl:node(ret)&lt;br /&gt;
    	else&lt;br /&gt;
    		table.insert(errors, &amp;#039;Error message: &amp;#039;..ret..&amp;#039;&amp;lt;br&amp;gt;Affected entry: &amp;lt;code&amp;gt;&amp;#039;..mw.text.nowiki(mw.text.jsonEncode(entry))..&amp;#039;&amp;lt;/code&amp;gt;&amp;#039;)&lt;br /&gt;
    	end&lt;br /&gt;
    end&lt;br /&gt;
    if #errors &amp;gt; 0 then&lt;br /&gt;
    	local errtag = div:tag(&amp;#039;div&amp;#039;):addClass(&amp;#039;error&amp;#039;):wikitext(&amp;#039;Errors with this query shown below:[[Category:Pages with script errors]]&amp;#039;)&lt;br /&gt;
    	for i,v in ipairs(errors) do&lt;br /&gt;
    		errtag:newline():wikitext(&amp;#039;* &amp;#039;,v)&lt;br /&gt;
    	end&lt;br /&gt;
    end&lt;br /&gt;
    return div&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Estimate the storage size of a serialized table of data&lt;br /&gt;
-- This function assumes somewhat consistent sizes of the elements&lt;br /&gt;
-- like for instance typical SMW data tables&lt;br /&gt;
function p.est_serial_size(tbl, datapoints)&lt;br /&gt;
    assert(type(tbl) == &amp;#039;table&amp;#039;)&lt;br /&gt;
    assert(type(datapoints) == &amp;#039;number&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
    local dp = {}&lt;br /&gt;
&lt;br /&gt;
    for p = 1, datapoints do&lt;br /&gt;
        local pos = math.floor(#tbl * p / datapoints)&lt;br /&gt;
        local txt = mw.text.jsonEncode(tbl[pos])&lt;br /&gt;
        table.insert(dp, txt:len())&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    local avgsize = math.floor(arr.sum(dp) / datapoints)&lt;br /&gt;
&lt;br /&gt;
    return #tbl * avgsize&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Filter data with exclusion lists&lt;br /&gt;
function p.filterData(indata, disco, quest, dmm, cache)&lt;br /&gt;
    -- Fetch exclusion list&lt;br /&gt;
    local exlist = {}&lt;br /&gt;
&lt;br /&gt;
    if not disco then&lt;br /&gt;
        table.insert(exlist, &amp;#039;[[Category:Monsters]] [[Category:Discontinued content]]&amp;#039;)&lt;br /&gt;
    end&lt;br /&gt;
    if not quest then&lt;br /&gt;
        table.insert(exlist, &amp;#039;[[Category:Quest monsters]]&amp;#039;)&lt;br /&gt;
    end&lt;br /&gt;
    if not dmm then&lt;br /&gt;
        table.insert(exlist, &amp;#039;[[Category:Monsters]] [[Category:Deadman Mode]]&amp;#039;)&lt;br /&gt;
    end&lt;br /&gt;
    if not cache then&lt;br /&gt;
        table.insert(exlist, &amp;#039;[[Category:Monsters]] [[Category:Pages using information from game APIs or cache]]&amp;#039;)&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    local pages_excl = pageswithcats(exlist)&lt;br /&gt;
&lt;br /&gt;
    -- Post-process the data&lt;br /&gt;
    local data = {}&lt;br /&gt;
&lt;br /&gt;
    for _, entry in ipairs(indata) do&lt;br /&gt;
        local process = true&lt;br /&gt;
&lt;br /&gt;
        if arr.contains(pages_excl, entry[&amp;#039;variantof&amp;#039;]) or arr.contains(pages_excl, entry[&amp;#039;name&amp;#039;]) then&lt;br /&gt;
            process = false&lt;br /&gt;
        end&lt;br /&gt;
&lt;br /&gt;
        if process then&lt;br /&gt;
            table.insert(data, entry)&lt;br /&gt;
        else&lt;br /&gt;
            --mw.log(string.format(&amp;#039;Removed: %s&amp;#039;, entry[1]))&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    -- Statistics&lt;br /&gt;
    mw.log(string.format(&amp;#039;Filter: exclusion list size: %i, start size: %i, end size: %i, removed %i.&amp;#039;,&lt;br /&gt;
        #pages_excl, #indata, #data, #indata - #data))&lt;br /&gt;
&lt;br /&gt;
    return data&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Sends a query to SMW and returns the data&lt;br /&gt;
function p.loadData(fromlevel, tolevel, fromletter, toletter, levelselect, mems, slayeronly, onlycat, attribute, assignedby, verbose)&lt;br /&gt;
    local props = {&lt;br /&gt;
        [&amp;#039;Image&amp;#039;]             = &amp;#039;image&amp;#039;,&lt;br /&gt;
        [&amp;#039;Is members only&amp;#039;]   = &amp;#039;members&amp;#039;,&lt;br /&gt;
        [&amp;#039;Combat level&amp;#039;]      = &amp;#039;level&amp;#039;,&lt;br /&gt;
        [&amp;#039;Hitpoints&amp;#039;]         = &amp;#039;hitpoints&amp;#039;,&lt;br /&gt;
        [&amp;#039;Attack level&amp;#039;]      = &amp;#039;attack&amp;#039;,&lt;br /&gt;
        [&amp;#039;Defence level&amp;#039;]     = &amp;#039;defence&amp;#039;,&lt;br /&gt;
        [&amp;#039;Magic level&amp;#039;]       = &amp;#039;magic&amp;#039;,&lt;br /&gt;
        [&amp;#039;Ranged level&amp;#039;]      = &amp;#039;ranged&amp;#039;,&lt;br /&gt;
        [&amp;#039;Stab defence bonus&amp;#039;]      = &amp;#039;stab defence&amp;#039;,&lt;br /&gt;
        [&amp;#039;Slash defence bonus&amp;#039;]     = &amp;#039;slash defence&amp;#039;,&lt;br /&gt;
        [&amp;#039;Crush defence bonus&amp;#039;]     = &amp;#039;crush defence&amp;#039;,&lt;br /&gt;
        [&amp;#039;Magic defence bonus&amp;#039;]     = &amp;#039;magic defence&amp;#039;,&lt;br /&gt;
        [&amp;#039;Light range defence bonus&amp;#039;]    = &amp;#039;light ranged defence&amp;#039;,&lt;br /&gt;
        [&amp;#039;Standard range defence bonus&amp;#039;]    = &amp;#039;standard ranged defence&amp;#039;,&lt;br /&gt;
        [&amp;#039;Heavy range defence bonus&amp;#039;]    = &amp;#039;heavy ranged defence&amp;#039;,&lt;br /&gt;
        [&amp;#039;Is variant of&amp;#039;]     = &amp;#039;variantof&amp;#039;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local extprops = {&lt;br /&gt;
        [&amp;#039;Slayer level&amp;#039;]      = &amp;#039;slaylvl&amp;#039;,&lt;br /&gt;
        [&amp;#039;Slayer experience&amp;#039;] = &amp;#039;slayxp&amp;#039;,&lt;br /&gt;
        [&amp;#039;Slayer category&amp;#039;]   = &amp;#039;slaycat&amp;#039;,&lt;br /&gt;
        [&amp;#039;Assigned by&amp;#039;]       = &amp;#039;assignedby&amp;#039;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    local query = {}&lt;br /&gt;
&lt;br /&gt;
    -- Conditions part of query&lt;br /&gt;
    local condition = { &amp;#039;[[Uses infobox::Monster]]&amp;#039; }&lt;br /&gt;
    if mems == &amp;#039;Members&amp;#039; then&lt;br /&gt;
        table.insert(condition, &amp;#039; [[Is members only::true]]&amp;#039;)&lt;br /&gt;
    elseif mems == &amp;#039;F2P&amp;#039; then&lt;br /&gt;
        table.insert(condition, &amp;#039; [[Is members only::false]]&amp;#039;)&lt;br /&gt;
    end&lt;br /&gt;
    if onlycat:len() &amp;gt; 0 or slayeronly then&lt;br /&gt;
        if onlycat:len() &amp;gt; 0 then&lt;br /&gt;
            table.insert(condition, string.format(&amp;#039; [[Slayer category::%s]]&amp;#039;, onlycat))&lt;br /&gt;
        else&lt;br /&gt;
            table.insert(condition, &amp;#039; [[Slayer category::+]]&amp;#039;)&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    if attribute:len() &amp;gt; 0 then&lt;br /&gt;
        table.insert(condition, string.format(&amp;#039; [[Monster attribute::%s]]&amp;#039;, attribute))&lt;br /&gt;
    end&lt;br /&gt;
    if assignedby:len() &amp;gt; 0 then&lt;br /&gt;
        table.insert(condition, string.format(&amp;#039; [[Assigned by::%s]]&amp;#039;, assignedby))&lt;br /&gt;
    end&lt;br /&gt;
    if levelselect then&lt;br /&gt;
        table.insert(condition, string.format(&amp;#039; [[Combat level::≥%i]] [[Combat level::≤%i]]&amp;#039;, fromlevel, tolevel))&lt;br /&gt;
    else&lt;br /&gt;
        if (toletter == &amp;#039;Z&amp;#039;) then&lt;br /&gt;
            table.insert(condition, string.format(&amp;#039; [[Name::≥%s]]&amp;#039;, fromletter))&lt;br /&gt;
        else&lt;br /&gt;
            table.insert(condition, string.format(&amp;#039; [[Name::≥%s]] [[Name::&amp;lt;&amp;lt;%s]]&amp;#039;, fromletter, string.char(toletter:byte() + 1)))&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    table.insert(query, table.concat(condition))&lt;br /&gt;
&lt;br /&gt;
    -- Printouts part of query&lt;br /&gt;
    table.insert(query, &amp;#039;?=#-&amp;#039;)&lt;br /&gt;
    for k, pr in pairs(props) do&lt;br /&gt;
        table.insert(query, string.format(&amp;#039;?%s #- = %s&amp;#039;, k, pr))&lt;br /&gt;
    end&lt;br /&gt;
    if verbose then&lt;br /&gt;
        for k, pr in pairs(extprops) do&lt;br /&gt;
            table.insert(query, string.format(&amp;#039;?%s #- = %s&amp;#039;, k, pr))&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    -- Parameters part of query&lt;br /&gt;
    query.offset = 0&lt;br /&gt;
    query.limit = verbose and 1000 or 580&lt;br /&gt;
&lt;br /&gt;
    -- Fetch the data&lt;br /&gt;
    -- mw.logObject(query)&lt;br /&gt;
    local t1 = os.clock()&lt;br /&gt;
    local smw = mw.smw.ask(query)&lt;br /&gt;
    local t2 = os.clock()&lt;br /&gt;
    if not smw or #smw == 0 then&lt;br /&gt;
        smw = {}&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    -- Post-process the data&lt;br /&gt;
    local data = {}&lt;br /&gt;
&lt;br /&gt;
    for _, entry in ipairs(smw) do&lt;br /&gt;
        local dataline = entry&lt;br /&gt;
&lt;br /&gt;
        dataline[&amp;#039;name&amp;#039;] = dataline[1]&lt;br /&gt;
        dataline[1] = nil&lt;br /&gt;
        if type(dataline[&amp;#039;image&amp;#039;]) == &amp;#039;table&amp;#039; then&lt;br /&gt;
            dataline[&amp;#039;image&amp;#039;] = dataline[&amp;#039;image&amp;#039;][1]&lt;br /&gt;
        end&lt;br /&gt;
        if type(dataline[&amp;#039;slaycat&amp;#039;]) == &amp;#039;table&amp;#039; then&lt;br /&gt;
            dataline[&amp;#039;slaycat&amp;#039;] = table.concat(entry[&amp;#039;slaycat&amp;#039;], &amp;#039;, &amp;#039;)&lt;br /&gt;
        end&lt;br /&gt;
        if type(dataline[&amp;#039;assignedby&amp;#039;]) == &amp;#039;string&amp;#039; then&lt;br /&gt;
            dataline[&amp;#039;assignedby&amp;#039;] = { entry[&amp;#039;assignedby&amp;#039;] }&lt;br /&gt;
        elseif type(dataline[&amp;#039;assignedby&amp;#039;]) == &amp;#039;nil&amp;#039; then&lt;br /&gt;
            dataline[&amp;#039;assignedby&amp;#039;] = { }&lt;br /&gt;
        end&lt;br /&gt;
&lt;br /&gt;
        table.insert(data, dataline)&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    -- Statistics&lt;br /&gt;
    smwstats = {&lt;br /&gt;
        offset  = query.offset,&lt;br /&gt;
        limit   = query.limit,&lt;br /&gt;
        found   = #smw,&lt;br /&gt;
        time    = (t2 - t1) * 1000,&lt;br /&gt;
        size    = p.est_serial_size(smw, 5)&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    mw.log(string.format(&amp;#039;SMW: Found %i, offset %i, limit %i, time elapsed %.3f ms, est. serial size: %.0f KiB.&amp;#039;,&lt;br /&gt;
        smwstats.found, smwstats.offset, smwstats.limit, smwstats.time, smwstats.size / 1024))&lt;br /&gt;
&lt;br /&gt;
    return data&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[ DEBUG COPYPASTA&lt;br /&gt;
mw.logObject( p.loadData(&amp;#039;1&amp;#039;, &amp;#039;1&amp;#039;, &amp;#039;A&amp;#039;, &amp;#039;A&amp;#039;, true, &amp;#039;All&amp;#039;, false, &amp;#039;&amp;#039;, &amp;#039;&amp;#039;, &amp;#039;&amp;#039;, false) )&lt;br /&gt;
mw.logObject( p.loadData(&amp;#039;1&amp;#039;, &amp;#039;1&amp;#039;, &amp;#039;A&amp;#039;, &amp;#039;A&amp;#039;, false, &amp;#039;All&amp;#039;, false, &amp;#039;&amp;#039;, &amp;#039;&amp;#039;, &amp;#039;&amp;#039;, false) )&lt;br /&gt;
= p._main({fromlevel=&amp;#039;1&amp;#039;, tolevel=&amp;#039;1&amp;#039;, verbose=&amp;#039;yes&amp;#039;})&lt;br /&gt;
= p._main({fromletter=&amp;#039;A&amp;#039;, toletter=&amp;#039;A&amp;#039;, levelselect=&amp;#039;no&amp;#039;, levelsort=&amp;#039;no&amp;#039;, verbose=&amp;#039;yes&amp;#039;})&lt;br /&gt;
--]]&lt;br /&gt;
&lt;br /&gt;
return p&lt;/div&gt;</summary>
		<author><name>Alex</name></author>
	</entry>
</feed>