Module:TraitLister/Chances

From Terra Invicta Official Wiki

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

---
---Reads the Trait data files and computes a table of Professions to Trait chances

--region Dependencies
local TraitData = mw.loadData('Module:CSVReader/Trait')
local CouncilorTypeData = mw.loadData('Module:CSVReader/CouncilorType')
--endregion

--region Private constants
local totalGroupCount = 20
--endregion

--region Private member variables
local chanceTable = {}
--endregion

--region Private methods

function getChanceTable()
	local initialChanceTable = {} -- Need this copy for rerolls
	
	-- Initialize table to contain a row for every profession and grouping
	for profession, _ in pairs(CouncilorTypeData) do
		chanceTable[profession] = {}
		initialChanceTable[profession] = {}
		for grouping = 1, totalGroupCount do
			chanceTable[profession][grouping] = {}
			initialChanceTable[profession][grouping] = {}
		end
	end
	
	-- Get the initial chances for every profession and trait.
	for rowID, row in pairs(TraitData) do
		local baseChance = tonumber(row['baseChance'] or 0) or 0
		local grouping = row['grouping']
		if grouping then
			grouping = tonumber(grouping)
		end
		for i = 0, 30 do
			local profession = row['classChance/' .. i .. '/councilorClass']
			if profession and profession ~= '' then 
				local classChance = row['classChance/' .. i .. '/chance']
				if not classChance or classChance == '' or classChance == 'null' or not tonumber(classChance) then
					classChance = baseChance	
				else
					classChance = tonumber(classChance)
				end
				if grouping then
					chanceTable[profession][grouping][rowID] = classChance
					initialChanceTable[profession][grouping][rowID] = classChance
				else
					chanceTable[profession][rowID] = classChance
					initialChanceTable[profession][rowID] = classChance
				end
			end
		end
		for profession, _ in pairs(CouncilorTypeData) do
			if grouping then
				if not chanceTable[profession][grouping][rowID] then
					chanceTable[profession][grouping][rowID] = baseChance
					initialChanceTable[profession][grouping][rowID] = baseChance
				end
			else
				if not chanceTable[profession][rowID] then
					chanceTable[profession][rowID] = baseChance
					initialChanceTable[profession][rowID] = baseChance
				end
			end
		end
	end
	
	-- Normalize trait chances by grouping
	local totalGroupChance = {} -- need this for rerolls
	for profession, _ in pairs(CouncilorTypeData) do
		totalGroupChance[profession] = {}
		for grouping = 1, totalGroupCount do
			totalGroupChance[profession][grouping] = 0
			if chanceTable[profession][grouping] then
				local anyGuaranteed = false
				for _, chance in pairs(initialChanceTable[profession][grouping]) do
					if chance == 100 then
						anyGuaranteed = true
					end
					totalGroupChance[profession][grouping] = totalGroupChance[profession][grouping] + chance
				end
				if anyGuaranteed then
					for trait, chance in pairs(initialChanceTable[profession][grouping]) do
						if chance ~= 100 then
							chanceTable[profession][grouping][trait] = 0
						end
					end
				elseif totalGroupChance[profession][grouping] > 100 then
					for trait, chance in pairs(initialChanceTable[profession][grouping]) do
						chanceTable[profession][grouping][trait] = 100 * chance / totalGroupChance[profession][grouping]
					end
				end
			end
		end
	end
	
	-- Reroll traits
	-- I really really want a second opinion to go through this and check that it makes sense.
	for rowID, row in pairs(TraitData) do
		local rerollTrait = row['rerollTrait']
		if rerollTrait and rerollTrait ~= '' and TraitData[rerollTrait] then
			local rerollTraitBonus = tonumber(row['rerollTraitBonus'] or 0) or 0
			local grouping = row['grouping']
			if grouping then
				grouping = tonumber(grouping)
			end
			for profession, _ in pairs(CouncilorTypeData) do
				local rowIDChance = 0
				if grouping then
					rowIDChance = chanceTable[profession][grouping][rowID]
				else
					rowIDChance = chanceTable[profession][rowID]
				end
				
				local rerollTraitGrouping = TraitData[rerollTrait]['grouping']
				if rerollTraitGrouping then
					rerollTraitGrouping = tonumber(rerollTraitGrouping)
				end
				local rerollTraitRerollChance = 0
				if rerollTraitGrouping then
					rerollTraitRerollChance = initialChanceTable[profession][rerollTraitGrouping][rerollTrait]
				else
					rerollTraitRerollChance = initialChanceTable[profession][rerollTrait]
				end
				rerollTraitRerollChance = rerollTraitRerollChance + rerollTraitBonus
				
				if rerollTraitBonus < 0 then
					local rerollTraitRemovalChance = rowIDChance * (100 - rerollTraitRerollChance) / 100
					if rerollTraitGrouping then
						chanceTable[profession][rerollTraitGrouping][rerollTrait] = chanceTable[profession][rerollTraitGrouping][rerollTrait] * (100 - rerollTraitRemovalChance) / 100
					else
						chanceTable[profession][rerollTrait] = chanceTable[profession][rerollTrait] * (100 - rerollTraitRemovalChance) / 100
					end
				else
					local rerollTraitAdditionChance = rowIDChance * rerollTraitRerollChance / 100
					if rerollTraitGrouping then
						if totalGroupChance[profession][rerollTraitGrouping] < 100 then
							chanceTable[profession][rerollTraitGrouping][rerollTrait] = chanceTable[profession][rerollTraitGrouping][rerollTrait] + (100 - totalGroupChance[profession][rerollTraitGrouping]) * rerollTraitAdditionChance / 100
						end
					else
						chanceTable[profession][rerollTrait] = chanceTable[profession][rerollTrait] + (100 - chanceTable[profession][rerollTrait]) * rerollTraitAdditionChance / 100
					end
				end
			end
		end
	end
	
	-- Transfer data from trait groupings
	for profession, _ in pairs(CouncilorTypeData) do
		for grouping = 1, totalGroupCount do	
			if chanceTable[profession][grouping] then
				for trait, chance in pairs(chanceTable[profession][grouping]) do
					chanceTable[profession][trait] = chance
				end
			end
		end
	end
	
	return chanceTable
end

--endregion

--region Public methods
--endregion

return getChanceTable()