Terraria Wiki
Advertisement
Terraria Wiki
Siehe auch die englische Modulseite: Module:Recipes/test2. Sie enthält möglicherweise umfassendere oder aktuellere Informationen.

Für dieses Modul gibt es noch keine Dokumentations-Unterseite. Erstelle jetzt eine.


-- Note: for "Any xxx" group (e.g. "Any Birds"), they should be added to {{tr}} database.
local l10n_info = {
	['de'] = {
		-- for {{recipes}}--
		['cate_unexcepted_rows_count'] = 'Rezepte-Tabelle mit unerwarteter Gesamtzahl an Zeilen',
		['cate_no_row'] = 'Rezepte-Tabelle ohne Zeilen',
		['header_result'] = 'Resultat',
		['header_ingredients'] = 'Zutaten',
		['header_station'] = '[[Herstellungsobjekt]]',

		['cate_craftable'] = 'Herstellbare Gegenstände',

		['station_by_hand'] = '[[kein Objekt]]',
		['station_sep_or'] = "<br/>'''''oder'''''<br/>",
		['station_sep_and'] = " '''und''' ",

		['ingredients_sep'] = " ''oder'' ",
		['snow_biome'] = '[[Tundra]]',

		['station_cate'] = {
			['Lead Anvil'] = 'Eisen- oder Bleiamboss',
			['Iron Anvil'] = 'Eisen- oder Bleiamboss',
			['Orichalcum Anvil'] = 'Mithril- oder Oreichalkosamboss',
			['Mythril Anvil'] = 'Mithril- oder Oreichalkosamboss',
			['Demon Altar'] =  'Dämonen- oder Purpur-Altar',
			['Crimson Altar'] = 'Dämonen- oder Purpur-Altar',
			['Altar'] = 'Dämonen- oder Purpur-Altar',
			['Titanium Forge'] = 'Adamantit- oder Titanschmiede',
			['Adamantite Forge'] = 'Adamantit- oder Titanschmiede',
			['Cauldron'] = 'Kochtopf oder Kessel',
			['Cooking Pot'] = 'Kochtopf oder Kessel',
			['Bottle only'] = 'Platzierte Flasche',
			['Placed Bottle only'] = 'Platzierte Flasche',
			['Bottle'] = 'Platzierte Flasche oder Alchemietisch',
			['Placed Bottle'] = 'Platzierte Flasche oder Alchemietisch',
			['Alchemy Table'] = 'Platzierte Flasche oder Alchemietisch',
			['Water'] = 'Wasser oder Waschbecken',
			['Sink'] = 'Wasser oder Waschbecken',
			['Crystal Ball and Water'] = 'Kristallkugel und Wasser oder Waschbecken',
			['Sky Mill and Snow Biome'] = 'Himmelsmühle und Tundra',
			['Sky Mill and Water'] = 'Himmelsmühle und Wasser oder Waschbecken',
			['Crystal Ball and Lava'] = 'Kristallkugel und Lava',
			['Crystal Ball and Honey'] = 'Kristallkugel und Honig',		
		},
		-- for {{recipes/extract}}--
		['default_sep_compact'] = "<br/>'''oder'''<br/>",
		['default_sep_ingredients'] = "'''oder'''",
		['compact_snow_biome'] = '[[Tundra]]',
	},
}


local l10n_auto_translate_eicons_pagename = {
	['zh'] = true,
}


------- The following is not related to l10n. --------------


local item_link = require('Module:Item').go
local trim = mw.text.trim
local cargo = mw.ext.cargo

local currentFrame -- global cache for current frame object.
local inputArgs -- global args cache.
local lang -- cache current lang.
local l10n_table

local l10n = function(key)
	return l10n_table[key] or l10n_info['en'][key]
end

function getArg(key)
	local v = trim(inputArgs[key] or '')
	if v=='' then
		return nil
	else
		return v
	end
end

local itemLink = function(name, args)
	local args = args or {}
	args[1] = name
	args[2] = currentFrame:expandTemplate{ title = 'tr', args = {name, lang=lang} }
	args['eicons'] = l10n_auto_translate_eicons_pagename[lang]
	args['small'] = 'y'
	args['lang'] = lang or 'en'
	args['nolink'] = args['nolink'] and 'y' or nil
	return item_link(currentFrame, args)
end

-- credit: http://richard.warburton.it
-- this version is with trim.
local explode = function(div,str)
	if (div=='') then return false end
	local pos,arr = 0,{}
	-- for each divider found
	for st,sp in function() return string.find(str,div,pos,true) end do
		table.insert(arr, trim(string.sub(str,pos,st-1))) -- Attach chars left of current divider
		pos = sp + 1 -- Jump past current divider
	end
	table.insert(arr, trim(string.sub(str,pos))) -- Attach chars right of last divider
	return arr
end

-- retuan a array of itemname, split xxx/yyy to item1=xxx, item2=yyy. If it's something like "Lead/Iron Bar", it will normalize as item1 = Iron Bar, item2 = Lead Bar.
local split = (function()
	local metals = {
		['Copper/Tin'] = 1,
		['Silver/Tungsten'] = 1,
		['Gold/Platinum'] = 1,
		['Iron/Lead'] = 1,
		['Cobalt/Palladium'] = 1,
		['Mythril/Orichalcum'] = 1,
		['Adamantite/Titanium'] = 1,
		['Tin/Copper'] = 2,
		['Tungsten/Silver'] = 2,
		['Platinum/Gold'] = 2,
		['Lead/Iron'] = 2,
		['Palladium/Cobalt'] = 2,
		['Orichalcum/Mythril'] = 2,
		['Titanium/Adamantite'] = 2,
	}
	return function(name)
		local count = select(2, name:gsub("/", "/", 2))
		if count == 0 then
			-- only 1 item
			return { trim(name) }
		elseif count == 1 then
			-- 2 items
			local item1a, item1b, item2a, item2b = name:match("^%s*(%S+)%s*(.-)/%s*(%S+)%s*(.-)$")
			local x = metals[item1a..'/'..item2a]
			if tostring(item1b) == '' and x then
				item1b = item2b
			end
			if x == 2 then
				return {trim(item2a..' '..item2b), trim(item1a..' '..item1b)}
			else
				return {trim(item1a..' '..item1b), trim(item2a..' '..item2b)}
			end
		else
			-- 3 or more items
			return explode('/', name)
		end
	end
end)()

-- return 1 or 2 value(s), when input is name[note], return item, note.
local itemname = function(str)
		local item, note = str:match("^(.-)(%b[])$")
		if item then
			return item, note
		else
			return str
		end
end

-- normalize ingredient name input, Lead Bar=>¦Lead Bar¦, Iron/Lead Bar => ¦Iron Bar¦Lead Bar¦, Lead/Iron Bar => ¦Iron Bar¦Lead Bar¦ ....
local normalize = function(name)
	local result = '¦'
	for k, v in ipairs(split(name)) do
		result = result .. itemname(v) .. '¦'
	end
	return result
end

local escape = function(str)
	return str:gsub("'", "\\'"):gsub("&#39;", "\\'")
end
local enclose = function(str)
	return "'" .. escape(str) .. "'"
end

local getItemGroupName = function(item)
	if item == 'Wood' or item == 'Ebonwood' or item == 'Rich Mahogany' or item == 'Pearlwood' or item == 'Shadewood'
	or item == 'Spooky Wood' or item == 'Boreal Wood' or item == 'Palm Wood' then
		return 'Any Wood'
	elseif item == 'Iron Bar' or item == 'Lead Bar' then
		return 'Any Iron Bar'
	elseif item == 'Sand Block' or item == 'Pearlsand Block' or item == 'Crimsand Block' or item == 'Ebonsand Block' or item == 'Hardened Sand Block' then
		return 'Any Sand'
	elseif item == 'Red Pressure Plate' or item == 'Green Pressure Plate' or item == 'Gray Pressure Plate' or item == 'Brown Pressure Plate'
	    or item == 'Blue Pressure Plate' or item == 'Yellow Pressure Plate' or item == 'Lihzahrd Pressure Plate' then
		return 'Any Pressure Plate'
	elseif item == 'Bird' or item == 'Blue Jay' or item == 'Cardinal' then
		return 'Any Bird'
	elseif item == 'Black Scorpion' or item == 'Scorpion' then
		return 'Any Scorpion'
	elseif item == 'Squirrel' or item == 'Red Squirrel' then
		return 'Any Squirrel'
	elseif item == 'Grubby' or item == 'Sluggy' or item == 'Buggy' then
		return 'Any Bug'
	elseif item == 'Mallard Duck' or item == 'Duck' then
		return 'Any Duck'
	elseif item == 'Sulphur Butterfly' or item == 'Julia Butterfly' or item == 'Monarch Butterfly' or item == 'Purple Emperor Butterfly'
	    or item == 'Red Admiral Butterfly' or item == 'Tree Nymph Butterfly' or item == 'Ulysses Butterfly' or item == 'Zebra Swallowtail Butterfly' then
		return 'Any Butterfly'
	elseif item == 'Firefly' or item == 'Lightning Bug' then
		return 'Any Firefly'
	elseif item == 'Snail' or item == 'Glowing Snail' then
		return 'Any Snail'
	end
end

local normalizeStation = function(station)
	if station == 'Altar' then
		station = 'Demon Altar'
	end
	return station
end

local normalizeVersion = function(_version)
	local _version = trim(_version):lower()
	local version = ''
	if _version:find('desktop', 1, true) then
		version = version .. ' desktop'
	end
	if _version:find('console', 1, true) then
		version = version .. ' console'
	elseif _version:find('konsole', 1, true) then
		version = version .. ' console'
	end
	if _version:find('old-gen', 1, true) then
		version = version .. ' old-gen'
	end
	if _version:find('japan', 1, true) then
		version = version .. ' japan'
	end
	if _version:find('mobile', 1, true) then
		version = version .. ' mobile'
	elseif _version:find('mobil', 1, true) then
		version = version .. ' mobile'
	end
	if _version:find('3ds', 1, true) then
		version = version .. ' 3ds'
	end
	if version == ' desktop console old-gen mobile 3ds' then
		version = ''
	elseif version == ' desktop konsole old-gen mobile 3ds' then
		version = ''
	elseif version == ' desktop console old-gen mobil 3ds' then
		version = ''
	elseif version == ' desktop konsole old-gen mobil 3ds' then
		version = ''
	end
	return trim(version)
end

local criStr = function(args)
	local constraints = {}
	-- station = ? and station != ?
	local _station = trim(args['station'] or '')
	local _stationnot = trim(args['stationnot'] or '')
	local str = ''
	if _station ~= '' then
		for _, v in ipairs(explode('/', _station)) do
			if str ~= '' then
				str = str .. ' OR '
			end
			str = str .. "station = " .. enclose(normalizeStation(v))
		end
	end
	if _stationnot ~= '' then
		if str ~= '' then
			str = '(' .. str .. ')'
		end
		for _, v in ipairs(explode('/', _stationnot)) do
			if str ~= '' then
				str = str .. ' AND '
			end
			str = str .. 'station <> ' .. enclose(normalizeStation(v))
		end
	end
	constraints['station'] = str
	-- result = ? and result != ?
	local _result = trim(args['result'] or '')
	local _resultnot = trim(args['resultnot'] or '')
	local str = ''
	if _result ~= '' then
		for _, v in ipairs(explode('/', _result)) do
			if str ~= '' then
				str = str .. ' OR '
			end
			if mw.ustring.sub(v, 1, 5) == 'LIKE ' then
				str = str .. "result LIKE " .. enclose(trim(mw.ustring.sub(v, 6)))
			else
				str = str .. 'result=' .. enclose(v)
			end
		end
	end
	if _resultnot ~= '' then
		if str ~= '' then
			str = '(' .. str .. ')'
		end
		for _, v in ipairs(explode('/', _resultnot)) do
			if str ~= '' then
				str = str .. ' AND '
			end
			if mw.ustring.sub(v, 1, 5) == 'LIKE ' then
				str = str .. "result NOT LIKE " .. enclose(trim(mw.ustring.sub(v, 6)))
			else
				str = str .. 'result <> ' .. enclose(v)
			end
		end
	end
	if str ~= '' then
		constraints['result'] = str
	end
	-- ingredient = ?
	local _ingredient = trim(args['ingredient'] or '')
	if _ingredient ~= '' then
		local str = ''
		for _, v in ipairs(explode('/', _ingredient)) do
			if str ~= '' then
				str = str .. ' OR '
			end
			if mw.ustring.sub(v, 1, 1) == '#' then
				str = str .. "ingredients HOLDS LIKE '%¦" .. escape(mw.ustring.sub(v, 2)) .. "¦%'"
			elseif mw.ustring.sub(v, 1, 5) == 'LIKE ' then
				str = str .. "ingredients HOLDS LIKE '%¦" .. escape(trim(mw.ustring.sub(v, 6))) .. "¦%'"
			else
				str = str .. "ingredients HOLDS LIKE '%¦" .. escape(v) .. "¦%'"
				-- any xxx
				local group = getItemGroupName(v)
				if group then
					str = str .. " OR ingredients HOLDS LIKE '%¦" .. escape(group) .. "¦%'"
				end
			end
		end
		constraints['ingredient'] = str
	end

	--versions
	local _version = normalizeVersion(args['version'] or args['versions'] or '')
	if _version ~= '' then
		constraints['version'] = 'version = '..enclose(_version)
	end

	local where = ''
	if constraints['station'] then
		where = constraints['station']
	end
	if constraints['result'] then
		if where ~= '' then
			where = where .. ' AND '
		end
		where = where .. '(' .. constraints['result'] .. ')'
	end
	if constraints['ingredient'] then
		if where ~= '' then
			where = where .. ' AND '
		end
		where = where .. '(' .. constraints['ingredient'] .. ')'
	end
	if constraints['version'] then
		if where ~= '' then
			where = where .. ' AND '
		end
		where = where .. '(' .. constraints['version'] .. ')'
	end
	return where
end

-- for extract/ingredientsum.
local compactStation = function(station, sep)
	sep = sep or ' @&thinsp;' -- default sep
	if station == 'By Hand' then
		return ''
	elseif station == 'Furnace' or station == 'Work Bench' or station == 'Sawmill' or station == "Tinkerer's Workshop" or station == 'Dye Vat'
	  or station == 'Loom' or station == 'Keg' or station == 'Hellforge' or station == 'Bookcase' or station == 'Imbuing Station' or station == 'Lava'
	  or station == 'Honey' or station == 'Glass Kiln' or station == 'Flesh Cloning Vat' or station == 'Autohammer' or station == 'Crystal Ball'
	  or station == 'Ice Machine' or station == 'Meat Grinder' or station == 'Living Loom' or station == 'Heavy Work Bench' or station == 'Sky Mill'
	  or station == 'Solidifier' or station == 'Honey Dispenser' or station == 'Bone Welder' or station == 'Blend-O-Matic' or station == 'Steampunk Boiler'
	  or station == 'Ancient Manipulator' or station == 'Lihzahrd Furnace' or station == 'Living Wood' then
		return sep .. itemLink(station, {mode = 'image'})
	elseif station == 'Iron Anvil' then
		return sep .. itemLink('Iron Anvil', {mode = 'image'}) .. "&thinsp;/&thinsp;" .. itemLink('Lead Anvil', {mode = 'image'})
	elseif station == 'Adamantite Forge' then
		return sep .. itemLink('Adamantite Forge', {mode = 'image'}) .. "&thinsp;/&thinsp;" .. itemLink('Titanium Forge', {mode = 'image'})
	elseif station == 'Mythril Anvil' then
		return sep .. itemLink('Mythril Anvil', {mode = 'image'}) .. "&thinsp;/&thinsp;" .. itemLink('Orichalcum Anvil', {mode = 'image'})
	elseif station == 'Demon Altar' then
		return sep .. itemLink('Demon Altar', {mode = 'image'}) .. "&thinsp;/&thinsp;" .. itemLink('Crimson Altar', {mode = 'image'})
	elseif station == 'Cooking Pot' then
		return sep .. itemLink('Cooking Pot', {mode = 'image'}) .. "&thinsp;/&thinsp;" .. itemLink('Cauldron', {mode = 'image'})
	elseif station == 'Placed Bottle' then
		return sep .. itemLink('Placed Bottle', {mode = 'image'}) .. "&thinsp;/&thinsp;" .. itemLink('Alchemy Table', {mode = 'image'})
	elseif station == 'Water' then
		return sep .. itemLink('Water', {mode = 'image'}) .. "&thinsp;/&thinsp;" .. itemLink('Sink', {mode = 'image'})
	elseif station == 'Table and Chair' then
		return sep .. itemLink('Table', {mode = 'image'}) .. "&thinsp;&amp;&thinsp;" .. itemLink('Chair', {mode = 'image'})
	elseif station == 'Work Bench and Chair' then
		return sep .. itemLink('Work Bench', {mode = 'image'}) .. "&thinsp;&amp;&thinsp;" .. itemLink('Chair', {mode = 'image'})
	elseif station == 'Crystal Ball and Lava' then
		return sep .. itemLink('Crystal Ball', {mode = 'image'}) .. "&thinsp;&amp;&thinsp;" .. itemLink('Lava', {mode = 'image'})
	elseif station == 'Crystal Ball and Honey' then
		return sep .. itemLink('Crystal Ball', {mode = 'image'}) .. "&thinsp;&amp;&thinsp;" .. itemLink('Honey', {mode = 'image'})
	elseif station == 'Crystal Ball and Water' then
		return sep .. itemLink('Crystal Ball', {mode = 'image'}) .. "&thinsp;&amp;&thinsp;".. '(&thinsp;' .. itemLink('Water', {mode = 'image'}) .. "&thinsp;/&thinsp;" .. itemLink('Sink', {mode = 'image'}) .. '&thinsp;)'
	elseif station == 'Sky Mill and Water' then
		return sep .. itemLink('Sky Mill', {mode = 'image'}) .. "&thinsp;&amp;&thinsp;".. '(&thinsp;' .. itemLink('Water', {mode = 'image'}) .. "&thinsp;/&thinsp;" .. itemLink('Sink', {mode = 'image'}) .. '&thinsp;)'
	elseif station == 'Sky Mill and Snow Biome' then
		return sep .. itemLink('Sky Mill', {mode = 'image'}) .. "&thinsp;&amp;&thinsp;".. l10n('compact_snow_biome')
	elseif station == 'Placed Bottle only' then
		return sep .. itemLink('Placed Bottle', {mode = 'image'})
	else
		return sep .. station
	end
end

local getFlags = function(args)
	local needCate = 1
	local needLink = true
	local _cate = trim(args['cate'] or '')
	if _cate == 'force' or _cate == 'all' then
		needCate = 2
	elseif _cate == 'n' or _cate == 'no' then
		needCate = nil
	end
	local _link = trim(args['link'] or '')
	if _link == 'y' or _link == 'yes' or _link == 'force' then
		needLink = true
	elseif _link == 'n' or _link == 'no' then
		needLink = false
	end
	return needCate, needLink
end

local identicalTables = function(a, b)
	if table.maxn(a) ~= table.maxn(b) then
		return false
	else
		table.sort(a)
		table.sort(b)
		-- sorting is stable enough; we don't expect any elements to be equal
		local i = 0
		for _, v in pairs(a) do
			for _, w in pairs(b) do
				if v == w then
					i = i+1
				end
			end
		end
		return i == table.maxn(a)
	end
end

local subset = function(a, b) -- is table 'a' a subset of table 'b'?
	if table.maxn(a) > table.maxn(b) then
		return false
	else
		table.sort(a)
		table.sort(b)
		-- sorting is stable enough; we don't expect any elements to be equal
		local i = 0
		for _, v in pairs(a) do
			for _, w in pairs(b) do
				if v == w then
					i = i+1
				end
			end
		end
		return i == table.maxn(a)
	end
end

-- only works with tables with numerical keys!
local removeEmptyElements = function(t, mode)
	if mode == 1 then -- table of strings
		local continue = true
		-- keep iterating over the table until no more empty elements are found
		while(continue) do
			if next(t) == nil then
				continue = false
			end
			for i, v in pairs(t) do
				if v == nil or v == '' then
					table.remove(t, i)
					continue = true
					break
				else
					continue = false
				end
			end
		end
		return t
	else -- table of tables
		local continue = true
		-- keep iterating over the table until no more empty elements are found
		while(continue) do
			if next(t) == nil then
				continue = false
			end
			for i, v in pairs(t) do
				if next(v) == nil then
					table.remove(t, i)
					continue = true
					break
				else
					continue = false
				end
			end
		end
		return t
	end
end

local tablelength = function(t)
  local count = 0
  for _ in pairs(t) do count = count + 1 end
  return count
end

-----------------------------------------------------------------

local p = {}

-- for {{recipes/ingredientsum}}
p.ingredientsum = function(frame)
	currentFrame = frame -- global frame cache

	local args = frame:getParent().args
	inputArgs = args

	lang = frame.args['lang'] or 'en'
	l10n_table = l10n_info[lang] or l10n_info['en']

	local where = trim(args['where'] or '')
	if where == '' then
		where = criStr(args)
	end

	-- no constraint no result.
	if where == '' then
		return '<span style="color:red;font-weight:bold;">Recipes/ingredientsum: No constraint</span>'
	end

	-- query:
	local result = mw.ext.cargo.query('Recipes', 'result, resultid, resultimage, resulttext, amount, version, station, args', {
		where = where,
		groupBy = "resultid, result, amount, version, ings",
		orderBy = "result, amount DESC, version", -- Don't order by station
		limit = 30, -- enough.
	})
	
	local str2 = ''
	--str2 = '----------------------------------------------------------------'
	-- determine versions to differentiate between
	local versions = {}
	for i, resultRow in ipairs(result) do
		if resultRow['version'] then
			local v = resultRow['version']
			v = string.gsub(v, ' ', '/')
			if v == '' then
				v = currentFrame:expandTemplate{ title = 'eversions', args = {resultRow['result'], ['raw'] = 'y'} }
			end
			if v == '' then v = 'desktop/console/old-gen/mobile/3ds' end
			local currentVersionGroup = explode('/', v)
			--str2 = str2 .. '<br/><br/>--- Cargo row ' .. i .. ' ---'
			--str2 = str2 .. '<br/>versions add: ' .. table.concat(currentVersionGroup, ', ') 
			--str2 = str2 .. '<br/>versions pre: ^'
			for j, v in ipairs(versions) do
				--if j ~= 1 then str2 = str2 .. ' | ' end
				--str2 = str2 .. table.concat(v, ', ')
			end
			--str2 = str2 .. '$'
			if next(versions) ~= nil and next(versions[next(versions)]) ~= nil then
				--str2 = str2 .. '<br/>Versions does exist. Length: ' .. tostring(table.maxn(versions)) .. ''
				local addVersion = {}
				local dontAdd = false
				for i, versionGroup in ipairs(versions) do
					--str2 = str2 .. '<br/>&emsp;-- Version group ' .. i .. ' --'
					local addVersionGroup = {}
					local versionsDiff= {}
					if identicalTables(currentVersionGroup, versionGroup) then
						dontAdd = true
						--str2 = str2 .. '<br/>&emsp;&emsp;Versions to insert are identical with existing ones.'
						break
					else
						--str2 = str2 .. '<br/>&emsp;&emsp;Versions to insert are different from existing ones.'
	
						for j, v in ipairs(currentVersionGroup) do
							for k, w in ipairs(versionGroup) do
								if w == v and w ~= nil then
									versionsDiff[w] = {
										['indexA'] = k,
										['indexB'] = j
									}
									--str2 = str2 .. '<br/>&emsp;&emsp;Inserting ' .. w .. ' with indexA=' .. k .. ' and indexB='.. j .. ' into versionsDiff'
									break
								end
							end
						end
						for v, indices in pairs(versionsDiff) do
							--str2 = str2 .. '<br/>&emsp;&emsp;Removing element with index ' .. indices['indexB'] .. ' (' .. currentVersionGroup[indices['indexB']] .. '=' .. v .. ') from currentVersionGroup'
							currentVersionGroup[indices['indexB']] = ''
							--str2 = str2 .. '<br/>&emsp;&emsp;currentVersionGroup: ' .. table.concat(currentVersionGroup, '|')
							--str2 = str2 .. '<br/>&emsp;&emsp;Removing element with index ' .. indices['indexA'] .. ' (' .. versionGroup[indices['indexA']] .. '=' .. v .. ') from versionGroup'
							versionGroup[indices['indexA']] = ''
							--str2 = str2 .. '<br/>&emsp;&emsp;versionGroup: ' .. table.concat(versionGroup, '|')
							table.insert(addVersionGroup, v)
						end
						currentVersionGroup = removeEmptyElements(currentVersionGroup, 1)
						--str2 = str2 .. '<br/>&emsp;&emsp;currentVersionGroup: ' .. table.concat(currentVersionGroup, '|')
						versionGroup = removeEmptyElements(versionGroup, 1)
						--str2 = str2 .. '<br/>&emsp;&emsp;versionGroup: ' .. table.concat(versionGroup, '|')
						if next(addVersionGroup) ~= nil then
							table.insert(addVersion, addVersionGroup)
						end
					end
				end
				if (next(addVersion) == nil or next(currentVersionGroup) ~= nil) and not dontAdd then
					--str2 = str2 .. '<br/>No overlaps or a currentVersion left. Add current version as it is.'
					local addVersionGroup = {}
					for _, v in ipairs(currentVersionGroup) do
						table.insert(addVersionGroup, v)
					end
					table.insert(addVersion, addVersionGroup)
				end
				if next(addVersion) ~= nil then
					for _, v in ipairs(addVersion) do
						if next(v) ~= nil then
							table.insert(versions, v)
						end
					end
				end
			else
				--str2 = str2 .. '<br/>Versions does not exist.'
				table.insert(versions, currentVersionGroup)
			end
		end
	
		--str2 = str2 .. '<br/>versions post: '
		for j, v in ipairs(versions) do
			--if j ~= 1 then str2 = str2 .. ' | ' end
			--str2 = str2 .. table.concat(v, ', ')
		end
	
		versions = removeEmptyElements(versions)
		if versions[1][1] == '' then
			table.remove(versions, 1)
		end
		
		--str2 = str2 .. '<br/>versions post: '
		for j, v in ipairs(versions) do
			--if j ~= 1 then str2 = str2 .. ' | ' end
			--str2 = str2 .. table.concat(v, ', ')
		end
		--[[str2 = str2 .. '<br/>versions[1] = ^' .. table.concat(versions[1], ', ') .. '$'
		str2 = str2 .. '<br/>' .. versions[1][1]
		if versions[1][1] == nil then
			str2 = str2 .. ' (nil)'
		end
		if versions[1][1] == '' then
			str2 = str2 .. ' (empty)'
		end]]
	end




	-- output
	local mode = getArg('mode')
	local sep = getArg('sep') or getArg('seperator')
	--default mode = compact
	local sep = sep or l10n('default_sep_compact')
	local withResult = getArg('withresult')
	local withStation = not getArg('nostation')
	local withVersion = not getArg('noversion')
	
	local str = ''
	--local outputStr = ''
	local outputRows = {} -- output rows
	str = str .. '<br/>Cycle through ' .. table.maxn(result) .. ' cargo result(s).'
	
	str = str .. '<br/>Different versions: '
	
	if next(versions) == nil then
		table.insert(versions, {'desktop', 'console', 'old-gen', 'mobile', '3ds'} )
	end
	
	for j, v in ipairs(versions) do
		if j ~= 1 then str = str .. ' | ' end
		str = str .. table.concat(v, ', ')
	end
	str = str .. '<br/>'
	
	for h, versionGroup in ipairs(versions) do
		version = table.concat(versionGroup, ' ')
		if version == '' then version = 'desktop console old-gen mobile 3ds' end
		outputRows[version] = {}
		
		str = str .. '<br/><br/>#### Version: ' .. version .. ' ####<br/>'
		
		local whereCached = where
		
		if versionGroup[next(versionGroup)] ~= '' then
			--str = str .. '<br/>next(versionGroup~=nil and ~=""): Lorem' .. next(versionGroup) .. 'ipsum.'
			where = where .. " AND ((version LIKE '%"
			for j, v in ipairs(versionGroup) do
				if j ~= 1 then
					where = where .. "%' AND version LIKE '%"
				end
				where = where .. v
			end
			where = where .. "%') OR version IS NULL)"
		end
		
		str = str .. '<br/>where for this version: ' .. where
		
		-- query for this specific version group
		local result = mw.ext.cargo.query('Recipes', 'result, resultid, resultimage, resulttext, amount, version, station, args', {
			where = where,
			groupBy = "resultid, result, amount, version, ings",
			orderBy = "result, amount DESC, version", -- Don't order by station
			limit = 20, -- enough.
		})
		where = whereCached -- restore where for next version
		
		if next(result) == nil then
			str = str .. '<br/>Result for this version is empty!'
		end
		
		local results = {}
		local firstRow = true
		for i, resultRow in ipairs(result) do
			local resultItem = tostring(resultRow['result'])
			str = str .. '<br/>: Cargo result row ' .. i .. '/' .. table.maxn(result) .. '.'
			-- skip this row if the result is not available in the current version(s)
			local _eversions = currentFrame:expandTemplate{ title = 'eversions', args = {resultRow['result'], ['raw'] = 'y'} }
			if  _eversions == '' then _eversions = 'desktop/console/old-gen/mobile/3ds' end
			eversions = explode('/', _eversions)
			if subset(versionGroup, eversions) then
				
				-- check if this resultRow requires a new output row
				local newRow = false
				--str = str .. '<br/>:: Cycling through <code>results</code>:'
				for j, v in ipairs(results) do
					--str = str .. '<br/>:::  ' .. j .. ' – ' .. v
					if v == resultItem then -- result is already present, add new row for it
						newRow = true
					end
				end
				--str = str .. '<br/>:: Done.'
				table.insert(results, resultItem) -- add current result to the list of results
				
				
				str = str .. '<br/>:: New output row? ' .. tostring(newRow)
				
				-- handle creation of new output row
				if newRow then
					local oldRowMaxn = table.maxn(outputRows[version])
					 -- cycle through current rows and duplicate them, removing the duplicate result we want to eliminate
					local rowsDupl = {}
					for j, row in ipairs(outputRows[version]) do -- fill duplicate table from source table
						rowsDupl[j] = {}
						rowDupl = rowsDupl[j]
						rowDupl.stations = row.stations
						rowDupl.ingredients = {}
						for k, v in pairs(row.ingredients) do
							rowDupl.ingredients[k] = {}
							for l, w in pairs(v) do
								rowDupl.ingredients[k][l] = w
							end
						end
					end
					for _, rowDupl in ipairs(rowsDupl) do
						if rowDupl.ingredients[resultItem] then
							rowDupl.ingredients[resultItem] = nil
						end
					end
					for _, v in ipairs(rowsDupl) do -- insert duplicate table into source table
						table.insert(outputRows[version], v)
					end
					str = str .. '<br/>:: Duplicated rows from ' .. oldRowMaxn .. ' to ' .. table.maxn(outputRows[version]) .. '.'
				end
				
				str = str .. '<br/>:: Add information from this cargo result row to output row(s).'
				
				if firstRow then -- first row of this version
					firstRow = false
					str = str .. '<br/>:: Creating first row.'
					-- first row in output rows of this version
					local firstRow = {}
					firstRow['ingredients'] = {}
					firstRow['stations'] = {}
					-- information: ingredients
					firstRow.ingredients[resultItem] = {}
					for _, v in ipairs(explode('^', resultRow['args'])) do
						local item, amount = v:match('^(.-)¦(.-)$')
						firstRow.ingredients[resultItem][item] = amount
					end
					-- information: stations
					table.insert(firstRow['stations'], resultRow['station'])
					
					table.insert(outputRows[version], firstRow)
					
					str = str .. '<br/>:: Stored row: <i>'
					for firstRowResult, firstRowResultIngs in pairs(firstRow.ingredients) do
						str = str .. '<br/> ' .. firstRowResult .. ': '
						for l, w in pairs(firstRowResultIngs) do
							str = str .. w .. ' ' .. l .. '&emsp;&emsp;'
						end
					end
					str = str .. '</i>'
					str = str .. '<br/> Station(s): ' .. table.concat(firstRow.stations, ', ')
					
					str = str .. '<br/>:: Check if that got inserted into outputRows: <i>'
					for firstRowResult, firstRowResultIngs in pairs(outputRows[version][1].ingredients) do
						str = str .. '<br/> ' .. firstRowResult .. ': '
						for l, w in pairs(firstRowResultIngs) do
							str = str .. w .. ' ' .. l .. '&emsp;&emsp;'
						end
					end
					str = str .. '</i>'
					str = str .. '<br/> Station(s): ' .. table.concat(outputRows[version][1].stations, ', ')
				else
					--str = str .. '<br/>:: Not creating first row.'
					-- add information from this resultRow to all/new output rows
					for j, row in ipairs(outputRows[version]) do
						str = str .. '<br/>:: outputRows[version] ' .. j .. '.'
						
						local skip = false
						if newRow then
							if j <= table.maxn(outputRows[version])/2 then
								skip = true
							end
						end
						str = str .. '<br/>:: Skip? ' .. j .. '<=' .. table.maxn(outputRows[version])/2 .. ' → ' .. tostring(skip)
						if skip then
							str = str .. "<br/>:: Skip. Don't change the row as it is stored (outputRows[version] " .. j .. '):'
							for k, v in pairs(row.ingredients) do
								str = str .. '<br/> ' .. k .. ': '
								for l, w in pairs(v) do
									str = str .. w .. ' ' .. l .. '&emsp;&emsp;'
								end
							end
						else
							-- information: ingredients
							str = str .. '<br/>:: Storing ingredients.'
							str = str .. '<br/>::: Existing ingredients in this row (outputRows[version] ' .. j .. '):<small>'
							for k, v in pairs(row.ingredients) do
								str = str .. '<br/> ' .. tostring(k) .. ': '
								for l, w in pairs(v) do
									str = str .. w .. ' ' .. l .. '&emsp;&emsp;'
								end
							end
							row.ingredients[resultItem] = {}
							str = str .. '</small>'
							for _, v in ipairs(explode('^', resultRow['args'])) do
								local item, amount = v:match('^(.-)¦(.-)$')
								row.ingredients[resultItem][item] = amount
								str = str .. '<br/>::: Stored ingredient.'
							end
							str = str .. '<br/>::: Now existing ingredients in this row (outputRows[version] ' .. j .. '):<small>'
							for k, v in pairs(row.ingredients) do
								str = str .. '<br/> ' .. tostring(k) .. ': '
								for l, w in pairs(v) do
									str = str .. w .. ' ' .. l .. '&emsp;&emsp;'
								end
							end
							str = str .. '</small>'
							
							-- information: stations
							str = str .. '<br/>:: Storing station.'
							local stations = row['stations'] or {}
							local newStation = true
							for _, station in ipairs(stations) do
								if station == resultRow['station'] then
									newStation = false
								end
							end
							if newStation then
								table.insert(stations, resultRow['station'])
								str = str .. '<br/>::: Stored station.'
							end
							
							str = str .. '<br/>:: Stored row: <i>'
							for k, v in pairs(row.ingredients) do
								str = str .. '<br/> ' .. k .. ': '
								for l, w in pairs(v) do
									str = str .. w .. ' ' .. l .. '&emsp;&emsp;'
								end
							end
							str = str .. '</i>'
							str = str .. '<br/> Station(s): ' .. table.concat(row.stations, ', ')
						end
						
						str = str .. '<br/>:: End output row ' .. j .. '.'
					end
				end
			else
				str = str .. '<br/>: Result item ' .. resultItem .. ' is not available on the current versions ([' .. version .. '] ⊈ [' .. table.concat(eversions, ' ') .. ']). Skipping it.'
			end
			str = str .. '<br/>: End cargo result row ' .. i .. '/' .. table.maxn(result) .. '.'
		end
	end
	str = str .. '<br/>End cargo result cycle.'
	
	str = str .. '<br/><br/>All rows: <i>'
	for version, versionRows in pairs(outputRows) do
		str = str .. '<br/></i>rows with version ' .. version .. '<i>'
		for i, row in ipairs(versionRows) do
			str = str .. '<br/><code>' .. version .. ' ' .. i .. '</code>:'
			for k, v in pairs(row.ingredients) do
				str = str .. '<br/> ' .. k .. ': '
				for l, w in pairs(v) do
					str = str .. w .. ' ' .. l .. '&emsp;&emsp;'
				end
			end
			str = str .. '<br/>' .. table.concat(row.stations)
		end
	end
	str = str .. '</i>'
	
	local finalOutputRows = {}
	for version, versionRows in pairs(outputRows) do
		for i, row in ipairs(versionRows) do
			local insert = {}
			insert['version'] = version
			insert['stations'] = row.stations
			insert['ingredients'] = row.ingredients
			table.insert(finalOutputRows, insert)
		end
	end	
	
	str = str .. '<br/>Start output:<br/><div class=terraria>'
	-- concat print string
	for _, row in ipairs(finalOutputRows) do	
		if outputStr then
			outputStr = outputStr .. sep
		else
			outputStr = ''
		end
		outputStr = outputStr .. '<span class="recipe compact">'
		
		-- version
		if withVersion then
			if row['version'] ~= '' and row['version'] ~= 'desktop console old-gen mobile 3ds' then
				outputStr = outputStr ..currentFrame:expandTemplate{ title = 'version icons', args = {row['version']} }..': '
			end
		end
		
		-- ingredients
		local ingSum = {}
		for k, v in pairs(row.ingredients) do
			for item, amount in pairs(v) do
				if ingSum[item] then
					ingSum[item] = ingSum[item] + amount
				else
					ingSum[item] = amount
				end
			end
		end
		
		-- sort ings
		local ingSumKeys = {}
		for k in pairs(ingSum) do
			table.insert(ingSumKeys, k)
		end
		table.sort(ingSumKeys)
		
		local ingFlag = nil
		for _, k in ipairs(ingSumKeys) do
			local item = k
			local amount = ingSum[k]
			if ingFlag then
				outputStr = outputStr .. ' + '
			else
				ingFlag = true
			end
			if amount ~= '1' then
				outputStr = outputStr .. amount .. ' '
			end
			local s
			for _, itemname in ipairs(split(item)) do
				if s then
					s = s .. "&thinsp;/&thinsp;" .. itemLink(itemname, {mode='image'})
				else
					s = itemLink(itemname, {mode='image'})
				end
			end
			outputStr = outputStr .. s
		end
		
		-- station
		local stationFlag = nil
		if withStation then
			for _, station in ipairs(row['stations']) do
				if station ~= 'By Hand' then
					if stationFlag then
						outputStr = outputStr .. ' + ' .. compactStation(station, '')
					else
						stationFlag = true
						outputStr = outputStr .. compactStation(station)
					end
				end
			end
		end
		
		outputStr = outputStr..'</span>'
	end
	
	str = str .. outputStr .. '</div>End output.<br/><br/>'
	
	return str
end -- p.ingredientsum

return p
Advertisement