|
|
(26 intermediate revisions by the same user not shown) |
Line 1: |
Line 1: |
| | ---@module WorkshopsData.lua |
| --- | | --- |
| -- Module for compiling goods (or resources as some call them) information from | | ---This module does not define an _actual_ derived class, but it creates an instance of one via prototyping patterns. Understand this file as a big procedure, top-to-bottom, rather than a class definition. |
| -- wiki data sources. | |
| --
| |
| -- @module WorkshopsData
| |
| local WorkshopsData = {}
| |
| | |
| ---
| |
| -- Dependencies
| |
| ---
| |
| local CsvUtils = require("Module:CsvUtils")
| |
| | |
| ---
| |
| -- Constants for this module
| |
| ---
| |
| local WORKSHOPS_DATA_TEMPLATE_NAME = "Template:Workshops_csv"
| |
| | |
| local INDEX_WORKSHOP_ID = 1
| |
| local INDEX_WORKSHOP_NAME = 2
| |
| local INDEX_WORKSHOP_DESCRIPTION = 3
| |
| local INDEX_WORKSHOP_CATEGORY = 4
| |
| local INDEX_WORKSHOP_SIZE_X = 5
| |
| local INDEX_WORKSHOP_SIZE_Y = 6
| |
| local INDEX_WORKSHOP_CITY_SCORE = 7
| |
| local INDEX_WORKSHOP_MOVABLE = 8
| |
| local INDEX_WORKSHOP_INITIALLY_ESSENTIAL = 9
| |
| local INDEX_WORKSHOP_STORAGE = 10
| |
| local INDEX_WORKSHOP_CONSTRUCTION_TIME = 11
| |
| local INDEX_WORKSHOP_REQUIRED_GOODS = 12
| |
| local INDEX_WORKSHOP_WORKPLACES = 13
| |
| local INDEX_WORKSHOP_RECIPES = 14
| |
| | |
| local HEADER_ROW = 1
| |
| local DATA_ROWS = 2
| |
| | |
| local PATTERN_SPLIT_STACK_AND_ID = "(%d+)%s([%[%]%s%a]+)"
| |
| | |
| | |
| ---
| |
| -- Private member variables
| |
| ---
| |
| | |
| -- Main data tables. Populated from CSV data and organized better for Lua.
| |
| | |
| -- like this: table[workshopID] = table containing workshops data
| |
| local workshopsTable
| |
| | |
| -- Lookup map. Built once and reused on subsequent calls
| |
| -- like this: table[display name] = workshopID
| |
| local workshopNameToWorkshopID
| |
| | |
| | |
| | |
| ---
| |
| -- 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 originalWorkshopsTable, workshopsHeaderLookup = CsvUtils.luaTableFromCSV(CsvUtils.extractCSV(WORKSHOPS_DATA_TEMPLATE_NAME))
| |
|
| |
| -- Now restructure the table so subtables can be passed to member functions
| |
| -- for cleaner code.
| |
| workshopsTable = restructureWorkshopTable(originalWorkshopsTable, workshopsHeaderLookup)
| |
| end
| |
| | |
| | |
| | |
| --- | | --- |
| -- Retrieve all data for the specified workshop. Returned items look like this: | | ---Initializes a BaseDataModel with the data file associated with this module. Makes necessary modifications to the basic data, including schema and method overrides, to permit the exceptions associated with data in this model. |
| -- workshop {
| |
| -- id
| |
| -- display name
| |
| -- description
| |
| -- category
| |
| -- size x
| |
| -- size y
| |
| -- city score
| |
| -- movable
| |
| -- initially essential
| |
| -- storage
| |
| -- construction time
| |
| -- required goods (just their IDs) {
| |
| -- #1 { stack size, id }
| |
| -- #2 { stack size, id }
| |
| -- #3 { stack size, id }
| |
| -- }
| |
| -- workplaces {
| |
| -- workplace #1
| |
| -- workplace #2
| |
| -- workplace #3
| |
| -- workplace #4
| |
| -- }
| |
| -- recipes (just their IDs) {
| |
| -- recipe #1
| |
| -- recipe #2
| |
| -- recipe #3
| |
| -- recipe #4
| |
| -- }
| |
| -- }
| |
| --
| |
| -- @param workshopName plain language name of the workshop
| |
| -- @return a table containing the data for the specified workshop
| |
| function WorkshopsData.getAllDataForWorkshop(workshopName)
| |
|
| |
| if not workshopsTable then
| |
| loadData()
| |
| end
| |
|
| |
| local targetWorkshopID = findWorkshopIDByName(workshopName)
| |
| if not targetWorkshopID then
| |
| error("No building found. Please check spelling and any punctuation like an apostrophe: " .. workshopName)
| |
| end
| |
|
| |
| return workshopsTable[targetWorkshopID]
| |
| end
| |
|
| |
|
|
| |
|
|
| |
|
| --- | | --Create instance |
| -- Transforms the oldWorkshopsTable returned from CSV processing to be more
| | local BaseDataModel = require("Module:BaseDataModel") |
| -- conducive to member functions looking up data. Essentially, we convert the
| | local DATA_FILE = "Module:WorkshopsData/Workshops.json" |
| -- text strings into tables with the same base name and an index.
| |
| --
| |
| -- @param oldRecipeTable the CSV-based table, with a header row then data rows
| |
| -- @param recipeHeaderLookup the lookup table built from the CSV data
| |
| -- @return a new table for use in looking up recipe data
| |
| function restructureWorkshopTable(oldWorkshopTable, workshopsHeaderLookup)
| |
|
| |
| -- New table structure is only data rows, no header row needed. Therefore,
| |
| -- the new table is one degree flatter, like this:
| |
| -- oldWorkshopTable[2][1] contains the same data as newWorkshopTable[1]
| |
| -- (but organized by workshopID instead of by index and with subtables)
| |
| local newWorkshopTable = {}
| |
| oldWorkshopTable = oldWorkshopTable[DATA_ROWS]
| |
|
| |
| -- A few constants we need only in this function.
| |
| local INDEX_OLD_WORKSHOP_ID = 1
| |
| local INDEX_OLD_WORKSHOP_NAME = 2
| |
| local INDEX_OLD_WORKSHOP_DESCRIPTION = 3
| |
| local INDEX_OLD_WORKSHOP_CATEGORY = 4
| |
| local INDEX_OLD_WORKSHOP_SIZE_X = 5
| |
| local INDEX_OLD_WORKSHOP_SIZE_Y = 6
| |
| local INDEX_OLD_WORKSHOP_CONSTRUCTION_TIME = 10
| |
| local INDEX_OLD_WORKSHOP_CITY_SCORE = 11
| |
| local INDEX_OLD_WORKSHOP_MOVABLE = 12
| |
| local INDEX_OLD_WORKSHOP_INITIALLY_ESSENTIAL = 13
| |
| local INDEX_OLD_WORKSHOP_STORAGE = 14
| |
|
| |
| for i, oldWorkshop in ipairs(oldWorkshopTable) do
| |
|
| |
| local newWorkshop = {}
| |
|
| |
| -- Copy over the flat information from the old recipe.
| |
| local newWorkshopID = oldWorkshop[INDEX_OLD_WORKSHOP_ID]
| |
| newWorkshop[INDEX_WORKSHOP_ID] = newWorkshopID
| |
| newWorkshop[INDEX_WORKSHOP_NAME] = oldWorkshop[INDEX_OLD_WORKSHOP_NAME]
| |
| newWorkshop[INDEX_WORKSHOP_DESCRIPTION] = oldWorkshop[INDEX_OLD_WORKSHOP_DESCRIPTION]
| |
| newWorkshop[INDEX_WORKSHOP_CATEGORY] = oldWorkshop[INDEX_OLD_WORKSHOP_CATEGORY]
| |
| newWorkshop[INDEX_WORKSHOP_SIZE_X] = oldWorkshop[INDEX_OLD_WORKSHOP_SIZE_X]
| |
| newWorkshop[INDEX_WORKSHOP_SIZE_Y] = oldWorkshop[INDEX_OLD_WORKSHOP_SIZE_Y]
| |
| newWorkshop[INDEX_WORKSHOP_CITY_SCORE] = oldWorkshop[INDEX_OLD_WORKSHOP_CITY_SCORE]
| |
| newWorkshop[INDEX_WORKSHOP_MOVABLE] = oldWorkshop[INDEX_OLD_WORKSHOP_MOVABLE]
| |
| newWorkshop[INDEX_WORKSHOP_INITIALLY_ESSENTIAL] = oldWorkshop[INDEX_OLD_WORKSHOP_INITIALLY_ESSENTIAL]
| |
| newWorkshop[INDEX_WORKSHOP_STORAGE] = oldWorkshop[INDEX_OLD_WORKSHOP_STORAGE]
| |
| newWorkshop[INDEX_WORKSHOP_CONSTRUCTION_TIME] = oldWorkshop[INDEX_OLD_WORKSHOP_CONSTRUCTION_TIME]
| |
|
| |
| newWorkshop[INDEX_WORKSHOP_REQUIRED_GOODS] = makeRequiredGoodsSubtable(oldWorkshop, workshopsHeaderLookup)
| |
| newWorkshop[INDEX_WORKSHOP_WORKPLACES] = makeWorkplacesSubtable(oldWorkshop, workshopsHeaderLookup)
| |
| newWorkshop[INDEX_WORKSHOP_RECIPES] = makeRecipesSubtable(oldWorkshop, workshopsHeaderLookup)
| |
|
| |
| newWorkshopTable[newWorkshopID] = newWorkshop
| |
| end
| |
|
| |
| return newWorkshopTable
| |
| end
| |
|
| |
|
| | ---@type BaseDataModel |
| | local workshopsDataModel = BaseDataModel.new(DATA_FILE) |
|
| |
|
|
| |
|
| ---
| |
| -- Loops through the old workshop, extracting req'd goods and putting them
| |
| -- into a new subtable. Uses the lookup table from the CSV extraction to
| |
| -- keep the data in the same order.
| |
| --
| |
| -- @param oldWorkshop the workshop from which to extract req'd goods information
| |
| -- @param workshopsHeaderLookup the lookup table built from the CSV data
| |
| -- @return a subtable with the req'd goods information from oldWorkshop
| |
| function makeRequiredGoodsSubtable(oldWorkshop, workshopsHeaderLookup)
| |
|
| |
| -- A few constants we'll need only within this function.
| |
| local REQ_GOOD_MAX = 3
| |
| local LOOKUP_REQ_GOOD_BASE_STRING = "requiredGood"
| |
|
| |
| -- A subtable to return
| |
| local requiredGoods = {}
| |
| for i = 1,REQ_GOOD_MAX do
| |
|
| |
| local oldIndex = workshopsHeaderLookup[LOOKUP_REQ_GOOD_BASE_STRING .. i]
| |
|
| |
| local newGroup = {}
| |
| -- Split the digit part into the req'd good stack size and the rest
| |
| -- of the text into the req'd good's id.
| |
| newGroup[1], newGroup[2] = oldWorkshop[oldIndex]:match(PATTERN_SPLIT_STACK_AND_ID)
| |
| table.insert(requiredGoods, newGroup)
| |
| end
| |
|
| |
| return requiredGoods
| |
| end
| |
|
| |
|
| | | --Begin instance overrides |
| | | for _, building in pairs(workshopsDataModel.dataTable) do |
| ---
| | building[workshopsDataModel.schema.CATEGORY2] = "Production Building" |
| -- Loops through the old workshop, extracting workplaces and putting them
| | building[workshopsDataModel.schema.IS_PROVIDING_SERVICES] = false |
| -- into a new subtable. Uses the lookup table from the CSV extraction to
| |
| -- keep the data in the same order.
| |
| --
| |
| -- @param oldWorkshop the workshop from which to extract workplaces information
| |
| -- @param workshopsHeaderLookup the lookup table built from the CSV data
| |
| -- @return a subtable with the workplaces information from oldWorkshop
| |
| function makeWorkplacesSubtable(oldWorkshop, workshopsHeaderLookup)
| |
|
| |
| -- A few constants we'll need only within this function.
| |
| local WORKPLACE_MAX = 4
| |
| local LOOKUP_WORKPLACE_BASE_STRING = "workplace"
| |
|
| |
| -- A subtable to return
| |
| local workplaces = {}
| |
|
| |
| for i = 1,WORKPLACE_MAX do
| |
|
| |
| local oldIndex = workshopsHeaderLookup[LOOKUP_WORKPLACE_BASE_STRING .. i]
| |
| workplaces[i] = oldWorkshop[oldIndex]
| |
| end
| |
|
| |
| return workplaces
| |
| end | | end |
|
| |
|
|
| |
|
|
| |
|
| --- | | --/** Function definitions follow. **/ |
| -- Loops through the old workshop, extracting recipes and putting them
| | --Collapse the regions in the IDE to see the procedure pick up with the assignments of these functions to override the associated member methods of BaseDataModel. |
| -- into a new subtable. Uses the lookup table from the CSV extraction to
| | --region Public building interface |
| -- keep the data in the same order. | | --no overrides! |
| --
| | --endregion |
| -- @param oldWorkshop the workshop from which to extract recipes
| |
| -- @param workshopsHeaderLookup the lookup table built from the CSV data
| |
| -- @return a subtable with the recipes from oldWorkshop
| |
| function makeRecipesSubtable(oldWorkshop, workshopsHeaderLookup)
| |
|
| |
| -- A few constants we'll need only within this function.
| |
| local RECIPE_MAX = 4
| |
| local LOOKUP_RECIPE_BASE_STRING = "recipe"
| |
|
| |
| -- A subtable to return
| |
| local recipes = {}
| |
|
| |
| for i=1,RECIPE_MAX do
| |
|
| |
| local oldIndex = workshopsHeaderLookup[LOOKUP_RECIPE_BASE_STRING .. i]
| |
| recipes[i] = oldWorkshop[oldIndex]
| |
| end
| |
|
| |
| return recipes
| |
| end
| |
| | |
| | |
| | |
| ---
| |
| -- Look up so workshops 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 workshop.
| |
| -- 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 workshop to find
| |
| -- @return the ID of the workshop found, or nil if not found
| |
| function findWorkshopIDByName(displayName)
| |
|
| |
| if not workshopsTable then
| |
| loadData()
| |
| end
| |
|
| |
| local foundWorkshopID = 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 workshopNameToWorkshopID then
| |
|
| |
| workshopNameToWorkshopID = {}
| |
|
| |
| for workshopID, workshop in pairs(workshopsTable) do
| |
|
| |
| if not foundWorkshopID and workshop[INDEX_WORKSHOP_NAME] == displayName then
| |
| -- Found it, but keep traversing to build the rest of the map.
| |
| foundWorkshopID = workshopID
| |
| end
| |
|
| |
| workshopNameToWorkshopID[workshop[INDEX_WORKSHOP_NAME]] = workshopID
| |
| end
| |
| else
| |
| -- From the lookup table.
| |
| foundWorkshopID = workshopNameToWorkshopID[displayName]
| |
| end
| |
|
| |
| return foundWorkshopID
| |
| end
| |
|
| |
|
| | --region Public building recipe query interface |
| | --no overrides! |
| | --endregion |
|
| |
|
| | | --region Public recipe data retrieval interface |
| ---
| | --no overrides! |
| -- Retrieves the name and icon filename for a workshop. | | --endregion |
| -- | | --/** End Function definitions. Procedure resumes. **/ |
| -- @param workshopID the ID of the workshop to look up | |
| -- @return display name, icon filename | |
| function WorkshopsData.getWorkshopNameAndIcon(workshopID)
| |
|
| |
| if not workshopsTable then
| |
| loadData()
| |
| end
| |
|
| |
| local workshop = workshopsTable[workshopID]
| |
|
| |
| if not workshop then
| |
| error("ID for workshop not found to look up name and icon: " .. workshopID)
| |
| end
| |
|
| |
| return workshop[INDEX_WORKSHOP_NAME], workshop[INDEX_WORKSHOP_NAME] .. "_icon"
| |
| end
| |
|
| |
|
|
| |
|
|
| |
|
| return WorkshopsData | | return workshopsDataModel |