<commit_before>﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Discord;
using Discord.Commands;
using Discord.WebSocket;
using SoraBot_v2.Data;
using SoraBot_v2.Data.Entities;
using SoraBot_v2.Data.Entities.SubEntities;

namespace SoraBot_v2.Services
{
    public class ExpService
    {
        private DiscordSocketClient _client;
        private GuildLevelRoleService _roleService;

        public ExpService(DiscordSocketClient client, GuildLevelRoleService roleService)
        {
            _client = client;
            _roleService = roleService;
        }
        
        public static int CalculateLevel(float exp)
        {
            return (int)Math.Floor(0.15F * Math.Sqrt(exp));
        }

        public static int CalculateNeededExp(int lvl)
        {
            return (int)Math.Pow((lvl/0.15F), 2.0);
        }
        
        public async Task ToggleEpGain(SocketCommandContext context)
        {
            using (var soraContext = new SoraContext())
            {
                var userDb = Utility.GetOrCreateUser(context.User.Id, soraContext);
                userDb.Notified = !userDb.Notified;
                await soraContext.SaveChangesAsync();
                if (userDb.Notified)
                {
                    await context.Channel.SendMessageAsync("",
                        embed: Utility.ResultFeedback(Utility.GreenSuccessEmbed, Utility.SuccessLevelEmoji[0], "You will now be notified on level up!").Build());
                    return;
                }
            }

            await context.Channel.SendMessageAsync("",
                embed: Utility.ResultFeedback(Utility.GreenSuccessEmbed, Utility.SuccessLevelEmoji[0],
                    "You will NOT be notified on level up!").Build());
        }
        
        private int GetIndexOfItem(List<User> list, ulong key)
        {
            for (int index = 0; index < list.Count; index++)
            {
                if (list[index].UserId == key)
                    return index;
            }
            return -1;
        }
        
        private int GetIndexOfItem(List<GuildUser> list, ulong key)
        {
            for (int index = 0; index < list.Count; index++)
            {
                if (list[index].UserId == key)
                    return index;
            }
            return -1;
        }

        public async Task GetLocalTop10List(SocketCommandContext context)
        {
            await context.Channel.SendMessageAsync($"Check out **{context.Guild.Name}'s leaderboard** here: https://sorabot.pw/guild/{context.Guild.Id}/leaderboard ｡◕ ‿ ◕｡");
        }

        public async Task GetGlobalTop10(SocketCommandContext context)
        {
            await context.Channel.SendMessageAsync($"Check out the **Global Leaderboard** here: https://sorabot.pw/globalleader °˖✧◝(⁰▿⁰)◜✧˖°");
        }


        public async Task IncreaseEpOnMessageReceive(SocketMessage msg)
        {
            using (var _soraContext = new SoraContext())
            {
                //Don't prcoess the command if it was a system message
                var message = msg as SocketUserMessage;
                if (message == null) return;
                //dont process if it was a bot
                if (message.Author.IsBot) return;
                
                //Create a command Context
                var context = new SocketCommandContext(_client, message);
                if (context.IsPrivate) return;
                
                var userDb = Utility.GetOrCreateUser(context.User.Id, _soraContext);
                //Check for cooldown
                if (userDb.CanGainAgain.CompareTo(DateTime.UtcNow) > 0)
                    return;
                //Reset cooldown
                userDb.CanGainAgain = DateTime.UtcNow.AddSeconds(10);
                int previousLevel = CalculateLevel(userDb.Exp);
                var epGain = (int)Math.Round(context.Message.Content.Length / 10F);
                if (epGain > 50)
                    epGain = 50;
                userDb.Exp += epGain;
                int currentLevel = CalculateLevel(userDb.Exp);
                await _soraContext.SaveChangesAsync();
                //Guild user gain
                Task.Run(async () =>
                {
                    await _roleService.OnUserExpGain(epGain, context);
                });
                
                //Notifying
                if (previousLevel != currentLevel && userDb.Notified)
                {
                    var eb = new EmbedBuilder()
                    {
                        Color = new Color(255, 204, 77),
                        Title = $"🏆 You leveled up! You are now level {currentLevel} \\ (•◡•) /"
                    };
                    await (await context.User.GetOrCreateDMChannelAsync()).SendMessageAsync("", embed: eb.Build());
                }
            }
        }<commit_msg>EXP on seperate thread<commit_after>﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Discord;
using Discord.Commands;
using Discord.WebSocket;
using SoraBot_v2.Data;
using SoraBot_v2.Data.Entities;
using SoraBot_v2.Data.Entities.SubEntities;

namespace SoraBot_v2.Services
{
    public class ExpService
    {
        private DiscordSocketClient _client;
        private GuildLevelRoleService _roleService;

        public ExpService(DiscordSocketClient client, GuildLevelRoleService roleService)
        {
            _client = client;
            _roleService = roleService;
        }
        
        public static int CalculateLevel(float exp)
        {
            return (int)Math.Floor(0.15F * Math.Sqrt(exp));
        }

        public static int CalculateNeededExp(int lvl)
        {
            return (int)Math.Pow((lvl/0.15F), 2.0);
        }
        
        public async Task ToggleEpGain(SocketCommandContext context)
        {
            using (var soraContext = new SoraContext())
            {
                var userDb = Utility.GetOrCreateUser(context.User.Id, soraContext);
                userDb.Notified = !userDb.Notified;
                await soraContext.SaveChangesAsync();
                if (userDb.Notified)
                {
                    await context.Channel.SendMessageAsync("",
                        embed: Utility.ResultFeedback(Utility.GreenSuccessEmbed, Utility.SuccessLevelEmoji[0], "You will now be notified on level up!").Build());
                    return;
                }
            }

            await context.Channel.SendMessageAsync("",
                embed: Utility.ResultFeedback(Utility.GreenSuccessEmbed, Utility.SuccessLevelEmoji[0],
                    "You will NOT be notified on level up!").Build());
        }
        
        private int GetIndexOfItem(List<User> list, ulong key)
        {
            for (int index = 0; index < list.Count; index++)
            {
                if (list[index].UserId == key)
                    return index;
            }
            return -1;
        }
        
        private int GetIndexOfItem(List<GuildUser> list, ulong key)
        {
            for (int index = 0; index < list.Count; index++)
            {
                if (list[index].UserId == key)
                    return index;
            }
            return -1;
        }

        public async Task GetLocalTop10List(SocketCommandContext context)
        {
            await context.Channel.SendMessageAsync($"Check out **{context.Guild.Name}'s leaderboard** here: https://sorabot.pw/guild/{context.Guild.Id}/leaderboard ｡◕ ‿ ◕｡");
        }

        public async Task GetGlobalTop10(SocketCommandContext context)
        {
            await context.Channel.SendMessageAsync($"Check out the **Global Leaderboard** here: https://sorabot.pw/globalleader °˖✧◝(⁰▿⁰)◜✧˖°");
        }


        public Task IncreaseEpOnMessageReceive(SocketMessage msg)
        {
            //Don't process the command if it was a system message
            var message = msg as SocketUserMessage;
            if (message == null) return Task.CompletedTask;
            //dont process if it was a bot
            if (message.Author.IsBot) return Task.CompletedTask;
                
            //Create a command Context
            var context = new SocketCommandContext(_client, message);
            if (context.IsPrivate) return Task.CompletedTask;
            
            // let's do all of this on a separate thread to relieve the main thread from some processing
            var _ = Task.Run(async () =>
            {
                using var soraContext = new SoraContext();
                var userDb = Utility.GetOrCreateUser(context.User.Id, soraContext);
                //Check for cooldown
                if (userDb.CanGainAgain.CompareTo(DateTime.UtcNow) > 0)
                    return;
                //Reset cooldown
                userDb.CanGainAgain = DateTime.UtcNow.AddSeconds(10);
                int previousLevel = CalculateLevel(userDb.Exp);
                var epGain = (int)Math.Round(context.Message.Content.Length / 10F);
                if (epGain > 50)
                    epGain = 50;
                userDb.Exp += epGain;
                int currentLevel = CalculateLevel(userDb.Exp);
                await soraContext.SaveChangesAsync();
                //Guild user gain
                await _roleService.OnUserExpGain(epGain, context);
                
                //Notifying
                if (previousLevel != currentLevel && userDb.Notified)
                {
                    var eb = new EmbedBuilder()
                    {
                        Color = new Color(255, 204, 77),
                        Title = $"🏆 You leveled up! You are now level {currentLevel} \\ (•◡•) /"
                    };
                    await (await context.User.GetOrCreateDMChannelAsync()).SendMessageAsync("", embed: eb.Build());
                }
            }).ConfigureAwait(false);
            return Task.CompletedTask;
        }
{'fraction_non_alphanumeric': 0.09151563433578969, 'fraction_numerical': 0.007767377016530572, 'mean_word_length': 1.5870685213807316, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 13, 'https://': 4, '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': '2001745', 'n_tokens_mistral': 2810, 'n_tokens_neox': 2615, 'n_words': 614}