<commit_before>﻿using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Discord;
using Discord.Rest;
using Discord.WebSocket;
using Microsoft.AspNetCore.Mvc;
using SoraBot.Data.Repositories.Interfaces;
using SoraBot.Services.Users;
using SoraBot.Services.Utils;
using SoraBot.WebApi.Dtos;

namespace SoraBot.WebApi.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class LeaderboardController : ControllerBase
    {
        private readonly IProfileRepository _profileRepo;
        private readonly IUserService _userService;
        private readonly DiscordSocketClient _client;
        private readonly DiscordRestClient _restClient;

        public LeaderboardController(
            IProfileRepository profileRepo, 
            IUserService userService,
            DiscordSocketClient client,
            DiscordRestClient restClient)
        {
            _profileRepo = profileRepo;
            _userService = userService;
            _client = client;
            _restClient = restClient;
        }

        [HttpGet("{guildId}")]
        public async Task<ActionResult<GuildLeaderboard>> GetLocalLeaderboard(ulong guildId)
        {
            var guild = _client.GetGuild(guildId);
            if (guild == null)
                return NotFound("The specified guild could not be found!");
            var gl = new GuildLeaderboard()
            {
                AvatarUrl = guild.IconUrl ?? _client.CurrentUser.GetAvatarUrl(),
                GuildName = guild.Name,
                Ranks = new List<GuildRank>(guild.MemberCount > 100 ? 100: guild.MemberCount) // Properly set capacity already for best performance!
            };

            var gUsersO = await _profileRepo.GetGuildUsersSorted(guildId);
            if (!gUsersO)
                return NotFound("Guild has no saved users!");

            var g = await _restClient.GetGuildAsync(guildId);
            // Create dictionary for easy and fast lookups later :)
            var users = (await g.GetUsersAsync().FlattenAsync()).ToDictionary(x=> x.Id, x=> x);
            var gUsers = (~gUsersO);
            for (var i = 0; i < gUsers.Count; i++)
            {
                var user = gUsers[i];
                int rank = i + 1;
                if (rank > 100) break;
                if (!users.TryGetValue(user.UserId, out var u))
                    continue;
                gl.Ranks.Add(new GuildRank()
                {
                    AvatarUrl = u.GetAvatarUrl() ?? u.GetDefaultAvatarUrl(),
                    Discrim = u.Discriminator,
                    Exp = user.Exp,
                    Name = u.Username,
                    Rank = rank
                });
            }

            return Ok(gl);
        }

        [HttpGet("global")]
        public async Task<ActionResult<GlobalLeaderboard>> GetGlobalLeaderboard()
        {
            var topUsers = await _profileRepo.GetTop150Users().ConfigureAwait(false);
            if (!topUsers)
                return NotFound("Could not fetch Leaderboard");
            
            var leaderboard = new GlobalLeaderboard(){ShardId = GlobalConstants.ShardId};
            var users = topUsers.Some();
            for (var i = 0; i < users.Count; i++)
            {
                var dbUser = users[i];
                var user = _userService.Get(dbUser.Id);
                if (!user) continue;
                int rank = i + 1;
                leaderboard.Ranks.Add(user.MatchSome((u) => new GuildRank()
                {
                    Rank = rank,
                    AvatarUrl = u.GetAvatarUrl() ?? u.GetDefaultAvatarUrl(),
                    Discrim = u.Discriminator,
                    Exp = dbUser.Exp,
                    Name = u.Username
                }));
                if (leaderboard.Ranks.Count >= 100) break;
            }

            return Ok(leaderboard);
        }
    }
}<commit_msg>#116 - Fix missing userId in global leaderboard<commit_after>﻿using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Discord;
using Discord.Rest;
using Discord.WebSocket;
using Microsoft.AspNetCore.Mvc;
using SoraBot.Data.Repositories.Interfaces;
using SoraBot.Services.Users;
using SoraBot.Services.Utils;
using SoraBot.WebApi.Dtos;

namespace SoraBot.WebApi.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class LeaderboardController : ControllerBase
    {
        private readonly IProfileRepository _profileRepo;
        private readonly IUserService _userService;
        private readonly DiscordSocketClient _client;
        private readonly DiscordRestClient _restClient;

        public LeaderboardController(
            IProfileRepository profileRepo, 
            IUserService userService,
            DiscordSocketClient client,
            DiscordRestClient restClient)
        {
            _profileRepo = profileRepo;
            _userService = userService;
            _client = client;
            _restClient = restClient;
        }

        [HttpGet("{guildId}")]
        public async Task<ActionResult<GuildLeaderboard>> GetLocalLeaderboard(ulong guildId)
        {
            var guild = _client.GetGuild(guildId);
            if (guild == null)
                return NotFound("The specified guild could not be found!");
            var gl = new GuildLeaderboard()
            {
                AvatarUrl = guild.IconUrl ?? _client.CurrentUser.GetAvatarUrl(),
                GuildName = guild.Name,
                Ranks = new List<GuildRank>(guild.MemberCount > 100 ? 100: guild.MemberCount) // Properly set capacity already for best performance!
            };

            var gUsersO = await _profileRepo.GetGuildUsersSorted(guildId);
            if (!gUsersO)
                return NotFound("Guild has no saved users!");

            var g = await _restClient.GetGuildAsync(guildId);
            // Create dictionary for easy and fast lookups later :)
            var users = (await g.GetUsersAsync().FlattenAsync()).ToDictionary(x=> x.Id, x=> x);
            var gUsers = (~gUsersO);
            for (var i = 0; i < gUsers.Count; i++)
            {
                var user = gUsers[i];
                int rank = i + 1;
                if (rank > 100) break;
                if (!users.TryGetValue(user.UserId, out var u))
                    continue;
                gl.Ranks.Add(new GuildRank()
                {
                    AvatarUrl = u.GetAvatarUrl() ?? u.GetDefaultAvatarUrl(),
                    Discrim = u.Discriminator,
                    Exp = user.Exp,
                    Name = u.Username,
                    Rank = rank
                });
            }

            return Ok(gl);
        }

        [HttpGet("global")]
        public async Task<ActionResult<GlobalLeaderboard>> GetGlobalLeaderboard()
        {
            var topUsers = await _profileRepo.GetTop150Users().ConfigureAwait(false);
            if (!topUsers)
                return NotFound("Could not fetch Leaderboard");
            
            var leaderboard = new GlobalLeaderboard(){ShardId = GlobalConstants.ShardId};
            var users = topUsers.Some();
            for (var i = 0; i < users.Count; i++)
            {
                var dbUser = users[i];
                var user = _userService.Get(dbUser.Id);
                if (!user) continue;
                int rank = i + 1;
                leaderboard.Ranks.Add(user.MatchSome((u) => new GuildRank()
                {
                    Rank = rank,
                    AvatarUrl = u.GetAvatarUrl() ?? u.GetDefaultAvatarUrl(),
                    Discrim = u.Discriminator,
                    Exp = dbUser.Exp,
                    Name = u.Username,
                    UserId = u.Id.ToString(),
                }));
                if (leaderboard.Ranks.Count >= 100) break;
            }

            return Ok(leaderboard);
        }
    }
}
{'fraction_non_alphanumeric': 0.09161940768746062, 'fraction_numerical': 0.00516698172652804, 'mean_word_length': 1.672053872053872, 'pattern_counts': {'":': 0, '<': 17, '<?xml version=': 0, '>': 25, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1085293', 'n_tokens_mistral': 2175, 'n_tokens_neox': 2063, 'n_words': 494}