Пример #1
0
        public static Dictionary <ulong, PlayerSummary> PlayerBestScoresSummary(IEnumerable <Dictionary <ulong, Record> > results, int nPositions = 20)
        {
            Dictionary <ulong, PlayerSummary> summary = new();
            int i = 0;

            foreach (Dictionary <ulong, Record> mapBestScores in results)
            {
                foreach (Record rec in mapBestScores.Values)
                {
                    if (!summary.TryGetValue(rec.SteamID, out PlayerSummary playerSummary))
                    {
                        playerSummary = new PlayerSummary()
                        {
                            name      = rec.Name,
                            positions = new int[nPositions],
                        };
                        summary[rec.SteamID] = playerSummary;
                    }
                    if (rec.Position <= nPositions)
                    {
                        playerSummary.positions[rec.Position - 1]++;
                        playerSummary.totalPositions += rec.Position;
                        playerSummary.totalPoints    += 21 - rec.Position;
                    }
                    if (rec.OldPosition > 0 && rec.OldPosition <= nPositions)
                    {
                        playerSummary.totalPointsOld += 21 - rec.OldPosition;
                    }
                }
                i++;
            }
            return(summary);
        }
Пример #2
0
        public PlayerSummary SavePlayer([FromBody] PlayerSummary player)
        {
            var playerMgr = Dependency.Resolve <IPlayerManager>();

            // Save player
            return(playerMgr.SavePlayer(player.PlayerID, player.FirstName, player.LastName, player.Phone, player.Email));
        }
Пример #3
0
        public Embed CreateAchievementEmbed(Achievement achievement, PlayerSummary summary, int totalAchievements, int achieved)
        {
            EmbedBuilder e = new EmbedBuilder();

            e.Color     = new Color(20, 48, 93);
            e.Title     = $"New achievement in {summary.gameextrainfo} ({achieved}/{totalAchievements})";
            e.Url       = $"https://store.steampowered.com/app/{summary.gameid}";
            e.Timestamp = DateTimeOffset.FromUnixTimeSeconds(achievement.unlocktime);

            EmbedAuthorBuilder author = new EmbedAuthorBuilder();

            author.Name    = summary.personaname;
            author.Url     = $"{summary.profileurl}";
            author.IconUrl = $"{summary.avatar}";
            e.Author       = author;

            EmbedFooterBuilder footer = new EmbedFooterBuilder();

            footer.IconUrl = "https://upload.wikimedia.org/wikipedia/commons/thumb/8/83/Steam_icon_logo.svg/2000px-Steam_icon_logo.svg.png";
            footer.Text    = "Steam";
            e.Footer       = footer;

            e.AddField($"{achievement.displayName}", String.IsNullOrEmpty(achievement.description) ? "No description" : achievement.description, true);
            e.AddField("Rarity", Math.Round(achievement.percent, 2) + "%", true);
            e.WithThumbnailUrl(achievement.icon);
            e.WithImageUrl($"https://steamcdn-a.akamaihd.net/steam/apps/{summary.gameid}/header.jpg");

            return(e.Build());
        }
Пример #4
0
        public async Task <PlayerSummary> GetProfile(uint accountId)
        {
            var summary = await DotaProfile(accountId);

            if (summary == null)
            {
                return(null);
            }

            var profile = new PlayerSummary()
            {
                AccountId    = accountId,
                Avatar       = summary.Avatar,
                OverallRank  = summary.OverallRank,
                Persona      = summary.Nickname,
                Rating       = summary.Rating,
                Region       = summary.Region,
                RegionalRank = summary.RegionalRank,
                Winrate      = summary.WinLoss.Winrate,
                Wins         = summary.WinLoss.Wins,
                Losses       = summary.WinLoss.Losses,
            };

            return(profile);
        }
Пример #5
0
        public static Dictionary <ulong, PlayerSummary> SingleMatchdaySummary(IEnumerable <Dictionary <ulong, Record> > results)
        {
            Dictionary <ulong, PlayerSummary> summary = new();
            int nEvents = results.Count();
            int i       = 0;

            foreach (Dictionary <ulong, Record> eventResults in results)
            {
                foreach (Record rec in eventResults.Values)
                {
                    if (!summary.TryGetValue(rec.SteamID, out PlayerSummary playerSummary))
                    {
                        playerSummary = new PlayerSummary()
                        {
                            name      = rec.Name,
                            points    = new decimal[nEvents],
                            positions = new int[nEvents],
                        };
                        summary[rec.SteamID] = playerSummary;
                    }
                    playerSummary.points[i]       = rec.Points;
                    playerSummary.positions[i]    = rec.Position;
                    playerSummary.totalPoints    += rec.Points;
                    playerSummary.totalPositions += rec.Position;
                    playerSummary.nTracks++;
                }
                i++;
            }
            // Calculate rankings
            CalculateRanks(summary);
            return(summary);
        }
Пример #6
0
        public void Setup()
        {
            _response = JsonConvert.DeserializeObject <PlayerSummary>(File.ReadAllText(Json));

            var mock = new Mock <IHaloSession>();

            mock.Setup(m => m.Get <PlayerSummary>(It.IsAny <string>()))
            .ReturnsAsync(_response);

            _mockSession = mock.Object;
        }
Пример #7
0
        public PlayerSummary SavePlayer(int playerID, [FromBody] PlayerSummary player)
        {
            player.PlayerID = playerID;
            // We now need to check if the player exists first...
            var existingPlayer = Dependency.Resolve <IPlayerManager>().GetPlayer(player.PlayerID);

            if (existingPlayer == null)
            {
                throw new UserException("The player could not be retrieved from the datastore");
            }
            return(this.SavePlayer(player));
        }
Пример #8
0
        public static string GetAccountSummary(ulong SteamID)
        {
            PlayerSummary account = GetAccountObject(SteamID);

            string username                 = account.personaname;
            ulong  steamid                  = account.steamid;
            string realName                 = account.realname;
            string avatarURL                = account.avatarfull;
            string personastate             = account.personastate.ToString();
            string communityvisibilitystate = account.communityvisibilitystate.ToString();
            string profileURL               = account.profileurl;
            string timecreated              = account.timecreated.ToString();
            string lastlogoff               = account.lastlogoff.ToString();
            string countrycode              = account.loccountrycode;
            string statecode                = account.locstatecode;
            string cityid            = account.loccityid;
            string clanid            = account.primaryclanid.ToString();
            string commentpermission = account.commentpermission.ToString();

            /*
             * Console.WriteLine("Username: "******"Real Name: " + realName);
             * Console.WriteLine("Avatar URL: " + avatarURL);
             * Console.WriteLine("Persona State: " + personastate);
             * Console.WriteLine("Community State: " + communityvisibilitystate);
             * Console.WriteLine("Profile URL: " + profileURL);
             * Console.WriteLine("Time Created: " + timecreated);
             * Console.WriteLine("Last Logoff: " + lastlogoff);
             * Console.WriteLine("Country: " + countrycode);
             * Console.WriteLine("State: " + statecode);
             * Console.WriteLine("City ID: " + cityid);
             * Console.WriteLine("Clan ID: " + clanid);
             * Console.WriteLine("SteamID: " + SteamID);
             * Console.WriteLine(CheckInGame(account));*/
            string msg = "**Username:** " + username + "\n**Steam ID:** " + steamid + "\n**Real Name:** " + realName + "\n**Online State:** " + SetPersonaState(int.Parse(personastate)) + "\n" +
                         "**Time Created:** " + UnixTimeStampToDateTime(double.Parse(timecreated)) + "\n**Last Logoff:** " +
                         UnixTimeStampToDateTime(double.Parse(lastlogoff)) + "\n**Primary Clan ID:** " + clanid + "\n**Community Visibility State:** " + SetCommunityState(int.Parse(communityvisibilitystate)) +
                         "\n**Allows Public Profile Comments:** " + commentpermission + "\n**Country:** " + countrycode + "\n**State:** " + statecode + "\n**City ID:** " + cityid + "\n**Profile URL:** " +
                         profileURL + "\n**Avatar URL:** " + avatarURL + CheckInGame(account);

            /*
             * if (objData[0][""].ContainsKey("steamid"))
             * {
             *  steamID = r["response"]["steamid"];
             *  Console.WriteLine("SteamID: " + steamID);
             * }
             * else
             * {
             *  steamID = r["response"]["message"];
             * }*/
            return(msg);
        }
Пример #9
0
        // Queries all player info.
        public static Player Query(string apikey, long playerId)
        {
            Player player = new Player
            {
                Summary     = PlayerSummary.Query(apikey, playerId),
                BanInfo     = PlayerBanInfo.Query(apikey, playerId),
                OwnedGames  = OwnedGameInfo.Query(apikey, playerId, true),
                RecentGames = OwnedGameInfo.QueryRecent(apikey, playerId, 3),
                Friends     = Friend.Query(apikey, playerId)
            };

            return(player);
        }
Пример #10
0
        public async Task <PlayerSummary> SavePlayer(PlayerSummary player)
        {
            BaseAPI <PlayerSummary> api = new BaseAPI <PlayerSummary>();

            api.RelativeUrl = "player/saveplayer";
            api.ParameterDictionary.Add("PlayerID", player.PlayerID.ToString());
            api.ParameterDictionary.Add("FirstName", player.FirstName);
            api.ParameterDictionary.Add("LastName", player.LastName);
            api.ParameterDictionary.Add("Email", player.Email);
            api.ParameterDictionary.Add("Phone", player.Phone);
            api.ParameterDictionary.Add("IsDeleted", false.ToString());
            var result = await api.GetAsync();

            return(result);
        }
Пример #11
0
        public ActionResult PlayerSummary()
        {
            var entity = new PlayerSummary
            {
                PlayerDetails    = SessionManager.Get <PlayerDetails>("playerDetails"),
                PlayerStatistics = SessionManager.Get <PlayerStatistics>("playerStatistics")
            };

            //save data

            //clean session
            SessionManager.Remove("playerDetails");
            SessionManager.Remove("playerStatistics");

            return(RedirectToAction("PlayerDetails"));
        }
        void FriendItem_Clicked(object sender, MouseButtonEventArgs e)
        {
            var control = sender as FriendControl;

            if (control == null)
            {
                return;
            }

            CheckCreateChatWindow();

            PlayerSummary summary = FriendSummaries.FirstOrDefault(x => x.PersonaName == control.personaName.Text);

            if (summary != null)
            {
                ChatWindow.AddChatWindow(control.Friend, string.Empty);
            }
        }
Пример #13
0
        public async Task <ActionResult> JoinSession([FromRoute] string sessionId)
        {
            Task <UserModel> userTask = userManager.GetUserAsync(HttpContext.User);
            Task <Game>      gameTask = gameService.Get(sessionId);
            Session?         session  = await sessionService.Get(sessionId);

            if (session == null)
            {
                return(Status404NotFound("Session"));
            }
            if (session.LinkEnabled == false)
            {
                return(Status400Invalid("Session is private."));
            }
            if ((session.Players.Count + session.Invitations.Length) >= 4)
            {
                return(Status400Invalid("Session is full."));
            }
            Game game = await gameTask;

            if (game.Status != GameStatus.Preparing)
            {
                return(Status400Invalid("Game has started."));
            }
            UserModel user = await userTask;

            if (session.Players.Any((kvp) => kvp.Key == user.UserId))
            {
                return(NoContent());
            }

            user.AddSession(session);
            List <Task> updateTasks = new List <Task> {
                userManager.UpdateAsync(user)
            };

            GameOperations.AddPlayer(game, user.UserId);
            updateTasks.Add(gameService.Update(sessionId, game));
            session.Players.Add(user.UserId, PlayerSummary.CreateFromUser(user));
            updateTasks.Add(sessionService.Update(sessionId, session));
            Task.WaitAll(updateTasks.ToArray());
            return(NoContent());
        }
        void OnMessage(object sender, ChatMessageArgs e)
        {
            CheckCreateChatWindow();

            PlayerSummary summary =
                FriendSummaries.FirstOrDefault(
                    x => x.SteamId == IdConversions.AccountIdToUlong(e.ChatMessage.AccountIdFrom));

            if (summary == null)
            {
                MessageBox.Show("I was lazy and I don't poll for new friends. They attempted to send you a message.");
                return;
            }

            List <FriendControl> friendControls = new List <FriendControl>();
            ChatUser             friend         = null;

            friendsStackPanel.Dispatcher.Invoke(() =>
            {
                friendControls = friendsStackPanel.Children.Cast <FriendControl>().ToList();
            });

            foreach (FriendControl control in friendControls)
            {
                ulong steamId = 0;
                control.Dispatcher.Invoke(() => { steamId = control.Friend.Summary.SteamId; });
                if (steamId != summary.SteamId)
                {
                    continue;
                }
                control.Dispatcher.Invoke(() => { friend = control.Friend; });
                break;
            }

            if (friend == null)
            {
                throw new Exception("Could not locate friend, please report this!");
            }

            ChatWindow.AddChatWindow(friend, e.ChatMessage.Text);
        }
Пример #15
0
 public static void UpdateMuitiMatchdaySummary(Dictionary <ulong, PlayerSummary> mmdSummary, Dictionary <ulong, PlayerSummary> mdSummary, int nPositions = 20, int nWins = 10)
 {
     foreach (var pair in mdSummary)
     {
         if (!mmdSummary.TryGetValue(pair.Key, out PlayerSummary playerSummary))
         {
             playerSummary = new PlayerSummary()
             {
                 name      = pair.Value.name,
                 points    = new decimal[10],
                 positions = new int[nPositions],
                 wins      = new int[nWins],
             };
             mmdSummary[pair.Key] = playerSummary;
         }
         foreach (int position in pair.Value.positions)
         {
             if (position >= 1 && position <= nPositions)
             {
                 playerSummary.positions[position - 1]++;
             }
         }
         foreach (decimal points in pair.Value.points)
         {
             if (points > 0)
             {
                 //playerSummary.points[10 - (int)points]++;
             }
         }
         playerSummary.totalPointsOld  = playerSummary.totalPoints;
         playerSummary.totalPoints    += pair.Value.totalPoints;
         playerSummary.totalPositions += pair.Value.totalPositions;
         playerSummary.nTracks        += pair.Value.nTracks;
         if (pair.Value.rank <= nWins)
         {
             playerSummary.wins[pair.Value.rank - 1]++;
         }
         playerSummary.parts++;
     }
 }
Пример #16
0
        public async Task CheckForNewAchievements(PlayerSummary summary, string gameId = null, bool setLastCheck = true)
        {
            if (gameId == null && CurrentGame != null)
            {
                gameId = CurrentGame;
            }
            else if (gameId != null)
            {
                summary = await GetUserSummaryAsync();

                var name = (await FetchJSONDataAsync <GameStats>($"http://api.steampowered.com/ISteamUserStats/GetSchemaForGame/v2/?appid={gameId}&key={Program.Config["SteamKey"]}")).game.gameName;
                summary.gameextrainfo = name;
                summary.gameid        = gameId;
            }

            if (gameId != null)
            {
                var achievements = await GetCompleteAchievements(gameId);

                var achievedCount       = achievements.Count(x => x.achieved == 1);
                var newAchievements     = achievements.TakeWhile(x => x.unlocktime > LastCheck).OrderBy(x => x.unlocktime);
                int curAchievementIndex = achievedCount - (newAchievements.Count() - 1);
                foreach (var achievement in newAchievements)
                {
                    var embed = CreateAchievementEmbed(achievement, summary, achievements.Count, curAchievementIndex++);
                    foreach (var channel in ChannelConfig.Keys.Where(x => (bool)ChannelConfig[x][ACHIEVEMENTCONFIG]))
                    {
                        await OnMajorChangeTracked(channel, embed, (string)ChannelConfig[channel]["Notification"]);
                    }
                }
                if (setLastCheck)
                {
                    LastCheck = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
                }
                await UpdateTracker();
            }
        }
Пример #17
0
 public static string CheckInGame(PlayerSummary account)
 {
     if (account.personastate != 0 && account.gameid != 0)
     {
         string msg = "\n\n**Currently Playing:** " + account.extragameinfo +
                      "\n**Game ID:** " + account.gameid;
         GameResponse r = GetAccountGames(account.steamid);
         foreach (Games game in r.games)
         {
             if (game.appid == account.gameid)
             {
                 msg = "\n\n**Currently Playing:** " + game.name +
                       "\n**Game ID:** " + account.gameid;
                 break;
             }
         }
         if (account.gameserverip != null)
         {
             msg += "\n**Game Server IP:** " + account.gameserverip;
         }
         return(msg);
     }
     return("");
 }
 public static int Compare(PlayerSummary x, PlayerSummary y)
 {
     return(x.totalPoints != y.totalPoints || x.nTracks == 0 ?
            y.totalPoints.CompareTo(x.totalPoints) :
            (y.totalPoints / y.nTracks).CompareTo(x.totalPoints / x.nTracks));
 }
 public static int CompareOld(PlayerSummary x, PlayerSummary y)
 {
     return(x.totalPointsOld != y.totalPointsOld || x.nTracks == 0 ?
            y.totalPointsOld.CompareTo(x.totalPointsOld) :
            (y.totalPointsOld / y.nTracks).CompareTo(x.totalPointsOld / x.nTracks));
 }
Пример #20
0
    public void TakeSnapshot()
    {
        TimeStart = Time.realtimeSinceStartup;
        Logger.trace("::::: Take Snapshot :::::");
        BonusXP       = GameData.getPlayerStat(GameData.MyPlayerId, "bonusXP");
        BonusCredits  = GameData.getPlayerStat(GameData.MyPlayerId, "bonusCred");
        XpGained      = GameData.MyBattleXP;
        CreditsGained = GameData.MyBattleCredits;
        for (int i = 0; i < 8; i++)
        {
            PlayerOrder[i] = i;
        }
        for (int j = 0; j < BanzaiOrder.Length; j++)
        {
            BanzaiOrder[j] = -1;
            AtlasOrder[j]  = -1;
        }
        for (int k = 0; k < 8; k++)
        {
            User userFromRoom = GameData.getUserFromRoom(Parent.m_networkManager, k + 1);
            if (userFromRoom != null)
            {
                Logger.trace("Snapshot Player: " + (k + 1));
                Players[k] = new PlayerSummary();
                Players[k].Init(userFromRoom);
            }
            else
            {
                Players[k] = null;
            }
        }
        Logger.traceError("Starting sort");
        bool flag = true;
        int  num  = 0;

        while (flag)
        {
            Logger.traceError("Sort loop: " + num++);
            flag = false;
            for (int l = 0; l < PlayerOrder.Length - 1; l++)
            {
                int num2 = CheckSwap(PlayerOrder, l, l + 1, Players[PlayerOrder[l]].GetHacks, Players[PlayerOrder[l + 1]].GetHacks);
                if (1 <= num2)
                {
                    flag = true;
                }
                else if (num2 == 0 && CheckSwap(PlayerOrder, l + 1, l, Players[PlayerOrder[l + 1]].GetCrashes, Players[PlayerOrder[l]].GetCrashes) == 1)
                {
                    flag = true;
                }
            }
        }
        Logger.traceError("Ended sort loop in " + num + " cycles");
        if (GameData.BattleType == 2)
        {
            int num3 = 0;
            int num4 = 0;
            for (int m = 0; m < 8; m++)
            {
                if (Players[PlayerOrder[m]] != null)
                {
                    switch (Players[PlayerOrder[m]].Faction)
                    {
                    case 1:
                        BanzaiOrder[num3++] = PlayerOrder[m];
                        break;

                    case 2:
                        AtlasOrder[num4++] = PlayerOrder[m];
                        break;
                    }
                }
            }
            bool flag2 = true;
            while (flag2)
            {
                flag2 = false;
                for (int n = 0; n < 3; n++)
                {
                    if (BanzaiOrder[n] == -1 && BanzaiOrder[n + 1] != -1)
                    {
                        int num5 = BanzaiOrder[n];
                        BanzaiOrder[n]     = BanzaiOrder[n + 1];
                        BanzaiOrder[n + 1] = num5;
                        flag2 = true;
                    }
                    else
                    {
                        if (BanzaiOrder[n] == -1 || BanzaiOrder[n + 1] == -1)
                        {
                            continue;
                        }
                        switch (CheckSwap(BanzaiOrder, n, n + 1, Players[BanzaiOrder[n]].GetHacks, Players[BanzaiOrder[n + 1]].GetHacks))
                        {
                        case 1:
                            flag = true;
                            break;

                        case 0:
                            if (CheckSwap(BanzaiOrder, n + 1, n, Players[BanzaiOrder[n + 1]].GetCrashes, Players[BanzaiOrder[n]].GetCrashes) == 1)
                            {
                                flag = true;
                            }
                            break;
                        }
                    }
                }
                for (int num6 = 0; num6 < 3; num6++)
                {
                    if (AtlasOrder[num6] == -1 && AtlasOrder[num6 + 1] != -1)
                    {
                        int num7 = AtlasOrder[num6];
                        AtlasOrder[num6]     = BanzaiOrder[num6 + 1];
                        AtlasOrder[num6 + 1] = num7;
                        flag2 = true;
                    }
                    else
                    {
                        if (AtlasOrder[num6] == -1 || AtlasOrder[num6 + 1] == -1)
                        {
                            continue;
                        }
                        switch (CheckSwap(AtlasOrder, num6, num6 + 1, Players[AtlasOrder[num6]].GetHacks, Players[AtlasOrder[num6 + 1]].GetHacks))
                        {
                        case 1:
                            flag = true;
                            break;

                        case 0:
                            if (CheckSwap(AtlasOrder, num6 + 1, num6, Players[AtlasOrder[num6 + 1]].GetCrashes, Players[AtlasOrder[num6]].GetCrashes) == 1)
                            {
                                flag = true;
                            }
                            break;
                        }
                    }
                }
            }
        }
        MissionNum = GameData.LatestCompletedMissions.Count - 1;
        DoStats();
        bRankup = false;
    }
Пример #21
0
 protected override async Task OnAppearing()
 {
     this.SelectedPlayer = null;
 }
Пример #22
0
 // Retrieves player summary.
 public PlayerSummary GetPlayerSummary(long playerId)
 {
     return(PlayerSummary.Query(Key, playerId));
 }
Пример #23
0
 public PlayerEditorModel(IContentPage ui, PlayerSummary player) : base(ui)
 {
     //if (player == null) this.Player = new PlayerSummary();
     this.Player = player;
 }
Пример #24
0
 public PlayerEditor(PlayerSummary player)
 {
     InitializeComponent();
     this.BindingContext = new PlayerEditorModel(this, player);
 }
Пример #25
0
        public static Table MakeSummaryTable(Dictionary <ulong, PlayerSummary> summary, string summaryName = "RESULTS",
                                             IEnumerable <string> headings = null, bool frequencyData = false, bool usePoints = true)
        {
            Table table = new();

            if (!summary.Any())
            {
                return(table);
            }

            // Check what information is available in the summary
            PlayerSummary firstSummary      = summary.First().Value;
            bool          hasTotalPoints    = firstSummary.totalPoints > 0;
            bool          hasTracks         = firstSummary.nTracks > 0;
            bool          hasParts          = firstSummary.parts > 0;
            bool          hasWins           = firstSummary.wins != null && firstSummary.wins.Length > 0;
            bool          hasPoints         = firstSummary.points != null && firstSummary.points.Length > 0;
            bool          hasPositions      = firstSummary.positions != null && firstSummary.positions.Length > 0;
            bool          hasOldRanks       = false;
            bool          hasOldTotalPoints = false;

            foreach (PlayerSummary playerSummary in summary.Values)
            {
                if (playerSummary.showRankDelta && playerSummary.rankOld != 0)
                {
                    hasOldRanks = true;
                }
                if (playerSummary.showPointDelta && playerSummary.totalPointsOld != 0)
                {
                    hasOldTotalPoints = true;
                }
                if (hasOldRanks && hasOldTotalPoints)
                {
                    break;
                }
            }

            // Headings
            int r = 0;
            int c = 0;

            table[r, c++] = "#";
            if (hasOldRanks)
            {
                c++;
            }
            table[r, c++] = summaryName;
            if (headings == null && frequencyData && usePoints)
            {
                // By default use point ranges
                headings = summaryHeadingsPoints;
            }
            if ((hasPoints && usePoints) || (hasPositions && !usePoints))
            {
                if (headings != null)
                {
                    foreach (string heading in headings)
                    {
                        table[r, c++] = heading;
                    }
                }
                else if (frequencyData)
                {
                    // By default use positions (maximum given in the summary)
                    int nPositions = firstSummary.positions.Length;
                    for (int i = 0; i < nPositions; i++)
                    {
                        table[r, c++] = (i + 1) + "°";
                    }
                }
                else
                {
                    // By default use the acronyms for all 21 tracks
                    foreach (Map map in Indexing.mapOrder)
                    {
                        table[r, c++] = ((MapAcronym)(uint)map).ToString();
                    }
                }
                c++;
            }
            if (hasTotalPoints)
            {
                table[r, c++] = "PTS";
            }
            if (hasOldTotalPoints)
            {
                c++;
            }
            if (hasTracks)
            {
                table[r, c++] = "Tracks";
            }
            if (hasTotalPoints && hasTracks)
            {
                table[r, c++] = "AVERAGE";
            }
            if (hasParts)
            {
                table[r, c++] = "PARTS";
            }
            if (hasWins)
            {
                int nWins = firstSummary.wins.Length;
                for (int i = 0; i < nWins; i++)
                {
                    table[r, c++] = (i + 1) + "°";
                }
            }

            // Data
            foreach (PlayerSummary playerSummary in summary.Values)
            {
                r = playerSummary.rank;
                c = 0;
                string rank =
                    table[r, c++] = playerSummary.rank + "°";
                if (hasOldRanks)
                {
                    if (playerSummary.showRankDelta && playerSummary.rankOld != 0 && (playerSummary.totalPoints > 0 || playerSummary.totalPointsOld > 0))
                    {
                        table[r, c] = Details.DeltaIndicator(playerSummary.rankOld, playerSummary.rank, inverseArrow: true);
                    }
                    c++;
                }
                table[r, c++] = playerSummary.name;
                if (usePoints && hasPoints)
                {
                    foreach (decimal points in playerSummary.points)
                    {
                        if (points != 0)
                        {
                            table[r, c] = Record.TruncatedNumString(points.ToString(), 3);
                        }
                        c++;
                    }
                    c++;
                }
                if (!usePoints && hasPositions)
                {
                    foreach (int position in playerSummary.positions)
                    {
                        if (position != 0)
                        {
                            table[r, c] = position.ToString();
                        }
                        c++;
                    }
                    c++;
                }
                if (hasTotalPoints)
                {
                    table[r, c++] = Record.TruncatedNumString(playerSummary.totalPoints.ToString(), 3);
                }
                if (hasOldTotalPoints)
                {
                    if (playerSummary.showPointDelta && playerSummary.totalPointsOld != 0)
                    {
                        table[r, c] = Details.DeltaIndicator(playerSummary.totalPointsOld, playerSummary.totalPoints, inverseArrow: false);
                    }
                    c++;
                }
                if (hasTracks)
                {
                    table[r, c++] = playerSummary.nTracks.ToString();
                }
                if (hasTotalPoints && hasTracks)
                {
                    table[r, c++] = Record.TruncatedNumString((playerSummary.totalPoints / playerSummary.nTracks * 10).ToString(), 3);
                }
                if (hasParts)
                {
                    table[r, c++] = playerSummary.parts.ToString();
                }
                if (hasWins)
                {
                    foreach (int win in playerSummary.wins)
                    {
                        if (win != 0)
                        {
                            table[r, c] = win.ToString();
                        }
                        c++;
                    }
                }
            }

            return(table);
        }