Module:RenderRecipe: Difference between revisions
From Against the Storm Official Wiki
m (forgot some constants) |
(swapped table code writing to use scribunto mw.html library instead of hand-coded the wiki table markup) |
||
Line 19: | Line 19: | ||
-- Constants | -- Constants | ||
------------------------------------------------------------------------------- | ------------------------------------------------------------------------------- | ||
local | local CSS_CLASS_WIKITABLE_SORTABLE = "wikitable sortable" | ||
local CSS_CLASS_RECIPE_CAPTION = | local CSS_CLASS_RECIPE_TABLE = "ATSrecipe" | ||
local CSS_CLASS_REQUIRED_INGREDIENT = | local CSS_CLASS_RECIPE_CAPTION = "ATSrecipecaption" | ||
local CSS_CLASS_SWAPPABLE_INGREDIENT = | local CSS_CLASS_REQUIRED_INGREDIENT = "ATSrequired" | ||
local CSS_CLASS_EMPTY_INGREDIENT = | local CSS_CLASS_SWAPPABLE_INGREDIENT = "ATSswappable" | ||
local CSS_CLASS_EMPTY_INGREDIENT = "ATSempty" | |||
local TEMPLATE_BUILDING_LINK = "Building_link" | local TEMPLATE_BUILDING_LINK = "Building_link" | ||
local TEMPLATE_RESOURCE_LINK = "Resource_link" | local TEMPLATE_RESOURCE_LINK = "Resource_link" | ||
Line 165: | Line 165: | ||
end | end | ||
local wikiTable = "{| " .. CSS_CLASS_RECIPE_TABLE .. NL .. | -- build the table header | ||
local wikiTable = mw.html.create('table'):addClass(CSS_CLASS_WIKITABLE_SORTABLE) | |||
wikiTable:tag('tr') | |||
:tag('th'):wikitext("Building"):done() | |||
:tag('th'):wikitext("Ingredient #1"):done() | |||
:tag('th'):wikitext("Ingredient #2"):done() | |||
:tag('th'):wikitext("Ingredient #3"):done() | |||
:tag('th'):wikitext("Product") | |||
--[[local wikiTable = "{| " .. CSS_CLASS_RECIPE_TABLE .. NL .. | |||
"|+ " .. CSS_CLASS_RECIPE_CAPTION .. "| " .. product .. NL .. | "|+ " .. CSS_CLASS_RECIPE_CAPTION .. "| " .. product .. NL .. | ||
"| " .. CSS_CLASS_CONSUME_SPACE .. "| " .. RenderRecipe.blTemplate(building) .. BR .. RenderRecipe.starTemplate(stars) .. BR .. speed .. NL | "| " .. CSS_CLASS_CONSUME_SPACE .. "| " .. RenderRecipe.blTemplate(building) .. BR .. RenderRecipe.starTemplate(stars) .. BR .. speed .. NL ]] | ||
local wikiTableDataRow = wikiTable:tag('tr') | |||
-- first fill in empty cells like in the recipe book, one for the blank ingredient with a border, then a space for a missing plus sign | -- first fill in empty cells like in the recipe book, one for the blank ingredient with a border, then a space for a missing plus sign | ||
local blanks = 3 - #ingredients | local blanks = 3 - #ingredients | ||
for h = 1,blanks do | for h = 1,blanks do | ||
wikiTable = wikiTable .. "| " .. CSS_CLASS_EMPTY_INGREDIENT .. " | " .. NL .. | |||
"| " .. NL | wikiTableDataRow:tag('td'):addClass(CSS_CLASS_EMPTY_INGREDIENT) | ||
--[[wikiTable = wikiTable .. "| " .. CSS_CLASS_EMPTY_INGREDIENT .. " | " .. NL .. | |||
"| " .. NL]] | |||
end | end | ||
Line 181: | Line 193: | ||
local groupOfQuantities = quantities[i] | local groupOfQuantities = quantities[i] | ||
-- on all but the first group, create a new cell with a + sign to separate ingredient groups | --[[ on all but the first group, create a new cell with a + sign to separate ingredient groups | ||
if i > 1 then | if i > 1 then | ||
wikiTable = wikiTable .. NL .. "| + " .. NL | wikiTable = wikiTable .. NL .. "| + " .. NL | ||
end | end]] | ||
local wikiTableDataRowDataCell = wikiTableDataRow:tag('td') | |||
-- | -- add a class to the table cell based on whether there's only one (required) or more (swappable) ingredients | ||
-- in the group | -- in the group | ||
if 1 == #group then | if 1 == #group then | ||
wikiTable = wikiTable .. | wikiTableDataRowDataCell:addClass(CSS_CLASS_REQUIRED_INGREDIENT) | ||
"| " .. CSS_CLASS_REQUIRED_INGREDIENT .. " | " | --[[wikiTable = wikiTable .. | ||
"| " .. CSS_CLASS_REQUIRED_INGREDIENT .. " | "]] | |||
else | else | ||
wikiTable = wikiTable .. | wikiTableDataRowDataCell:addClass(CSS_CLASS_SWAPPABLE_INGREDIENT) | ||
"| " .. CSS_CLASS_SWAPPABLE_INGREDIENT .. " | " | --[[wikiTable = wikiTable .. | ||
"| " .. CSS_CLASS_SWAPPABLE_INGREDIENT .. " | "]] | |||
end | end | ||
Line 202: | Line 218: | ||
-- need to add breaks only between the first and any subsequent options | -- need to add breaks only between the first and any subsequent options | ||
if j > 1 then | if j > 1 then | ||
wikiTable = wikiTable .. BR | wikiTableDataRowDataCell:newline() | ||
--[[wikiTable = wikiTable .. BR]] | |||
end | end | ||
wikiTable = wikiTable .. quant .. " " .. RenderRecipe.rlTemplate(alt) -- line breaks handled by above if statement and addition below for close | wikiTableDataRowDataCell:wikitext(quant .. " " .. RenderRecipe.rlTemplate(alt)) | ||
--[[wikiTable = wikiTable .. quant .. " " .. RenderRecipe.rlTemplate(alt) -- line breaks handled by above if statement and addition below for close]] | |||
end | end | ||
end | end | ||
wikiTable = wikiTable .. NL .. | -- close up the table with the product | ||
wikiTableDataRow:tag('td'):wikitext(number .. " " .. RenderRecipe.rlTemplate(product,"large")) | |||
--[[wikiTable = wikiTable .. NL .. | |||
"| = " .. NL .. | "| = " .. NL .. | ||
"| " .. number .. " " .. RenderRecipe.rlTemplate(product,"large") .. NL .. | "| " .. number .. " " .. RenderRecipe.rlTemplate(product,"large") .. NL .. | ||
"|}" | "|}"]] | ||
return wikiTable | return wikiTable | ||
Line 257: | Line 278: | ||
-- modules, but we may decide later it should be different) | -- modules, but we may decide later it should be different) | ||
------------------------------------------------------------------------------- | ------------------------------------------------------------------------------- | ||
--use | --use large size for recipes unless speified | ||
function RenderRecipe.blTemplate(strBuilding,strSize) | function RenderRecipe.blTemplate(strBuilding,strSize) | ||
if not strSize then | if not strSize then | ||
strSize = " | strSize = "large" | ||
end | end | ||
Revision as of 14:07, 10 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_WIKITABLE_SORTABLE = "wikitable sortable" local CSS_CLASS_RECIPE_TABLE = "ATSrecipe" local CSS_CLASS_RECIPE_CAPTION = "ATSrecipecaption" local CSS_CLASS_REQUIRED_INGREDIENT = "ATSrequired" local CSS_CLASS_SWAPPABLE_INGREDIENT = "ATSswappable" local CSS_CLASS_EMPTY_INGREDIENT = "ATSempty" 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 -- build the table header local wikiTable = mw.html.create('table'):addClass(CSS_CLASS_WIKITABLE_SORTABLE) wikiTable:tag('tr') :tag('th'):wikitext("Building"):done() :tag('th'):wikitext("Ingredient #1"):done() :tag('th'):wikitext("Ingredient #2"):done() :tag('th'):wikitext("Ingredient #3"):done() :tag('th'):wikitext("Product") --[[local wikiTable = "{| " .. CSS_CLASS_RECIPE_TABLE .. NL .. "|+ " .. CSS_CLASS_RECIPE_CAPTION .. "| " .. product .. NL .. "| " .. CSS_CLASS_CONSUME_SPACE .. "| " .. RenderRecipe.blTemplate(building) .. BR .. RenderRecipe.starTemplate(stars) .. BR .. speed .. NL ]] local wikiTableDataRow = wikiTable:tag('tr') -- first fill in empty cells like in the recipe book, one for the blank ingredient with a border, then a space for a missing plus sign local blanks = 3 - #ingredients for h = 1,blanks do wikiTableDataRow:tag('td'):addClass(CSS_CLASS_EMPTY_INGREDIENT) --[[wikiTable = wikiTable .. "| " .. CSS_CLASS_EMPTY_INGREDIENT .. " | " .. NL .. "| " .. NL]] end -- 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]] local wikiTableDataRowDataCell = wikiTableDataRow:tag('td') -- add a class to the table cell based on whether there's only one (required) or more (swappable) ingredients -- in the group if 1 == #group then wikiTableDataRowDataCell:addClass(CSS_CLASS_REQUIRED_INGREDIENT) --[[wikiTable = wikiTable .. "| " .. CSS_CLASS_REQUIRED_INGREDIENT .. " | "]] else wikiTableDataRowDataCell:addClass(CSS_CLASS_SWAPPABLE_INGREDIENT) --[[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 wikiTableDataRowDataCell:newline() --[[wikiTable = wikiTable .. BR]] end wikiTableDataRowDataCell:wikitext(quant .. " " .. RenderRecipe.rlTemplate(alt)) --[[wikiTable = wikiTable .. quant .. " " .. RenderRecipe.rlTemplate(alt) -- line breaks handled by above if statement and addition below for close]] end end -- close up the table with the product wikiTableDataRow:tag('td'):wikitext(number .. " " .. RenderRecipe.rlTemplate(product,"large")) --[[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 large size for recipes unless speified function RenderRecipe.blTemplate(strBuilding,strSize) if not strSize then strSize = "large" 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