Module:NationLister/Single

From Terra Invicta Official Wiki

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

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

--region Dependencies
local IconModule = require('Module:Icon')
local TVModule = require('Module:TV')
local NLModule = require('Module:NationLister')
local RegionNameBuilder = require('Module:RegionLister/NameBuilder')

local RegionData = mw.loadData('Module:CSVReader/Region')
local NationData = mw.loadData('Module:CSVReader/Nation')
local StartTimeData = mw.loadData('Module:CSVReader/StartTime')
local ClaimData = mw.loadData('Module:CSVReader/Claim')
local PeaceData = mw.loadData('Module:ClaimLister/Peace')
local FullData = mw.loadData('Module:ClaimLister/Full')
local RegionArmyData = mw.loadData('Module:RegionLister/Armies')

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
local tinsert = table.insert
local tconcat = table.concat
--endregion

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

--region Private methods
--endregion

--region Public methods

---@param frame a set of arguments that includes:
----frame.args[1] the dataName of the nation
----frame.args['notes'] any additional notes the output table should contain
---@return wiki table of details for that nation
function NationLister.SingleNationTable(frame)
	local NationID = frame.args[1]
	local NationNotes = frame.args['notes'] or ''
	
	local GDP = tonumber(NationData[NationID]['initialGDP'] or 0) or 0
	startTimeDataName = ''
	if ssub(NationID,1,4) == '2026' then
		startTimeDataName = '2026Start'
	elseif ssub(NationID,1,4) == '2070' then
		startTimeDataName = '2070Start'
	else
		startTimeDataName = 'ModernDayStart'
	end
	GDP = GDP * (tonumber(StartTimeData[startTimeDataName]['globalStartingGDPScaling'] or 1) or 1)
	local education = tonumber(NationData[NationID]['education'] or 0) or 0
	
	local CPCost = NLModule.calculateCPCost(GDP)
	local IP = NLModule.calculateIP(GDP)
	local numControlPoints = NLModule.calculateNumControlPoints(GDP)
	local democracy = tonumber(NationData[NationID]['democracy'] or 0) or 0
	local nukes = tonumber(NationData[NationID]['nuclearWeapons'] or 0) or 0
	local funding = tonumber(NationData[NationID]['spaceFunding_year']) or 0
	-- Convert funding to monthly.
	funding = funding / 12
	local pollutionMultiplier = tonumber(NationData[NationID]['greenEconomy'])
	local regionCount = 0
	local regionPopulationInMns = 0
	local totalRegionGDPShares = 0
	local regionBoost = 0
	local regionMC = 0
	local regionMCCap = 0
	local regionGood = {0,0,0}
	local regionArmy = 0
	local regionNavy = 0
	local claimList = ClaimData[1][NationID]
	if claimList then
		for i, regionID in ipairs(claimList) do
			if ClaimData[3][NationID][regionID]['initialOwner'] == 'true' and RegionData[regionID] then
				regionCount = regionCount + 1
				regionPopulationInMns = regionPopulationInMns + (tonumber(RegionData[regionID]['population_Millions']) or 0)
				local regionMultiplier = 1
				if RegionData[regionID]['oilResource'] == 'true' or RegionData[regionID]['mining'] == 'true' or RegionData[regionID]['coreEco'] == 'true' then
					regionMultiplier = 1.25
				elseif ClaimData[3][NationID][regionID]['initialColony'] == 'true' then
					regionMultiplier = 0.5
				end
				totalRegionGDPShares = totalRegionGDPShares + (tonumber(RegionData[regionID]['population_Millions']) or 0) * regionMultiplier
				regionBoost = regionBoost + (tonumber(RegionData[regionID]['boostPerYear_tons']) or 0)
				regionMC = regionMC + (tonumber(RegionData[regionID]['missionControl']) or 0)
				if RegionData[regionID]['oilResource'] == 'true' then
					regionGood[3] = regionGood[3] + 1
				elseif RegionData[regionID]['mining'] == 'true' then
					regionGood[2] = regionGood[2] + 1
				elseif RegionData[regionID]['coreEco'] == 'true' then
					regionGood[1] = regionGood[1] + 1
				end
				if RegionArmyData[regionID] then
					regionArmy = regionArmy + 1
					if RegionArmyData[regionID] == 'Naval' then
						regionNavy = regionNavy + 1
					end
				end
			end
		end
		for i, regionID in ipairs(claimList) do
			if ClaimData[3][NationID][regionID]['initialOwner'] == 'true' and RegionData[regionID] then
				local regionMultiplier = 1
				if RegionData[regionID]['oilResource'] == 'true' or RegionData[regionID]['mining'] == 'true' or RegionData[regionID]['coreEco'] == 'true'  then
					regionMultiplier = 1.25
				elseif ClaimData[3][NationID][regionID]['initialColony'] == 'true' then
					regionMultiplier = 0.5
				end
				local regionShare = (tonumber(RegionData[regionID]['population_Millions']) or 0) * regionMultiplier
				local regionGDP = GDP * regionShare / totalRegionGDPShares
				regionMCCap = regionMCCap + 1 + floor(regionGDP / 1000000000 / mmax(200,300 - education * 6))
			end
		end
	end
	-- Convert boost to monthly decatons.
	regionBoost = regionBoost / 120
	local gdppc = GDP / regionPopulationInMns / 1000000
	local researchOutput = NLModule.calculateResearch(regionPopulationInMns * 1000000, gdppc, education, democracy, numControlPoints)
	local spoilsOutput = NLModule.calculateSpoils(IP, democracy, regionGood[2] + regionGood[3])
	
	local nationName = '[[' .. ssub(NationID,-3) .. '|' .. (NationNames['TINationTemplate.displayName.' .. ssub(NationID,-3)] or NationID) .. ']]'
	local nationFlag = IconModule.Icon({args={ssub(NationID,-3),size='120px'}})
	local unionFlag = nationFlag
	if NationData[NationID]['unionFlagResource'] and NationData[NationID]['unionFlagResource'] ~= '' then
		unionFlag = IconModule.Icon({args={ssub(NationID,-3) .. 'U',size='120px'}})
	end
	local unionName = NationNames['TINationTemplate.unionDisplayName.' .. ssub(NationID,-3)] or ''
	
	local returnString = '{| class="wikitable" style="width: 100%;text-align:center;"'
	returnString = returnString .. '\n|-'
	if unionName == '' then
		returnString = returnString .. '\n! colspan=4 | <big>'
	else
		returnString = returnString .. '\n! colspan=2 | <big>'
	end
	returnString = returnString .. nationName .. '</big><br>' .. nationFlag
	if unionName ~= '' then
		returnString = returnString .. '\n! colspan=2 | <big>'
		returnString = returnString .. unionName .. '</big><br>' .. unionFlag
	end
	returnString = returnString .. '\n|-'
	
	if regionCount > 0 then
		returnString = returnString .. '\n! colspan=4 | Initial Stats'
		returnString = returnString .. '\n|-'
		
		returnString = returnString .. '\n! ' .. TVModule.TV({args={'democracy'}}) 
		returnString = returnString .. '\n| ' .. democracy
		returnString = returnString .. '\n! ' .. TVModule.TV({args={'miltech'}}) 
		returnString = returnString .. '\n| ' .. NationData[NationID]['miltech']
		returnString = returnString .. '\n|-'
		
		returnString = returnString .. '\n! ' .. TVModule.TV({args={'unrest'}})
		returnString = returnString .. '\n| ' .. NationData[NationID]['unrest']
		returnString = returnString .. '\n! ' .. TVModule.TV({args={'navies'}}) 
		returnString = returnString .. '\n| ' .. regionNavy
		returnString = returnString .. '\n|-'
		
		returnString = returnString .. '\n! [[GDP]] in Billions'
		returnString = returnString .. '\n| ' .. (GDP / 1000000000)
		returnString = returnString .. '\n! ' .. TVModule.TV({args={'nukes'}})
		returnString = returnString .. '\n| ' .. nukes	
		returnString = returnString .. '\n|-'
	
		returnString = returnString .. '\n! Total ' .. TVModule.TV({args={'cp'}}) .. ' Cost'
		returnString = returnString .. '\n| ' .. round(CPCost,2)
		returnString = returnString .. '\n! ' .. TVModule.TV({args={'armies'}})
		returnString = returnString .. '\n| ' .. regionArmy
		returnString = returnString .. '\n|-'
		
		returnString = returnString .. '\n! Total ' .. TVModule.TV({args={'pop'}}) .. ' in Millions'
		returnString = returnString .. '\n| ' .. (regionPopulationInMns)
		returnString = returnString .. '\n! ' .. TVModule.TV({args={'gdppc'}}) 
		returnString = returnString .. '\n| ' .. round(GDP / regionPopulationInMns / 1000000)
		returnString = returnString .. '\n|-'
		
		returnString = returnString .. '\n! Base ' .. TVModule.TV({args={'ip'}})
		returnString = returnString .. '\n| ' .. round(IP,2)
		returnString = returnString .. '\n! ' .. TVModule.TV({args={'sustainability'}}) 
		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| ' .. round(1/pollutionMultiplier,2)
		end
		returnString = returnString .. '\n|-'
		
		returnString = returnString .. '\n! Monthly ' .. IconModule.Icon({args={'money'}}) .. '[[Funding]]'
		returnString = returnString .. '\n| ' .. round(funding,2)
		returnString = returnString .. '\n! ' .. TVModule.TV({args={'education'}}) 
		returnString = returnString .. '\n| ' .. education
		returnString = returnString .. '\n|-'
		
		returnString = returnString .. '\n! Monthly ' .. IconModule.Icon({args={'boost'}}) .. '[[Boost]]'
		returnString = returnString .. '\n| ' .. round(regionBoost,2)
		returnString = returnString .. '\n! ' .. TVModule.TV({args={'inequality'}})
		returnString = returnString .. '\n| ' .. NationData[NationID]['inequality']
		returnString = returnString .. '\n|-'
		
		returnString = returnString .. '\n! ' .. IconModule.Icon({args={'mc'}}) .. '[[Mission Control]]'
		returnString = returnString .. '\n| ' .. regionMC .. '/' .. regionMCCap
		returnString = returnString .. '\n! ' .. TVModule.TV({args={'cohesion'}})
		returnString = returnString .. '\n| ' .. NationData[NationID]['cohesion']
		returnString = returnString .. '\n|-'
		
		
		returnString = returnString .. '\n! colspan=4 | Estimated Stats at 0 Unrest, 0 Armies, 5 Cohesion'
		returnString = returnString .. '\n|-'
		
		returnString = returnString .. '\n! Monthly ' .. IconModule.Icon({args={'research', bgcolor='DarkSlateGray'}}) .. '[[Research]]'
		returnString = returnString .. '\n| ' .. round(researchOutput, 2)
		returnString = returnString .. '\n! Monthly ' .. IconModule.Icon({args={'research', bgcolor='DarkSlateGray'}}) .. '[[Research]]<br>Per Total ' .. TVModule.TV({args={'cp', nil, 'true'}}) .. ' Cost'
		returnString = returnString .. '\n| ' .. round(researchOutput / CPCost, 2)
		returnString = returnString .. '\n|-'
		
		returnString = returnString .. '\n! Monthly ' .. IconModule.Icon({args={'spoils'}}) .. 'Spoils'
		returnString = returnString .. '\n| ' .. round(spoilsOutput, 2)
		returnString = returnString .. '\n! Monthly ' .. IconModule.Icon({args={'spoils'}}) .. 'Spoils<br>Per Total ' .. TVModule.TV({args={'cp', nil, 'true'}}) .. ' Cost'
		returnString = returnString .. '\n| ' .. round(spoilsOutput / CPCost, 2)
		returnString = returnString .. '\n|-'

		returnString = returnString .. '\n! colspan=4 | ' .. regionCount .. ' Initial [[Regions]]: '
		returnString = returnString .. regionGood[1] .. IconModule.Icon({args={'core economic region', bgcolor='DarkSlateGray'}})
		returnString = returnString .. regionGood[2] .. IconModule.Icon({args={'resource region'}})
		returnString = returnString .. regionGood[3] .. IconModule.Icon({args={'oil region'}})
		returnString = returnString .. '\n|-'
		
		returnString = returnString .. '\n! Region'
		returnString = returnString .. '\n! Region ' .. TVModule.TV({args={'pop'}}) .. ' in Millions'
		returnString = returnString .. '\n! Region Space Facilities'
		returnString = returnString .. '\n! Region Sub-Nations'
		returnString = returnString .. '\n|-'
		
		for i, regionID in ipairs(claimList) do
			if ClaimData[3][NationID][regionID]['initialOwner'] == 'true' and RegionData[regionID] then
				returnString = returnString .. '\n| ' .. RegionNameBuilder.buildName({args={regionID, NationID}}) -- .. '<br>(' .. regionID .. ')' 
				returnString = returnString .. '\n| ' .. (tonumber(RegionData[regionID]['population_Millions']) or 0)
				returnString = returnString .. '\n| ' 
				if round((tonumber(RegionData[regionID]['boostPerYear_tons']) or 0) / 120, 2) > 0 then
					returnString = returnString .. round((tonumber(RegionData[regionID]['boostPerYear_tons']) or 0) / 120, 2)
					returnString = returnString .. ' Monthly ' .. IconModule.Icon({args={'boost'}}) .. '[[Boost]]<br>'
				end
				returnString = returnString .. (tonumber(RegionData[regionID]['missionControl']) or 0)
				local regionMultiplier = 1
				if RegionData[regionID]['oilResource'] == 'true' or RegionData[regionID]['mining'] == 'true' or RegionData[regionID]['coreEco'] == 'true'  then
					regionMultiplier = 1.25
				elseif ClaimData[3][NationID][regionID]['initialColony'] == 'true' then
					regionMultiplier = 0.5
				end
				local regionShare = (tonumber(RegionData[regionID]['population_Millions']) or 0) * regionMultiplier
				local regionGDP = GDP * regionShare / totalRegionGDPShares
				returnString = returnString .. '/' .. (1 + floor(regionGDP / 1000000000 / mmax(200,300 - education * 6)))
				returnString = returnString .. ' ' .. IconModule.Icon({args={'mc'}}) .. '[[Mission Control]]'
				
				local subnations = {}
				for _, subnationID in ipairs(ClaimData[5][regionID]) do
					if subnationID ~= NationID then
						tinsert(subnations,'[[' .. ssub(subnationID,-3) .. '|' .. (NationNames['TINationTemplate.displayName.' .. ssub(subnationID,-3)] or subnationID) .. ']]')
					end	
				end
				returnString = returnString .. '\n| ' .. tconcat(subnations, ' ● ')
				returnString = returnString .. '\n|-'
				local Illustrations = {}
				for j = 0, 5 do
					if RegionData[regionID]['illustrationPathStrs/' .. j] and RegionData[regionID]['illustrationPathStrs/' .. j] ~= '' then
						tinsert(Illustrations,RegionData[regionID]['illustrationPathStrs/' .. j])
					end
				end
				returnString = returnString .. '\n| colspan=4 | Illustrations: ' .. tconcat(Illustrations, ' ● ')
				returnString = returnString .. '\n|-'
			end
		end
	else
		returnString = returnString .. '\n! colspan=4 | 0 Initial [[Regions]]'
		returnString = returnString .. '\n|-'
	end
	
	local directCount = 0
	local directPopulationInMns = 0
	local directGood = {0,0,0}
	local directClaims = {}
	if claimList then
		for i, regionID in ipairs(claimList) do
			if ClaimData[3][NationID][regionID]['initialOwner'] ~= 'true' and RegionData[regionID] then
				directCount = directCount + 1
				directPopulationInMns = directPopulationInMns + (tonumber(RegionData[regionID]['population_Millions']) or 0)
				if RegionData[regionID]['oilResource'] == 'true' then
					directGood[3] = directGood[3] + 1
				elseif RegionData[regionID]['mining'] == 'true' then
					directGood[2] = directGood[2] + 1
				elseif RegionData[regionID]['coreEco'] == 'true' then
					directGood[1] = directGood[1] + 1
				end
				tinsert(directClaims,RegionNameBuilder.buildName({args={regionID, NationID}}))
			end
		end
	end
	
	if directCount > 0 then
		returnString = returnString .. '\n! colspan=4 | + ' .. directCount .. ' Additional Direct [[Claims]]: '
		returnString = returnString .. directGood[1] .. IconModule.Icon({args={'core economic region', bgcolor='DarkSlateGray'}})
		returnString = returnString .. directGood[2] .. IconModule.Icon({args={'resource region'}})
		returnString = returnString .. directGood[3] .. IconModule.Icon({args={'oil region'}})
		returnString = returnString .. '\n|-'
		returnString = returnString .. '\n| colspan=4 | '
		returnString = returnString .. tconcat(directClaims, ' ● ')
		returnString = returnString .. '\n|-'
	else
		returnString = returnString .. '\n! colspan=4 | +0 Additional Direct [[Claims]]'
		returnString = returnString .. '\n|-'
	end
	returnString = returnString .. '\n! colspan=4 | = ' .. (regionCount + directCount) .. ' [[Regions]]: '
	returnString = returnString .. (regionGood[1] + directGood[1]) .. IconModule.Icon({args={'core economic region', bgcolor='DarkSlateGray'}})
	returnString = returnString .. (regionGood[2] + directGood[2]) .. IconModule.Icon({args={'resource region'}})
	returnString = returnString .. (regionGood[3] + directGood[3]) .. IconModule.Icon({args={'oil region'}})
	returnString = returnString .. '\n|-'
	returnString = returnString .. '\n! ' .. IconModule.Icon({args={'pop', bgcolor='DarkSlateGray'}}) .. 'Population in Millions'
	returnString = returnString .. '\n| ' .. round(regionPopulationInMns, 2) .. ' from Initial [[Regions]]' 
	returnString = returnString .. '\n| ' .. round(directPopulationInMns, 2) .. ' from Additional Direct [[Claims]]' 
	returnString = returnString .. '\n| ' .. round(directPopulationInMns + regionPopulationInMns, 2) .. ' Total'
	returnString = returnString .. '\n|-'
	
	local peaceCount = 0
	local peacePopulationInMns = 0
	local peaceGood = {0,0,0}
	local peaceClaims = {}
	for regionID, _ in pairs(PeaceData[2][NationID]) do
		peaceCount = peaceCount + 1
		peacePopulationInMns = peacePopulationInMns + (tonumber(RegionData[regionID]['population_Millions']) or 0)
		if RegionData[regionID]['oilResource'] == 'true' then
			peaceGood[3] = peaceGood[3] + 1
		elseif RegionData[regionID]['mining'] == 'true' then
			peaceGood[2] = peaceGood[2] + 1
		elseif RegionData[regionID]['coreEco'] == 'true' then
			peaceGood[1] = peaceGood[1] + 1
		end
		tinsert(peaceClaims,RegionNameBuilder.buildName({args={regionID, NationID}}))
	end

	returnString = returnString .. '\n! colspan=4 | <big>Maximum Size using only [[Foreign_Relations#Peaceful_Unification|Peaceful Unification]] of non-hostile [[Claims]]</big>'
	returnString = returnString .. '\n|-'
	returnString = returnString .. '\n! ' .. peaceCount .. ' [[Regions]] \n| '
	returnString = returnString .. peaceGood[1] .. IconModule.Icon({args={'core economic region', bgcolor='DarkSlateGray'}})
	returnString = returnString .. peaceGood[2] .. IconModule.Icon({args={'resource region'}})
	returnString = returnString .. peaceGood[3] .. IconModule.Icon({args={'oil region'}})
	returnString = returnString .. '\n! ' .. IconModule.Icon({args={'pop', bgcolor='DarkSlateGray'}}) .. 'Population in Millions'
	returnString = returnString .. '\n| ' .. round(peacePopulationInMns, 2)
	returnString = returnString .. '\n|-'
	returnString = returnString .. '\n| colspan=4 | '
	returnString = returnString .. tconcat(peaceClaims, ' ● ')
	returnString = returnString .. '\n|-'	

	local fullCount = 0
	local fullPopulationInMns = 0
	local fullGood = {0,0,0}
	local fullClaims = {}
	for regionID, _ in pairs(FullData[2][NationID]) do
		fullCount = fullCount + 1
		fullPopulationInMns = fullPopulationInMns + (tonumber(RegionData[regionID]['population_Millions']) or 0)
		if RegionData[regionID]['oilResource'] == 'true' then
			fullGood[3] = fullGood[3] + 1
		elseif RegionData[regionID]['mining'] == 'true' then
			fullGood[2] = fullGood[2] + 1
		elseif RegionData[regionID]['coreEco'] == 'true' then
			fullGood[1] = fullGood[1] + 1
		end
		
		tinsert(fullClaims,RegionNameBuilder.buildName({args={regionID, NationID}}))
	end

	returnString = returnString .. '\n! colspan=4 | <big>Maximum Size using any means.</big>'
	returnString = returnString .. '\n|-'
	returnString = returnString .. '\n! ' .. fullCount .. ' [[Regions]] \n| '
	returnString = returnString .. fullGood[1] .. IconModule.Icon({args={'core economic region', bgcolor='DarkSlateGray'}})
	returnString = returnString .. fullGood[2] .. IconModule.Icon({args={'resource region'}})
	returnString = returnString .. fullGood[3] .. IconModule.Icon({args={'oil region'}})
	returnString = returnString .. '\n! ' .. IconModule.Icon({args={'pop', bgcolor='DarkSlateGray'}}) .. 'Population in Millions'
	returnString = returnString .. '\n| ' .. round(fullPopulationInMns, 2)
	returnString = returnString .. '\n|-'
	returnString = returnString .. '\n| colspan=4 | '
	returnString = returnString .. tconcat(fullClaims, ' ● ')
	returnString = returnString .. '\n|-'	
	
	returnString = returnString .. '\n|-'
	returnString = returnString .. '\n! colspan=4 | Notes'
	returnString = returnString .. '\n|-'
	returnString = returnString .. '\n| colspan=4 | ' .. NationNotes
	returnString = returnString .. '\n|-'
	returnString = returnString .. '\n! colspan=4 | Data Sources'
	returnString = returnString .. '\n|-'
	returnString = returnString .. '\n| colspan=4 | [[TINationTemplate_CSV]] • [[TINationTemplate EN]] • [[TIArmyTemplate CSV]] • [[TIRegionTemplate CSV]] • [[TIRegionTemplate EN]] • [[TIBilateralTemplate CSV]]'
	returnString = returnString .. '\n|-'
	returnString = returnString .. '\n! colspan=4 | Related Pages'
	returnString = returnString .. '\n|-'
	returnString = returnString .. '\n| colspan=4 | [[Nation List]] • [[Region List]] • [[Claim List]] • [[Peaceful Unification List]] • [[Full Unification List]] • [[Nations]] • [[Foreign Relations]]'
	returnString = returnString .. '\n|-'
	
	returnString = returnString .. '\n|}'

	return returnString
end

--endregion

return NationLister