Module:OrgLister

From Terra Invicta Official Wiki

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

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

--region Dependencies
local RestrictionChecker = require('Module:RestrictionChecker')
local IconModule = require('Module:Icon')
local TVModule = require('Module:TV')
local OrgIcon = mw.loadData('Module:OrgLister/Icon')

local OrgData = mw.loadData('Module:CSVReader/Org')
local MapRegionToRegion = mw.loadData('Module:RegionLister/MapRegions')

local MissionNames = mw.loadData('Module:ENReader/Mission')
local OrgNames = mw.loadData('Module:ENReader/Org')
local RegionNames = mw.loadData('Module:ENReader/Region')
local TechNames = mw.loadData('Module:ENReader/Tech')
local TraitNames = mw.loadData('Module:ENReader/Trait')
--endregion

--region Private constants
local slen = string.len
local sfind = string.find
local slower = string.lower
local ssub = string.sub
local ScienceCategories = {
	Energy = 'energy',
	InformationScience='information',
	LifeScience='life',
	Materials='material',
	MilitaryScience='military',
	SocialScience='social',
	SpaceScience='space',
	Xenology='xenology'
}
local attributeTable = {
	[1] = 'persuasion',
	[2] = 'investigation',
	[3] = 'espionage',
	[4] = 'command',
	[5] = 'administration',
	[6] = 'science',
	[7] = 'security',
}
local NPBTable = {
	[1] = 'economy',
	[2] = 'welfare',
	[3] = 'environment',
	[4] = 'knowledge',
	[5] = 'government priority',
	[6] = 'unity',
	[7] = 'oppression',
	[8] = 'funding',
	[9] = 'spoils',
	[10] = 'combined spaceflight',
	[11] = 'mission control priority',
	[12] = 'combined military',
}
local incomeTable = {
	[1] = 'money',
	[2] = 'influence',
	[3] = 'ops',
	[4] = 'boost',
	[5] = 'mc',
	[6] = 'research',
}
local costTable = {
	[1] = 'money',
	[2] = 'influence',
	[3] = 'ops',
	[4] = 'boost',
}
--endregion



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

--region Private methods


--endregion

--region Public methods
function OrgLister.ListRestrictedOrgs(frame)
	local focus = frame.args['Focus']
	if focus and focus ~= '' then
		focus = mw.text.trim(slower(focus))
	end
	return OrgLister.ListOrgs(frame.args, nil, nil, focus)
end

function OrgLister.ListBasicOrgs()
	return OrgLister.ListOrgs({})
end

function OrgLister.ListDestroyOrgs()
	return OrgLister.ListOrgs({},'Destroy',true)
end

function OrgLister.ListAntiDestroyOrgs()
	return OrgLister.ListOrgs({},'Destroy',false)
end

function OrgLister.ListResistOrgs()
	return OrgLister.ListOrgs({},'Resist',true)
end

function OrgLister.ListAntiResistOrgs()
	return OrgLister.ListOrgs({},'Resist',false)
end

function OrgLister.ListEscapeOrgs()
	return OrgLister.ListOrgs({},'Escape',true)
end

function OrgLister.ListAntiEscapeOrgs()
	return OrgLister.ListOrgs({},'Escape',false)
end

function OrgLister.ListExploitOrgs()
	return OrgLister.ListOrgs({},'Exploit',true)
end

function OrgLister.ListAntiExploitOrgs()
	return OrgLister.ListOrgs({},'Exploit',false)
end

function OrgLister.ListCooperateOrgs()
	return OrgLister.ListOrgs({},'Cooperate',true)
end

function OrgLister.ListAntiCooperateOrgs()
	return OrgLister.ListOrgs({},'Cooperate',false)
end

function OrgLister.ListAppeaseOrgs()
	return OrgLister.ListOrgs({},'Appease',true)
end

function OrgLister.ListAntiAppeaseOrgs()
	return OrgLister.ListOrgs({},'Appease',false)
end

function OrgLister.ListSubmitOrgs()
	return OrgLister.ListOrgs({},'Submit',true)
end

function OrgLister.ListAntiSubmitOrgs()
	return OrgLister.ListOrgs({},'Submit',false)
end

function OrgLister.ListAlienOrgs()
	return OrgLister.ListOrgs({},'Alien',true)
end

function OrgLister.ListAntiAlienOrgs()
	return OrgLister.ListOrgs({},'Alien',false)
end


---@param restrictionsTable table of restrictions
---@param forFaction which faction to focus on, if any.
---- Use the ideology, e.g. Humanity First = Destroy
---@param goodAffinity boolean whether to show the affinities or restricted.
---@return wiki table of Orgs
function OrgLister.ListOrgs(restrictionsTable, forFaction, goodAffinity, focus)
	local attributeFocus = 0
	local NPBFocus = 0
	if focus and focus ~= '' then
		for i, attribute in ipairs(attributeTable) do
			if attribute == focus then
				attributeFocus = i
			end
		end
		for i, NPB in ipairs(NPBTable) do
			if NPB == focus then
				NPBFocus = i
			end
		end
	end
	
	local returnString = '{| class="wikitable sortable mw-collapsible" style="text-align: center;"'
	returnString = returnString .. '\n|-'
	returnString = returnString .. '\n! Org<br>Stars'
	if attributeFocus ~= 0 then
		returnString = returnString .. '\n! ' .. TVModule.TV({args={attributeTable[attributeFocus], '', 'true'}}) 
	elseif NPBFocus ~= 0 then
		returnString = returnString .. '\n! ' .. TVModule.TV({args={NPBTable[NPBFocus], '', 'true'}}) 
	end
	returnString = returnString .. '\n! Stats and [[Missions]]'
	returnString = returnString .. '\n! Bonuses and [[Resources|Resource]] Incomes'
	returnString = returnString .. '\n! Affinities and Requirements'
	returnString = returnString .. '\n! Purchase Cost'
	returnString = returnString .. '\n|-'
	
	for rowID, row in pairs(OrgData) do
		if (not row['disable']) or row['disable'] ~= 'true' then
			local affinities = {}
			for i = 0, 2 do
				local affinity = row['affinities/' .. i]
				if affinity and affinity ~= '' then
					affinities[affinity] = true
				end
			end
			local restricted = {}
			for i = 0, 6 do
				local restrict = row['restricted/' .. i]
				if restrict and restrict ~= '' then
					restricted[restrict] = true
				end
			end
			
			if RestrictionChecker.AllPass(restrictionsTable, row) and (not forFaction or forFaction == '' or (affinities[forFaction] and goodAffinity) or (restricted[forFaction] and not goodAffinity)) then
				local orgDisplayName = (OrgNames['TIOrgTemplate.displayName.' .. rowID] or rowID)
				if ssub(orgDisplayName,1,6) == 'Random' then
					orgDisplayName = 'Random<br>' .. ssub(orgDisplayName,7)	
				end
				local oicon = OrgIcon[row['iconResource'] or ''] or '' 
				returnString = returnString .. '\n| ' .. oicon .. ' ' .. orgDisplayName .. '<br>' .. IconModule.Icon({args={'star'}})
				if tonumber(row['tier']) > 1 then
					returnString = returnString .. IconModule.Icon({args={'star'}})
				end
				if tonumber(row['tier']) > 2 then
					returnString = returnString .. IconModule.Icon({args={'star'}})
				end

				local chanceAttributes = {tonumber(row['chancePersuasion']) or 0, tonumber(row['chanceInvestigation']) or 0, tonumber(row['chanceEspionage']) or 0, tonumber(row['chanceCommand']) or 0, tonumber(row['chanceAdministration']) or 0, tonumber(row['chanceScience']) or 0, tonumber(row['chanceSecurity']) or 0}
				local baseAttributes = {tonumber(row['persuasion']) or 0, tonumber(row['investigation']) or 0, tonumber(row['espionage']) or 0, tonumber(row['command']) or 0, tonumber(row['administration']) or 0, tonumber(row['science']) or 0, tonumber(row['security']) or 0}
				local randAttributes = {tonumber(row['randPersuasion']) or 0, tonumber(row['randInvestigation']) or 0, tonumber(row['randEspionage']) or 0, tonumber(row['randCommand']) or 0, tonumber(row['randAdministration']) or 0, tonumber(row['randScience']) or 0, tonumber(row['randSecurity']) or 0}

				local chanceNPB = {tonumber(row['chanceEconomyBonus']) or 0,tonumber(row['chanceWelfareBonus']) or 0,tonumber(row['chanceEnvironmentBonus']) or 0,tonumber(row['chanceKnowledgeBonus']) or 0,tonumber(row['chanceGovernmentBonus']) or 0,tonumber(row['chanceUnityBonus']) or 0,tonumber(row['chanceOppressionBonus']) or 0,tonumber(row['chanceSpaceDevBonus']) or 0,tonumber(row['chanceSpoilsBonus']) or 0,tonumber(row['chanceSpaceflightBonus']) or 0,tonumber(row['chanceMCBonus']) or 0,tonumber(row['chanceMilitaryBonus']) or 0}
				local baseNPB = {tonumber(row['economyBonus']) or 0,tonumber(row['welfareBonus']) or 0,tonumber(row['environmentBonus']) or 0,tonumber(row['knowledgeBonus']) or 0,tonumber(row['governmentBonus']) or 0,tonumber(row['unityBonus']) or 0,tonumber(row['oppressionBonus']) or 0,tonumber(row['spaceDevBonus']) or 0,tonumber(row['spoilsBonus']) or 0,tonumber(row['spaceflightBonus']) or 0,tonumber(row['MCBonus']) or 0,tonumber(row['militaryBonus']) or 0}
				local randNPB = {tonumber(row['randEconomyBonus']) or 0,tonumber(row['randWelfareBonus']) or 0,tonumber(row['randEnvironmentBonus']) or 0,tonumber(row['randKnowledgeBonus']) or 0,tonumber(row['randGovernmentBonus']) or 0,tonumber(row['randUnityBonus']) or 0,tonumber(row['randOppressionBonus']) or 0,tonumber(row['randSpaceDevBonus']) or 0,tonumber(row['randSpoilsBonus']) or 0,tonumber(row['randSpaceflightBonus']) or 0,tonumber(row['randMCBonus']) or 0,tonumber(row['randMilitaryBonus']) or 0}
				
				if attributeFocus ~= 0 then
					returnString = returnString .. '\n| ' 
					if chanceAttributes[attributeFocus] > 0 then
						local valueString = ''
						if chanceAttributes[attributeFocus] < 100 then
							valueString = chanceAttributes[attributeFocus] .. '%: '
						end
						valueString = valueString .. baseAttributes[attributeFocus]
						if randAttributes[attributeFocus] > 0 then
							valueString = valueString .. ' to ' .. (baseAttributes[attributeFocus] + randAttributes[attributeFocus])
						end
						local sortValue = chanceAttributes[attributeFocus] * (baseAttributes[attributeFocus] + randAttributes[attributeFocus] / 2)
						returnString = returnString .. 'data-sort-value=' .. sortValue .. '|' .. TVModule.TV({args={attributeTable[attributeFocus], valueString, 'true'}}) .. ' '
					end
				elseif NPBFocus ~= 0 then
					returnString = returnString .. '\n| ' 
					if chanceNPB[NPBFocus] > 0 then
						local valueString = ''
						if chanceNPB[NPBFocus] < 100 then
							valueString = chanceNPB[NPBFocus] .. '%: '
						end
						valueString = valueString .. (baseNPB[NPBFocus] * 100) .. '%'
						if randNPB[NPBFocus] > 0 then
							valueString = valueString .. ' to ' .. ((baseNPB[NPBFocus] + randNPB[NPBFocus]) * 100) .. '%'
						end
						local sortValue = chanceNPB[NPBFocus] * (baseNPB[NPBFocus] + randNPB[NPBFocus] / 2)
						returnString = returnString .. 'data-sort-value=' .. sortValue .. '|' .. TVModule.TV({args={NPBTable[NPBFocus], valueString, 'true'}}) .. ' '
					end
				end

				returnString = returnString .. '\n| ' 
				for i = 1, 7 do
					if chanceAttributes[i] > 0 then
						local valueString = ''
						if chanceAttributes[i] < 100 then
							valueString = chanceAttributes[i] .. '%: '
						end
						valueString = valueString .. baseAttributes[i]
						if randAttributes[i] > 0 then
							valueString = valueString .. ' to ' .. (baseAttributes[i] + randAttributes[i])
						end
						returnString = returnString .. TVModule.TV({args={attributeTable[i], valueString, 'true'}}) .. ' '
					end
				end
				
				for i = 0, 3 do
					local missionName = row['missionsGrantedNames/' .. i]
					if missionName and missionName ~= '' then
						returnString = returnString .. '<br>' .. IconModule.MissionIcon({args={missionName}}) .. '[[' .. MissionNames['TIMissionTemplate.displayName.' .. missionName] .. ']]'
					end
				end
				
		    	returnString = returnString .. '\n|'
				
				if row['grantsMarked'] == "true" then
					returnString = returnString .. 'Prominent<br>'
				end
				
				for i = 1, 12 do
					if chanceNPB[i] > 0 then
						local valueString = ''
						if chanceNPB[i] < 100 then
							valueString = chanceNPB[i] .. '%: '
						end
						valueString = valueString .. (baseNPB[i] * 100) .. '%'
						if randNPB[i] > 0 then
							valueString = valueString .. ' to ' .. ((baseNPB[i] + randNPB[i]) * 100) .. '%'
						end
						returnString = returnString .. TVModule.TV({args={NPBTable[i], valueString, 'true'}}) .. ' '
					end
				end
				
				local techBonuses = {row['techBonuses/0/category'], row['techBonuses/0/bonus']}
				if techBonuses[1] and techBonuses[1] ~= '' then
					returnString = returnString .. TVModule.TV({args={ScienceCategories[techBonuses[1]], tostring(tonumber(techBonuses[2]) * 100) .. '%', 'true'}}) .. ' '
				end
				if (tonumber(row['projectsGranted']) or 0) > 0 then
					returnString = returnString .. TVModule.TV({args={'projects', row['projectsGranted'],'true'}}) .. ' '
				end
				if (tonumber(row['chanceMiningBonus']) or 0) > 0 then
					local valueString = ''
					if tonumber(row['chanceMiningBonus']) < 100 then
						valueString = row['chanceMiningBonus'] .. '%: '
					end
					valueString = valueString .. tostring(tonumber(row['miningBonus']) * 100) .. '%'
					if (tonumber(row['randMiningBonus']) or 0) > 0 then
						valueString = valueString .. ' to ' .. tostring((tonumber(row['miningBonus']) + (tonumber(row['randMiningBonus']) or 0)) * 100) .. '%' 
					end
					returnString = returnString .. TVModule.TV({args={'mining', valueString, 'true'}}) .. ' '
				end
				
				local chanceIncomes = {tonumber(row['chanceIncomeMoney']) or 0,tonumber(row['chanceIncomeInfluence']) or 0,tonumber(row['chanceIncomeOps']) or 0,tonumber(row['chanceIncomeBoost']) or 0,tonumber(row['chanceIncomeMissionControl']) or 0,tonumber(row['chanceIncomeResearch']) or 0}
				local baseIncomes = {tonumber(row['incomeMoney']) or 0,tonumber(row['incomeInfluence']) or 0,tonumber(row['incomeOps']) or 0,tonumber(row['incomeBoost']) or 0,tonumber(row['incomeMissionControl']) or 0,tonumber(row['incomeResearch']) or 0}
				local randIncomes = {tonumber(row['randIncomeMoney']) or 0,tonumber(row['randIncomeInfluence']) or 0,tonumber(row['randIncomeOps']) or 0,tonumber(row['randIncomeBoost']) or 0,tonumber(row['randIncomeMissionControl']) or 0,tonumber(row['randIncomeResearch']) or 0}
				for i = 1, 6 do
					if chanceIncomes[i] > 0 then
						local valueString = ''
						if chanceIncomes[i] < 100 then
							valueString = chanceIncomes[i] .. '%: '
						end
						valueString = valueString .. baseIncomes[i]
						if randIncomes[i] > 0 then
							valueString = valueString .. ' to ' .. (baseIncomes[i] + randIncomes[i])
						end
						returnString = returnString .. TVModule.TV({args={incomeTable[i], valueString, 'true'}}) .. ' '
					end
				end
				
				returnString = returnString .. '\n|'
				local notDoneHeader = true
				for ideo, _ in pairs(affinities) do
					if notDoneHeader then
						returnString = returnString .. '<span style="color:green;">Affinity: </span>'
						notDoneHeader = false
					end
					returnString = returnString .. IconModule.Icon({args={ideo}})
				end
				if not notDoneHeader then
					returnString = returnString .. '<br>'
				end
				
				notDoneHeader = true
				for ideo, _ in pairs(restricted) do
					if notDoneHeader then
						returnString = returnString .. '<span style="color:red;">Banned: </span>'
						notDoneHeader = false
					end
					returnString = returnString .. IconModule.Icon({args={ideo}})
				end
				if not notDoneHeader then
					returnString = returnString .. '<br>'
				end
				
				local req = row['requiredTechName']
				if req ~= '' then
					returnString = returnString .. '[[' .. req .. '|' .. (TechNames['TITechTemplate.displayName.' .. req] or req) .. ']]<br>'
				end
				if row['requiresNationality'] ~= '' and row['requiresNationality'] ~= 'false' then
					returnString = returnString .. (RegionNames['TIRegionTemplate.displayName.' .. MapRegionToRegion[row['homeRegionMapTemplateName']]] or 'Error: Region Not Found "' .. row['homeRegionMapTemplateName']) .. '<br>'
				end
				req = row['requiredOwnerTraits/0']
				if req ~= '' then
					returnString = returnString .. (TraitNames['TITraitTemplate.displayName.' .. req] or req) .. '<br>'
				end
				req = row['prohibitedOwnerTraits/0']
				if req ~= '' then
					returnString = returnString .. 'NOT ' .. (TraitNames['TITraitTemplate.displayName.' .. req] or req) .. '<br>'
				end
				req = row['allowedOnMarket']
				if req ~= 'true' then
					returnString = returnString .. 'Not on Market'
				end
				
				returnString = returnString .. '\n|'
				local baseCosts = {tonumber(row['costMoney']) or 0,tonumber(row['costInfluence']) or 0,tonumber(row['costOps']) or 0,tonumber(row['costBoost']) or 0}
				local randCosts = {tonumber(row['randCostMoney']) or 0,tonumber(row['randCostInfluence']) or 0,tonumber(row['randCostOps']) or 0,tonumber(row['randCostBoost']) or 0}
				for i = 1, 4 do
					if baseCosts[i] > 0 or randCosts[i] > 0 then
						local valueString = ''
						if baseCosts[i] > 0 then
							valueString = baseCosts[i]
						else
							valueString = '0'
						end
						if randCosts[i] > 0 then
							valueString = valueString .. ' to ' .. (baseCosts[i] + randCosts[i])
						end
						returnString = returnString .. TVModule.TV({args={costTable[i], valueString, 'true'}}) .. ' '
					end
				end
		    	returnString = returnString .. '\n|-'
		    end
    	end
	end
	returnString = returnString .. '\n|}'
	
	return returnString
end

--endregion

return OrgLister