Module:Sandbox

From Delanor Wiki
Revision as of 09:47, 3 July 2025 by Nulled (talk | contribs) (Created page with "local p = {} require('Module:Mw.html extension') local yesNo = require('Module:Yesno') local paramTest = require('Module:Paramtest') local contains = require('Module:Array').contains local minimum = require('Module:Array').min local pagesWithCats = require('Module:PageListTools').pageswithcats local pagesWithConditions = require('Module:PageListTools').pageswithconditions local editbtn = require('Module:Edit button') local memberOptions = {'members', 'f2p', 'all'} loc...")
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search

local p = {}

require('Module:Mw.html extension')

local yesNo = require('Module:Yesno') local paramTest = require('Module:Paramtest') local contains = require('Module:Array').contains local minimum = require('Module:Array').min local pagesWithCats = require('Module:PageListTools').pageswithcats local pagesWithConditions = require('Module:PageListTools').pageswithconditions local editbtn = require('Module:Edit button')

local memberOptions = {'members', 'f2p', 'all'} local slotOptions = {'head', 'cape', 'neck', 'ammo', 'weapon', 'shield', 'body', 'legs', 'hands', 'feet', 'ring', '2h'} local statOptions = {'astab', 'aslash', 'acrush', 'amagic', 'arange', 'dstab', 'dslash', 'dcrush', 'dmagic', 'drange', 'str', 'rstr', 'mdmg', 'prayer'}

function statFormat(_arg, default) local arg = tonumber(_arg) if(not arg) then return (default or _arg) end if(arg < 0) then return tostring(arg) end return '+' .. arg end

function buildRow(item, attackSpeedColumn, uim) local row = mw.html.create('tr') :tag('td'):wikitext(item.image and 'link=|' .. item.name .. '' or ):done() :tag('td'):wikitext('' .. item.name .. ''):done() :tag('td'):wikitext(item.members and 'Members' or 'Free-to-play'):done()

for _, stat in ipairs(statOptions) do local statNum = tonumber(item[stat]) row:tag('td'):wikitext((statFormat(item[stat]) or editbtn("? (edit)", item.name)) .. (stat == 'mdmg' and '%' or )) :addClassIf(statNum and (statNum > 0), 'table-positive') :addClassIf(statNum and (statNum < 0), 'table-negative') end

local weightNum = tonumber(item.weight) row:tag('td'):wikitext(item.weight)

if(attackSpeedColumn) then if((item.speed == nil) or (item.speed < 0)) then row:tag('td'):addClass('table-na nohighlight'):css('text-align', 'center'):wikitext('N/A') else row:tag('td'):wikitext(item.speed):done() end end

if(uim) then local storeability = 'Shop' if(item.emote) then storeability = 'STASH' elseif(item.costume) then storeability = 'POH' end row:tag('td'):wikitext(storeability):done() end

return row end

function createHeader(slotName, attackSpeedColumn, uim) local tabl = mw.html.create('table'):addClass('wikitable lighttable sortable sticky-header align-center-1 align-left-2 align-center-3 align-right-4 align-right-5 align-right-6 align-right-7 align-right-8 align-right-9 align-right-10 align-right-11 align-right-12 align-right-13 align-right-14 align-right-15 align-right-16 align-right-17 align-center-18'):done() local header = tabl:tag('tr') header:tag('th'):attr('colspan', '2'):wikitext('Name'):done() :tag('th'):wikitext('Members'):done() :tag('th'):attr('data-sort-type', 'number'):wikitext('Stab attack'):done() :tag('th'):attr('data-sort-type', 'number'):wikitext('Slash attack'):done() :tag('th'):attr('data-sort-type', 'number'):wikitext('Crush attack'):done() :tag('th'):attr('data-sort-type', 'number'):wikitext('Magic attack'):done() :tag('th'):attr('data-sort-type', 'number'):wikitext('Ranged attack'):done() :tag('th'):attr('data-sort-type', 'number'):wikitext('Stab defenceFile:Defence icon.png'):done() :tag('th'):attr('data-sort-type', 'number'):wikitext('Slash defenceFile:Defence icon.png'):done() :tag('th'):attr('data-sort-type', 'number'):wikitext('Crush defenceFile:Defence icon.png'):done() :tag('th'):attr('data-sort-type', 'number'):wikitext('Magic defenceFile:Defence icon.png'):done() :tag('th'):attr('data-sort-type', 'number'):wikitext('Ranged defenceFile:Defence icon.png'):done() :tag('th'):attr('data-sort-type', 'number'):wikitext('Strength'):done() :tag('th'):attr('data-sort-type', 'number'):wikitext('Ranged Strength'):done() :tag('th'):attr('data-sort-type', 'number'):wikitext('Magic Damage'):done() :tag('th'):attr('data-sort-type', 'number'):wikitext('Prayer'):done() :tag('th'):attr('data-sort-type', 'number'):wikitext('Weight'):done()

if(attackSpeedColumn) then header:tag('th'):attr('data-sort-type', 'number'):wikitext('Speed'):done() end

if(uim) then header:tag('th'):wikitext('File:Marble magic wardrobe icon.pngStored/Buy'):done() end

return tabl end

function filterData(data, slotName, options)

if(slotName == 'ammo') then slotName = 'Ammunition' end -- hacky shit until ammo/ammunition is resolved slotCat = if slotName == '2h' then slotCat = end local exclusionListCategories = { { options.beta, slotCat .. }, { options.bounty, slotCat .. }, { options.cosmetic, slotCat .. }, { options.discontinued, slotCat .. }, { options.dmm, slotCat .. }, { options.emir, slotCat .. }, { options.failedPoll, slotCat .. }, { options.gauntlet, slotCat .. }, { options.lms, slotCat .. }, { options.quest, slotCat .. }, }

local exclusionList = { } for _, excl in ipairs(exclusionListCategories) do if(not excl[1]) then table.insert(exclusionList, excl[2]) end end local pagesToExclude = #exclusionList > 0 and pagesWithCats(exclusionList) or {} local emotePagesToInclude, costumePagesToInclude if(options.uim) then emotePagesToInclude = pagesWithCats({ slotCat .. }) or {} costumePagesToInclude = pagesWithCats({ slotCat .. }) or {} end

-- Filter the data local retData = {}

for _, item in ipairs(data) do local keep = true

if(((options.members == 'members') and (item['members'] == false)) or ((options.members == 'f2p') and (item['members'] == true)) or ((contains(pagesToExclude, item['variantof'])) or (contains(pagesToExclude, item['name'])))) then keep = false end

if(options.uim) then if((not (contains(emotePagesToInclude, item['variantof']) or (contains(emotePagesToInclude, item['name'])))) and (not (contains(costumePagesToInclude, item['variantof']) or (contains(costumePagesToInclude, item['name'])))) and (next(pagesWithConditions('Sells item::' .. item.name .. '')) == nil)) then keep = false elseif(contains(costumePagesToInclude, item['variantof']) or (contains(costumePagesToInclude, item['name']))) then item.costume = true elseif(contains(emotePagesToInclude, item['variantof']) or (contains(emotePagesToInclude, item['name']))) then item.emote = true end end

if(keep) then table.insert(retData, item) end

end

mw.log(string.format('Filter: exclusion list size: %i, start size: %i, end size: %i, removed %i.', #pagesToExclude, #data, #retData, #data - #retData))

return retData end

function loadData(slotName, attackSpeed, members) local query = { 'Equipment slot::' .. slotName .. '', '?=#-', '?Stab attack bonus#-=astab', '?Slash attack bonus#-=aslash', '?Crush attack bonus#-=acrush', '?Magic attack bonus#-=amagic', '?Range attack bonus#-=arange', '?Stab defence bonus#-=dstab', '?Slash defence bonus#-=dslash', '?Crush defence bonus#-=dcrush', '?Magic defence bonus#-=dmagic', '?Range defence bonus#-=drange', '?Strength bonus#-=str', '?Magic Damage bonus#-=mdmg', '?Ranged Strength bonus#-=rstr', '?Prayer bonus#-=prayer', '?Weight#-=weight', '?Is members only#-=members', '?Image#-=image', '?Is variant of#-=variantof', offset = 0, limit = 1000, }

if(attackSpeed) then table.insert(query, '?Weapon attack speed#-=speed') end

local t1 = os.clock() local smwData = mw.smw.ask(query) local t2 = os.clock() assert(smwData ~= nil and #smwData > 0, 'SMW query failed')

for _, item in ipairs(smwData) do -- Rename the first parameter to name for clarity and ease of use item['name'] = item[1] item[1] = nil

if(item['image'] == nil) then local hasDefaultFile = mw.title.new(item['name'] .. '.png', 'File'):getContent() item['image'] = hasDefaultFile and 'File:' .. item['name'] .. '.png' or elseif(type(item['image']) == 'table') then item['image'] = item['image'][1] end -- Fix members values by defaulting when running into issue if(type(item.members) == 'boolean') then -- Short circuit elseif(item.members == nil) then item.members = false elseif(type(item.members) == 'table') then for _, mems in ipairs(item.members) do if(mems == false) then item.members = false break end end end -- Fix weights with multiple values (Max cape), this may do nothing and is precautionary if(item.weight == nil) then item.weight = 0 elseif(type(item.weight) == 'table') then item.weight, _ = minimum(item.weight) end end

mw.log(string.format('SMW: entries %d, time elapsed: %.3f ms.', #smwData, (t2 - t1) * 1000))

return smwData end

-- JSON data dump entry-point function p.dumpData(frame) local args = frame:getParent().args return p._dumpData(args) end

function p._dumpData(args) local slot = args.slot assert(contains(slotOptions, slot), 'Invalid slot specified')

local data = loadData(slot, true)

-- Tests indicate that JSON pretty-printing increases the size by a factor of 1.78. -- Removing indenting results in an increase in size by a factor of 1.15. -- The latter is a very reasonable trade-off to make the files more wiki-friendly. local prefix = string.format('-- Data for item slot \'%s\' @ %s.\n-- Generated by Module:Slottable, function dumpData()\nreturn mw.text.jsonDecode([=[\n', slot, os.date('%F %T', os.time())) local rawjson = mw.text.jsonEncode(data, mw.text.JSON_PRETTY) local jsondata, subst = rawjson:gsub('\n%s+', '\n') local postfix = '\n]=])\n'

mw.log(string.format('Dumping JSON data for item slot \'%s\'. Raw size: %d bytes, formatted size: %d bytes (factor: %.2f).', slot, rawjson:len(), jsondata:len(), jsondata:len() / rawjson:len()))

return prefix .. jsondata .. postfix end


-- Turtle data dump entry-point function p.dumpDataTTL(frame) local args = frame:getParent().args return p._dumpDataTTL(args) end

function p._dumpDataTTL(args) local slot = args.slot assert(contains(slotOptions, slot), 'Invalid slot specified')

local data = loadData(slot, true)

   local slot_
   if(slot == "2h") then
   	slot_ = "zweihander"
   else
   	slot_ = slot
   end

local prefix = string.format('# Data for item slot \'%s\' @ %s.\n# Generated by Module:Slottable, function dumpDataTTL()\n\n', slot, os.date('%F %T', os.time())) prefix = prefix .. "@prefix " .. slot_ .. ": <http://oldschool.runescape.wiki/rdf/" .. slot_ .. "/> .\n" prefix = prefix .. "@prefix prop: <http://oldschool.runescape.wiki/rdf/prop/> .\n\n"

local ttlData = "" for _, i in ipairs(data) do ttlData = ttlData .. slot_ .. ":" .. _ .. " " .. "prop:slot \"" .. slot_ .. "\"; " local outl = {} for k, v in pairs(i) do if((k == "image") or (k == "name") or (k == "variantof")) then table.insert(outl, "prop:" .. k .. " \"" .. tostring(v) .. "\"") else table.insert(outl, "prop:" .. k .. " " .. tostring(v)) end end ttlData = ttlData .. table.concat(outl, "; ") .. " .\n" end

local postfix = '\n\n' mw.log(string.format('Dumping Turtle data for item slot \'%s\'. Size: %d bytes.', slot, ttlData:len()))

return prefix .. ttlData .. postfix end

function p._main(args) local slot = string.lower(paramTest.default_to(args.slot, )) local members = string.lower(paramTest.default_to(args.members, 'all'))

assert(contains(slotOptions, slot), 'Invalid slot specified') assert(contains(memberOptions, members), 'Invalid members status specified')

local beta = yesNo(paramTest.default_to(args.beta, false), false) local bounty = yesNo(paramTest.default_to(args.bounty, true), true) local cosmetic = yesNo(paramTest.default_to(args.cosmetic, true), true) local discontinued = yesNo(paramTest.default_to(args.discontinued, false), false) local dmm = yesNo(paramTest.default_to(args.dmm, false), false) local emir = yesNo(paramTest.default_to(args.emir, false), false) local failedPoll = yesNo(paramTest.default_to(args.failedpoll, false), false) local gauntlet = yesNo(paramTest.default_to(args.beta, false), false) local lms = yesNo(paramTest.default_to(args.lms, false), false) local quest = yesNo(paramTest.default_to(args.quest, true), true)

-- UIM specific tables, that only display items that can be: -- purchased, stored in the POH, or stored in STASH untsi local uim = yesNo(paramTest.default_to(args.uim, false), false)

local attackSpeed = false if((slot == '2h') or (slot == 'weapon')) then attackSpeed = true end

local data = loadData(slot, attackSpeed, members, uim) data = filterData(data, slot, {members = members, uim = uim, beta = beta, bounty = bounty, cosmetic = cosmetic, discontinued = discontinued, dmm = dmm, emir = emir, failedPoll = failedPoll, gauntlet = gauntlet, lms = lms, quest = quest })

local ret = createHeader(slot, attackSpeed, uim) for _, item in ipairs(data) do ret:node(buildRow(item, attackSpeed, uim)) end

return ret end

function p.main(frame) local args = frame:getParent().args return p._main(args) end

--[[ DEBUG mw.logObject(p.getData('weapon')) p._main({slot='weapon', members='all'}) p._dumpData({slot='weapon'}) p._dumpDataTTL({slot='weapon'}) --]]

return p