Module:RenderRecipe: Difference between revisions

From Against the Storm Official Wiki
m (added some logging for now)
m (removed logging)
Tag: Manual revert
Line 93: Line 93:
return "Render_Recipe Error: no recipes found at building=" .. argBuildingName .. "."
return "Render_Recipe Error: no recipes found at building=" .. argBuildingName .. "."
end
end
mw.log("it returned to here")
mw.logObject(tableOfRecipes)
local strToReturn = ""
local strToReturn = "<nowiki>"
-- go through each recipe and just send it straight to the table renderer, since the place already matches
-- go through each recipe and just send it straight to the table renderer, since the place already matches
for j, recipe in ipairs(tableOfRecipes) do
for j, recipe in ipairs(tableOfRecipes) do
Line 106: Line 105:
strToReturn = strToReturn .. RenderRecipe.renderTable(recipe)
strToReturn = strToReturn .. RenderRecipe.renderTable(recipe)
end
end
strToReturn = strToReturn .. "</nowiki>"
return strToReturn
return strToReturn

Revision as of 05:31, 9 February 2023

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

-------------------------------------------------------------------------------
-- Renders the {{recipe}} template
--
-- Takes at least one argument. The first, requried, is the name of the 
-- resource for which the recipes are needed. Optionally, the second argument
-- is the name of the building.
-- This module renders small wikimarkup tables to represent one or more 
-- recipes: one table if the building was specified. several tables 
-- corresponding to all the buildings in which the resource can be produced.
-------------------------------------------------------------------------------

local RenderRecipe = {}

local RecipeData = require("Module:RecipeData") -- lookup table for recipes



-------------------------------------------------------------------------------
-- Constants
-------------------------------------------------------------------------------
local CSS_CLASS_RECIPE_TABLE = "class=\"ATSrecipe\""
local CSS_CLASS_REQUIRED_INGREDIENT =  "class=\"ATSrequired\""
local CSS_CLASS_SWAPPABLE_INGREDIENT = "class=\"ATSswappable\""
local TEMPLATE_BUILDING_LINK = "Building_link"
local TEMPLATE_RESOURCE_LINK = "Resource_link"
local TEMPLATE_STAR_SUFFIX = "Star"
local BR = "<br />"
local NL = "\n\n"



-------------------------------------------------------------------------------
-- Main rendering function
-- uses ResourceData lookup function, parses the result and handles errors 
-- with default values, then assembles a final string to return to the wiki
-------------------------------------------------------------------------------
-- need this in whole-class scope, sorry
local thisFrame = {}

function RenderRecipe.renderRecipe(frame)
	
	-- need to set the class variable so expandTemplate can work later
	thisFrame = frame

	local argProductName = frame.args.product
	local argBuildingName = frame.args.building
	
	-- both product and building are specified
	if argProductName and argProductName ~= "" and argBuildingName and argBuildingName ~= "" then
		
		-- returns exactly one recipe with one place
		local recipe = RecipeData.getRecipeAtBuilding(argProductName, argBuildingName)
		if not recipe then
			return "Render_Recipe Error: no recipe found with product=" .. argProductName .. " and building=" .. argBuildingName .. "."
		end
		
		-- only one to render
		-- renderTable will use just the first place in the recipe, which is perfect for this version with only one place
		return RenderRecipe.renderTable(recipe)
	
	-- only product is specified
	elseif argProductName and argProductName ~= "" then
		
		-- gets a whole product's recipe stack, which may be any number of places (1-6)
		local tRecipe = RecipeData.getRecipeForProduct(argProductName)
		if not tRecipe then
			return "Render_Recipe Error: no recipe found with product=" .. argProductName .. "."
		end
		
		local strToReturn = ""
		
		-- go through each place and send a simplified (one place) version of tRecipe to the table renderer
		for i, place in ipairs(tRecipe.places) do
		
			local tempRecipe = { product=argProductName, pattern=tRecipe.pattern, places={place} }
			
			if i > 1 then
				strToReturn = strToReturn .. NL -- separate tables with new lines
			end
			
			-- concatenate the tables together
			strToReturn = strToReturn .. RenderRecipe.renderTable(tempRecipe)
		end
		
		return strToReturn
	
	-- only building is specified
	elseif argBuildingName and argBuildingName ~= "" then
		
		-- gets a table of recipes for different products, each one has exactly one place
		local tableOfRecipes = RecipeData.getBuildingsRecipes(argBuildingName)
		if not tableOfRecipes then
			return "Render_Recipe Error: no recipes found at building=" .. argBuildingName .. "."
		end
		
		local strToReturn = ""
		-- go through each recipe and just send it straight to the table renderer, since the place already matches
		for j, recipe in ipairs(tableOfRecipes) do
			
			if j > 1 then
				strToReturn = strToReturn .. NL -- separate tables with new lines
			end
			
			-- concatenate the tables together
			strToReturn = strToReturn .. RenderRecipe.renderTable(recipe)
		end
		
		return strToReturn
	
	-- something was bad about the arguments; can't print them since they may be nil
	else
		return "Render_Recipe Error: invalid template parameters. at least a product or building is required"
	end
	
	-- does not get here, all if/else resulted in returns
end



-- writes the wiki table markup to represent a recipe
-- takes a recipe table (pattern and place), and uses only the first place
function RenderRecipe.renderTable(tRecipe)

	if not tRecipe then
		return nil
	end
	
	-- call the helper functions to extract the data, make sure we have something usable,
	-- then get only the first values since we're assuming that there's only one top-level record in tRecipe
	local building, stars = RecipeData.getBuildingsAndStarsLists(tRecipe)
	if building and stars then
		building, stars = building[1], stars[1]
	else
		return "Render_Recipe Error: did not find building or stars in recipe."
	end
	
	local speed = RecipeData.getProductionSpeed(tRecipe)
	if speed then
		speed = speed[1]
	else
		return "Render_Recipe Error: did not find production speed in recipe."
	end
	
	local product, number = RecipeData.getProductAndNumbers(tRecipe)
	if product and number then
		number = number[1]
	else
		return "Render_Recipe Error: did not find product or output numbers in recipe."
	end
	
	-- need separate error checking, because ingredients is the same structure as EACH 
	-- of the top-level elements of quantities
	local ingredients, quantities = RecipeData.getIngredientsAndQuantities(tRecipe)
	if not ingredients or 0 == #ingredients then
		return "Render_Recipe Error: did not find ingredients in recipe."
	end
	-- just want the first values since we're assuming there's only one top-level record in tRecipe
	if quantities then
		quantities = quantities[1] -- now ingredients and quantities have the same structure
	else
		return "Render_Recipe Error: did not find quantities in recipe."
	end
	
	local wikiTable = "{| " .. CSS_CLASS_RECIPE_TABLE .. NL .. 
    "| " .. RenderRecipe.blTemplate(building) .. BR .. RenderRecipe.starTemplate(stars) .. BR .. speed .. NL
	
	-- looping over groups of alternative ingredients and quantities simultaneously, 
	-- so use local group and groupOfQuantities for each i
	for i, group in ipairs(ingredients) do
		local groupOfQuantities = quantities[i]
		
		-- on all but the first group, create a new cell with a + sign to separate ingredient groups
		if i > 1 then
			wikiTable = wikiTable .. NL .. "| + " .. NL
		end
		
		-- prefix the table cell based on whether there's only one (required) or more (swappable) ingredients
		-- in the group
		if 1 == #group then
			wikiTable = wikiTable ..
			"| " .. CSS_CLASS_REQUIRED_INGREDIENT .. " | "
		else
			wikiTable = wikiTable ..
			"| " .. CSS_CLASS_SWAPPABLE_INGREDIENT .. " | "
		end
		
		-- for every group, list out the required or alternatives within that group
		for j, alt in ipairs(group) do
			local quant = groupOfQuantities[j]
			
			-- need to add breaks only between the first and any subsequent options
			if j > 1 then
				wikiTable = wikiTable .. BR
			end
			
			wikiTable = wikiTable .. quant .. " " .. RenderRecipe.rlTemplate(alt) -- line breaks handled by above if statement and addition below for close
		end
		
	end
    
	wikiTable = wikiTable .. NL ..
	"| = " .. NL ..
	"| " .. number .. " " .. RenderRecipe.rlTemplate(product,"large") .. NL ..
	"|}"
	
    return wikiTable
end



-- redirect a rendering request to the recipe data and create appropriate 
-- templates for the list. The caller can decide how to output the list
function RenderRecipe.getBuildingsAndStarsForProduct(frame)

	local argProductName = frame.args.product
	
	-- make sure there's an argument to work with
	if not tableRecipe then
		return "Render_Recipe Error: no product given."
	end
	
	-- get the associated recipe data, including all buildings
	local tableRecipe = RecipeData.getAllRecipes(argProductName)
	-- make sure what's returned is valid before we loop through it
	if not tableRecipe or not tableRecipe.places or #tableRecipe.places < 1 then
		return "Render_Recipe Error: no recipes found"
	end
	
	local listOfTemplates = {}
	local buildings, stars = RecipeData.getBuildingsAndStarsLists(tRecipe)
	
	-- loop through the buildings and stars and build the templates
	for i, building in pairs(buildings) do
		listOfTemplates[i] = RenderRecipe.blTemplate(building) .. " " .. RenderRecipe.pstarTemplate(stars[i])
	end
	
	return listOfTemplates
end



-------------------------------------------------------------------------------
-- Helper rendering functions
-- these do not call member functions, but write out the actual templates
-- (which will in turn invoke the code. this is to protect variations in the
-- modules, but we may decide later it should be different)
-------------------------------------------------------------------------------
--use huge size for recipes unless speified
function RenderRecipe.blTemplate(strBuilding,strSize)
	
	if not strSize then
		strSize = "huge"
	end
	
	--return "{{" .. TEMPLATE_BUILDING_LINK .. "|" .. strBuilding .. "|" .. strSize .. "}}"
	return thisFrame:expandTemplate{ title=TEMPLATE_BUILDING_LINK, args={ strBuilding, strSize } }
end

-- use recipe-sized icons, "med", unless specified
function RenderRecipe.rlTemplate(strResource,strSize)
	
	if not strSize then
		strSize = "med"
	end
	
	--return "{{" .. TEMPLATE_RESOURCE_LINK .. "|" .. strResource .. "|" .. strSize .. "}}"
	return thisFrame:expandTemplate{ title=TEMPLATE_RESOURCE_LINK, args={ strResource, strSize } }
end

-- use the parentheses version, with "P"
function RenderRecipe.pstarTemplate(intStars)
	
	--return "{{P" .. intStars .. "star}}"
	return thisFrame:expandTemplate{ title= "P" .. intStars .. TEMPLATE_STAR_SUFFIX}
end

-- no parens version
function RenderRecipe.starTemplate(intStars)
	
	--return "{{" .. intStars .. "star}}"
	return thisFrame:expandTemplate{ title= intStars .. TEMPLATE_STAR_SUFFIX}
end



-------------------------------------------------------------------------------
-- Return when required into another Module.
-------------------------------------------------------------------------------
return RenderRecipe