--Various functions
------------------------------------------------------------------------------------------------------- 
-- last modification: M56_a
if not versionDCE then versionDCE = {} end
versionDCE["UTIL_Functions.lua"] = "1.12.43"
------------------------------------------------------------------------------------------------------- 
-- cleanCode_b						
-- adjustment_d						(d:CheckConfModMaster )(c: fire playable_m from conf_mod)
-- debug_c							Angle et Bearing des statics sur PA
-- miguel21 modification M56_a		AssignCallnameSquad
-- miguel21 modification M53_a		automatic update of the conf_mod file
-- miguel21 modification M49_b		big central db_loadout (b: routine Check)
-- miguel21 modification M47_c		keeps the history of the campaign files (c: save debugging information during mission generation)
-- miguel21 modification M43		assignation des numeros de parking du type C08 
-- Miguel21 modification M41		Scratchpad written in the Sratchpad file, if this modul is installed
-- miguel21 modification M38_e		(e: helps to balance the game (type "Z" in firstmission.bat))(d: checks only the right  theatre) (c: Check conf_mod) Check and Help CampaignMaker
-- miguel21 modification M34_o		custom FrequenceRadio (mno: freq group bug)(i  3 frequency bands)(g: VHF helicopter)(h: bug Gazelle)
-- Miguel21 modification M17_f		Option F-14B & All AddPropAircraft
------------------------------------------------------------------------------------------------------- 




--function to return txt whith carriage return
function StringToTxt(text)
	text = string.gsub(text, "\\n", "\n")	
	return text
end

--function to return txt whith carriage return for Sratchpad
-- Miguel21 modification M41
function StringToTxtBrief(text)
	if type(text) == "string" then
		text = string.gsub(text, "\\n", " \\\n")		
		return text
	else
		return  text
	end
end

--function to turn a table into a string
function TableSerialization(t, i)
	
	local text = "{\n"
	local tab = ""
	for n = 1, i + 1 do																	--controls the indent for the current text line
		tab = tab .. "\t"
	end
	for k,v in pairs(t) do
		if type(k) == "string" then
			text = text .. tab .. "['" .. k .. "'] = "
		else
			text = text .. tab .. "[" .. k .. "] = "
		end
		if type(v) == "string" then
			text = text .. "'" .. v .. "',\n"
		elseif type(v) == "number" then
			text = text .. v .. ",\n"
		elseif type(v) == "table" then
			text = text .. TableSerialization(v, i + 1)
		elseif type(v) == "boolean" then
			if v == true then
				text = text .. "true,\n"
			else
				text = text .. "false,\n"
			end
		elseif type(v) == "function" then
			text = text .. v .. ",\n"
		elseif v == nil then
			text = text .. "nil,\n"
		end
	end
	tab = ""
	for n = 1, i do																		--indent for closing bracket is one less then previous text line
		tab = tab .. "\t"
	end
	if i == 0 then
		text = text .. tab .. "}\n"														--the last bracket should not be followed by an comma
	else
		text = text .. tab .. "},\n"													--all brackets with indent higher than 0 are followed by a comma
	end
	return text
end


--function to make a deep copy of a table
function deepcopy(orig)
    local orig_type = type(orig)
    local copy
    if orig_type == 'table' then
        copy = {}
        for orig_key, orig_value in next, orig, nil do
            copy[deepcopy(orig_key)] = deepcopy(orig_value)
        end
        setmetatable(copy, deepcopy(getmetatable(orig)))
    else -- number, string, boolean, etc
        copy = orig
    end
    return copy
end


--function to return heading between two vector2 points
function GetHeading(p1, p2)
	local deltax = p2.x - p1.x
	local deltay = p2.y - p1.y
	if (deltax > 0) and (deltay == 0) then
		return 0
	elseif (deltax > 0) and (deltay > 0) then
		return math.deg(math.atan(deltay / deltax))
	elseif (deltax == 0) and (deltay > 0) then
		return 90
	elseif (deltax < 0) and (deltay > 0) then
		return 90 - math.deg(math.atan(deltax / deltay))
	elseif (deltax < 0) and (deltay == 0) then
		return 180
	elseif (deltax < 0) and (deltay < 0) then
		return 180 + math.deg(math.atan(deltay / deltax))
	elseif (deltax == 0) and (deltay < 0) then
		return 270
	elseif (deltax > 0) and (deltay < 0) then
		return 270 - math.deg(math.atan(deltax / deltay))
	else
		return 0
	end
end

--https://github.com/mrSkortch/MissionScriptingTools/releases
--- Returns heading of given unit.
-- @tparam Unit unit unit whose heading is returned.
-- @param rawHeading
-- @treturn number heading of the unit, in range
-- of 0 to 2*pi.
function getHeadingByPos(unit)
	local unitpos = unit:getPosition()
	if unitpos then
		local Heading = math.atan2(unitpos.x.z, unitpos.x.x)
		if Heading < 0 then
			Heading = Heading + 2*math.pi	-- put heading in range of 0 to 2*pi
		end
		return Heading
	end
end
	
function HeadingDegToRad(angle)
	angle = angle % 360 							-- garde le reste de 360
	return angle * 0.0174532925				-- 0,0174532925
end
	
	
--function to return the angle between two headings
function GetDeltaHeading(h1, h2)
	local delta = h2 - h1
	if delta > 180 then
		delta = delta - 360
	elseif delta <= -180 then
		delta = delta + 360
	end
	return delta
end


--function to return distance between two vector2 points
function GetDistance(p1, p2)
	local deltax = p2.x - p1.x
	local deltay = p2.y - p1.y
	return math.sqrt(math.pow(deltax, 2) + math.pow(deltay, 2))
end


--function to return a new point offset from an initial point
function GetOffsetPoint(point, heading, distance)
	return {
		x = point.x + math.cos(math.rad(heading)) * distance,
		y = point.y + math.sin(math.rad(heading)) * distance
	}
end


--function to return closest distance of point p3 to the line p1 to p2
function GetTangentDistance(p1, p2, p3)
	local p1_p2_heading = GetHeading(p1, p2)
	local p1_p3_heading = GetHeading(p1, p3)
	local alpha = math.abs(p1_p2_heading - p1_p3_heading)
	if alpha > 180 then
		alpha = math.abs(alpha - 360)
	end
	local p1_p3_distance = GetDistance(p1, p3)
	
	local p2_p1_heading = GetHeading(p2, p1)
	local p2_p3_heading = GetHeading(p2, p3)
	
	local beta = math.abs(p2_p1_heading - p2_p3_heading)
	if beta > 180 then
		beta = math.abs(beta - 360)
	end
	local p2_p3_distance = GetDistance(p2, p3)
	
	if alpha > 90 or alpha < -90 then
		return p1_p3_distance
	elseif beta > 90 or beta < -90 then
		return p2_p3_distance
	elseif GetDistance(p1, p2) == 0 then
		return p1_p3_distance
	else
		return math.abs(math.sin(math.rad(alpha)) * p1_p3_distance)
	end
end


--function to return lenght of a line from p1 to p2 that is within a circle c with radius r
function GetTangentLenght(p1, p2, pc, r)
	local p1_pc = GetDistance(p1, pc)
	local p2_pc = GetDistance(p2, pc)
	local p1_p2 = GetDistance(p1, p2)
	
	if (p1.x == pc.x and p1.y == pc.y) or (p2.x == pc.x and p2.y == pc.y) then			--p1 or p2 are the center of the circle
		if p1_p2 > r then																--the other point is outside of the circle
			return r																	--return the circle radius
		else																			--the other point is inside the cicle
			return p1_p2																--return distance from p1 to p2
		end
	elseif p1_pc < r and p2_pc < r then													--p1 and p2 are in circle
		return p1_p2																	--return distance from p1 to p2
	elseif p1_pc < r then																--only p1 is in circle
		local p1_p2_heading = GetHeading(p1, p2)										--heading from p1 to p2
		local p1_pc_heading = GetHeading(p1, pc)										--heading from p1 to pc
		local alpha = math.abs(p1_p2_heading - p1_pc_heading)							--angle in deg		
		local a = r
		local b = p1_pc
		local beta = math.deg(math.asin(b * math.sin(math.rad(alpha)) / a))
		local gamma = 180 - alpha - beta
		local c = a * math.sin(math.rad(gamma)) / math.sin(math.rad(alpha))
		return math.abs(c)
	elseif p2_pc < r then																--only p2 is in circle
		local p2_p1_heading = GetHeading(p2, p1)										--heading from p2 to p1
		local p2_pc_heading = GetHeading(p2, pc)										--heading from p2 to pc
		local alpha = math.abs(p2_p1_heading - p2_pc_heading)							--angle in deg		
		local a = r
		local b = p2_pc
		local beta = math.deg(math.asin(b * math.sin(math.rad(alpha)) / a))
		local gamma = 180 - alpha - beta
		local c = a * math.sin(math.rad(gamma)) / math.sin(math.rad(alpha))
		return math.abs(c)
	else																				--neither p1 or p2 is in circle
		local t = GetTangentDistance(p1, p2, pc)
		return 2 * math.sqrt(math.pow(r, 2) - math.pow(t, 2))
	end
end


--function to return subsequent IDs
id_counter = 100000
function GenerateID()
	local id = id_counter
	id_counter = id_counter + 1
	return id
end


--function to return various date and time formats of a number in seconds
function FormatTime(t, form)
	local hour
	local minute
	local second
		
	hour = math.floor(t / 3600)
	t = t - hour * 3600
	if hour < 10 then
		hour = "0" .. hour
	end
	
	minute = math.floor(t / 60)
	t = t - minute * 60
	if minute < 10 then
		minute = "0" .. minute
	end
	
	second = math.floor(t)
	if second < 10 then
		second = "0" .. second
	end
	
	if form == "hh:mm" then
		minute =  math.floor(minute + 0.5)
		if minute < 10 then
			minute = "0" .. minute
		end
		return hour .. ":" .. minute
	elseif form == "hh:mm:ss" then
		return hour .. ":" .. minute .. ":" .. second
	end
end


--function to format date
function FormatDate(day, month, year)
	if month == 1 then
		month = "January"
	elseif month == 2 then
		month = "February"
	elseif month == 3 then
		month = "March"
	elseif month == 4 then
		month = "April"
	elseif month == 5 then
		month = "May"
	elseif month == 6 then
		month = "June"
	elseif month == 7 then
		month = "July"
	elseif month == 8 then
		month = "August"
	elseif month == 9 then
		month = "September"
	elseif month == 10 then
		month = "October"
	elseif month == 11 then
		month = "November"
	elseif month == 12 then
		month = "December"
	end
	
	return month .. " " .. day .. ", " .. year
end


--function to format altitude in metric or imperial measurement
function FormatDistance(a)
	a = a / 1000																			--round to km
	if camp.units == "metric" then															--metric units
		a = math.floor(a) .. " km"															--kilometers
	elseif camp.units == "imperial" then													--imperial units
		a = a * 0.539957																	--covert to nm
		a = math.floor(a) .. " nm"															--nautical miles
	end
	return a
end


--function to format altitude in metric or imperial measurement
function FormatAlt(a)
	if camp.units == "metric" then															--metric units
		a = math.ceil(a / 10) * 10															--round to tens
		if a <= 1000 then																	--for altitudes until 1000m
			a = a .. " m AGL"																--meters AGL
		else
			a = a .. " m MSL"																--meters MSL
		end
	elseif camp.units == "imperial" then													--imperial units
		a = a * 3.28																		--covert to feet
		a = math.ceil(a / 100) * 100														--round to hunderts
		if a <= 3300 then																	--for altitudes until 3300ft
			a = a .. " ft AGL"																--feet AGL
		else
			a = a .. " ft MSL"																--feet MSL
		end
	end
	return a
end


--function to format speed in metric or imperial measurement
function FormatSpeed(a)
	if camp.units == "metric" then															--metric units
		a = a * 3.6
		a = math.floor(a / 10) * 10															--round to tens
		a = a .. " kph"																		--km per hour
	elseif camp.units == "imperial" then													--imperial units
		a = a * 1.94																		--covert to knots
		a = math.floor(a / 5) * 5															--round to fives
		a = a .. " kts"																		--knots
	end
	return a
end


--function to replace certain type names
function ReplaceTypeName(s)
	if TypeAlias and TypeAlias[s] then
		return TypeAlias[s]
	else
		return s
	end
end




 function _affiche(_table, titre, prof)
 
 if not prof or prof == nil then prof = 999 end 						-- prof = profondeur de niveau dans la hierarchie
  print()
   print()
    print()
    if titre == nil then print( string.format(" _affiche() titre = nil ")) 
    elseif type( titre) == "string" then
		print( string.format(" _affiche(titre) "..tostring(titre)))
	end
  
	if type( _table) == "table"  then
	
		for a, b in pairs(_table) do 
		
			if  type(b) ~= "table" then
				print(" _affiche(a b)    |"..tostring(a).."|"..tostring(b).."|")
			elseif type(b) == "table"   and prof >= 2 then
				for c, d in pairs(b) do
					print( " _affiche(a c)     "..tostring(a).."   "..tostring(c))
					
					
					if type(d)~= "table"  then
						print( " _affiche(d)                "..tostring(d))
					elseif type(d) == "table"  and prof >= 3 then
						for e, f in pairs(d) do							
							
							if type( f ) ~= "table"  then
								print( " _affiche(e f)                          "..tostring(e).." "..tostring(f))
							elseif type( f ) == "table"  and prof >= 4 then
								for g, h in pairs(f) do
									print( " _affiche(  e)                     "..tostring(e))									
									
									if type( h ) ~= "table"  then
										print( " _affiche(g h)                                    "..tostring(g).." "..tostring(h))	
									elseif type( h ) == "table"  and prof >= 5 then
										for i, j in pairs(h) do										
										
											if type( j ) ~= "table"  then
												print( " _affiche(i j)                                              "..tostring(i).." "..tostring(j))
											elseif type( j ) == "table" and prof >= 6 then									
												for k, l in pairs(j) do
													print( " _affiche(k)                                                   "..tostring(k))
													
													if type( l ) ~= "table"  then
														print( " _affiche(l)                                                   "..tostring(l))
													elseif type( l ) == "table" and prof >= 7 then
														for m, n in pairs(l) do
															print( " _affiche(m)                                                        "..tostring(m))
														
															if type( n ) ~= "table"  then
																print( " _affiche(n)                                                             "..tostring(n))
															elseif type( n ) == "table"  and prof >= 8 then
																print( " n est une table                                                              "..tostring(n).."---------------------------")
												  
															end --if
														end --for l
													end --if
												end -- for j
											end --if
										end -- for h
									end --if
								end --for f
							end --elseif
						end -- for d
					end -- if d
				end -- for v
			end -- if v
		end  -- for _table
	
	else print( "_affiche NoTable==> " ..tostring(_table))
	
	end -- if if type( _table) == "table"
	
end -- function affiche

function _afficheTXT(_table, titre, prof)


	--export custom mission log
	local logExp = "logExp  " 
		
 if not prof or prof == nil then prof = 999 end 						-- prof = profondeur de niveau dans la hierarchie
  logExp = logExp.."\n"
  
    if titre == nil then logExp = logExp.. string.format(" _affiche() titre = nil ")
    elseif type( titre) == "string" then
		logExp = logExp.. string.format(" _affiche(titre) "..tostring(titre)).."\n"
	end
  
	if type( _table) == "table"  then --and  (table.getn(_table) ~= 0 or table.getn(_table) ~= nil
	
		for a, b in pairs(_table) do --for a, b in pairs(event.initiator) do --for a, b in pairs(_ammo) do
		
			if  type(b) ~= "table" then
				logExp = logExp.." _affiche (a b)     "..tostring(a).." "..tostring(b).."\n"
			elseif type(b) == "table"   and prof >= 2 then
				for c, d in pairs(b) do
					logExp = logExp.. " _affiche(a c)           "..tostring(a).." "..tostring(c).."\n"
					
					
					if type(d)~= "table"  then
						logExp = logExp.. " _affiche(d)                "..tostring(d).."\n"
					elseif type(d) == "table"  and prof >= 3 then
						for e, f in pairs(d) do
							
							if type( f ) ~= "table"  then
								logExp = logExp.. " _affiche(e f)                          "..tostring(e).." "..tostring(f).."\n"
							elseif type( f ) == "table"  and prof >= 4 then
								logExp = logExp.. " _affiche( e)                                "..tostring(e).."\n"
								for g, h in pairs(f) do
									logExp = logExp.. " _affiche(Ig)                                 "..tostring(g).."\n"
									
									
									if type( h ) ~= "table"  then
										logExp = logExp.. " _affiche(g h)                                    "..tostring(g).." "..tostring(h).."\n"	
									elseif type( h ) == "table"  and prof >= 5 then
										logExp = logExp.. " _affiche( g)                                         "..tostring(g).."\n"
										for i, j in pairs(h) do
										
											if type( j ) ~= "table"  then
												logExp = logExp.. " _affiche(i j)                                              "..tostring(i).." "..tostring(j).."\n"
											elseif type( j ) == "table" and prof >= 6 then									
												logExp = logExp.. " _affiche(i)                                                  "..tostring(i).."\n"
												for k, l in pairs(j) do													
													
													if type( l ) ~= "table"  then
														logExp = logExp.. " _affiche(k l)                                                   "..tostring(k).." "..tostring(l).."\n"
													elseif type( l ) == "table" and prof >= 7 then
														logExp = logExp.. " _affiche(k)                                                       "..tostring(k).."\n"
														for m, n in pairs(l) do
															logExp = logExp.. " _affiche(m)                                                        "..tostring(m).."\n"
														
														
															if type( n ) ~= "table"  then
																logExp = logExp.. " _affiche(m n)                                                   "..tostring(m).." "..tostring(n).."\n"
															elseif type( n ) == "table" and prof >= 7 then
																logExp = logExp.. " _affiche(m)                                                       "..tostring(m).."\n"
																for o, p in pairs(n) do
																	logExp = logExp.. " _affiche(o)                                                        "..tostring(o).."\n"
														
														
																	if type( p ) ~= "table"  then
																		logExp = logExp.. " _affiche(p)                                                             "..tostring(p).."\n"
																	elseif type( p ) == "table"  and prof >= 8 then
																		logExp = logExp.. " p est une table                                                              "..tostring(p).."---------------------------".."\n"
																			
																	end
																end
															end --if
														end --for l
													end --if
												end -- for j
											end --if
										end -- for h
									end --if
								end --for f
							end --elseif
						end -- for d
					end -- if d
				end -- for v
			end -- if v
		end  -- for _table
	
	else logExp = logExp.. "_affiche NoTable==> " ..tostring(_table).."\n"
	
	end -- if if type( _table) == "table"
	
	return logExp
	
end -- function affiche

--function pour assigner les fréquences pour tout le monde, Plane and vehicle (EWR)
-- miguel21 modification M34.i  custom FrequenceRadio (i  3 frequency bands)(g: VHF helicopter)(h: bug Gazelle)

function CreatePlageFrequency()																				--trouve une plage de frequence commune si c'est possible
	local activeVHF = false
	camp.radio = {}
	
	local TempRadio = {
		["blue"] = {
			-- [1] = {
			-- },
		},
		["red"] = {
			-- [1] = {
			-- },
		},
	}

	-- miguel21 modification M38.g (g: prise en compte des 3 bandes de fréquence)(e: priority to the player's frequencies)
	for side, oob_side in pairs(oob_air) do
		for n, sqd in pairs(oob_side) do
			if not sqd.inactive and sqd.player then
				if frequency[sqd.type] then					
					for n = 1,  #frequency[sqd.type].radio do	
						for bandFreq, value in pairs(frequency[sqd.type].radio[n]) do
							if bandFreq == "FM" or bandFreq == "VHF" or bandFreq == "UHF" then								
								
								if not TempRadio[side][n] then TempRadio[side][n] = {} end	
								if not TempRadio[side][n][bandFreq] then TempRadio[side][n][bandFreq] = {} end
								
								TempRadio[side][n][bandFreq].min = value.min
								TempRadio[side][n][bandFreq].max = value.max
							end
						end					
					end				
				end
			end
		end
	end	
	-- _affiche(TempRadio, "UTIL_F 1er TempRadio")
	
	for side, oob_side in pairs(oob_air) do
		for n, sqd in pairs(oob_side) do
			if not sqd.inactive then
				if frequency[sqd.type] then
					for typeRadio , PlaneFreqRadio in pairs(frequency[sqd.type]) do	
						if typeRadio == "radio" and type(PlaneFreqRadio) == "table" then
							for nr , _bandFreq in pairs(PlaneFreqRadio) do	--for nr , value in pairs(frequency[sqd.type].radio) do
								for bandFreq , value in pairs(_bandFreq) do		
									if bandFreq == "FM" or bandFreq == "VHF" or bandFreq == "UHF" then		
			
										if not TempRadio[side][nr] then TempRadio[side][nr] = {} end	
										if not TempRadio[side][nr][bandFreq] then TempRadio[side][nr][bandFreq] = {} end
										if not TempRadio[side][nr][bandFreq].min then TempRadio[side][nr][bandFreq].min = value.min  end
										if not TempRadio[side][nr][bandFreq].max then TempRadio[side][nr][bandFreq].max = value.max  end
								
										if (value.min < TempRadio[side][nr][bandFreq].max)  then								--si une plage radio est en dehors des autres, on privilègie le joueur
											if value.min > TempRadio[side][nr][bandFreq].min then 
												TempRadio[side][nr][bandFreq].min =  value.min	
											end
											
											if (value.max < TempRadio[side][nr][bandFreq].max) and (value.max > TempRadio[side][nr][bandFreq].min )  then 
												TempRadio[side][nr][bandFreq].max =  value.max
											end
										end
										
										if sqd.player and TempRadio[side][1][bandFreq] then 
											-- print("sqd.type "..tostring(sqd.type))
											TempRadio[side][1][bandFreq]["player"] = true
										end
										
									end
								end
							end
						elseif typeRadio == "frequency"  then											-- frequence de base utilisé par FC3 ou gazelle
								print("UTIL_F Type No Frequency FC3? "..sqd.type)
						end
					end
				else
					-- print("UTIL_F Type No Frequency "..sqd.type)
				end
			end
		end
	end

	camp.radio = TempRadio
	-- _affiche(camp.radio, "UTIL_F camp.radio")

end


----- function to assign frquencies to packages -----
assigned_freq = {}														--table to store frequencies in use
package_freq = {															--table to store frequencies assigned to packages
	["blue"] = {
		["UHF"] = {},
		["VHF"] = {},
		["FM"] = {},		
	},
	["red"] = {
		["UHF"] = {},
		["VHF"] = {},
		["FM"] = {},
	},
}

-- from ATO_ThreatEvaluation pour asssigner une frequence EWR aléatoire
-- from ATO_FlightPlan pour assigner une freqence de groupe
function GetFrequency(side, targetname,  task , type, waves)
	
	local freq
	local nRadio = 1																					--chose frequency range from radio 1
	if camp.radio[side][2] and (task == "EWR" or task == "AWACS" or task == "Refueling") then			--if player has two radions, chose frequency range from AWACS and tanker from radio 2
		nRadio = 2
	end
	
	--check si la freq existe dans la radio 1, debug freq groupe
	local tabWave = {"UHF", "VHF", "FM", "HF"}
	function freqValide(checkFreq)
		for nb, Wave in pairs(tabWave) do 
			local nRadio = 1
			if checkFreq and frequency[type] and frequency[type]["radio"] and frequency[type]["radio"][nRadio] and frequency[type]["radio"][nRadio][Wave] then
				return true
			else
				return false
			end
		end
	end
	
	--si la freq package à déjà été désigné, on la reprend
	if package_freq[side]["UHF"][targetname] and freqValide(package_freq[side]["UHF"][targetname]) then
		return package_freq[side]["UHF"][targetname]															--return frequency
	elseif package_freq[side]["VHF"][targetname] and freqValide(package_freq[side]["VHF"][targetname]) then
		return package_freq[side]["VHF"][targetname]															--return frequency
	elseif package_freq[side]["FM"][targetname] and freqValide(package_freq[side]["FM"][targetname]) then
		return package_freq[side]["FM"][targetname]																--return frequency
	end


	function GetLocFrequency(side, targetname, nRadio,type,  range)		
		if (range == "UHF" or range == "VHF")  and task == "EWR" then
			if camp.radio[side][nRadio] and camp.radio[side][nRadio][range]  then		--Cherche d'abord une frequence UHF commune
				repeat
					freq = math.random(camp.radio[side][nRadio][range].min, camp.radio[side][nRadio][range].max - 1)		--find random frequency in mHz
					local deci = math.random(0, 9) / 10									--random first decimal place
					local mil = math.random(0, 3) * 25 / 1000							--random second and third decimal place (00/25/50/75)
					freq = freq + deci + mil											--combine to complete frequency
				until assigned_freq[freq] == nil										--repeat until a frequency is found that is not yet in use

				assigned_freq[freq] = true												--mark frequency in use
				package_freq[side][range][targetname] = freq							--store frequency for package
				return freq																--return frequency
			end
			
		elseif range == "UHF" and task ~= "EWR" then
			if camp.radio[side][nRadio] and camp.radio[side][nRadio][range]	and frequency[type] and frequency[type]["radio"] and frequency[type]["radio"][nRadio] and frequency[type]["radio"][nRadio][range]  then		--Cherche d'abord une frequence UHF commune
				repeat
					freq = math.random(camp.radio[side][nRadio][range].min, camp.radio[side][nRadio][range].max - 1)		--find random frequency in mHz
					local deci = math.random(0, 9) / 10									--random first decimal place
					local mil = math.random(0, 3) * 25 / 1000							--random second and third decimal place (00/25/50/75)
					freq = freq + deci + mil											--combine to complete frequency
				until assigned_freq[freq] == nil										--repeat until a frequency is found that is not yet in use

				assigned_freq[freq] = true												--mark frequency in use
				package_freq[side][range][targetname] = freq							--store frequency for package
				return freq																--return frequency
			end
		elseif range == "VHF" then
			if camp.radio[side][nRadio] and camp.radio[side][nRadio][range] and frequency[type] and frequency[type]["radio"] and frequency[type]["radio"][nRadio] and frequency[type]["radio"][nRadio][range]  then	--Cherche ensuite une frequence VHF
				repeat
					freq = math.random(camp.radio[side][nRadio][range].min, camp.radio[side][nRadio][range].max - 1)		--find random frequency in mHz
					local deci = math.random(0, 9) / 10									--random first decimal place
					local mil = math.random(0, 3) * 25 / 1000							--random second and third decimal place (00/25/50/75)
					freq = freq + deci + mil											--combine to complete frequency
				until assigned_freq[freq] == nil										--repeat until a frequency is found that is not yet in use

				assigned_freq[freq] = true												--mark frequency in use
				package_freq[side][range][targetname] = freq							--store frequency for package
				return freq																--return frequency
			end
		elseif range == "FM" then				
			if camp.radio[side][nRadio] and camp.radio[side][nRadio][range] and frequency[type] and frequency[type]["radio"] and frequency[type]["radio"][nRadio] and frequency[type]["radio"][nRadio][range]  then	--Cherche enfin une frequence FM
				repeat
					freq = math.random(camp.radio[side][nRadio][range].min, camp.radio[side][nRadio][range].max - 1)		--find random frequency in mHz
				until assigned_freq[freq] == nil										--repeat until a frequency is found that is not yet in use

				assigned_freq[freq] = true												--mark frequency in use
				package_freq[side][range][targetname] = freq							--store frequency for package
				return freq																--return frequency
			end	
		end
	end



	
	--TODO faire des functions pour nettoyer ce code
	if type and type ~= false and type ~= nil then
		if frequency[type]  and frequency[type].prefFreqPackage  then
			result = GetLocFrequency(side, targetname, frequency[type].prefFreqPackage.nRadio, type,  frequency[type].prefFreqPackage.range)
			return result
		end
	end
	
	local result
	
	if task == "EWR" then	
		if camp.radio[side][1] and camp.radio[side][1]["UHF"] and camp.radio[side][1]["UHF"]["player"] then
			result = GetLocFrequency(side, targetname, nRadio, type,  "UHF")
		elseif camp.radio[side][1] and camp.radio[side][1]["VHF"] and camp.radio[side][1]["VHF"]["player"] then
			result = GetLocFrequency(side, targetname, nRadio, type,  "VHF")			
		else
			result = GetLocFrequency(side, targetname, nRadio, type,  "UHF")
		end
	else
		result = GetLocFrequency(side, targetname, nRadio, type,  "UHF")
	end
	
	if result then
		return result
	else 
		result = GetLocFrequency(side, targetname, nRadio, type,  "UHF")
		if result then
			return result
		else 
			result = GetLocFrequency(side, targetname, nRadio, type,  "FM")
			if result then
				return result
			else 
				if not camp.radio[side] then camp.radio[side] = {} end
				if not camp.radio[side][nRadio] then camp.radio[side][nRadio] = {} end
				if not camp.radio[side][nRadio]["VHF"] then camp.radio[side][nRadio]["VHF"]  = {} end
				camp.radio[side][nRadio]["VHF"] = {
					min = 118,
					max = 136,
				}
				result = GetLocFrequency(side, targetname, nRadio, type,  "VHF")

				if result then
					return result
				else
					camp.radio[side][nRadio]["UHF"] = {
						min = 225,
						max = 300,
					}
					range = "UHF"
					repeat
						freq = math.random(camp.radio[side][nRadio][range].min, camp.radio[side][nRadio][range].max - 1)		--find random frequency in mHz
						local deci = math.random(0, 9) / 10									--random first decimal place
						local mil = math.random(0, 3) * 25 / 1000							--random second and third decimal place (00/25/50/75)
						freq = freq + deci + mil											--combine to complete frequency
					until assigned_freq[freq] == nil										--repeat until a frequency is found that is not yet in use

					assigned_freq[freq] = true												--mark frequency in use
					package_freq[side][range][targetname] = freq							--store frequency for package

					return freq								
				end 				
			end
		end
	end

	print()
	print("********************ATTENTION******************")
	print("**** Note for the Campaign Maker: Impossible to assign a frequency to  "..tostring(type).."**********")
	print("********************ATTENTION******************")
	print()
	os.execute 'pause'
end


-- http://www.lua.org/pil/19.3.html
-- Trier un tableau A[b] en le classant par A, et non b... pas simple .. ^^
function pairsByKeys (t, f)
	local a = {}
	for n in pairs(t) do table.insert(a, n) end
		table.sort(a, f)
		local i = 0      -- iterator variable
		local iter = function ()   -- iterator function
		i = i + 1
		if a[i] == nil then return nil
		else return a[i], t[a[i]]
		end
	end
	return iter
end
	
	

-- miguel21 modification M38.d Check and Help CampaignMaker
	
function CheckConfModMaster()
	local needUpdate = 0 
	function CheckConfMod( check, _table, chapter)		
		
		if not _table then
			needUpdate = needUpdate + 1 
		end
		
		for key1, checkValue1 in pairs(check) do
			if _table and _table[key1] == nil then
				print(" (0a) this variable : "..key1.." will be added in the conf_mod file, chapter: "..chapter)
				needUpdate = needUpdate + 1 
			end
			
			local stopCTRL = false
			if type(checkValue1) == "table" then
				for key2, checkValue2 in pairs(checkValue1) do
					
					-- if type(checkValue2) ~= "table"  and not (_table[key1] or _table[key1][key2]) and key1 ~= "MovedBullseye" then
					if  _table[key1] == nil  and key1 ~= "MovedBullseye" then
						print(" (0b) this variable : "..key1.." "..tostring(key2).." will be added in the conf_mod file, chapter: "..chapter)
						needUpdate = needUpdate + 1 
					elseif  type(_table[key1]) == "table" then
						if  _table[key1][key2] == nil  then
							print(" (0bb) this variable : "..key1.." "..tostring(key2).." will be added in the conf_mod file, chapter: "..chapter)
							needUpdate = needUpdate + 1
						end
					elseif  key1 == "MovedBullseye" then 
						local test_theatre = string.lower(mission.theatre)
						stopCTRL = true
						key2 = test_theatre
						if  _table[key1][test_theatre] == nil  then
							print(" (0bbb) this variable : "..key1.." "..test_theatre.." will be added in the conf_mod file, chapter: "..chapter)
							needUpdate = needUpdate + 1 
						end
					end
							
					if type(checkValue2) == "table"  then						
						for key3, checkValue3 in pairs(checkValue2) do
							if  _table[key1][key2] == nil then
								print(" (0c) this variable : "..key1.." "..key2.." "..tostring(key3).." will be added in the conf_mod file, chapter: "..chapter)
								needUpdate = needUpdate + 1 
							end
							
							if type(checkValue3) == "table"  then								
								for key4, checkValue4 in pairs(checkValue3) do
									if  _table[key1]== nil or _table[key1][key2] == nil or _table[key1][key2][key3] == nil or _table[key1][key2][key3][key4] == nil then
										print(" (0d) this variable : "..key1.." "..key2.." "..key3.." "..key4.." will be added in the conf_mod file, chapter: "..chapter)
										needUpdate = needUpdate + 1 
									end
									
									if type(checkValue4) == "table" then
										for key5, checkValue5 in pairs(checkValue4) do
											if  _table[key1][key2][key3][key4][key5] == nil then
												print(" (0e) this variable : "..key1.." "..key2.." "..key3.." "..key4.." "..key5.." will be added in the conf_mod file, chapter: "..chapter)
												needUpdate = needUpdate + 1 
											end
										end
									end
								end
							end
						end
					end
				end
			end
		end
	end
	
	--["theatre"] = "PersianGulf",
	
	dofile("../../../ScriptsMod."..versionPackageICM.."/conf_mod_check.lua")

	CheckConfMod(mission_ini_check, mission_ini, "mission_ini")
	CheckConfMod(mission_forcedOptions_check, mission_forcedOptions, "mission_forcedOptions")
	CheckConfMod(Debug_check, Debug, "Debug")
	CheckConfMod(campMod_check, campMod, "campMod")
	
	return needUpdate 

end


-- miguel21 modification M49.a big central db_loadout
	
function CheckCodeLoadout()

	-- campaigns_code_loadout = { 
		-- ["Cyprus"] =		"Cyprus Incident",
		-- ["Crisis"] = 		"Crisis in PG",
		-- ["PG"] = 			"Over PG",
		-- ["Caucasus"] = 		"Over Caucasus",
		-- ["TF"] = 			"TF-71",             
		-- ["TF80s"] = 		"TF-71-80s",           
		-- ["TF80sRED"] = 		"TF-71-Fishbed-80s",   
		-- ["IPW71"] = 		"India Pak War 71",    
		-- ["HWITC"] = 		"Hot War in the Cold",
		-- ["IIW"] = 			"Iran Iraq War",
	-- }   
	
	--routine de verification des code campagne
	dofile("../../../ScriptsMod."..versionPackageICM.."/UTIL_db_loadouts.lua")
	
	for plane, planeTab  in pairs(db_all_loadouts) do
		for taskName, loadout  in pairs(planeTab) do			
			for loadoutName, value  in pairs(loadout) do
				-- print("UtilF "..plane.." "..taskName.." "..loadoutName)
				if value.code_loadout and value.code_loadout ~= "" then 			
					for code_loadout_number, code in ipairs(value.code_loadout) do									
						if not campaigns_code_loadout[code]  then	--and not string.lower(code) == "all"
						
							if  string.lower(code) ~= "all"  then
								
								print()
								print("********************ATTENTION******************")
								print("***************Note for the Campaign Maker*****"..plane.." ||| "..taskName.." ||| "..loadoutName.." ||| "..code.." not found in campaigns_code_loadout****************")
								print("********************ATTENTION******************")
								print()
								os.execute 'pause'
							end
						else						
							-- print("UtilF camp.code_loadout "..camp.code_loadout.." found")						
						end
					end
				end
			end
		end
	end	
end

CheckCodeLoadout()


-- Miguel21 modification M54		revoir CustomTaskScript et TaskBombing
-- check si tous les avions prévu dans oob_air ont leur task déclaré possible dans la table TaskByPlane
function Check_TaskPossibleByPlane()
	
	-- StrikeCombi = {
		-- ["CAS"] = false,
		-- ["Ground Attack"] = false,
		-- -- ["Runway Attack"] = false,
		-- ["Pinpoint Strike"] = true,
	-- }
	
	checkOobAir = deepcopy(oob_air)
	
	
	for side, squadTbl in  pairs(checkOobAir) do		
		for squad_n, squad in  pairs(squadTbl) do
			local foundPlane = false
			
			if squad.tasks then 
				
				-- StrikeCombi
				local addMultipleStrike = false
				for taskOA, valueOA in  pairs(squad.tasks) do					
					if taskOA == "Strike" and valueOA == true  then					
						addMultipleStrike = true
					end				
				end
				
				--ajoute les vrais id des differents Strike
				if addMultipleStrike then
					squad.tasks["Strike"] = nil
					squad.tasks["CAS"] = true
					squad.tasks["Ground Attack"] = true
					squad.tasks["Pinpoint Strike"] = true
					-- squad.tasks["Runway Attack"] = true				
				end
				
				local foundStrikeTask = false
				for taskOA, valueOA in  pairs(squad.tasks) do
					local foundTask = false
					
					if taskOA == "Laser Illumination" then
						taskOA = "AFAC"
					elseif taskOA == "Anti-ship Strike" then
						taskOA = "Antiship Strike"						
					end
					
					if valueOA == true and TaskByPlane[taskOA] then
						for plane_TbP, value in  pairs(TaskByPlane[taskOA]) do
							if squad.type == plane_TbP   then
								foundPlane = true
								foundTask = true
								if taskOA == "CAS" or taskOA == "Ground Attack" or taskOA == "Pinpoint Strike"  then
									foundStrikeTask = true
								end
							end
						end						
						
						--toutes les tasks sauf strike
						if not foundTask and not addMultipleStrike and not tostring(taskOA) == "Fighter Sweep" then
							print("(Error UutilF C01) this task, requested in Init\oob_air_init.lua, is not listed in the UTIL_Data.lua file : "..tostring(squad.type).." "..tostring(taskOA))
							os.execute 'pause'				
						end
					
					elseif valueOA == true and not TaskByPlane[taskOA] and not tostring(taskOA) == "Fighter Sweep" then
						print("(Error UutilF C02) this task, requested in Init\oob_air_init.lua, is not listed in the UTIL_Data.lua file : "..tostring(squad.type).." "..tostring(taskOA))
						os.execute 'pause'
					end			
				end
				
				--si aucune tasks strike n'a été trouvé
				if not foundStrikeTask and  addMultipleStrike then
					print("(Error UutilF C03) this task, requested in Init\oob_air_init.lua, is not listed in the UTIL_Data.lua file : "..tostring(squad.type).." "..tostring("Strike"))
					os.execute 'pause'				
				end
				if not squad.inactive and not foundPlane   then
					print("(Error UutilF C04)"..tostring(squad.type).."  is not listed in the UTIL_Data.lua file ")
					os.execute 'pause'				
				end
			end			
		end
	end	
end


--M43 assignation des numeros de parking du type C08 
parkOccupied = {}
function GetParkingId(parkingId, base)
	local s	
	local counter
	if not parkOccupied[base]  then										
		parkOccupied[base] = {}												
	end

	for prefix, value in pairs(parkingId) do
		counter = 0
		if #value == 2 then
			lower = value[1]
			upper = value[2]
			
			repeat
				counter = counter + 1
				s = math.random(tonumber(lower), tonumber(upper))		
				s = prefix..string.format("%02d", s)
			until parkOccupied[base][s] == nil 	or counter == 100				
			
		elseif #value > 2 then
			repeat
				counter = counter + 1
				local r = math.random(1,#value)
				s = value[r]
				s = prefix..string.format("%02d", s)
			until parkOccupied[base][s] == nil 	or counter == 100					
		end
		if parkOccupied[base][s] == nil then
			break
		end
	end
	
	--ne trouve pas de place libre:
	if counter >= 100 then
		return false
	end
	parkOccupied[base][s] = true

	return tostring(s)

end

--function to check if point is in polygon
--function repris de Mbot dans DC_NavalEnvironment
function CheckPointInPolygon(point, poly)
	local crossings = 0
	for n = 1, #poly - 1 do
		if (poly[n].y < point.y and poly[n + 1].y > point.y) or (poly[n].y > point.y and poly[n + 1].y < point.y) then
			local dx = poly[n + 1].x - poly[n].x
			local dy = poly[n + 1].y - poly[n].y
			local delta_point_y = point.y - poly[n].y
			local delta_point_x = dx / dy * delta_point_y
			if poly[n].x + delta_point_x > point.x then
				crossings = crossings + 1
			end
		end
	end
	if crossings % 2 ~= 0 then
		return true
	else
		return false
	end
end

  --a function that automatically updates the conf_mod keeping as much as possible the old settings of the player
function UpdateConfMod()
	
	dofile("../../../ScriptsMod."..versionPackageICM.."/conf_mod_check.lua")
	local confModCheck = {
		mission_ini = mission_ini_check,
		mission_forcedOptions = mission_forcedOptions_check,
		Debug = Debug_check, 
		campMod = campMod_check,
		
	}

	monfichier = io.open("../../../ScriptsMod."..versionPackageICM.."/conf_mod_check.lua", "r")
	
	io.input(monfichier)

	local TableName
	local TableNameSub
	local txt = ""
	local nTable = {}
	local n = 0
	local ligne = 0
	for line in io.lines() do 
		local one
		local two
		local com
		local com1
		local com2
		local firstTab = ""
		local VariableName
		local str_length
		local nextTab = ""
		
		ligne = ligne +1
		--cherche le nom de la table "principal" dans le fichier de référence conf_mod_check
		if string.find(line, "=") and string.find(line, "{") and not string.find(line, "versionDCE")  then
			n = n +1																								--compte le nombre de sous table
			one, two = line:match("(.*)=(.*)")																		--sépare la ligne en 2, au niveau de =
			if string.find(one, "_check") and not string.find(one, "%-%-") then										--trouve le nom d'une table principale, finissant par _check
				TableName = one:gsub("_check", "")
				TableName = TableName:gsub("	", "")
				TableName = TableName:gsub(" ", "")
				nTable[n] = TableName																				--compte le nombre de sous-table, ici, on ajoute n+1
				txt = txt ..""..TableName.." = {\n"
			--cherche le nom de la table "secondaire n+1"
			elseif not string.find(one, "%-%-") then																--si la ligne n'est pas un commentaire
				TableNameSub = one:gsub("	", "")
				TableNameSub = TableNameSub:gsub(" ", "")
				nTable[n] = TableNameSub				
				for m = 2, n do 
					firstTab = firstTab.."	"
				end
				txt = txt ..firstTab..TableNameSub.." = {\n"
			end		
		
		--cherche le nom de la variable (key)
		elseif string.find(line, "=") and string.find(line, ",") and not string.find(line, "{") then				
			one, two = line:match("(.*)=(.*)")																		--sépare la ligne en 2, au niveau de =
			if  not string.find(one, "%-%-") then				
				VariableName = one:gsub("	", "")
				ShowVariableName = VariableName				
				if string.find(VariableName, "%[") then																--si la key est une autre table, on enleve les crochets, guillemet				
					VariableName = VariableName:gsub("%[", "")
					VariableName = VariableName:gsub("%]", "")
					VariableName = VariableName:gsub("\"", "")
					if string.sub(VariableName, -1) == " " then 
						VariableName = VariableName:sub(1, -2)
					end
				else
					VariableName = VariableName:gsub(" ", "")
				end
			end	
			--traitement du commentaire avec la valeur de la variable
			com1, com2 = two:match("(.*)\-(.*)")
			if com2 and string.find(com2, "%-%-") then
				comTemp, com2 = com2:match("(.*)\-(.*)")
			end
			
		elseif string.find(line, "}") and not string.find(line, "=") then
			nTable[n] = nil																								--supprime la sous-table, comme si on fermait par }
			n = n -1																									--ferme la sous table ou l'iteration
			txt = txt ..""..line.."\n"		
		else
			txt = txt ..""..line.."\n"		
		end

		if not com2 or com2 == nil then
			com2 = "" 
		end
		
		local check = {}
		if (nTable[1] == "mission_ini" or nTable[1] == "mission_forcedOptions" or nTable[1] == "Debug" or nTable[1] == "campMod") and VariableName  then
			if nTable[1] == "mission_ini" then tableId = mission_ini												--on donne le nom de la clef
			elseif nTable[1] == "mission_forcedOptions" then tableId = mission_forcedOptions						--on donne le nom de la clef
			elseif nTable[1] == "Debug" then tableId = Debug														--on donne le nom de la clef
			elseif nTable[1] == "campMod" then tableId = campMod													--on donne le nom de la clef
			end
		
			--test si les sous table existent
			-- si elle n'existe pas, on load la table _check à la place
			local notLoad = false
			local testSubTableId = deepcopy(tableId)
			if #nTable >=2 then																						--iteration des cascades de sous table
				for n = 2, #nTable do
					if  testSubTableId[nTable[n]] == nil then
						notLoad = true
					else
						testSubTableId =  testSubTableId[nTable[n]]													--prend la valeur de la table du joueur  n-1
					end
				end
			end							

			--la table est inconnue dans le conf_mod du joueur, donc  on load la table _check à la place
			if not tableId or tableId == nil or notLoad then
				if nTable[1] == "mission_ini" then tableId = mission_ini_check
				elseif nTable[1] == "mission_forcedOptions" then tableId = mission_forcedOptions_check
				elseif nTable[1] == "Debug" then tableId = Debug_check
				elseif nTable[1] == "campMod" then tableId = campMod_check
				end
			end

			for m = 1, n do 
				firstTab = firstTab.."	"
			end
			if #nTable >=2 then																						--iteration des cascades de sous table
				for n = 2, #nTable do
					tableId =  tableId[nTable[n]]																	--prend la valeur de la table n-1
				end
			end

			-- on lui colle la value du conf_mod player
			if  not tableId[VariableName] then
				if com1 then
					com1a, com2b = com1:match("(.*),(.*)")
					
					com1a = com1a:gsub(" ", "")
					if  not string.find(com1a, "true") and not string.find(com1a, "false") and not string.find(com1a, ".") and not string.find(com1a, "\"") and  type(com1a) ~= "number" then						
						com1a = "\""..com1a.."\""
					end				
					tableId[VariableName] = com1a
				else
					if n == 2 then
						--si la ligne est inconnue (donc la variable) du conf_mod joueur, on lui colle la valeur du conf_mod_check
						tableId[VariableName] = confModCheck[nTable[1]][nTable[n]][VariableName]
					elseif n == 3 then
						tableId[VariableName] = confModCheck[nTable[1]][nTable[n-1]][nTable[n]][VariableName]
					elseif n== 4 then
						tableId[VariableName] = confModCheck[nTable[1]][nTable[n-2]][nTable[n-1]][nTable[n]][VariableName]					
					end
				end
			end

			--récupère et format la valeur de la variable
			local resultNumber = tonumber(tableId[VariableName])			
			if  type(tableId[VariableName]) ~= "boolean"	and not (string.find(tableId[VariableName], "true") or string.find(tableId[VariableName], "false"))
			-- and not string.find(com1a, "\"")
			and  not resultNumber then
				if com1a and not string.find(com1a, "\"") then
					result = tableId[VariableName]
				end
				
				if not string.find(tableId[VariableName], "\"") then					
					result = "\""..tableId[VariableName].."\""					
				else
					result = tableId[VariableName]
				end
			else 
				result = tableId[VariableName]
			end
			
			--calcul l'espace necessaire pour afficher les commentaires
			str_length = string.len(tostring(firstTab..ShowVariableName.." = "..tostring(result)))
			for n = 1, 14 - math.floor(str_length/4) do														
				nextTab = nextTab .. "	"
			end		

			txt = txt..firstTab..ShowVariableName.." = "..tostring(result)..","..nextTab.."--"..com2.."\n"
		end		
	end
	
	io.close(monfichier)
	
	txt = txt.. "pictureBrief = " .. TableSerialization(pictureBrief, 0)

	local updateFile = io.open("Init/conf_mod.lua", "w")										--open targetlist file
	updateFile:write(txt)																		--save new data
	
	io.close(updateFile)

	dofile("Init/conf_mod.lua")
end


--assigne un CallName à tous les squad West pour tout le reste de la campagne 
function AssignCallnameSquad()
	--le callsign ou callname sera dorenavant assigné à un squad "west" pour toute la campagne
	--par default, l'assignation se fait lors de la premiere mission ou a n'importe quel skipMission si cela n'avait pas été fait avant
	--l'assignation se fait en priorité avec des SpecificCallnames s'ils existent, ensuite, le choix est automatique et aléatoire.
	--le joueur à la possibilité de "forcer" le callsign à un ou plusieurs squads dans Init/oob_air_init.lua
	--Il peut meme le changer au cours de la campagne, DCE le prendra en compte
	-- il existe une "protection" contre les mauvais callsign ajouté par le joueur, s'il se trompe
	--https://wiki.hoggitworld.com/view/DCS_enum_callsigns
	
	--******************************
	
	--the callsign or callname will now be assigned to a "west" squad for the entire campaign
	--by default, the assignment is done at the first mission or at any skipMission if it was not done before
	--the assignment is done in priority with SpecificCallnames if they exist, then, the choice is automatic and random.
	--the player has the possibility to "force" the callsign to one or more squads in Init/oob_air_init.lua
	--he can even change it during the campaign, DCE will take it into account
	-- there is a "protection" against bad callsign added by the player, if he is wrong
	--https://wiki.hoggitworld.com/view/DCS_enum_callsigns

	
	
	--si le joueur veut changer de callname à un squad, nous mettons à jour le Active/oob_air par rapport au Init/oob_air_init
	dofile("Init/oob_air_init.lua")
	initOobAir = deepcopy(oob_air)
	
	oob_air = nil
	
	dofile("Active/oob_air.lua")
	
	for initSide, initUnit in pairs(initOobAir) do
		for n = 1, #initUnit do	
			if initUnit[n].callsign then												--si le joueur a enregistré une callname perso
				for side, unit in pairs(oob_air) do	
					for r = 1, #unit do	
						if unit[r].name == initUnit[n].name and unit[r].callsign ~= initUnit[n].callsign then				--si c'est le meme suad
							
							unit[r].callsign = initUnit[n].callsign
							-- print("utilFct CORRECTION callsign "..unit[r].callsign)
							-- os.execute 'pause'
						end			
					end
				end
			end
		end
	end	
	

	
	local CallSigneAssigned = {}

	for side,unit in pairs(oob_air) do	
		for n = 1, #unit do	
			--regarde les CallName déjà attribué par le concepteur de campagne
			if WestCallsign[unit[n].country] == "west" and unit[n].callsign then
				CallSigneAssigned[unit[n].callsign] = true								
			end			
		end
	end
	
	for side, unit_ in pairs(oob_air) do	
		for n = 1, #unit_ do			
			unit = unit_[n]	
			
			if  not unit.inactive then
			
				local Imax = 0			
				-- print("UtilFct Passe 1a "..tostring(unit.type).." "..tostring(unit.name))
				-- print("UtilFct Passe 1b "..unit.country)

				if WestCallsign[unit.country] == "west" and not unit.callsign then 
						-- print("UtilFct Passe 2 ")
						
						local assigneOk = false
						
						--s'il existe une table avec des CallName spécifique à un type d'avion
						if  SpecificCallnames[unit.type] and SpecificCallnames[unit.type][unit.country]  then
							-- print("UtilFct Passe 3 ")
							
							--recherch l'index le plus haut de la table SpecificCallnames
							local Imax = 0
							for index, value in pairs(SpecificCallnames[unit.type][unit.country]) do
								if index > Imax then
									Imax = index
								end						
							end
							
							local j = 0
							repeat
								local i =  math.random(9, Imax)
								
								if not CallSigneAssigned[SpecificCallnames[unit.type][unit.country][i]] then
									unit.callsign = SpecificCallnames[unit.type][unit.country][i]
									unit.callsignId = i
									CallSigneAssigned[unit.callsign] = true
									assigneOk = true
									-- print("UtilFct Passe AAA 5 "..tostring(unit.callsign))	
									break								
								end
								j = j + 1
							until j > 50 or assigneOk						
						end
						
						-- if  not unit.inactive   then
							if not assigneOk then
								-- print("UtilFct Passe 6 ")
								
								if unit.tasks["AWACS"] then
									category = "AWACS"
								elseif unit.tasks["Refueling"] then
									category = "tanker"
								else
									category = "generic"
								end
								
								-- print("UtilFct Passe 7 "..tostring(category))
								
								for i = 1, #callsign_west[category] do
									-- print("UtilFct Passe 8 ")
									
									if not CallSigneAssigned[callsign_west[category][i]] then
										unit.callsign = callsign_west[category][i]
										unit.callsignId = i
										CallSigneAssigned[unit.callsign] = true
										assigneOk = true
										-- print("UtilFct Passe BBB 9 "..tostring(unit.callsign))
										break
									end
								end
								
								if not assigneOk then
									local i =  math.random(1, #callsign_west[category])
									unit.callsign = callsign_west[category][i]
									unit.callsignId = i
									CallSigneAssigned[unit.callsign] = true
									assigneOk = true
									
									-- print("UtilFct Passe CCC 10 "..tostring(unit.callsign))
									break
								end
							
							end
						-- end
		
				elseif WestCallsign[unit.country] == "west" and unit.callsign then								--controle si le callsign renseigné par le joueur/campaignMaker est compatible
					local GoodCallSign = false
					if  not unit.inactive and SpecificCallnames[unit.type] and SpecificCallnames[unit.type][unit.country]  then
						
						--recherch l'index le plus haut de la table SpecificCallnames
						local Imax = 0
						for index, value in pairs(SpecificCallnames[unit.type][unit.country]) do
							if index > Imax then
								Imax = index
							end						
						end
						-- print("UtilFct Passe 39 ")
						
						for i = 9, Imax do
							-- print("UtilFct Passe 40 ")
							
							if SpecificCallnames[unit.type][unit.country][i] == unit.callsign then
								unit.callsignId = i
								GoodCallSign = true
								-- print("UtilFct Passe found A_A 41 "..tostring(unit.callsign))	
								break								
							end
						end
					end
					
					if not GoodCallSign then
						if unit.tasks["AWACS"] then
							category = "AWACS"
						elseif unit.tasks["Refueling"] then
							category = "tanker"
						else
							category = "generic"
						end
						
						-- print("UtilFct Passe 42 "..tostring(category))
						
						for i = 1, #callsign_west[category] do
							-- print("UtilFct Passe 43 ")
							
							if callsign_west[category][i] == unit.callsign then
								GoodCallSign = true
								unit.callsignId = i
								-- print("UtilFct Passe B_B 44 "..tostring(unit.callsign))
								break
							end
						end
					end
					
					if not GoodCallSign then
						print("Error(UtilFct) This callsign: ("..tostring(unit.callsign)..") is not compatible with this type of aircraft ("..tostring(unit.type)..")")
						print(" This callsign is ignored for this mission. Change this callsign in /Init/oob_air_init.lua for this squadron ("..tostring(unit.name)..")")
						print(" select a new callsign corresponding to the aircraft type as in this page. Or delete it, DCE will automatically assign the right one.")
						print("https://wiki.hoggitworld.com/view/DCS_enum_callsigns")
						os.execute 'pause'
						unit.callsign = nil
					end				
				end
			end
		end
	end
end

