Documentation for this module may be created at Module:Data/CivBE/doc

local utils = require("Module:TemplateUtils")
local baseUtils = require("Module:Data")
local civBEUtils = require("Module:Data/CivBE/Utils")

local p = {}

local civFeatureRow = [[|-
|%s
|%s
|
%s
]]

local sponsorRow= [[|-
|%s
|%s
|%s
|
%s
]]

local virtueRow = [[|-
|%s
|%s
|%s
|
%s
]]

local function GetAffinity(affinityType)
	local affinities = {}
	affinities["AFFINITY_TYPE_HARMONY"] = "Harmony"
	affinities["AFFINITY_TYPE_PURITY"] = "Purity"
	affinities["AFFINITY_TYPE_SUPREMACY"] = "Supremacy"
	return affinities[affinityType]
end

local function GetFeatureRow(dataType, frame)
	local displayname = frame.args[1]
	local name = string.gsub(displayname , " %(.*","")
	local data = mw.loadData("Module:Data/CivBE/CivFeatures")
	local item = data[dataType][name]

	return frame:preprocess(string.format(civFeatureRow,
	"[[File:"..displayname.." (CivBE).png|55px|link="..displayname.." (CivBE)]]",
	name .. (item.alias and " ("..item.alias..")" or ""), --"[["..displayname.." (CivBE)|"..name.."]]"
	item.specialty or "None"))
end

function p.GetSponsorRow(frame)
	local displayname = frame.args[1]
	local name = string.gsub(displayname , " %(.*","")
	local data = mw.loadData("Module:Data/CivBE/CivFeatures")
	local item = data["sponsor"][name]

	return frame:preprocess(string.format(civFeatureRow,
	"[[File:"..displayname.." (CivBE).png|55px|link="..displayname.." (CivBE)]]",
	"[["..displayname.." (CivBE)|"..name.."]]" .. (item.alias and " ("..item.alias..")" or ""), --"[["..displayname.." (CivBE)|"..name.."]]"
	item.specialty or "None"))
end

function p.GetColonistRow(frame)
	return GetFeatureRow("colonists", frame)
end

function p.GetSpacecraftRow(frame)
	return GetFeatureRow("spacecraft", frame)
end

function p.GetCargoRow(frame)
	return GetFeatureRow("cargo", frame)
end

function p.GetPlanetRow(frame)
	return GetFeatureRow("planet", frame)
end

function p.GetVirtueTier(name)
	return mw.loadData("Module:Data/CivBE/Virtues")[name].tier;
end

function p.GetVirtueDescription(name)
	return mw.loadData("Module:Data/CivBE/Virtues")[name].description;
end

function p.GetVirtueTree(name)
	return mw.loadData("Module:Data/CivBE/Virtues")[name].tree;
end

function p.GetVirtueRow(frame, articlename)
	local displayname = articlename or frame.args[1]
	local name = string.gsub(displayname , " %(.*","")
	local data = mw.loadData("Module:Data/CivBE/Virtues")
	local item = data[name]

	return utils.PreProcess(frame,string.format(virtueRow,
    "[[File:"..displayname.." (CivBE).png|55px]]",
	"<span class=\""..item.tree.."\">"..item.tier .. "</span><span class='hidden'>" .. item.tree .. "</span>",
	"<span class=\""..item.tree.."\">"..name.."</span>",
	item.description))
end

local sponsorpage = [=[<div class="container-with-margins" style="float:right; width:270px; clear:right;">
{| class="civbetable" style="margin:0; width:270px"
!colspan="2" align="center"|<big><big>'''%s'''</big></big>
|-
|colspan="2" align="center"|%s
|-
|colspan="2" align="center"|%s
|-
! align="left"| Leader
|%s
|-
! align="left"| Capital
|%s
|-
! align="left"| Specialty
|
%s
|}</div>
{{#if:{{NAMESPACE}} | |[[Category:Sponsors (CivBE)]]}}]=]

function p.GetSponsorPage(frame, articlename)
	local PAGENAME = articlename or mw.title.getCurrentTitle().text
	local name = string.gsub(PAGENAME, " %(.*","")
	local data = mw.loadData("Module:Data/CivBE/CivFeatures")
	local sponsor = data["sponsor"][name]
	local civname = string.gsub(PAGENAME, " %(.*","")
	local civData = mw.loadData("Module:Data/CivBE/Base/Civilizations")
	local cp = civBEUtils.GetCivilization(civname).CivilopediaTag
 
	return utils.PreProcess(frame,string.format(sponsorpage,
	name .. (sponsor.alias and " ("..sponsor.alias..")" or ""),
	"[[File:"..PAGENAME..".png|60px]]",
	cp.DESC,
	sponsor.leader,
	sponsor.capital,
	sponsor.specialty))
end

local sponsorCP = [=[<div class="container-with-margins" >
== Civilopedia entry ==
===%s===
%s
===%s===
%s
===%s===
%s
%s
</div>
]=]

function p.GetCPPage(frame, articlename)
	local PAGENAME = articlename or mw.title.getCurrentTitle().text
	local civname = string.gsub(PAGENAME, " %(.*","")
	local cp = civBEUtils.GetCivilization(civname).CivilopediaTag
	
	if cp.HEADING_5 then
	    lastline = "==="..cp.HEADING_4.."=== \n"..cp.TEXT_4.."\n".."==="..cp.HEADING_5.."=== \n"..cp.TEXT_5
    else
        lastline = "==="..cp.HEADING_4.."=== \n"..cp.TEXT_4
    end    
	
	return utils.PreProcess(frame,string.format(sponsorCP,
	cp.HEADING_1,
	cp.TEXT_1,
	cp.HEADING_2,
	cp.TEXT_2,
	cp.HEADING_3,
	cp.TEXT_3,
	lastline))
end

local leaderCP = [=[<div class="container-with-margins" >
== Civilopedia entry ==
===%s===
%s
===%s===
%s
%s
==Loading screen quotes==
%s

%s

%s

%s

%s
</div>
]=]

function p.GetLeaderCPPage(frame, articlename)
	local PAGENAME = articlename or mw.title.getCurrentTitle().text
	local leadername = string.gsub(PAGENAME, " %(.*","")
	local leaderData = baseUtils.SelectFromWhere(mw.loadData("Module:Data/CivBE/Base/Leaders"), "Description", leadername)
	local cp = leaderData.CivilopediaTag
	local civname = string.gsub(leaderData.Type, "LEADER", "CIVILIZATION")
	if civname == "CIVILIZATION_INDIA" then
	    civname = "CIVILIZATION_KAVITHAN"
	end
	local civData = baseUtils.SelectFromWhere(mw.loadData("Module:Data/CivBE/Base/Civilizations"), "Type", civname)
	
	if cp.HEADING_4 then
	    lastline = "==="..cp.HEADING_3.."=== \n"..cp.TEXT_3.."\n".."==="..cp.HEADING_4.."=== \n"..cp.TEXT_4
    else
        lastline = "==="..cp.HEADING_3.."=== \n"..cp.TEXT_3
    end    
	
	return utils.PreProcess(frame,string.format(leaderCP,
	cp.HEADING_1,
	cp.TEXT_1,
	cp.HEADING_2,
	cp.TEXT_2,
	lastline,
	civData.IntroductionQuote[1],
	civData.IntroductionQuote[2],
	civData.IntroductionQuote[3],
	civData.IntroductionQuote[4],
	civData.IntroductionQuote[5]))
end

local buildingCP = [=[<div>
%s
==History==
%s
</div>]=]

function p.GetBuildingCPPage(frame, articlename)
	local PAGENAME = articlename or mw.title.getCurrentTitle().text
	local buildingname = string.gsub(PAGENAME, " %(.*","")
	local buildingData = baseUtils.SelectFromWhere(mw.loadData("Module:Data/CivBE/RT/Buildings"), "Description", buildingname)
	local cp = string.gsub(buildingData.Civilopedia, "\\r\\n", "<br>")
	
	if buildingData.Quote then
	    firstline = "==Quote== \n"..string.gsub(buildingData.Quote, "\\r\\n", "<br>").."\n"
    else
        firstline = ""
    end    
	
	return utils.PreProcess(frame,string.format(buildingCP,
	firstline,
	cp))
end

local projectCP = [=[<div class="container-with-margins" >
==History==
%s

</div>
]=]

function p.GetProjectCPPage(frame, articlename)
	local PAGENAME = articlename or mw.title.getCurrentTitle().text
	local projectName = string.gsub(PAGENAME, " %(.*","")
	local projectData = baseUtils.SelectFromWhere(mw.loadData("Module:Data/CivBE/Base/Projects"), "Description", projectName)
	local cp = string.gsub(projectData.Civilopedia, "\\r\\n", "<br>")
	
	return utils.PreProcess(frame,string.format(projectCP,
	cp))
end

local technologypage = [=[<div class="container-with-margins" style="float:right; width:270px; clear:right;">
{| class="civbetable" style="margin:0; width:270px"
!colspan="2" align="center"|<big><big>'''%s'''</big></big>
|-
|colspan="2" align="center"|%s<br/>
%s technology of Tier %s
|-
! align="left" | Science
|%s {{ScienceIconBE}}
|-
! align="left" | Requires
|%s
|-
! align="left" | Leads to
|%s
|-
! align="left" | Affinity
|
%s
|-
! align="left" | Buildings enabled
|%s
|-
! align="left" | Improvements enabled
|%s
|-
! align="left" | Satellites enabled
|%s
|-
! align="left" | Units enabled
|%s
|-
! align="left"| Notes
|
%s
|}</div>
:%s
==History==
%s
{{#if:{{NAMESPACE}} | |[[Category:Technologies (CivBE)]]}}]=]

local function Trim(s)
    local result = s:gsub("^%s*(.-)%s*$", "%1")
    return result
end

local function GetTechByName(techName)
	return baseUtils.SelectFromWhere(mw.loadData("Module:Data/CivBE/Base/Technologies"), "Description", techName)
end

local function GetNormalizedTechBaseQuote(techName)
    local baseData = GetTechByName(techName)
    local baseQuote = baseData and baseData.Quote or "('"..techName.."' not found)"
    return baseQuote:gsub("\\r\\n", ""):gsub("\"", "")
end

function p.GetTechQuote(frame, name)
    local techName = name or frame.args[1];
	local quote = GetNormalizedTechBaseQuote(techName):gsub("(.*)-([^-]*)$", "%1")
	return Trim(quote)
end

function p.GetTechQuoteAuthor(frame, name)
    local techName = name or frame.args[1];
	local quote = GetNormalizedTechBaseQuote(techName):gsub("(.*)-([^-]*)$", "%2")
	return Trim(quote)
end

local function GetTechByType(techType)
	return baseUtils.SelectFromWhere(mw.loadData("Module:Data/CivBE/Base/Technologies"), "Type", techType)
end

local function GetTechName(techType)
	return baseUtils.SelectFromWhere(mw.loadData("Module:Data/CivBE/Base/Technologies"), "Type", techType).Description
end 
 
local function GetTechType(techName)
	return baseUtils.SelectFromWhere(mw.loadData("Module:Data/CivBE/Base/Technologies"), "Description", techName).Type
end

function p.GetTechLeadsTo(techName)
	local connections = mw.loadData("Module:Data/CivBE/Base/Technology_Values")["Connections"][GetTechType(techName)]
	local baseData = GetTechByName(techName)
	if connections == nil or baseData.LeafTech then
		return {}
	end
	local leadsto = {}
	for k,v in pairs(connections) do
		table.insert(leadsto, GetTechName(v["SecondTech"]))
	end
	return leadsto
end 

function p.GetBuildingsEnabledByTechnology(techName)
	local techType = GetTechType(techName)
	local buildings = baseUtils.SelectAllFromWhere(mw.loadData("Module:Data/CivBE/Base/Buildings"), "PrereqTech", techType)		
	local buildingNamesResult = {}
	for buildingType,buildingData in pairs(buildings) do
		table.insert(buildingNamesResult,buildingData.Description)
	end
	return buildingNamesResult
end

function p.GetImprovementsEnabledByTechnology(techName)
	local techType = GetTechType(techName)
	local baseImprovementData = mw.loadData("Module:Data/CivBE/Base/Improvements")
	if baseImprovementData == nil then
	   baseImprovementData = baseUtils.SelectFromWhere(mw.loadData("Module:Data/CivBE/Extra/Improvements"), "Description", name)
	end
	local builds = baseUtils.SelectAllFromWhere(mw.loadData("Module:Data/CivBE/Base/Builds"), "PrereqTech", techType)
	local improvementTypes = {}
	for buildType,buildData in pairs(builds) do
		if buildData.ImprovementType then
			table.insert(improvementTypes,buildData.ImprovementType)
		end
	end
	local improvementNamesResult = {}
	for key,improvementType in pairs(improvementTypes) do
		table.insert(improvementNamesResult,baseImprovementData[improvementType].Description)
	end
	return improvementNamesResult
end

function p.GetTechnologyAffinities(techName)
	local techType = GetTechType(techName)
	local affinitiesResult = {}
	local affinities = mw.loadData("Module:Data/CivBE/Base/Technology_Values")
	local techAffinities = affinities.Affinities[techType]
	if techAffinities then
		for key,value in pairs(techAffinities) do
			affinitiesResult[GetAffinity(value.AffinityType)] = value.AffinityValue
		end
	end
	return affinitiesResult
end

function p.GetTechnologyPage(frame, articlename)
	local PAGENAME = articlename or mw.title.getCurrentTitle().text
	local name = string.gsub(PAGENAME, " %(.*","")
	local data = mw.loadData("Module:Data/CivBE/Technologies")
	local baseTechData = GetTechByName(name)
	local tech = data[name]
	local leadsto = (baseTechData and p.GetTechLeadsTo(name) or {})
	local buildings = p.GetBuildingsEnabledByTechnology(name)
	local improvements = p.GetImprovementsEnabledByTechnology(name)
	local affinities = p.GetTechnologyAffinities(name)
	local affinityText = "None"
	for affinity,value in pairs(affinities) do 
		affinityText = "+"..value.."{{"..affinity.."BE}}"
	end
 
	return utils.PreProcess(frame,string.format(technologypage,
	name and name or "N/A",
	"[[File:"..PAGENAME..".png|120px]]",
	baseTechData and (baseTechData.LeafTech and "Secondary" or "Primary") or "Unknown",
	tech and (tech.tier and tech.tier or "unknown") or "N/A",
	baseTechData and baseTechData.Cost or "N/A",
	tech and (tech.reqtech and utils.LinkAll(tech.reqtech, "CivBE") or "None") or "N/A",
	(#leadsto > 0) and utils.LinkAll(leadsto, "CivBE") or "None",
	affinityText,
	table.getn(buildings) > 0 and utils.LinkAll(buildings, "CivBE") or "None",
	table.getn(improvements) > 0 and utils.LinkAll(improvements, "CivBE") or "None",
	tech and (tech.satellites and utils.LinkAll(tech.satellites, "CivBE") or "None") or "N/A",
	tech and (tech.units and utils.LinkAll(tech.units, "CivBE") or "None") or "N/A",
	baseTechData.Help and baseTechData.Help or "None",
	baseTechData and baseTechData.Quote.gsub(baseTechData.Quote,"\\r\\n", " ") or "",
	baseTechData and baseTechData.Civilopedia or ""
	))
end

local buildingpage= [=[%s<div class="container-with-margins" style="float:right; width:270px; clear:right;">
{| class="civbetable" style="margin:0; width:270px"
!colspan="2" align="center"|<big><big>'''%s'''</big></big>
|-
|colspan="2" align="center"| %s<br/>%s in ''[[Beyond Earth]]''
|-
! align="left" | Cost
| %s {{ProductionIconBE}}
|-
! align="left" | Maintenance
| %s
|-
! align="left" | Requires
| %s %s %s %s
|-
! align="left" | Specialist slots
| %s
|-
! align="left" | Effect
| %s
|-
! align="left" | Notes
| %s
|}</div>
]=]

local game = "Base"

local function GetNameByType(typeType, typeValue)
	return baseUtils.SelectFromWhere(mw.loadData("Module:Data/CivBE/RT/"..typeType), "Type", typeValue).Description
end

local function GetYieldName(type)
	return GetNameByType("Yields", type)
end

local function GetResourceName(type)
	return GetNameByType("Resources", type)
end

local function GetFeatureName(type)
	return GetNameByType("Features", type)
end

local function GetTerrainName(type)
	return GetNameByType("Terrains", type)
end

local function GetSpecialistName(type)
	return GetNameByType("Specialists", type)
end

local function GetDomainName(type)
	return GetNameByType("Domains", type)
end

local function InsertPlus(value)
	return value > 0 and "+"..value or value
end

function p.GetBuildingPageRT(frame, articlename)
    game = "RT"
    return p.GetBuildingPage(frame, articlename)
end

function p.GetBuildingPage(frame, articlename)
	local PAGENAME = articlename or mw.title.getCurrentTitle().text
	local name = string.gsub(PAGENAME, " %(.*","")
	local baseData = baseUtils.SelectFromWhere(mw.loadData("Module:Data/CivBE/"..game.."/Buildings"), "Description", name)
	local values = mw.loadData("Module:Data/CivBE/"..game.."/Building_Values")
	local requiredAffinity = values.AffinityPrereqs[baseData.Type]
	local requiredTechnology = baseUtils.SelectFromWhere(mw.loadData("Module:Data/CivBE/"..game.."/Technologies"), "Type", baseData.PrereqTech)
	local requiredResourceOrs = values.LocalResourceOrs[baseData.Type]
	local requiredResources = values.ResourceQuantityRequirements[baseData.Type]
	local buildingYields = values.YieldChanges[baseData.Type]
	local resourceYields = values.ResourceYieldChanges[baseData.Type]
	local resourceHealths = values.ResourceHealthChange[baseData.Type]
	local yieldModifiers = values.YieldModifiers[baseData.Type]
	local featureYields = values.FeatureYieldChanges[baseData.Type]
	local terrainYields = values.TerrainYieldChanges[baseData.Type]
	local seaYields = values.SeaPlotYieldChanges[baseData.Type]
	local tradeYields = values.TradeYieldChanges[baseData.Type]
	local domainProductionModifiers = values.DomainProductionModifiers[baseData.Type]
	local yieldsText = ""
	local requiredAffinityText = nil
	local requiredResourcesText = nil
	local requiredResourceOrsText = nil
	local specialistsText = nil
	local class = baseUtils.SelectFromWhere(mw.loadData("Module:Data/CivBE/"..game.."/BuildingClasses"), "Type", baseData.BuildingClass)
	local globalWonder = (class.MaxGlobalInstances == 1)
	local nationalWonder = (class.MaxPlayerInstances == 1)
	if requiredAffinity then
		requiredAffinityText = requiredAffinity[1]["Level"] .." {{"..GetAffinity(requiredAffinity[1]["AffinityType"]).."BE}}<br/>"
	end
	if requiredResources then
		requiredResourcesText = ""
		for key,value in pairs(requiredResources) do
			local resourceSymbol = "{{"..GetResourceName(value.ResourceType).."BE}}"
			requiredResourcesText = requiredResourcesText..value.Cost.." "..resourceSymbol.."<br/>"
		end
	end
	if requiredResourceOrs then
		requiredResourceOrsText = ""
		for key,value in pairs(requiredResourceOrs) do
			local resourceSymbol = "{{"..GetResourceName(value.ResourceType).."BE}}"
			if string.len(requiredResourceOrsText) > 0 then
				requiredResourceOrsText = requiredResourceOrsText .. " or "
			end
			requiredResourceOrsText = requiredResourceOrsText..resourceSymbol
		end
	end
	if buildingYields then
		for key,value in pairs(buildingYields) do
			local yieldSymbol = "{{"..GetYieldName(value.YieldType).."BE}}"
			yieldsText = yieldsText..InsertPlus(value.Yield).." "..yieldSymbol.."<br/>"
		end
	end
	if resourceYields then
		for key,value in pairs(resourceYields) do
			local yieldSymbol = "{{"..GetYieldName(value.YieldType).."IconBE}} "
			yieldsText = yieldsText..InsertPlus(value.Yield).." "..yieldSymbol.." from {{"..GetResourceName(value.ResourceType).."BE}}<br/>"
		end
	end
	if featureYields then
		for key,value in pairs(featureYields) do
			local yieldSymbol = "{{"..GetYieldName(value.YieldType).."IconBE}} "
			yieldsText = yieldsText..InsertPlus(value.Yield).." "..yieldSymbol.." from {{LinkBE|"..GetFeatureName(value.FeatureType).."}}<br/>"
		end
	end
	if terrainYields then
		for key,value in pairs(terrainYields) do
			local yieldSymbol = "{{"..GetYieldName(value.YieldType).."IconBE}} "
			yieldsText = yieldsText.."+"..value.Yield.." "..yieldSymbol.." from {{LinkBE|"..GetTerrainName(value.TerrainType).."}}<br/>"
		end
	end
	if seaYields then
		for key,value in pairs(seaYields) do
			local yieldSymbol = "{{"..GetYieldName(value.YieldType).."IconBE}} "
			yieldsText = yieldsText.."+"..value.Yield.." "..yieldSymbol.." from {{LinkBE|Ocean}}<br/>"
		end
	end
	if baseData.Health then
		yieldsText = yieldsText.."+"..baseData.Health.." {{HealthBE}}<br/>"
	end
	if baseData.SpecialistType then
		local forms = string.gmatch(GetSpecialistName(baseData.SpecialistType), "%w+")
		local singular, plural = forms(), forms()
		specialistsText = baseData.SpecialistCount.." [["..singular.." (CivBE)|"..(baseData.SpecialistCount == 1 and singular or plural).."]]"
	end
	if resourceHealths then
		for key,value in pairs(resourceHealths) do
			local yieldSymbol = "{{HealthBE}} "
			yieldsText = yieldsText.."+"..value.Quantity.." "..yieldSymbol.." from {{"..GetResourceName(value.ResourceType).."BE}}<br/>"
		end
	end
	if yieldModifiers then
		for key,value in pairs(yieldModifiers) do
			local yieldSymbol = "{{"..GetYieldName(value.YieldType).."BE}}"
			yieldsText = yieldsText.."+"..value.Yield.."% "..yieldSymbol.."<br/>"
		end
	end
	if tradeYields then
		for key,value in pairs(tradeYields) do
			local yieldSymbol = "{{"..GetYieldName(value.YieldType).."BE}}"
			yieldsText = yieldsText.."+"..value.Yield.." "..yieldSymbol.." from <span title='International'>Int'l</span> and Station {{LinkBE|Trade Routes}}<br/>"
		end
	end
	if domainProductionModifiers then
		for key,value in pairs(domainProductionModifiers) do
			yieldsText = yieldsText.."+"..value.Modifier.."% {{ProductionIconBE}} for "..GetDomainName(value.DomainType).."<br/>"
		end
	end
	if baseData.ExtraCityHitPoints then
		yieldsText = yieldsText.."+"..baseData.ExtraCityHitPoints.." City Hitpoints<br/>"
	end
	if baseData.Defense then
		yieldsText = yieldsText.."+"..(baseData.Defense/100).." City Defense<br/>"
	end
	if baseData.OrbitalCoverageChange then
		yieldsText = yieldsText.."+"..baseData.OrbitalCoverageChange.." {{LinkBE|Orbital Coverage}}<br/>"
	end
	if baseData.OrbitalStrikeRangeChange then
		yieldsText = yieldsText.."+"..baseData.OrbitalStrikeRangeChange.." {{LinkBE|Orbital}} Strike Range<br/>"
	end
	if baseData.CityStrikeModifier then
		yieldsText = yieldsText.."+"..baseData.CityStrikeModifier.."% City Strike Strength<br/>"
	end
	if baseData.IntrigueCapChange then
		yieldsText = yieldsText..(baseData.IntrigueCapChange/20).." max {{LinkBE|Intrigue}} for this City<br/>"
	end
	if baseData.VirtueCostModifier then
		yieldsText = yieldsText..InsertPlus(baseData.VirtueCostModifier).."% {{LinkBE|Virtue}} cost<br/>"
	end
	if string.len(yieldsText) == 0 then
		yieldsText = "None"
	end

	return utils.PreProcess(frame,string.format(buildingpage,
	(globalWonder or nationalWonder) and "{{BackArrowBE|Wonders (CivBE)|Wonders}}" or "{{BackArrowBE|Buildings (CivBE)|Buildings}}",
	globalWonder and "[[File:"..PAGENAME..".png|32px]]"..name or name,
	globalWonder and "[[File:"..name.." wonder (CivBE).png|260px]]" or "[[File:"..PAGENAME..".png|120px]]",
	(nationalWonder and "National Wonder {{#if:{{NAMESPACE}} | |[[Category:National Wonders (CivBE)]]}}" or (globalWonder and "Wonder {{#if:{{NAMESPACE}} | |[[Category:Wonders (CivBE)]]}}" or "Building {{#if:{{NAMESPACE}} | |[[Category:Buildings (CivBE)]]}}")),
	baseData.Cost and (baseData.Cost > 0 and baseData.Cost or "None") or "N/A",
	baseData.EnergyMaintenance and baseData.EnergyMaintenance.." {{EnergyBE}}" or "None",
	requiredAffinityText and requiredAffinityText or "",
	requiredResourceOrsText and requiredResourceOrsText.." near the city<br/>" or "",
	requiredResourcesText and requiredResourcesText or "",
	requiredTechnology and "{{LinkBE|"..requiredTechnology.Description.."}}" or "None",
	specialistsText and specialistsText or "None",
	yieldsText,
	baseData.Help and baseData.Help or "None"
	))
end

local projectPage= [=[{{BackArrowBE|Wonders (CivBE)|Wonders}}<div class="container-with-margins" style="float:right; width:270px; clear:right;">
{| class="civbetable" style="margin:0; width:270px"
!colspan="2" align="center"|<big><big>'''%s'''</big></big>
|-
|colspan="2" align="center"| %s<br/>Project {{#if:{{NAMESPACE}} | |[[Category:Projects (CivBE)]]}} in ''[[Beyond Earth]]''
|-
! align="left" | Cost
| %s {{ProductionIconBE}}
|-
! align="left" | Requires
| %s %s
|-
! align="left" | Purpose
| %s
|}</div>
]=]



function p.GetProjectPage(frame, articlename)
	local PAGENAME = articlename or mw.title.getCurrentTitle().text
	local name = string.gsub(PAGENAME, " %(.*","")
	local baseData = baseUtils.SelectFromWhere(mw.loadData("Module:Data/CivBE/Base/Projects"), "Description", name)
	local values = mw.loadData("Module:Data/CivBE/Base/Project_Values")
	local requiredAffinity = values.AffinityPrereqs[baseData.Type]
	local requiredTechnology = baseUtils.SelectFromWhere(mw.loadData("Module:Data/CivBE/Base/Technologies"), "Type", baseData.TechPrereq)
	local requiredAffinityText = nil
	if requiredAffinity then
		requiredAffinityText = requiredAffinity[1]["Level"] .." {{"..GetAffinity(requiredAffinity[1]["AffinityType"]).."BE}}<br/>"
	end
	
	return utils.PreProcess(frame,string.format(projectPage,
	name and name or "N/A",
	"[[File:"..PAGENAME..".png|120px]]",
	baseData.Cost and (baseData.Cost > 0 and baseData.Cost or "None") or "N/A",
	requiredAffinityText and requiredAffinityText or "",
	requiredTechnology and "{{LinkBE|"..requiredTechnology.Description.."}}" or "No technology",
	baseData.Help and baseData.Help or "None"
	))
end

local stationRow = [[|-
|
%s
|
%s
|
%s
|
%s
]]

function p.GetStationRow(frame, articlename)
	local displayname = articlename or frame.args[1]
	local name = string.gsub(displayname , " %(.*","")
	local data = mw.loadData("Module:Data/CivBE/Stations")
	local item = data[name]

	local tier1 = p.GetStationTierDescription(item.yields, 1)
	local tier2 = p.GetStationTierDescription(item.yields, 2)
	local tier3 = p.GetStationTierDescription(item.yields, 3)

	return utils.PreProcess(frame,string.format(stationRow,
	name,
	tier1,
	tier2,
	tier3))
end

function p.GetStationTierDescription(yields, tier)
	local data = yields[tier]
	return (data.science and "+"..data.science.." {{ScienceBE}}<br/>" or "") .. (data.energy and "+"..data.energy.." {{EnergyBE}}<br/>" or "") .. (data.food and "+"..data.food.." {{FoodBE}}<br/>" or "") .. (data.production and "+"..data.production.." {{ProductionBE}}<br/>" or "") .. (data.culture and "+"..data.culture.." {{CultureBE}}" or "")
end

local terrainpage = [=[<div class="container-with-margins" style="float:right; width:270px; clear:right;">
{| class="civbetable" style="margin:0; width:270px"
!colspan="2" align="center"|<big><big>'''%s'''</big></big>
|-
|colspan="2" align="center"|%s
Type of [[Terrain (CivBE)|Terrain]] in ''[[Beyond Earth]]''
|-
! align="left"| Yields
| %s
|-
|}</div>
%s
{{#if:{{NAMESPACE}} | |[[Category:Terrain (CivBE)]]}}]=]

function p.GetTerrainPage(frame, articlename)
	local PAGENAME = articlename or mw.title.getCurrentTitle().text
	local name = string.gsub(PAGENAME, " %(.*","")
	local baseData = baseUtils.SelectFromWhere(mw.loadData("Module:Data/CivBE/RT/Terrains"), "Description", name)
	if baseData == nil then
	    baseData = baseUtils.SelectFromWhere(mw.loadData("Module:Data/CivBE/Extra/Terrains"), "Description", name)
	end
	local yieldsData = mw.loadData("Module:Data/CivBE/RT/Terrain_Values")

	local yieldsText = ""
	local resourceYields = yieldsData.Yields[baseData.Type]

	if resourceYields then
		for key,value in pairs(resourceYields) do
			local yieldSymbol = "{{"..GetYieldName(value.YieldType).."IconBE}} "
			yieldsText = yieldsText..InsertPlus(value.Yield).." "..yieldSymbol.."<br/>"
		end
	end

	if string.len(yieldsText) == 0 then
		yieldsText = "None"
	end

	return utils.PreProcess(frame,string.format(terrainpage,
	name,
	"[[File:"..PAGENAME..".png|120px]]",
	yieldsText or "Unknown",
	baseData.Civilopedia))
end

local terrainRow = [[|-
|
%s
|
%s
]]

function p.GetTerrainRow(frame, articlename)
	local displayname = articlename or frame.args[1]
	local name = string.gsub(displayname , " %(.*","")
	local baseData = baseUtils.SelectFromWhere(mw.loadData("Module:Data/CivBE/RT/Terrains"), "Description", name)
	if baseData == nil then
	   baseData = baseUtils.SelectFromWhere(mw.loadData("Module:Data/CivBE/Extra/Improvements"), "Description", name)
	end
	local yieldsData = mw.loadData("Module:Data/CivBE/RT/Terrain_Values")

	local yieldsText = ""
	local improvedBy = ""
	local resourceYields = yieldsData.Yields[baseData.Type]

	if resourceYields then
		for key,value in pairs(resourceYields) do
			local yieldSymbol = "{{"..GetYieldName(value.YieldType).."IconBE}} "
			yieldsText = yieldsText..InsertPlus(value.Yield).." "..yieldSymbol.." "
		end
	end

	if string.len(yieldsText) == 0 then
		yieldsText = "None"
	end

	return utils.PreProcess(frame,string.format(terrainRow,
	"[["..name.." (CivBE)|"..name.."]]",
	yieldsText))
end


function GetTechnologyForImprovement(improvementType)
	local buildData = baseUtils.SelectFromWhere(mw.loadData("Module:Data/CivBE/Base/Builds"), "ImprovementType", improvementType)
	if buildData and buildData.PrereqTech then
		return GetTechName(buildData.PrereqTech)
	end
	return nil
end

local improvementpage = [=[<div class="container-with-margins" style="float:right; width:270px; clear:right;">
{| class="civbetable" style="margin:0; width:270px"
!colspan="2" align="center"|<big><big>'''%s'''</big></big>
|-
|colspan="2" align="center"|%s
[[Tile improvement (CivBE)|Tile improvement]] in ''[[%s]]''
|-
! align="left"| Maintenance
| %s
|-
! align="left"| Required technology
| %s
|-
! align="left"| Yields
| %s
|-
! align="left"| Notes
| %s
|}</div>
{{#if:{{NAMESPACE}} | |[[Category:Tile improvements (CivBE)]]}}]=]

function p.GetImprovementPage(frame, articlename)
	local PAGENAME = articlename or mw.title.getCurrentTitle().text
	local name = string.gsub(PAGENAME, " %(.*","")
	local baseData = baseUtils.SelectFromWhere(mw.loadData("Module:Data/CivBE/Base/Improvements"), "Description", name)
	if baseData == nil then
	   baseData = baseUtils.SelectFromWhere(mw.loadData("Module:Data/CivBE/Extra/Improvements"), "Description", name)
	end
	local yieldsData = mw.loadData("Module:Data/CivBE/Base/Improvement_Values")
	local game = "Beyond Earth"
	
	if baseData == nil then
	    game = "Beyond Earth"
	    baseData = baseUtils.SelectFromWhere(mw.loadData("Module:Data/CivBE/RT/Improvements"), "Description", name)
	    yieldsData = mw.loadData("Module:Data/CivBE/RT/Improvement_Values")
	end

	local yieldsText = ""
	local resourceYields = yieldsData.Yields[baseData.Type]
	local prereqTech = GetTechnologyForImprovement(baseData.Type) or (baseData.PrereqTech and GetTechName(baseData.PrereqTech))

	if resourceYields then
		for key,value in pairs(resourceYields) do
			local yieldSymbol = "{{"..GetYieldName(value.YieldType).."IconBE}} "
			yieldsText = yieldsText..InsertPlus(value.Yield).." "..yieldSymbol.."<br/>"
		end
	end

	if string.len(yieldsText) == 0 then
		yieldsText = "None"
	end

	return utils.PreProcess(frame,string.format(improvementpage,
	name,
	"[[File:"..PAGENAME..".png|120px]]",
	game,
	baseData.EnergyMaintenance and baseData.EnergyMaintenance.." {{EnergyBE}}" or "None",
	prereqTech and "{{LinkBE|"..prereqTech.."}}" or "None",
	yieldsText or "Unknown",
	baseData.Help or "None"))
end

local resourcepage = [=[<div class="container-with-margins" style="float:right; width:270px; clear:right;">
{| class="civbetable" style="margin:0; width:270px"
!colspan="2" align="center"|<big><big>'''%s'''</big></big>
|-
|colspan="2" align="center"|%s
[[Resources (CivBE)|Resource]] in ''[[%s]]''
|-
! align="left"| Yields
| %s
|-
! align="left"| Notes
| %s
|}</div>
{{#if:{{NAMESPACE}} | |[[Category:Resources (CivBE)]]}}]=]

function p.GetResourcePage(frame, articlename)
	local PAGENAME = articlename or mw.title.getCurrentTitle().text
	local name = string.gsub(PAGENAME, " %(.*","")
	local baseData = baseUtils.SelectFromWhere(mw.loadData("Module:Data/CivBE/Base/Resources"), "Description", name)
	local yieldsData = mw.loadData("Module:Data/CivBE/Base/Resource_Values")

	local yieldsText = ""
	local game = "Beyond Earth"
	
	if baseData == nil then
	    game = "Rising Tide"
	    baseData = baseUtils.SelectFromWhere(mw.loadData("Module:Data/CivBE/RT/Resources"), "Description", name)
	    yieldsData = mw.loadData("Module:Data/CivBE/RT/Resource_Values")
	end
	local resourceYields = yieldsData.YieldChanges[baseData.Type]

	if resourceYields then
		for key,value in pairs(resourceYields) do
			local yieldSymbol = "{{"..GetYieldName(value.YieldType).."IconBE}} "
			yieldsText = yieldsText..InsertPlus(value.Yield).." "..yieldSymbol.."<br/>"
		end
	end

	if string.len(yieldsText) == 0 then
		yieldsText = "None"
	end

	return utils.PreProcess(frame,string.format(resourcepage,
	name,
	"[[File:"..PAGENAME..".png|120px]]",
	game,
	yieldsText or "Unknown",
	baseData.Help or "None"))
end

local steamachievementbox = [=[{| class="steam-achievement-container"
!class="steam-achievement-image-cell" |[[File:Steam achievement %s (CivBE).jpg|64px|%s]]
!class="steam-achievement-text-cell"|<div class="steam-achievement-text-cell-inner-container"><span class="steam-achievement-name">%s</span><br/><div class="steam-achievement-description">%s
:%s</div></div>
|}[[Category:Steam achievements in CivBE]]]=]
 
local function isEmpty(param) 
	return param == nil or param == ''
end
 
function p.GetSteamAchievement(frame, articlename)
	local PAGENAME = articlename or frame.args[1]
	local name = string.gsub(PAGENAME, " %(.*","")
	local data = mw.loadData("Module:Data/CivBE/Base/Achievements")[name]
	local missing = "<small>(Is this a reference to something in popular culture? Please [[Module:Data/CivBE/Base/Achievements|add the information here]]!)</small>"
 
	if data == nil then
		return "''Achievement infobox data not found for \""..name.."\". Check the parameter or add the data to [[Module:Data/CivBE/Base/Achievements]].''"
	end
 
	return utils.PreProcess(frame,string.format(steamachievementbox,
	name, name, name,
	data.condition,
	not isEmpty(data.reference) and data.reference or missing))
end

local unitinfobox= [=[<div class="container-with-margins" style="float:right; width:270px; clear:right;">
{| class="civbetable" style="margin:0; width:270px"
!colspan="2" align="center"|<big><big>'''%s'''</big></big>
|-
|colspan="2" align="center"| {{IconBE|%s|180}}<br/>%s in ''[[Beyond Earth]]''
%s
%s
%s
|}</div>
%s]=]

local requiredstats= [=[
|-
! align="left" | Required
| %s %s %s
]=]

local nonorbitalsection= [=[|-
! align="left" | Moves
| {{MovesIconBE}} %s
|-
! align="left" | Base Unit Strength
| {{StrengthIconBE}} %s]=]

local orbitalsection= [=[|-
! align="left" | Orbital Zone Radius
| %s
|-
! align="left" | Sight Range
| %s
|-
! align="left" | Orbital Lifespan
| %s]=]

local rangesection= [=[|-
! align="left" | Base Ranged Strength
| {{RangedStrengthIconBE}} %s
|-
! align="left" | Base Range
| {{RangeBE}} %s]=]

local unitcategories= [=[{{BackArrowBE|List_of_units_in_CivBE|Back to the list of units}}
{{#if:{{NAMESPACE}} | |[[Category:Units (CivBE)]]}}]=]

local aliencategories= [=[{{BackArrowBE|List of Aliens (CivBE)|List of Aliens in CivBE|Back to the List of Aliens}}
{{#if:{{NAMESPACE}} | |[[Category:Aliens (CivBE)]]}}]=]

local orbitalcategories= [=[{{BackArrowBE|List of orbital units (CivBE)|Back to the list of orbital units}}
{{#if:{{NAMESPACE}} | |[[Category:Orbital units (CivBE)]]}}]=]

 
local function getUnitType(unitCombatClass, orbital)
    local unitTypeText = '';
    if not unitCombatClass then
        if not orbital then
            unitTypeText = "Non-Combat "
        end
    elseif unitCombatClass == 'UNITCOMBAT_RECON' then
        unitTypeText = "Recon "
    elseif unitCombatClass == 'UNITCOMBAT_MELEE' then
        unitTypeText = "Melee "
    elseif unitCombatClass == 'UNITCOMBAT_NAVALMELEE' then
        unitTypeText = "Melee Sea "
    elseif unitCombatClass == 'UNITCOMBAT_ARCHER' or unitCombatClass == 'UNITCOMBAT_GUN' then
        unitTypeText = "Ranged "
    elseif unitCombatClass =='UNITCOMBAT_NAVALRANGED' then
        unitTypeText = "Ranged Sea "
    elseif unitCombatClass == 'UNITCOMBAT_SUBMARINE' then
        unitTypeText = "Submarine "
    elseif unitCombatClass == 'UNITCOMBAT_MOUNTED' then
        unitTypeText = "Mounted "
    elseif unitCombatClass == 'UNITCOMBAT_SIEGE' then
        unitTypeText = "Siege "
    elseif unitCombatClass == 'UNITAI_CARRIER_SEA' then
        unitTypeText = "Carrier "    
    elseif unitCombatClass == 'UNITCOMBAT_HELICOPTER' then
        unitTypeText = "Hover "  
    elseif unitCombatClass == 'UNITAI_CITY_BOMBARD' then
        unitTypeText = "Bombard "
    elseif unitCombatClass == 'UNITCOMBAT_FIGHTER' then
        unitTypeText = "Air "
    else
        unitTypeText = ""
    end

    return unitTypeText .. 'Unit'
end

function p.GetUnitInfobox(frame, articlename)
    local PAGENAME = articlename or mw.title.getCurrentTitle().text 
   	local name = string.gsub(PAGENAME, " %(.*","")
	local baseData = baseUtils.SelectFromWhere(mw.loadData("Module:Data/CivBE/RT/Units"), "Description", name)
	local values = mw.loadData("Module:Data/CivBE/RT/Unit_Values")
	local requiredAffinity = values.AffinityPrereqs[baseData.Type]
	local requiredTechnology = baseUtils.SelectFromWhere(mw.loadData("Module:Data/CivBE/RT/Technologies"), "Type", baseData.PrereqTech)
	local requiredResources = values.ResourceQuantityRequirements[baseData.Type]
	local moves = baseData.Moves
    -- local unitDomain= baseData.Domain
    local unitCombatClass= baseData.CombatClass
	local alien= baseData.AlienLifeform
	local strength = baseData.Combat 
	local rangestrength = baseData.RangedCombat
	local range = baseData.Range
	local orbital = baseData.Orbital
	
	local unitTypeText = getUnitType(unitCombatClass, orbital)
	
	if requiredAffinity then
	    requiredAffinityText = ""
	    for key,value in pairs(requiredAffinity) do
		requiredAffinityText = requiredAffinityText..requiredAffinity[key]["Level"] .." {{"..GetAffinity(requiredAffinity[key]["AffinityType"]).."BE}}<br/>"
		end
	end
	if requiredResources then
		requiredResourcesText = ""
		for key,value in pairs(requiredResources) do
			local resourceSymbol = "{{"..GetResourceName(value.ResourceType).."BE}}"
			requiredResourcesText = requiredResourcesText..value.Cost.." "..resourceSymbol.."<br/>"
		end
    end

    local nonorbital = utils.PreProcess(frame,string.format(nonorbitalsection, 
        moves or '0', 
        strength or '0')
    )
    
    if range then
        rangeinfo = utils.PreProcess(frame,string.format(rangesection , rangestrength, range))
    else
        rangeinfo = ''
    end
    
    if orbital then
        local orbitalvalues = mw.loadData("Module:Data/CivBE/RT/OrbitalUnits")
        unitTypeText = "Orbital " .. unitTypeText
        local effectRange =  orbitalvalues[orbital].EffectRange or 'N/A'
        local sightRange = orbitalvalues[orbital].SightRange or 'N/A'
        local duration  = orbitalvalues[orbital].TurnDuration or 'N/A'
        nonorbital = utils.PreProcess(frame,string.format(orbitalsection, effectRange, sightRange, duration))
    end
    
    if alien then
        unitTypeText = "Alien " .. unitTypeText
        required = ''
        categories = aliencategories
    else
        required = utils.PreProcess(frame,string.format(requiredstats, requiredAffinityText and requiredAffinityText or "", requiredResourcesText and requiredResourcesText or "", requiredTechnology and "{{SureIconBE|"..requiredTechnology.Description.."|30}}" or "None"  
        ))
    
        if orbital and unitCombatClass then -- Required to put here due to rocktopus
            categories = unitcategories .. '<br />' .. orbitalcategories
        elseif orbital then
            categories = orbitalcategories
        else
            categories = unitcategories
        end
    end
    

    
	return utils.PreProcess(frame,string.format(unitinfobox, name, name, unitTypeText, required, nonorbital, rangeinfo, categories
	))

end

local function GetCPDescription(frame, type, articlename)
    local PAGENAME = articlename or mw.title.getCurrentTitle().text 
   	local name = string.gsub(PAGENAME, " %(.*","")
	local baseData = baseUtils.SelectFromWhere(mw.loadData("Module:Data/CivBE/RT/"..type), "Description", name)
	local cp = string.gsub(baseData.Civilopedia, "\\r\\n", "<br>")
	return utils.PreProcess(frame,string.format(cp))
end

function p.GetUnitCPPage(frame, articlename)
	return GetCPDescription(frame, "Units", articlename)
end

function p.GetResourceCPPage(frame, articlename)
	return GetCPDescription(frame, "Resources", articlename)
end

function p.GetImprovementCPPage(frame, articlename)
	return GetCPDescription(frame, "Improvements", articlename)
end
 
return p
Community content is available under CC-BY-SA unless otherwise noted.