Module:Sandbox/User:Fjara/Sandbox/Rake

From Illerai
Jump to navigation Jump to search

Documentation for this module may be created at Module:Sandbox/User:Fjara/Sandbox/Rake/doc

local p = {}

local buildOutput = require('Module:RuneReq').buildOutput
local paramTest = require('Module:Paramtest')
local yesNo = require('Module:Yesno')
local contains = require('Module:Array').contains

local jsonDecode = mw.text.jsonDecode

local ComboRunes = {
	['Dust rune'] = {'Air rune', 'Earth rune'},
	['Lava rune'] = {'Earth rune', 'Fire rune'},
	['Mist rune'] = {'Air rune', 'Water rune'},
	['Mud rune'] = {'Earth rune', 'Water rune'},
	['Smoke rune'] = {'Air rune', 'Fire rune'},
	['Steam rune'] = {'Fire rune', 'Water rune'},
}

local MemberRunes = { 'Astral rune', 'Blood rune', 'Dust rune', 'Lava rune', 'Mist rune', 'Mud rune', 'Smoke rune', 'Soul rune', 'Steam rune', 'Wrath rune' }
local Spellbooks = { 'Standard', 'Ancient', 'Lunar', 'Arceuus' }

function createRow(isRuneMemberOnly, spellbook, rowData)
	local row = mw.html.create('tr')
		:tag('td'):wikitext(rowData.image):done()
		:tag('td'):wikitext(rowData.name):done()
		:tag('td'):wikitext(rowData.magicLevel):done()
		:tag('td'):wikitext(rowData.runes):done()
		:tag('td'):wikitext(rowData.magicExperience):done()
		:tag('td'):wikitext(rowData.spellType):done()
	if(spellbook == nil) then
		row:tag('td'):wikitext(rowData.spellbookType):done()
	end
	if(((spellbook == nil) or (spellbook == 'Standard')) and (not isRuneMemberOnly)) then
		row:tag('td'):wikitext(rowData.members and '[[File:Member icon.png|center|link=Members]]' or '[[File:Free-to-play icon.png|center|link=Free-to-play]]'):done()
	end
	return row
end

function createHeader(isRuneMemberOnly, spellbook)
	local ret = mw.html.create('table'):addClass('wikitable sortable mw-collapsible mw-collapsed')
		:addClass('align-center-1 align-center-2 align-center-3 align-center-4 align-center-5 align-center-6 align-center-7')
	
	local header = mw.html.create('tr')
		:tag('th'):wikitext('Icon'):done()
		:tag('th'):wikitext('Spell'):done()
		:tag('th'):wikitext('[[File:Magic icon.png|link=|Magic]] level'):done()
		:tag('th'):wikitext('[[Runes]]'):done()
		:tag('th'):wikitext('[[File:Magic icon.png|link=|Magic]] [[Experience]]'):done()
		:tag('th'):wikitext('Spell type'):done()
	
	if(spellbook == nil) then
		ret:addClass('align-center-8')
		header:tag('th'):wikitext('[[Spellbook]]'):done()
	end
	if((spellbook == nil or spellbook == 'Standard') and (not isRuneMemberOnly)) then
		ret:addClass('align-center-8 align-center-9')
		header:tag('th'):wikitext('[[Members]]'):done()
	end
	
	return ret:node(header):done()
end

function loadData(rune, spellbook)
	local query = {
		offset = 0,
		limit = 500,
	}
	local conditions = { '[[Spellbook::+]]' }
	if(ComboRunes[rune]) then
		table.insert(conditions, '[[Uses material::' .. ComboRunes[rune][1] .. ']]')
		table.insert(conditions, '[[Uses material::' .. ComboRunes[rune][2] .. ']]')
	else
		table.insert(conditions, '[[Uses material::' .. rune .. ']]')
	end
	if(spellbook) then
		table.insert(conditions, '[[Spellbook::' .. spellbook .. ' spellbook]]')
	end
	table.insert(query, table.concat(conditions))
	table.insert(query, '?=#-')
	table.insert(query, '?Image = image')
	table.insert(query, '?Magic level = magicLevel')
	table.insert(query, '?Spell JSON = json')
	table.insert(query, '?Magic experience = magicExperience')
	table.insert(query, '?Spell type = spellType')
	table.insert(query, '?Spellbook = spellbookType')
	table.insert(query, '?Is members only = members')
	
	local t1 = os.clock()
	local smwData = mw.smw.ask(query)
	local t2 = os.clock()
	
	assert(smwData ~= nil and #smwData > 0, 'No spells found with ' .. spellbook .. ' and ' .. rune)
	mw.log(string.format('SMW: Found %i, offset %i, limit %i, time elapsed %.3f ms', #smwData, query.offset, query.limit, (t2 - t1) * 1000))

	-- Format data in table to be usable elsewhere
	for _, datum in ipairs(smwData) do
		datum.name = '[[' .. datum[1] .. ']]'
		datum[1] = nil
		datum.image = datum.image:sub(1, datum.image:find('|') - 1) .. ']]'
		-- Format rune quantities identically to buildOutput input parameters
		local json = jsonDecode(datum.json)
		local itemCount = {}
		for _, runeData in ipairs(json.runes) do
			table.insert(itemCount, { runeData.rune, runeData.quantity } )
		end
		datum.runes = buildOutput(itemCount, json.bolts, json.staff, json.prayer)
		datum.spellType = datum.spellType:sub(4, datum.spellType:find(' ') - 1)
		if(type(datum.spellbookType) == 'table') then
			local bookConcat = ''
			for i, book in ipairs(datum.spellbookType) do
				bookConcat = bookConcat .. book:sub(4, book:find(' ') - 1)
				if(i < #datum.spellbookType) then
					bookConcat = bookConcat .. '<br/>'
				end
			end
			datum.spellbookType = bookConcat
		else
			datum.spellbookType = datum.spellbookType:sub(4, datum.spellbookType:find(' ') - 1)
		end
	end
	-- Sort the rows by Magic level
	
	local sortOrder = {}
	for _, rowData in ipairs(smwData) do
		rowData.magicLevel = ''
	end
	
	table.sort(sortorder, function(a, b) return (a > b) end)
	
	return smwData
end

function p._main(args)
	local rune = paramTest.default_to(paramTest.ucflc(args.rune), nil)
	local spellbook = paramTest.default_to(paramTest.ucflc(args.spellbook), nil)
	assert(contains(Spellbooks, spellbook), 'Invalid spellbook: ' .. spellbook)
	assert(contains(MemberRunes, rune), 'Invalid rune: ' .. rune)
	
	local isRuneMemberOnly = contains(MemberRunes, rune)
	
	local data = loadData(rune, spellbook)
	local ret = createHeader(isRuneMemberOnly, spellbook)
	for _, rowData in ipairs(data) do
		ret:node(createRow(isRuneMemberOnly, spellbook, rowData))
	end
	
	return ret
end

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

return p