Example #1
0
        private void ResetSettings()
        {
            MULTIbalancer rhs = new MULTIbalancer();

            /* ===== SECTION 0 - Presets ===== */

            Preset = rhs.Preset;
            // EnableUnstacking = rhs.EnableUnstacking; // don't reset EnableUnstacking

            /* ===== SECTION 1 - Settings ===== */

            DebugLevel = rhs.DebugLevel;
            MaximumServerSize = rhs.MaximumServerSize;
            EnableBattlelogRequests = rhs.EnableBattlelogRequests;
            MaximumRequestRate =  rhs.MaximumRequestRate;
            WaitTimeout = rhs.WaitTimeout;
            WhichBattlelogStats = rhs.WhichBattlelogStats;
            MaxTeamSwitchesByStrongPlayers = rhs.MaxTeamSwitchesByStrongPlayers;
            MaxTeamSwitchesByWeakPlayers = rhs.MaxTeamSwitchesByWeakPlayers;
            UnlimitedTeamSwitchingDuringFirstMinutesOfRound = rhs.UnlimitedTeamSwitchingDuringFirstMinutesOfRound;
            Enable2SlotReserve = rhs.Enable2SlotReserve;
            EnablerecruitCommand = rhs.EnablerecruitCommand;
            EnableWhitelistingOfReservedSlotsList = rhs.EnableWhitelistingOfReservedSlotsList;
            SecondsUntilAdaptiveSpeedBecomesFast = rhs.SecondsUntilAdaptiveSpeedBecomesFast;
            EnableInGameCommands = rhs.EnableInGameCommands;
            // Whitelist = rhs.Whitelist; // don't reset the whitelist
            // DisperseEvenlyList = rhs.DisperseEvenlyList; // don't reset the dispersal list

            /* ===== SECTION 2 - Exclusions ===== */

            OnWhitelist = rhs.OnWhitelist;
            OnFriendsList = rhs.OnFriendsList;
            ApplyFriendsListToTeam = rhs.ApplyFriendsListToTeam;
            TopScorers = rhs.TopScorers;
            SameClanTagsInSquad = rhs.SameClanTagsInSquad;
            SameClanTagsInTeam = rhs.SameClanTagsInTeam;
            SameClanTagsForRankDispersal = rhs.SameClanTagsForRankDispersal;
            LenientRankDispersal = rhs.LenientRankDispersal;
            MinutesAfterJoining = rhs.MinutesAfterJoining;
            MinutesAfterBeingMoved = rhs.MinutesAfterBeingMoved;
            JoinedEarlyPhase = rhs.JoinedEarlyPhase;
            JoinedMidPhase = rhs.JoinedMidPhase;
            JoinedLatePhase = rhs.JoinedLatePhase;

            /* ===== SECTION 3 - Round Phase & Population Settings ===== */

            EarlyPhaseTicketPercentageToUnstack = rhs.EarlyPhaseTicketPercentageToUnstack;
            MidPhaseTicketPercentageToUnstack = rhs.MidPhaseTicketPercentageToUnstack;
            LatePhaseTicketPercentageToUnstack = rhs.LatePhaseTicketPercentageToUnstack;

            EnableTicketLossRateLogging = rhs.EnableTicketLossRateLogging;

            SpellingOfSpeedNamesReminder = rhs.SpellingOfSpeedNamesReminder;

            EarlyPhaseBalanceSpeed = rhs.EarlyPhaseBalanceSpeed;
            MidPhaseBalanceSpeed = rhs.MidPhaseBalanceSpeed;
            LatePhaseBalanceSpeed = rhs.LatePhaseBalanceSpeed;

            /* ===== SECTION 4 - Scrambler ===== */

            OnlyOnNewMaps = rhs.OnlyOnNewMaps;
            OnlyOnFinalTicketPercentage = rhs.OnlyOnFinalTicketPercentage;
            ScrambleBy = rhs.ScrambleBy;
            KeepClanTagsInSameTeam = rhs.KeepClanTagsInSameTeam;
            KeepFriendsInSameTeam = rhs.KeepFriendsInSameTeam;
            DivideBy = rhs.DivideBy;
            ClanTagToDivideBy = rhs.ClanTagToDivideBy;
            DelaySeconds = rhs.DelaySeconds;

            /* ===== SECTION 5 - Messages ===== */

            QuietMode =  rhs.QuietMode;
            YellDurationSeconds = rhs.YellDurationSeconds;
            BadBecauseMovedByBalancer = rhs.BadBecauseMovedByBalancer;
            BadBecauseWinningTeam = rhs.BadBecauseWinningTeam;
            BadBecauseBiggestTeam = rhs.BadBecauseBiggestTeam;
            BadBecauseRank = rhs.BadBecauseRank;
            BadBecauseDispersalList = rhs.BadBecauseDispersalList;
            ChatMovedForBalance = rhs.ChatMovedForBalance;
            YellMovedForBalance = rhs.YellMovedForBalance;
            ChatMovedToUnstack = rhs.ChatMovedToUnstack;
            YellMovedToUnstack = rhs.YellMovedToUnstack;
            ChatDetectedBadTeamSwitch = rhs.ChatDetectedBadTeamSwitch;
            YellDetectedBadTeamSwitch = rhs.YellDetectedBadTeamSwitch;
            ChatDetectedGoodTeamSwitch = rhs.ChatDetectedGoodTeamSwitch;
            YellDetectedGoodTeamSwitch = rhs.YellDetectedGoodTeamSwitch;
            ChatAfterUnswitching = rhs.ChatAfterUnswitching;
            YellAfterUnswitching = rhs.YellAfterUnswitching;

            /* ===== SECTION 6 - Unswitcher ===== */

            ForbidSwitchingAfterAutobalance = rhs.ForbidSwitchingAfterAutobalance;
            ForbidSwitchingToWinningTeam = rhs.ForbidSwitchingToWinningTeam;
            ForbidSwitchingToBiggestTeam = rhs.ForbidSwitchingToBiggestTeam;
            ForbidSwitchingAfterDispersal = rhs.ForbidSwitchingAfterDispersal;
            EnableImmediateUnswitch = rhs.EnableImmediateUnswitch;

            /* ===== SECTION 7 - TBD ===== */

            /* ===== SECTION 8 - Per-Mode Settings ===== */

            List<String> simpleModes = GetSimplifiedModes();

            fPerMode.Clear();

            foreach (String sm in simpleModes) {
            PerModeSettings oneSet = null;
            if (!fPerMode.ContainsKey(sm)) {
            oneSet = new PerModeSettings(sm, fGameVersion == GameVersion.BF4);
            fPerMode[sm] = oneSet;
            }
            }

            /* ===== SECTION 9 - Debug Settings ===== */

            ShowCommandInLog = rhs.ShowCommandInLog;
            LogChat = rhs.LogChat;
            EnableLoggingOnlyMode = rhs.EnableLoggingOnlyMode;
        }
Example #2
0
        /* Constructor */
        public MULTIbalancer()
        {
            /* Private members */
            fIsEnabled = false;
            fFinalizerActive = false;
            fPluginState = PluginState.Disabled;
            fGameState = GameState.Unknown;
            fServerInfo = null;
            fRefreshCommand = false;
            fServerUptime = 0;
            fServerCrashed = false;
            fDebugScramblerBefore = new List<PlayerModel>[2]{new List<PlayerModel>(), new List<PlayerModel>()};
            fDebugScramblerAfter = new List<PlayerModel>[2]{new List<PlayerModel>(), new List<PlayerModel>()};
            fDebugScramblerStartRound = new List<PlayerModel>[2]{new List<PlayerModel>(), new List<PlayerModel>()};

            fBalancedRound = 0;
            fUnstackedRound = 0;
            fUnswitchedRound = 0;
            fExcludedRound = 0;
            fExemptRound = 0;
            fFailedRound = 0;
            fTotalRound = 0;
            fBalanceIsActive = false;
            fRoundsEnabled = 0;
            fGrandTotalQuits = 0;
            fGrandRageQuits = 0;
            fTotalQuits = 0;
            fRageQuits = 0;

            fMoveThread = null;
            fFetchThread = null;
            fListPlayersThread = null;
            fScramblerThread = null;
            fTimerThread = null;

            fModeToSimple = new Dictionary<String,String>();

            fEasyTypeDict = new Dictionary<int, Type>();
            fEasyTypeDict.Add(0, typeof(int));
            fEasyTypeDict.Add(1, typeof(Int16));
            fEasyTypeDict.Add(2, typeof(Int32));
            fEasyTypeDict.Add(3, typeof(Int64));
            fEasyTypeDict.Add(4, typeof(float));
            fEasyTypeDict.Add(5, typeof(long));
            fEasyTypeDict.Add(6, typeof(String));
            fEasyTypeDict.Add(7, typeof(string));
            fEasyTypeDict.Add(8, typeof(double));

            fBoolDict = new Dictionary<int, Type>();
            fBoolDict.Add(0, typeof(Boolean));
            fBoolDict.Add(1, typeof(bool));

            fListStrDict = new Dictionary<int, Type>();
            fListStrDict.Add(0, typeof(String[]));

            fPerMode = new Dictionary<String,PerModeSettings>();

            fAllPlayers = new List<String>();
            fKnownPlayers = new Dictionary<String, PlayerModel>();
            fTeam1 = new List<PlayerModel>();
            fTeam2 = new List<PlayerModel>();
            fTeam3 = new List<PlayerModel>();
            fTeam4 = new List<PlayerModel>();
            fUnassigned = new List<String>();
            fRoundStartTimestamp = DateTime.MinValue;
            fRoundOverTimestamp = DateTime.MinValue;
            fListPlayersTimestamp = DateTime.MinValue;
            fFullUnstackSwapTimestamp = DateTime.MinValue;
            fLastValidationTimestamp = DateTime.MinValue;
            fListPlayersQ = new Queue<DelayedRequest>();

            fPendingTeamChange = new Dictionary<String,int>();
            fMoving = new Dictionary<String, MoveInfo>();
            fMoveQ = new Queue<MoveInfo>();
            fReassigned = new List<String>();
            fReservedSlots = new List<String>();
            fTickets = new int[5]{0,0,0,0,0};
            fFriendlyMaps = new Dictionary<String,String>();
            fFriendlyModes = new Dictionary<String,String>();
            fMaxTickets = -1;
            fRushMaxTickets = -1;
            fLastBalancedTimestamp = DateTime.MinValue;
            fEnabledTimestamp = DateTime.MinValue;
            fFinalStatus = null;
            fIsFullRound = false;
            fUnstackState = UnstackState.Off;
            fLastMsg = null;
            fRushStage = 0;
            fRushPrevAttackerTickets = 0;
            fRushAttackerStageLoss = 0;
            fRushAttackerStageSamples = 0;
            fMoveStash = new List<MoveInfo>();
            fLastVersionCheckTimestamp = DateTime.MinValue;
            fTimeOutOfJoint = 0;
            fUnstackGroupCount = 0;
            fPriorityFetchQ = new PriorityQueue(this);
            fIsCacheEnabled = false;
            fScramblerLock = new DelayedRequest();
            fWinner = 0;
            fUpdateThreadLock = new DelayedRequest();
            fLastServerInfoTimestamp = DateTime.Now;
            fStageInProgress = false;
            fHost = String.Empty;
            fPort = String.Empty;
            fRushMap3Stages = new List<String>(new String[6]{"MP_007", "XP4_Quake", "XP5_002", "MP_012", "XP4_Rubble", "MP_Damage"});
            fRushMap5Stages = new List<String>(new String[6]{"MP_013", "XP3_Valley", "MP_017", "XP5_001", "MP_Prison", "MP_Siege"});
            fGroupAssignments = new int[5]{0,0,0,0,0};
            fDispersalGroups = new List<String>[5]{null, new List<String>(), new List<String>(), new List<String>(), new List<String>()};
            fNeedPlayerListUpdate = false;
            fFriends = new Dictionary<int, List<String>>();
            fAllFriends = new List<String>();
            fWhileScrambling = false;
            fExtrasLock = new DelayedRequest();
            fExtraNames = new List<String>();
            fGotLogin = false;
            fDebugScramblerSuspects = new Dictionary<String,String>();
            fTimerRequestList = new List<DelayedRequest>();
            fAverageTicketLoss = new Queue<double>[3]{null, new Queue<double>(), new Queue<double>()};
            fTicketLossHistogram = new Histogram();

            /* Settings */

            /* ===== SECTION 0 - Presets ===== */

            SettingsVersion = 1;
            Preset = PresetItems.Standard;
            EnableUnstacking = false;
            EnableSettingsWizard = false;
            WhichMode = "Conquest Large";
            MetroIsInMapRotation = false;
            MaximumPlayersForMode = 64;
            LowestMaximumTicketsForMode = 300;
            HighestMaximumTicketsForMode = 400;
            PreferredStyleOfBalancing = PresetItems.Standard;
            ApplySettingsChanges = false;

            /* ===== SECTION 1 - Settings ===== */

            DebugLevel = 2;
            MaximumServerSize = 64;
            EnableBattlelogRequests = true;
            MaximumRequestRate = 10; // in 20 seconds
            WaitTimeout = 30; // seconds
            WhichBattlelogStats = BattlelogStats.ClanTagOnly;
            MaxTeamSwitchesByStrongPlayers = 1;
            MaxTeamSwitchesByWeakPlayers = 2;
            UnlimitedTeamSwitchingDuringFirstMinutesOfRound = 5.0;
            Enable2SlotReserve = false;
            EnablerecruitCommand = false;
            EnableWhitelistingOfReservedSlotsList = true;
            Whitelist = new String[] {DEFAULT_LIST_ITEM};
            fSettingWhitelist = new List<String>(Whitelist);
            DisperseEvenlyList = new String[] {DEFAULT_LIST_ITEM};
            fSettingDisperseEvenlyList = new List<String>(DisperseEvenlyList);
            FriendsList = new String[] {DEFAULT_LIST_ITEM};
            fSettingFriendsList = new List<String>();
            SecondsUntilAdaptiveSpeedBecomesFast = 3*60; // 3 minutes default
            EnableInGameCommands = true;

            /* ===== SECTION 2 - Exclusions ===== */

            OnWhitelist = true;
            OnFriendsList = false;
            ApplyFriendsListToTeam = false;
            TopScorers = true;
            SameClanTagsInSquad = true;
            SameClanTagsInTeam = false;
            SameClanTagsForRankDispersal = false;
            LenientRankDispersal = false;
            MinutesAfterJoining = 5;
            MinutesAfterBeingMoved = 90; // 1.5 hours
            JoinedEarlyPhase = true;
            JoinedMidPhase = true;
            JoinedLatePhase = false;

            /* ===== SECTION 3 - Round Phase & Population Settings ===== */

            EarlyPhaseTicketPercentageToUnstack = new double[3]         {  0,120,120};
            MidPhaseTicketPercentageToUnstack = new double[3]           {  0,120,120};
            LatePhaseTicketPercentageToUnstack = new double[3]          {  0,  0,  0};

            EnableTicketLossRateLogging = false;

            SpellingOfSpeedNamesReminder = Speed.Click_Here_For_Speed_Names;

            EarlyPhaseBalanceSpeed = new Speed[3]           {     Speed.Fast, Speed.Adaptive, Speed.Adaptive};
            MidPhaseBalanceSpeed = new Speed[3]             {     Speed.Fast, Speed.Adaptive, Speed.Adaptive};
            LatePhaseBalanceSpeed = new Speed[3]            {     Speed.Stop,     Speed.Stop,     Speed.Stop};

            /* ===== SECTION 4 - Scrambler ===== */

            OnlyOnNewMaps = true; // false means scramble every round
            OnlyOnFinalTicketPercentage = 120; // 0 means scramble regardless of final score
            ScrambleBy = DefineStrong.RoundScore;
            KeepSquadsTogether = true;
            KeepClanTagsInSameTeam = true;
            KeepFriendsInSameTeam = false;
            DivideBy = DivideByChoices.None;
            ClanTagToDivideBy = String.Empty;
            DelaySeconds = 50;

            /* ===== SECTION 5 - Messages ===== */

            QuietMode = false; // false: chat is global, true: chat is private. Yells are always private
            YellDurationSeconds = 10;
            BadBecauseMovedByBalancer = "autobalance moved you to the %toTeam% team";
            BadBecauseWinningTeam = "switching to the winning team is not allowed";
            BadBecauseBiggestTeam = "switching to the biggest team is not allowed";
            BadBecauseRank = "this server splits Colonel 100's between teams";
            BadBecauseDispersalList = "you're on the list of players to split between teams";
            ChatMovedForBalance = "*** MOVED %name% for balance ...";
            YellMovedForBalance = "Moved %name% for balance ...";
            ChatMovedToUnstack = "*** MOVED %name% to unstack teams ...";
            YellMovedToUnstack = "Moved %name% to unstack teams ...";
            ChatDetectedBadTeamSwitch = "%name%, you can't switch to team %fromTeam%: %reason%, sending you back ...";
            YellDetectedBadTeamSwitch = "You can't switch to the %fromTeam% team: %reason%, sending you back!";
            ChatDetectedGoodTeamSwitch = "%name%, thanks for helping out the %toTeam% team!";
            YellDetectedGoodTeamSwitch = "Thanks for helping out the %toTeam% team!";
            ChatAfterUnswitching = "%name%, please stay on the %toTeam% team for the rest of this round";
            YellAfterUnswitching = "Please stay on the %toTeam% team for the rest of this round";

            /* ===== SECTION 6 - Unswitcher ===== */

            EnableImmediateUnswitch = true;
            ForbidSwitchingAfterAutobalance = UnswitchChoice.Always;
            ForbidSwitchingToWinningTeam = UnswitchChoice.Always;
            ForbidSwitchingToBiggestTeam = UnswitchChoice.Always;
            ForbidSwitchingAfterDispersal = UnswitchChoice.Always;

            /* ===== SECTION 7 - TBD ===== */

            /* ===== SECTION 8 - Per-Mode Settings ===== */

            /* ===== SECTION 9 - Debug Settings ===== */

            ShowInLog = INVALID_NAME_TAG_GUID;
            ShowCommandInLog = String.Empty;
            LogChat = true;
            EnableLoggingOnlyMode = false;
            EnableExternalLogging = false;
            ExternalLogSuffix = "_mb.log";
        }
 private double GetPlayerStat(PlayerModel player, DefineStrong which)
 {
     double stat = 0;
     switch (which) {
     case DefineStrong.RoundScore:
     stat = player.ScoreRound;
     break;
     case DefineStrong.RoundSPM:
     stat = player.SPMRound;
     break;
     case DefineStrong.RoundKills:
     stat = player.KillsRound;
     break;
     case DefineStrong.RoundKDR:
     stat = player.KDRRound;
     break;
     case DefineStrong.PlayerRank:
     stat = player.Rank;
     break;
     case DefineStrong.RoundKPM:
     stat = player.KPMRound;
     break;
     case DefineStrong.BattlelogSPM:
     stat = ((player.StatsVerified) ? player.SPM :player.SPMRound);
     break;
     case DefineStrong.BattlelogKDR:
     stat = ((player.StatsVerified) ? player.KDR :player.KDRRound);
     break;
     case DefineStrong.BattlelogKPM:
     stat = ((player.StatsVerified) ? player.KPM :player.KPMRound);
     break;
     default:
     break;
     }
     return stat;
 }
Example #4
0
            public PerModeSettings(String simplifiedModeName, bool isBF4)
            {
                DetermineStrongPlayersBy = DefineStrong.RoundScore;
                PercentOfTopOfTeamIsStrong = 50;
                DisperseEvenlyByRank = 0;
                EnableDisperseEvenlyList = false;
                EnableStrictDispersal = true;
                EnableScrambler = false;
                OnlyMoveWeakPlayers = true;
                isDefault = false;
                EnableTicketLossRatio = false;
                TicketLossSampleCount = 180;
                // Rush only
                Stage1TicketPercentageToUnstackAdjustment = 0;
                Stage2TicketPercentageToUnstackAdjustment = 0;
                Stage3TicketPercentageToUnstackAdjustment = 0;
                Stage4And5TicketPercentageToUnstackAdjustment = 0;

                switch (simplifiedModeName) {
                case "Conq Small, Dom, Scav":
                case "Conquest Small": // BF4
                case "Domination": // BF4
                    MaxPlayers = (isBF4 && simplifiedModeName == "Domination") ? 20 : 32;
                    CheckTeamStackingAfterFirstMinutes = 10;
                    MaxUnstackingSwapsPerRound = 2;
                    NumberOfSwapsPerGroup = 2;
                    DelaySecondsBetweenSwapGroups = SWAP_TIMEOUT;
                    MaxUnstackingTicketDifference = 100;
                    DefinitionOfHighPopulationForPlayers = (isBF4 && simplifiedModeName == "Domination") ? 16 :24;
                    DefinitionOfLowPopulationForPlayers = 8;
                    DefinitionOfEarlyPhaseFromStart = 50; // assuming 200 tickets typical
                    DefinitionOfLatePhaseFromEnd = 50; // assuming 200 tickets typical
                    MetroAdjustedDefinitionOfLatePhase = 100;
                    EnableMetroAdjustments = false;
                    break;
                case "Conquest Large":
                    MaxPlayers = 64;
                    CheckTeamStackingAfterFirstMinutes = 10;
                    MaxUnstackingSwapsPerRound = 4;
                    NumberOfSwapsPerGroup = 2;
                    DelaySecondsBetweenSwapGroups = SWAP_TIMEOUT;
                    MaxUnstackingTicketDifference = 150;
                    DefinitionOfHighPopulationForPlayers = 48;
                    DefinitionOfLowPopulationForPlayers = 16;
                    DefinitionOfEarlyPhaseFromStart = 100; // assuming 300 tickets typical
                    DefinitionOfLatePhaseFromEnd = 100; // assuming 300 tickets typical
                    EnableMetroAdjustments = false;
                    MetroAdjustedDefinitionOfLatePhase = 200;
                    break;
                case "CTF":
                    MaxPlayers = 64;
                    CheckTeamStackingAfterFirstMinutes = 5;
                    MaxUnstackingSwapsPerRound = 4;
                    NumberOfSwapsPerGroup = 2;
                    DelaySecondsBetweenSwapGroups = SWAP_TIMEOUT;
                    MaxUnstackingTicketDifference = 0;
                    DefinitionOfHighPopulationForPlayers = 48;
                    DefinitionOfLowPopulationForPlayers = 16;
                    DefinitionOfEarlyPhaseFromStart = 5; // minutes
                    DefinitionOfLatePhaseFromEnd = 5; // minutes
                    break;
                case "Rush":
                    MaxPlayers = 32;
                    CheckTeamStackingAfterFirstMinutes = 5;
                    MaxUnstackingSwapsPerRound = 2;
                    NumberOfSwapsPerGroup = 2;
                    DelaySecondsBetweenSwapGroups = SWAP_TIMEOUT;
                    MaxUnstackingTicketDifference = 40;
                    DefinitionOfHighPopulationForPlayers = 24;
                    DefinitionOfLowPopulationForPlayers = 8;
                    DefinitionOfEarlyPhaseFromStart = 25; // assuming 75 tickets typical
                    DefinitionOfLatePhaseFromEnd = 25; // assuming 75 tickets typical
                    // Rush only
                    Stage1TicketPercentageToUnstackAdjustment = 5;
                    Stage2TicketPercentageToUnstackAdjustment = 30;
                    Stage3TicketPercentageToUnstackAdjustment = 80;
                    Stage4And5TicketPercentageToUnstackAdjustment = -120;
                    SecondsToCheckForNewStage = 10;
                    break;
                case "Squad Deathmatch":
                    MaxPlayers = (isBF4) ? 20 : 16;
                    CheckTeamStackingAfterFirstMinutes = 0;
                    MaxUnstackingSwapsPerRound = 0;
                    NumberOfSwapsPerGroup = 0;
                    DelaySecondsBetweenSwapGroups = 60;
                    MaxUnstackingTicketDifference = 25;
                    DefinitionOfHighPopulationForPlayers = 14;
                    DefinitionOfLowPopulationForPlayers = 8;
                    DefinitionOfEarlyPhaseFromStart = 10; // assuming 50 tickets typical
                    DefinitionOfLatePhaseFromEnd = 10; // assuming 50 tickets typical
                    break;
                case "Superiority":
                    MaxPlayers = 24;
                    CheckTeamStackingAfterFirstMinutes = 15;
                    MaxUnstackingSwapsPerRound = 2;
                    NumberOfSwapsPerGroup = 2;
                    DelaySecondsBetweenSwapGroups = SWAP_TIMEOUT;
                    MaxUnstackingTicketDifference = 125;
                    DefinitionOfHighPopulationForPlayers = 16;
                    DefinitionOfLowPopulationForPlayers = 8;
                    DefinitionOfEarlyPhaseFromStart = 50; // assuming 250 tickets typical
                    DefinitionOfLatePhaseFromEnd = 50; // assuming 250 tickets typical
                    break;
                case "Team Deathmatch":
                    MaxPlayers = (isBF4) ? 20 : 64;
                    CheckTeamStackingAfterFirstMinutes = 5;
                    MaxUnstackingSwapsPerRound = 4;
                    NumberOfSwapsPerGroup = 2;
                    DelaySecondsBetweenSwapGroups = SWAP_TIMEOUT;
                    MaxUnstackingTicketDifference = 50;
                    DefinitionOfHighPopulationForPlayers = (isBF4) ? 16 : 48;
                    DefinitionOfLowPopulationForPlayers = (isBF4) ? 8 : 16;
                    DefinitionOfEarlyPhaseFromStart = 20; // assuming 100 tickets typical
                    DefinitionOfLatePhaseFromEnd = 20; // assuming 100 tickets typical
                    break;
                case "Squad Rush":
                    MaxPlayers = 8;
                    CheckTeamStackingAfterFirstMinutes = 2;
                    MaxUnstackingSwapsPerRound = 1;
                    NumberOfSwapsPerGroup = 1;
                    DelaySecondsBetweenSwapGroups = 60;
                    MaxUnstackingTicketDifference = 10;
                    DefinitionOfHighPopulationForPlayers = 6;
                    DefinitionOfLowPopulationForPlayers = 4;
                    DefinitionOfEarlyPhaseFromStart = 5; // assuming 20 tickets typical
                    DefinitionOfLatePhaseFromEnd = 5; // assuming 20 tickets typical
                    // Rush only
                    Stage1TicketPercentageToUnstackAdjustment = 5;
                    Stage2TicketPercentageToUnstackAdjustment = 30;
                    Stage3TicketPercentageToUnstackAdjustment = 80;
                    Stage4And5TicketPercentageToUnstackAdjustment = -120;
                    SecondsToCheckForNewStage = 10;
                    break;
                case "Gun Master":
                    MaxPlayers = 16;
                    CheckTeamStackingAfterFirstMinutes = 2;
                    MaxUnstackingSwapsPerRound = 2;
                    NumberOfSwapsPerGroup = 2;
                    DelaySecondsBetweenSwapGroups = SWAP_TIMEOUT;
                    MaxUnstackingTicketDifference = 0;
                    DefinitionOfHighPopulationForPlayers = 12;
                    DefinitionOfLowPopulationForPlayers = 6;
                    DefinitionOfEarlyPhaseFromStart = 0;
                    DefinitionOfLatePhaseFromEnd = 0;
                    break;
                case "Defuse": // BF4
                    MaxPlayers = 10;
                    CheckTeamStackingAfterFirstMinutes = 2;
                    MaxUnstackingSwapsPerRound = 2;
                    NumberOfSwapsPerGroup = 2;
                    DelaySecondsBetweenSwapGroups = SWAP_TIMEOUT;
                    MaxUnstackingTicketDifference = 0;
                    DefinitionOfHighPopulationForPlayers = 8;
                    DefinitionOfLowPopulationForPlayers = 4;
                    DefinitionOfEarlyPhaseFromStart = 0;
                    DefinitionOfLatePhaseFromEnd = 0;
                    break;
                case "Obliteration": // BF4
                    MaxPlayers = 32;
                    CheckTeamStackingAfterFirstMinutes = 2;
                    MaxUnstackingSwapsPerRound = 2;
                    NumberOfSwapsPerGroup = 2;
                    DelaySecondsBetweenSwapGroups = SWAP_TIMEOUT;
                    MaxUnstackingTicketDifference = 0;
                    DefinitionOfHighPopulationForPlayers = 24;
                    DefinitionOfLowPopulationForPlayers = 8;
                    DefinitionOfEarlyPhaseFromStart = 1;
                    DefinitionOfLatePhaseFromEnd = 1;
                    break;
                case "Unknown or New Mode":
                default:
                    MaxPlayers = 32;
                    CheckTeamStackingAfterFirstMinutes = 10;
                    MaxUnstackingSwapsPerRound = 2;
                    NumberOfSwapsPerGroup = 2;
                    DelaySecondsBetweenSwapGroups = SWAP_TIMEOUT;
                    MaxUnstackingTicketDifference = 0;
                    DefinitionOfHighPopulationForPlayers = 24;
                    DefinitionOfLowPopulationForPlayers = 8;
                    DefinitionOfEarlyPhaseFromStart = 50;
                    DefinitionOfLatePhaseFromEnd = 50;
                    break;
                }
            }
 double GetAveragePlayerStats(int teamId, DefineStrong stat)
 {
     double avg = 0;
     List<PlayerModel> team = GetTeam(teamId);
     if (team.Count < 1) return 0;
     double n = Convert.ToDouble(team.Count);
     switch (stat) {
     case DefineStrong.BattlelogKDR:
     foreach (PlayerModel player in team) {
         avg = avg + player.KDR;
     }
     break;
     case DefineStrong.BattlelogKPM:
     foreach (PlayerModel player in team) {
         avg = avg + player.KPM;
     }
     break;
     case DefineStrong.BattlelogSPM:
     foreach (PlayerModel player in team) {
         avg = avg + player.SPM;
     }
     break;
     case DefineStrong.PlayerRank:
     foreach (PlayerModel player in team) {
         avg = avg + player.Rank;
     }
     break;
     case DefineStrong.RoundKDR:
     foreach (PlayerModel player in team) {
         avg = avg + player.KDRRound;
     }
     break;
     case DefineStrong.RoundKills:
     foreach (PlayerModel player in team) {
         avg = avg + player.KillsRound;
     }
     break;
     case DefineStrong.RoundKPM:
     foreach (PlayerModel player in team) {
         avg = avg + player.KPMRound;
     }
     break;
     case DefineStrong.RoundScore:
     foreach (PlayerModel player in team) {
         avg = avg + player.ScoreRound;
     }
     break;
     case DefineStrong.RoundSPM:
     foreach (PlayerModel player in team) {
         avg = avg + player.SPMRound;
     }
     break;
     default: return 0;
     }
     return (avg / n);
 }