private CampaignHandler()
        {
            InitCampaigns();

            ReadBattleIni("INI/Battle.ini");
            ReadBattleIni("INI/" + ClientConfiguration.Instance.BattleFSFileName);

            MissionRankHandler.LoadData(Missions, GlobalVariables);
        }
        /// <summary>
        /// Parses singleplayer mission completion info from the game output files.
        /// Call this when the game has exited after the user has started or loaded
        /// a singleplayer mission.
        /// </summary>
        public void PostGameExitOnSingleplayerMission(GameSessionInfo sessionInfo)
        {
            if (sessionInfo.SessionType != GameSessionType.SINGLEPLAYER)
            {
                throw new ArgumentException(nameof(CampaignHandler) + "." + nameof(PostGameExitOnSingleplayerMission) + " should only be called after playing a singleplayer mission.");
            }

            string logFileName = LogFileFinder.GetLogFilePath();

            if (!File.Exists(ProgramConstants.GamePath + logFileName))
            {
                Logger.Log("WARNING: Could not parse log file after game end because the log file was not found!");
                return;
            }

            string[] lines = File.ReadAllLines(ProgramConstants.GamePath + logFileName);
            bool     scoreScreenLineFound = false;

            bool[] globalVariableStates = new bool[GLOBAL_VARIABLE_MAX];

            foreach (string line in lines)
            {
                if (line.StartsWith("ScoreScreen: Loaded "))
                {
                    scoreScreenLineFound = true;
                }

                // Also parse global variables from the log file
                if (line.StartsWith("Global variables: "))
                {
                    string   gvarString = line.Substring(18);
                    string[] gVarValues = gvarString.Split(',');

                    for (int i = 0; i < gVarValues.Length && i < globalVariableStates.Length; i++)
                    {
                        globalVariableStates[i] = gVarValues[i] == "1";
                    }
                }
            }

            if (!scoreScreenLineFound)
            {
                Logger.Log("Relevant line not found, assuming the player did not win the mission.");
                return;
            }

            Mission mission = Missions.Find(m => m.InternalName == sessionInfo.MissionInternalName);

            if (mission == null)
            {
                Logger.Log("WARNING: Failed to set mission progression data; could not find mission " + sessionInfo.MissionInternalName);
                return;
            }

            var unlockedMissions = new List <Mission>();

            Logger.Log("Finding and unlocking missions related to " + mission.InternalName);
            foreach (string unlockMissionName in mission.UnlockMissions)
            {
                Mission otherMission = Missions.Find(m => m.InternalName == unlockMissionName);
                if (otherMission == null)
                {
                    Logger.Log("FAILED to unlock mission " + unlockMissionName + "because it was not found!");
                    continue;
                }

                if (!otherMission.IsUnlocked)
                {
                    otherMission.IsUnlocked = true;
                    unlockedMissions.Add(otherMission);
                    Logger.Log("Unlocked mission " + otherMission.InternalName);
                }
            }

            Logger.Log("Finding and unlocking conditionally unlocked missions related to " + mission.InternalName);
            foreach (var conditionalMissionUnlock in mission.ConditionalMissionUnlocks)
            {
                bool conditionsMet = true;

                foreach (var globalVariableCondition in conditionalMissionUnlock.PrerequisiteGlobalVariableStates)
                {
                    var globalVariable = GlobalVariables.Find(gv => gv.InternalName == globalVariableCondition.GlobalVariableName);

                    if (globalVariable == null)
                    {
                        Logger.Log("FAILED to check condition of global variable " + globalVariableCondition.GlobalVariableName + " because it was not found!");
                        continue;
                    }

                    if (globalVariableStates[globalVariable.Index] != globalVariableCondition.Enabled)
                    {
                        conditionsMet = false;
                        break;
                    }
                }

                if (conditionsMet)
                {
                    Mission otherMission = Missions.Find(m => m.InternalName == conditionalMissionUnlock.UnlockMissionName);
                    if (otherMission == null)
                    {
                        Logger.Log("FAILED to unlock conditional mission " + conditionalMissionUnlock.UnlockMissionName + " because it was not found!");
                        continue;
                    }

                    if (!otherMission.IsUnlocked)
                    {
                        otherMission.IsUnlocked = true;
                        unlockedMissions.Add(otherMission);
                        Logger.Log("Unlocked conditional mission " + mission.InternalName);
                    }
                }
            }

            Logger.Log("Finding and unlocking global variable states related to " + mission.InternalName);
            foreach (var globalVariableName in mission.UnlockGlobalVariables)
            {
                var globalVariable = GlobalVariables.Find(gv => gv.InternalName == globalVariableName);

                if (globalVariable == null)
                {
                    Logger.Log("FAILED to unlock global variable " + globalVariableName + " because it was not found!");
                    continue;
                }

                if (globalVariableStates[globalVariable.Index])
                {
                    Logger.Log("Unlocked 'enabled' state of " + globalVariable.InternalName);
                    globalVariable.IsEnabledUnlocked = true;
                    globalVariable.EnabledThroughPreviousScenario = true;
                }
                else
                {
                    Logger.Log("Unlocked 'disabled' state of " + globalVariable.InternalName);
                    globalVariable.IsDisabledUnlocked             = true;
                    globalVariable.EnabledThroughPreviousScenario = false;
                }
            }

            Logger.Log("Finding and setting default enabled states of global variables used in " + mission.InternalName);
            foreach (var globalVariableName in mission.UsedGlobalVariables)
            {
                var globalVariable = GlobalVariables.Find(gv => gv.InternalName == globalVariableName);

                if (globalVariable == null)
                {
                    Logger.Log("FAILED to set default state of global variable " + globalVariableName + " because it was not found!");
                    continue;
                }

                if (globalVariableStates[globalVariable.Index])
                {
                    Logger.Log("Set default state to 'enabled' for " + globalVariable.InternalName);
                    globalVariable.EnabledThroughPreviousScenario = true;
                }
                else
                {
                    Logger.Log("Set default state to 'disabled' for " + globalVariable.InternalName);
                    globalVariable.EnabledThroughPreviousScenario = false;
                }
            }

            Mission primaryUnlockedMission = unlockedMissions.Count > 0 ? unlockedMissions[0] : null;

            if (sessionInfo.IsCheatSession)
            {
                Logger.Log("The player finished the mission with modified files, skipping setting of completion rank.");
            }
            else if ((int)mission.Rank < (int)sessionInfo.Difficulty)
            {
                Logger.Log("Setting completion rank of " + mission.InternalName + " to " + sessionInfo.Difficulty);
                mission.Rank = sessionInfo.Difficulty;
                MissionRankUpdated?.Invoke(this, new MissionCompletionEventArgs(mission, primaryUnlockedMission));
            }

            MissionRankHandler.WriteData(Missions, GlobalVariables);
            MissionCompleted?.Invoke(this, new MissionCompletionEventArgs(mission, primaryUnlockedMission));
        }