Module:RecipeData

From Against the Storm Official Wiki
Revision as of 05:11, 9 February 2023 by Aeredor (talk | contribs) (added some logging for now)

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", pattern={ {"Insects","Meat"},{"Wood","Oil","Coal","Sea Marrow"} },
		places={{building="Field Kitchen", stars=0, speed="02:06", quantities={{8,8},{5,2,1,1}}, out=10},
				{building="Smokehouse", stars=3, speed="02:06", quantities={{4,4},{5,2,1,1}}, out=10},
				{building="Kiln", stars=1, speed="02:06", quantities={{6,6},{5,2,1,1}}, out=10},
				{building="Butcher", stars=2, speed="02:06", quantities={{5,5},{5,2,1,1}}, out=10}, 
				{building="Cellar", stars=1, speed="02:06", quantities={{6,6},{5,2,1,1}}, out=10} } },
	["pickled goods"] = { product="Pickled Goods", pattern={{"Vegetables","Mushrooms","Roots","Berries","Eggs"},{"Pottery","Barrels","Waterskins"}},
		places={{building="Field Kitchen", stars=0, speed="02:06", quantities={{7,7,7,7,7},{3,3,3}}, out=10},
				{building="Granary", stars=2, speed="02:06", quantities={{5,5,5,5,5},{3,3,2}}, out=10},
				{building="Cellar", stars=1, speed="02:06", quantities={{6,6,6,6,6},{3,3,3}}, out=10},
				{building="Brewery", stars=1, speed="02:06", quantities={{6,6,6,6,6},{3,3,3}}, out=10},
				{building="Flawless Brewery", stars=3, speed="01:45", quantities={{4,4,4,4,4},{3,3,2}}, out=15} } },
	["pie"] = { product="Pie", pattern={{"Flour"},{"Herbs","Meat","Insects","Eggs","Berries"}},
		places={{building="Furnace", stars=2, speed="01:56", quantities={{6},{4,4,4,4,4}}, out=10},
				{building="Bakery", stars=2, speed="02:06", quantities={{6},{4,4,4,4,4}}, out=10},
				{building="Brick Oven", stars=3, speed="01:45", quantities={{6},{3,3,3,3,3}}, out=10} } },
	["skewers"] = { product="Skewers", pattern={{"Insects","Meat","Eggs","Jerky"},{"Vegetables","Roots","Berries","Eggs"}},
		places={{building="Cookhouse", stars=2, speed="02:06", quantities={{4,4,4,3},{4,4,4,4}}, out=10},
				{building="Grill", stars=3, speed="01:45", quantities={{3,3,3,2},{3,3,3,3}}, out=10},
				{building="Butcher", stars=2, speed="02:06", quantities={{4,4,4,3},{4,4,4,4}}, out=10} } },
	-- Building Materials
	["bricks"] = { product="Bricks", pattern={{"Clay","Stone"}},
		places={{building="Crude Workstation", stars=0, speed="00:51", quantities={{6,6}}, out=2},
				{building="Furnace", stars=2, speed="00:38", quantities={{3,3}}, out=2},
				{building="Workshop", stars=2, speed="00:42", quantities={{3,3}}, out=2},
				{building="Brickyard", stars=2, speed="00:42", quantities={{3,3}}, out=2},
				{building="Kiln", stars=1, speed="00:42", quantities={{4,4}}, out=2} } },
	["fabric"] = { product="Fabric", pattern={{"Plant Fiber","Reeds","Leather"}},
		places={{building="Crude Workstation", stars=0, speed="00:51", quantities={{6,6,6}}, out=2},
				{building="Leatherworker", stars=2, speed="00:38", quantities={{3,3,3}}, out=2},
				{building="Workshop", stars=2, speed="00:42", quantities={{3,3,3}}, out=2},
				{building="Weaver", stars=3, speed="00:28", quantities={{2,2,2}}, out=2},
				{building="Granary", stars=2, speed="00:42", quantities={{3,3,3}}, out=2} } },
	["planks"] = { product="Planks", pattern={{"Wood"}},
		places={{building="Crude Workstation", stars=0, speed="00:51", quantities={{8}}, out=2},
				{building="Carpenter", stars=2, speed="00:38", quantities={{5}}, out=2},
				{building="Workshop", stars=2, speed="00:42", quantities={{5}}, out=2},
				{building="Lumber Mill", stars=3, speed="00:28", quantities={{3}}, out=2},
				{building="Supplier", stars=2, speed="00:42", quantities={{5}}, out=2} } },
	["parts"] = { product="Parts", pattern={{"Copper Bars","Crystalized Dew","Stone","Clay"},{"Coal","Oil","Wood"}},
		places={{building="Rainpunk Foundry", stars=3, speed="02:48", quantities={{4,4,15,15},{1,2,5}}, out=1} } },
	["pipes"] = { product="Pipes", pattern={{"Copper Bars","Crystalized Dew"}},
		places={{building="Crude Workstation", stars=0, speed="00:55", quantities={{3,3}}, out=2},
				{building="Workshop", stars=0, speed="01:00", quantities={{3,3}}, out=2},
				{building="Smelter", stars=2, speed="01:00", quantities={{2,2}}, out=3},
				{building="Toolshop", stars=2, speed="01:00", quantities={{2,2}}, out=3} } },
	-- no recipe for ["wildfire essence"] = { product="Wildfire Essence" },
	-- Consumable Items
	["coats"] = { product="Coats", pattern={{"Fabric"}}, 
		places={{building="Clothier", stars=3, speed="02:06", quantities={{1}}, out=10},
				{building="Smithy", stars=2, speed="02:48", quantities={{2}}, out=10},
				{building="Artisan", stars=2, speed="02:48", quantities={{2}}, out=10},
				{building="Druid's Hut", stars=1, speed="02:48", quantities={{3}}, out=10} } },
	["ale"] = { product="Ale", pattern={{"Grain","Roots"},{"Pottery","Barrels","Waterskins"}},
		places={{building="Grill", stars=1, speed="02:06", quantities={{6,6},{3,2,3}}, out=10},
				{building="Brewery", stars=3, speed="01:45", quantities={{4,4},{2,1,2}}, out=10},
				{building="Flawless Brewery", stars=3, speed="01:45", quantities={{4,4},{2,1,2}}, out=15},
				{building="Tinctury", stars=2, speed="02:06", quantities={{5,5},{3,2,3}}, out=10},
				{building="Scribe", stars=2, speed="02:06", quantities={{5,5},{3,2,3}}, out=10} } },
	["cosmetics"] = { product="Cosmetics", pattern={{"Oil","Eggs"},{"Pigment","Herbs","Resin"}},
		places={{building="Cooperage", stars=1, speed="02:06", quantities={{4,4},{4,4,4}}, out=10},
				{building="Alchemist's Hut", stars=2, speed="02:06", quantities={{3,3},{3,3,3}}, out=10},
				{building="Apothecary", stars=2, speed="02:06", quantities={{3,3},{3,3,3}}, out=10} } },
	["incense"] = { product="Incense", pattern={{"Herbs","Roots","Insects","Resin"},{"Wood","Oil","Coal","Sea Marrow"}},
		places={{building="Smokehouse", stars=1, speed="02:06", quantities={{6,6,6,8},{6,3,2,2}}, out=10},
				{building="Brick Oven", stars=1, speed="02:06", quantities={{6,6,6,8},{6,3,2,2}}, out=10},
				{building="Apothecary", stars=2, speed="02:06", quantities={{5,5,5,7},{6,3,2,2}}, out=10},
				{building="Druid's Hut", stars=1, speed="02:06", quantities={{6,6,6,8},{6,3,2,2}}, out=10} } },
	["scrolls"] = { product="Scrolls", pattern={{"Leather","Plant Fiber","Wood"},{"Pigment","Wine"}},
		places={{building="Lumber Mill", stars=1, speed="01:24", quantities={{4,4,10},{3,3}}, out=8},
				{building="Clothier", stars=1, speed="01:24", quantities={{4,4,10},{3,3}}, out=8},
				{building="Flawless Rain Mill", stars=3, speed="01:03", quantities={{2,2,6},{1,1}}, out=8},
				{building="Rain Mill", stars=1, speed="01:24", quantities={{4,4,10},{3,3}}, out=8},
				{building="Scribe", stars=3, speed="01:03", quantities={{2,2,6},{1,1}}, out=8} } },
	["training gear"] = { product="Training Gear", pattern={{"Stone","Copper Bars","Crystalized Dew"},{"Planks","Reeds"}},
		places={{building="Cooperage", stars=2, speed="02:06", quantities={{5,2,2},{3,3}}, out=10},
				{building="Weaver", stars=1, speed="02:06", quantities={{8,3,3},{3,3}}, out=10},
				{building="Tinkerer", stars=2, speed="02:06", quantities={{5,2,2},{3,3}}, out=10},
				{building="Manufactory", stars=2, speed="02:06", quantities={{5,2,2},{3,3}}, out=10} } },
	["wine"] = { product="Wine", pattern={{"Berries","Mushrooms","Reeds"},{"Pottery","Barrels","Waterskins"}},
		places={{building="Cellar", stars=3, speed="01:03", quantities={{2,2,2},{2,2,2}}, out=10},
				{building="Alchemist's Hut", stars=2, speed="01:24", quantities={{3,3,3},{3,3,3}}, out=10},
				{building="Tinctury", stars=2, speed="01:24", quantities={{3,3,3},{3,3,3}}, out=10} } },
	-- Crafting Materials
	["clay"] = { product="Clay", pattern={{"Clearance Water"}},
		places={{building="Clay Pit", stars=2, speed="01:24", quantities={{4}}, out=4} } },
	-- no recipe for ["copper ore"] = { product="Copper Ore" },
	["crystalized dew"] = { product="Crystalized Dew", pattern={{"Herbs","Insects","Resin","Vegetables"},{"Stone","Clay"},{"Storm Water","Clearance Water","Drizzle Water"}},
		places={{building="Brickyard", stars=2, speed="00:42", quantities={{2,2,2,2},{3,3},{8,12,16}}, out=2},
				{building="Alchemist's Hut", stars=2, speed="00:42", quantities={{2,2,2,2},{3,3},{8,12,16}}, out=2} } },
	-- no recipe for ["grain"] = { product="Grain" },
	["herbs"] = { product="Herbs", pattern={{"Drizzle Water"}},
		places={{building="Greenhouse", stars=2, speed="01:24", quantities={{4}}, out=4} } },
	["leather"] = { product="Leather", pattern={{"Plant Fiber","Reeds","Grain","Vegetables"}},
		places={{building="Ranch", stars=1, speed="00:42", quantities={{2,2,2,1}}, out=4} } },
	-- no recipe for ["plant fiber"] = { product="Plant Fiber" },
	["reeds"] = { product="Reeds", pattern={{"Clearance Water"}},
		places={{building="Clay Pit", stars=2, speed="01:24", quantities={{4}}, out=4} } },
	-- no recipe for ["resin"] = { product="Resin" },
	-- no recipe for ["sparkdew"] = { product="Sparkdew" },
	-- no recipe for ["stone"] = { product="Stone" },
	-- Refined Crafting Materials
	["barrels"] = { product="Barrels", pattern={{"Copper Bars","Crystalized Dew"},{"Planks"}},
		places={{building="Cooperage", stars=3, speed="01:45", quantities={{1,1},{2}}, out=10},
				{building="Provisioner", stars=2, speed="02:06", quantities={{2,2},{2}}, out=10},
				{building="Toolshop", stars=1, speed="02:06", quantities={{3,3},{2}}, out=10},
				{building="Artisan", stars=2, speed="02:06", quantities={{2,2},{2}}, out=10} } },
	["copper bars"] = { product="Copper Bars", pattern={{"Copper Ore"},{"Wood","Oil","Coal","Sea Marrow"}},
		places={{building="Furnace", stars=2, speed="00:38", quantities={{5},{5,2,1,1}}, out=2},
				{building="Grill", stars=1, speed="00:42", quantities={{6},{5,2,1,1}}, out=2},
				{building="Stamping Mill", stars=1, speed="00:42", quantities={{6},{5,2,1,1}}, out=2},
				{building="Smelter", stars=3, speed="00:28", quantities={{4},{5,2,1,1}}, out=2} } },
	["flour"] = { product="Flour", pattern={{"Grain","Mushrooms","Roots"}},
		places={{building="Press", stars=1, speed="00:53", quantities={{8,8,8}}, out=10},
				{building="Flawless Rain Mill", stars=3, speed="01:03", quantities={{5,5,5}}, out=10},
				{building="Rain Mill", stars=3, speed="01:03", quantities={{5,5,5}}, out=10},
				{building="Provisioner", stars=2, speed="01:03", quantities={{7,7,7}}, out=10},
				{building="Stamping Mill", stars=2, speed="01:03", quantities={{7,7,7}}, out=10},
				{building="Supplier", stars=2, speed="01:03", quantities={{7,7,7}}, out=10} } },
	["pigment"] = { product="Pigment", pattern={{"Insects","Berries","Copper Ore","Coal"}},
		places={{building="Cookhouse", stars=2, speed="02:06", quantities={{4,4,4,3}}, out=10},
				{building="Artisan", stars=2, speed="02:06", quantities={{4,4,4,3}}, out=10},
				{building="Tinctury", stars=2, speed="02:06", quantities={{4,4,4,3}}, out=10},
				{building="Manufactory", stars=2, speed="02:06", quantities={{4,4,4,3}}, out=10} } },
	["pottery"] = { product="Pottery", pattern={{"Clay"},{"Wood","Oil","Coal","Sea Marrow"}},
		places={{building="Bakery", stars=2, speed="01:24", quantities={{3},{5,2,1,1}}, out=5},
				{building="Smokehouse", stars=1, speed="01:24", quantities={{4},{5,2,1,1}}, out=5},
				{building="Brickyard", stars=2, speed="01:24", quantities={{3},{5,2,1,1}}, out=5},
				{building="Stamping Mill", stars=3, speed="01:03", quantities={{2},{5,2,1,1}}, out=5} } },
	["waterskins"] = { product="Waterskins", pattern={{"Leather"},{"Oil","Meat"}},
		places={{building="Leatherworker", stars=3, speed="00:58", quantities={{4},{3,2}}, out=10},
				{building="Clothier", stars=1, speed="01:24", quantities={{6},{5,4}}, out=10},
				{building="Supplier", stars=2, speed="01:24", quantities={{5},{4,3}}, out=10} } },
	-- Trade Goods
	["amber"] = { product="Amber", pattern={{"Resin"},{"Clearance Water","Oil"}},
		places={{building="Finesmith", stars=3, speed="00:42", quantities={{3},{10,1}}, out=1} } },
	-- no recipe for ["ancient tablet"] = { product="Ancient Tablet" },
	["pack of building materials"] = { product="Pack of Building Materials", pattern={{"Planks","Fabric","Bricks","Copper Ore"}},
		places={{building="Makeshift Post", stars=0, speed="00:56", quantities={{10,6,6,14}}, out=2},
				{building="Flawless Rain Mill", stars=3, speed="00:42", quantities={{6,3,3,8}}, out=2},
				{building="Rain Mill", stars=1, speed="00:42", quantities={{8,5,5,12}}, out=2},
				{building="Tinkerer", stars=2, speed="00:42", quantities={{7,4,4,10}}, out=2} } },
	["pack of crops"] = { product="Pack of Crops", pattern={{"Roots","Grain","Vegetables","Mushrooms"}},
		places={{building="Makeshift Post", stars=0, speed="00:56", quantities={{6,6,6,6}}, out=2},
				{building="Granary", stars=2, speed="00:42", quantities={{4,4,4,4}}, out=2},
				{building="Brewery", stars=1, speed="00:42", quantities={{5,5,5,5}}, out=2},
				{building="Flawless Brewery", stars=3, speed="00:28", quantities={{3,3,3,3}}, out=5} } },
	["pack of luxury goods"] = { product="Pack of Luxury Goods", pattern={{"Wine","Training Gear","Incense","Scrolls","Ale","Cosmetics"}},
		places={{building="Carpenter", stars=2, speed="00:38", quantities={{4,4,4,4,4,4}}, out=2},
				{building="Press", stars=1, speed="00:26", quantities={{5,5,5,5,5,5}}, out=2},
				{building="Leatherworker", stars=1, speed="00:38", quantities={{5,5,5,5,5,5}}, out=2} } },
	["pack of provisions"] = { product="Pack of Provisions", pattern={{"Herbs","Berries","Insects","Meat","Eggs"}},
		places={{building="Makeshift Post", stars=0, speed="00:56", quantities={{6,6,6,6,6}}, out=3},
				{building="Provisioner", stars=2, speed="00:42", quantities={{4,4,4,4,4}}, out=3},
				{building="Manufactory", stars=2, speed="00:42", quantities={{4,4,4,4,4}}, out=3} } },
	["pack of trade goods"] = { product="Pack of Trade Goods", pattern={{"Pigment","Oil","Flour","Pottery","Barrels","Waterskins"}},
		places={{building="Lumber Mill", stars=0, speed="00:42", quantities={{8,8,6,6,6,6}}, out=2},
				{building="Weaver", stars=0, speed="00:42", quantities={{8,8,6,6,6,6}}, out=2},
				{building="Smithy", stars=0, speed="00:42", quantities={{6,6,4,4,4,4}}, out=2} } },
	-- Meta resources
	-- no recipe for ["artifacts"] = { product="Artifacts" },
	-- no recipe for ["food stockpiles"] = { product="Food Stockpiles" },
	-- no recipe for ["machinery"] = { product="Machinery" },
	-- Fuel & Exploration
	["coal"] = { product="Coal", pattern={{"Wood"}},
		places={{building="Brick Oven", stars=1, speed="02:06", quantities={{15}}, out=3},
				{building="Kiln", stars=3, speed="01:24", quantities={{10}}, out=5} } },
	["oil"] = { product="Oil", pattern={{"Grain","Meat","Vegetables","Plant Fiber"}},
		places={{building="Press", stars=3, speed="00:39", quantities={{2,2,2,2}}, out=5},
				{building="Butcher", stars=2, speed="01:24", quantities={{3,3,3,3}}, out=5},
				{building="Druid's Hut", stars=3, speed="01:03", quantities={{2,2,2,2}}, out=5} } },
	-- no recipe for ["sea marrow"] = { product="Sea Marrow" },
	-- no recipe for ["wood"] = { product="Wood" },
	["simple tools"] = { product="Simple Tools", pattern={{"Wood","Planks"},{"Copper Bars","Crystalized Dew"}},
		places={{building="Carpenter", stars=2, speed="01:30", quantities={{8,2},{3,3}}, out=2},
				{building="Smithy", stars=2, speed="01:38", quantities={{8,2},{3,3}}, out=2},
				{building="Toolshop", stars=3, speed="01:24", quantities={{6,1},{2,2}}, out=2},
				{building="Tinkerer", stars=2, speed="01:38", quantities={{8,2},{3,3}}, out=2},
				{building="Scribe", stars=1, speed="01:52", quantities={{10,3},{4,4}}, out=2} } },
	["infused tools"] = { product="Infused Tools", pattern={{"Wood","Planks"},{"Copper Bars","Crystalized Dew"},{"Storm Water","Clearance Water","Drizzle Water"}},
		places={{building="", stars=0, speed="", quantities={{6,1},{2,2},{8,12,16}}, out=2},
				{building="", stars=0, speed="", quantities={{6,1},{2,2},{8,12,16}}, out=2} } }
}
	-- no recipe for ["purging fire"] = { product="Purging Fire" },
	-- Rain
	-- no recipe for ["clearance water"] = { product="Clearance Water" },
	-- no recipe for ["drizzle water"] = { product="Drizzle Water" },
	-- no recipe for ["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.getRecipeForProduct(argProductName)
	
	if not argProductName then
		return "Recipe_Data Error: product not given."
	end

	-- normalize input using resource normalizer method
    local strProductName = RecipeData.normalizeProductName(argProductName)
	
	-- 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(argProductName, argBuildingName)
	
	if not argProductName then
		 return "Recipe_Data Error: product not given."
	end
	if not argBuildingName then
		return "Recipe_Data Error: building not given."
	end
	
	-- normalize inputs using resource and building normalizer methods
    local strProductName = RecipeData.normalizeProductName(argProductName)
	local strBuildingName = RecipeData.normalizeBuildingName(argBuildingName)
	
	-- 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 string.lower(place.building) == strBuildingName then
			tableToReturn.places = {place}
			return tableToReturn
		end
	end
	
	-- the building was not found, so return nothing
	return nil
end



-- loop over all the places for all the recipes and get a list of all the recipes a building has
function RecipeData.getBuildingsRecipes(argBuildingName)
	
	-- check input
	if not argBuildingName then
		return "Recipe_Data Error: building not given."
	end
	
	-- normalize inputs using resource and building normalizer methods
	local strBuildingName = RecipeData.normalizeBuildingName(argBuildingName)
mw.log(strBuildingName)
	local recipesFoundHere = {}
mw.log("looping thru " .. #tableData)
	-- loop through the recipes
	for i,recipe in ipairs(tableData) do
mw.log("####")
mw.log(i)
mw.log(recipe)
		-- for each recipe, loop through the places
		for j, place in ipairs(recipe.places) do
mw.log("    ---")
mw.log("    " .. j)
mw.log("    " .. place) 
			-- once we find it, we can break out to the next recipe
			if place.building == strBuildingName then
mw.log("found it: building=" .. place.building)
				-- build a new recipe to add to recipesFoundHere
				local newRecipe = {}
				newRecipe.product = recipe.product
				newRecipe.pattern = recipe.pattern
				newRecipe.places = {place}
				
				table.insert(recipesFoundHere,newRecipe)
				
				break
			end
		end
	end
	
	return recipesFoundHere
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(strArg)
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