Module:NPC Trades

From Tensura Wiki
Jump to navigation Jump to search

Documentation for this module may be created at Module:NPC Trades/doc

local p = {}
local namespace = mw.title.getCurrentTitle().nsText
local sprite = require("Module:SpriteFile")
local tradeTable = require("Module:TradeTable")
local refUsed = false
local note_list = {} -- Track note names that have already been used, so we don't output them twice

function p.match_wanted(frame)
	return p._main(frame:getParent().args, 'wanted_item')
end

function p.match_given(frame)
	return p._main(frame:getParent().args, 'given_item')
end

function p.match_profession(frame)
	return p._main(frame:getParent().args, 'profession', true)
end

local function makeTradeLine(data, hideProfession, professionRowspan, levelRowspan, hideXP, hideMulti)
	local profession = data['profession']
	local level = data['level']
	local probability = data['probability']
	local given_item = data['given_item']
	local given_quant = data['given_quant']
	local given_sprite = data['given_sprite']
	local wanted_item = data['wanted_item']
	local wanted_quant = data['wanted_quant']
	local wanted_sprite = data['wanted_sprite']
	local wanted_item_2 = data['wanted_item_2']
	local wanted_quant_2 = data['wanted_quant_2']
	local wanted_sprite_2 = data['wanted_sprite_2']
	local given_note = data['given_note']
	local given_note_text = data['given_note_text']
	local wanted_note = data['wanted_note']
	local wanted_note_text = data['wanted_note_text']
	local price_multiplier = data['price_multiplier']
	local max_trades = data['max_trades']
	local villager_xp_gain = data['villager_xp_gain']
	
	if not profession then
		mw.log("Error empty profession")
		mw.logObject(data)
		return nil
	end

	local ret = mw.html.create('tr'):css('text-align', 'center')
	
	local level_sort_key = 0
	if level == 'Novice' then level_sort_key = 1 end
	if level == 'Apprentice' then level_sort_key = 2 end
	if level == 'Journeyman' then level_sort_key = 3 end
	if level == 'Expert' then level_sort_key = 4 end
	if level == 'Master' then level_sort_key = 5 end

	if not hideProfession and professionRowspan > 0 then
		ret:tag('td'):css('text-align', 'left')
			:attr('rowspan', professionRowspan)
			:wikitext(sprite.link({profession, name='EntitySprite'}))
	end
	
	if levelRowspan > 0 then
		local level_cell = ret:tag(hideProfession and 'th' or 'td')
			:css('text-align', hideProfession and 'center' or 'left')
			:attr('rowspan', levelRowspan)
			:attr('data-sort-value', level_sort_key)
		
		level_cell:wikitext(level)
	end
		
	ret:tag('td'):wikitext(java_probability)
	ret:tag('td'):wikitext(bedrock_probability)

	local wanted = ret:tag('td')
	wanted:wikitext(tradeTable.formatItemOutput(wanted_item, wanted_quant, wanted_item_2, wanted_quant_2, wanted_sprite, wanted_sprite_2))
	if wanted_note_text then
		refUsed = true -- Used to set references at footer
		if wanted_note ~= nil and note_list[wanted_note] == nil then
			note_list[wanted_note] = wanted_note_text
		end
		wanted:wikitext(mw.getCurrentFrame():extensionTag{ name='ref', content=wanted_note_text, args = {name=wanted_note, group='t'}})
	end
	
	local given = ret:tag('td'):wikitext(tradeTable.formatItemOutput(given_item, given_quant, nil, nil, given_sprite))
	if given_note_text then
		refUsed = true -- Used to set references at footer
		if given_note ~= nil and note_list[given_note] == nil then
			note_list[given_note] = given_note_text
		end
		given:wikitext(mw.getCurrentFrame():extensionTag{ name='ref', content=given_note_text, args = {name=given_note, group='t'}})
	end
	
	ret:tag('td'):wikitext(max_trades or '—')
	if not hideXP then
		ret:tag('td'):wikitext(villager_xp_gain or '—')
	end
	if not hideMulti then
		ret:tag('td'):wikitext(price_multiplier or '—')
	end
	
	return ret:done()
end

function p._main(args, primary, hideProfession)
	-- Get the trading data from bucket
	local b = bucket('trade')
		.select('json')

	local hideXP = (args.hide_xp and true) or false
	local hideMulti = (args.hide_multiplier and true) or false

	local wheres = {}
	if args.name then
		table.insert(wheres, {primary, args.name})	
	elseif not args[1] then
		table.insert(wheres, {primary, mw.title.getCurrentTitle().text})
	else
		for _,arg in ipairs(args) do
			table.insert(wheres, {primary, arg})
		end
	end
	
	b.where(bucket.Or(wheres))

	local data = b.run()
	for i,bucketRow in ipairs(data) do
		data[i] = mw.text.jsonDecode(bucketRow.json or '{}')
	end

	-- Create the html table to display results
	local tradeTable = mw.html.create('table'):addClass('wikitable sortable autosort=1,a'):css('text-align', 'center')
	
	-- Generate the table header
	header = tradeTable
		:tag('tr')
		:tag('th'):wikitext(hideProfession and 'Level' or 'Villager'):attr('rowspan', 2):attr('colspan', hideProfession and 1 or 2)
		:tag('th'):wikitext('Probability'):attr('colspan', 2)
		:tag('th'):wikitext('Villager wants'):attr('rowspan', 2)
		:tag('th'):wikitext('Player receives'):attr('rowspan', 2)
		:tag('th'):wikitext('Trades in<br>stock'):attr('rowspan', 2)
	if not hideXP then
		header:tag('th'):wikitext('Villager<br>experience'):attr('rowspan', 2)
	end
	if not hideMulti then
		header:tag('th'):wikitext('Price<br>multiplier'):attr('rowspan', 2)
	end
	tradeTable
		:tag('tr')
		:tag('th'):wikitext("''[[JE]]''")
		:tag('th'):wikitext("''[[BE]]''")
	
	-- If there are no results, add an error category
	if #data == 0 and namespace == '' then
		tradeTable:node():wikitext('[[Category:Empty trade info]]')
	end

	-- Merge rows in the first two cells if appropriate:
	-- Traverse the list in reverse to set the rowspans for each row
	local rowspansProfession = {}
	local rowspansLevel = {}
	for i = 1,#data do
		local j = #data + 1 - i
		if j > 1 then
			if data[j-1]['profession'] == data[j]['profession'] then
				rowspansProfession[j-1] = (rowspansProfession[j] or 1) + 1
				rowspansProfession[j] = 0
				if data[j-1]['level'] == data[j]['level'] then
					rowspansLevel[j-1] = (rowspansLevel[j] or 1) + 1
					rowspansLevel[j] = 0
				end
			end
		end
	end

	-- Generate all the table rows and insert them into the table
	for i,tradeData in ipairs(data) do
		local professionRowspan = hideProfession and 0 or rowspansProfession[i] or 1
		local levelRowspan = rowspansLevel[i] or 1
		local row = makeTradeLine(tradeData, hideProfession, professionRowspan, levelRowspan, hideXP, hideMulti)
		tradeTable:node(row)
	end

	return mw.html.create():wikitext(tostring(tradeTable) .. mw.getCurrentFrame():extensionTag{name="references", args = {group='t'}})
end

return p