Module:RecipeData: Difference between revisions

From Against the Storm Official Wiki
m (more commenting)
No edit summary
Line 1: Line 1:
-------------------------------------------------------------------------------
-------------------------------------------------------------------------------
-- Lua storage table for looking up wiki pages, names, and recipes
-- Renders the {{recipe}} template
-- based on in-game names. All data is in English.
--
--
-- The table contains some deconfliction, but only for spaces, apostrophes, and
-- Takes at least one argument. The first, requried, is the name of the
-- some singular/plural.
-- resource for which the recipes are needed. Optionally, the second argument
-- Use in-game names for things, and help keep this table updated as the game
-- is the name of the building.
-- is updated.
-- This module renders small wikimarkup tables to represent one or more
--
-- recipes: one table if the building was specified. several tables
-- Using the table requires a locally defined lookup function that performs
-- corresponding to all the buildings in which the resource can be produced.
-- a string.lower on the argument so that the lookup table can accept any case
-- and still function properly. Otherwise, we would need the table to define
-- both Berries = "Berries" and berries = "Berries" which would multiply our
-- work.
-------------------------------------------------------------------------------
-------------------------------------------------------------------------------


local RenderRecipe = {}


-- for returning when REQUIRE'd by other Lua modules.
local RecipeData = require("Module:RecipeData") -- lookup table for recipes
local RecipeData = {}
 
local ResourceData = require("Module:ResourceData") -- need to reuse the normalize method
local BuildingData = require("Module:BuildingData") -- need to reuse the normalize method




Line 27: Line 19:
-- Constants
-- Constants
-------------------------------------------------------------------------------
-------------------------------------------------------------------------------
-- if needed
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 BR = " <br /> "
local NL = " \n "






-------------------------------------------------------------------------------
-------------------------------------------------------------------------------
-- Main data table, with string keys and string values.
-- Main rendering function
-- Some of these are defined inline with string.lower to make the key easier
-- uses ResourceData lookup function, parses the result and handles errors
-- to spell and read correctly.
-- with default values, then assembles a final string to return to the wiki
-------------------------------------------------------------------------------
-------------------------------------------------------------------------------
function RenderRecipe.renderRecipe(frame)


-- a design decision of this table is to make the key the same as the product name.
local argProductName = frame.args.product
-- (the lookup methods will automatically make it lowercase.)
local argBuildingName = frame.args.building
-- that way, whenever .product is referenced, it can be used again to retrieve
-- the rest of the data.
local tableData = {
---------------------------------------
if not argProductName then
-- Recipes
return "Render_Recipe Error: no product given."
-- product: string: name of the product, as it appears in the game
end
-- pattern: table of tables: the basic components of the recipe that don't depend on buildings, stars, or numbers of things.
-- pattern/1..n: table of strings: use as many inner tables as necessary to represent each the ingredients of the recipe (no numbers here; they go with the stars). if an ingredient is required, then use a table with only one string in it, like this: {"Flour"}. please use the same order as in the in-game recipe book, left-to-right, for consistency
-- used by second case where we need to loop over the results
-- places: table: 1..n: the info that depends on the buildings and stars
local strToReturn = ""
-- places/1..n: table of tables: the building, stars, the speed (production time), the number of input resources (including all options) required, and the number of output yield (usually 10). please use the same order as the in-game recipe book, top-to-bottom, for consistency.
-- building: string: building name, as written in-game (spelling and punctuation count)
-- stars: integer: stars number, 0 (red) to 3
-- speed: string: production time, in the format 00:00 for minutes and seconds
-- places/quantities: array of arrays: corresponding to the order of ingredients in the pattern table.
-- places/quantities/1..n: array of integers: number of required ingredients for each alternative
-- out: integer: count of product (usually 10)
---------------------------------------
-- Raw Food
["eggs"] = { product="Eggs", pattern={ {"Grain","Insects","Reeds","Berries"} },
places={ {building="Ranch", stars=1, speed="01:24", quantities={{3,2,2,2}}, out=10} } },
["meat"] = { product="Meat", pattern={ {"Plant Fiber","Reeds","Grain","Vegetables"} },
places={ {building="Ranch", stars=1, speed="01:24", quantities={{8,8,8,5}}, out=10} } },
["mushrooms"] = { product="Mushrooms", pattern={ {"Drizzle Water"} },
places={ {building="Greenhouse", stars=2, speed="01:24", quantities={{4}}, out=4} } },
-- Complex Food
["biscuits"] = { product="Biscuits", pattern={ {"Flour"}, {"Vegetables","Berries","Roots"} },
places={ {building="Field Kitchen", stars=0, speed="02:06", quantities={{10},{4,4,4}}, out=10},
{building="Bakery", stars=2, speed="02:06", quantities={{8},{3,3,3}}, out=10},
{building="Cookhouse", stars=2, speed="02:06", quantities={{8},{3,3,3}}, out=10},
{building="Smelter", stars=1, speed="02:06", quantities={{8},{4,4,4}}, out=10},
{building="Apothecary", stars=2, speed="02:06", quantities={{8},{3,3,3}}, out=10}
} },
["jerky"] = { product="Jerky" },
["pickled goods"] = { product="Pickled Goods" },
["pie"] = { product="Pie" },
["skewers"] = { product="Skewers" },
-- Building Materials
["bricks"] = { product="Bricks" },
["fabric"] = { product="Fabric" },
["planks"] = { product="Planks" },
["parts"] = { product="Parts" },
["wildfire essence"] = { product="Wildfire Essence" },
-- Consumable Items
["coats"] = { product="Coats" },
["ale"] = { product="Ale" },
["cosmetics"] = { product="Cosmetics" },
["incense"] = { product="Incense" },
["scrolls"] = { product="Scrolls" },
["training gear"] = { product="Training Gear" },
["wine"] = { product="Wine" },
-- Crafting Materials
["clay"] = { product="Clay" },
["copper ore"] = { product="Copper Ore" },
["crystalized dew"] = { product="Crystalized Dew" },
["grain"] = { product="Grain" },
["herbs"] = { product="Herbs" },
["leather"] = { product="Leather" },
["plant fiber"] = { product="Plant Fiber" },
["reeds"] = { product="Reeds" },
["resin"] = { product="Resin" },
["sparkdew"] = { product="Sparkdew" },
["stone"] = { product="Stone" },
-- Refined Crafting Materials
["barrels"] = { product="Barrels" },
["copper bars"] = { product="Copper Bars" },
["flour"] = { product="Flour" },
["pigment"] = { product="Pigment" },
["pottery"] = { product="Pottery" },
["waterskins"] = { product="Waterskins" },
-- Trade Goods
["amber"] = { product="Amber" },
["ancient tablet"] = { product="Ancient Tablet" },
["pack of building materials"] = { product="Pack of Building Materials" },
["pack of crops"] = { product="Pack of Crops"},
["pack of luxury goods"] = { product="Pack of Luxury Goods" },
["pack of provisions"] = { product="Pack of Provisions" },
["pack of trade goods"] = { product="Pack of Trade Goods" },
-- Meta resources
["artifacts"] = { product="Artifacts" },
["food stockpiles"] = { product="Food Stockpiles" },
["machinery"] = { product="Machinery" },
-- Fuel & Exploration
["coal"] = { product="Coal" },
["oil"] = { product="Oil" },
["sea marrow"] = { product="Sea Marrow" },
["wood"] = { product="Wood" },
["simple tools"] = { product="Simple Tools" },
["infused tools"] = { product="Infused Tools" },
["purging fire"] = { product="Purging Fire" },
-- Rain
["clearance water"] = { product="Clearance Water" },
["drizzle water"] = { product="Drizzle Water" },
["storm water"] = { product="Storm Water" }
}
 
 
 
-------------------------------------------------------------------------------
-- Main lookup functions
-- Accepts the in-game name and returns the recipe associated with the
-- specified product.
-------------------------------------------------------------------------------
 
 
 
-- returns the whole recipe table for a given product
-- need to run normalize function first
-- this (currently) returns a reference, not a copy, so be careful not to change the data
function RecipeData.getAllRecipes(strArg)
if not strArg then
-- decide how to proceed based on whether the building was specified
return "Recipe_Data Error: product not given."
if argBuildingName then -- 1. easier case, when the building was specified
local tRecipe = RecipeData.getRecipeAtBuilding(argProductName, argBuildingName)
if not tRecipe then
return "Render_Recipe Error: no recipe found."
end
--renderTable will use just the first place in the recipe, which is perfect for this version
return renderTable(tRecipe)
else -- 2. harder case, when no building was specified, need to loop
local tRecipe = RecipeData.getAllRecipes(argProductName)
if not tRecipe then
return "Render_Recipe Error: no recipe found."
end
-- go through each place and send a shallow copy version of tRecipe to the table renderer,
-- then concatenate them with appropriate wiki markup
for i, place in pairs(tRecipe.places) do
local tempRecipe = { product=argProductName, pattern=tRecipe.pattern, places=place }
return tempRecipe end end end function more() if 1 then if 1 then
strToReturn = strToReturn .. "\n\n" .. RenderRecipe.renderTable(tRecipe)
end
end
end
-- normalize input using resource normalizer method
    local strProductName = RecipeData.normalizeProductName(strArg)
-- Get it from the big table above and return the whole pattern and places contents
return strToReturn
    return tableData[strProductName]
end
end






-- extract the pattern from the recipe table
-- writes the wiki table markup to represent a recipe
-- hide the internals from calling modules
-- takes a recipe table (pattern and place), and uses only the first place
function RecipeData.getPatternFromRecipe(tRecipe)
function RenderRecipe.renderTable(tRecipe)
 
return tRecipe.pattern
end


-- extract the recipe specifics for a given building.
-- this will return a reduced recipe table (following the specification above),
-- with only one place, corresponding to the provided building.
-- this function returns raw data, so other helper functions are necessary to
-- hide internals from calling methods.
-- error handling will be necessary by calling function.
function RecipeData.getRecipeAtBuilding(strArg1, strArg2)
if not strArg1 then
return "Recipe_Data Error: product not given."
end
if not strArg2 then
return "Recipe_Data Error: building not given."
end
-- normalize inputs using resource and building normalizer methods
    local strProductName = RecipeData.normalizeProductName(strArg1)
local strBuildingName = RecipeData.normalizeBuildingName(strArg2)
-- start with the table for the product, then find the building within its places
local tRecipe = tableData[strProductName]
-- and make sure there's something to do
if not tRecipe then
if not tRecipe then
return nil
return nil
end
end
-- build a separate, simplified table to return
-- call the helper functions to extract the data, make sure we have something usable,
local tableToReturn = {}
-- then get only the first values since we're assuming that there's only one top-level record in tRecipe
tableToReturn.product = tRecipe.product
local building, stars = RecipeData.getBuildingsAndStarsLists(tRecipe)
tableToReturn.pattern = tRecipe.pattern
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
-- loop over the places. once the building matches, copy just that place (reference) into the table to return
local speed = RecipeData.getProductionSpeed(tRecipe)
for _, place in pairs(tRecipe.places) do
if speed then
if place.building == strBuildingName then
speed = speed[1]
tableToReturn.places = {place}
else
return tableToReturn
return "Render_Recipe Error: did not find production speed in recipe."
end
end
end
-- the building was not found, so return nothing
local product, number = RecipeData.getProductAndNumbers(tRecipe)
return nil
if product and number then
end
number = number[1]
 
else
 
return "Render_Recipe Error: did not find product or output numbers in recipe."
 
end
-- hide the internals of the previous methods.
-- extract a list of buildings and stars, then the caller can decide how to output the list
function RecipeData.getBuildingsAndStarsLists(tRecipe)
-- make sure we have something to work with
-- need separate error checking, because ingredients is the same structure as EACH
if not tRecipe or not tRecipe.places or #tRecipe.places < 1 then
-- of the top-level elements of quantities
return nil, nil
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
end
local strBuildings = {}
local wikiTable = "{| " .. CSS_CLASS_RECIPE_TABLE .. NL ..
local intStars = {}
    "| " .. RenderRecipe.blTemplate(building) .. BR .. RenderRecipe.starTemplate(stars) .. BR .. speed .. NL
-- loop through the places, extracting the strings and integers for the buildings and stars
-- looping over groups of alternative ingredients and quantities simultaneously,  
-- and storing them in the tables that will be returned
-- so use local group and groupOfQuantities for each i
for i, place in pairs(tRecipe.places) do
for i, group in ipairs(ingredients) do
-- make sure no nil values or we don't need to continue
local groupOfQuantities = quantities[i]
if not place.building or not place.stars then
return nil, nil
-- on all but the first group, create a new cell with a + sign to separate ingredient groups
if i > 1 then
wikiTable = wikiTable .. " || + "
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)
end
end
strBuildings[i] = place.building
intStars[i] = place.stars
end
end
   
wikiTable = wikiTable .. NL ..
"| = " .. NL ..
"| " .. number .. " " .. RenderRecipe.rlTemplate(product,"large") .. NL ..
"|}"
return strBuildings, intStars
    return wikiTable
end
end






-- hide the internals of the above methods.
-- redirect a rendering request to the recipe data and create appropriate
-- extract lists of ingredients and quantity for a specific recipe at a specific building
-- templates for the list. The caller can decide how to output the list
function RecipeData.getIngredientsAndQuantities(tRecipe)
function RenderRecipe.getBuildingsAndStarsForProduct(frame)
-- make sure we have something to work with
if not tRecipe or not tRecipe.places or 0 == #tRecipe.places then
return nil, nil
end


-- the pattern has the same structure as _EACH_ item in the returnQuantities list
local argProductName = frame.args.product
local returnQuantities = {}
for i, place in ipairs(tRecipe.places) do
returnQuantities[i] = place.quantities
end
return tRecipe.pattern, returnQuantities
end
 
 
 
-- loop over the places and make a new list of extracting all the production times
function RecipeData.getProductionSpeed(tRecipe)
-- make sure we have something to work with
if not tRecipe or not tRecipe.places or 0 == #tRecipe.places then
return nil
end
local speeds = {}
-- make sure there's an argument to work with
if not tableRecipe then
for i, place in ipairs(tRecipe.places) do
return "Render_Recipe Error: no product given."
speeds[i] = place.speed
end
end
return speeds
-- get the associated recipe data, including all buildings
end
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"
-- loop over the places and make a new list of extracting all the products and number output
-- at this point, the key has been lost, so we use the product field of the recipe table
function RecipeData.getProductAndNumbers(tRecipe)
 
-- make sure we have something to work with
if not tRecipe or not tRecipe.places or 0 == #tRecipe.places then
return nil, nil
end
end
local numbers = {}
local listOfTemplates = {}
local buildings, stars = RecipeData.getBuildingsAndStarsLists(tRecipe)
for i, place in ipairs(tRecipe.places) do
-- loop through the buildings and stars and build the templates
numbers[i] = place.out
for i, building in pairs(buildings) do
listOfTemplates[i] = RenderRecipe.blTemplate(building) .. " " .. RenderRecipe.pstarTemplate(stars[i])
end
end
return tRecipe.product, numbers
return listOfTemplates
end
end






-------------------------------------------------------------------------------
-------------------------------------------------------------------------------
-- Helper functions
-- 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)
 
-- Normalize the argument to the standard in-game name, and the one that
-- is used as the key in the big lookup table.
--
-- These functions call external normalize methods.
function RecipeData.normalizeProductName(strArg)
-- invoke the ResourceData.normalize method, since we're dealing in resource names
if not strSize then
return ResourceData.normalizeName(strArg)
strSize= "huge"
end
end
 
function RecipeData.normalizeBuildingName(strArg)
-- invoke the BuildingData.normalize method, since we're dealing in building names
return "{{" .. TEMPLATE_BUILDING_LINK .. "|" .. strBuilding .. "|" .. strSize .. "}}"
return BuildingData.normalizeName(strArg2)
end
end


 
-- use recipe-sized icons, "med", unless specified
 
function RenderRecipe.rlTemplate(strResource,strSize)
-- accepts a 2x2 table in the format of pattern and quantities in tableData above
function RecipeData.copyPatternTypeTable(tArg)
 
local tReturn = {}
for k, v in ipairs(tArg) do
if not strSize then
for ik, iv in ipairs(tArg[k]) do
strSize= "med"
tReturn[k][ik] = iv
end
end
end
return tReturn
return "{{" .. TEMPLATE_RESOURCE_LINK .. "|" .. strResource .. "|" .. strSize .. "}}"
end
end


-- use the parentheses version, with "P"
function RenderRecipe.pstarTemplate(intStars)
return "{{P" .. intStars .. "star}}"
end


 
-- no parens version
-- accepts a complex table in the format of places in tableData above
function RenderRecipe.starTemplate(intStars)
function RecipeData.copyPlaceTypeTable(tArg)
 
local tReturn = {}
tReturn["building"] = tArg["building"]
return "{{" .. intStars .. "star}}"
tReturn["stars"] = tArg["stars"]
tReturn["speed"] = tArg["speed"]
tReturn["out"] = tArg["out"]
tReturn["places"] = copyPatternTypeTable(tArg["places"])
 
return tReturn
end
end


Line 365: Line 245:
-- Return when required into another Module.
-- Return when required into another Module.
-------------------------------------------------------------------------------
-------------------------------------------------------------------------------
return RecipeData
return RenderRecipe

Revision as of 18:14, 8 February 2023

Documentation for this module may be created at Module:RecipeData/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 BR = " <br /> "
local NL = " \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
-------------------------------------------------------------------------------
function RenderRecipe.renderRecipe(frame)

	local argProductName = frame.args.product
	local argBuildingName = frame.args.building
	
	if not argProductName then
		return "Render_Recipe Error: no product given."
	end
	
	-- used by second case where we need to loop over the results
	local strToReturn = ""
	
	-- decide how to proceed based on whether the building was specified
	if argBuildingName then -- 1. easier case, when the building was specified
		
		local tRecipe = RecipeData.getRecipeAtBuilding(argProductName, argBuildingName)
		
		if not tRecipe then
			return "Render_Recipe Error: no recipe found."
		end
		
		--renderTable will use just the first place in the recipe, which is perfect for this version
		return renderTable(tRecipe)
		
	else -- 2. harder case, when no building was specified, need to loop
		
		local tRecipe = RecipeData.getAllRecipes(argProductName)
		
		if not tRecipe then
			return "Render_Recipe Error: no recipe found."
		end
		
		-- go through each place and send a shallow copy version of tRecipe to the table renderer,
		-- then concatenate them with appropriate wiki markup
		for i, place in pairs(tRecipe.places) do
			local tempRecipe = { product=argProductName, pattern=tRecipe.pattern, places=place }
return tempRecipe end end end function more() if 1 then if 1 then
			strToReturn = strToReturn .. "\n\n"	.. RenderRecipe.renderTable(tRecipe)
		end
	end
	
	return strToReturn
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 .. " || + "
		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)
		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 .. "}}"
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 .. "}}"
end

-- use the parentheses version, with "P"
function RenderRecipe.pstarTemplate(intStars)
	
	return "{{P" .. intStars .. "star}}"
end

-- no parens version
function RenderRecipe.starTemplate(intStars)
	
	return "{{" .. intStars .. "star}}"
end



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