Module:GoodsData

--- -- Module for compiling goods (or resources as some call them) information from -- wiki data sources. -- -- @module GoodsData local GoodsData = {}

--- -- Dependencies --- local CsvUtils = require("Module:CsvUtils")

--- -- Constants for this module --- local GOODS_DATA_TEMPLATE_NAME = "Template:Goods_csv"

local INDEX_GOOD_ID = 1 local INDEX_GOOD_NAME = 2 local INDEX_GOOD_DESCRIPTION = 3 local INDEX_GOOD_CATEGORY = 4 local INDEX_GOOD_EATABLE = 5 local INDEX_GOOD_CAN_BE_BURNED = 6 local INDEX_GOOD_BURNING_TIME = 7 local INDEX_GOOD_TRADING_SELL_VALUE = 8 local INDEX_GOOD_TRADING_BUY_VALUE = 9 local INDEX_GOOD_ICON_FILENAME = 10

local HEADER_ROW = 1 local DATA_ROWS = 2

--- -- Private member variables ---

-- Main data tables. Populated from CSV data and organized better for Lua.

-- like this: table[goodID] = table containing good data local goodsTable

-- Lookup maps. Built once and reused on subsequent calls

-- like this: table[display name] = goodID local goodsNameToGoodID

--- -- Data loader function. Calls the data templates, restructures the data to be -- useful for getter methods, and makes a merge table. -- -- This method is called the first time any of the actual template methods are -- invoked and they see that the data tables are nil. This method populates -- them and reorganizes them for easier use (and easier code). function loadData -- Use the CSV utility module to load the data templates we need for -- resources. local originalGoodsTable, goodsHeaderLookup = CsvUtils.luaTableFromCSV(CsvUtils.extractCSV(GOODS_DATA_TEMPLATE_NAME)) -- Now restructure the table so subtables can be passed to member functions -- for cleaner code. goodsTable = restructureGoodsTable(originalGoodsTable, goodsHeaderLookup) end

--- -- Retrieve all data for the specified good. -- -- @param goodName plain language name of the good -- @return a table containing the data for the specified good function GoodsData.getAllDataForGood(goodName) if not goodsTable then loadData end local targetGoodID = findGoodIDByName(goodName) if not targetGoodID then error("No good found. Please check spelling and any punctuation like an apostrophe: " .. goodName) end return goodsTable[targetGoodID] end

--- -- Since the goods information is already flat and well structured, all this has -- to do is swap out the integer keys for the good IDs and only return the data -- rows, without the header row. -- -- @param oldGoodsTable the CSV-based table, with a header row then data rows -- @param goodsHeaderLookup the lookup table built from the CSV data -- @return a new table for use in looking up goods data function restructureGoodsTable(oldGoodsTable, goodsHeaderLookup) local newGoodsTable = {} for _, good in ipairs(oldGoodsTable[DATA_ROWS]) do		newGoodsTable[good[INDEX_GOOD_ID]] = good end return newGoodsTable end

--- -- Look up so products and ingredients can be found by their common id, rather -- than their display name, which people are more familiar with. -- -- Uses the display name provided to look up the associated ID for the good. -- Builds a lookup table the first time it's called so it only has to happen -- once. -- -- @param displayName the plain-language name of the good to find -- @return the ID of the good found, or nil if not found function findGoodIDByName(displayName) if not goodsTable then loadData end local foundGoodID = nil -- Decide whether we need to traverse the big table. If this isn't the first -- time this method is called, we won't have to build the table again, we -- can just look it up. if not goodsNameToGoodID then goodsNameToGoodID = {} for goodID, good in pairs(goodsTable) do			if not foundGoodID and good[INDEX_GOOD_NAME] == displayName then -- Found it, keep traversing to build the rest of the map. foundGoodID = goodID end goodsNameToGoodID[good[INDEX_GOOD_NAME]] = goodID end else -- From the lookup table. foundGoodID = goodsNameToGoodID[displayName] end return foundGoodID end

--- -- Retrieves the name and icon filename for a good. -- -- @param goodID the ID of the good to look up -- @return display name, icon filename function GoodsData.getGoodNameAndIcon(goodID) if not recipeTable or not workshopTable or not goodsTable then loadData end local good = goodsTable[goodID] if not good then error("ID for good not found to look up name and icon: " .. goodID) end return good[INDEX_GOOD_NAME], good[INDEX_GOOD_ICON_FILENAME] end

return GoodsData