Module:CraftingRecipe

From dos2.wiki
Jump to navigation Jump to search

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

local p = {}

local cargo = mw.ext.cargo
local html = mw.html
local recipeData = mw.loadData('Module:CraftingRecipe/RecipeData')
local categoryIcons = mw.loadData('Module:CraftingRecipe/CategoryIcons')
local stationIcons = mw.loadData('Module:CraftingRecipe/StationIcons')
local propertyIcons = mw.loadData('Module:CraftingRecipe/PropertyIcons')

local function lookupItem(pageName)
	if not pageName or pageName == "" or not cargo then return nil end
	
	local tables = "Items"
	local fields = "name, icon, page_name"
	local where = string.format("page_name = '%s'", pageName:gsub("'", "''"))
	
	local results = cargo.query(tables, fields, { where = where, limit = 1 })
	
	if results and #results > 0 then
		return results[1]
	end
	return nil
end

local function resolveData(args, prefix, index)
	local suffix = index and tostring(index) or ""
	local keyId = prefix .. suffix
	
	local id = args[keyId]
	if not id then return nil end
	
	local data = {
		id = id,
		name = args[keyId .. "_name"],
		icon = args[keyId .. "_icon"],
		link = nil,
		type = args[keyId .. "_type"] or "Object",
		transform = args[keyId .. "_transform"] or "Consume",
		amount = args[keyId .. "_amount"]
	}
	
	local searchName = data.name or id

	if data.type ~= "Category" and data.type ~= "Property" and prefix ~= "station" then
		local cargoData = lookupItem(searchName)
		if cargoData then
			data.name = data.name or cargoData.name
			data.icon = data.icon or cargoData.icon
			data.link = cargoData.page_name
		end
	end
	
	data.name = data.name or id

	if not data.icon then
		if prefix == "station" then
			local foundIcon = stationIcons[data.id]
			if foundIcon then
				data.icon = foundIcon .. "_Icon.webp"
			else
				data.icon = "Icon_World_Gears.png"
			end
		elseif data.type == "Category" then
			local foundIcon = categoryIcons[data.id]
			if foundIcon then
				data.icon = foundIcon .. "_Icon.webp"
			end
		elseif data.type == "Property" then
			local foundIcon = propertyIcons[data.id]
			if foundIcon then
				data.icon = foundIcon .. "_Icon.webp"
			end
		end
	end

	if not data.icon then
		data.icon = "Inv_Unknown_A.webp"
	end

	if not data.link then
		if data.type == "Category" then
			data.link = data.name .. " (Item Category)"
		elseif data.type == "Property" then
			data.link = data.name .. " (Item Property)"
		else
			data.link = data.name
		end
	end
	
	return data
end

local function getRecipeArgs(recipeId)
	local recipe = recipeData[recipeId]
	if not recipe then return nil end

	local args = {}

	if recipe.station then
		args.station = recipe.station
	end

	if recipe.ingredients then
		for i, v in ipairs(recipe.ingredients) do
			local k = "mat" .. i
			args[k] = v.id
			args[k .. "_type"] = v.type
			args[k .. "_name"] = v.name
			args[k .. "_transform"] = v.transform
		end
	end

	if recipe.results then
		for i, v in ipairs(recipe.results) do
			local k = "res" .. i
			args[k] = v.id
			args[k .. "_name"] = v.name
		end
	end

	return args
end

function p.lookup(frame)
	local recipeId = frame.args.recipe
	if not recipeId then return "" end

	local args = getRecipeArgs(recipeId)
	if not args then return "" end

	local mockFrame = {
		args = args,
		expandTemplate = function(self, t) return frame:expandTemplate(t) end
	}

	return p.row(mockFrame)
end

function p.table(frame)
	local recipes = frame.args.recipes
	if not recipes then return "" end

	local output = frame:expandTemplate{ title = 'CraftingTable/Header' }

	for recipeId in mw.text.gsplit(recipes, ",") do
		recipeId = mw.text.trim(recipeId)
		if recipeId ~= "" then
			local args = getRecipeArgs(recipeId)
			if args then
				local mockFrame = {
					args = args,
					expandTemplate = function(self, t) return frame:expandTemplate(t) end
				}
				output = output .. "\n" .. p.row(mockFrame)
			end
		end
	end

	output = output .. "\n" .. frame:expandTemplate{ title = 'CraftingTable/Footer' }
	return output
end

function p.row(frame)
	local args = frame.args
	local tr = html.create('tr')
	
	local res1 = resolveData(args, "res", 1) or resolveData(args, "result", nil)
	local productTd = tr:tag('td')
	
	if res1 then
		local templateArgs = {
			[1] = res1.link,
			name = res1.link,
			override_icon = res1.icon
		}
		productTd:wikitext(frame:expandTemplate{ title = 'MdItemIcon', args = templateArgs })
		
		if res1.amount and tonumber(res1.amount) > 1 then
			productTd:wikitext(" ×" .. res1.amount)
		end
	end

	local inputs = {}
	
	local station = resolveData(args, "station", nil)
	if station then
		station.isStation = true
		table.insert(inputs, station)
	end
	
	for i = 1, 5 do
		local item = resolveData(args, "mat", i)
		if item then table.insert(inputs, item) end
	end
	
	local maxColumns = 5
	local filledColumns = 0
	
	for _, item in ipairs(inputs) do
		if filledColumns < maxColumns then
			local td = tr:tag('td')
			
			if item.isStation then
				td:addClass('recipe-status-station')
			elseif item.transform == "Keep" or item.transform == "None" then
				td:addClass('recipe-status-keep')
			elseif item.transform == "Boost" then
				td:addClass('recipe-status-boost')
			end
			
			local templateArgs = {
				[1] = item.link,
				name = item.link,
				override_icon = item.icon
			}
			td:wikitext(frame:expandTemplate{ title = 'MdItemIcon', args = templateArgs })
			
			if item.amount and tonumber(item.amount) > 1 then
				td:tag('small'):wikitext(" (" .. item.amount .. ")")
			end
			
			filledColumns = filledColumns + 1
		end
	end
	
	if filledColumns < maxColumns then
		tr:tag('td')
			:attr('colspan', maxColumns - filledColumns)
			:css('background-color', 'transparent')
	end

	return tostring(tr)
end

function p.resolveRow(frame)
	local args = {}
	for k, v in pairs(frame.args) do
		args[k] = v
	end

	if args[1] then
		local recipeArgs = getRecipeArgs(args[1])
		if recipeArgs then
			for k, v in pairs(recipeArgs) do
				if args[k] == nil then
					args[k] = v
				end
			end
		end
	end

	local tr = html.create('tr')
	
	local res1 = resolveData(args, "res", 1) or resolveData(args, "result", nil)
	local productTd = tr:tag('td')
	
	if res1 then
		local templateArgs = {
			[1] = res1.link,
			name = res1.link,
			override_icon = res1.icon
		}
		productTd:wikitext(frame:expandTemplate{ title = 'MdItemIcon', args = templateArgs })
		
		if res1.amount and tonumber(res1.amount) > 1 then
			productTd:wikitext(" &times;" .. res1.amount)
		end
	end

	local inputs = {}
	
	local station = resolveData(args, "station", nil)
	if station then
		station.isStation = true
		table.insert(inputs, station)
	end
	
	for i = 1, 5 do
		local item = resolveData(args, "mat", i)
		if item then table.insert(inputs, item) end
	end
	
	local maxColumns = 5
	local filledColumns = 0
	
	for _, item in ipairs(inputs) do
		if filledColumns < maxColumns then
			local td = tr:tag('td')
			
			if item.isStation then
				td:addClass('recipe-status-station')
			elseif item.transform == "Keep" or item.transform == "None" then
				td:addClass('recipe-status-keep')
			elseif item.transform == "Boost" then
				td:addClass('recipe-status-boost')
			end
			
			local templateArgs = {
				[1] = item.link,
				name = item.link,
				override_icon = item.icon
			}
			td:wikitext(frame:expandTemplate{ title = 'MdItemIcon', args = templateArgs })
			
			if item.amount and tonumber(item.amount) > 1 then
				td:tag('small'):wikitext(" (" .. item.amount .. ")")
			end
			
			filledColumns = filledColumns + 1
		end
	end
	
	if filledColumns < maxColumns then
		tr:tag('td')
			:attr('colspan', maxColumns - filledColumns)
			:css('background-color', 'transparent')
	end

	return tostring(tr)
end

return p