Module:EmberFantasy/sandbox/Slottable: Difference between revisions
		
		
		
		Jump to navigation
		Jump to search
		
Content added Content deleted
No edit summary Tag: Reverted  | 
				No edit summary Tag: Manual revert  | 
				||
| Line 1: | Line 1: | ||
-- <pre>  | 
|||
require('Module:Mw.html extension')  | 
|||
local p = {}  | 
  local p = {}  | 
||
local format = require('Module:Format equipment stat').format --for formatting the stats with + and - symbols on output  | 
|||
require('Module:Mw.html extension')  | 
  |||
local p2pIcon = '[[File:Member icon.png|frameless|link=Pay-to-play]]' --these icons are for the later members/f2p stars  | 
|||
local yesNo = require('Module:Yesno')  | 
  |||
local f2pIcon = '[[File:Free-to-play icon.png|frameless|link=Free-to-play]]'  | 
|||
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 stats = {'astab', 'aslash', 'acrush', 'amagic', 'arange', 'dstab', 'dslash', 'dcrush', 'dmagic', 'drange', 'str', 'rstr', 'mdmg', 'prayer'}  | 
|||
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   | 
  function p.main(frame)  | 
||
	local args = frame:getParent().args --get the input from the template  | 
|||
	local arg = tonumber(_arg)  | 
  |||
	local slot = string.lower(tostring(args['slot'])) --take the slot input as the slot we want the table for  | 
|||
	if(not arg) then return (default or _arg) end  | 
  |||
	local mems = args['mems']  | 
|||
	if(arg < 0) then return tostring(arg) end  | 
  |||
	local dmm = args['dmm']  | 
|||
	return '+' .. arg  | 
  |||
	local beta = args['beta']  | 
|||
end  | 
  |||
	local data = getData(slot,mems,dmm,beta) --this takes the slot and sends it to our getData function (seen below) which gives us back a data table  | 
|||
	local restbl = mw.html.create('table') --start making our results table, beginninig with the header  | 
|||
function buildRow(item, attackSpeedColumn, uim)  | 
  |||
	restbl:addClass('wikitable align-center-1 sortable align-center')  | 
|||
	local row = mw.html.create('tr')  | 
  |||
		:tag('tr')  | 
|||
		:tag('td'):wikitext(item.image and '[[' .. item.image .. '|link=|' .. item.name .. ']]' or ''):done()  | 
  |||
		:tag('  | 
  			:tag('th'):addClass('unsortable'):wikitext(''):done()  | 
||
		:tag('  | 
  			:tag('th'):wikitext('Name'):done()  | 
||
			:tag('th'):wikitext('Members'):done()  | 
|||
			:tag('th'):wikitext('[[File:White dagger.png|Stab attack]]') :done()  | 
|||
	for _, stat in ipairs(statOptions) do  | 
  |||
			:tag('th'):wikitext('[[File:White scimitar.png|Slash attack]]') :done()  | 
|||
		local statNum = tonumber(item[stat])  | 
  |||
			:tag('th'):wikitext('[[File:White warhammer.png|Crush attack]]') :done()  | 
|||
		row:tag('td'):wikitext((statFormat(item[stat]) or editbtn("'''?''' (edit)", item.name)) .. (stat == 'mdmg' and '%' or ''))  | 
  |||
			:tag('th'):wikitext('[[File:Magic icon.png|Magic attack]]') :done()  | 
|||
			:addClassIf(statNum and (statNum > 0), 'table-positive')  | 
  |||
			:tag('th'):wikitext('[[File:Ranged icon.png|Ranged attack]]') :done()  | 
|||
			:addClassIf(statNum and (statNum < 0), 'table-negative')  | 
  |||
			:tag('th'):wikitext('[[File:White dagger.png|Stab defence]]<sup>[[File:Defence icon.png]]</sup>') :done()  | 
|||
	end  | 
  |||
			:tag('th'):wikitext('[[File:White scimitar.png|Slash defence]]<sup>[[File:Defence icon.png]]</sup>') :done()  | 
|||
			:tag('th'):wikitext('[[File:White warhammer.png|Crush defence]]<sup>[[File:Defence icon.png]]</sup>') :done()  | 
|||
	local weightNum = tonumber(item.weight)  | 
  |||
			:tag('th'):wikitext('[[File:Magic icon.png|Magic defence]]<sup>[[File:Defence icon.png]]</sup>') :done()  | 
|||
	row:tag('td'):wikitext(item.weight)  | 
  |||
			:tag('th'):wikitext('[[File:Ranged icon.png|Ranged defence]]<sup>[[File:Defence icon.png]]</sup>') :done()  | 
|||
			:tag('th'):wikitext('[[File:Strength icon.png|Strength]]') :done()  | 
|||
			:tag('th'):wikitext('[[File:Ranged Strength icon.png|Ranged Strength]]') :done()  | 
|||
			:tag('th'):wikitext('[[File:Magic Damage icon.png|Magic Damage]]') :done()  | 
|||
			:tag('th'):wikitext('[[File:Prayer icon.png|Prayer]]') :done()  | 
|||
			:tag('th'):wikitext('Weight') :done()  | 
|||
		:done()  | 
|||
	-- Create the rows for the output table  | 
|||
	if(attackSpeedColumn) then  | 
  |||
	for _, item in ipairs(data) do    --for each row of data, we take it and split it up, then put it into our table row. We also format them with + and - symbols here  | 
|||
		if((item.speed == nil) or (item.speed < 0)) then  | 
  |||
		local row = restbl:tag('tr')  | 
|||
			row:tag('td'):addClass('table-na nohighlight'):css('text-align', 'center'):wikitext('<small>N/A</small>')  | 
  |||
			:tag('td'):wikitext(item.image):done()  | 
|||
		else  | 
  |||
			:tag('td'):wikitext(item.name):done()  | 
|||
			:tag('td'):wikitext(item.members):done()  | 
|||
		for _, stat in ipairs(stats) do  | 
|||
			local value = item[stat]  | 
|||
			local value_num = tonumber(value)  | 
|||
			row:tag('td'):wikitext(format(value))  | 
|||
				:addClassIf(value_num and (value_num > 0), 'table-positive')  | 
|||
				:addClassIf(value_num and (value_num < 0), 'table-negative')  | 
|||
		end  | 
  		end  | 
||
		row:tag('td'):wikitext(item.weight):done()  | 
|||
	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  | 
  	end  | 
||
	return tostring(restbl) --returns the table back to the template to be put onto the page  | 
|||
	return row  | 
  |||
end  | 
  end  | 
||
function getData(slotName,mems,dmm,beta) --so this is the function that takes the slot name and gets all the data for the items  | 
|||
function createHeader(slotName, attackSpeedColumn, uim)  | 
  |||
	--first we set up our SMW query  | 
|||
	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   | 
  	local q = {  | 
||
		'[[Equipment slot::'..slotName..']]', --we want everything that matches the slot we called, and then all the attached data below  | 
|||
	header:tag('th'):attr('colspan', '2'):wikitext('Name'):done()  | 
  |||
		'?Is members only',  | 
|||
		:tag('th'):wikitext('[[File:Member icon.png|link=|Members]]'):done()  | 
  |||
		'?Stab attack bonus',  | 
|||
		:tag('th'):attr('data-sort-type', 'number'):wikitext('[[File:White dagger.png|link=|Stab attack]]'):done()  | 
  |||
		'?Slash attack bonus',  | 
|||
		:tag('th'):attr('data-sort-type', 'number'):wikitext('[[File:White scimitar.png|link=|Slash attack]]'):done()  | 
  |||
		'?Crush attack bonus',  | 
|||
		:tag('th'):attr('data-sort-type', 'number'):wikitext('[[File:White warhammer.png|link=|Crush attack]]'):done()  | 
  |||
		'?Magic attack bonus',  | 
|||
		:tag('th'):attr('data-sort-type', 'number'):wikitext('[[File:Magic icon.png|link=|Magic attack]]'):done()  | 
  |||
		'?Range attack bonus',  | 
|||
		:tag('th'):attr('data-sort-type', 'number'):wikitext('[[File:Ranged icon.png|link=|Ranged attack]]'):done()  | 
  |||
		'?Stab defence bonus',  | 
|||
		:tag('th'):attr('data-sort-type', 'number'):wikitext('[[File:White dagger.png|link=|Stab defence]]<sup>[[File:Defence icon.png|link=]]</sup>'):done()  | 
  |||
		'?Slash defence bonus',  | 
|||
		:tag('th'):attr('data-sort-type', 'number'):wikitext('[[File:White scimitar.png|link=|Slash defence]]<sup>[[File:Defence icon.png|link=]]</sup>'):done()  | 
  |||
		'?Crush defence bonus',  | 
|||
		:tag('th'):attr('data-sort-type', 'number'):wikitext('[[File:White warhammer.png|link=|Crush defence]]<sup>[[File:Defence icon.png|link=]]</sup>'):done()  | 
  |||
		'?Magic defence bonus',  | 
|||
		:tag('th'):attr('data-sort-type', 'number'):wikitext('[[File:Magic icon.png|link=|Magic defence]]<sup>[[File:Defence icon.png|link=]]</sup>'):done()  | 
  |||
		'?Range defence bonus',  | 
|||
		:tag('th'):attr('data-sort-type', 'number'):wikitext('[[File:Ranged icon.png|link=|Ranged defence]]<sup>[[File:Defence icon.png|link=]]</sup>'):done()  | 
  |||
		'?Strength bonus',  | 
|||
		:tag('th'):attr('data-sort-type', 'number'):wikitext('[[File:Strength icon.png|link=|Strength]]'):done()  | 
  |||
		'?Ranged Strength bonus',  | 
|||
		:tag('th'):attr('data-sort-type', 'number'):wikitext('[[File:Ranged Strength icon.png|link=|Ranged Strength]]'):done()  | 
  |||
		'?Magic Damage bonus',  | 
|||
		:tag('th'):attr('data-sort-type', 'number'):wikitext('[[File:Magic Damage icon.png|link=|Magic Damage]]'):done()  | 
  |||
		'?Prayer bonus',  | 
|||
		:tag('th'):attr('data-sort-type', 'number'):wikitext('[[File:Prayer icon.png|link=|Prayer]]'):done()  | 
  |||
		'?Category',  | 
|||
		:tag('th'):attr('data-sort-type', 'number'):wikitext('[[File:Weight icon.png|link=|Weight]]'):done()  | 
  |||
		'?Image',  | 
|||
		'?Weight',  | 
|||
	if(attackSpeedColumn) then  | 
  |||
		limit = 1000,  | 
|||
		header:tag('th'):attr('data-sort-type', 'number'):wikitext('[[File:Watch.png|link=|Speed]]'):done()  | 
  |||
		order = 'ascending'  | 
|||
	end  | 
  |||
	if(uim) then  | 
  |||
		header:tag('th'):wikitext('[[File:Marble magic wardrobe icon.png|link=]]Stored/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 = '[[Category:' .. paramTest.ucfirst(slotName) .. ' slot items]]'  | 
  |||
	if slotName == '2h' then  | 
  |||
		slotCat = '[[Category:Two-handed slot items]]'	  | 
  |||
	end  | 
  |||
	local exclusionListCategories = {  | 
  |||
		{ options.beta,			slotCat .. '[[Category:Beta items]]' },  | 
  |||
		{ options.discontinued,	slotCat .. '[[Category:Discontinued content]]' },  | 
  |||
		{ options.dmm,			slotCat .. '[[Category:Deadman seasonal items]]' },  | 
  |||
		{ options.emir,			slotCat .. '[[Category:Emir\'s Arena]]' },  | 
  |||
		{ options.failedPoll,	slotCat .. '[[Category:Pages containing information from failed polls]]' },  | 
  |||
		{ options.gauntlet,		slotCat .. '[[Category:The Gauntlet]]' },  | 
  |||
		{ options.lms,			slotCat .. '[[Category:Last Man Standing]]' },  | 
  |||
		{ options.quest,		slotCat .. '[[Category:Quest items]]' },  | 
  |||
	}  | 
  	}  | 
||
	local smwdata = mw.smw.ask(q) --this now asks the smw for all the data, and saves all of it in smwdata  | 
|||
	local data = {} --setting this table up to insert processed data into  | 
|||
	for _, item in ipairs(smwdata) do --for each item we found with our smw query  | 
|||
	local exclusionList = { }  | 
  |||
		local process = true  | 
|||
	for _, excl in ipairs(exclusionListCategories) do  | 
  |||
		local dmmcat = false  | 
|||
		if(not excl[1]) then  | 
  |||
		local betacat = false  | 
|||
			table.insert(exclusionList, excl[2])  | 
  |||
		if type(item['Category']) == 'table' then  | 
|||
			for _, category in ipairs(item['Category']) do  | 
|||
				if category == "[[:Category:Deadman seasonal items|Deadman seasonal items]]" then  | 
|||
					dmmcat = true  | 
|||
				elseif category == "[[:Category:Beta items|Beta items]]" then  | 
|||
					betacat = true  | 
|||
				end  | 
|||
			end  | 
|||
		end  | 
  		end  | 
||
		if mems == 'Members' then  | 
|||
	end  | 
  |||
			if not item['Is members only'] then  | 
|||
	local pagesToExclude = #exclusionList > 0 and pagesWithCats(exclusionList) or {}  | 
  |||
				process = false  | 
|||
	local emotePagesToInclude, costumePagesToInclude  | 
  |||
			end  | 
|||
	if(options.uim) then  | 
  |||
		emotePagesToInclude = pagesWithCats({ slotCat .. '[[Category:Items needed for an emote clue]]' }) or {}  | 
  |||
		costumePagesToInclude = pagesWithCats({ slotCat .. '[[Category:Items storable in the costume room]]' }) 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  | 
  		end  | 
||
		if mems == 'F2P' then  | 
|||
		if  | 
  			if item['Is members only'] then  | 
||
				process = false  | 
|||
			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  | 
||
		end  | 
  		end  | 
||
		if dmm == 'No' then  | 
|||
		if  | 
  			if dmmcat == true then  | 
||
				process = false  | 
|||
			table.insert(retData, item)  | 
  |||
			end  | 
|||
		end  | 
  		end  | 
||
		if beta == 'No' then  | 
|||
			if betacat == true then  | 
|||
	end  | 
  |||
				process = false  | 
|||
	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  | 
||
		end  | 
  		end  | 
||
		if process then  | 
|||
		-- Fix weights with multiple values (Max cape), this may do nothing and is precautionary  | 
  |||
			local dataline = processData(item) --we process it (seen below) and then save it as a line  | 
|||
		if(item.weight == nil) then  | 
  |||
			table.insert(data, dataline) --and then we insert that line into our data table to be returned  | 
|||
			item.weight = 0  | 
  |||
		elseif(type(item.weight) == 'table') then  | 
  |||
			item.weight, _ = minimum(item.weight)  | 
  |||
		end  | 
  		end  | 
||
	end  | 
  	end  | 
||
	return data --and once we've processed all the data we send the data table back up to main for the formatting  | 
|||
	mw.log(string.format('SMW: entries %d, time elapsed: %.3f ms.', #smwData, (t2 - t1) * 1000))  | 
  |||
	return smwData  | 
  |||
end  | 
  end  | 
||
function processData(item) --this breaks up the smwdata bit into manageable little bites  | 
|||
-- JSON data dump entry-point  | 
  |||
	local name = item[1] or '' --this gets the item name, which by default is in the first position of the query results (lua starts at 1, not 0)  | 
|||
function p.dumpData(frame)  | 
  |||
	local   | 
  	local _name = string.match(name, '|(.-)%]')  | 
||
	return p._dumpData(args)  | 
  |||
	local members = item['Is members only'] --members we have to do a bit extra for  | 
|||
end  | 
  |||
	if members == true then --if it is members, we use the members star  | 
|||
		members = p2pIcon  | 
|||
function p._dumpData(args)  | 
  |||
	elseif members == false then --if not, use f2p star  | 
|||
	local slot = args.slot  | 
  |||
		members = f2pIcon  | 
|||
	assert(contains(slotOptions, slot), 'Invalid slot specified')  | 
  |||
	else  | 
|||
		members = ''  | 
|||
	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  | 
  	end  | 
||
	local   | 
  	local image = item['Image'] or ''  | 
||
	if type(image) == 'table' then  | 
|||
	mw.log(string.format('Dumping Turtle data for item slot \'%s\'. Size: %d bytes.', slot, ttlData:len()))  | 
  |||
		image = image[1] -- take the first image available  | 
|||
	end  | 
|||
	return prefix .. ttlData .. postfix  | 
  |||
	image = string.match(image, '[Ff]ile:.-%.png') or ''  | 
|||
end  | 
  |||
	if image ~= '' then  | 
|||
		image = string.format('[[%s|link=%s]]', image, _name)  | 
|||
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 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  | 
  	end  | 
||
	local data = loadData(slot, attackSpeed, members, uim)  | 
  |||
	data = filterData(data, slot, {members = members, uim = uim, beta = beta, discontinued = discontinued, dmm = dmm, emir = emir, failedPoll = failedPoll, gauntlet = gauntlet, lms = lms,  quest = quest })  | 
  |||
	local keyset=""  | 
|||
	local ret = createHeader(slot, attackSpeed, uim)  | 
  |||
	local n=0  | 
|||
	for _, item in ipairs(data) do  | 
  |||
		ret:node(buildRow(item, attackSpeed, uim))  | 
  |||
	for k,v in pairs(item) do  | 
|||
	  n=n+1  | 
|||
	  keyset = keyset .. k .. " (" .. tostring(v) ..")" .. ":"  | 
|||
	end  | 
  	end  | 
||
	return { --now we return the processed data for this item back to the getData function, which sends us another item and repeats until we've done them all  | 
|||
	return ret  | 
  |||
		name = name,  | 
|||
		image = image,  | 
|||
		members = members,  | 
|||
		astab = item['Stab attack bonus'] or '',  | 
|||
		aslash = item['Slash attack bonus'] or '',  | 
|||
		acrush = item['Crush attack bonus'] or '',  | 
|||
		amagic = item['Magic attack bonus'] or '',  | 
|||
		arange = item['Range attack bonus'] or '',  | 
|||
		dstab = item['Stab defence bonus'] or '',  | 
|||
		dslash = item['Slash defence bonus'] or '',  | 
|||
		dcrush = item['Crush defence bonus'] or '',  | 
|||
		dmagic = item['Magic defence bonus'] or '',  | 
|||
		drange = item['Range defence bonus'] or '',  | 
|||
		str = item['Strength bonus'] or '',  | 
|||
		rstr = item['Ranged Strength bonus'] or '',  | 
|||
		mdmg = item['Magic Damage bonus'] or keyset,  | 
|||
		prayer = item['Prayer bonus'] or '',  | 
|||
		weight = item['Weight'] or '',  | 
|||
	}  | 
|||
end  | 
  end  | 
||
p.getData = getData  | 
|||
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  | 
  return p  | 
||
Latest revision as of 11:22, 17 October 2024
Documentation for this module may be created at Module:EmberFantasy/sandbox/Slottable/doc
-- <pre>
require('Module:Mw.html extension')
local p = {}
local format = require('Module:Format equipment stat').format --for formatting the stats with + and - symbols on output
local p2pIcon = '[[File:Member icon.png|frameless|link=Pay-to-play]]' --these icons are for the later members/f2p stars
local f2pIcon = '[[File:Free-to-play icon.png|frameless|link=Free-to-play]]'
local stats = {'astab', 'aslash', 'acrush', 'amagic', 'arange', 'dstab', 'dslash', 'dcrush', 'dmagic', 'drange', 'str', 'rstr', 'mdmg', 'prayer'}
function p.main(frame)
	local args = frame:getParent().args --get the input from the template
	local slot = string.lower(tostring(args['slot'])) --take the slot input as the slot we want the table for
	local mems = args['mems']
	local dmm = args['dmm']
	local beta = args['beta']
	local data = getData(slot,mems,dmm,beta) --this takes the slot and sends it to our getData function (seen below) which gives us back a data table
	local restbl = mw.html.create('table') --start making our results table, beginninig with the header
	restbl:addClass('wikitable align-center-1 sortable align-center')
		:tag('tr')
			:tag('th'):addClass('unsortable'):wikitext(''):done()
			:tag('th'):wikitext('Name'):done()
			:tag('th'):wikitext('Members'):done()
			:tag('th'):wikitext('[[File:White dagger.png|Stab attack]]') :done()
			:tag('th'):wikitext('[[File:White scimitar.png|Slash attack]]') :done()
			:tag('th'):wikitext('[[File:White warhammer.png|Crush attack]]') :done()
			:tag('th'):wikitext('[[File:Magic icon.png|Magic attack]]') :done()
			:tag('th'):wikitext('[[File:Ranged icon.png|Ranged attack]]') :done()
			:tag('th'):wikitext('[[File:White dagger.png|Stab defence]]<sup>[[File:Defence icon.png]]</sup>') :done()
			:tag('th'):wikitext('[[File:White scimitar.png|Slash defence]]<sup>[[File:Defence icon.png]]</sup>') :done()
			:tag('th'):wikitext('[[File:White warhammer.png|Crush defence]]<sup>[[File:Defence icon.png]]</sup>') :done()
			:tag('th'):wikitext('[[File:Magic icon.png|Magic defence]]<sup>[[File:Defence icon.png]]</sup>') :done()
			:tag('th'):wikitext('[[File:Ranged icon.png|Ranged defence]]<sup>[[File:Defence icon.png]]</sup>') :done()
			:tag('th'):wikitext('[[File:Strength icon.png|Strength]]') :done()
			:tag('th'):wikitext('[[File:Ranged Strength icon.png|Ranged Strength]]') :done()
			:tag('th'):wikitext('[[File:Magic Damage icon.png|Magic Damage]]') :done()
			:tag('th'):wikitext('[[File:Prayer icon.png|Prayer]]') :done()
			:tag('th'):wikitext('Weight') :done()
		:done()
	-- Create the rows for the output table
	for _, item in ipairs(data) do    --for each row of data, we take it and split it up, then put it into our table row. We also format them with + and - symbols here
		local row = restbl:tag('tr')
			:tag('td'):wikitext(item.image):done()
			:tag('td'):wikitext(item.name):done()
			:tag('td'):wikitext(item.members):done()
		for _, stat in ipairs(stats) do
			local value = item[stat]
			local value_num = tonumber(value)
			row:tag('td'):wikitext(format(value))
				:addClassIf(value_num and (value_num > 0), 'table-positive')
				:addClassIf(value_num and (value_num < 0), 'table-negative')
		end
		row:tag('td'):wikitext(item.weight):done()
	end
	return tostring(restbl) --returns the table back to the template to be put onto the page
end
function getData(slotName,mems,dmm,beta) --so this is the function that takes the slot name and gets all the data for the items
	--first we set up our SMW query
	local q = {
		'[[Equipment slot::'..slotName..']]', --we want everything that matches the slot we called, and then all the attached data below
		'?Is members only',
		'?Stab attack bonus',
		'?Slash attack bonus',
		'?Crush attack bonus',
		'?Magic attack bonus',
		'?Range attack bonus',
		'?Stab defence bonus',
		'?Slash defence bonus',
		'?Crush defence bonus',
		'?Magic defence bonus',
		'?Range defence bonus',
		'?Strength bonus',
		'?Ranged Strength bonus',
		'?Magic Damage bonus',
		'?Prayer bonus',
		'?Category',
		'?Image',
		'?Weight',
		limit = 1000,
		order = 'ascending'
	}
	local smwdata = mw.smw.ask(q) --this now asks the smw for all the data, and saves all of it in smwdata
	local data = {} --setting this table up to insert processed data into
	for _, item in ipairs(smwdata) do --for each item we found with our smw query
		local process = true
		local dmmcat = false
		local betacat = false
		if type(item['Category']) == 'table' then
			for _, category in ipairs(item['Category']) do
				if category == "[[:Category:Deadman seasonal items|Deadman seasonal items]]" then
					dmmcat = true
				elseif category == "[[:Category:Beta items|Beta items]]" then
					betacat = true
				end
			end
		end
		if mems == 'Members' then
			if not item['Is members only'] then
				process = false
			end
		end
		if mems == 'F2P' then
			if item['Is members only'] then
				process = false
			end
		end
		if dmm == 'No' then
			if dmmcat == true then
				process = false
			end
		end
		if beta == 'No' then
			if betacat == true then
				process = false
			end
		end
		if process then
			local dataline = processData(item) --we process it (seen below) and then save it as a line
			table.insert(data, dataline) --and then we insert that line into our data table to be returned
		end
	end
	return data --and once we've processed all the data we send the data table back up to main for the formatting
end
function processData(item) --this breaks up the smwdata bit into manageable little bites
	local name = item[1] or '' --this gets the item name, which by default is in the first position of the query results (lua starts at 1, not 0)
	local _name = string.match(name, '|(.-)%]')
	
	local members = item['Is members only'] --members we have to do a bit extra for
	if members == true then --if it is members, we use the members star
		members = p2pIcon
	elseif members == false then --if not, use f2p star
		members = f2pIcon
	else
		members = ''
	end
	
	local image = item['Image'] or ''
	if type(image) == 'table' then
		image = image[1] -- take the first image available
	end
	image = string.match(image, '[Ff]ile:.-%.png') or ''
	if image ~= '' then
		image = string.format('[[%s|link=%s]]', image, _name)
	end
	
	local keyset=""
	local n=0
	
	for k,v in pairs(item) do
	  n=n+1
	  keyset = keyset .. k .. " (" .. tostring(v) ..")" .. ":"
	end
	return { --now we return the processed data for this item back to the getData function, which sends us another item and repeats until we've done them all
		name = name,
		image = image,
		members = members,
		astab = item['Stab attack bonus'] or '',
		aslash = item['Slash attack bonus'] or '',
		acrush = item['Crush attack bonus'] or '',
		amagic = item['Magic attack bonus'] or '',
		arange = item['Range attack bonus'] or '',
		dstab = item['Stab defence bonus'] or '',
		dslash = item['Slash defence bonus'] or '',
		dcrush = item['Crush defence bonus'] or '',
		dmagic = item['Magic defence bonus'] or '',
		drange = item['Range defence bonus'] or '',
		str = item['Strength bonus'] or '',
		rstr = item['Ranged Strength bonus'] or '',
		mdmg = item['Magic Damage bonus'] or keyset,
		prayer = item['Prayer bonus'] or '',
		weight = item['Weight'] or '',
	}
end
p.getData = getData
return p