Module:NationLister: Difference between revisions

From Terra Invicta Official Wiki
Redwah (talk | contribs)
No edit summary
Redwah (talk | contribs)
No edit summary
Tag: Reverted
Line 187: Line 187:
returnString = returnString .. '\n| ' .. row['miltech']
returnString = returnString .. '\n| ' .. row['miltech']
else
else
returnString = returnString .. '\n| ' .. row['foundMilitaryIPs']
returnString = returnString .. '\n| ' .. (tonumber(row['foundMilitaryIPs']) * 100) .. '%' .. IconModule.Icon({args={'found military'}})
end
end
if row['nuclearWeapons'] and tonumber(row['nuclearWeapons']) and tonumber(row['nuclearWeapons']) > 0 then
if row['nuclearWeapons'] and tonumber(row['nuclearWeapons']) and tonumber(row['nuclearWeapons']) > 0 then
returnString = returnString .. '\n| ' .. row['nuclearWeapons']
returnString = returnString .. '\n| ' .. row['nuclearWeapons']
elseif row['nuclearProgramIPs'] then
elseif row['nuclearProgramIPs'] then
returnString = returnString .. '\n| ' .. row['nuclearProgramIPs']
returnString = returnString .. '\n| ' .. (tonumber(row['nuclearProgramIPs']) * 100) .. '%' .. IconModule.Icon({args={'develop atomic bomb'}})
else
else
returnString = returnString .. '\n| 0'
returnString = returnString .. '\n| 0%' .. IconModule.Icon({args={'develop atomic bomb'}})
end
end

Revision as of 02:19, 29 November 2025

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

---
---Reads the Nation data files and presents them in readable formats, with additional calculated statistics.
---
---@module NationLister
local NationLister = {}

--region Dependencies
local IconModule = require('Module:Icon')
local RegionData = mw.loadData('Module:CSVReader/Region')
local NationData = mw.loadData('Module:CSVReader/Nation')
local ClaimData = mw.loadData('Module:CSVReader/Claim')
local RegionNames = mw.loadData('Module:ENReader/Region')
local NationNames = mw.loadData('Module:ENReader/Nation')
--endregion

--region Private constants
local floor = math.floor
local mlog = math.log
local mmin = math.min
local mmax = math.max
local round = function(num, decimals)
    local mult = 10^(decimals or 0)
    return floor(num * mult + 0.5) / mult
end
local ssub = string.sub
--endregion

--region Private member variables
--none
--endregion

--region Private methods
local function calculateCPCost(GDP)
	return (GDP / 1000000000) ^ 0.6 / 2
end

local function calculateNumControlPoints(GDP)
	return mmin(6, mmax(1, round((GDP / 1000000000) ^ 0.18 / 1.09)))
end

---@return monthly research output for nation if unrest = 0 and there are no armies.
local function calculateIP(GDP)
	return (GDP / 1000000000) ^ 0.35
end


---@return monthly research output for nation if cohesion = 5 and unrest = 0.
local function calculateResearch(pop, gdppc, education, democracy, numControlPoints)
--float population_Millions = this.population_Millions;
--float perCapitaGDP = this.perCapitaGDP;
--return (population_Millions * ((perCapitaGDP <= 30000f) ? Mathf.Pow(this.perCapitaGDP / 15000f, 0.6f) : (1.5157166f + 0.90942997f * (Mathf.Log(this.perCapitaGDP / 15000f) - 0.6931472f))) * (this.education * Mathf.Min(this.education, 12f)) * Mathf.Pow(Mathf.Max(this.democracy, 1f), 0.16666667f) * 0.0075f + Mathf.Min(this.population / 5000f, (float)this.numControlPoints + this.education + this.democracy / 2f)) * (1.25f - Mathf.Abs(this.cohesion - 5f) / 10f) * (1f - this.unrest * this.unrest * 0.01f) * (1f + this.adviserScienceBonus);
	local gdppcMultiplier = 0
	if gdppc <= 30000 then
		gdppcMultiplier = (gdppc / 15000) ^ 0.6
	else
		gdppcMultiplier = 1.5157166 + 0.90942997 * (mlog(gdppc / 15000) - 0.6931472)
	end
	local educationMultiplier = education * mmin(education, 12)
	local democracyMultiplier = mmax(democracy, 1) ^ 0.16666667
	local baseValue = mmin(pop / 5000, numControlPoints + education + democracy / 2)
	return (pop / 1000000 * gdppcMultiplier * educationMultiplier * democracyMultiplier * 0.0075 + baseValue) * 1.25
end

---@return monthly spoils profit for nation if unrest = 0 and there are no armies and 100% of the IP is put into spoils.
local function calculateSpoils(IP, democracy, numResourceRegions)
	return (5 * IP + 5 * numResourceRegions + 2.5 * (10 - democracy)) * IP
end

--endregion

--region Public methods
function NationLister.ListPresentNations()
	return NationLister.ListNations(false)
end

function NationLister.ListFutureNations()
	return NationLister.ListNations(true)
end

---@param futureCampaign boolean whether to show the 2070 Nations or the 2022 Nations.
---@return table
function NationLister.ListNations(futureCampaign)
	local frame = mw.getCurrentFrame()
	
	local returnString = '{| class="wikitable sortable mw-collapsible" style="text-align: center;'
	returnString = returnString .. '\n|-'
	returnString = returnString .. '\n! rowspan=2 | Nation<br>Alternate Name<br>(# Regions)'
	returnString = returnString .. '\n! rowspan=2 | [[Nations#GDP|GDP]]<br>'  .. IconModule.Icon({args={'cp'}}) .. '<br>' .. IconModule.Icon({args={'ip', bgcolor='DarkSlateGray'}})
	returnString = returnString .. '\n! rowspan=2 | ' .. IconModule.Icon({args={'pop'}}) .. '<br>(Mns)'
	returnString = returnString .. '\n! colspan=2 | ' .. IconModule.Icon({args={'research', bgcolor='DarkSlateGray'}}) .. ' per'
	returnString = returnString .. '\n! colspan=2 | ' .. IconModule.Icon({args={'spoils'}}) .. ' per'
	returnString = returnString .. '\n! rowspan=2 | ' .. IconModule.Icon({args={'cohesion', bgcolor='DarkSlateGray'}})
	returnString = returnString .. '\n! rowspan=2 | ' .. IconModule.Icon({args={'unrest', bgcolor='DarkSlateGray'}})
	returnString = returnString .. '\n! rowspan=2 | ' .. IconModule.Icon({args={'inequality', bgcolor='DarkSlateGray'}})
	returnString = returnString .. '\n! rowspan=2 | ' .. IconModule.Icon({args={'democracy', bgcolor='DarkSlateGray'}})
	returnString = returnString .. '\n! rowspan=2 | ' .. IconModule.Icon({args={'education'}})
	returnString = returnString .. '\n! rowspan=2 | ' .. IconModule.Icon({args={'sustainability'}})
	returnString = returnString .. '\n! rowspan=2 | ' .. IconModule.Icon({args={'money'}})
	returnString = returnString .. '\n! rowspan=2 | ' .. IconModule.Icon({args={'miltech'}})
	returnString = returnString .. '\n! rowspan=2 | ' .. IconModule.Icon({args={'nuke'}})
	returnString = returnString .. '\n! rowspan=2 | ' .. IconModule.Icon({args={'boost'}})
	returnString = returnString .. '\n! rowspan=2 | ' .. IconModule.Icon({args={'mc'}})
	returnString = returnString .. '\n|-'
	
	returnString = returnString .. '\n! Month' 
	returnString = returnString .. '\n! '  .. IconModule.Icon({args={'cp'}})
	returnString = returnString .. '\n! Month' 
	returnString = returnString .. '\n! '  .. IconModule.Icon({args={'cp'}})
	returnString = returnString .. '\n|-'
	
	for rowID, row in pairs(NationData) do
		if ((futureCampaign and string.sub(rowID,1,4) == '2070') or (not futureCampaign and string.sub(rowID,1,4) ~= '2070')) then
			
			local regionCount = 0
			local regionPopulationInMns = 0
			local regionBoost = 0
			local regionMC = 0
			local regionResource = 0
			local claimList = ClaimData[1][rowID]
			if claimList then
				for i, regionID in ipairs(claimList) do
					if ClaimData[3][rowID][regionID]['initialOwner'] == 'true' and RegionData[regionID] then
						regionCount = regionCount + 1
						regionPopulationInMns = regionPopulationInMns + (tonumber(RegionData[regionID]['population_Millions']) or 0)
						regionBoost = regionBoost + (tonumber(RegionData[regionID]['boostPerYear_tons']) or 0)
						regionMC = regionMC + (tonumber(RegionData[regionID]['missionControl']) or 0)
						if RegionData[regionID]['oilResource'] == 'true' or RegionData[regionID]['mining'] == 'true' then
							regionResource = regionResource + 1
						end
					end
				end
			end
			-- Convert boost to monthly, and round to 2 decimals.
			regionBoost = floor(regionBoost / 12 * 100 + 0.5) / 100

			returnString = returnString .. '\n| [[' .. rowID .. '|' .. (NationNames['TINationTemplate.displayName.' .. rowID] or NationNames['TINationTemplate.displayName.' .. ssub(rowID,6)]  or rowID) .. ']]<br>' .. (NationNames['TINationTemplate.unionDisplayName.' .. rowID] or NationNames['TINationTemplate.unionDisplayName.' .. ssub(rowID,6)] or '') .. '<br>(' .. tostring(regionCount) .. ' Initial Regions)'
			if regionCount > 0 then
				-- This nation actually exists at the start of the scenario.
				local GDP = tonumber(row['initialGDP'] or 0) or 0
				local CPCost = calculateCPCost(GDP)
				local IP = calculateIP(GDP)
				returnString = returnString .. '\n| ' .. round(GDP / 1000000000) .. '<br>' .. round(CPCost, 1) .. IconModule.Icon({args={'cp'}}) .. '<br>' .. round(IP, 2) .. IconModule.Icon({args={'ip', bgcolor='DarkSlateGray'}})
				returnString = returnString .. '\n| ' .. round(regionPopulationInMns, 2)
				local numControlPoints = calculateNumControlPoints(GDP)
				local gdppc = GDP / regionPopulationInMns / 1000000
				local education = tonumber(row['education'] or 0) or 0
				local democracy = tonumber(row['democracy'] or 0) or 0
				local researchOutput = calculateResearch(regionPopulationInMns * 1000000, gdppc, education, democracy, numControlPoints)
				returnString = returnString .. '\n| ' .. round(researchOutput, 1)
				returnString = returnString .. '\n| ' .. round(researchOutput / CPCost, 1)
				local spoilsOutput = calculateSpoils(IP, democracy, regionResource)
				returnString = returnString .. '\n| ' .. round(spoilsOutput, 1)
				returnString = returnString .. '\n| ' .. round(spoilsOutput / CPCost, 1)
				
				
				
				
				returnString = returnString .. '\n| ' .. row['cohesion']
				
				returnString = returnString .. '\n| ' .. row['unrest']
				
				returnString = returnString .. '\n| ' .. row['inequality']
				
				returnString = returnString .. '\n| ' .. democracy
				
				returnString = returnString .. '\n| ' .. education
				
				local pollutionMultiplier = tonumber(row['greenEconomy'])
				if not pollutionMultiplier then
					returnString = returnString .. '\n|'
				elseif pollutionMultiplier == 0 then
					returnString = returnString .. '\n| 10'
				elseif (1/pollutionMultiplier) > 9.99 then
					returnString = returnString .. '\n| 9.99+'
				elseif (1/pollutionMultiplier) > 9.9 then
					returnString = returnString .. '\n| 9.9+'
				else
					returnString = returnString .. '\n| ' .. tostring(floor(1/pollutionMultiplier * 100 + 0.5) / 100)
				end
				
				local funding = tonumber(row['spaceFunding_year']) or 0
				-- Convert funding to monthly, and round to 2 decimals.
				funding = floor(funding / 12 * 100 + 0.5) / 100
				returnString = returnString .. '\n| ' .. tostring(funding)
				
				if not row['foundMilitaryIPs'] or not tonumber(row['foundMilitaryIPs']) or tonumber(row['foundMilitaryIPs']) == 1 then
					returnString = returnString .. '\n| ' .. row['miltech']
				else
					returnString = returnString .. '\n| ' .. (tonumber(row['foundMilitaryIPs']) * 100) .. '%' .. IconModule.Icon({args={'found military'}})
				end
				
				
				
				if row['nuclearWeapons'] and tonumber(row['nuclearWeapons']) and tonumber(row['nuclearWeapons']) > 0 then
					returnString = returnString .. '\n| ' .. row['nuclearWeapons']
				elseif row['nuclearProgramIPs'] then
					returnString = returnString .. '\n| ' .. (tonumber(row['nuclearProgramIPs']) * 100) .. '%' .. IconModule.Icon({args={'develop atomic bomb'}})
				else
					returnString = returnString .. '\n| 0%' .. IconModule.Icon({args={'develop atomic bomb'}})
				end
				
				returnString = returnString .. '\n| ' .. tostring(regionBoost)
				
				returnString = returnString .. '\n| ' .. tostring(regionMC)
				
		    end
		    returnString = returnString .. '\n|-'
	    end
	end
	returnString = returnString .. '\n|}'
	return returnString
end

--endregion

return NationLister