Beispiel #1
0
        private static void CalculateMoE(DateTime?moeLastDateXbox, DateTime?moeLastDatePs, DbProvider provider,
                                         DbRecorder recorder, MailSender mailSender, string resultDirectoryXbox, string resultDirectoryPs,
                                         FtpPutter ftpPutterXbox, FtpPutter ftpPutterPs, int utcShiftToCalculate)
        {
            var csw = Stopwatch.StartNew();

            recorder.CalculateMoE(utcShiftToCalculate);
            csw.Stop();
            Log.Debug($"Cálculo das MoE feito em {csw.Elapsed.TotalSeconds:N0}.");

            if (csw.Elapsed.TotalMinutes > 1)
            {
                mailSender.Send("Cálculo das MoE", $"Cálculo das MoE feito em {csw.Elapsed.TotalSeconds:N0}.");
            }

            if (moeLastDateXbox.HasValue)
            {
                PutMoEOnPlataform(Platform.XBOX, moeLastDateXbox, provider, mailSender, resultDirectoryXbox, ftpPutterXbox);
            }

            if (moeLastDatePs.HasValue)
            {
                PutMoEOnPlataform(Platform.PS, moeLastDatePs, provider, mailSender, resultDirectoryPs, ftpPutterPs);
            }
        }
Beispiel #2
0
 public ImportWn8WotcStat(Fetcher fetcher, Putter putter, DbProvider provider, DbRecorder recorder)
 {
     _fetcher  = fetcher;
     _provider = provider;
     _recorder = recorder;
     _putter   = putter;
 }
Beispiel #3
0
 public GetPlayers(Fetcher fetcher, Putter putter, DbProvider provider, DbRecorder recorder)
 {
     _fetcher  = fetcher;
     _provider = provider;
     _recorder = recorder;
     _putter   = putter;
 }
Beispiel #4
0
        public async Task ForgetWhoIAm(CommandContext ctx)
        {
            try
            {
                await ctx.TriggerTypingAsync();

                if (!await CanExecute(ctx, Features.Players))
                {
                    return;
                }

                long userId = (long)(ctx?.User?.Id ?? 0UL);
                if (userId == 0)
                {
                    await ctx.RespondAsync($"Sorry, {ctx.User.Mention}. I don't now your Discord User Id! WTF!??!");

                    return;
                }

                var recorder = new DbRecorder(_connectionString);
                recorder.AssociateDiscordUserToPlayer(userId, 0);

                await ctx.RespondAsync($"Done, {ctx.User.Mention}, I no longer know who you are on the game.");

                return;
            }
            catch (Exception ex)
            {
                Log.Error($"{nameof(WhoIAm)}()", ex);
                await ctx.RespondAsync($"Sorry, {ctx.User.Mention}. There was an error... the *Coder* will be notified of `{ex.Message}`.");

                return;
            }
        }
Beispiel #5
0
 public CalculateStats(Fetcher fetcher, Putter putter, DbProvider provider, DbRecorder recorder)
 {
     _fetcher  = fetcher;
     _provider = provider;
     _recorder = recorder;
     _putter   = putter;
 }
Beispiel #6
0
        private static Clan CalculateClan(ClanPlataform clan, DbProvider provider,
                                          DbRecorder recorder)
        {
            Log.DebugFormat("Calculando cla {0}@{1}...", clan.ClanTag, clan.Plataform);

            var cc = provider.GetClan(clan.Plataform, clan.ClanId);

            if (cc == null)
            {
                Log.Warn("O cla ainda não teve nenhum membro atualizado.");
                return(null);
            }

            if (cc.Count == 0)
            {
                Log.Warn("O cla ainda não teve nenhum membro atualizado.");
                return(null);
            }

            Log.InfoFormat("------------------------------------------------------------------");
            Log.InfoFormat("cla:                     {0}@{1}", cc.ClanTag, cc.Plataform);
            Log.InfoFormat("# Membros:               {0};{1};{2} - Patched: {3}", cc.Count, cc.Active, 0,
                           cc.NumberOfPatchedPlayers);
            Log.InfoFormat("Batalhas:                T:{0:N0};A:{1:N0};W:{2:N0}", cc.TotalBattles, cc.ActiveBattles,
                           0);

            recorder.SetClanCalculation(cc);

            return(cc);
        }
Beispiel #7
0
        private static void CalculateTanksReferences(DateTime?lastReferencesXbox, DateTime?lastReferencesPs,
                                                     DbProvider provider, DbRecorder recorder, MailSender mailSender, string resultDirectoryXbox,
                                                     string resultDirectoryPs, FtpPutter ftpPutterXbox, FtpPutter ftpPutterPs, int utcShiftToCalculate)
        {
            var csw = Stopwatch.StartNew();

            recorder.CalculateReference(utcShiftToCalculate);
            csw.Stop();
            Log.Debug($"Cálculo das Referências de Tanques feito em {csw.Elapsed.TotalSeconds:N0}.");

            if (csw.Elapsed.TotalMinutes > 1)
            {
                mailSender.Send("Cálculo das Referências de Tanques",
                                $"Cálculo das Referências de Tanques feito em {csw.Elapsed.TotalSeconds:N0}.");
            }

            if (lastReferencesXbox.HasValue)
            {
                PutTanksReferencesOnPlataform(Platform.XBOX, lastReferencesXbox, provider, mailSender, resultDirectoryXbox, ftpPutterXbox, utcShiftToCalculate);
            }

            if (lastReferencesPs.HasValue)
            {
                PutTanksReferencesOnPlataform(Platform.PS, lastReferencesPs, provider, mailSender, resultDirectoryPs, ftpPutterPs, utcShiftToCalculate);
            }
        }
Beispiel #8
0
        public async Task SetWhoIAm(CommandContext ctx,
                                    [Description("The *gamer tag* or *PSN Name*")][RemainingText] string gamerTag = "")
        {
            try
            {
                await ctx.TriggerTypingAsync();

                if (!await CanExecute(ctx, Features.Players))
                {
                    return;
                }

                long userId = (long)(ctx?.User?.Id ?? 0UL);
                if (userId == 0)
                {
                    await ctx.RespondAsync($"Sorry, {ctx.User.Mention}. I don't now your Discord User Id! WTF!??!");

                    return;
                }

                var cfg       = GuildConfiguration.FromGuild(ctx.Guild);
                var plataform = GetPlataform(gamerTag, cfg.Plataform, out gamerTag);

                if (string.IsNullOrWhiteSpace(gamerTag))
                {
                    gamerTag = ctx.User.Username;
                }

                var provider = new DbProvider(_connectionString);

                var playerId = provider.GetPlayerIdByName(plataform, gamerTag);
                if (playerId == null)
                {
                    await ctx.RespondAsync($"Sorry, {ctx.User.Mention}, I do not track `{gamerTag}` yet. Are you a member of a tracked clan? Are you sure about the gamer tag?");

                    return;
                }

                var recorder = new DbRecorder(_connectionString);
                recorder.AssociateDiscordUserToPlayer(userId, playerId.Value);

                await ctx.RespondAsync($"Ok, {ctx.User.Mention}, for now on you can use `me` instead of your full {plataform.TagName()} on " +
                                       $"commands that take it as a parameters. I promisse to never abuse this association, and protected it from use outside of this system. " +
                                       $"If you want me to remove this piece of information use the `ForgetWhoIAm` command.");

                return;
            }
            catch (Exception ex)
            {
                Log.Error($"{nameof(WhoIAm)}()", ex);
                await ctx.RespondAsync($"Sorry, {ctx.User.Mention}. There was an error... the *Coder* will be notified of `{ex.Message}`.");

                return;
            }
        }
Beispiel #9
0
        private static void RetrievePlayer(Player player, Fetcher fetcher,
                                           DbProvider provider, DbRecorder recorder, IReadOnlyDictionary <long, Tank> allTanks,
                                           Wn8ExpectedValues wn8Expected, Putter putter)
        {
            var tanks      = fetcher.GetTanksForPlayer(player.Plataform, player.Id);
            var validTanks = tanks.Where(t => allTanks.ContainsKey(t.TankId)).ToArray();

            recorder.Set(validTanks);

            var played = provider.GetWn8RawStatsForPlayer(player.Plataform, player.Id);

            player.Performance = played;
            player.Calculate(wn8Expected);
            player.Moment = DateTime.UtcNow;
            player.Origin = PlayerDataOrigin.Self;

            var previous = provider.GetPlayer(player.Id, player.Date, true);

            if (previous != null)
            {
                if (player.Check(previous, true))
                {
                    Log.Warn($"Player {player.Name}.{player.Id}@{player.Plataform} was patched.");
                }
            }

            if (player.CanSave())
            {
                recorder.Set(player);
                if (!player.IsPatched)
                {
                    _ = Task.Run(() =>
                    {
                        try
                        {
                            putter?.Put(player);
                        }
                        catch (Exception ex)
                        {
                            Log.Error($"Error putting player {player.Id} on the remote site.", ex);
                        }
                    });
                }
            }
            else
            {
                Log.Warn($"Player {player.Name}.{player.Id}@{player.Plataform} has to much zero data.");
            }
        }
Beispiel #10
0
        private static void RetrievePlayer(Player player, Fetcher fetcher, Fetcher externalFetcher,
                                           DbProvider provider, DbRecorder recorder, IReadOnlyDictionary <long, Tank> allTanks, Wn8ExpectedValues wn8Expected, Putter putter)
        {
            Task <Player> externalTask = null;

            if (externalFetcher != null)
            {
                externalTask = externalFetcher.GetPlayerWn8Async((Player)player.Clone());
            }

            var tanks      = fetcher.GetTanksForPlayer(player.Plataform, player.Id);
            var validTanks = tanks.Where(t => allTanks.ContainsKey(t.TankId)).ToArray();

            recorder.Set(validTanks);

            var played = provider.GetWn8RawStatsForPlayer(player.Plataform, player.Id);

            player.Performance = played;
            player.Calculate(wn8Expected);
            player.Moment = DateTime.UtcNow;
            player.Origin = PlayerDataOrigin.Self;

            var previous = provider.GetPlayer(player.Id, player.Date, true);

            if (previous != null)
            {
                if (player.Check(previous, true))
                {
                    Log.Warn($"Player {player.Name}.{player.Id}@{player.Plataform} was patched.");
                }
            }

            if (player.CanSave())
            {
                recorder.Set(player);
                if (!player.IsPatched)
                {
                    putter?.Put(player);
                }
            }
            else
            {
                Log.Warn($"Player {player.Name}.{player.Id}@{player.Plataform} has to much zero data.");
            }

            // Se foi feita a chamada na API externa, espero o retorno, que será ignorado; mas serviu para popular o BD do parceiro.
            externalTask?.Wait();
        }
Beispiel #11
0
        private static void GetXvmWn8()
        {
            var connectionString = ConfigurationManager.ConnectionStrings["Main"].ConnectionString;
            var provider         = new DbProvider(connectionString);
            var recorder         = new DbRecorder(connectionString);

            var webCacheAge    = TimeSpan.FromMinutes(10);
            var cacheDirectory = ConfigurationManager.AppSettings["CacheDirectory"];

            var fetcher = new Fetcher(cacheDirectory)
            {
                WebCacheAge      = webCacheAge,
                WebFetchInterval = TimeSpan.FromSeconds(1),
                ApplicationId    = ConfigurationManager.AppSettings["WgApi"]
            };
        }
Beispiel #12
0
        public async Task PurgePlayer(CommandContext ctx, [Description("Player Id")] long playerId)
        {
            await ctx.TriggerTypingAsync();

            var userId = ctx.User?.Id ?? 0;

            Log.Info($"Requesting {nameof(GetPlayerById)}({playerId}) by {userId}...");
            if (userId != _coder)
            {
                var emoji = DiscordEmoji.FromName(ctx.Client, ":no_entry:");
                var embed = new DiscordEmbedBuilder
                {
                    Title       = "Access denied",
                    Description = $"{emoji} You may be a *coder*, but you are not **The Coder**!",
                    Color       = DiscordColor.Red
                };

                await ctx.RespondAsync("", embed : embed);

                return;
            }

            try
            {
                var provider = new DbProvider(_connectionString);
                var player   = provider.GetPlayer(playerId);
                if (player == null)
                {
                    await ctx.RespondAsync($"There is no player on the database with the id `{playerId}`.");

                    return;
                }

                await ctx.RespondAsync($"The id `{playerId}` corresponds to the tanker `{player.Name}` on the `{player.Platform}`...");

                var recorder = new DbRecorder(_connectionString);
                recorder.PurgePlayer(playerId);

                await ctx.RespondAsync($"The tanker `{player.Name}` on `{player.Platform}` was purged from the database. Rip.");
            }
            catch (Exception ex)
            {
                Log.Error($"{nameof(GetDbStatus)}", ex);
                await ctx.RespondAsync(
                    $"Sorry, {ctx.User?.Mention}. There was an error... the *Coder* will be notified of `{ex.Message}`.");
            }
        }
Beispiel #13
0
        private static void GetAllTanks(Plataform plataform)
        {
            var cacheDirectory = ConfigurationManager.AppSettings["CacheDirectory"];
            var fetcher        = new Fetcher(cacheDirectory)
            {
                WebCacheAge      = TimeSpan.FromMinutes(15),
                WebFetchInterval = TimeSpan.FromSeconds(1),
                ApplicationId    = ConfigurationManager.AppSettings["WgApi"]
            };

            var tanks = fetcher.GetTanks(Plataform.PC).ToArray();

            var connectionString = ConfigurationManager.ConnectionStrings["Main"].ConnectionString;
            var recorder         = new DbRecorder(connectionString);

            recorder.Set(tanks);
        }
Beispiel #14
0
        private static void GetXvmWn8()
        {
            string     connectionString = ConfigurationManager.ConnectionStrings["Main"].ConnectionString;
            DbProvider provider         = new DbProvider(connectionString);
            DbRecorder recorder         = new DbRecorder(connectionString);

            TimeSpan webCacheAge    = TimeSpan.FromMinutes(10);
            string   cacheDirectory = ConfigurationManager.AppSettings["CacheDirectory"];

            Fetcher fetcher = new Fetcher(cacheDirectory)
            {
                WebCacheAge      = webCacheAge,
                WebFetchInterval = TimeSpan.FromSeconds(1),
                ApplicationId    = ConfigurationManager.AppSettings["WgApi"]
            };

            Negri.Wot.Tanks.Tank[] data = provider.EnumTanks(Platform.XBOX).ToArray();
        }
Beispiel #15
0
        /// <summary>
        /// Retrieve and populate all medals in the game
        /// </summary>
        private static void PopulateAllMedals()
        {
            var cacheDirectory = ConfigurationManager.AppSettings["CacheDirectory"];
            var fetcher        = new Fetcher(cacheDirectory)
            {
                WebCacheAge      = TimeSpan.FromMinutes(15),
                WebFetchInterval = TimeSpan.FromSeconds(1),
                ApplicationId    = ConfigurationManager.AppSettings["WgApi"]
            };

            var gameMedals         = fetcher.GetMedals(Platform.XBOX).ToDictionary(m => m.Code);
            var maxCode            = gameMedals.Values.Max(m => m.Code.Length);
            var maxName            = gameMedals.Values.Max(m => m.Name.Length);
            var maxDescription     = gameMedals.Values.Max(m => m.Description.Length);
            var maxHeroInformation = gameMedals.Values.Max(m => m.HeroInformation?.Length ?? 0);
            var maxCondition       = gameMedals.Values.Max(m => m.Condition?.Length ?? 0);

            var connectionString = ConfigurationManager.ConnectionStrings["Main"].ConnectionString;
            var recorder         = new DbRecorder(connectionString);

            recorder.Set(gameMedals.Values);
        }
Beispiel #16
0
        private static void CalculateAndPutReferences()
        {
            var connectionString = ConfigurationManager.ConnectionStrings["Main"].ConnectionString;
            var provider         = new DbProvider(connectionString);
            var recorder         = new DbRecorder(connectionString);

            var cacheDirectory         = ConfigurationManager.AppSettings["CacheDirectory"];
            var wargamingApplicationId = ConfigurationManager.AppSettings["WgAppId"];
            var wotClansAdminApiKey    = ConfigurationManager.AppSettings["ApiAdminKey"];
            var webCacheAge            = TimeSpan.FromMinutes(1);

            var fetcher = new Fetcher(cacheDirectory)
            {
                WebCacheAge            = webCacheAge,
                WebFetchInterval       = TimeSpan.FromSeconds(1),
                WargamingApplicationId = wargamingApplicationId,
                WotClansAdminApiKey    = wotClansAdminApiKey,
                WotClansBaseUrl        = "http://localhost/ClanStatsWeb"
            };

            var putter = new Putter(wotClansAdminApiKey)
            {
                BaseUrl = "http://localhost/ClanStatsWeb"
            };

            const int utcShiftToCalculate = -7;
            const int topLeaders          = 50;
            const int maxParallel         = 1;

            recorder.CalculateReference(utcShiftToCalculate);

            var siteDiagnostic  = fetcher.GetSiteDiagnostic();
            var lastLeaderboard = siteDiagnostic.TankLeadersLastDate;

            Log.Info($"Last leaderboard on site: {lastLeaderboard:yyyy-MM-dd}");

            var cd             = DateTime.UtcNow.AddHours(utcShiftToCalculate);
            var previousMonday = cd.PreviousDayOfWeek(DayOfWeek.Monday);

            Log.Info($"Previous Monday: {previousMonday:yyyy-MM-dd}");

            if (previousMonday <= lastLeaderboard)
            {
                Log.Info("No need to upload.");
                return;
            }

            Log.Info($"Getting tanks stats for {previousMonday:yyyy-MM-dd}...");
            var references = provider.GetTanksReferences(previousMonday, null, true, false, true, topLeaders).ToArray();

            Log.Debug($"Data for {references.Length} tanks retrieved.");
            var leaders = new ConcurrentBag <Leader>();

            Parallel.For(0, references.Length, new ParallelOptions {
                MaxDegreeOfParallelism = maxParallel
            }, i =>
            {
                var r = references[i];

                Log.Debug($"Putting references for tank {r.Name}...");
                if (!putter.Put(r))
                {
                    Log.Error($"Error putting tank reference files for tank {r.Name}.");
                }

                foreach (var leader in r.Leaders)
                {
                    leaders.Add(leader);
                }
            });

            var orderedLeaders = leaders.OrderByDescending(l => l.Tier).ThenBy(l => l.Type).ThenBy(l => l.Nation).ThenBy(l => l.Name).ThenBy(l => l.Order)
                                 .ToArray();

            Log.Info($"Uploading leaderboard with {orderedLeaders.Length} players...");
            if (!putter.Put(previousMonday, orderedLeaders))
            {
                Log.Error("Error putting leaders to the server.");
            }
        }
Beispiel #17
0
        /// <summary>
        ///     Calcula todos os clas habilitados e os salva
        /// </summary>
        private static void CalculateAllClans()
        {
            var connectionString = ConfigurationManager.ConnectionStrings["Main"].ConnectionString;
            var provider         = new DbProvider(connectionString);
            var clans            = provider.GetClans().ToArray();

            Log.InfoFormat("{0} clas devem ser calculados.", clans.Length);

            var recorder = new DbRecorder(connectionString);

            var putterXbox = new FtpPutter(ConfigurationManager.AppSettings["FtpFolder"],
                                           ConfigurationManager.AppSettings["FtpUser"],
                                           ConfigurationManager.AppSettings["FtpPassworld"], Plataform.XBOX);

            var putterPs = new FtpPutter(ConfigurationManager.AppSettings["PsFtpFolder"],
                                         ConfigurationManager.AppSettings["PsFtpUser"],
                                         ConfigurationManager.AppSettings["PsFtpPassworld"], Plataform.PS);

            var resultDirectory   = ConfigurationManager.AppSettings["ResultDirectory"];
            var resultDirectoryPs = ConfigurationManager.AppSettings["PsResultDirectory"];


            var already   = new HashSet <string>(File.ReadAllLines(Path.Combine(resultDirectory, "CalcTask.txt")));
            var alreadyPs = new HashSet <string>(File.ReadAllLines(Path.Combine(resultDirectoryPs, "CalcTask.txt")));

            var o = new object();

            // Calcula cada cla
            var doneCount = 0;
            var sw        = Stopwatch.StartNew();

            Parallel.For(0, clans.Length, new ParallelOptions {
                MaxDegreeOfParallelism = 2
            }, i =>
            {
                var clan = clans[i];

                bool done = false;
                if (clan.Plataform == Plataform.XBOX)
                {
                    done = already.Contains(clan.ClanTag);
                }
                else if (clan.Plataform == Plataform.PS)
                {
                    done = alreadyPs.Contains(clan.ClanTag);
                }

                if (done)
                {
                    Log.InfoFormat("cla {0} de {1}: {2}@{3} feito anteriormente.", i + 1, clans.Length, clan.ClanTag, clan.Plataform);
                    Interlocked.Increment(ref doneCount);
                    return;
                }

                Log.InfoFormat("Processando cla {0} de {1}: {2}@{3}...", i + 1, clans.Length, clan.ClanTag,
                               clan.Plataform);
                var csw = Stopwatch.StartNew();

                var cc = CalculateClan(clan, provider, recorder);

                Log.InfoFormat("Calculado cla {0} de {1}: {2}@{3} em {4:N1}s...",
                               i + 1, clans.Length, clan.ClanTag, clan.Plataform, csw.Elapsed.TotalSeconds);

                if (cc != null)
                {
                    var fsw = Stopwatch.StartNew();
                    switch (cc.Plataform)
                    {
                    case Plataform.XBOX:
                        {
                            var fileName = cc.ToFile(resultDirectory);
                            Log.InfoFormat("Arquivo de resultado escrito em '{0}'", fileName);
                            putterXbox.PutClan(fileName);
                            lock (o)
                            {
                                File.AppendAllText(Path.Combine(resultDirectory, "CalcTask.txt"), $"{cc.ClanTag}\r\n", Encoding.UTF8);
                            }
                        }
                        break;

                    case Plataform.PS:
                        {
                            var fileName = cc.ToFile(resultDirectoryPs);
                            Log.InfoFormat("Arquivo de resultado escrito em '{0}'", fileName);
                            putterPs.PutClan(fileName);
                            lock (o)
                            {
                                File.AppendAllText(Path.Combine(resultDirectoryPs, "CalcTask.txt"), $"{cc.ClanTag}\r\n", Encoding.UTF8);
                            }
                        }
                        break;

                    case Plataform.Virtual:
                        break;

                    default:
                        throw new ArgumentOutOfRangeException();
                    }

                    Log.InfoFormat("Upload do cla {0} de {1}: {2}@{3} em {4:N1}s...",
                                   i + 1, clans.Length, clan.ClanTag, clan.Plataform, fsw.Elapsed.TotalSeconds);
                }

                Interlocked.Increment(ref doneCount);
                Log.InfoFormat("Processado cla {0} de {1}: {2}@{3} em {4:N1}s. {5} totais.",
                               i + 1, clans.Length, clan.ClanTag, clan.Plataform, csw.Elapsed.TotalSeconds, doneCount);
            });
            var calculationTime = sw.Elapsed;
        }
Beispiel #18
0
 public CalculateClans(Putter putter, DbProvider provider, DbRecorder recorder)
 {
     _provider = provider;
     _recorder = recorder;
     _putter   = putter;
 }
Beispiel #19
0
        private static int Main(string[] args)
        {
            try
            {
                var sw = Stopwatch.StartNew();
                ParseParans(args, out int ageHours, out int maxClans, out int maxRunMinutes, out bool noSaveOnDatabase,
                            out TimeSpan webFetchInterval, out int maxToAutoAdd, out int hourToAutoAdd,
                            out int autoMinNumberOfMembers);
                var saveOnDatabase = !noSaveOnDatabase;

                var cacheDirectory = ConfigurationManager.AppSettings["CacheDirectory"];

                Log.Info("------------------------------------------------------------------------------------");
                Log.Info("FetchClanMembership iniciando...");
                Log.InfoFormat(
                    "ageHours: {0}; maxClans: {1}; maxRunMinutes: {2}; cacheDirectory: {3}; noSaveOnDatabase:{4}; webFetchInterval:{5}",
                    ageHours, maxClans, maxRunMinutes, cacheDirectory, noSaveOnDatabase, webFetchInterval);

                var connectionString = ConfigurationManager.ConnectionStrings["Main"].ConnectionString;
                var provider         = new DbProvider(connectionString);
                var fetcher          = new Fetcher(cacheDirectory)
                {
                    WebCacheAge      = TimeSpan.FromHours(ageHours - 1),
                    WebFetchInterval = webFetchInterval,
                    ApplicationId    = ConfigurationManager.AppSettings["WgApi"]
                };
                var recorder = new DbRecorder(connectionString);

                var mailSender = new MailSender(ConfigurationManager.AppSettings["SmtpHost"],
                                                int.Parse(ConfigurationManager.AppSettings["SmtpPort"]),
                                                true, ConfigurationManager.AppSettings["SmtpUsername"],
                                                ConfigurationManager.AppSettings["SmtpPassword"])
                {
                    From = new MailAddress(ConfigurationManager.AppSettings["SmtpUsername"], "Membership Service")
                };

                // Verifica a necessidade de adicionar novos clãs ao sistema
                var clansToAdd = provider.GetClansToAdd().ToArray();
                foreach (var clanToAdd in clansToAdd)
                {
                    var clanWithId = fetcher.FindClan(clanToAdd.Plataform, clanToAdd.ClanTag);
                    if (clanWithId != null)
                    {
                        var existingClan = provider.GetClan(clanWithId.Plataform, clanWithId.ClanId);
                        if (existingClan != null)
                        {
                            if (existingClan.Enabled)
                            {
                                Log.WarnFormat(
                                    "Foi requerido adicionar o clã {0}@{1}, mas já existe no sistema o clã {2}.{3}@{4}.",
                                    clanToAdd.ClanTag, clanToAdd.Plataform, existingClan.ClanId, existingClan.ClanTag,
                                    existingClan.Plataform);
                                mailSender.Send($"Clã {clanWithId.ClanTag} já existe e está habilitado",
                                                $"Id: {clanWithId.ClanId}; Plataforma: {clanWithId.Plataform}; URL: {GetClanUrl(clanWithId.Plataform, clanWithId.ClanTag)}");
                            }
                            else
                            {
                                // Reabilitar o cla
                                recorder.EnableClan(clanWithId.Plataform, clanWithId.ClanId);
                                mailSender.Send($"Habilitado manualmente o clã {clanWithId.ClanTag}",
                                                $"Id: {clanWithId.ClanId}; Plataforma: {clanWithId.Plataform}; URL: {GetClanUrl(clanWithId.Plataform, clanWithId.ClanTag)}");
                            }
                        }
                        else
                        {
                            clanWithId.Country = clanToAdd.Country;
                            recorder.Add(clanWithId);
                            mailSender.Send($"Adicionado manualmente o clã {clanWithId.ClanTag}",
                                            $"Id: {clanWithId.ClanId}; Plataforma: {clanWithId.Plataform}; URL: {GetClanUrl(clanWithId.Plataform, clanWithId.ClanTag)}");
                        }
                    }
                    else
                    {
                        Log.WarnFormat(
                            "Foi requerido adicionar o clã {0}@{1}, mas ele não foi encontrado, ou é muito pequeno.",
                            clanToAdd.ClanTag, clanToAdd.Plataform);
                        mailSender.Send($"Clã {clanToAdd.ClanTag}@{clanToAdd.Plataform} não adicionado",
                                        $"Foi requerido adicionar o clã {clanToAdd.ClanTag}@{clanToAdd.Plataform}, mas ele não foi encontrado, ou é muito pequeno.");
                    }
                }

                recorder.ClearClansToAddQueue();

                // Autocadastro de clãs
                if (maxToAutoAdd > 0 && DateTime.UtcNow.Hour == hourToAutoAdd)
                {
                    var toAdd = fetcher.GetClans(Platform.XBOX, autoMinNumberOfMembers)
                                .Where(c => !provider.ClanExists(c.Plataform, c.ClanId))
                                .Concat(fetcher.GetClans(Platform.PS, autoMinNumberOfMembers)
                                        .Where(c => !provider.ClanExists(c.Plataform, c.ClanId)))
                                .OrderByDescending(c => c.AllMembersCount).ThenBy(c => c.ClanId).ToArray();

                    foreach (var c in toAdd.Take(maxToAutoAdd))
                    {
                        recorder.Add(c);
                        mailSender.Send($"Adicionado automaticamente o clã {c.ClanTag}@{c.Plataform}",
                                        $"Id: {c.ClanId}, Plataforma: {c.Plataform}; Membros: {c.AllMembersCount}; URL: {GetClanUrl(c.Plataform, c.ClanTag)}");
                    }

                    // Readição de clãs pequenos ou que ficaram inativos
                    recorder.ReAddClans(maxToAutoAdd);
                }

                var clans = provider.GetClanMembershipUpdateOrder(maxClans, ageHours).ToArray();
                Log.InfoFormat("{0} clãs devem ser atualizados.", clans.Length);

                if (clans.Length == 0)
                {
                    Log.Info("Nenhum clã para atualizar.");
                    return(0);
                }

                var clansToRename = new List <Clan>();
                var clansToUpdate = fetcher.GetClans(clans).ToArray();



                // Clãs debandados
                foreach (var clan in clansToUpdate.Where(c => c.IsDisbanded))
                {
                    var disbandedClan = provider.GetClan(clan.Plataform, clan.ClanId);
                    if (saveOnDatabase)
                    {
                        recorder.DisableClan(disbandedClan.Plataform, disbandedClan.ClanId, DisabledReason.Disbanded);

                        var putter = new Putter(disbandedClan.Plataform, ConfigurationManager.AppSettings["ApiAdminKey"]);
                        putter.DeleteClan(disbandedClan.ClanTag);
                    }

                    var sb = new StringBuilder();
                    sb.AppendLine(
                        $"Clã {disbandedClan.ClanTag}, id {disbandedClan.ClanId}, no {disbandedClan.Plataform}, com {disbandedClan.Count} jogadores, foi debandado.");
                    sb.AppendLine($"WN8t15: {disbandedClan.Top15Wn8:N0} em {disbandedClan.Moment:yyyy-MM-dd HH:mm:ss}");
                    sb.AppendLine($"URL: {GetClanUrl(disbandedClan.Plataform, disbandedClan.ClanTag)}");
                    sb.AppendLine();
                    sb.AppendLine("Jogadores:");
                    foreach (var player in disbandedClan.Players)
                    {
                        sb.AppendLine(
                            $"{player.Name}: WN8 recente de {player.MonthWn8:N0} em {player.MonthBattles:N0}");
                    }

                    mailSender.Send($"Clã {disbandedClan.ClanTag}@{disbandedClan.Plataform} foi debandado",
                                    sb.ToString());
                }

                // Clãs que ficaram pequenos demais
                foreach (var clan in clansToUpdate.Where(c => !c.IsDisbanded && c.Count < 4))
                {
                    if (saveOnDatabase)
                    {
                        recorder.DisableClan(clan.Plataform, clan.ClanId, DisabledReason.TooSmall);
                    }

                    mailSender.Send($"Clã {clan.ClanTag}@{clan.Plataform} foi suspenso",
                                    $"Clã {clan.ClanTag}@{clan.Plataform} com {clan.Count} jogadores foi suspenso de atualizações futuras. " +
                                    $"URL: {GetClanUrl(clan.Plataform, clan.ClanTag)}");
                }

                foreach (var clan in clansToUpdate.Where(c => !c.IsDisbanded && c.Count >= 4))
                {
                    Log.DebugFormat("Clã {0}.{1}@{2}...", clan.ClanId, clan.ClanTag, clan.Plataform);
                    if (saveOnDatabase)
                    {
                        recorder.Set(clan, true);
                        if (clan.HasChangedTag)
                        {
                            clansToRename.Add(clan);
                        }
                    }
                }

                if (clansToRename.Any(c => c.Plataform == Platform.XBOX))
                {
                    var putter = new FtpPutter(ConfigurationManager.AppSettings["FtpFolder"],
                                               ConfigurationManager.AppSettings["FtpUser"],
                                               ConfigurationManager.AppSettings["FtpPassworld"]);

                    var resultDirectory = Path.Combine(ConfigurationManager.AppSettings["ResultDirectory"], "Clans");

                    foreach (var clan in clansToRename.Where(c => c.Plataform == Platform.XBOX))
                    {
                        Log.InfoFormat("O clã {0}.{1}@{2} teve o tag trocado a partir de {3}.", clan.ClanId,
                                       clan.ClanTag, clan.Plataform, clan.OldTag);

                        // Faz copia do arquivo local, e o upload com o novo nome
                        string oldFile = Path.Combine(resultDirectory, $"clan.{clan.OldTag}.json");
                        if (File.Exists(oldFile))
                        {
                            string newFile = Path.Combine(resultDirectory, $"clan.{clan.ClanTag}.json");
                            File.Copy(oldFile, newFile, true);

                            _ = Task.Run(() =>
                            {
                                try
                                {
                                    putter.PutClan(newFile);
                                    putter.DeleteFile($"Clans/clan.{clan.OldTag}.json");
                                    putter.SetRenameFile(clan.OldTag, clan.ClanTag);
                                }
                                catch (Exception ex)
                                {
                                    Log.Error($"Error on XBOX renaming clan {clan.OldTag} to {clan.ClanTag}", ex);
                                }
                            });
                        }

                        mailSender.Send($"Clã Renomeado: {clan.OldTag} -> {clan.ClanTag} em {clan.Plataform}",
                                        $"URL: {GetClanUrl(clan.Plataform, clan.ClanTag)}");
                    }
                }

                if (clansToRename.Any(c => c.Plataform == Platform.PS))
                {
                    var putter = new FtpPutter(ConfigurationManager.AppSettings["PsFtpFolder"],
                                               ConfigurationManager.AppSettings["PsFtpUser"],
                                               ConfigurationManager.AppSettings["PsFtpPassworld"]);

                    var resultDirectory = ConfigurationManager.AppSettings["PsResultDirectory"];

                    foreach (var clan in clansToRename.Where(c => c.Plataform == Platform.PS))
                    {
                        Log.InfoFormat("O clã {0}.{1}@{2} teve o tag trocado a partir de {3}.", clan.ClanId,
                                       clan.ClanTag, clan.Plataform, clan.OldTag);

                        // Faz copia do arquivo local, e o upload com o novo nome
                        string oldFile = Path.Combine(resultDirectory, $"clan.{clan.OldTag}.json");
                        if (File.Exists(oldFile))
                        {
                            string newFile = Path.Combine(resultDirectory, $"clan.{clan.ClanTag}.json");
                            File.Copy(oldFile, newFile, true);

                            _ = Task.Run(() =>
                            {
                                try
                                {
                                    putter.PutClan(newFile);
                                    putter.DeleteFile($"Clans/clan.{clan.OldTag}.json");
                                    putter.SetRenameFile(clan.OldTag, clan.ClanTag);
                                }
                                catch (Exception ex)
                                {
                                    Log.Error($"Error on PS renaming clan {clan.OldTag} to {clan.ClanTag}", ex);
                                }
                            });
                        }

                        mailSender.Send($"Clã Renomeado: {clan.OldTag} -> {clan.ClanTag} em {clan.Plataform}",
                                        $"URL: {GetClanUrl(clan.Plataform, clan.ClanTag)}");
                    }
                }

                // Tempo extra para os e-mails terminarem de serem enviados
                Log.Info("Esperando 2 minutos antes de encerrar para terminar de enviar os e-mails...");
                Thread.Sleep(TimeSpan.FromMinutes(2));

                Log.InfoFormat("FetchClanMembership terminando normalmente em {0}.", sw.Elapsed);
                return(0);
            }
            catch (Exception ex)
            {
                Log.Fatal(ex);
                Console.WriteLine(ex);
                return(1);
            }
        }
Beispiel #20
0
        private static int Main(string[] args)
        {
            try
            {
                ParseParams(args, out var ageHours, out var maxRunMinutes,
                            out var hourToDeleteOldFiles, out var daysToKeepOnDelete, out var calculateMoe,
                            out var calculateReference, out var playersPerMinute, out var utcShiftToCalculate, out var waitForRemote);

                var resultDirectoryXbox = ConfigurationManager.AppSettings["ResultDirectory"];
                var resultDirectoryPs   = ConfigurationManager.AppSettings["PsResultDirectory"];

                Log.Info("------------------------------------------------------------------------------------");
                Log.Info("CalculateClanStats iniciando...");
                Log.InfoFormat(
                    "ageHours: {0}; maxRunMinutes: {1}; resultDirectory: {2}; resultDirectoryPs: {3}; utcShiftToCalculate: {4}; waitForRemote: {5}",
                    ageHours, maxRunMinutes, resultDirectoryXbox, resultDirectoryPs, utcShiftToCalculate, waitForRemote);

                var sw = Stopwatch.StartNew();

                var connectionString = ConfigurationManager.ConnectionStrings["Main"].ConnectionString;
                var provider         = new DbProvider(connectionString);
                var clans            = provider.GetClanCalculateOrder(ageHours).ToArray();
                Log.InfoFormat("{0} clãs devem ser calculados.", clans.Length);

                const int averageOutTimeMinutes = 30;
                const int averageClanSize       = 25;
                var       maxPerDay             = playersPerMinute * 60 * 24 - averageOutTimeMinutes * playersPerMinute;
                var       minPerDay             = maxPerDay - averageClanSize;
                Log.Info($"playersPerMinute: {playersPerMinute}; maxPerDay: {maxPerDay}; minPerDay: {minPerDay}");

                var recorder = new DbRecorder(connectionString);

                var putterXbox = new FtpPutter(ConfigurationManager.AppSettings["FtpFolder"],
                                               ConfigurationManager.AppSettings["FtpUser"],
                                               ConfigurationManager.AppSettings["FtpPassworld"]);

                var putterPs = new FtpPutter(ConfigurationManager.AppSettings["PsFtpFolder"],
                                             ConfigurationManager.AppSettings["PsFtpUser"],
                                             ConfigurationManager.AppSettings["PsFtpPassworld"]);

                var mailSender = new MailSender(ConfigurationManager.AppSettings["SmtpHost"],
                                                int.Parse(ConfigurationManager.AppSettings["SmtpPort"]),
                                                true, ConfigurationManager.AppSettings["SmtpUsername"],
                                                ConfigurationManager.AppSettings["SmtpPassword"])
                {
                    From = new MailAddress(ConfigurationManager.AppSettings["SmtpUsername"],
                                           "Calculate Service")
                };

                var webCacheAge    = TimeSpan.FromMinutes(1);
                var cacheDirectory = ConfigurationManager.AppSettings["CacheDirectory"];
                var fetcher        = new Fetcher(cacheDirectory)
                {
                    WebCacheAge      = webCacheAge,
                    WebFetchInterval = TimeSpan.FromSeconds(1),
                    ApplicationId    = ConfigurationManager.AppSettings["WgApi"]
                };

                // Obtém o status, por causa da data dos MoE, para disparar o cálculo assíncrono
                DateTime       lastMoeXbox, lastMoePs, lastReferencesXbox, lastReferencesPs;
                SiteDiagnostic siteStatusXbox, siteStatusPs;
                try
                {
                    siteStatusXbox = fetcher.GetSiteDiagnostic(
                        ConfigurationManager.AppSettings["RemoteSiteStatusApi"], ConfigurationManager.AppSettings["ApiAdminKey"]);
                    siteStatusPs = fetcher.GetSiteDiagnostic(
                        ConfigurationManager.AppSettings["PsRemoteSiteStatusApi"], ConfigurationManager.AppSettings["ApiAdminKey"]);

                    lastMoeXbox        = siteStatusXbox.TanksMoELastDate;
                    lastMoePs          = siteStatusPs.TanksMoELastDate;
                    lastReferencesXbox = siteStatusXbox.TankLeadersLastDate;
                    lastReferencesPs   = siteStatusPs.TankLeadersLastDate;
                }
                catch (Exception ex)
                {
                    Log.Error("Error getting initial site diagnostics", ex);

                    // Since the site id offline...
                    siteStatusXbox = siteStatusPs = new SiteDiagnostic(null);
                    GetLastDatesFromFiles(resultDirectoryXbox, out lastMoeXbox, out lastReferencesXbox);
                    GetLastDatesFromFiles(resultDirectoryPs, out lastMoePs, out lastReferencesPs);
                }

                Log.Info($"lastMoeXbox: {lastMoeXbox:yyyy-MM-dd}");
                Log.Info($"lastMoePs: {lastMoePs:yyyy-MM-dd}");

                Log.Info($"lastReferencesXbox: {lastReferencesXbox:yyyy-MM-dd}");
                Log.Info($"lastReferencesPs: {lastReferencesPs:yyyy-MM-dd}");

                // Dispara as tarefas de calculo gerais
                var calculationTask = Task.Run(() => RunCalculations(calculateReference, calculateMoe,
                                                                     lastMoeXbox, lastMoePs, lastReferencesXbox, lastReferencesPs, provider, recorder, mailSender,
                                                                     resultDirectoryXbox, resultDirectoryPs,
                                                                     putterXbox, putterPs, fetcher, utcShiftToCalculate));

                // Dispara a tarefa de apagar arquivos antigos dos servidores
                var deleteTask = Task.Run(() =>
                {
                    if (DateTime.UtcNow.Hour != hourToDeleteOldFiles || daysToKeepOnDelete < 28)
                    {
                        return;
                    }

                    // Apaga arquivos com a API administrativa
                    var cleanXBox = Task.Run(() =>
                    {
                        try
                        {
                            var cleaner = new Putter(Platform.XBOX, ConfigurationManager.AppSettings["ApiAdminKey"]);
                            cleaner.CleanFiles();
                        }
                        catch (Exception ex)
                        {
                            Log.Error("Erro cleaning XBOX", ex);
                        }
                    });

                    var cleanPs = Task.Run(() =>
                    {
                        try
                        {
                            var cleaner = new Putter(Platform.PS, ConfigurationManager.AppSettings["ApiAdminKey"]);
                            cleaner.CleanFiles();
                        }
                        catch (Exception ex)
                        {
                            Log.Error("Erro cleaning XBOX", ex);
                        }
                    });

                    if (waitForRemote)
                    {
                        Task.WhenAll(cleanXBox, cleanPs);
                    }
                });

                // Calcula cada clã
                var doneCount = 0;
                var timedOut  = false;
                Parallel.For(0, clans.Length, new ParallelOptions {
                    MaxDegreeOfParallelism = 2
                }, i =>
                {
                    if (sw.Elapsed.TotalMinutes > maxRunMinutes)
                    {
                        timedOut = true;
                        return;
                    }

                    var clan = clans[i];

                    Log.InfoFormat("Processando clã {0} de {1}: {2}@{3}...", i + 1, clans.Length, clan.ClanTag,
                                   clan.Plataform);
                    var csw = Stopwatch.StartNew();

                    var cc = CalculateClan(clan, provider, recorder);

                    Log.InfoFormat("Calculado clã {0} de {1}: {2}@{3} em {4:N1}s...",
                                   i + 1, clans.Length, clan.ClanTag, clan.Plataform, csw.Elapsed.TotalSeconds);

                    if (cc != null)
                    {
                        var fsw = Stopwatch.StartNew();
                        switch (cc.Plataform)
                        {
                        case Platform.XBOX:
                            {
                                var fileName = cc.ToFile(resultDirectoryXbox);
                                Log.InfoFormat("Arquivo de resultado escrito em '{0}'", fileName);

                                var putTask = Task.Run(() =>
                                {
                                    try
                                    {
                                        putterXbox.PutClan(fileName);
                                    }
                                    catch (Exception ex)
                                    {
                                        Log.Error($"Error putting XBOX clan file for {cc.ClanTag}", ex);
                                    }
                                });

                                if (waitForRemote)
                                {
                                    putTask.Wait();
                                }
                            }
                            break;

                        case Platform.PS:
                            {
                                var fileName = cc.ToFile(resultDirectoryPs);
                                Log.InfoFormat("Arquivo de resultado escrito em '{0}'", fileName);

                                var putTask = Task.Run(() =>
                                {
                                    try
                                    {
                                        putterPs.PutClan(fileName);
                                    }
                                    catch (Exception ex)
                                    {
                                        Log.Error($"Error putting PS clan file for {cc.ClanTag}", ex);
                                    }
                                });

                                if (waitForRemote)
                                {
                                    putTask.Wait();
                                }
                            }
                            break;

                        case Platform.Virtual:
                            break;

                        default:
                            throw new ArgumentOutOfRangeException();
                        }
                        Log.InfoFormat("Upload do clã {0} de {1}: {2}@{3} em {4:N1}s...",
                                       i + 1, clans.Length, clan.ClanTag, clan.Plataform, fsw.Elapsed.TotalSeconds);
                    }
                    Interlocked.Increment(ref doneCount);
                    Log.InfoFormat("Processado clã {0} de {1}: {2}@{3} em {4:N1}s. {5} totais.",
                                   i + 1, clans.Length, clan.ClanTag, clan.Plataform, csw.Elapsed.TotalSeconds, doneCount);
                });
                var calculationTime = sw.Elapsed;

                // Envia o e-mail de status

                try
                {
                    siteStatusXbox = fetcher.GetSiteDiagnostic(ConfigurationManager.AppSettings["RemoteSiteStatusApi"], ConfigurationManager.AppSettings["ApiAdminKey"]);
                    siteStatusPs   = fetcher.GetSiteDiagnostic(ConfigurationManager.AppSettings["PsRemoteSiteStatusApi"], ConfigurationManager.AppSettings["ApiAdminKey"]);
                }
                catch (Exception ex)
                {
                    Log.Error("Error getting final site diagnostics", ex);

                    // The site is offline...
                    siteStatusXbox = siteStatusPs = new SiteDiagnostic(null);
                }

                Log.Debug("Obtendo informações do BD...");
                var dd = provider.GetDataDiagnostic();
                Log.InfoFormat("Filas: {0} jogadores; {1} clans; {2} cálculos.",
                               dd.PlayersQueueLenght, dd.MembershipQueueLenght, dd.CalculateQueueLenght);
                Log.InfoFormat(
                    "{0} jogadores; {1:N0} por dia; {2:N0} por hora; reais: {3:N0}; {4:N0}; {5:N0}; {6:N0}",
                    dd.TotalPlayers, dd.ScheduledPlayersPerDay, dd.ScheduledPlayersPerHour,
                    dd.AvgPlayersPerHourLastDay, dd.AvgPlayersPerHourLast6Hours, dd.AvgPlayersPerHourLast2Hours,
                    dd.AvgPlayersPerHourLastHour);

                Log.Debug("Enviando e-mail...");
                mailSender.SendStatusMessage(siteStatusXbox, siteStatusPs, dd, minPerDay, maxPerDay,
                                             calculationTime, doneCount, timedOut);

                if (dd.ScheduledPlayersPerDay < minPerDay || dd.ScheduledPlayersPerDay > maxPerDay)
                {
                    recorder.BalanceClanSchedule(minPerDay, maxPerDay);
                }

                Log.DebugFormat(
                    "DateTime.UtcNow: {0:o}; hourToDeleteOldFiles: {1}; daysToKeepOnDelete: {2}",
                    DateTime.UtcNow, hourToDeleteOldFiles, daysToKeepOnDelete);

                // Espera o cálculo e a deleção terminarem
                Task.WaitAll(calculationTask, deleteTask);

                // Tempo extra para os e-mails terminarem de serem enviados
                Thread.Sleep(TimeSpan.FromMinutes(2));

                Log.InfoFormat("CalculateClanStats terminando normalmente para {1} clãs em {0}.", sw.Elapsed,
                               clans.Length);
                return(0);
            }
            catch (Exception ex)
            {
                Log.Fatal(ex);
                Console.WriteLine(ex);
                return(1);
            }
        }
Beispiel #21
0
        public async Task SetClan(CommandContext ctx, [Description("The clan tag")] string clanTag,
                                  [Description("The clan flag")] string flagCode                 = null,
                                  [Description("Enable or Disable the Clan")] bool enable        = true,
                                  [Description("To ban or not a clan from the site")] bool isBan = false)
        {
            await ctx.TriggerTypingAsync();

            var userId = ctx?.User?.Id ?? 0;

            Log.Info($"Requesting {nameof(SetClan)} by {userId}...");
            if (userId != _coder)
            {
                var emoji = DiscordEmoji.FromName(ctx.Client, ":no_entry:");
                var embed = new DiscordEmbedBuilder
                {
                    Title       = "Access denied",
                    Description = $"{emoji} You may be a *coder*, but you are not **The Coder**!",
                    Color       = DiscordColor.Red
                };

                await ctx.RespondAsync("", embed : embed);

                return;
            }
            var cfg       = GuildConfiguration.FromGuild(ctx.Guild);
            var plataform = GetPlataform(clanTag, cfg.Plataform, out clanTag);

            clanTag = clanTag.Trim('[', ']');
            clanTag = clanTag.ToUpperInvariant();

            if (!ClanTagRegex.IsMatch(clanTag))
            {
                await ctx.RespondAsync($"You must send a **valid** clan **tag** as parameter, {ctx.User.Mention}.");

                return;
            }

            if (!string.IsNullOrWhiteSpace(flagCode))
            {
                flagCode = flagCode.RemoveDiacritics().ToUpperInvariant();

                if (flagCode.Length != 2)
                {
                    await ctx.RespondAsync($"The flag code must be 2 letters only, {ctx.User.Mention}.");

                    return;
                }
            }

            Log.Warn($"{nameof(SetClan)}({clanTag}, {plataform}, {flagCode}, {enable}, {isBan})...");

            try
            {
                await ctx.TriggerTypingAsync();

                var provider = new DbProvider(_connectionString);
                var recorder = new DbRecorder(_connectionString);

                var cacheDirectory = ConfigurationManager.AppSettings["CacheDir"] ?? Path.GetTempPath();
                var webCacheAge    = TimeSpan.FromHours(4);
                var appId          = ConfigurationManager.AppSettings["WgAppId"] ?? "demo";

                var fetcher = new Fetcher(cacheDirectory)
                {
                    ApplicationId    = appId,
                    WebCacheAge      = webCacheAge,
                    WebFetchInterval = TimeSpan.FromSeconds(1)
                };

                var clan = provider.GetClan(plataform, clanTag);
                if (clan == null && enable)
                {
                    // Check to add...
                    await ctx.RespondAsync($"Not found `{clanTag}` on the database. Searching the WG API...");

                    await ctx.TriggerTypingAsync();

                    var clanOnSite = fetcher.FindClan(plataform, clanTag, true);
                    if (clanOnSite == null)
                    {
                        await ctx.RespondAsync($"Not found `{clanTag}` on the WG API for `{plataform}`. Check the clan tag.");

                        return;
                    }

                    if (clanOnSite.AllMembersCount < 7)
                    {
                        await ctx.RespondAsync($"The clan `{clanTag}` on `{plataform}` has only {clanOnSite.AllMembersCount}, and will not be added to the system.");

                        return;
                    }

                    clanOnSite.Country = flagCode;
                    recorder.Add(clanOnSite);

                    await ctx.RespondAsync($"The clan `{clanTag}` on `{plataform}` with {clanOnSite.AllMembersCount} members was added to the system and " +
                                           $"should appear on the site in ~12 hours. Keep playing to achieve at least 7 members with 21 recent battles and appear on the default view.");

                    Log.Info($"Added {plataform}.{clanTag}");
                    return;
                }

                if (!clan.Enabled && enable)
                {
                    // Can be enabled?
                    var clanOnSite = fetcher.GetClans(new[] { clan }).FirstOrDefault();
                    if (clanOnSite == null)
                    {
                        await ctx.RespondAsync($"Not found `{clanTag}` on the WG API for `{plataform}`. Check the clan tag.");

                        return;
                    }

                    if (clanOnSite.IsDisbanded)
                    {
                        await ctx.RespondAsync($"The clan `{clanTag}` on `{plataform}` was disbanded.");

                        return;
                    }

                    if (clanOnSite.Count < 7)
                    {
                        await ctx.RespondAsync($"The clan `{clanTag}` on `{plataform}` has only {clanOnSite.Count} members and will not be enabled.");

                        return;
                    }

                    if (clan.DisabledReason == DisabledReason.Banned)
                    {
                        await ctx.RespondAsync($"The clan `{clanTag}` ({clan.ClanId}) on `{plataform}` was **banned** from the site.");

                        return;
                    }

                    recorder.EnableClan(clanOnSite.Plataform, clanOnSite.ClanId);
                    await ctx.RespondAsync($"The clan `{clanTag}` on `{plataform}` disabled for `{clan.DisabledReason}` is enabled again.");

                    Log.Info($"Enabled {plataform}.{clanTag}");
                }
                else if (clan.Enabled && !enable)
                {
                    if (isBan)
                    {
                        recorder.DisableClan(clan.Plataform, clan.ClanId, DisabledReason.Banned);
                        await ctx.RespondAsync($"The clan `{clanTag}` ({clan.ClanId}) on `{plataform}` was **BANNED** from the site.");

                        Log.Warn($"BANNED {plataform}.{clanTag}");
                    }
                    else
                    {
                        recorder.DisableClan(clan.Plataform, clan.ClanId, DisabledReason.Unknow);
                        await ctx.RespondAsync($"The clan `{clanTag}` ({clan.ClanId}) on `{plataform}` was **disabled** from the site.");

                        Log.Warn($"Disabled {plataform}.{clanTag}");
                    }
                }

                // change flag?
                flagCode = flagCode ?? string.Empty;
                if (flagCode.ToUpperInvariant() != (clan.Country ?? string.Empty).ToUpperInvariant())
                {
                    recorder.SetClanFlag(clan.Plataform, clan.ClanId, flagCode);
                    await ctx.RespondAsync($"The flag of the clan `{clanTag}` on `{plataform}` was changed to `{flagCode}`.");

                    Log.Info($"Flag changed on {plataform}.{clanTag} to {flagCode}.");
                }

                await ctx.RespondAsync($"all done for `{clan.ClanTag}` on `{plataform}`.");
            }
            catch (Exception ex)
            {
                Log.Error($"{nameof(SetClan)}", ex);
                await ctx.RespondAsync($"Sorry, {ctx.User.Mention}. There was an error... the *Coder* will be notified of `{ex.Message}`.");

                return;
            }
        }
Beispiel #22
0
        private static void RunCalculations(bool calculateReference, bool calculateMoe, DateTime?moeLastDateXbox, DateTime?moeLastDatePs,
                                            DateTime?lastReferencesXbox, DateTime?lastReferencesPs, DbProvider provider, DbRecorder recorder, MailSender mailSender,
                                            string resultDirectory, string resultDirectoryPs, FtpPutter ftpPutterXbox, FtpPutter ftpPutterPs,
                                            Fetcher fetcher, int utcShiftToCalculate)
        {
            Debug.Assert(mailSender != null);

            // Obtém os valores esperados de WN8
            if ((DateTime.UtcNow.Hour % 4) == 1)
            {
                HandleWn8ExpectedValues(Platform.XBOX, provider, resultDirectory, ftpPutterXbox, recorder, fetcher);
                HandleWn8ExpectedValues(Platform.PS, provider, resultDirectoryPs, ftpPutterPs, recorder, fetcher);
            }

            // 2nd hour of every day retrieve PC Tanks
            if (DateTime.UtcNow.Hour == 2)
            {
                Log.Info("Retrieving PC Tanks...");
                recorder.Set(fetcher.GetTanks(Platform.PC));
                Log.Debug("PC Tanks saved on Database");
            }

            if (calculateMoe)
            {
                CalculateMoE(moeLastDateXbox, moeLastDatePs, provider, recorder, mailSender, resultDirectory, resultDirectoryPs,
                             ftpPutterXbox, ftpPutterPs, utcShiftToCalculate);
            }


            if (calculateReference)
            {
                CalculateTanksReferences(lastReferencesXbox, lastReferencesPs, provider, recorder, mailSender, resultDirectory, resultDirectoryPs,
                                         ftpPutterXbox, ftpPutterPs, utcShiftToCalculate);
            }
        }
Beispiel #23
0
        private static void GetFromWoTStatConsole()
        {
            var connectionString = ConfigurationManager.ConnectionStrings["Main"].ConnectionString;
            var provider         = new DbProvider(connectionString);
            var recorder         = new DbRecorder(connectionString);

            var webCacheAge    = TimeSpan.FromMinutes(10);
            var cacheDirectory = ConfigurationManager.AppSettings["CacheDirectory"];

            var fetcher = new Fetcher(cacheDirectory)
            {
                WebCacheAge      = webCacheAge,
                WebFetchInterval = TimeSpan.FromSeconds(1),
                ApplicationId    = ConfigurationManager.AppSettings["WgApi"]
            };

            Log.Debug("Obtendo jogadores a atualizar.");
            const int ageHours = 24;
            var       players  = provider.GetPlayersUpdateOrder(1000, ageHours).Where(p => p.AdjustedAgeHours < 1000).Take(1000).ToArray();

            if (players.Length <= 0)
            {
                Log.Warn("Fila vazia!");
                return;
            }

            Log.Info($"{players.Length} na fila.");

            var sw = Stopwatch.StartNew();

            var cts = new CancellationTokenSource();
            var po  = new ParallelOptions
            {
                CancellationToken      = cts.Token,
                MaxDegreeOfParallelism = 2
            };

            bool isEnd = false;
            int  count = 0;

            Parallel.For(0, players.Length, po, i =>
            {
                if (isEnd)
                {
                    return;
                }

                if (sw.Elapsed.TotalMinutes > 10)
                {
                    isEnd = true;

                    Log.Warn("Tempo Esgotado!");
                    Log.Info($"Completo! {count} em {sw.Elapsed.TotalSeconds}. {count / sw.Elapsed.TotalMinutes:N1} players/minute");
                    return;
                }

                var player = players[i];
                var task   = fetcher.GetPlayerWn8Async(player);
                task.Wait(po.CancellationToken);

                var completePlayer = task.Result;
                if (completePlayer != null)
                {
                    if (completePlayer.CanSave())
                    {
                        recorder.Set(completePlayer);
                        Log.Info("Salvo!");
                    }
                    else
                    {
                        Log.WarnFormat("Jogador {0}.{1}@{2} com muitos dados zerados não será salvo no BD.",
                                       completePlayer.Id, completePlayer.Name, completePlayer.Plataform);
                    }
                }

                Interlocked.Increment(ref count);
            });
            sw.Stop();

            Log.Info($"Completo! {count} em {sw.Elapsed.TotalSeconds}. {count / sw.Elapsed.TotalMinutes:N1} players/minute");
        }
Beispiel #24
0
 public ImportMoe(Fetcher fetcher, DbRecorder recorder)
 {
     _fetcher  = fetcher;
     _recorder = recorder;
 }
Beispiel #25
0
        /// <summary>
        /// Retrieves a player from database, or only WG API
        /// </summary>
        /// <param name="gamerTag"></param>
        /// <returns></returns>
        public async Task <Player> GetPlayer(CommandContext ctx, string gamerTag)
        {
            try
            {
                var cfg       = GuildConfiguration.FromGuild(ctx.Guild);
                var plataform = GetPlataform(gamerTag, cfg.Plataform, out gamerTag);

                var provider = new DbProvider(_connectionString);
                var recorder = new DbRecorder(_connectionString);

                DiscordMessage willTryApiMessage = null;

                long?playerId = null;
                if (gamerTag.EqualsCiAi("me"))
                {
                    playerId = provider.GetPlayerIdByDiscordId((long)ctx.User.Id);
                }

                playerId = playerId ?? provider.GetPlayerIdByName(plataform, gamerTag);
                if (playerId == null)
                {
                    Log.Debug($"Could not find player {plataform}.{gamerTag} on the database... trying the API...");
                    willTryApiMessage = await ctx.RespondAsync($"I could not find a player on `{plataform}` " +
                                                               $"with the Gamer Tag `{gamerTag}` on the Database, {ctx.User.Mention}. I will try the Wargaming API... it may take some time...");
                }

                var cacheDirectory = ConfigurationManager.AppSettings["CacheDir"] ?? Path.GetTempPath();
                var webCacheAge    = TimeSpan.FromHours(4);
                var appId          = ConfigurationManager.AppSettings["WgAppId"] ?? "demo";

                var fetcher = new Fetcher(cacheDirectory)
                {
                    ApplicationId    = appId,
                    WebCacheAge      = webCacheAge,
                    WebFetchInterval = TimeSpan.FromSeconds(1)
                };

                Player apiPlayer = null;
                if (playerId == null)
                {
                    await ctx.TriggerTypingAsync();

                    apiPlayer = fetcher.GetPlayerByGamerTag(plataform, gamerTag);
                    if (apiPlayer == null)
                    {
                        Log.Debug($"Could not find player {plataform}.{gamerTag} on the WG API.");

                        if (willTryApiMessage != null)
                        {
                            await willTryApiMessage.DeleteAsync("Information updated.");
                        }

                        await ctx.RespondAsync($"Sorry, {ctx.User.Mention}. I could not find a player on `{plataform}` " +
                                               $"with the Gamer Tag `{gamerTag}` on the Wargaming API. Are you sure about the **exact** gamer tag?.");

                        return(null);
                    }
                    playerId = apiPlayer.Id;
                }

                var player = provider.GetPlayer(playerId.Value, true);

                var wn8Expected = provider.GetWn8ExpectedValues(player?.Plataform ?? apiPlayer.Plataform);

                if ((player == null) && (apiPlayer != null))
                {
                    // Not on my database, but on the API Let's work with overall data!
                    IEnumerable <WgApi.TankPlayer> tanks = fetcher.GetTanksForPlayer(apiPlayer.Plataform, apiPlayer.Id);
                    foreach (var t in tanks)
                    {
                        t.All.TreesCut = t.TreesCut;
                        t.All.BattleLifeTimeSeconds = t.BattleLifeTimeSeconds;
                        t.All.MarkOfMastery         = t.MarkOfMastery;
                        t.All.MaxFrags   = t.MaxFrags;
                        t.All.LastBattle = t.LastBattle;
                    }

                    apiPlayer.Performance = new Tanks.TankPlayerPeriods()
                    {
                        All = tanks.ToDictionary(t => t.TankId, t => t.All)
                    };

                    apiPlayer.Calculate(wn8Expected);

                    if (willTryApiMessage != null)
                    {
                        await willTryApiMessage.DeleteAsync("Information updated.");
                    }

                    return(apiPlayer);
                }

                if (player.Age.TotalHours > 4)
                {
                    willTryApiMessage = await ctx.RespondAsync($"Data for  `{player.Name}` on `{player.Plataform}` " +
                                                               $"is more than {player.Age.TotalHours:N0}h old, {ctx.User.Mention}. Retrieving fresh data, please wait...");

                    var tanks      = fetcher.GetTanksForPlayer(player.Plataform, player.Id);
                    var allTanks   = provider.GetTanks(player.Plataform).ToDictionary(t => t.TankId);
                    var validTanks = tanks.Where(t => allTanks.ContainsKey(t.TankId)).ToArray();
                    recorder.Set(validTanks);

                    var played = provider.GetWn8RawStatsForPlayer(player.Plataform, player.Id);
                    player.Performance = played;
                    player.Calculate(wn8Expected);
                    player.Moment = DateTime.UtcNow;
                    player.Origin = PlayerDataOrigin.Self;

                    var previous = provider.GetPlayer(player.Id, player.Date, true);
                    if (previous != null)
                    {
                        if (player.Check(previous, true))
                        {
                            Log.Warn($"Player {player.Name}.{player.Id}@{player.Plataform} was patched.");
                        }
                    }

                    if (player.CanSave())
                    {
                        recorder.Set(player);
                        if (!player.IsPatched)
                        {
                            var putter = new Putter(player.Plataform, ConfigurationManager.AppSettings["ApiAdminKey"]);
                            putter.Put(player);
                        }
                    }
                    else
                    {
                        Log.Warn($"Player {player.Name}.{player.Id}@{player.Plataform} has to much zero data.");
                    }
                }
                else
                {
                    player.Calculate(wn8Expected);
                }

                if (willTryApiMessage != null)
                {
                    await willTryApiMessage.DeleteAsync("Information updated.");
                }

                return(player);
            }
            catch (Exception ex)
            {
                Log.Error($"{nameof(GetPlayer)}({gamerTag})", ex);
                await ctx.RespondAsync($"Sorry, {ctx.User.Mention}. There was an error... the *Coder* will be notified of `{ex.Message}`.");

                return(null);
            }
        }
Beispiel #26
0
 public PurgeOldPlayers(DbRecorder recorder)
 {
     _recorder = recorder;
 }
Beispiel #27
0
        private static int Main(string[] args)
        {
            try
            {
                var sw = Stopwatch.StartNew();

                ParseParans(args, out var ageHours, out var maxPlayers, out var maxRunMinutes,
                            out var webCacheAge, out var kp, out var ki, out var kd, out var maxParallel, out var queryWotStatConsoleApi,
                            out var putPlayers);

                var cacheDirectory = ConfigurationManager.AppSettings["CacheDirectory"];

                Log.Info("------------------------------------------------------------------------------------");
                Log.Info("FetchPlayers iniciando...");
                Log.Info($"Compilado em {RetrieveLinkerTimestamp():yyyy-MM-dd HH:mm}; executando no diretorio {Environment.CurrentDirectory}");
                Log.InfoFormat("ageHours: {0}; cacheDirectory: {1}, maxParallel: {2}, queryWotStatConsoleApi: {3}", ageHours, cacheDirectory, maxParallel, queryWotStatConsoleApi);
                Log.Info($"kp: {kp:R}; ki: {ki:R}; kd: {kd:R}");

                var connectionString = ConfigurationManager.ConnectionStrings["Main"].ConnectionString;
                var provider         = new DbProvider(connectionString);
                var recorder         = new DbRecorder(connectionString);

                if (maxRunMinutes == null)
                {
                    maxRunMinutes = 60 - DateTime.Now.Minute;
                    if (maxRunMinutes < 5)
                    {
                        maxRunMinutes = 5;
                    }
                }

                var dbInfo             = provider.GetDataDiagnostic();
                int originalMaxPlayers = maxPlayers ?? 0;
                if (maxPlayers == null)
                {
                    maxPlayers         = (int?)(dbInfo.ScheduledPlayersPerHour / 60.0 * maxRunMinutes.Value);
                    originalMaxPlayers = maxPlayers.Value;
                    maxPlayers         = (int?)(maxPlayers.Value * 1.20);
                }

                Log.Info($"maxRunMinutes: {maxRunMinutes}; maxPlayers: {maxPlayers}; originalMaxPlayers: {originalMaxPlayers}");

                var players = provider.GetPlayersUpdateOrder(maxPlayers.Value, ageHours).ToArray();

                if (players.Length <= 0)
                {
                    Log.Warn("Fila vazia!");
                    return(3);
                }

                double playersPerMinute = players.Length * 1.0 / ((double)maxRunMinutes);
                Log.Debug("Avg playersPerMinute: {playersPerMinute:N0}");
                double externalApiCallFactor = 0.0;
                if (queryWotStatConsoleApi > 0)
                {
                    externalApiCallFactor = queryWotStatConsoleApi / playersPerMinute;
                    if (externalApiCallFactor > 1.0)
                    {
                        externalApiCallFactor = 1.0;
                    }
                    Log.Debug("externalApiCallFactor: {externalApiCallFactor}");
                }
                var externalCallRandom = new Random(69);

                var recentlyUpdatedPlayers = players.Select(p => p.AdjustedAgeHours).Where(a => a < 6000).ToArray();
                if (recentlyUpdatedPlayers.Any())
                {
                    var averageAgeHours = recentlyUpdatedPlayers.Take(originalMaxPlayers).Average();
                    var modeAgeHours    = recentlyUpdatedPlayers
                                          .Take(originalMaxPlayers).Select(a => (decimal)(Math.Floor(a * 100.0) / 100.0)).GroupBy(a => a)
                                          .OrderByDescending(g => g.Count()).ThenBy(g => g.Key).Select(g => g.Key).FirstOrDefault();
                    Log.Info($"Idade média dos dados: {averageAgeHours:N2}");
                    Log.Info($"Idade moda  dos dados: {modeAgeHours:N2}");
                }

                Log.Info($"Delay últimas 48h: {dbInfo.Last48HDelay:N2}");
                if (dbInfo.Last48HDelay <= ageHours)
                {
                    // Pontual, faz apenas o planejado
                    Log.InfoFormat("Não está atrasado.");
                    players = players.Take(originalMaxPlayers).ToArray();
                }

                var fetchers = new ConcurrentQueue <Fetcher>();

                for (int i = 0; i < maxParallel * 8; ++i)
                {
                    var fetcher = new Fetcher(cacheDirectory)
                    {
                        WebCacheAge      = webCacheAge,
                        WebFetchInterval = TimeSpan.FromSeconds(1),
                        ApplicationId    = ConfigurationManager.AppSettings["WgApi"]
                    };
                    fetchers.Enqueue(fetcher);
                }

                Log.Debug("Obtendo todos os tanques em XBOX...");
                var f = fetchers.Dequeue();
                recorder.Set(f.GetTanks(Plataform.XBOX));
                var allTanksXbox = provider.GetTanks(Plataform.XBOX).ToDictionary(t => t.TankId);
                fetchers.Enqueue(f);
                Log.InfoFormat("Obtidos {0} tanques para XBOX.", allTanksXbox.Count);

                Log.Debug("Obtendo todos os tanques em PS...");
                f = fetchers.Dequeue();
                recorder.Set(f.GetTanks(Plataform.PS));
                var allTanksPs = provider.GetTanks(Plataform.PS).ToDictionary(t => t.TankId);
                fetchers.Enqueue(f);
                Log.InfoFormat("Obtidos {0} tanques para PS.", allTanksPs.Count);

                // Ambas as plataformas usam os mesmos valores de referência
                var wn8Expected = provider.GetWn8ExpectedValues(Plataform.XBOX);

                var    idealInterval  = (maxRunMinutes.Value * 60.0 - sw.Elapsed.TotalSeconds) / players.Length;
                double threadInterval = idealInterval * maxParallel * 0.80;
                var    lockObject     = new object();

                // To save on players on the remote server (Same remote DB, so the plataform doesn't matter)
                var putter = putPlayers ? new Putter(Plataform.PS, ConfigurationManager.AppSettings["ApiAdminKey"]) : null;

                var cts = new CancellationTokenSource();
                var po  = new ParallelOptions
                {
                    CancellationToken      = cts.Token,
                    MaxDegreeOfParallelism = maxParallel
                };

                // A velocidade do loop é controlada por um sistema PID. Veja exemplo em https://www.codeproject.com/Articles/36459/PID-process-control-a-Cruise-Control-example

                double   integral = 0.0;
                double   previousError = 0.0, sumErrorSq = 0.0;
                DateTime previousTime = DateTime.UtcNow;
                int      count = 0, controlledLoops = 0;

                try
                {
                    Parallel.For(0, players.Length, po, i =>
                    {
                        if (po.CancellationToken.IsCancellationRequested)
                        {
                            return;
                        }

                        if (sw.Elapsed.TotalMinutes > maxRunMinutes)
                        {
                            cts.Cancel();
                        }

                        var wg = fetchers.Dequeue();

                        Fetcher ext = null;
                        if (externalCallRandom.NextDouble() < externalApiCallFactor)
                        {
                            ext = fetchers.Dequeue();
                        }

                        var player = players[i];

                        var swPlayer = Stopwatch.StartNew();
                        var allTanks = player.Plataform == Plataform.XBOX ? allTanksXbox : allTanksPs;
                        RetrievePlayer(player, wg, ext, provider, recorder, allTanks, wn8Expected, putter);
                        swPlayer.Stop();

                        if (ext != null)
                        {
                            fetchers.Enqueue(ext);
                        }

                        fetchers.Enqueue(wg);

                        Thread.Sleep(TimeSpan.FromSeconds(threadInterval));

                        lock (lockObject)
                        {
                            Interlocked.Increment(ref count);
                            var actualInterval = sw.Elapsed.TotalSeconds / count;

                            var error = idealInterval - actualInterval;
                            var time  = DateTime.UtcNow;
                            var dt    = (time - previousTime).TotalSeconds;

                            var remainingSeconds = maxRunMinutes.Value * 60.0 - sw.Elapsed.TotalSeconds;
                            var remainingPlayers = players.Length - count;

                            if ((count > 20) && (remainingSeconds > 60) && (remainingPlayers > 5) && (dt > 0.01))
                            {
                                integral       += error * dt;
                                var derivative  = (error - previousError) / dt;
                                var output      = (error * kp) + (integral * ki) + (derivative * kd);
                                threadInterval += output;

                                controlledLoops++;
                                sumErrorSq += error * error;

                                if (threadInterval < 0.1)
                                {
                                    threadInterval = 0.1;
                                }
                                else if (threadInterval > 30)
                                {
                                    threadInterval = 30;
                                }

                                Log.Info($"i: {i:0000}; {player.Id:00000000000}@{player.Plataform.ToString().PadRight(4)}; Count: {count:0000}; " +
                                         $"TI: {threadInterval:00.00}; Actual: {actualInterval:00.00}; Ideal: {idealInterval:00.00}; " +
                                         $"out: {output:+00.000;-00.000}; dt: {dt:000.000}; rt: {swPlayer.Elapsed.TotalSeconds:000.000}; Target: {maxRunMinutes*60.0/actualInterval:0000}; " +
                                         $"HadExt: {ext != null}");

                                idealInterval = remainingSeconds / remainingPlayers;
                            }
                            else
                            {
                                Log.Info($"i: {i:0000}; {player.Id:00000000000}@{player.Plataform.ToString().PadRight(4)}; Count: {count:0000}; " +
                                         $"TI: {threadInterval:00.00}; Actual: {actualInterval:00.00}; Ideal: {idealInterval:00.00}; " +
                                         $"out: {0.0:+00.000;-00.000}; dt: {dt:000.000}; rt: {swPlayer.Elapsed.TotalSeconds:000.000}; Target: {maxRunMinutes * 60.0 / actualInterval:0000}; " +
                                         $"HadExt: {ext != null}");
                            }

                            previousError = error;
                            previousTime  = time;
                        }
                    });
                }
                catch (OperationCanceledException)
                {
                    Log.WarnFormat("Tempo esgotado antes de concluir a fila no {0} de {1}. Erro de Controle: {2:N4}",
                                   count, players.Length, sumErrorSq / controlledLoops);
                    return(2);
                }

                Log.InfoFormat("FetchPlayers terminando normalmente em {0}. Feitos {1}. Erro de Controle: {2:N4}",
                               sw.Elapsed, players.Length, sumErrorSq / controlledLoops);
                return(0);
            }
            catch (Exception ex)
            {
                Log.Fatal(ex);
                Console.WriteLine(ex);
                return(1);
            }
        }
Beispiel #28
0
        private static void HandleWn8ExpectedValues(Platform platform, DbProvider provider, string resultDirectory, FtpPutter ftpPutter, DbRecorder recorder, Fetcher fetcher)
        {
            // Aproveito e pego e salvo os dados de WN8
            if ((recorder != null) && (fetcher != null))
            {
                Log.Info($"Pegando dados de WN8 para {platform}...");
                recorder.Set(fetcher.GetXvmWn8ExpectedValuesAsync().Result);
                Log.Info("Dados de WN8 obtidos e salvos.");
            }

            var wn8 = provider.GetWn8ExpectedValues(platform);

            if (wn8 != null)
            {
                var json = JsonConvert.SerializeObject(wn8, Formatting.Indented);
                var file = Path.Combine(resultDirectory, "MoE", $"{wn8.Date:yyyy-MM-dd}.WN8.json");
                File.WriteAllText(file, json, Encoding.UTF8);
                Log.DebugFormat("Salvo o WN8 Expected em '{0}'", file);

                _ = Task.Run(() =>
                {
                    try
                    {
                        ftpPutter.PutMoe(file);
                    }
                    catch (Exception ex)
                    {
                        Log.Error($"Error putting WN8 on {platform}", ex);
                    }
                });

                Log.Debug($"Feito upload do WN8 para {platform}");
            }
        }
Beispiel #29
0
 public BalanceClans(DbProvider provider, DbRecorder recorder)
 {
     _provider = provider;
     _recorder = recorder;
 }
Beispiel #30
0
        private static void RunCalculations(bool calculateReference, bool calculateMoe, DateTime?moeLastDateXbox, DateTime?moeLastDatePs,
                                            DateTime?lastReferencesXbox, DateTime?lastReferencesPs, DbProvider provider, DbRecorder recorder, MailSender mailSender,
                                            string resultDirectory, string resultDirectoryPs, FtpPutter ftpPutterXbox, FtpPutter ftpPutterPs,
                                            Fetcher fetcher, int utcShiftToCalculate)
        {
            Debug.Assert(mailSender != null);

            // Obtem os valores esperados de WN8
            if ((DateTime.UtcNow.Hour % 4) == 1)
            {
                HandleWn8ExpectedValues(Platform.XBOX, provider, resultDirectory, ftpPutterXbox, recorder, fetcher);
                HandleWn8ExpectedValues(Platform.PS, provider, resultDirectoryPs, ftpPutterPs, recorder, fetcher);
            }

            if (calculateMoe)
            {
                CalculateMoE(moeLastDateXbox, moeLastDatePs, provider, recorder, mailSender, resultDirectory, resultDirectoryPs,
                             ftpPutterXbox, ftpPutterPs, utcShiftToCalculate);
            }


            if (calculateReference)
            {
                CalculateTanksReferences(lastReferencesXbox, lastReferencesPs, provider, recorder, mailSender, resultDirectory, resultDirectoryPs,
                                         ftpPutterXbox, ftpPutterPs, utcShiftToCalculate);
            }
        }