Module:RecipeData: Difference between revisions

From Against the Storm Official Wiki
No edit summary
(Undo revision 1652 by Aeredor (talk))
Tag: Undo
Line 1: Line 1:
-------------------------------------------------------------------------------
-------------------------------------------------------------------------------
-- Renders the {{recipe}} template
-- Lua storage table for looking up wiki pages, names, and recipes
-- based on in-game names. All data is in English.
--
--
-- Takes at least one argument. The first, requried, is the name of the
-- The table contains some deconfliction, but only for spaces, apostrophes, and
-- resource for which the recipes are needed. Optionally, the second argument
-- some singular/plural.
-- is the name of the building.
-- Use in-game names for things, and help keep this table updated as the game
-- This module renders small wikimarkup tables to represent one or more
-- is updated.
-- recipes: one table if the building was specified. several tables
--
-- corresponding to all the buildings in which the resource can be produced.
-- Using the table requires a locally defined lookup function that performs
-- 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 = {}


local RecipeData = require("Module:RecipeData") -- lookup table for recipes
-- for returning when REQUIRE'd by other Lua modules.
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 19: Line 27:
-- Constants
-- Constants
-------------------------------------------------------------------------------
-------------------------------------------------------------------------------
local CSS_CLASS_RECIPE_TABLE = "class=\"ATSrecipe\""
-- if needed
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
-- Main data table, with string keys and string values.
-- uses ResourceData lookup function, parses the result and handles errors
-- Some of these are defined inline with string.lower to make the key easier
-- with default values, then assembles a final string to return to the wiki
-- to spell and read correctly.
-------------------------------------------------------------------------------
-------------------------------------------------------------------------------
function RenderRecipe.renderRecipe(frame)


local argProductName = frame.args.product
-- a design decision of this table is to make the key the same as the product name.
local argBuildingName = frame.args.building
-- (the lookup methods will automatically make it lowercase.)
-- that way, whenever .product is referenced, it can be used again to retrieve
-- the rest of the data.
local tableData = {
if not argProductName then
---------------------------------------
return "Render_Recipe Error: no product given."
-- Recipes
end
-- product: string: name of the product, as it appears in the game
-- 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
-- places: table: 1..n: the info that depends on the buildings and stars
-- 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)
-- used by second case where we need to loop over the results
if not strArg then
local strToReturn = ""
return "Recipe_Data Error: product not given."
-- 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
end
-- normalize input using resource normalizer method
    local strProductName = RecipeData.normalizeProductName(strArg)
return strToReturn
-- Get it from the big table above and return the whole pattern and places contents
    return tableData[strProductName]
end
end






-- writes the wiki table markup to represent a recipe
-- extract the pattern from the recipe table
-- takes a recipe table (pattern and place), and uses only the first place
-- hide the internals from calling modules
function RenderRecipe.renderTable(tRecipe)
function RecipeData.getPatternFromRecipe(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
-- call the helper functions to extract the data, make sure we have something usable,
-- build a separate, simplified table to return
-- then get only the first values since we're assuming that there's only one top-level record in tRecipe
local tableToReturn = {}
local building, stars = RecipeData.getBuildingsAndStarsLists(tRecipe)
tableToReturn.product = tRecipe.product
if building and stars then
tableToReturn.pattern = tRecipe.pattern
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)
-- loop over the places. once the building matches, copy just that place (reference) into the table to return
if speed then
for _, place in pairs(tRecipe.places) do
speed = speed[1]
if place.building == strBuildingName then
else
tableToReturn.places = {place}
return "Render_Recipe Error: did not find production speed in recipe."
return tableToReturn
end
end
end
local product, number = RecipeData.getProductAndNumbers(tRecipe)
-- the building was not found, so return nothing
if product and number then
return nil
number = number[1]
end
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)
-- need separate error checking, because ingredients is the same structure as EACH
-- make sure we have something to work with
-- of the top-level elements of quantities
if not tRecipe or not tRecipe.places or #tRecipe.places < 1 then
local ingredients, quantities = RecipeData.getIngredientsAndQuantities(tRecipe)
return nil, nil
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 wikiTable = "{| " .. CSS_CLASS_RECIPE_TABLE .. NL ..
local strBuildings = {}
    "| " .. RenderRecipe.blTemplate(building) .. BR .. RenderRecipe.starTemplate(stars) .. BR .. speed .. NL
local intStars = {}
-- looping over groups of alternative ingredients and quantities simultaneously,
-- loop through the places, extracting the strings and integers for the buildings and stars
-- so use local group and groupOfQuantities for each i
-- and storing them in the tables that will be returned
for i, group in ipairs(ingredients) do
for i, place in pairs(tRecipe.places) do
local groupOfQuantities = quantities[i]
-- make sure no nil values or we don't need to continue
if not place.building or not place.stars then
-- on all but the first group, create a new cell with a + sign to separate ingredient groups
return nil, nil
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 wikiTable
return strBuildings, intStars
end
end






-- redirect a rendering request to the recipe data and create appropriate
-- hide the internals of the above methods.
-- templates for the list. The caller can decide how to output the list
-- extract lists of ingredients and quantity for a specific recipe at a specific building
function RenderRecipe.getBuildingsAndStarsForProduct(frame)
function RecipeData.getIngredientsAndQuantities(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


local argProductName = frame.args.product
-- the pattern has the same structure as _EACH_ item in the returnQuantities list
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
-- make sure there's an argument to work with
local speeds = {}
if not tableRecipe then
return "Render_Recipe Error: no product given."
for i, place in ipairs(tRecipe.places) do
speeds[i] = place.speed
end
end
-- get the associated recipe data, including all buildings
return speeds
local tableRecipe = RecipeData.getAllRecipes(argProductName)
end
-- 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 listOfTemplates = {}
local numbers = {}
local buildings, stars = RecipeData.getBuildingsAndStarsLists(tRecipe)
-- loop through the buildings and stars and build the templates
for i, place in ipairs(tRecipe.places) do
for i, building in pairs(buildings) do
numbers[i] = place.out
listOfTemplates[i] = RenderRecipe.blTemplate(building) .. " " .. RenderRecipe.pstarTemplate(stars[i])
end
end
return listOfTemplates
return tRecipe.product, numbers
end
end






-------------------------------------------------------------------------------
-------------------------------------------------------------------------------
-- Helper rendering functions
-- Helper 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)
if not strSize then
-- invoke the ResourceData.normalize method, since we're dealing in resource names
strSize= "huge"
return ResourceData.normalizeName(strArg)
end
end
 
function RecipeData.normalizeBuildingName(strArg)
return "{{" .. TEMPLATE_BUILDING_LINK .. "|" .. strBuilding .. "|" .. strSize .. "}}"
-- invoke the BuildingData.normalize method, since we're dealing in building names
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 = {}
if not strSize then
for k, v in ipairs(tArg) do
strSize= "med"
for ik, iv in ipairs(tArg[k]) do
tReturn[k][ik] = iv
end
end
end
return "{{" .. TEMPLATE_RESOURCE_LINK .. "|" .. strResource .. "|" .. strSize .. "}}"
return tReturn
end
end


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


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


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

Revision as of 18:14, 8 February 2023

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

-------------------------------------------------------------------------------
-- Lua storage table for looking up wiki pages, names, and recipes 
-- based on in-game names. All data is in English.
--
-- The table contains some deconfliction, but only for spaces, apostrophes, and
-- some singular/plural.
-- Use in-game names for things, and help keep this table updated as the game
-- is updated.
--
-- Using the table requires a locally defined lookup function that performs 
-- 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.
-------------------------------------------------------------------------------


-- for returning when REQUIRE'd by other Lua modules.
local RecipeData = {}

local ResourceData = require("Module:ResourceData") -- need to reuse the normalize method
local BuildingData = require("Module:BuildingData") -- need to reuse the normalize method



-------------------------------------------------------------------------------
-- Constants
-------------------------------------------------------------------------------
-- if needed



-------------------------------------------------------------------------------
-- Main data table, with string keys and string values.
-- Some of these are defined inline with string.lower to make the key easier
-- to spell and read correctly.
-------------------------------------------------------------------------------

-- a design decision of this table is to make the key the same as the product name.
-- (the lookup methods will automatically make it lowercase.)
-- that way, whenever .product is referenced, it can be used again to retrieve 
-- the rest of the data.
local tableData = {
	
	---------------------------------------
	-- Recipes
	-- product: string: name of the product, as it appears in the game
	-- 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
	-- places: table: 1..n: the info that depends on the buildings and stars
		-- 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
		return "Recipe_Data Error: product not given."
	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 tableData[strProductName]
end



-- extract the pattern from the recipe table
-- hide the internals from calling modules
function RecipeData.getPatternFromRecipe(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
		return nil
	end
	
	-- build a separate, simplified table to return
	local tableToReturn = {}
	tableToReturn.product = tRecipe.product
	tableToReturn.pattern = tRecipe.pattern
	
	-- loop over the places. once the building matches, copy just that place (reference) into the table to return
	for _, place in pairs(tRecipe.places) do
		if place.building == strBuildingName then
			tableToReturn.places = {place}
			return tableToReturn
		end
	end
	
	-- the building was not found, so return nothing
	return nil
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
	if not tRecipe or not tRecipe.places or #tRecipe.places < 1 then
		return nil, nil
	end
	
	local strBuildings = {}
	local intStars = {}
	
	-- loop through the places, extracting the strings and integers for the buildings and stars
	-- and storing them in the tables that will be returned
	for i, place in pairs(tRecipe.places) do
		-- make sure no nil values or we don't need to continue
		if not place.building or not place.stars then
			return nil, nil
		end
		strBuildings[i] = place.building
		intStars[i] = place.stars
	end
	
	return strBuildings, intStars
end



-- hide the internals of the above methods.
-- extract lists of ingredients and quantity for a specific recipe at a specific building
function RecipeData.getIngredientsAndQuantities(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

	-- the pattern has the same structure as _EACH_ item in the returnQuantities list
	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 = {}
	
	for i, place in ipairs(tRecipe.places) do
		speeds[i] = place.speed
	end
	
	return speeds
end



-- 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
	
	local numbers = {}
	
	for i, place in ipairs(tRecipe.places) do
		numbers[i] = place.out
	end
	
	return tRecipe.product, numbers
end





-------------------------------------------------------------------------------
-- Helper functions
-------------------------------------------------------------------------------



-- 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
	return ResourceData.normalizeName(strArg)
end

function RecipeData.normalizeBuildingName(strArg)
	
	-- invoke the BuildingData.normalize method, since we're dealing in building names
	return BuildingData.normalizeName(strArg2)
end



-- 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
		for ik, iv in ipairs(tArg[k]) do
			tReturn[k][ik] = iv
		end
	end
	
	return tReturn
end



-- accepts a complex table in the format of places in tableData above
function RecipeData.copyPlaceTypeTable(tArg)

	local tReturn = {}
	
	tReturn["building"] = tArg["building"]
	tReturn["stars"] = tArg["stars"]
	tReturn["speed"] = tArg["speed"]
	tReturn["out"] = tArg["out"]
	tReturn["places"] = copyPatternTypeTable(tArg["places"])

	return tReturn
end



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