PRoConEvents.MULTIbalancer.LogStatus C# (CSharp) Method

LogStatus() private method

private LogStatus ( bool isFinal, int level ) : void
isFinal bool
level int
return void
        private void LogStatus(bool isFinal, int level)
        {
            try {
            String tmsg = null;
            // If server is empty, log status only every 60 minutes
            int totalPlayers = TotalPlayerCount();
            if (!isFinal && level < 9 && totalPlayers == 0) {
            if (fRoundStartTimestamp != DateTime.MinValue && DateTime.Now.Subtract(fRoundStartTimestamp).TotalMinutes <= 60) {
            return;
            } else {
            fRoundStartTimestamp = DateTime.Now;
            }
            }

            if (!isFinal && (level == 4)) ConsoleWrite("+------------------------------------------------+", 0);

            if (isFinal && fWinner != 0) {
            tmsg = "^1Winner was team " + fWinner + " (" + GetTeamName(fWinner) + ")^0";
            DebugWrite("^bStatus^n: " + tmsg, 2);
            ProconChat(tmsg);
            }

            Speed balanceSpeed = Speed.Adaptive;

            String tm = fTickets[1] + "/" + fTickets[2];
            if (IsSQDM()) tm = tm + "/" + fTickets[3] + "/" + fTickets[4];
            if (IsRush()) tm = tm  + "(" + Math.Max(fTickets[1]/2, fMaxTickets - (fRushMaxTickets - fTickets[2])) + ")";
            bool isCTF = IsCTF();
            bool isCarrierAssault = IsCarrierAssault();
            bool isObliteration = IsObliteration();
            if (isCTF || isCarrierAssault || isObliteration) tm = GetTeamPoints(1) + "/" + GetTeamPoints(2);

            double goal = 0;
            bool countDown = true;
            if (IsCountUp()) {
            countDown = false;
            if (fServerInfo.TeamScores != null && fServerInfo.TeamScores.Count > 1) {
            foreach (TeamScore ts in fServerInfo.TeamScores) {
                if (ts.TeamID == 1) {
                    goal = ts.WinningScore;
                    break;
                }
            }
            }
            }

            if (goal == 0) {
            if (fMaxTickets != -1) {
            tm = tm + " <- [" + fMaxTickets.ToString("F0") + "]";
            goal = fMaxTickets;
            }
            } else {
            tm = tm + " -> [" + goal.ToString("F0") + "]";
            }

            String rt = GetTimeInRoundString();

            PerModeSettings perMode = GetPerModeSettings();

            String metroAdj = (perMode.EnableMetroAdjustments) ? ", Metro Adjustments Enabled" : String.Empty;
            String unstackDisabled = (!EnableUnstacking) ? ", Unstacking Disabled" : String.Empty;
            String logOnly = (EnableLoggingOnlyMode) ? ", Logging Only Mode Enabled" : String.Empty;
            String weakOnly = (perMode.OnlyMoveWeakPlayers) ? ", Only Move Weak Players" : String.Empty;
            String fastBalance = (EnableAdminKillForFastBalance) ? ", Admin Kill Enabled": String.Empty;

            if (level >= 6) DebugWrite("^bStatus^n: Plugin state = " + fPluginState + ", game state = " + fGameState + fastBalance + weakOnly + metroAdj + unstackDisabled + logOnly, 0);
            int useLevel = (isFinal) ? 2 : 4;
            if (IsRush()) {
            tmsg = "Map = " + this.FriendlyMap + ", mode = " + this.FriendlyMode + ", stage = " + fRushStage + ", time in round = " + rt + ", tickets = " + tm;
            } else if (isCTF || isCarrierAssault || isObliteration) {
            tmsg = "Map = " + this.FriendlyMap + ", mode = " + this.FriendlyMode + ", time in round = " + rt + ", score = " + tm;
            } else {
            tmsg = "Map = " + this.FriendlyMap + ", mode = " + this.FriendlyMode + ", time in round = " + rt + ", tickets = " + tm;
            }
            if (level >= useLevel)
            DebugWrite("^bStatus^n: " + tmsg, 0);
            if (isFinal)
            ProconChat(tmsg);

            int ticketGap = Math.Abs(fTickets[1] - fTickets[2]);
            if (IsRush()) ticketGap = Convert.ToInt32(Math.Abs(fTickets[1] - Math.Max(fTickets[1]/2, fMaxTickets - (fRushMaxTickets - fTickets[2]))));
            if (perMode.EnableTicketLossRatio && false) { // disable for this release
            double a1 = GetAverageTicketLossRate(1, !EnableTicketLossRateLogging);
            double a2 = GetAverageTicketLossRate(2, !EnableTicketLossRateLogging);
            double rat = (a1 > a2) ? (a1/Math.Max(1, a2)) : (a2/Math.Max(1, a1));
            rat = Math.Min(rat, 50.0); // cap at 50x
            rat = rat * 100.0;
            if (level >= useLevel) DebugWrite("^bStatus^n: Ticket difference = " + ticketGap + ", average ticket loss = " + a1.ToString("F2") + "(US) vs " + a2.ToString("F2") + " (RU)" + " for " + perMode.TicketLossSampleCount + " samples, ratio is " + rat.ToString("F0") + "%", 0);
            } else if (!IsSQDM() && fServerInfo.GameMode != "GunMaster0")  {
            bool privIsRush = IsRush();
            double a1 = fTickets[1];
            double a2 = (privIsRush) ? (Math.Max(fTickets[1]/2, fMaxTickets - (fRushMaxTickets - fTickets[2]))) : fTickets[2];
            double rat = (a1 > a2) ? (a1/Math.Max(1, a2)) : (a2/Math.Max(1, a1));
            // For end of round, use standard function for ratio
            if (fTickets[1] < 1 || fTickets[2] < 1) {
            String cmsg = String.Empty;
            a1 = fTickets[1];
            a2 = fTickets[2];
            rat = ComputeTicketRatio(a1, a2, goal, countDown, out cmsg);
            DebugWrite("^9DEBUG: " + cmsg, 7);
            }
            rat = Math.Min(rat, 50.0); // cap at 50x
            rat = rat * 100.0;
            String extra = ", score " + GetTeamPoints(1) + "/" + GetTeamPoints(2);
            if (perMode.EnableUnstackingByPlayerStats) {
            a1 = GetAveragePlayerStats(1, perMode.DetermineStrongPlayersBy);
            a2 = GetAveragePlayerStats(2, perMode.DetermineStrongPlayersBy);
            double ratio = (a1 > a2) ? (a1/Math.Max(0.01, a2)) : (a2/Math.Max(0.01, a1));
            ratio = Math.Min(ratio, 50.0); // cap at 50x

            String cmp = (a1 > a2) ? (a1.ToString("F1") + "/" + a2.ToString("F1")) : (a2.ToString("F1") + "/" + a1.ToString("F1"));
            extra = ", average " + perMode.DetermineStrongPlayersBy + " stats ratio = " + (ratio*100.0).ToString("F0") + "% (" + cmp + ")";
            } else if ((privIsRush && perMode.EnableAdvancedRushUnstacking) || isCTF || isCarrierAssault || isObliteration) {
            // Check team points as well as tickets
            double usPoints = GetTeamPoints(1);
            double ruPoints = GetTeamPoints(2);
            if (usPoints <= 0) usPoints = 1;
            if (ruPoints <= 0) ruPoints = 1;
            double sratio = (usPoints > ruPoints) ? (usPoints/ruPoints) : (ruPoints/usPoints);
            String cr = (usPoints > ruPoints) ? (usPoints.ToString("F0") + "/" + ruPoints.ToString("F0")) : (ruPoints.ToString("F0") + "/" + usPoints.ToString("F0")) ;
            extra = ", score ratio = " + (sratio * 100).ToString("F0") + "% (" + cr + ")";
            }
            if (level >= useLevel) DebugWrite("^bStatus^n: Ticket difference = " + ticketGap + ", ticket ratio percentage is " + rat.ToString("F0") + "%" + extra, 0);
            }

            if (fPluginState == PluginState.Active) {
            double secs = DateTime.Now.Subtract(fLastBalancedTimestamp).TotalSeconds;
            if (!fBalanceIsActive || fLastBalancedTimestamp == DateTime.MinValue) secs = 0;
            /*
            PerModeSettings perMode = null;
            String simpleMode = String.Empty;
            if (fModeToSimple.TryGetValue(fServerInfo.GameMode, out simpleMode)
              && fPerMode.TryGetValue(simpleMode, out perMode) && perMode != null) {
            */
            if (perMode != null) {
            balanceSpeed = GetBalanceSpeed(perMode);
            double unstackRatio = GetUnstackTicketRatio(perMode);
            String activeTime = (secs > 0) ? "^1active (" + secs.ToString("F0") + " secs)^0" : "not active";
            if (level >= 4) DebugWrite("^bStatus^n: Autobalance is " + activeTime + ", phase = " + GetPhase(perMode, false) + ", population = " + GetPopulation(perMode, false) + ", speed = " + balanceSpeed + ", unstack when ratio >= " + (unstackRatio * 100).ToString("F0") + "%", 0);
            }
            }
            if (!IsModelInSync()) {
            double toj = (fTimeOutOfJoint == 0) ? 0 : GetTimeInRoundMinutes() - fTimeOutOfJoint;
            if (level >= 6) DebugWrite("^bStatus^n: Model not in sync for " + toj.ToString("F1") + " mins: fMoving = " + fMoving.Count + ", fReassigned = " + fReassigned.Count, 0);
            }

            String raged = fRageQuits.ToString() + "/" + fTotalQuits + " raged, ";
            useLevel = (isFinal) ? 2 : 5;
            if (level >= useLevel) DebugWrite("^bStatus^n: " + raged + fReassignedRound + " reassigned, " + fBalancedRound + " balanced, " + fUnstackedRound + " unstacked, " + fUnswitchedRound + " unswitched, " + fExcludedRound + " excluded, " + fExemptRound + " exempted, " + fFailedRound + " failed; of " + fTotalRound + " TOTAL", 0);

            useLevel = (isFinal) ? 2 : 4;
            String bf4Extras = (fGameVersion != GameVersion.BF3) ? ", " + fBF4CommanderCount + " commanders, " + fBF4SpectatorCount + " spectators" : String.Empty;
            if (IsSQDM()) {
            if (level >= useLevel) DebugWrite("^bStatus^n: Team counts [" + totalPlayers + "] = " + fTeam1.Count + "(A) vs " + fTeam2.Count + "(B) vs " + fTeam3.Count + "(C) vs " + fTeam4.Count + "(D), with " + fUnassigned.Count + " unassigned" + bf4Extras, 0);
            } else {
            if (level >= useLevel) DebugWrite("^bStatus^n: Team counts [" + totalPlayers + "] = " + fTeam1.Count + "(" + GetTeamName(1) + ") vs " + fTeam2.Count + "(" + GetTeamName(2) + "), with " + fUnassigned.Count + " unassigned" + bf4Extras, 0);
            }

            List<int> counts = new List<int>();
            counts.Add(fTeam1.Count);
            counts.Add(fTeam2.Count);
            if (IsSQDM()) {
            counts.Add(fTeam3.Count);
            counts.Add(fTeam4.Count);
            }

            // Announce autobalancing status

            counts.Sort();
            int diff = Math.Abs(counts[0] - counts[counts.Count-1]);
            String next = "^n";
            String annType = null;

            if (EnableAdminKillForFastBalance && diff > MaxFastDiff()) {
            next = "^n^0 ... fast balance with admin kills in progress!";
            annType = "USING ADMIN KILL";
            } else if ((totalPlayers >= 6 && diff > MaxDiff() && fGameState == GameState.Playing && balanceSpeed != Speed.Stop && !fBalanceIsActive)) {
            next = "^n^0 ... autobalance will activate as soon as possible!";

            if (fUnassigned.Count >= (diff - MaxDiff())) {
            annType = "WAITING FOR " + fUnassigned.Count + " PLAYERS TO JOIN";
            } else {
            annType = "MOVE ON DEATH";
            }
            }

            // Team difference

            if (level >= 4) {
            String md = ((diff > MaxDiff()) ? "^8^b" : "^b") + diff + ((diff > MaxFastDiff() && EnableAdminKillForFastBalance) ? " (FAST)" : String.Empty);
            DebugWrite("^bStatus^n: Team difference = " + md + next, 0);
            }

            // chats and yells
            if (fLastAutoChatTimestamp == DateTime.MinValue || DateTime.Now.Subtract(fLastAutoChatTimestamp).TotalSeconds > (YellDurationSeconds + 2.0)) {
            String cab = ChatAutobalancing;
            String yab = YellAutobalancing;
            if (!String.IsNullOrEmpty(cab) && cab.Contains("%technicalDetails%"))
            cab = cab.Replace("%technicalDetails%", annType);
            if (!String.IsNullOrEmpty(yab) && yab.Contains("%technicalDetails%"))
            yab = yab.Replace("%technicalDetails%", annType);

            if (annType != null && !String.IsNullOrEmpty(cab)) {
            fLastAutoChatTimestamp = DateTime.Now;
            Chat("all", cab);
            }
            if (annType != null && !String.IsNullOrEmpty(yab)) {
            fLastAutoChatTimestamp = DateTime.Now;
            Yell("all", yab);
            }
            }

              } catch (Exception e) {
            ConsoleException(e);
              }
        }
MULTIbalancer