Exemple #1
0
        public async Task <CachedWar?> GetActiveClanWarOrDefaultAsync(string tag, CancellationToken?cancellationToken = default)
        {
            string formattedTag = Clash.FormatTag(tag);

            using var scope = Services.CreateScope();

            CacheContext dbContext = scope.ServiceProvider.GetRequiredService <CacheContext>();

            List <CachedWar> cache = await dbContext.Wars
                                     .AsNoTracking()
                                     .Where(i => (i.ClanTag == formattedTag || i.OpponentTag == formattedTag))
                                     .OrderByDescending(w => w.PreparationStartTime)
                                     .ToListAsync(cancellationToken.GetValueOrDefault(_stopRequestedTokenSource.Token))
                                     .ConfigureAwait(false);

            if (cache.Count == 0)
            {
                return(null);
            }

            return(cache.FirstOrDefault(c => c.State == WarState.InWar && c.EndTime > DateTime.UtcNow)
                   ?? cache.FirstOrDefault(c => c.State == WarState.Preparation && c.EndTime > DateTime.UtcNow)
                   ?? cache.First());
        }
Exemple #2
0
        private async Task <CachedClan> PrepareNewCachedClanAsync(string formattedTag, bool downloadWars, bool downloadCwl, bool downloadMembers, CacheContext dbContext)
        {
            CachedClan cachedClan = new CachedClan(formattedTag)
            {
                DownloadCurrentWar = downloadWars,
                DownloadCwl        = downloadCwl,
                DownloadMembers    = downloadMembers
            };

            dbContext.Clans.Add(cachedClan);

            CachedClanWar cachedClanWar = await dbContext.ClanWars
                                          .Where(w => w.Tag == formattedTag)
                                          .FirstOrDefaultAsync(_stopRequestedTokenSource.Token)
                                          .ConfigureAwait(false);

            if (cachedClanWar == null)
            {
                cachedClanWar = new CachedClanWar(formattedTag);

                dbContext.ClanWars.Add(cachedClanWar);
            }

            dbContext.Groups.Add(new CachedClanWarLeagueGroup(formattedTag));

            dbContext.WarLogs.Add(new CachedClanWarLog(formattedTag));

            return(cachedClan);
        }
        public async Task RunAsync(CancellationToken cancellationToken)
        {
            try
            {
                if (_isRunning)
                {
                    return;
                }

                _isRunning = true;

                _stopRequestedTokenSource = new CancellationTokenSource();

                _clansClient.OnLog(this, new LogEventArgs(nameof(RunAsync), LogLevel.Information));

                int id = int.MinValue;

                while (_stopRequestedTokenSource.IsCancellationRequested == false && cancellationToken.IsCancellationRequested == false)
                {
                    if (!_clansClient.DownloadMembers)
                    {
                        await Task.Delay(Configuration.DelayBetweenTasks);

                        continue;
                    }

                    using var scope = Services.CreateScope();

                    CacheContext dbContext = scope.ServiceProvider.GetRequiredService <CacheContext>();

                    List <CachedClan> cachedClans = await dbContext.Clans
                                                    .OrderBy(c => c.Id)
                                                    .Where(c => c.Id > id && c.DownloadMembers)
                                                    .Take(Configuration.ConcurrentClanDownloads)
                                                    .AsNoTracking()
                                                    .ToListAsync(_stopRequestedTokenSource.Token)
                                                    .ConfigureAwait(false);

                    id = cachedClans.Count < Configuration.ConcurrentClanDownloads
                        ? int.MinValue
                        : cachedClans.Max(c => c.Id);

                    foreach (CachedClan cachedClan in cachedClans)
                    {
                        await MonitorMembersAsync(cachedClan);
                    }

                    await Task.Delay(Configuration.DelayBetweenTasks, _stopRequestedTokenSource.Token).ConfigureAwait(false);
                }

                _isRunning = false;
            }
            catch (Exception e)
            {
                _isRunning = false;

                if (_stopRequestedTokenSource.IsCancellationRequested)
                {
                    return;
                }

                _clansClient.OnLog(this, new ExceptionEventArgs(nameof(RunAsync), e));

                if (cancellationToken.IsCancellationRequested == false)
                {
                    _ = RunAsync(cancellationToken);
                }
            }
        }
Exemple #4
0
        public async Task RunAsync(CancellationToken cancellationToken)
        {
            try
            {
                if (_isRunning)
                {
                    return;
                }

                _isRunning = true;

                _stopRequestedTokenSource = new CancellationTokenSource();

                _playersClientBase.OnLog(this, new LogEventArgs(nameof(RunAsync), LogLevel.Information));

                while (cancellationToken.IsCancellationRequested == false && _stopRequestedTokenSource.IsCancellationRequested == false)
                {
                    using var scope = Services.CreateScope();

                    using CacheContext dbContext = scope.ServiceProvider.GetRequiredService <CacheContext>();

                    List <CachedPlayer> cachedPlayers = await dbContext.Players
                                                        .Where(v =>
                                                               v.Download &&
                                                               v.ServerExpiration < DateTime.UtcNow.AddSeconds(-3) &&
                                                               v.LocalExpiration < DateTime.UtcNow)
                                                        .OrderBy(v => v.ServerExpiration)
                                                        .Take(Configuration.ConcurrentPlayerDownloads)
                                                        .ToListAsync(_stopRequestedTokenSource.Token)
                                                        .ConfigureAwait(false);

                    List <Task> tasks = new();

                    for (int i = 0; i < cachedPlayers.Count; i++)
                    {
                        tasks.Add(UpdatePlayerAsync(cachedPlayers[i]));
                    }

                    await Task.WhenAll(tasks).ConfigureAwait(false);

                    await dbContext.SaveChangesAsync(_stopRequestedTokenSource.Token).ConfigureAwait(false);

                    await Task.Delay(Configuration.DelayBetweenTasks, _stopRequestedTokenSource.Token).ConfigureAwait(false);
                }

                _isRunning = false;
            }
            catch (Exception e)
            {
                _isRunning = false;

                if (_stopRequestedTokenSource.IsCancellationRequested)
                {
                    return;
                }

                _playersClientBase.OnLog(this, new ExceptionEventArgs(nameof(RunAsync), e));

                if (cancellationToken.IsCancellationRequested == false)
                {
                    _ = RunAsync(cancellationToken);
                }
            }
        }
Exemple #5
0
        public async Task RunAsync(CancellationToken cancellationToken)
        {
            try
            {
                if (_isRunning)
                {
                    return;
                }

                _isRunning = true;

                _stopRequestedTokenSource = new CancellationTokenSource();

                _clansClient.OnLog(this, new LogEventArgs(nameof(RunAsync), LogLevel.Information));

                while (_stopRequestedTokenSource.IsCancellationRequested == false && cancellationToken.IsCancellationRequested == false)
                {
                    if (_clansClient.DownloadCurrentWars == false)
                    {
                        await Task.Delay(Configuration.DelayBetweenTasks, _stopRequestedTokenSource.Token).ConfigureAwait(false);

                        continue;
                    }

                    using var scope = Services.CreateScope();

                    CacheContext dbContext = scope.ServiceProvider.GetRequiredService <CacheContext>();

                    //List<string> clanWarWithLogStatus = await dbContext.ClanWarWithLogStatus
                    //    .Where(w =>
                    //        w.IsWarLogPublic == true &&
                    //        w.DownloadCurrentWar &&
                    //        w.ServerExpiration < DateTime.UtcNow.AddSeconds(-3) &&
                    //        w.LocalExpiration < DateTime.UtcNow)
                    //    .OrderBy(w => w.ServerExpiration)
                    //    .Take(100)
                    //    .Select(l => l.Tag )
                    //    .ToListAsync()
                    //    .ConfigureAwait(false);

                    List <CachedClanWar> cachedClanWars = await(
                        from cw in dbContext.ClanWars
                        join c in dbContext.Clans on cw.Tag equals c.Tag
                        into cw_c_join
                        from c2 in cw_c_join.DefaultIfEmpty()
                        where
                        c2.IsWarLogPublic == true &&
                        c2.DownloadCurrentWar == true &&
                        cw.ServerExpiration < DateTime.UtcNow.AddSeconds(-3) &&
                        cw.LocalExpiration < DateTime.UtcNow
                        orderby cw.ServerExpiration
                        select cw)
                                                          .Take(Configuration.ConcurrentClanWarDownloads)
                                                          .ToListAsync();

                    List <Task> tasks = new();

                    foreach (CachedClanWar cachedClanWar in cachedClanWars)
                    {
                        tasks.Add(MonitorClanWarAsync(cachedClanWar));
                    }

                    await Task.WhenAll(tasks).ConfigureAwait(false);

                    await dbContext.SaveChangesAsync(_stopRequestedTokenSource.Token).ConfigureAwait(false);

                    await Task.Delay(Configuration.DelayBetweenTasks, _stopRequestedTokenSource.Token).ConfigureAwait(false);
                }

                _isRunning = false;
            }
            catch (Exception e)
            {
                _isRunning = false;

                if (_stopRequestedTokenSource.IsCancellationRequested)
                {
                    return;
                }

                _clansClient.OnLog(this, new ExceptionEventArgs(nameof(RunAsync), e));

                if (cancellationToken.IsCancellationRequested == false)
                {
                    _ = RunAsync(cancellationToken);
                }
            }
        }
Exemple #6
0
        public async Task RunAsync(CancellationToken cancellationToken)
        {
            try
            {
                if (_isRunning)
                {
                    return;
                }

                _isRunning = true;

                _stopRequestedTokenSource = new CancellationTokenSource();

                _clansClient.OnLog(this, new LogEventArgs(nameof(RunAsync), LogLevel.Information));

                while (_stopRequestedTokenSource.IsCancellationRequested == false && cancellationToken.IsCancellationRequested == false)
                {
                    if (_clansClient.DownloadWarLog == false)
                    {
                        await Task.Delay(Configuration.DelayBetweenTasks, _stopRequestedTokenSource.Token).ConfigureAwait(false);

                        continue;
                    }

                    using var scope = Services.CreateScope();

                    CacheContext dbContext = scope.ServiceProvider.GetRequiredService <CacheContext>();

                    //var clanWarLogsWithLogStatus = await dbContext.ClanWarLogWithLogStatus
                    //    .Where(w =>
                    //        w.IsWarLogPublic &&
                    //        w.DownloadCurrentWar &&
                    //        w.ServerExpiration < DateTime.UtcNow.AddSeconds(-3) &&
                    //        w.LocalExpiration < DateTime.UtcNow)
                    //    .OrderBy(w => w.ServerExpiration)
                    //    .Take(1000)
                    //    .Select(l => l.Tag)
                    //    .ToListAsync()
                    //    .ConfigureAwait(false);

                    List <CachedClanWarLog> cachedLogs = await(
                        from l in dbContext.WarLogs
                        join c in dbContext.Clans on l.Tag equals c.Tag
                        where c.IsWarLogPublic == true && c.DownloadCurrentWar && l.ServerExpiration < DateTime.UtcNow.AddSeconds(-3) && l.LocalExpiration < DateTime.UtcNow
                        orderby l.ServerExpiration
                        select l)
                                                         .Take(Configuration.ConcurrentWarLogDownloads)
                                                         .ToListAsync()
                                                         .ConfigureAwait(false);

                    List <Task> tasks = new();

                    foreach (CachedClanWarLog cachedLog in cachedLogs)
                    {
                        tasks.Add(MonitorLogAsync(cachedLog));
                    }

                    await Task.WhenAll(tasks).ConfigureAwait(false);

                    await dbContext.SaveChangesAsync(_stopRequestedTokenSource.Token).ConfigureAwait(false);

                    //for (int i = 0; i < clanWarLogsWithLogStatus.Count; i++)
                    //    await MonitorLogAsync(clanWarLogsWithLogStatus[i]);

                    await Task.Delay(Configuration.DelayBetweenTasks, _stopRequestedTokenSource.Token).ConfigureAwait(false);
                }

                _isRunning = false;
            }
            catch (Exception e)
            {
                _isRunning = false;

                if (_stopRequestedTokenSource.IsCancellationRequested)
                {
                    return;
                }

                _clansClient.OnLog(this, new ExceptionEventArgs(nameof(RunAsync), e));

                if (cancellationToken.IsCancellationRequested == false)
                {
                    _ = RunAsync(cancellationToken);
                }
            }
        }
Exemple #7
0
        public async Task RunAsync(CancellationToken cancellationToken)
        {
            try
            {
                if (_isRunning)
                {
                    return;
                }

                _isRunning = true;

                _stopRequestedTokenSource = new CancellationTokenSource();

                _clansClient.OnLog(this, new LogEventArgs(nameof(RunAsync), LogLevel.Information));

                while (_stopRequestedTokenSource.IsCancellationRequested == false && cancellationToken.IsCancellationRequested == false)
                {
                    using var scope = Services.CreateScope();

                    CacheContext dbContext = scope.ServiceProvider.GetRequiredService <CacheContext>();

                    List <CachedClan> cachedClans = await dbContext.Clans
                                                    .Where(w =>
                                                           w.ServerExpiration < DateTime.UtcNow.AddSeconds(-3) &&
                                                           w.LocalExpiration < DateTime.UtcNow)
                                                    .OrderBy(w => w.ServerExpiration)
                                                    .Take(Configuration.ConcurrentClanDownloads)
                                                    .ToListAsync(_stopRequestedTokenSource.Token)
                                                    .ConfigureAwait(false);

                    List <Task> tasks = new();

                    foreach (CachedClan cachedClan in cachedClans)
                    {
                        tasks.Add(MonitorClanAsync(cachedClan));
                    }

                    await Task.WhenAll(tasks).ConfigureAwait(false);

                    await dbContext.SaveChangesAsync(_stopRequestedTokenSource.Token).ConfigureAwait(false);

                    if (_deletedUnmonitoredPlayers < DateTime.UtcNow.AddMinutes(-10))
                    {
                        _deletedUnmonitoredPlayers = DateTime.UtcNow;

                        tasks = new List <Task>
                        {
                            DeleteUnmonitoredPlayersNotInAClan(),

                            DeletePlayersInClansNotMonitored()
                        };

                        await Task.WhenAll(tasks);
                    }

                    await Task.Delay(Configuration.DelayBetweenTasks, _stopRequestedTokenSource.Token).ConfigureAwait(false);
                }

                _isRunning = false;
            }
            catch (Exception e)
            {
                _isRunning = false;

                if (_stopRequestedTokenSource.IsCancellationRequested)
                {
                    return;
                }

                _clansClient.OnLog(this, new ExceptionEventArgs(nameof(RunAsync), e));

                if (cancellationToken.IsCancellationRequested == false)
                {
                    _ = RunAsync(cancellationToken);
                }
            }
        }
Exemple #8
0
        public async Task RunAsync(CancellationToken cancellationToken)
        {
            try
            {
                if (_isRunning)
                {
                    return;
                }

                _isRunning = true;

                _stopRequestedTokenSource = new CancellationTokenSource();

                _clansClient.OnLog(this, new LogEventArgs(nameof(RunAsync), LogLevel.Information));

                while (_stopRequestedTokenSource.IsCancellationRequested == false && cancellationToken.IsCancellationRequested == false)
                {
                    if (_clansClient.DownloadCurrentWars == false && _clansClient.DownloadCwl == false)
                    {
                        await Task.Delay(Configuration.DelayBetweenTasks, _stopRequestedTokenSource.Token).ConfigureAwait(false);

                        continue;
                    }

                    using var scope = Services.CreateScope();

                    CacheContext dbContext = scope.ServiceProvider.GetRequiredService <CacheContext>();

                    var wars = await dbContext.Wars
                               .Where(w =>
                                      w.IsFinal == false &&
                                      w.ServerExpiration < DateTime.UtcNow.AddSeconds(-3) &&
                                      w.LocalExpiration < DateTime.UtcNow //&&
                                                                          //w.State < WarState.WarEnded && //todo is there an index on state?
                                                                          //w.EndTime.AddDays(8) > DateTime.UtcNow //todo does this require a new column and a new index?
                                                                          //todo w.StartTime < DateTime.UtcNow.AddHours(-1))  //todo preparation start time < now
                                      )
                               .OrderBy(w => w.ServerExpiration)
                               .ToListAsync()
                               .ConfigureAwait(false);

                    for (int i = 0; i < wars.Count; i++)
                    {
                        await MonitorWarAsync(wars[i]).ConfigureAwait(false);
                    }

                    await dbContext.SaveChangesAsync(_stopRequestedTokenSource.Token).ConfigureAwait(false);

                    await Task.Delay(Configuration.DelayBetweenTasks, _stopRequestedTokenSource.Token).ConfigureAwait(false);
                }

                _isRunning = false;
            }
            catch (Exception e)
            {
                _isRunning = false;

                if (_stopRequestedTokenSource.IsCancellationRequested)
                {
                    return;
                }

                _clansClient.OnLog(this, new ExceptionEventArgs(nameof(RunAsync), e));

                if (cancellationToken.IsCancellationRequested == false)
                {
                    _ = RunAsync(cancellationToken);
                }
            }
        }
Exemple #9
0
        private async Task MonitorWarAsync(CachedWar cached)
        {
            if (_stopRequestedTokenSource.IsCancellationRequested ||
                _clansClient.UpdatingWar.TryAdd(cached, new byte()) == false)
            {
                return;
            }

            try
            {
                using var scope = Services.CreateScope();

                CacheContext dbContext = scope.ServiceProvider.GetRequiredService <CacheContext>();

                List <CachedClanWar>?cachedClanWars = null;

                if (cached.WarTag == null)
                {
                    cachedClanWars = await dbContext.ClanWars
                                     .AsNoTracking()
                                     .Where(c => cached.ClanTags.Contains(c.Tag))
                                     .OrderByDescending(c => c.ServerExpiration)
                                     .ToListAsync(_stopRequestedTokenSource.Token)
                                     .ConfigureAwait(false);

                    if (cachedClanWars.Count == 2 && cachedClanWars.All(c => c.PreparationStartTime > cached.PreparationStartTime) ||
                        cached.EndTime.AddDays(8) < DateTime.UtcNow)
                    {
                        cached.IsFinal = true;

                        return;
                    }

                    CachedClanWar?cachedClanWar = cachedClanWars
                                                  .OrderByDescending(c => c.ServerExpiration)
                                                  .FirstOrDefault(c => c.PreparationStartTime == cached.PreparationStartTime);

                    if (cached.Data != null && cachedClanWar?.Data != null && _clansClient.HasUpdated(cached, cachedClanWar))
                    {
                        _clansClient.OnClanWarUpdated(cached.Data, cachedClanWar.Data);
                    }

                    if (cachedClanWar != null)
                    {
                        cached.UpdateFrom(cachedClanWar);
                    }
                }
                else
                {
                    CachedWar?fetched = await CachedWar
                                        .FromClanWarLeagueWarResponseAsync(
                        cached.WarTag, cached.Season.Value, _clansClient, _clansApi, _stopRequestedTokenSource.Token)
                                        .ConfigureAwait(false);

                    if (cached.Data != null &&
                        fetched.Data != null &&
                        cached.Season == fetched.Season &&
                        _clansClient.HasUpdated(cached, fetched))
                    {
                        _clansClient.OnClanWarUpdated(cached.Data, fetched.Data);
                    }

                    cached.UpdateFrom(fetched);
                }

                cached.IsFinal = cached.State == WarState.WarEnded;

                SendWarAnnouncements(cached, cachedClanWars);
            }
            finally
            {
                _clansClient.UpdatingWar.TryRemove(cached, out _);
            }
        }
Exemple #10
0
        public async Task RunAsync(CancellationToken cancellationToken)
        {
            try
            {
                if (_isRunning)
                {
                    return;
                }

                _isRunning = true;

                _stopRequestedTokenSource = new CancellationTokenSource();

                _clansClient.OnLog(this, new LogEventArgs(nameof(RunAsync), LogLevel.Information));

                int id = int.MinValue;

                while (_stopRequestedTokenSource.IsCancellationRequested == false && cancellationToken.IsCancellationRequested == false)
                {
                    if (_clansClient.DownloadCwl == false)
                    {
                        await Task.Delay(Configuration.DelayBetweenTasks, _stopRequestedTokenSource.Token).ConfigureAwait(false);

                        continue;
                    }

                    using var scope = Services.CreateScope();

                    CacheContext dbContext = scope.ServiceProvider.GetRequiredService <CacheContext>();

                    //var cachedWarLogs = await dbContext.ClanWarLeagueGroupWithStatus
                    //    .Where(w =>
                    //        w.DownloadCwl == true &&
                    //        w.ServerExpiration < DateTime.UtcNow.AddSeconds(-3) &&
                    //        w.LocalExpiration < DateTime.UtcNow)
                    //    .OrderBy(w => w.ServerExpiration)
                    //    .Take(10)
                    //    .ToListAsync()
                    //    .ConfigureAwait(false);

                    List <CachedClanWarLeagueGroup> cachedGroup = await(
                        from g in dbContext.Groups
                        join c in dbContext.Clans on g.Tag equals c.Tag
                        where c.DownloadCwl && g.ServerExpiration < DateTime.UtcNow.AddSeconds(-3) && g.LocalExpiration <DateTime.UtcNow && g.Id> id
                        orderby g.Id
                        select g)
                                                                  .Take(Configuration.ConcurrentCwlDownloads)
                                                                  .ToListAsync()
                                                                  .ConfigureAwait(false);

                    id = cachedGroup.Count == Configuration.ConcurrentClanDownloads
                        ? cachedGroup.Max(g => g.Id)
                        : int.MinValue;

                    List <Task> tasks = new();

                    foreach (CachedClanWarLeagueGroup group in cachedGroup)
                    {
                        tasks.Add(MonitorCwlAsync(group, dbContext));
                    }

                    await Task.WhenAll(tasks).ConfigureAwait(false);

                    await dbContext.SaveChangesAsync(_stopRequestedTokenSource.Token).ConfigureAwait(false);

                    await Task.Delay(Configuration.DelayBetweenTasks, _stopRequestedTokenSource.Token).ConfigureAwait(false);
                }

                _isRunning = false;
            }
            catch (Exception e)
            {
                _isRunning = false;

                if (_stopRequestedTokenSource.IsCancellationRequested)
                {
                    return;
                }

                _clansClient.OnLog(this, new ExceptionEventArgs(nameof(RunAsync), e));

                if (cancellationToken.IsCancellationRequested == false)
                {
                    _ = RunAsync(cancellationToken);
                }
            }
        }
Exemple #11
0
        private async Task MonitorCwlAsync(CachedClanWarLeagueGroup cached, CacheContext dbContext)
        {
            if (_stopRequestedTokenSource.IsCancellationRequested ||
                _updatingGroup.TryAdd(cached.Tag, new byte()) == false)
            {
                return;
            }

            try
            {
                CachedClanWarLeagueGroup?fetched = await CachedClanWarLeagueGroup
                                                   .FromClanWarLeagueGroupResponseAsync(cached.Tag, _clansClient, _clansApi, _stopRequestedTokenSource.Token)
                                                   .ConfigureAwait(false);

                if (fetched.Data != null && _clansClient.HasUpdated(cached, fetched))
                {
                    _clansClient.OnClanWarLeagueGroupUpdated(cached.Data, fetched.Data);
                }

                cached.UpdateFrom(fetched);

                List <Task> tasks = new List <Task>();

                HashSet <string> downloadWarTags = new HashSet <string>();

                if (cached.Data == null || cached.Season.Value.Month < DateTime.Now.Month)
                {
                    return;
                }

                try
                {
                    foreach (var round in cached.Data.Rounds)
                    {
                        foreach (string warTag in round.WarTags.Where(w => w != "#0"))
                        {
                            if (_updatingWarTags.TryAdd(warTag, new byte()))
                            {
                                downloadWarTags.Add(warTag);

                                tasks.Add(ReturnNewWarOrDefaultAsync(cached.Tag, cached.Season.Value, warTag));
                            }
                        }
                    }

                    await Task.WhenAll(tasks).ConfigureAwait(false);

                    foreach (Task <CachedWar?> cachedWarTask in tasks)
                    {
                        if (cachedWarTask.IsCompletedSuccessfully && cachedWarTask.Result is CachedWar cachedWar && cachedWar.Data != null)
                        {
                            dbContext.Wars.Add(cachedWar);
                            _clansClient.OnClanWarAdded(cachedWar.Data);
                        }
                    }
                }
                finally
                {
                    foreach (string warTag in downloadWarTags)
                    {
                        _updatingWarTags.TryRemove(warTag, out _);
                    }
                }
            }
            catch (Exception e)
            {
                _clansClient.OnLog(this, new LogEventArgs(nameof(MonitorCwlAsync), LogLevel.Debug, $"Error updating group:{cached.Tag};\n{e.Message};\n{e.InnerException?.Message}"));
            }
            finally
            {
                _updatingGroup.TryRemove(cached.Tag, out _);
            }
        }