Module:Building data: Difference between revisions

From Beyond These Stars Official Wiki
Added skip for building controls when retrieving all buildings only. also added interface constant for building Names without portraits to avoid page lookup
m fixed a few building Names that should have missing portraits or should be skipped
Line 1,101: Line 1,101:
   ["CompostTool"] = true,
   ["CompostTool"] = true,
   ["CompostingSite"] = true,
   ["CompostingSite"] = true,
   ["Forest"] = true,
   ["Forest_WorldTwo"] = true,
   ["HomeSpaceshipLanded"] = true,
   ["HomeSpaceshipLanded"] = true,
   ["Mill"] = true,
   ["Mill"] = true,
Line 1,127: Line 1,127:
   ["RampConstruction"] = true,
   ["RampConstruction"] = true,
   ["RepairControl"] = true,
   ["RepairControl"] = true,
   ["Resource Cache"] = true,
   ["ResourceCache"] = true,
   ["RoadConstruction"] = true,
   ["RoadConstruction"] = true,
   ["SettlementSpaceshipReload"] = true,
   ["SettlementSpaceshipReload"] = true,

Revision as of 03:46, 25 September 2026

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

--[[
Test in Scribunto console with:
=mw.dumpObject(p.get_building("Ore Smelter"))
]]--
local p = {}



--#region Cargo-related type definitions and constants

--- Cargo row from querying Buildings; all values are strings at runtime.
---@class CargoBuildingRecord
---@field page_name string|nil
---@field guid string|nil
---@field Name string|nil
---@field Category string|nil
---@field DisplayNameTerm_en string|nil
---@field DisplayNamePluralTerm_en string|nil
---@field DescriptionTerm_en string|nil
---@field UpgradeTerm string|nil
---@field UpgradeTerm_en string|nil
---@field IconAddress string|nil
---@field PlacementRules_1 string|nil
---@field PlacementRules_2 string|nil
---@field PlacementRules_3 string|nil
---@field PlacementRules_4 string|nil
---@field PlacementRules_5 string|nil
---@field PlacementRules_6 string|nil
---@field AnchorBuildingNames_1 string|nil
---@field AnchorBuildingNames_2 string|nil
---@field ConstructionResources string|nil
---@field ConstructionResources_1_Name string|nil
---@field ConstructionResources_1_Amount string|nil
---@field ConstructionResources_2_Name string|nil
---@field ConstructionResources_2_Amount string|nil
---@field ConstructionResources_3_Name string|nil
---@field ConstructionResources_3_Amount string|nil
---@field ConstructionResources_4_Name string|nil
---@field ConstructionResources_4_Amount string|nil
---@field ConstructionResources_5_Name string|nil
---@field ConstructionResources_5_Amount string|nil
---@field ConstructionResources_6_Name string|nil
---@field ConstructionResources_6_Amount string|nil
---@field SecondaryPrefabAddresses_1 string|nil
---@field SecondaryPrefabAddresses_2 string|nil
---@field RepairResources_1_Name string|nil
---@field RepairResources_1_Amount string|nil
---@field RepairResources_2_Name string|nil
---@field RepairResources_2_Amount string|nil
---@field RepairResources_3_Name string|nil
---@field RepairResources_3_Amount string|nil
---@field RepairResources_4_Name string|nil
---@field RepairResources_4_Amount string|nil
---@field RepairResources_5_Name string|nil
---@field RepairResources_5_Amount string|nil
---@field RepairResources_6_Name string|nil
---@field RepairResources_6_Amount string|nil
---@field ConstructionTime string|nil
---@field ConstructionPeepCount string|nil
---@field UnlockMode string|nil
---@field UnlockValues string|nil
---@field UnlockValues_1 string|nil
---@field UnlockValues_2 string|nil
---@field UnlockValues_3 string|nil
---@field UnlockValues_4 string|nil
---@field RequiredRecords_1 string|nil
---@field UpgradePointsEarned string|nil
---@field LockedInDemo string|nil
---@field FootprintIconAddress string|nil
---@field TechTreeDisplay string|nil
---@field TechTreePrevious string|nil
---@field TechTreeRow string|nil
---@field AdjacencyBonuses string|nil
---@field AdjacencyBonuses_1_GroupName string|nil
---@field AdjacencyBonuses_1_Evaluator string|nil
---@field AdjacencyBonuses_1_EvaluatorThreshold string|nil
---@field AdjacencyBonuses_1_Action string|nil
---@field AdjacencyBonuses_1_ActionNames string|nil
---@field AdjacencyBonuses_1_ActionNames_1 string|nil
---@field AdjacencyBonuses_1_ActionNames_2 string|nil
---@field AdjacencyBonuses_1_ActionNames_3 string|nil
---@field AdjacencyBonuses_1_ActionNames_4 string|nil
---@field AdjacencyBonuses_1_ActionNames_5 string|nil
---@field AdjacencyBonuses_1_EvaluatorValue string|nil
---@field AdjacencyBonuses_1_ActionValue string|nil
---@field AdjacencyBonuses_2_GroupName string|nil
---@field AdjacencyBonuses_2_Evaluator string|nil
---@field AdjacencyBonuses_2_EvaluatorThreshold string|nil
---@field AdjacencyBonuses_2_Action string|nil
---@field AdjacencyBonuses_2_ActionNames string|nil
---@field AdjacencyBonuses_2_ActionNames_1 string|nil
---@field AdjacencyBonuses_2_ActionNames_2 string|nil
---@field AdjacencyBonuses_2_ActionNames_3 string|nil
---@field AdjacencyBonuses_2_ActionNames_4 string|nil
---@field AdjacencyBonuses_2_ActionNames_5 string|nil
---@field AdjacencyBonuses_2_EvaluatorValue string|nil
---@field AdjacencyBonuses_2_ActionValue string|nil
---@field AdjacencyBonuses_3_GroupName string|nil
---@field AdjacencyBonuses_3_Evaluator string|nil
---@field AdjacencyBonuses_3_EvaluatorThreshold string|nil
---@field AdjacencyBonuses_3_Action string|nil
---@field AdjacencyBonuses_3_ActionNames string|nil
---@field AdjacencyBonuses_3_ActionNames_1 string|nil
---@field AdjacencyBonuses_3_ActionNames_2 string|nil
---@field AdjacencyBonuses_3_ActionNames_3 string|nil
---@field AdjacencyBonuses_3_ActionNames_4 string|nil
---@field AdjacencyBonuses_3_EvaluatorValue string|nil
---@field AdjacencyBonuses_3_ActionValue string|nil
---@field AdjacencyBonuses_4_GroupName string|nil
---@field AdjacencyBonuses_4_Evaluator string|nil
---@field AdjacencyBonuses_4_EvaluatorThreshold string|nil
---@field AdjacencyBonuses_4_Action string|nil
---@field AdjacencyBonuses_4_ActionNames string|nil
---@field AdjacencyBonuses_4_EvaluatorValue string|nil
---@field AdjacencyBonuses_4_ActionValue string|nil
---@field OperationRules string|nil
---@field OperationRules_1 string|nil
---@field OperationRules_2 string|nil
---@field OperationRules_3 string|nil
---@field OperationRules_4 string|nil
---@field OperationRules_5 string|nil
---@field OperationRules_6 string|nil
---@field OperationRules_7 string|nil
---@field OperationRules_8 string|nil
---@field OperationRules_9 string|nil
---@field OperationRules_10 string|nil
---@field OperationRules_11 string|nil
---@field OperationRules_12 string|nil
---@field OperationRules_13 string|nil
---@field MaxPeeps string|nil
---@field PeepExhaustionRemoved string|nil
---@field PeepAgeAdded string|nil
---@field PeepHappinessAdded string|nil
---@field PeepHappinessCost string|nil
---@field PollutionOutputMode string|nil
---@field SourceOfOxygenRange string|nil
---@field Resources string|nil
---@field Resources_1_Name string|nil
---@field Resources_1_Maximum string|nil
---@field Resources_1_StorageMode string|nil
---@field Resources_1_StartFull string|nil
---@field Resources_1_FetchInRange string|nil
---@field Resources_1_CanBeShared string|nil
---@field Resources_1_CycleThoughResourceSources string|nil
---@field Resources_1_GatheringMode string|nil
---@field Resources_1_DistributionMode string|nil
---@field Resources_1_DeliverInRange string|nil
---@field Resources_1_VehicleFetchsAndDelivers string|nil
---@field Resources_2_Name string|nil
---@field Resources_2_Maximum string|nil
---@field Resources_2_StorageMode string|nil
---@field Resources_2_StartFull string|nil
---@field Resources_2_FetchInRange string|nil
---@field Resources_2_CanBeShared string|nil
---@field Resources_2_CycleThoughResourceSources string|nil
---@field Resources_2_GatheringMode string|nil
---@field Resources_2_DistributionMode string|nil
---@field Resources_2_DeliverInRange string|nil
---@field Resources_2_VehicleFetchsAndDelivers string|nil
---@field Resources_3_Name string|nil
---@field Resources_3_Maximum string|nil
---@field Resources_3_StorageMode string|nil
---@field Resources_3_StartFull string|nil
---@field Resources_3_FetchInRange string|nil
---@field Resources_3_CanBeShared string|nil
---@field Resources_3_CycleThoughResourceSources string|nil
---@field Resources_3_GatheringMode string|nil
---@field Resources_3_DistributionMode string|nil
---@field Resources_3_DeliverInRange string|nil
---@field Resources_3_VehicleFetchsAndDelivers string|nil
---@field Resources_4_Name string|nil
---@field Resources_4_Maximum string|nil
---@field Resources_4_StorageMode string|nil
---@field Resources_4_StartFull string|nil
---@field Resources_4_FetchInRange string|nil
---@field Resources_4_CanBeShared string|nil
---@field Resources_4_CycleThoughResourceSources string|nil
---@field Resources_4_GatheringMode string|nil
---@field Resources_4_DistributionMode string|nil
---@field Resources_4_DeliverInRange string|nil
---@field Resources_4_VehicleFetchsAndDelivers string|nil
---@field Resources_5_Name string|nil
---@field Resources_5_Maximum string|nil
---@field Resources_5_StorageMode string|nil
---@field Resources_5_StartFull string|nil
---@field Resources_5_FetchInRange string|nil
---@field Resources_5_CanBeShared string|nil
---@field Resources_5_CycleThoughResourceSources string|nil
---@field Resources_5_GatheringMode string|nil
---@field Resources_5_DistributionMode string|nil
---@field Resources_5_DeliverInRange string|nil
---@field Resources_5_VehicleFetchsAndDelivers string|nil
---@field Resources_6_Name string|nil
---@field Resources_6_Maximum string|nil
---@field Resources_6_StorageMode string|nil
---@field Resources_6_StartFull string|nil
---@field Resources_6_FetchInRange string|nil
---@field Resources_6_CanBeShared string|nil
---@field Resources_6_CycleThoughResourceSources string|nil
---@field Resources_6_GatheringMode string|nil
---@field Resources_6_DistributionMode string|nil
---@field Resources_6_DeliverInRange string|nil
---@field Resources_6_VehicleFetchsAndDelivers string|nil
---@field Resources_7_Name string|nil
---@field Resources_7_Maximum string|nil
---@field Resources_7_StorageMode string|nil
---@field Resources_7_StartFull string|nil
---@field Resources_7_FetchInRange string|nil
---@field Resources_7_CanBeShared string|nil
---@field Resources_7_CycleThoughResourceSources string|nil
---@field Resources_7_GatheringMode string|nil
---@field Resources_7_DistributionMode string|nil
---@field Resources_7_DeliverInRange string|nil
---@field Resources_7_VehicleFetchsAndDelivers string|nil
---@field Resources_8_Name string|nil
---@field Resources_8_Maximum string|nil
---@field Resources_8_StorageMode string|nil
---@field Resources_8_StartFull string|nil
---@field Resources_8_FetchInRange string|nil
---@field Resources_8_CanBeShared string|nil
---@field Resources_8_CycleThoughResourceSources string|nil
---@field Resources_8_GatheringMode string|nil
---@field Resources_8_DistributionMode string|nil
---@field Resources_8_DeliverInRange string|nil
---@field Resources_8_VehicleFetchsAndDelivers string|nil
---@field Resources_9_Name string|nil
---@field Resources_9_Maximum string|nil
---@field Resources_9_StorageMode string|nil
---@field Resources_9_StartFull string|nil
---@field Resources_9_FetchInRange string|nil
---@field Resources_9_CanBeShared string|nil
---@field Resources_9_CycleThoughResourceSources string|nil
---@field Resources_9_GatheringMode string|nil
---@field Resources_9_DistributionMode string|nil
---@field Resources_9_DeliverInRange string|nil
---@field Resources_9_VehicleFetchsAndDelivers string|nil
---@field ResourceGroups string|nil
---@field ResourceGroups_1_Type string|nil
---@field ResourceGroups_1_Maximum string|nil
---@field ResourceGroups_1_GatheringMode string|nil
---@field ResourceGroups_1_DistributionMode string|nil
---@field ResourceGroups_1_StartFullResource string|nil
---@field ResourceGroups_2_Type string|nil
---@field ResourceGroups_2_Maximum string|nil
---@field ResourceGroups_2_GatheringMode string|nil
---@field ResourceGroups_2_DistributionMode string|nil
---@field ResourceGroups_2_StartFullResource string|nil
---@field DefinedResourceLists string|nil
---@field DefinedResourceLists_2_Name string|nil
---@field DefinedResourceLists_2_Maximum string|nil
---@field DefinedResourceLists_2_StorageMode string|nil
---@field DefinedResourceLists_2_StartFull string|nil
---@field DefinedResourceLists_2_FetchInRange string|nil
---@field DefinedResourceLists_2_CanBeShared string|nil
---@field DefinedResourceLists_2_CycleThoughResourceSources string|nil
---@field DefinedResourceLists_2_GatheringMode string|nil
---@field DefinedResourceLists_2_DistributionMode string|nil
---@field DefinedResourceLists_2_DeliverInRange string|nil
---@field DefinedResourceLists_2_VehicleFetchsAndDelivers string|nil
---@field DefaultFetchMode string|nil
---@field DefaultDeliveryMode string|nil
---@field FetchTime string|nil
---@field DeliveryTime string|nil
---@field TotalStorageMaximum string|nil
---@field MaxSeedSlots string|nil
---@field BuildingTasks string|nil
---@field PlayerSelectableTasks_1 string|nil
---@field PlayerSelectableTasks_2 string|nil
---@field PlayerSelectableTasks_3 string|nil
---@field SourceDefinition string|nil
---@field Hotkey string|nil
---@field ConstructionMustReplace string|nil
---@field AutoUnlock string|nil
---@field TechTreeListPreviousExit string|nil
---@field TechTreeListEntry string|nil
---@field TechTreeLineVerticalOffset string|nil
---@field PowerRange string|nil
---@field PeepEnergyAdded string|nil
---@field PeepEnergyCost string|nil

-- FIELDS that fit the pattern but were proven to not exist: 
--   BuildingTasks_4_Outputs_2_*
--   BuildingTasks_4_Inputs_2_*
--   BuildingTasks_5_Outputs_2_*
--   BuildingTasks_5_Inputs_2_*
-- Commented out fields are not used in BuildingTask
--- Cargo row from querying BuildingTasks; all values are strings at runtime.
---@class CargoBuildingTasksRecord
---@field BuildingTasks_1_Name string|nil
---@field BuildingTasks_1_InitialState string|nil
---@field BuildingTasks_1_Time string|nil
---@field BuildingTasks_1_MinimumTimeDelta string|nil
---@field BuildingTasks_1_Outputs_1_Type string|nil
---@field BuildingTasks_1_Outputs_1_Resource string|nil
---@field BuildingTasks_1_Outputs_1_Value string|nil
---@field BuildingTasks_1_Outputs_2_Type string|nil
---@field BuildingTasks_1_Outputs_2_Resource string|nil
---@field BuildingTasks_1_Outputs_2_Value string|nil
---@field BuildingTasks_1_PollutionSlowdownThreshold string|nil
---@field BuildingTasks_1_Inputs_1_Type string|nil
---@field BuildingTasks_1_Inputs_1_Resource string|nil
---@field BuildingTasks_1_Inputs_1_Value string|nil
---@field BuildingTasks_1_Inputs_2_Type string|nil
---@field BuildingTasks_1_Inputs_2_Resource string|nil
---@field BuildingTasks_1_Inputs_2_Value string|nil
---@field BuildingTasks_1_Inputs_3_Type string|nil
---@field BuildingTasks_1_Inputs_3_Resource string|nil
---@field BuildingTasks_1_Inputs_3_Value string|nil
---@field BuildingTasks_1_Inputs_4_Type string|nil
---@field BuildingTasks_1_Inputs_4_Resource string|nil
---@field BuildingTasks_1_Inputs_4_Value string|nil
---@field BuildingTasks_1_DescriptionTerm_en string|nil
---@field BuildingTasks_2_Name string|nil
---@field BuildingTasks_2_InitialState string|nil
---@field BuildingTasks_2_Time string|nil
---@field BuildingTasks_2_MinimumTimeDelta string|nil
---@field BuildingTasks_2_Outputs_1_Type string|nil
---@field BuildingTasks_2_Outputs_1_Resource string|nil
---@field BuildingTasks_2_Outputs_1_Value string|nil
---@field BuildingTasks_2_Outputs_2_Type string|nil
---@field BuildingTasks_2_Outputs_2_Resource string|nil
---@field BuildingTasks_2_Outputs_2_Value string|nil
---@field BuildingTasks_2_PollutionSlowdownThreshold string|nil
---@field BuildingTasks_2_Inputs_1_Type string|nil
---@field BuildingTasks_2_Inputs_1_Resource string|nil
---@field BuildingTasks_2_Inputs_1_Value string|nil
---@field BuildingTasks_2_Inputs_2_Type string|nil
---@field BuildingTasks_2_Inputs_2_Resource string|nil
---@field BuildingTasks_2_Inputs_2_Value string|nil
---@field BuildingTasks_2_Inputs_3_Type string|nil
---@field BuildingTasks_2_Inputs_3_Resource string|nil
---@field BuildingTasks_2_Inputs_3_Value string|nil
---@field BuildingTasks_3_Name string|nil
---@field BuildingTasks_3_InitialState string|nil
---@field BuildingTasks_3_Time string|nil
---@field BuildingTasks_3_MinimumTimeDelta string|nil
---@field BuildingTasks_3_Outputs_1_Type string|nil
---@field BuildingTasks_3_Outputs_1_Resource string|nil
---@field BuildingTasks_3_Outputs_1_Value string|nil
---@field BuildingTasks_3_Outputs_2_Type string|nil
---@field BuildingTasks_3_Outputs_2_Resource string|nil
---@field BuildingTasks_3_Outputs_2_Value string|nil
---@field BuildingTasks_3_PollutionSlowdownThreshold string|nil
---@field BuildingTasks_3_Inputs_1_Type string|nil
---@field BuildingTasks_3_Inputs_1_Resource string|nil
---@field BuildingTasks_3_Inputs_1_Value string|nil
---@field BuildingTasks_3_Inputs_2_Type string|nil
---@field BuildingTasks_3_Inputs_2_Resource string|nil
---@field BuildingTasks_3_Inputs_2_Value string|nil
---@field BuildingTasks_4_Name string|nil
---@field BuildingTasks_4_InitialState string|nil
---@field BuildingTasks_4_Time string|nil
---@field BuildingTasks_4_MinimumTimeDelta string|nil
---@field BuildingTasks_4_Outputs_1_Type string|nil
---@field BuildingTasks_4_Outputs_1_Resource string|nil
---@field BuildingTasks_4_Outputs_1_Value string|nil
---@field BuildingTasks_4_PollutionSlowdownThreshold string|nil
---@field BuildingTasks_4_Inputs_1_Type string|nil
---@field BuildingTasks_4_Inputs_1_Resource string|nil
---@field BuildingTasks_4_Inputs_1_Value string|nil
---@field BuildingTasks_5_Name string|nil
---@field BuildingTasks_5_InitialState string|nil
---@field BuildingTasks_5_Time string|nil
---@field BuildingTasks_5_MinimumTimeDelta string|nil
---@field BuildingTasks_5_Outputs_1_Type string|nil
---@field BuildingTasks_5_Outputs_1_Resource string|nil
---@field BuildingTasks_5_Outputs_1_Value string|nil
---@field BuildingTasks_5_PollutionSlowdownThreshold string|nil
---@field BuildingTasks_5_Inputs_1_Type string|nil
---@field BuildingTasks_5_Inputs_1_Resource string|nil
---@field BuildingTasks_5_Inputs_1_Value string|nil
---@field BuildingTasks_6_Name string|nil
---@field BuildingTasks_6_InitialState string|nil
---@field BuildingTasks_6_Time string|nil
---@field BuildingTasks_6_MinimumTimeDelta string|nil
---@field BuildingTasks_6_Outputs_1_Type string|nil
---@field BuildingTasks_6_Outputs_1_Resource string|nil
---@field BuildingTasks_6_Outputs_1_Value string|nil
---@field BuildingTasks_6_PollutionSlowdownThreshold string|nil
---@field BuildingTasks_6_Inputs_1_Type string|nil
---@field BuildingTasks_6_Inputs_1_Resource string|nil
---@field BuildingTasks_6_Inputs_1_Value string|nil
---@field BuildingTasks_6_Inputs_2_Type string|nil
---@field BuildingTasks_6_Inputs_2_Resource string|nil
---@field BuildingTasks_6_Inputs_2_Value string|nil
---@field BuildingTasks_7_Name string|nil
---@field BuildingTasks_7_InitialState string|nil
---@field BuildingTasks_7_Time string|nil
---@field BuildingTasks_7_MinimumTimeDelta string|nil
---@field BuildingTasks_7_Outputs_1_Type string|nil
---@field BuildingTasks_7_Outputs_1_Resource string|nil
---@field BuildingTasks_7_Outputs_1_Value string|nil
---@field BuildingTasks_7_PollutionSlowdownThreshold string|nil
---@field BuildingTasks_7_Inputs_1_Type string|nil
---@field BuildingTasks_7_Inputs_1_Resource string|nil
---@field BuildingTasks_7_Inputs_1_Value string|nil
---@field BuildingTasks_8_Name string|nil
---@field BuildingTasks_8_InitialState string|nil
---@field BuildingTasks_8_Time string|nil
---@field BuildingTasks_8_MinimumTimeDelta string|nil
---@field BuildingTasks_8_Outputs_1_Type string|nil
---@field BuildingTasks_8_Outputs_1_Resource string|nil
---@field BuildingTasks_8_Outputs_1_Value string|nil
---@field BuildingTasks_8_PollutionSlowdownThreshold string|nil
---@field BuildingTasks_8_Inputs_1_Type string|nil
---@field BuildingTasks_8_Inputs_1_Resource string|nil
---@field BuildingTasks_8_Inputs_1_Value string|nil
---@field BuildingTasks_9_Name string|nil
---@field BuildingTasks_9_InitialState string|nil
---@field BuildingTasks_9_Time string|nil
---@field BuildingTasks_9_MinimumTimeDelta string|nil
---@field BuildingTasks_9_Outputs_1_Type string|nil
---@field BuildingTasks_9_Outputs_1_Resource string|nil
---@field BuildingTasks_9_Outputs_1_Value string|nil
---@field BuildingTasks_9_PollutionSlowdownThreshold string|nil
---@field BuildingTasks_9_Inputs_1_Type string|nil
---@field BuildingTasks_9_Inputs_1_Resource string|nil
---@field BuildingTasks_9_Inputs_1_Value string|nil

local QUERIES = {
  BUILDINGS = {
    TABLE = "Buildings",
    WHERE_NAME = "page_name",
    WHERE_ID = "Name",
    ORDER_BY = "page_name",
    FIELDS_NAME_ONLY = {
      "page_name",
    },
    FIELDS_FULL = {
      "page_name",
      "guid",
      "Name",
      "Category",
      "DisplayNameTerm_en",
      "DisplayNamePluralTerm_en",
      "DescriptionTerm_en",
      -- "UpgradeTerm",
      -- "UpgradeTerm_en",
      "IconAddress",
      -- "PlacementRules_1",
      -- "PlacementRules_2",
      -- "PlacementRules_3",
      -- "PlacementRules_4",
      -- "PlacementRules_5",
      -- "PlacementRules_6",
      -- "AnchorBuildingNames_1",
      -- "AnchorBuildingNames_2",
      -- "ConstructionResources",
      "ConstructionResources_1_Name",
      "ConstructionResources_1_Amount",
      "ConstructionResources_2_Name",
      "ConstructionResources_2_Amount",
      "ConstructionResources_3_Name",
      "ConstructionResources_3_Amount",
      "ConstructionResources_4_Name",
      "ConstructionResources_4_Amount",
      "ConstructionResources_5_Name",
      "ConstructionResources_5_Amount",
      "ConstructionResources_6_Name",
      "ConstructionResources_6_Amount",
      -- "SecondaryPrefabAddresses_1",
      -- "SecondaryPrefabAddresses_2",
      -- "RepairResources_1_Name",
      -- "RepairResources_1_Amount",
      -- "RepairResources_2_Name",
      -- "RepairResources_2_Amount",
      -- "RepairResources_3_Name",
      -- "RepairResources_3_Amount",
      -- "RepairResources_4_Name",
      -- "RepairResources_4_Amount",
      -- "RepairResources_5_Name",
      -- "RepairResources_5_Amount",
      -- "RepairResources_6_Name",
      -- "RepairResources_6_Amount",
      "ConstructionTime",
      -- "ConstructionPeepCount",
      "UnlockMode",
      "UnlockValues",
      "UnlockValues_1",
      "UnlockValues_2",
      "UnlockValues_3",
      "UnlockValues_4",
      -- "RequiredRecords_1",
      -- "UpgradePointsEarned",
      "LockedInDemo",
      "FootprintIconAddress",
      -- "TechTreeDisplay",
      "TechTreePrevious",
      -- "TechTreeRow",
      -- "AdjacencyBonuses",
      "AdjacencyBonuses_1_GroupName",
      "AdjacencyBonuses_1_Evaluator",
      "AdjacencyBonuses_1_EvaluatorThreshold",
      "AdjacencyBonuses_1_Action",
      -- "AdjacencyBonuses_1_ActionNames",
      -- "AdjacencyBonuses_1_ActionNames_1",
      -- "AdjacencyBonuses_1_ActionNames_2",
      -- "AdjacencyBonuses_1_ActionNames_3",
      -- "AdjacencyBonuses_1_ActionNames_4",
      -- "AdjacencyBonuses_1_ActionNames_5",
      "AdjacencyBonuses_1_EvaluatorValue",
      "AdjacencyBonuses_1_ActionValue",
      "AdjacencyBonuses_2_GroupName",
      "AdjacencyBonuses_2_Evaluator",
      "AdjacencyBonuses_2_EvaluatorThreshold",
      "AdjacencyBonuses_2_Action",
      -- "AdjacencyBonuses_2_ActionNames",
      -- "AdjacencyBonuses_2_ActionNames_1",
      -- "AdjacencyBonuses_2_ActionNames_2",
      -- "AdjacencyBonuses_2_ActionNames_3",
      -- "AdjacencyBonuses_2_ActionNames_4",
      -- "AdjacencyBonuses_2_ActionNames_5",
      "AdjacencyBonuses_2_EvaluatorValue",
      "AdjacencyBonuses_2_ActionValue",
      "AdjacencyBonuses_3_GroupName",
      "AdjacencyBonuses_3_Evaluator",
      "AdjacencyBonuses_3_EvaluatorThreshold",
      "AdjacencyBonuses_3_Action",
      -- "AdjacencyBonuses_3_ActionNames",
      -- "AdjacencyBonuses_3_ActionNames_1",
      -- "AdjacencyBonuses_3_ActionNames_2",
      -- "AdjacencyBonuses_3_ActionNames_3",
      -- "AdjacencyBonuses_3_ActionNames_4",
      "AdjacencyBonuses_3_EvaluatorValue",
      "AdjacencyBonuses_3_ActionValue",
      "AdjacencyBonuses_4_GroupName",
      "AdjacencyBonuses_4_Evaluator",
      "AdjacencyBonuses_4_EvaluatorThreshold",
      "AdjacencyBonuses_4_Action",
      -- "AdjacencyBonuses_4_ActionNames",
      "AdjacencyBonuses_4_EvaluatorValue",
      "AdjacencyBonuses_4_ActionValue",
      -- "OperationRules",
      -- "OperationRules_1",
      -- "OperationRules_2",
      -- "OperationRules_3",
      -- "OperationRules_4",
      -- "OperationRules_5",
      -- "OperationRules_6",
      -- "OperationRules_7",
      -- "OperationRules_8",
      -- "OperationRules_9",
      -- "OperationRules_10",
      -- "OperationRules_11",
      -- "OperationRules_12",
      -- "OperationRules_13",
      "MaxPeeps",
      "PeepExhaustionRemoved",
      "PeepAgeAdded",
      "PeepHappinessAdded",
      "PeepHappinessCost",
      "PollutionOutputMode",
      "SourceOfOxygenRange",
      -- "Resources",
      -- "Resources_1_Name",
      -- "Resources_1_Maximum",
      -- "Resources_1_StorageMode",
      -- "Resources_1_StartFull",
      -- "Resources_1_FetchInRange",
      -- "Resources_1_CanBeShared",
      -- "Resources_1_CycleThoughResourceSources",
      -- "Resources_1_GatheringMode",
      -- "Resources_1_DistributionMode",
      -- "Resources_1_DeliverInRange",
      -- "Resources_1_VehicleFetchsAndDelivers",
      -- "Resources_2_Name",
      -- "Resources_2_Maximum",
      -- "Resources_2_StorageMode",
      -- "Resources_2_StartFull",
      -- "Resources_2_FetchInRange",
      -- "Resources_2_CanBeShared",
      -- "Resources_2_CycleThoughResourceSources",
      -- "Resources_2_GatheringMode",
      -- "Resources_2_DistributionMode",
      -- "Resources_2_DeliverInRange",
      -- "Resources_2_VehicleFetchsAndDelivers",
      -- "Resources_3_Name",
      -- "Resources_3_Maximum",
      -- "Resources_3_StorageMode",
      -- "Resources_3_StartFull",
      -- "Resources_3_FetchInRange",
      -- "Resources_3_CanBeShared",
      -- "Resources_3_CycleThoughResourceSources",
      -- "Resources_3_GatheringMode",
      -- "Resources_3_DistributionMode",
      -- "Resources_3_DeliverInRange",
      -- "Resources_3_VehicleFetchsAndDelivers",
      -- "Resources_4_Name",
      -- "Resources_4_Maximum",
      -- "Resources_4_StorageMode",
      -- "Resources_4_StartFull",
      -- "Resources_4_FetchInRange",
      -- "Resources_4_CanBeShared",
      -- "Resources_4_CycleThoughResourceSources",
      -- "Resources_4_GatheringMode",
      -- "Resources_4_DistributionMode",
      -- "Resources_4_DeliverInRange",
      -- "Resources_4_VehicleFetchsAndDelivers",
      -- "Resources_5_Name",
      -- "Resources_5_Maximum",
      -- "Resources_5_StorageMode",
      -- "Resources_5_StartFull",
      -- "Resources_5_FetchInRange",
      -- "Resources_5_CanBeShared",
      -- "Resources_5_CycleThoughResourceSources",
      -- "Resources_5_GatheringMode",
      -- "Resources_5_DistributionMode",
      -- "Resources_5_DeliverInRange",
      -- "Resources_5_VehicleFetchsAndDelivers",
      -- "Resources_6_Name",
      -- "Resources_6_Maximum",
      -- "Resources_6_StorageMode",
      -- "Resources_6_StartFull",
      -- "Resources_6_FetchInRange",
      -- "Resources_6_CanBeShared",
      -- "Resources_6_CycleThoughResourceSources",
      -- "Resources_6_GatheringMode",
      -- "Resources_6_DistributionMode",
      -- "Resources_6_DeliverInRange",
      -- "Resources_6_VehicleFetchsAndDelivers",
      -- "Resources_7_Name",
      -- "Resources_7_Maximum",
      -- "Resources_7_StorageMode",
      -- "Resources_7_StartFull",
      -- "Resources_7_FetchInRange",
      -- "Resources_7_CanBeShared",
      -- "Resources_7_CycleThoughResourceSources",
      -- "Resources_7_GatheringMode",
      -- "Resources_7_DistributionMode",
      -- "Resources_7_DeliverInRange",
      -- "Resources_7_VehicleFetchsAndDelivers",
      -- "Resources_8_Name",
      -- "Resources_8_Maximum",
      -- "Resources_8_StorageMode",
      -- "Resources_8_StartFull",
      -- "Resources_8_FetchInRange",
      -- "Resources_8_CanBeShared",
      -- "Resources_8_CycleThoughResourceSources",
      -- "Resources_8_GatheringMode",
      -- "Resources_8_DistributionMode",
      -- "Resources_8_DeliverInRange",
      -- "Resources_8_VehicleFetchsAndDelivers",
      -- "Resources_9_Name",
      -- "Resources_9_Maximum",
      -- "Resources_9_StorageMode",
      -- "Resources_9_StartFull",
      -- "Resources_9_FetchInRange",
      -- "Resources_9_CanBeShared",
      -- "Resources_9_CycleThoughResourceSources",
      -- "Resources_9_GatheringMode",
      -- "Resources_9_DistributionMode",
      -- "Resources_9_DeliverInRange",
      -- "Resources_9_VehicleFetchsAndDelivers",
      -- "ResourceGroups",
      -- "ResourceGroups_1_Type",
      -- "ResourceGroups_1_Maximum",
      -- "ResourceGroups_1_GatheringMode",
      -- "ResourceGroups_1_DistributionMode",
      -- "ResourceGroups_1_StartFullResource",
      -- "ResourceGroups_2_Type",
      -- "ResourceGroups_2_Maximum",
      -- "ResourceGroups_2_GatheringMode",
      -- "ResourceGroups_2_DistributionMode",
      -- "ResourceGroups_2_StartFullResource",
      -- "DefinedResourceLists",
      -- "DefinedResourceLists_2_Name",
      -- "DefinedResourceLists_2_Maximum",
      -- "DefinedResourceLists_2_StorageMode",
      -- "DefinedResourceLists_2_StartFull",
      -- "DefinedResourceLists_2_FetchInRange",
      -- "DefinedResourceLists_2_CanBeShared",
      -- "DefinedResourceLists_2_CycleThoughResourceSources",
      -- "DefinedResourceLists_2_GatheringMode",
      -- "DefinedResourceLists_2_DistributionMode",
      -- "DefinedResourceLists_2_DeliverInRange",
      -- "DefinedResourceLists_2_VehicleFetchsAndDelivers",
      -- "DefaultFetchMode",
      -- "DefaultDeliveryMode",
      "FetchTime",
      "DeliveryTime",
      "TotalStorageMaximum",
      -- "MaxSeedSlots",
      "BuildingTasks",
      -- "PlayerSelectableTasks_1",
      -- "PlayerSelectableTasks_2",
      -- "PlayerSelectableTasks_3",
      -- "SourceDefinition",
      -- "Hotkey",
      -- "ConstructionMustReplace",
      -- "AutoUnlock",
      -- "TechTreeListPreviousExit",
      -- "TechTreeListEntry",
      -- "TechTreeLineVerticalOffset",
      "PowerRange",
      "PeepEnergyAdded",
      "PeepEnergyCost",
    },
  },
  TASKS = {
    TABLE = "BuildingTasks",
    WHERE_GUID = "guid",
    -- FIELDS that fit the pattern but are not declared in the DB table definition: 
    --   BuildingTasks_4_Outputs_2_*
    --   BuildingTasks_4_Inputs_2_*
    --   BuildingTasks_5_Outputs_2_*
    --   BuildingTasks_5_Inputs_2_*
    -- Commented out fields are not used in BuildingTask
    FIELDS = {
      "BuildingTasks_1_Name",
      -- "BuildingTasks_1_InitialState",
      "BuildingTasks_1_Time",
      -- "BuildingTasks_1_MinimumTimeDelta",
      "BuildingTasks_1_Outputs_1_Type",
      "BuildingTasks_1_Outputs_1_Resource",
      "BuildingTasks_1_Outputs_1_Value",
      "BuildingTasks_1_Outputs_2_Type",
      "BuildingTasks_1_Outputs_2_Resource",
      "BuildingTasks_1_Outputs_2_Value",
      "BuildingTasks_1_Inputs_1_Type",
      "BuildingTasks_1_Inputs_1_Resource",
      "BuildingTasks_1_Inputs_1_Value",
      "BuildingTasks_1_Inputs_2_Type",
      "BuildingTasks_1_Inputs_2_Resource",
      "BuildingTasks_1_Inputs_2_Value",
      "BuildingTasks_1_Inputs_3_Type",
      "BuildingTasks_1_Inputs_3_Resource",
      "BuildingTasks_1_Inputs_3_Value",
      "BuildingTasks_1_Inputs_4_Type",
      "BuildingTasks_1_Inputs_4_Resource",
      "BuildingTasks_1_Inputs_4_Value",
      "BuildingTasks_1_PollutionSlowdownThreshold",
      "BuildingTasks_2_Name",
      -- "BuildingTasks_2_InitialState",
      "BuildingTasks_2_Time",
      -- "BuildingTasks_2_MinimumTimeDelta",
      "BuildingTasks_2_Outputs_1_Type",
      "BuildingTasks_2_Outputs_1_Resource",
      "BuildingTasks_2_Outputs_1_Value",
      "BuildingTasks_2_Outputs_2_Type",
      "BuildingTasks_2_Outputs_2_Resource",
      "BuildingTasks_2_Outputs_2_Value",
      "BuildingTasks_2_PollutionSlowdownThreshold",
      "BuildingTasks_2_Inputs_1_Type",
      "BuildingTasks_2_Inputs_1_Resource",
      "BuildingTasks_2_Inputs_1_Value",
      "BuildingTasks_2_Inputs_2_Type",
      "BuildingTasks_2_Inputs_2_Resource",
      "BuildingTasks_2_Inputs_2_Value",
      "BuildingTasks_2_Inputs_3_Type",
      "BuildingTasks_2_Inputs_3_Resource",
      "BuildingTasks_2_Inputs_3_Value",
      "BuildingTasks_3_Name",
      -- "BuildingTasks_3_InitialState",
      "BuildingTasks_3_Time",
      -- "BuildingTasks_3_MinimumTimeDelta",
      "BuildingTasks_3_Outputs_1_Type",
      "BuildingTasks_3_Outputs_1_Resource",
      "BuildingTasks_3_Outputs_1_Value",
      "BuildingTasks_3_Outputs_2_Type",
      "BuildingTasks_3_Outputs_2_Resource",
      "BuildingTasks_3_Outputs_2_Value",
      "BuildingTasks_3_PollutionSlowdownThreshold",
      "BuildingTasks_3_Inputs_1_Type",
      "BuildingTasks_3_Inputs_1_Resource",
      "BuildingTasks_3_Inputs_1_Value",
      "BuildingTasks_3_Inputs_2_Type",
      "BuildingTasks_3_Inputs_2_Resource",
      "BuildingTasks_3_Inputs_2_Value",
      "BuildingTasks_4_Name",
      -- "BuildingTasks_4_InitialState",
      "BuildingTasks_4_Time",
      -- "BuildingTasks_4_MinimumTimeDelta",
      "BuildingTasks_4_Outputs_1_Type",
      "BuildingTasks_4_Outputs_1_Resource",
      "BuildingTasks_4_Outputs_1_Value",
      "BuildingTasks_4_PollutionSlowdownThreshold",
      "BuildingTasks_4_Inputs_1_Type",
      "BuildingTasks_4_Inputs_1_Resource",
      "BuildingTasks_4_Inputs_1_Value",
      "BuildingTasks_5_Name",
      -- "BuildingTasks_5_InitialState",
      "BuildingTasks_5_Time",
      -- "BuildingTasks_5_MinimumTimeDelta",
      "BuildingTasks_5_Outputs_1_Type",
      "BuildingTasks_5_Outputs_1_Resource",
      "BuildingTasks_5_Outputs_1_Value",
      "BuildingTasks_5_PollutionSlowdownThreshold",
      "BuildingTasks_5_Inputs_1_Type",
      "BuildingTasks_5_Inputs_1_Resource",
      "BuildingTasks_5_Inputs_1_Value",
      "BuildingTasks_6_Name",
      -- "BuildingTasks_6_InitialState",
      "BuildingTasks_6_Time",
      -- "BuildingTasks_6_MinimumTimeDelta",
      "BuildingTasks_6_Outputs_1_Type",
      "BuildingTasks_6_Outputs_1_Resource",
      "BuildingTasks_6_Outputs_1_Value",
      "BuildingTasks_6_PollutionSlowdownThreshold",
      "BuildingTasks_6_Inputs_1_Type",
      "BuildingTasks_6_Inputs_1_Resource",
      "BuildingTasks_6_Inputs_1_Value",
      "BuildingTasks_6_Inputs_2_Type",
      "BuildingTasks_6_Inputs_2_Resource",
      "BuildingTasks_6_Inputs_2_Value",
      "BuildingTasks_7_Name",
      -- "BuildingTasks_7_InitialState",
      "BuildingTasks_7_Time",
      -- "BuildingTasks_7_MinimumTimeDelta",
      "BuildingTasks_7_Outputs_1_Type",
      "BuildingTasks_7_Outputs_1_Resource",
      "BuildingTasks_7_Outputs_1_Value",
      "BuildingTasks_7_PollutionSlowdownThreshold",
      "BuildingTasks_7_Inputs_1_Type",
      "BuildingTasks_7_Inputs_1_Resource",
      "BuildingTasks_7_Inputs_1_Value",
      "BuildingTasks_8_Name",
      -- "BuildingTasks_8_InitialState",
      "BuildingTasks_8_Time",
      -- "BuildingTasks_8_MinimumTimeDelta",
      "BuildingTasks_8_Outputs_1_Type",
      "BuildingTasks_8_Outputs_1_Resource",
      "BuildingTasks_8_Outputs_1_Value",
      "BuildingTasks_8_PollutionSlowdownThreshold",
      "BuildingTasks_8_Inputs_1_Type",
      "BuildingTasks_8_Inputs_1_Resource",
      "BuildingTasks_8_Inputs_1_Value",
      "BuildingTasks_9_Name",
      -- "BuildingTasks_9_InitialState",
      "BuildingTasks_9_Time",
      -- "BuildingTasks_9_MinimumTimeDelta",
      "BuildingTasks_9_Outputs_1_Type",
      "BuildingTasks_9_Outputs_1_Resource",
      "BuildingTasks_9_Outputs_1_Value",
      "BuildingTasks_9_PollutionSlowdownThreshold",
      "BuildingTasks_9_Inputs_1_Type",
      "BuildingTasks_9_Inputs_1_Resource",
      "BuildingTasks_9_Inputs_1_Value",
    }
  }
}

--#endregion



--#region Cargo queries

--- Queries cargo for all building records.
---@return CargoBuildingRecord[]
local function query_all_buildings()
  local cargo = mw.ext.cargo
  if not cargo then return {} end
  local result = cargo.query(
    QUERIES.BUILDINGS.TABLE,
    table.concat(QUERIES.BUILDINGS.FIELDS_FULL, ","), 
    {
      limit = 150,
      orderBy = QUERIES.BUILDINGS.ORDER_BY,
    })
  if not result or #result == 0 then return {} end
  return result
end

--- Queries cargo for the building record with the given name.
---@param building_name string the name of the building to fetch
---@return CargoBuildingRecord|nil
local function query_building(building_name)
  local cargo = mw.ext.cargo
  if not cargo then return nil end
  local result = cargo.query(
    QUERIES.BUILDINGS.TABLE,
    table.concat(QUERIES.BUILDINGS.FIELDS_FULL, ","), 
    {
      where = QUERIES.BUILDINGS.WHERE_NAME .. '="' .. building_name .. '"',
    })
  if not result or #result == 0 then return nil end
  return result[1]
end

--- Queries cargo for the building tasks record with the given guid.
---@param building_tasks_guid string the guid of the building tasks to fetch
---@return CargoBuildingTasksRecord|nil
local function query_building_tasks(building_tasks_guid)
  local cargo = mw.ext.cargo
  if not cargo then return nil end
  local result = cargo.query(
    QUERIES.TASKS.TABLE,
    table.concat(QUERIES.TASKS.FIELDS, ","), 
    {
      where = QUERIES.TASKS.WHERE_GUID .. '="' .. building_tasks_guid .. '"',
    })
  if not result or #result == 0 then return nil end
  return result[1]
end

--- Queries cargo for the building name only with the given id.
---@param building_id string the id of the building to fetch
---@return CargoBuildingRecord|nil
local function query_building_name_only(building_id)
  local cargo = mw.ext.cargo
  if not cargo then return nil end
  local result = cargo.query(
    QUERIES.BUILDINGS.TABLE,
    table.concat(QUERIES.BUILDINGS.FIELDS_NAME_ONLY, ","), 
    {
      where = QUERIES.BUILDINGS.WHERE_ID .. '="' .. building_id .. '"',
    })
  if not result or #result == 0 then return nil end
  return result[1]
end

--#endregion



--#region Local helper functions

--- Restructures the construction resources of a building record from the database into a more usable format.
---@param record CargoBuildingRecord
---@return ConstructionPair[]
local function restructure_construction_resources(record)
  local construction_resources = {}
  for i = 1, p.MAX_CONSTRUCTION_PAIRS do
    local construction_resource = record[string.format("ConstructionResources_%d_Name", i)]
    local construction_amount = record[string.format("ConstructionResources_%d_Amount", i)]
    if construction_resource and construction_amount then
      table.insert(construction_resources, {
        name = construction_resource,
        amount = tonumber(construction_amount),
      })
    end
  end
  return construction_resources
end

--- Restructures the unlock values of a building record from the database into a more usable format.
---@param record CargoBuildingRecord
---@return string[]
local function restructure_unlock_values(record)
  local unlock_values = {}
  for i = 1, p.MAX_UNLOCK_VALUES do
    local unlock_value = record[string.format("UnlockValues_%d", i)]
    if unlock_value then
      table.insert(unlock_values, unlock_value)
    end
  end
  return unlock_values
end

--- Restructures the adjacency bonuses of a building record from the database into a more usable format.
---@param record CargoBuildingRecord
---@return AdjacencyBonus[]
local function restructure_adjacency_bonuses(record)
  local adjacency_bonuses = {}
  for i = 1, p.MAX_ADJACENCY_BONUSES do
    local group_name = record[string.format("AdjacencyBonuses_%d_GroupName", i)]
    local evaluator_type = record[string.format("AdjacencyBonuses_%d_Evaluator", i)]
    local evaluator_threshold = record[string.format("AdjacencyBonuses_%d_EvaluatorThreshold", i)]
    local evaluator_value = record[string.format("AdjacencyBonuses_%d_EvaluatorValue", i)]
    local action = record[string.format("AdjacencyBonuses_%d_Action", i)]
    local action_value = record[string.format("AdjacencyBonuses_%d_ActionValue", i)]
    if group_name and evaluator_type and evaluator_threshold and evaluator_value and action and action_value then
      table.insert(adjacency_bonuses, {
        bonus_name = group_name,
        evaluator_type = evaluator_type,
        evaluator_threshold = tonumber(evaluator_threshold),
        evaluator_value = evaluator_value,
        action = action,
        action_value = tonumber(action_value),
      })
    end
  end
  return adjacency_bonuses
end

--- Restructures the inputs or ouputs of a building task
---@param record CargoBuildingTasksRecord the building tasks record retrieved for the building
---@param task_num number which task to restructure
---@param which_io "Inputs"|"Outputs" the type of tasks to restructure
---@return BuildingTaskIO[]
local function restructure_task_io(record, task_num, which_io)
  local task_io = {}
  local max = ((which_io == "Inputs") and p.MAX_BUILDING_TASK_INPUTS) or p.MAX_BUILDING_TASK_OUTPUTS
  local task_type_prefix = "BuildingTasks_" .. task_num .. "_" .. which_io .. "_%d_"
  for i = 1, max do
    local put_type = record[string.format(task_type_prefix .. "Type", i)]
    local put_resource = record[string.format(task_type_prefix .. "Resource", i)]
    local put_value = record[string.format(task_type_prefix .. "Value", i)]
    if put_type or put_resource or put_value then
      table.insert(task_io, {
        type = put_type,
        resource = put_resource,
        value = put_value,
      })
    end
  end
  return task_io
end

--- Restructures the tasks of a building record from the database into a more usable format.
---@param record CargoBuildingRecord
---@return BuildingTask[]
local function restructure_tasks(record)
  local tasks_guid = record.BuildingTasks
  if not tasks_guid then return {} end
  local raw_tasks = query_building_tasks(tasks_guid)
  if not raw_tasks then return {}
   end
  local tasks = {}
  for i = 1, p.MAX_BUILDING_TASKS do
    local task_name = raw_tasks[string.format("BuildingTasks_%d_Name", i)]
    local time = tonumber(raw_tasks[string.format("BuildingTasks_%d_Time", i)])
    local pollution_slowdown = tonumber(raw_tasks[string.format("BuildingTasks_%d_PollutionSlowdownThreshold", i)])
    local outputs = restructure_task_io(raw_tasks, i, "Outputs")
    local inputs = restructure_task_io(raw_tasks, i, "Inputs")
    if task_name then
      table.insert(tasks, {
        task_name = task_name,
        time = time,
        outputs = outputs,
        inputs = inputs,
        pollution_slowdown_threshold = pollution_slowdown,
      })
    end
  end
  return tasks
end

--- Restructures a flat building record from the database into a more usable format.
---@param record CargoBuildingRecord
---@return Building|nil
local function restructure_building_record(record)
  local portrait_icon_filename = nil
  if not p.PORTRAITS_MISSING_NAMES[record.Name] then
    portrait_icon_filename = p.BUILDING_PORTRAIT_PREFIX .. record.Name
  end
  local building = {
    name = record.page_name,
    category = record.Category,
    display_name = record.DisplayNameTerm_en or record.page_name,
    display_name_plural = record.DisplayNamePluralTerm_en,
    description = record.DescriptionTerm_en,
    icon = record.IconAddress,
    portrait_icon = portrait_icon_filename,
    construction_resources = {},
    construction_time = tonumber(record.ConstructionTime),
    unlock_mode = record.UnlockMode,
    unlock_values = {},
    is_in_demo = record.LockedInDemo,
    footprint_icon = record.FootprintIconAddress,
    tech_tree_previous = record.TechTreePrevious,
    adjacency_bonuses = {},
    max_peeps = tonumber(record.MaxPeeps),
    peep_exhaustion_removed = tonumber(record.PeepExhaustionRemoved),
    peep_age_added = tonumber(record.PeepAgeAdded),
    peep_happiness_added = tonumber(record.PeepHappinessAdded),
    peep_happiness_cost = tonumber(record.PeepHappinessCost),
    peep_energy_added = tonumber(record.PeepEnergyAdded),
    peep_energy_cost = tonumber(record.PeepEnergyCost),
    pollution_output_mode = record.PollutionOutputMode,
    oxygen_source_range = tonumber(record.SourceOfOxygenRange),
    fetch_mode = record.DefaultFetchMode,
    delivery_mode = record.DefaultDeliveryMode,
    fetch_time = tonumber(record.FetchTime),
    delivery_time = tonumber(record.DeliveryTime),
    storage_max = tonumber(record.TotalStorageMaximum),
    power_range = tonumber(record.PowerRange),
    tasks = {},
  }
  building.construction_resources = restructure_construction_resources(record)
  building.unlock_values = restructure_unlock_values(record)
  building.adjacency_bonuses = restructure_adjacency_bonuses(record)
  building.tasks = restructure_tasks(record)
  return building
end

--#endregion



--#region Public interface

---@class BuildingDataModule
---@field MAX_CONSTRUCTION_PAIRS number the maximum number of construction pairs
---@field MAX_UNLOCK_VALUES number the maximum number of unlock values
---@field MAX_ADJACENCY_BONUSES number the maximum number of adjacency bonuses
---@field MAX_BUILDING_TASKS number the maximum number of building tasks
---@field MAX_BUILDING_TASK_OUTPUTS number the maximum number of building task outputs
---@field MAX_BUILDING_TASK_INPUTS number the maximum number of building task inputs
---@field get_all_buildings fun(): Building[] gets all buildings
---@field get_building fun(building_name: string): Building|nil looks up a building by name

p.MAX_CONSTRUCTION_PAIRS = 6
p.MAX_UNLOCK_VALUES = 4
p.MAX_ADJACENCY_BONUSES = 4
p.MAX_BUILDING_TASKS = 9
p.MAX_BUILDING_TASK_OUTPUTS = 2
p.MAX_BUILDING_TASK_INPUTS = 4
p.BUILDING_PORTRAIT_PREFIX = "BuildingPortrait_"
p.PORTRAITS_MISSING_NAMES = {
  ["CompostTool"] = true,
  ["CompostingSite"] = true,
  ["Forest_WorldTwo"] = true,
  ["HomeSpaceshipLanded"] = true,
  ["Mill"] = true,
  ["WhaleTranslatorRuin"] = true,
  ["OxygenGenerator"] = true,
  ["Rock_WorldThree"] = true,
  ["Ruin_WorldTwo"] = true,
  ["SettlementSpaceshipLanded"] = true,
  ["SettlementSpaceshipLauncher"] = true,
  ["SteelBridge"] = true,
  ["StorageExtension"] = true,
}
p.SKIPPED_BUILDINGS_NAMES = {
  ["ConstructionConsumption"] = true,
  ["DemolitionControl"] = true,
  ["Drone_Repair"] = true,
  ["ForestPlantingTool"] = true,
  ["CreateMineableArea"] = true,
  ["MiningTile"] = true,
  ["MoveBuildingControl"] = true,
  ["PauseControl"] = true,
  ["PeepConsumption"] = true,
  ["PriorityControl"] = true,
  ["LandFillingSite"] = true,
  ["RampConstruction"] = true,
  ["RepairControl"] = true,
  ["ResourceCache"] = true,
  ["RoadConstruction"] = true,
  ["SettlementSpaceshipReload"] = true,
  ["ThornyStems"] = true,
}

---@class ConstructionPair
---@field name string the name of the construction resource
---@field amount number the amount of the construction resource

---@class AdjacencyBonus
---@field bonus_name string|nil the codename for the bonus group
---@field evaluator_type string|nil the type of evaluator that triggers the bonus
---@field evaluator_threshold number|nil the threshold value for the evaluator
---@field evaluator_value string|nil the codename for what condition evaluated for the trigger
---@field action string|nil the action to take when the bonus is triggered
---@field action_value number|nil the value to apply for the action

---@class BuildingTaskIO
---@field type string|nil the type of input/output
---@field resource string|nil the codename for the resource
---@field value string|nil the value of the input/output

---@class BuildingTask
---@field task_name string|nil the name of the task
---@field time number|nil the time it takes to complete the task
---@field outputs BuildingTaskIO[]|nil the outputs of the task
---@field inputs BuildingTaskIO[]|nil the inputs of the task
---@field pollution_slowdown_threshold number|nil the threshold at which pollution slows down the task

---@class Building
---@field name string|nil the in-game codename for the building
---@field category string|nil the category of the building
---@field display_name string|nil the display name of the building
---@field display_name_plural string|nil the plural display name of the building
---@field description string|nil the description of the building
---@field icon string|nil the flat icon asset name for this building
---@field portrait_icon string|nil the pre-rendered portrait icon asset name for this building
---@field construction_resources ConstructionPair[]|nil the construction resources of the building
---@field construction_time number|nil the time it takes to construct the building
---@field unlock_mode string|nil the requirement for unlocking the building
---@field unlock_values string[]|nil the values required for unlocking the building
---@field is_in_demo boolean whether the building is locked in the demo
---@field footprint_icon string|nil the icon filename for the building's footprint
---@field tech_tree_previous string|nil the previous building in the tech tree
---@field adjacency_bonuses AdjacencyBonus[]|nil the adjacency bonuses of the building
---@field max_peeps number|nil the maximum number of peeps that can be assigned to the building
---@field peep_exhaustion_removed number|nil the amount of exhaustion removed per peep per second
---@field peep_age_added number|nil the amount of age added per peep per second
---@field peep_happiness_added number|nil the amount of happiness added per peep per second
---@field peep_happiness_cost number|nil the cost of happiness per peep per second
---@field peep_energy_added number|nil the amount of energy added per peep per second
---@field peep_energy_cost number|nil the cost of energy per peep per second
---@field pollution_output_mode string|nil the level of pollution output from the building
---@field oxygen_source_range number|nil the range of the oxygen source for the building
---@field fetch_mode string|nil the mode for fetching resources from the building
---@field delivery_mode string|nil the mode for delivering resources to the building
---@field fetch_time number|nil the time it takes to fetch resources from the building
---@field delivery_time number|nil the time it takes to deliver resources to the building
---@field storage_max number|nil the maximum amount of storage for the building
---@field power_range number|nil the range of the power source for the building
---@field tasks BuildingTask[]|nil the tasks the building can work on

--- Fetches a building record from the database.
---@param building_name string the in-game name of the building to fetch
---@return Building|nil
function p.get_building(building_name)
  local raw_record = query_building(building_name)
  if not raw_record then return nil end
  local record = restructure_building_record(raw_record)
  return record
end

--- Fetches a building's page name by its id.
---@param id string the id of the building to fetch
---@return string|nil the page name of the building
function p.get_building_by_id(id)
  local raw_record = query_building_name_only(id)
  if not raw_record then return nil end
  return raw_record.page_name or nil
end

--- Fetches all building records from the database.
---@return Building[]
function p.get_all_buildings()
  local raw_records = query_all_buildings()
  if not raw_records then return {} end
  local new_records = {}
  for _, raw_record in ipairs(raw_records) do
    if not p.SKIPPED_BUILDINGS_NAMES[raw_record.Name] then
      local record = restructure_building_record(raw_record)
      table.insert(new_records, record)
    end
  end
  return new_records
end

---@cast p BuildingDataModule
return p

--#endregion