<commit_before>function HeroSelection:CheckEndHeroSelection()
	local canEnd = false --HeroSelection:GetState() < HERO_SELECTION_PHASE_END and GameRules:IsCheatMode()
	for team,_v in pairs(PlayerTables:GetAllTableValuesForReadOnly("hero_selection")) do
		for plyId,v in pairs(_v) do
			if v.status ~= "picked" then
				canEnd = false
				break
			end
		end
	end
	if canEnd then
		HeroSelection:StartStateStrategy()
	end
end

function HeroSelection:PreformRandomForNotPickedUnits()
	for team,_v in pairs(PlayerTables:GetAllTableValuesForReadOnly("hero_selection")) do
		for plyId,v in pairs(_v) do
			if v.status ~= "picked" then
				HeroSelection:PreformPlayerRandom(plyId)
			end
		end
	end
end

function HeroSelection:GetSelectedHeroName(playerId)
	local status = HeroSelection:GetPlayerStatus(playerId)
	if status and status.status == "picked" then
		return status.hero
	end
end

function HeroSelection:IsHeroSelected(heroName)
	for team,_v in pairs(PlayerTables:GetAllTableValuesForReadOnly("hero_selection")) do
		for plyId,v in pairs(_v) do
			if v.hero == heroName and v.status == "picked" then
				return true
			end
		end
	end
	return false
end

function HeroSelection:GetSelectedHeroPlayer(hero)
	for team,_v in pairs(PlayerTables:GetAllTableValuesForReadOnly("hero_selection")) do
		for plyId,v in pairs(_v) do
			if v.hero == hero and v.status == "picked" then
				return plyId
			end
		end
	end
end

function HeroSelection:ExtractHeroStats(heroTable)
	local attributes = {
		attribute_primary = _G[heroTable.AttributePrimary],
		attribute_base_0 = heroTable.AttributeBaseStrength,
		attribute_base_1 = heroTable.AttributeBaseAgility,
		attribute_base_2 = heroTable.AttributeBaseIntelligence,
		attribute_gain_0 = heroTable.AttributeStrengthGain,
		attribute_gain_1 = heroTable.AttributeAgilityGain,
		attribute_gain_2 = heroTable.AttributeIntelligenceGain,
		damage_min = tonumber(heroTable.AttackDamageMin),
		damage_max = tonumber(heroTable.AttackDamageMax),
		movespeed = heroTable.MovementSpeed,
		attackrate = heroTable.AttackRate,
		armor = heroTable.ArmorPhysical,
		team = heroTable.Team
	}
	attributes.damage_min = attributes.damage_min + attributes["attribute_base_" .. attributes.attribute_primary]
	attributes.damage_max = attributes.damage_max + attributes["attribute_base_" .. attributes.attribute_primary]

	local armorForFirstLevel = CalculateBaseArmor({
		value = heroTable.AttributeBaseIntelligence,
		isPrimary = heroTable.AttributePrimary == "DOTA_ATTRIBUTE_INTELLECT",
	})
	attributes.armor = attributes.armor + armorForFirstLevel
	return attributes
end

function TransformUnitClass(unit, classTable, skipAbilityRemap)
	if not skipAbilityRemap then
		for i = 0, unit:GetAbilityCount() - 1 do
			if unit:GetAbilityByIndex(i) then
				unit:RemoveAbility(unit:GetAbilityByIndex(i):GetName())
			end
		end
		if Options:IsEquals("EnableAbilityShop", false) and Options:IsEquals("EnableRandomAbilities", false) then
			for i = 1, 24 do
				if classTable["Ability" .. i] and classTable["Ability" .. i] ~= "" then
					PrecacheItemByNameAsync(classTable["Ability" .. i], function() end)
					unit:AddNewAbility(classTable["Ability" .. i])
				end
			end
		end
	end

	for key, value in pairs(classTable) do
		if key == "Level" then
			unit:SetLevel(value)
		elseif key == "Model" then
			unit.ModelOverride = value
			unit:SetModel(value)
			unit:SetOriginalModel(value)
		elseif key == "ModelScale" then
			unit:SetModelScale(value)
		elseif key == "ArmorPhysical" then
			unit:SetPhysicalArmorBaseValue(value)
		elseif key == "MagicalResistance" then
			unit:SetBaseMagicalResistanceValue(value)
		elseif key == "AttackCapabilities" then
			unit:SetAttackCapability(_G[value])
		elseif key == "AttackDamageMin" then
			unit:SetBaseDamageMin(value)
		elseif key == "AttackDamageMax" then
			unit:SetBaseDamageMax(value)
		elseif key == "AttackRate" then
			unit:SetBaseAttackTime(value)
			unit:SetNetworkableEntityInfo("AttackRate", value)
		elseif key == "AttackAcquisitionRange" then
			unit:SetAcquisitionRange(value)
		elseif key == "ProjectileModel" then
			unit:SetRangedProjectileName(value)
		elseif key == "AttributePrimary" then
			Timers:CreateTimer(2/30, function()
				unit:SetPrimaryAttribute(_G[value])
				unit:CalculateStatBonus()

				local illusionParent = unit:GetIllusionParent()
				if IsValidEntity(illusionParent) then<commit_msg>chore(hero_selection): use NextTick to delay attribute changing (#449)<commit_after>function HeroSelection:CheckEndHeroSelection()
	local canEnd = false --HeroSelection:GetState() < HERO_SELECTION_PHASE_END and GameRules:IsCheatMode()
	for team,_v in pairs(PlayerTables:GetAllTableValuesForReadOnly("hero_selection")) do
		for plyId,v in pairs(_v) do
			if v.status ~= "picked" then
				canEnd = false
				break
			end
		end
	end
	if canEnd then
		HeroSelection:StartStateStrategy()
	end
end

function HeroSelection:PreformRandomForNotPickedUnits()
	for team,_v in pairs(PlayerTables:GetAllTableValuesForReadOnly("hero_selection")) do
		for plyId,v in pairs(_v) do
			if v.status ~= "picked" then
				HeroSelection:PreformPlayerRandom(plyId)
			end
		end
	end
end

function HeroSelection:GetSelectedHeroName(playerId)
	local status = HeroSelection:GetPlayerStatus(playerId)
	if status and status.status == "picked" then
		return status.hero
	end
end

function HeroSelection:IsHeroSelected(heroName)
	for team,_v in pairs(PlayerTables:GetAllTableValuesForReadOnly("hero_selection")) do
		for plyId,v in pairs(_v) do
			if v.hero == heroName and v.status == "picked" then
				return true
			end
		end
	end
	return false
end

function HeroSelection:GetSelectedHeroPlayer(hero)
	for team,_v in pairs(PlayerTables:GetAllTableValuesForReadOnly("hero_selection")) do
		for plyId,v in pairs(_v) do
			if v.hero == hero and v.status == "picked" then
				return plyId
			end
		end
	end
end

function HeroSelection:ExtractHeroStats(heroTable)
	local attributes = {
		attribute_primary = _G[heroTable.AttributePrimary],
		attribute_base_0 = heroTable.AttributeBaseStrength,
		attribute_base_1 = heroTable.AttributeBaseAgility,
		attribute_base_2 = heroTable.AttributeBaseIntelligence,
		attribute_gain_0 = heroTable.AttributeStrengthGain,
		attribute_gain_1 = heroTable.AttributeAgilityGain,
		attribute_gain_2 = heroTable.AttributeIntelligenceGain,
		damage_min = tonumber(heroTable.AttackDamageMin),
		damage_max = tonumber(heroTable.AttackDamageMax),
		movespeed = heroTable.MovementSpeed,
		attackrate = heroTable.AttackRate,
		armor = heroTable.ArmorPhysical,
		team = heroTable.Team
	}
	attributes.damage_min = attributes.damage_min + attributes["attribute_base_" .. attributes.attribute_primary]
	attributes.damage_max = attributes.damage_max + attributes["attribute_base_" .. attributes.attribute_primary]

	local armorForFirstLevel = CalculateBaseArmor({
		value = heroTable.AttributeBaseIntelligence,
		isPrimary = heroTable.AttributePrimary == "DOTA_ATTRIBUTE_INTELLECT",
	})
	attributes.armor = attributes.armor + armorForFirstLevel
	return attributes
end

function TransformUnitClass(unit, classTable, skipAbilityRemap)
	if not skipAbilityRemap then
		for i = 0, unit:GetAbilityCount() - 1 do
			if unit:GetAbilityByIndex(i) then
				unit:RemoveAbility(unit:GetAbilityByIndex(i):GetName())
			end
		end
		if Options:IsEquals("EnableAbilityShop", false) and Options:IsEquals("EnableRandomAbilities", false) then
			for i = 1, 24 do
				if classTable["Ability" .. i] and classTable["Ability" .. i] ~= "" then
					PrecacheItemByNameAsync(classTable["Ability" .. i], function() end)
					unit:AddNewAbility(classTable["Ability" .. i])
				end
			end
		end
	end

	for key, value in pairs(classTable) do
		if key == "Level" then
			unit:SetLevel(value)
		elseif key == "Model" then
			unit.ModelOverride = value
			unit:SetModel(value)
			unit:SetOriginalModel(value)
		elseif key == "ModelScale" then
			unit:SetModelScale(value)
		elseif key == "ArmorPhysical" then
			unit:SetPhysicalArmorBaseValue(value)
		elseif key == "MagicalResistance" then
			unit:SetBaseMagicalResistanceValue(value)
		elseif key == "AttackCapabilities" then
			unit:SetAttackCapability(_G[value])
		elseif key == "AttackDamageMin" then
			unit:SetBaseDamageMin(value)
		elseif key == "AttackDamageMax" then
			unit:SetBaseDamageMax(value)
		elseif key == "AttackRate" then
			unit:SetBaseAttackTime(value)
			unit:SetNetworkableEntityInfo("AttackRate", value)
		elseif key == "AttackAcquisitionRange" then
			unit:SetAcquisitionRange(value)
		elseif key == "ProjectileModel" then
			unit:SetRangedProjectileName(value)
		elseif key == "AttributePrimary" then
			Timers:NextTick(function()
				unit:SetPrimaryAttribute(_G[value])
				unit:CalculateStatBonus()

				local illusionParent = unit:GetIllusionParent()
				if IsValidEntity(illusionParent) then
{'fraction_non_alphanumeric': 0.09014532243415077, 'fraction_numerical': 0.003178928247048138, 'mean_word_length': 5.544576523031203, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3397037', 'n_tokens_mistral': 3109, 'n_tokens_neox': 2817, 'n_words': 613}