<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://wiki.you107657.duckdns.org/index.php?action=history&amp;feed=atom&amp;title=Module%3ANPC_Trades</id>
	<title>Module:NPC Trades - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.you107657.duckdns.org/index.php?action=history&amp;feed=atom&amp;title=Module%3ANPC_Trades"/>
	<link rel="alternate" type="text/html" href="https://wiki.you107657.duckdns.org/index.php?title=Module:NPC_Trades&amp;action=history"/>
	<updated>2026-09-26T22:48:09Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.43.9</generator>
	<entry>
		<id>https://wiki.you107657.duckdns.org/index.php?title=Module:NPC_Trades&amp;diff=13187&amp;oldid=prev</id>
		<title>imported&gt;Merge: merge.py</title>
		<link rel="alternate" type="text/html" href="https://wiki.you107657.duckdns.org/index.php?title=Module:NPC_Trades&amp;diff=13187&amp;oldid=prev"/>
		<updated>2026-09-25T10:55:52Z</updated>

		<summary type="html">&lt;p&gt;merge.py&lt;/p&gt;
&lt;table style=&quot;background-color: #fff; color: #202122;&quot; data-mw=&quot;interface&quot;&gt;
				&lt;tr class=&quot;diff-title&quot; lang=&quot;en&quot;&gt;
				&lt;td colspan=&quot;1&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;← Older revision&lt;/td&gt;
				&lt;td colspan=&quot;1&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;Revision as of 10:55, 25 September 2026&lt;/td&gt;
				&lt;/tr&gt;&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-notice&quot; lang=&quot;en&quot;&gt;&lt;div class=&quot;mw-diff-empty&quot;&gt;(No difference)&lt;/div&gt;
&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;</summary>
		<author><name>imported&gt;Merge</name></author>
	</entry>
	<entry>
		<id>https://wiki.you107657.duckdns.org/index.php?title=Module:NPC_Trades&amp;diff=5370&amp;oldid=prev</id>
		<title>imported&gt;Merge: merge.py</title>
		<link rel="alternate" type="text/html" href="https://wiki.you107657.duckdns.org/index.php?title=Module:NPC_Trades&amp;diff=5370&amp;oldid=prev"/>
		<updated>2026-09-25T10:55:52Z</updated>

		<summary type="html">&lt;p&gt;merge.py&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;local p = {}&lt;br /&gt;
local namespace = mw.title.getCurrentTitle().nsText&lt;br /&gt;
local sprite = require(&amp;quot;Module:SpriteFile&amp;quot;)&lt;br /&gt;
local tradeTable = require(&amp;quot;Module:TradeTable&amp;quot;)&lt;br /&gt;
local refUsed = false&lt;br /&gt;
local note_list = {} -- Track note names that have already been used, so we don&amp;#039;t output them twice&lt;br /&gt;
&lt;br /&gt;
function p.match_wanted(frame)&lt;br /&gt;
	return p._main(frame:getParent().args, &amp;#039;wanted_item&amp;#039;)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.match_given(frame)&lt;br /&gt;
	return p._main(frame:getParent().args, &amp;#039;given_item&amp;#039;)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.match_profession(frame)&lt;br /&gt;
	return p._main(frame:getParent().args, &amp;#039;profession&amp;#039;, true)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function makeTradeLine(data, hideProfession, professionRowspan, levelRowspan, hideXP, hideMulti)&lt;br /&gt;
	local profession = data[&amp;#039;profession&amp;#039;]&lt;br /&gt;
	local level = data[&amp;#039;level&amp;#039;]&lt;br /&gt;
	local probability = data[&amp;#039;probability&amp;#039;]&lt;br /&gt;
	local given_item = data[&amp;#039;given_item&amp;#039;]&lt;br /&gt;
	local given_quant = data[&amp;#039;given_quant&amp;#039;]&lt;br /&gt;
	local given_sprite = data[&amp;#039;given_sprite&amp;#039;]&lt;br /&gt;
	local wanted_item = data[&amp;#039;wanted_item&amp;#039;]&lt;br /&gt;
	local wanted_quant = data[&amp;#039;wanted_quant&amp;#039;]&lt;br /&gt;
	local wanted_sprite = data[&amp;#039;wanted_sprite&amp;#039;]&lt;br /&gt;
	local wanted_item_2 = data[&amp;#039;wanted_item_2&amp;#039;]&lt;br /&gt;
	local wanted_quant_2 = data[&amp;#039;wanted_quant_2&amp;#039;]&lt;br /&gt;
	local wanted_sprite_2 = data[&amp;#039;wanted_sprite_2&amp;#039;]&lt;br /&gt;
	local given_note = data[&amp;#039;given_note&amp;#039;]&lt;br /&gt;
	local given_note_text = data[&amp;#039;given_note_text&amp;#039;]&lt;br /&gt;
	local wanted_note = data[&amp;#039;wanted_note&amp;#039;]&lt;br /&gt;
	local wanted_note_text = data[&amp;#039;wanted_note_text&amp;#039;]&lt;br /&gt;
	local price_multiplier = data[&amp;#039;price_multiplier&amp;#039;]&lt;br /&gt;
	local max_trades = data[&amp;#039;max_trades&amp;#039;]&lt;br /&gt;
	local villager_xp_gain = data[&amp;#039;villager_xp_gain&amp;#039;]&lt;br /&gt;
	&lt;br /&gt;
	if not profession then&lt;br /&gt;
		mw.log(&amp;quot;Error empty profession&amp;quot;)&lt;br /&gt;
		mw.logObject(data)&lt;br /&gt;
		return nil&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local ret = mw.html.create(&amp;#039;tr&amp;#039;):css(&amp;#039;text-align&amp;#039;, &amp;#039;center&amp;#039;)&lt;br /&gt;
	&lt;br /&gt;
	local level_sort_key = 0&lt;br /&gt;
	if level == &amp;#039;Novice&amp;#039; then level_sort_key = 1 end&lt;br /&gt;
	if level == &amp;#039;Apprentice&amp;#039; then level_sort_key = 2 end&lt;br /&gt;
	if level == &amp;#039;Journeyman&amp;#039; then level_sort_key = 3 end&lt;br /&gt;
	if level == &amp;#039;Expert&amp;#039; then level_sort_key = 4 end&lt;br /&gt;
	if level == &amp;#039;Master&amp;#039; then level_sort_key = 5 end&lt;br /&gt;
&lt;br /&gt;
	if not hideProfession and professionRowspan &amp;gt; 0 then&lt;br /&gt;
		ret:tag(&amp;#039;td&amp;#039;):css(&amp;#039;text-align&amp;#039;, &amp;#039;left&amp;#039;)&lt;br /&gt;
			:attr(&amp;#039;rowspan&amp;#039;, professionRowspan)&lt;br /&gt;
			:wikitext(sprite.link({profession, name=&amp;#039;EntitySprite&amp;#039;}))&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	if levelRowspan &amp;gt; 0 then&lt;br /&gt;
		local level_cell = ret:tag(hideProfession and &amp;#039;th&amp;#039; or &amp;#039;td&amp;#039;)&lt;br /&gt;
			:css(&amp;#039;text-align&amp;#039;, hideProfession and &amp;#039;center&amp;#039; or &amp;#039;left&amp;#039;)&lt;br /&gt;
			:attr(&amp;#039;rowspan&amp;#039;, levelRowspan)&lt;br /&gt;
			:attr(&amp;#039;data-sort-value&amp;#039;, level_sort_key)&lt;br /&gt;
		&lt;br /&gt;
		level_cell:wikitext(level)&lt;br /&gt;
	end&lt;br /&gt;
		&lt;br /&gt;
	ret:tag(&amp;#039;td&amp;#039;):wikitext(java_probability)&lt;br /&gt;
	ret:tag(&amp;#039;td&amp;#039;):wikitext(bedrock_probability)&lt;br /&gt;
&lt;br /&gt;
	local wanted = ret:tag(&amp;#039;td&amp;#039;)&lt;br /&gt;
	wanted:wikitext(tradeTable.formatItemOutput(wanted_item, wanted_quant, wanted_item_2, wanted_quant_2, wanted_sprite, wanted_sprite_2))&lt;br /&gt;
	if wanted_note_text then&lt;br /&gt;
		refUsed = true -- Used to set references at footer&lt;br /&gt;
		if wanted_note ~= nil and note_list[wanted_note] == nil then&lt;br /&gt;
			note_list[wanted_note] = wanted_note_text&lt;br /&gt;
		end&lt;br /&gt;
		wanted:wikitext(mw.getCurrentFrame():extensionTag{ name=&amp;#039;ref&amp;#039;, content=wanted_note_text, args = {name=wanted_note, group=&amp;#039;t&amp;#039;}})&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	local given = ret:tag(&amp;#039;td&amp;#039;):wikitext(tradeTable.formatItemOutput(given_item, given_quant, nil, nil, given_sprite))&lt;br /&gt;
	if given_note_text then&lt;br /&gt;
		refUsed = true -- Used to set references at footer&lt;br /&gt;
		if given_note ~= nil and note_list[given_note] == nil then&lt;br /&gt;
			note_list[given_note] = given_note_text&lt;br /&gt;
		end&lt;br /&gt;
		given:wikitext(mw.getCurrentFrame():extensionTag{ name=&amp;#039;ref&amp;#039;, content=given_note_text, args = {name=given_note, group=&amp;#039;t&amp;#039;}})&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	ret:tag(&amp;#039;td&amp;#039;):wikitext(max_trades or &amp;#039;—&amp;#039;)&lt;br /&gt;
	if not hideXP then&lt;br /&gt;
		ret:tag(&amp;#039;td&amp;#039;):wikitext(villager_xp_gain or &amp;#039;—&amp;#039;)&lt;br /&gt;
	end&lt;br /&gt;
	if not hideMulti then&lt;br /&gt;
		ret:tag(&amp;#039;td&amp;#039;):wikitext(price_multiplier or &amp;#039;—&amp;#039;)&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	return ret:done()&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p._main(args, primary, hideProfession)&lt;br /&gt;
	-- Get the trading data from bucket&lt;br /&gt;
	local b = bucket(&amp;#039;trade&amp;#039;)&lt;br /&gt;
		.select(&amp;#039;json&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
	local hideXP = (args.hide_xp and true) or false&lt;br /&gt;
	local hideMulti = (args.hide_multiplier and true) or false&lt;br /&gt;
&lt;br /&gt;
	local wheres = {}&lt;br /&gt;
	if args.name then&lt;br /&gt;
		table.insert(wheres, {primary, args.name})	&lt;br /&gt;
	elseif not args[1] then&lt;br /&gt;
		table.insert(wheres, {primary, mw.title.getCurrentTitle().text})&lt;br /&gt;
	else&lt;br /&gt;
		for _,arg in ipairs(args) do&lt;br /&gt;
			table.insert(wheres, {primary, arg})&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	b.where(bucket.Or(wheres))&lt;br /&gt;
&lt;br /&gt;
	local data = b.run()&lt;br /&gt;
	for i,bucketRow in ipairs(data) do&lt;br /&gt;
		data[i] = mw.text.jsonDecode(bucketRow.json or &amp;#039;{}&amp;#039;)&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- Create the html table to display results&lt;br /&gt;
	local tradeTable = mw.html.create(&amp;#039;table&amp;#039;):addClass(&amp;#039;wikitable sortable autosort=1,a&amp;#039;):css(&amp;#039;text-align&amp;#039;, &amp;#039;center&amp;#039;)&lt;br /&gt;
	&lt;br /&gt;
	-- Generate the table header&lt;br /&gt;
	header = tradeTable&lt;br /&gt;
		:tag(&amp;#039;tr&amp;#039;)&lt;br /&gt;
		:tag(&amp;#039;th&amp;#039;):wikitext(hideProfession and &amp;#039;Level&amp;#039; or &amp;#039;Villager&amp;#039;):attr(&amp;#039;rowspan&amp;#039;, 2):attr(&amp;#039;colspan&amp;#039;, hideProfession and 1 or 2)&lt;br /&gt;
		:tag(&amp;#039;th&amp;#039;):wikitext(&amp;#039;Probability&amp;#039;):attr(&amp;#039;colspan&amp;#039;, 2)&lt;br /&gt;
		:tag(&amp;#039;th&amp;#039;):wikitext(&amp;#039;Villager wants&amp;#039;):attr(&amp;#039;rowspan&amp;#039;, 2)&lt;br /&gt;
		:tag(&amp;#039;th&amp;#039;):wikitext(&amp;#039;Player receives&amp;#039;):attr(&amp;#039;rowspan&amp;#039;, 2)&lt;br /&gt;
		:tag(&amp;#039;th&amp;#039;):wikitext(&amp;#039;Trades in&amp;lt;br&amp;gt;stock&amp;#039;):attr(&amp;#039;rowspan&amp;#039;, 2)&lt;br /&gt;
	if not hideXP then&lt;br /&gt;
		header:tag(&amp;#039;th&amp;#039;):wikitext(&amp;#039;Villager&amp;lt;br&amp;gt;experience&amp;#039;):attr(&amp;#039;rowspan&amp;#039;, 2)&lt;br /&gt;
	end&lt;br /&gt;
	if not hideMulti then&lt;br /&gt;
		header:tag(&amp;#039;th&amp;#039;):wikitext(&amp;#039;Price&amp;lt;br&amp;gt;multiplier&amp;#039;):attr(&amp;#039;rowspan&amp;#039;, 2)&lt;br /&gt;
	end&lt;br /&gt;
	tradeTable&lt;br /&gt;
		:tag(&amp;#039;tr&amp;#039;)&lt;br /&gt;
		:tag(&amp;#039;th&amp;#039;):wikitext(&amp;quot;&amp;#039;&amp;#039;[[JE]]&amp;#039;&amp;#039;&amp;quot;)&lt;br /&gt;
		:tag(&amp;#039;th&amp;#039;):wikitext(&amp;quot;&amp;#039;&amp;#039;[[BE]]&amp;#039;&amp;#039;&amp;quot;)&lt;br /&gt;
	&lt;br /&gt;
	-- If there are no results, add an error category&lt;br /&gt;
	if #data == 0 and namespace == &amp;#039;&amp;#039; then&lt;br /&gt;
		tradeTable:node():wikitext(&amp;#039;[[Category:Empty trade info]]&amp;#039;)&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- Merge rows in the first two cells if appropriate:&lt;br /&gt;
	-- Traverse the list in reverse to set the rowspans for each row&lt;br /&gt;
	local rowspansProfession = {}&lt;br /&gt;
	local rowspansLevel = {}&lt;br /&gt;
	for i = 1,#data do&lt;br /&gt;
		local j = #data + 1 - i&lt;br /&gt;
		if j &amp;gt; 1 then&lt;br /&gt;
			if data[j-1][&amp;#039;profession&amp;#039;] == data[j][&amp;#039;profession&amp;#039;] then&lt;br /&gt;
				rowspansProfession[j-1] = (rowspansProfession[j] or 1) + 1&lt;br /&gt;
				rowspansProfession[j] = 0&lt;br /&gt;
				if data[j-1][&amp;#039;level&amp;#039;] == data[j][&amp;#039;level&amp;#039;] then&lt;br /&gt;
					rowspansLevel[j-1] = (rowspansLevel[j] or 1) + 1&lt;br /&gt;
					rowspansLevel[j] = 0&lt;br /&gt;
				end&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- Generate all the table rows and insert them into the table&lt;br /&gt;
	for i,tradeData in ipairs(data) do&lt;br /&gt;
		local professionRowspan = hideProfession and 0 or rowspansProfession[i] or 1&lt;br /&gt;
		local levelRowspan = rowspansLevel[i] or 1&lt;br /&gt;
		local row = makeTradeLine(tradeData, hideProfession, professionRowspan, levelRowspan, hideXP, hideMulti)&lt;br /&gt;
		tradeTable:node(row)&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return mw.html.create():wikitext(tostring(tradeTable) .. mw.getCurrentFrame():extensionTag{name=&amp;quot;references&amp;quot;, args = {group=&amp;#039;t&amp;#039;}})&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
return p&lt;/div&gt;</summary>
		<author><name>imported&gt;Merge</name></author>
	</entry>
</feed>