Esempio n. 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);
            }
        }
Esempio n. 2
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);
            }
        }
Esempio n. 3
0
        private static void PutMoEOnPlataform(Platform platform, DateTime?moeLastDate,
                                              DbProvider provider, MailSender mailSender,
                                              string resultDirectory, FtpPutter ftpPutter)
        {
            Log.Debug($"Verificando atualização de MoE em {platform}");

            Debug.Assert(moeLastDate != null, nameof(moeLastDate) + " != null");
            Log.DebugFormat("Site Date: {0:yyyy-MM-dd}", moeLastDate.Value);

            var dbDate = provider.GetMoe(platform).First().Date;

            Log.DebugFormat("DB Date: {0:yyyy-MM-dd}", dbDate);

            var date = moeLastDate.Value.AddDays(1);

            while (date <= dbDate)
            {
                Log.InfoFormat("Calculando e fazendo upload para {0:yyyy-MM-dd}...", date);
                var moes = provider.GetMoe(platform, date).ToDictionary(t => t.TankId);

                if (moes.Count > 0)
                {
                    var json = JsonConvert.SerializeObject(moes, Formatting.Indented);
                    var file = Path.Combine(resultDirectory, "MoE", $"{date:yyyy-MM-dd}.moe.json");
                    File.WriteAllText(file, json, Encoding.UTF8);
                    Log.DebugFormat("Salvo o MoE em '{0}'", file);

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

                    Log.Debug("Feito uploado do MoE");

                    mailSender.Send($"Upload das MoE {platform} para {date:yyyy-MM-dd} Ok",
                                    $"MoE: https://{(platform == Platform.PS ? "ps." : "")}wotclans.com.br/Tanks/MoE");
                }
                else
                {
                    Log.ErrorFormat("Os MoEs para {0:yyyy-MM-dd} retornaram 0 tanques!", date);
                }

                date = date.AddDays(1);
            }

            Log.Debug($"Verificação do MoE completa para {platform}.");
        }
Esempio n. 4
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);
            }
        }
Esempio n. 5
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}");
            }
        }
Esempio n. 6
0
        private static void PutTanksReferencesOnPlataform(Platform platform, DateTime?lastReferences,
                                                          DbProvider provider, MailSender mailSender, string resultDirectory, FtpPutter ftpPutter, int utcShiftToCalculate)
        {
            Debug.Assert(lastReferences != null, nameof(lastReferences) + " != null");
            Log.Debug($"Referências no site {platform}: {lastReferences.Value:yyyy-MM-dd ddd}");
            var cd             = DateTime.UtcNow.AddHours(utcShiftToCalculate);
            var previousMonday = cd.PreviousDayOfWeek(DayOfWeek.Monday);

            Log.Debug($"Segunda-Feira anterior: {previousMonday:yyyy-MM-dd ddd}; Current: {cd:o}");

            if (previousMonday <= lastReferences.Value)
            {
                return;
            }

            // Preciso gerar referências e subir
            var references = provider
                             .GetTanksReferences(platform, previousMonday).ToArray();
            var referencesDir = Path.Combine(resultDirectory, "Tanks");
            var leaders       = new ConcurrentBag <Leader>();

            Parallel.For(0, references.Length, new ParallelOptions {
                MaxDegreeOfParallelism = 4
            }, (i) =>
            {
                var r        = references[i];
                var tankFile = r.Save(referencesDir);

                _ = Task.Run(() =>
                {
                    try
                    {
                        ftpPutter.PutTankReference(tankFile);
                    }
                    catch (Exception ex)
                    {
                        Log.Error($"Error putting tank reference files for {platform} and tank {r.Name}", ex);
                    }
                });

                Log.Info($"Escrito e feito upload da referência {tankFile}");

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

            var json        = JsonConvert.SerializeObject(leaders.ToArray(), Formatting.Indented);
            var leadersFile = Path.Combine(referencesDir, $"{previousMonday:yyyy-MM-dd}.Leaders.json");

            File.WriteAllText(leadersFile, json, Encoding.UTF8);

            _ = Task.Run(() =>
            {
                try
                {
                    ftpPutter.PutTankReference(leadersFile);
                }
                catch (Exception ex)
                {
                    Log.Error($"Error putting leader file for {platform}", ex);
                }
            });

            mailSender.Send($"Upload das Referências {platform} para {previousMonday:yyyy-MM-dd} Ok",
                            $"Leaderboard: https://{(platform == Platform.PS ? "ps." : "")}wotclans.com.br/Leaderboard/All");
        }
Esempio n. 7
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);
            }
        }
Esempio n. 8
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);
            }
        }
Esempio n. 9
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);
            }
        }