public async override Task <ActionResult> Index(ContentModel contentModel)
        {
            if (contentModel is null)
            {
                throw new ArgumentNullException(nameof(contentModel));
            }

            var team = await _teamDataSource.ReadTeamByRoute(Request.RawUrl, true).ConfigureAwait(false);

            if (team == null)
            {
                return(new HttpNotFoundResult());
            }
            else
            {
                var filter = _matchFilterFactory.MatchesForTeams(new List <Guid> {
                    team.TeamId.Value
                });
                var model = new TeamViewModel(contentModel.Content, Services?.UserService)
                {
                    Team = team,
                    DefaultMatchFilter = filter.filter,
                    Matches            = new MatchListingViewModel(contentModel.Content, Services?.UserService)
                    {
                        DateTimeFormatter = _dateFormatter
                    },
                };
                model.AppliedMatchFilter = _matchFilterQueryStringParser.ParseQueryString(model.DefaultMatchFilter, HttpUtility.ParseQueryString(Request.Url.Query));
                model.Matches.Matches    = await _matchDataSource.ReadMatchListings(model.AppliedMatchFilter, filter.sortOrder).ConfigureAwait(false);

                model.IsAuthorized       = _authorizationPolicy.IsAuthorized(model.Team);
                model.IsInACurrentLeague = _createMatchSeasonSelector.SelectPossibleSeasons(model.Team.Seasons, MatchType.LeagueMatch).Any();
                model.IsInACurrentKnockoutCompetition = _createMatchSeasonSelector.SelectPossibleSeasons(model.Team.Seasons, MatchType.KnockoutMatch).Any();

                var userFilter = _matchFilterHumanizer.MatchingFilter(model.AppliedMatchFilter);
                if (!string.IsNullOrWhiteSpace(userFilter))
                {
                    model.FilterDescription = _matchFilterHumanizer.MatchesAndTournaments(model.AppliedMatchFilter) + userFilter;
                }
                model.Metadata.PageTitle = $"{_matchFilterHumanizer.MatchesAndTournaments(model.AppliedMatchFilter)} for {model.Team.TeamName} stoolball team{userFilter}";

                model.Breadcrumbs.Add(new Breadcrumb {
                    Name = Constants.Pages.Teams, Url = new Uri(Constants.Pages.TeamsUrl, UriKind.Relative)
                });
                if (model.Team.Club != null)
                {
                    model.Breadcrumbs.Add(new Breadcrumb {
                        Name = model.Team.Club.ClubName, Url = new Uri(model.Team.Club.ClubRoute, UriKind.Relative)
                    });
                }

                return(CurrentTemplate(model));
            }
        }
        public async Task <ActionResult> DeleteTournament([Bind(Prefix = "ConfirmDeleteRequest", Include = "RequiredText,ConfirmationText")] MatchingTextConfirmation postedModel)
        {
            if (postedModel is null)
            {
                throw new ArgumentNullException(nameof(postedModel));
            }

            var model = new DeleteTournamentViewModel(CurrentPage, Services.UserService)
            {
                Tournament        = await _tournamentDataSource.ReadTournamentByRoute(Request.RawUrl).ConfigureAwait(false),
                DateTimeFormatter = _dateTimeFormatter
            };

            model.IsAuthorized = _authorizationPolicy.IsAuthorized(model.Tournament);

            if (model.IsAuthorized[AuthorizedAction.DeleteTournament] && ModelState.IsValid)
            {
                var currentMember = Members.GetCurrentMember();
                await _tournamentRepository.DeleteTournament(model.Tournament, currentMember.Key, currentMember.Name).ConfigureAwait(false);

                await _cacheClearer.ClearCacheFor(model.Tournament).ConfigureAwait(false);

                model.Deleted = true;
            }
            else
            {
                model.TotalComments = await _commentsDataSource.ReadTotalComments(model.Tournament.TournamentId.Value).ConfigureAwait(false);

                model.Matches = new MatchListingViewModel(CurrentPage, Services?.UserService)
                {
                    Matches = await _matchListingDataSource.ReadMatchListings(new MatchFilter
                    {
                        TournamentId             = model.Tournament.TournamentId,
                        IncludeTournamentMatches = true,
                        IncludeTournaments       = false
                    }, MatchSortOrder.MatchDateEarliestFirst).ConfigureAwait(false)
                };
            }

            model.Metadata.PageTitle = "Delete " + model.Tournament.TournamentFullNameAndPlayerType(x => _dateTimeFormatter.FormatDate(x, false, false, false));

            model.Breadcrumbs.Add(new Breadcrumb {
                Name = Constants.Pages.Tournaments, Url = new Uri(Constants.Pages.TournamentsUrl, UriKind.Relative)
            });
            if (!model.Deleted)
            {
                model.Breadcrumbs.Add(new Breadcrumb {
                    Name = model.Tournament.TournamentName, Url = new Uri(model.Tournament.TournamentRoute, UriKind.Relative)
                });
            }

            return(View("DeleteTournament", model));
        }
        public async override Task <ActionResult> Index(ContentModel contentModel)
        {
            if (contentModel is null)
            {
                throw new ArgumentNullException(nameof(contentModel));
            }

            var model = new SeasonViewModel(contentModel.Content, Services?.UserService)
            {
                Season = await _seasonDataSource.ReadSeasonByRoute(Request.RawUrl, true).ConfigureAwait(false)
            };

            if (model.Season == null || (!model.Season.MatchTypes.Contains(MatchType.LeagueMatch) &&
                                         !model.Season.MatchTypes.Contains(MatchType.KnockoutMatch) &&
                                         !model.Season.MatchTypes.Contains(MatchType.FriendlyMatch) &&
                                         string.IsNullOrEmpty(model.Season.Results)))
            {
                return(new HttpNotFoundResult());
            }
            else
            {
                model.Matches = new MatchListingViewModel(contentModel.Content, Services?.UserService)
                {
                    Matches = await _matchDataSource.ReadMatchListings(new MatchFilter
                    {
                        SeasonIds = new List <Guid> {
                            model.Season.SeasonId.Value
                        },
                        IncludeTournaments = false
                    }, MatchSortOrder.MatchDateEarliestFirst).ConfigureAwait(false),
                    DateTimeFormatter = _dateTimeFormatter
                };
                model.Season.PointsRules.AddRange(await _seasonDataSource.ReadPointsRules(model.Season.SeasonId.Value).ConfigureAwait(false));
                model.Season.PointsAdjustments.AddRange(await _seasonDataSource.ReadPointsAdjustments(model.Season.SeasonId.Value).ConfigureAwait(false));

                model.Season.Results = _emailProtector.ProtectEmailAddresses(model.Season.Results, User.Identity.IsAuthenticated);

                model.IsAuthorized = _authorizationPolicy.IsAuthorized(model.Season.Competition);

                var the = model.Season.Competition.CompetitionName.StartsWith("THE ", StringComparison.OrdinalIgnoreCase);
                model.Metadata.PageTitle   = $"Results table for {(the ? string.Empty : "the ")}{model.Season.SeasonFullNameAndPlayerType()}";
                model.Metadata.Description = model.Season.Description();

                model.Breadcrumbs.Add(new Breadcrumb {
                    Name = Constants.Pages.Competitions, Url = new Uri(Constants.Pages.CompetitionsUrl, UriKind.Relative)
                });
                model.Breadcrumbs.Add(new Breadcrumb {
                    Name = model.Season.Competition.CompetitionName, Url = new Uri(model.Season.Competition.CompetitionRoute, UriKind.Relative)
                });

                return(CurrentTemplate(model));
            }
        }
Beispiel #4
0
        public async override Task <ActionResult> Index(ContentModel contentModel)
        {
            if (contentModel is null)
            {
                throw new ArgumentNullException(nameof(contentModel));
            }

            var model = new TournamentViewModel(contentModel.Content, Services?.UserService)
            {
                Tournament        = await _tournamentDataSource.ReadTournamentByRoute(Request.Url.AbsolutePath).ConfigureAwait(false),
                DateTimeFormatter = _dateFormatter
            };

            if (model.Tournament == null)
            {
                return(new HttpNotFoundResult());
            }
            else
            {
                model.IsAuthorized = _authorizationPolicy.IsAuthorized(model.Tournament);

                model.Tournament.Comments = await _commentsDataSource.ReadComments(model.Tournament.TournamentId.Value).ConfigureAwait(false);

                foreach (var comment in model.Tournament.Comments)
                {
                    comment.Comment = _emailProtector.ProtectEmailAddresses(comment.Comment, User.Identity.IsAuthenticated);
                    comment.Comment = _badLanguageFilter.Filter(comment.Comment);
                }

                var filter = _matchFilterFactory.MatchesForTournament(model.Tournament.TournamentId.Value);
                model.Matches = new MatchListingViewModel(contentModel.Content, Services?.UserService)
                {
                    Matches            = await _matchDataSource.ReadMatchListings(filter.filter, filter.sortOrder).ConfigureAwait(false),
                    ShowMatchDate      = false,
                    HighlightNextMatch = false,
                    DateTimeFormatter  = _dateFormatter
                };

                model.Metadata.PageTitle   = model.Tournament.TournamentFullNameAndPlayerType(x => _dateFormatter.FormatDate(x, false, false, false));
                model.Metadata.Description = model.Tournament.Description();

                model.Tournament.TournamentNotes = _emailProtector.ProtectEmailAddresses(model.Tournament.TournamentNotes, User.Identity.IsAuthenticated);

                model.Breadcrumbs.Add(new Breadcrumb {
                    Name = Constants.Pages.Tournaments, Url = new Uri(Constants.Pages.TournamentsUrl, UriKind.Relative)
                });

                return(CurrentTemplate(model));
            }
        }
Beispiel #5
0
        public async override Task <ActionResult> Index(ContentModel contentModel)
        {
            if (contentModel is null)
            {
                throw new ArgumentNullException(nameof(contentModel));
            }

            var club = await _clubDataSource.ReadClubByRoute(Request.RawUrl).ConfigureAwait(false);

            if (club == null)
            {
                return(new HttpNotFoundResult());
            }
            else
            {
                var filter = _matchFilterFactory.MatchesForTeams(club.Teams.Select(team => team.TeamId.Value).ToList());
                var model  = new ClubViewModel(contentModel.Content, Services?.UserService)
                {
                    Club = club,
                    DefaultMatchFilter = filter.filter,
                    Matches            = new MatchListingViewModel(contentModel.Content, Services?.UserService)
                    {
                        DateTimeFormatter = _dateFormatter
                    }
                };
                model.AppliedMatchFilter = _matchFilterQueryStringParser.ParseQueryString(model.DefaultMatchFilter, HttpUtility.ParseQueryString(Request.Url.Query));

                // Only get matches if there are teams, otherwise matches for all teams will be returned
                if (model.Club.Teams.Count > 0)
                {
                    model.Matches.Matches = await _matchDataSource.ReadMatchListings(model.AppliedMatchFilter, filter.sortOrder).ConfigureAwait(false);
                }

                model.IsAuthorized = _authorizationPolicy.IsAuthorized(model.Club);

                var userFilter = _matchFilterHumanizer.MatchingFilter(model.AppliedMatchFilter);
                if (!string.IsNullOrWhiteSpace(userFilter))
                {
                    model.FilterDescription = _matchFilterHumanizer.MatchesAndTournaments(model.AppliedMatchFilter) + userFilter;
                }
                model.Metadata.PageTitle = $"{_matchFilterHumanizer.MatchesAndTournaments(model.AppliedMatchFilter)} for {model.Club.ClubName}{userFilter}";

                model.Breadcrumbs.Add(new Breadcrumb {
                    Name = Constants.Pages.Teams, Url = new Uri(Constants.Pages.TeamsUrl, UriKind.Relative)
                });

                return(CurrentTemplate(model));
            }
        }
        public async override Task <ActionResult> Index(ContentModel contentModel)
        {
            if (contentModel is null)
            {
                throw new System.ArgumentNullException(nameof(contentModel));
            }

            var model = new DeleteTournamentViewModel(contentModel.Content, Services?.UserService)
            {
                Tournament        = await _tournamentDataSource.ReadTournamentByRoute(Request.RawUrl).ConfigureAwait(false),
                DateTimeFormatter = _dateFormatter
            };

            if (model.Tournament == null)
            {
                return(new HttpNotFoundResult());
            }
            else
            {
                model.TotalComments = await _tournamentCommentsDataSource.ReadTotalComments(model.Tournament.TournamentId.Value).ConfigureAwait(false);

                model.Matches = new MatchListingViewModel(contentModel.Content, Services?.UserService)
                {
                    Matches = await _matchDataSource.ReadMatchListings(new MatchFilter
                    {
                        TournamentId             = model.Tournament.TournamentId,
                        IncludeTournamentMatches = true,
                        IncludeTournaments       = false
                    }, MatchSortOrder.MatchDateEarliestFirst).ConfigureAwait(false)
                };

                model.ConfirmDeleteRequest.RequiredText = model.Tournament.TournamentName;

                model.IsAuthorized = _authorizationPolicy.IsAuthorized(model.Tournament);

                model.Metadata.PageTitle = "Delete " + model.Tournament.TournamentFullNameAndPlayerType(x => _dateFormatter.FormatDate(x, false, false, false));

                model.Breadcrumbs.Add(new Breadcrumb {
                    Name = Constants.Pages.Tournaments, Url = new Uri(Constants.Pages.TournamentsUrl, UriKind.Relative)
                });
                model.Breadcrumbs.Add(new Breadcrumb {
                    Name = model.Tournament.TournamentName, Url = new Uri(model.Tournament.TournamentRoute, UriKind.Relative)
                });

                return(CurrentTemplate(model));
            }
        }
        public async override Task <ActionResult> Index(ContentModel contentModel)
        {
            if (contentModel is null)
            {
                throw new ArgumentNullException(nameof(contentModel));
            }

            var model = new EditTournamentViewModel(contentModel.Content, Services?.UserService)
            {
                Tournament    = await _tournamentDataSource.ReadTournamentByRoute(Request.RawUrl).ConfigureAwait(false),
                DateFormatter = _dateFormatter,
                UrlReferrer   = Request.UrlReferrer
            };

            if (model.Tournament == null)
            {
                return(new HttpNotFoundResult());
            }
            else
            {
                model.IsAuthorized = _authorizationPolicy.IsAuthorized(model.Tournament);

                model.Tournament.Matches = (await _matchDataSource.ReadMatchListings(new MatchFilter
                {
                    TournamentId = model.Tournament.TournamentId,
                    IncludeTournamentMatches = true,
                    IncludeTournaments = false
                }, MatchSortOrder.MatchDateEarliestFirst).ConfigureAwait(false))
                                           .Select(x => new MatchInTournament
                {
                    MatchId   = x.MatchId,
                    MatchName = x.MatchName
                }).ToList();

                model.Metadata.PageTitle = "Matches in the " + model.Tournament.TournamentFullName(x => _dateFormatter.FormatDate(x, false, false, false));

                model.Breadcrumbs.Add(new Breadcrumb {
                    Name = Constants.Pages.Tournaments, Url = new Uri(Constants.Pages.TournamentsUrl, UriKind.Relative)
                });
                model.Breadcrumbs.Add(new Breadcrumb {
                    Name = model.Tournament.TournamentName, Url = new Uri(model.Tournament.TournamentRoute, UriKind.Relative)
                });

                return(CurrentTemplate(model));
            }
        }
        public async override Task <ActionResult> Index(ContentModel contentModel)
        {
            if (contentModel is null)
            {
                throw new ArgumentNullException(nameof(contentModel));
            }

            var model = new TeamViewModel(contentModel.Content, Services?.UserService)
            {
                Team = await _teamDataSource.ReadTeamByRoute(Request.RawUrl, true).ConfigureAwait(false)
            };

            if (model.Team == null)
            {
                return(new HttpNotFoundResult());
            }

            model.IsAuthorized = _authorizationPolicy.IsAuthorized(model.Team);

            model.Matches = new MatchListingViewModel(contentModel.Content, Services?.UserService)
            {
                Matches = await _matchDataSource.ReadMatchListings(new MatchFilter
                {
                    TeamIds = new List <Guid> {
                        model.Team.TeamId.Value
                    },
                    IncludeMatches = false
                }, MatchSortOrder.MatchDateEarliestFirst).ConfigureAwait(false),
                HighlightNextMatch = false,
                DateTimeFormatter  = _dateFormatter
            };

            var match = model.Matches.Matches.First();

            model.Metadata.PageTitle = model.Team.TeamNameAndPlayerType() + ", " + _dateFormatter.FormatDate(match.StartTime, false, false);

            model.Team.Cost                 = _emailProtector.ProtectEmailAddresses(model.Team.Cost, User.Identity.IsAuthenticated);
            model.Team.Introduction         = _emailProtector.ProtectEmailAddresses(model.Team.Introduction, User.Identity.IsAuthenticated);
            model.Team.PublicContactDetails = _emailProtector.ProtectEmailAddresses(model.Team.PublicContactDetails, User.Identity.IsAuthenticated);

            model.Breadcrumbs.Add(new Breadcrumb {
                Name = match.MatchName, Url = new Uri(match.MatchRoute, UriKind.Relative)
            });

            return(CurrentTemplate(model));
        }
        public async override Task <ActionResult> Index(ContentModel contentModel)
        {
            if (contentModel is null)
            {
                throw new ArgumentNullException(nameof(contentModel));
            }

            var location = await _matchLocationDataSource.ReadMatchLocationByRoute(Request.RawUrl, false).ConfigureAwait(false);

            if (location == null)
            {
                return(new HttpNotFoundResult());
            }
            else
            {
                var filter = _matchFilterFactory.MatchesForMatchLocation(location.MatchLocationId.Value);
                var model  = new MatchLocationViewModel(contentModel.Content, Services?.UserService)
                {
                    MatchLocation      = location,
                    DefaultMatchFilter = filter.filter,
                    Matches            = new MatchListingViewModel(contentModel.Content, Services?.UserService)
                    {
                        DateTimeFormatter = _dateFormatter
                    },
                };
                model.AppliedMatchFilter = _matchFilterQueryStringParser.ParseQueryString(model.DefaultMatchFilter, HttpUtility.ParseQueryString(Request.Url.Query));
                model.Matches.Matches    = await _matchDataSource.ReadMatchListings(model.AppliedMatchFilter, filter.sortOrder).ConfigureAwait(false);

                model.IsAuthorized = _authorizationPolicy.IsAuthorized(model.MatchLocation);

                var userFilter = _matchFilterHumanizer.MatchingFilter(model.AppliedMatchFilter);
                if (!string.IsNullOrWhiteSpace(userFilter))
                {
                    model.FilterDescription = _matchFilterHumanizer.MatchesAndTournaments(model.AppliedMatchFilter) + userFilter;
                }
                model.Metadata.PageTitle = $"{_matchFilterHumanizer.MatchesAndTournaments(model.AppliedMatchFilter)} at {model.MatchLocation.NameAndLocalityOrTownIfDifferent()}{userFilter}";

                model.Breadcrumbs.Add(new Breadcrumb {
                    Name = Constants.Pages.MatchLocations, Url = new Uri(Constants.Pages.MatchLocationsUrl, UriKind.Relative)
                });

                return(CurrentTemplate(model));
            }
        }
        public async override Task <ActionResult> Index(ContentModel contentModel)
        {
            if (contentModel is null)
            {
                throw new ArgumentNullException(nameof(contentModel));
            }

            var season = await _seasonDataSource.ReadSeasonByRoute(Request.RawUrl, false).ConfigureAwait(false);

            if (season == null)
            {
                return(new HttpNotFoundResult());
            }
            else
            {
                var filter = _matchFilterFactory.MatchesForSeason(season.SeasonId.Value);
                var model  = new SeasonViewModel(contentModel.Content, Services?.UserService)
                {
                    Season  = season,
                    Matches = new MatchListingViewModel(contentModel.Content, Services?.UserService)
                    {
                        Matches           = await _matchDataSource.ReadMatchListings(filter.filter, filter.sortOrder).ConfigureAwait(false),
                        DateTimeFormatter = _dateFormatter
                    },
                };
                if (model.Season.MatchTypes.Contains(MatchType.LeagueMatch) || model.Season.MatchTypes.Contains(MatchType.KnockoutMatch))
                {
                    model.Matches.MatchTypesToLabel.Add(MatchType.FriendlyMatch);
                }

                model.IsAuthorized = _authorizationPolicy.IsAuthorized(model.Season.Competition);

                model.Metadata.PageTitle = $"Matches and tournaments in {model.Season.SeasonFullNameAndPlayerType()}";

                model.Breadcrumbs.Add(new Breadcrumb {
                    Name = Constants.Pages.Competitions, Url = new Uri(Constants.Pages.CompetitionsUrl, UriKind.Relative)
                });
                model.Breadcrumbs.Add(new Breadcrumb {
                    Name = model.Season.Competition.CompetitionName, Url = new Uri(model.Season.Competition.CompetitionRoute, UriKind.Relative)
                });

                return(CurrentTemplate(model));
            }
        }
        public async override Task <ActionResult> Index(ContentModel contentModel)
        {
            if (contentModel is null)
            {
                throw new ArgumentNullException(nameof(contentModel));
            }

            var model = new TeamViewModel(contentModel.Content, Services?.UserService)
            {
                Team = await _teamDataSource.ReadTeamByRoute(Request.RawUrl, true).ConfigureAwait(false)
            };


            if (model.Team == null)
            {
                return(new HttpNotFoundResult());
            }
            else
            {
                model.IsAuthorized = _authorizationPolicy.IsAuthorized(model.Team);

                model.Matches = new MatchListingViewModel(contentModel.Content, Services?.UserService)
                {
                    Matches = await _matchDataSource.ReadMatchListings(new MatchFilter
                    {
                        TeamIds = new List <Guid> {
                            model.Team.TeamId.Value
                        },
                        IncludeMatches = false
                    }, MatchSortOrder.MatchDateEarliestFirst).ConfigureAwait(false),
                    DateTimeFormatter = _dateFormatter
                };

                var match = model.Matches.Matches.First();
                model.Metadata.PageTitle = $"Edit {model.Team.TeamName}, {_dateFormatter.FormatDate(match.StartTime, false, false)}";

                model.Breadcrumbs.Add(new Breadcrumb {
                    Name = match.MatchName, Url = new Uri(match.MatchRoute, UriKind.Relative)
                });

                return(CurrentTemplate(model));
            }
        }
        public async override Task <bool> PerformRunAsync(CancellationToken cancellationToken)
        {
            if (cancellationToken.IsCancellationRequested)
            {
                _logger.Warn(GetType(), "Background task cancellation requested in {Type:l}.", GetType());
                return(false);
            }

            _logger.Info <OnlySportCsvExportTask>(nameof(OnlySportCsvExportTask) + " running");

            var matches = (await _matchDataSource.ReadMatchListings(new MatchFilter
            {
                FromDate = DateTimeOffset.UtcNow
            }, MatchSortOrder.MatchDateEarliestFirst).ConfigureAwait(false)).Select(x => new OnlySportCsvRecord
            {
                MatchId     = x.MatchId.GetHashCode() > 0 ? x.MatchId.GetHashCode() : x.MatchId.GetHashCode() * -1,
                Title       = x.MatchName,
                StartTime   = x.StartTime.ToUnixTimeSeconds(),
                Latitude    = x.MatchLocation?.Latitude,
                Longitude   = x.MatchLocation?.Longitude,
                Website     = "https://www.stoolball.org.uk" + x.MatchRoute,
                Description = x.Description()
            }).ToList();

            var path = Path.Combine(HostingEnvironment.ApplicationPhysicalPath, @"App_Data\csv");

            if (!Directory.Exists(path))
            {
                Directory.CreateDirectory(path);
            }
            using (var writer = new StreamWriter(Path.Combine(path, "onlysport.csv")))
            {
                using (var csv = new CsvWriter(writer, CultureInfo.InvariantCulture))
                {
                    csv.WriteRecords(matches);
                }
            }

            // Keep repeating
            return(true);
        }
        /// <remarks>
        /// https://devblogs.microsoft.com/aspnet/queuebackgroundworkitem-to-reliably-schedule-and-run-background-processes-in-asp-net/
        /// </remarks>
        private async Task <CancellationToken> UpdateStatistics(Guid taskId, Guid memberKey, string memberName, CancellationToken cancellationToken)
        {
            try
            {
                Logger.Info(GetType(), "Updating match statistics for all matches in {Type:l}.{Method:l}.", GetType(), nameof(UpdateStatistics));

                var matchListings = (await _matchListingDataSource.ReadMatchListings(new MatchFilter
                {
                    IncludeMatches = true,
                    IncludeTournamentMatches = true,
                    IncludeTournaments = false,
                    UntilDate = DateTime.UtcNow
                }, MatchSortOrder.MatchDateEarliestFirst).ConfigureAwait(false));

                _taskTracker.SetTarget(taskId, matchListings.Sum(x => x.MatchInnings.Count) + matchListings.Count);

                using (var connection = _databaseConnectionFactory.CreateDatabaseConnection())
                {
                    connection.Open();

                    foreach (var matchListing in matchListings)
                    {
                        if (cancellationToken.IsCancellationRequested)
                        {
                            Logger.Warn(GetType(), "Background task cancellation requested in {Type:l}.{Method:l}.", GetType(), nameof(UpdateStatistics));
                        }

                        try
                        {
                            var match = await _matchDataSource.ReadMatchByRoute(matchListing.MatchRoute).ConfigureAwait(false);

                            if (match != null)
                            {
                                using (var transaction = connection.BeginTransaction())
                                {
                                    await _statisticsRepository.DeletePlayerStatistics(match.MatchId.Value, transaction).ConfigureAwait(false);

                                    foreach (var innings in match.MatchInnings)
                                    {
                                        await _statisticsRepository.DeleteBowlingFigures(innings.MatchInningsId.Value, transaction).ConfigureAwait(false);

                                        innings.BowlingFigures = _bowlingFiguresCalculator.CalculateBowlingFigures(innings);
                                        await _statisticsRepository.UpdateBowlingFigures(innings, memberKey, memberName, transaction).ConfigureAwait(false);

                                        _taskTracker.IncrementCompletedBy(taskId, 1);
                                    }

                                    var hasPlayerData = _playerIdentityFinder.PlayerIdentitiesInMatch(match).Any();
                                    if (hasPlayerData)
                                    {
                                        var statisticsData = _playerInMatchStatisticsBuilder.BuildStatisticsForMatch(match);
                                        await _statisticsRepository.UpdatePlayerStatistics(statisticsData, transaction).ConfigureAwait(false);
                                    }
                                    _taskTracker.IncrementCompletedBy(taskId, 1);
                                    transaction.Commit();
                                }
                            }
                        }
                        catch (Exception ex)
                        {
                            Logger.Error(GetType(), "Error '{Error}' updating match statistics for '{MatchRoute}' in {Type:l}.{Method:l}.", ex.Message, matchListing.MatchRoute, GetType(), nameof(UpdateStatistics));
                            _taskTracker.IncrementErrorsBy(taskId, 1);
                        }
                    }

                    using (var transaction = connection.BeginTransaction())
                    {
                        await _statisticsRepository.UpdatePlayerProbability(null, transaction).ConfigureAwait(false);

                        transaction.Commit();
                    }

                    Logger.Info(GetType(), "Completed updating match statistics for all matches in {Type:l}.{Method:l}.", GetType(), nameof(UpdateStatistics));
                }
            }
            catch (TaskCanceledException tce)
            {
                Logger.Error(GetType(), "Caught TaskCanceledException '{Message}' in {Type:l}.{Method:l}.", tce.Message, GetType(), nameof(UpdateStatistics));
            }

            return(cancellationToken);
        }
Beispiel #14
0
        public async Task <ActionResult> UpdateTransientTeam([Bind(Prefix = "Team", Include = "TeamName,AgeRangeLower,AgeRangeUpper,PlayerType,Facebook,Twitter,Instagram,YouTube,Website")] Team team)
        {
            if (team is null)
            {
                throw new ArgumentNullException(nameof(team));
            }

            var beforeUpdate = await _teamDataSource.ReadTeamByRoute(Request.RawUrl).ConfigureAwait(false);

            team.TeamId    = beforeUpdate.TeamId;
            team.TeamRoute = beforeUpdate.TeamRoute;

            // get this from the unvalidated form instead of via modelbinding so that HTML can be allowed
            team.Introduction          = Request.Unvalidated.Form["Team.Introduction"];
            team.Cost                  = Request.Unvalidated.Form["Team.Cost"];
            team.PublicContactDetails  = Request.Unvalidated.Form["Team.PublicContactDetails"];
            team.PrivateContactDetails = Request.Unvalidated.Form["Team.PrivateContactDetails"];

            if (team.AgeRangeLower < 11 && !team.AgeRangeUpper.HasValue)
            {
                ModelState.AddModelError("Team.AgeRangeUpper", "School teams and junior teams must specify a maximum age for players");
            }

            if (team.AgeRangeUpper.HasValue && team.AgeRangeUpper < team.AgeRangeLower)
            {
                ModelState.AddModelError("Team.AgeRangeUpper", "The maximum age for players cannot be lower than the minimum age");
            }

            var isAuthorized = _authorizationPolicy.IsAuthorized(beforeUpdate);

            if (isAuthorized[AuthorizedAction.EditTeam] && ModelState.IsValid)
            {
                var currentMember = Members.GetCurrentMember();
                var updatedTeam   = await _teamRepository.UpdateTransientTeam(team, currentMember.Key, currentMember.Name).ConfigureAwait(false);

                // redirect back to the team, as there is no actions page for a transient team
                return(Redirect(updatedTeam.TeamRoute));
            }

            var model = new TeamViewModel(CurrentPage, Services.UserService)
            {
                Team = team,
            };

            model.IsAuthorized = isAuthorized;

            model.Matches = new MatchListingViewModel(CurrentPage, Services?.UserService)
            {
                Matches = await _matchDataSource.ReadMatchListings(new MatchFilter
                {
                    TeamIds = new List <Guid> {
                        model.Team.TeamId.Value
                    },
                    IncludeMatches = false
                }, MatchSortOrder.MatchDateEarliestFirst).ConfigureAwait(false),
                DateTimeFormatter = _dateFormatter
            };

            var match = model.Matches.Matches.First();

            model.Metadata.PageTitle = $"Edit {model.Team.TeamName}, {_dateFormatter.FormatDate(match.StartTime, false, false)}";

            model.Breadcrumbs.Add(new Breadcrumb {
                Name = match.MatchName, Url = new Uri(match.MatchRoute, UriKind.Relative)
            });

            return(View("EditTransientTeam", model));
        }
        public async override Task <ActionResult> Index(ContentModel contentModel)
        {
            if (contentModel is null)
            {
                throw new ArgumentNullException(nameof(contentModel));
            }

            var model = new MatchListingViewModel(contentModel.Content, Services?.UserService)
            {
                AppliedMatchFilter = _matchFilterQueryStringParser.ParseQueryString(new MatchFilter(), HttpUtility.ParseQueryString(Request.Url.Query)),
                DateTimeFormatter  = _dateFormatter
            };

            model.AppliedMatchFilter.IncludeTournaments       = true;
            model.AppliedMatchFilter.IncludeTournamentMatches = false;
            model.AppliedMatchFilter.IncludeMatches           = false;
            if (!model.AppliedMatchFilter.FromDate.HasValue)
            {
                model.AppliedMatchFilter.FromDate = DateTimeOffset.UtcNow.AddDays(-1);
            }
            if (!model.AppliedMatchFilter.UntilDate.HasValue)
            {
                if (!int.TryParse(Request.QueryString["days"], out var daysAhead))
                {
                    daysAhead = 365;
                }
                model.AppliedMatchFilter.UntilDate = DateTimeOffset.UtcNow.AddDays(daysAhead);
            }

            var playerType = Path.GetFileNameWithoutExtension(Request.RawUrl.ToUpperInvariant());

            switch (playerType)
            {
            case "MIXED":
                model.AppliedMatchFilter.PlayerTypes.Add(PlayerType.Mixed);
                break;

            case "LADIES":
                model.AppliedMatchFilter.PlayerTypes.Add(PlayerType.Ladies);
                break;

            case "JUNIOR":
                model.AppliedMatchFilter.PlayerTypes.Add(PlayerType.JuniorMixed);
                model.AppliedMatchFilter.PlayerTypes.Add(PlayerType.JuniorGirls);
                model.AppliedMatchFilter.PlayerTypes.Add(PlayerType.JuniorBoys);
                break;

            default:
                playerType = null;
                break;
            }

            // Remove date from filter and describe the remainder in the feed title, because the date range is not the subject of the feed,
            // it's just what we're including in the feed right now to return only currently relevant data.
            var clonedFilter = model.AppliedMatchFilter.Clone();

            clonedFilter.FromDate      = clonedFilter.UntilDate = null;
            model.Metadata.PageTitle   = "Stoolball tournaments" + _matchFilterHumanizer.MatchingFilter(clonedFilter);
            model.Metadata.Description = $"New or updated stoolball tournaments on the Stoolball England website";
            if (!string.IsNullOrEmpty(playerType))
            {
                model.Metadata.PageTitle   = $"{playerType.ToLower(CultureInfo.CurrentCulture).Humanize(LetterCasing.Sentence)} {model.Metadata.PageTitle.ToLower(CultureInfo.CurrentCulture)}";
                model.Metadata.Description = $"New or updated {playerType.Humanize(LetterCasing.LowerCase)} stoolball tournaments on the Stoolball England website";
            }
            model.Matches = await _matchDataSource.ReadMatchListings(model.AppliedMatchFilter, MatchSortOrder.LatestUpdateFirst).ConfigureAwait(false);

            return(View(Request.QueryString["format"] == "tweet" ? "TournamentTweets" : "TournamentsRss", model));
        }
        public async override Task <ActionResult> Index(ContentModel contentModel)
        {
            if (contentModel is null)
            {
                throw new ArgumentNullException(nameof(contentModel));
            }

            var model = new MatchListingViewModel(contentModel.Content, Services?.UserService)
            {
                DefaultMatchFilter = new MatchFilter
                {
                    FromDate                 = DateTimeOffset.UtcNow.Date,
                    IncludeMatches           = true,
                    IncludeTournaments       = true,
                    IncludeTournamentMatches = false
                },
                DateTimeFormatter = _dateFormatter
            };

            model.AppliedMatchFilter = _matchFilterQueryStringParser.ParseQueryString(model.DefaultMatchFilter, HttpUtility.ParseQueryString(Request.Url.Query));

            // Don't allow matches in the past - this is a calendar for planning future events
            if (model.AppliedMatchFilter.FromDate < model.DefaultMatchFilter.FromDate)
            {
                model.AppliedMatchFilter.FromDate = model.DefaultMatchFilter.FromDate;
            }

            var pageTitle = "Stoolball matches and tournaments";
            var legacyTournamentsCalendarUrl = Regex.Match(Request.RawUrl, "/tournaments/(all|mixed|ladies|junior)/calendar.ics", RegexOptions.IgnoreCase);

            if (Request.RawUrl.StartsWith("/matches.ics", StringComparison.OrdinalIgnoreCase))
            {
                model.AppliedMatchFilter.IncludeTournaments = false;
                pageTitle = "Stoolball matches";
            }
            else if (legacyTournamentsCalendarUrl.Success || Request.RawUrl.StartsWith("/tournaments.ics", StringComparison.OrdinalIgnoreCase))
            {
                model.AppliedMatchFilter.IncludeMatches = false;
                pageTitle = "Stoolball tournaments";

                if (legacyTournamentsCalendarUrl.Success)
                {
                    switch (legacyTournamentsCalendarUrl.Groups[1].Value.ToUpperInvariant())
                    {
                    case "MIXED":
                        model.AppliedMatchFilter.PlayerTypes.Add(PlayerType.Mixed);
                        break;

                    case "LADIES":
                        model.AppliedMatchFilter.PlayerTypes.Add(PlayerType.Ladies);
                        break;

                    case "JUNIOR":
                        model.AppliedMatchFilter.PlayerTypes.Add(PlayerType.JuniorMixed);
                        model.AppliedMatchFilter.PlayerTypes.Add(PlayerType.JuniorGirls);
                        model.AppliedMatchFilter.PlayerTypes.Add(PlayerType.JuniorBoys);
                        break;

                    default:
                        break;
                    }
                }
            }
            else if (Request.RawUrl.StartsWith("/tournaments/", StringComparison.OrdinalIgnoreCase))
            {
                var tournament = await _tournamentDataSource.ReadTournamentByRoute(Request.RawUrl).ConfigureAwait(false);

                if (tournament == null)
                {
                    return(new HttpNotFoundResult());
                }
                pageTitle = tournament.TournamentFullName(x => tournament.StartTimeIsKnown ? _dateFormatter.FormatDateTime(tournament.StartTime, true, false) : _dateFormatter.FormatDate(tournament.StartTime, true, false));
                model.Matches.Add(tournament.ToMatchListing());
            }
            else if (Request.RawUrl.StartsWith("/matches/", StringComparison.OrdinalIgnoreCase))
            {
                var match = await _matchDataSource.ReadMatchByRoute(Request.RawUrl).ConfigureAwait(false);

                if (match == null)
                {
                    return(new HttpNotFoundResult());
                }
                pageTitle = match.MatchFullName(x => match.StartTimeIsKnown ? _dateFormatter.FormatDateTime(match.StartTime, true, false) : _dateFormatter.FormatDate(match.StartTime, true, false));
                model.Matches.Add(match.ToMatchListing());
            }
            else if (Request.RawUrl.StartsWith("/clubs/", StringComparison.OrdinalIgnoreCase))
            {
                var club = await _clubDataSource.ReadClubByRoute(Request.RawUrl).ConfigureAwait(false);

                if (club == null)
                {
                    return(new HttpNotFoundResult());
                }
                pageTitle += " for " + club.ClubName;
                model.AppliedMatchFilter.TeamIds.AddRange(club.Teams.Select(x => x.TeamId.Value));
            }
            else if (Request.RawUrl.StartsWith("/teams/", StringComparison.OrdinalIgnoreCase))
            {
                var team = await _teamDataSource.ReadTeamByRoute(Request.RawUrl).ConfigureAwait(false);

                if (team == null)
                {
                    return(new HttpNotFoundResult());
                }
                pageTitle += " for " + team.TeamName;
                model.AppliedMatchFilter.TeamIds.Add(team.TeamId.Value);
            }
            else if (Request.RawUrl.StartsWith("/competitions/", StringComparison.OrdinalIgnoreCase))
            {
                var competition = await _competitionDataSource.ReadCompetitionByRoute(Request.RawUrl).ConfigureAwait(false);

                if (competition == null)
                {
                    return(new HttpNotFoundResult());
                }
                pageTitle += " in the " + competition.CompetitionName;
                model.AppliedMatchFilter.CompetitionIds.Add(competition.CompetitionId.Value);
            }
            else if (Request.RawUrl.StartsWith("/locations/", StringComparison.OrdinalIgnoreCase))
            {
                var location = await _matchLocationDataSource.ReadMatchLocationByRoute(Request.RawUrl).ConfigureAwait(false);

                if (location == null)
                {
                    return(new HttpNotFoundResult());
                }
                pageTitle += " at " + location.NameAndLocalityOrTown();
                model.AppliedMatchFilter.MatchLocationIds.Add(location.MatchLocationId.Value);
            }

            // Remove from date from filter if it's the default, and describe the remainder in the feed title.
            var clonedFilter = model.AppliedMatchFilter.Clone();

            if (clonedFilter.FromDate == model.DefaultMatchFilter.FromDate)
            {
                clonedFilter.FromDate = null;
            }
            model.Metadata.PageTitle = pageTitle + _matchFilterHumanizer.MatchingFilter(clonedFilter);
            if (model.AppliedMatchFilter.PlayerTypes.Any())
            {
                model.Metadata.PageTitle = $"{model.AppliedMatchFilter.PlayerTypes.First().Humanize(LetterCasing.Sentence).Replace("Junior mixed", "Junior")} {model.Metadata.PageTitle.ToLower(CultureInfo.CurrentCulture)}";
            }
            if (!model.Matches.Any())
            {
                model.Matches = await _matchListingDataSource.ReadMatchListings(model.AppliedMatchFilter, MatchSortOrder.LatestUpdateFirst).ConfigureAwait(false);
            }

            return(CurrentTemplate(model));
        }
        public async override Task <ActionResult> Index(ContentModel contentModel)
        {
            if (contentModel is null)
            {
                throw new ArgumentNullException(nameof(contentModel));
            }

            var model = new MatchListingViewModel(contentModel.Content, Services?.UserService)
            {
                AppliedMatchFilter = _queryStringParser.ParseFilterFromQueryString(Request.QueryString),
                DateTimeFormatter  = _dateFormatter
            };

            string pageTitle = "Stoolball matches";

            if (Request.RawUrl.StartsWith("/clubs/", StringComparison.OrdinalIgnoreCase))
            {
                var club = await _clubDataSource.ReadClubByRoute(Request.RawUrl).ConfigureAwait(false);

                if (club == null)
                {
                    return(new HttpNotFoundResult());
                }
                pageTitle += " for " + club.ClubName;
                model.AppliedMatchFilter.TeamIds.AddRange(club.Teams.Select(x => x.TeamId.Value));
            }
            else if (Request.RawUrl.StartsWith("/teams/", StringComparison.OrdinalIgnoreCase))
            {
                var team = await _teamDataSource.ReadTeamByRoute(Request.RawUrl).ConfigureAwait(false);

                if (team == null)
                {
                    return(new HttpNotFoundResult());
                }
                pageTitle += " for " + team.TeamName;
                model.AppliedMatchFilter.TeamIds.Add(team.TeamId.Value);
            }
            else if (Request.RawUrl.StartsWith("/competitions/", StringComparison.OrdinalIgnoreCase))
            {
                var competition = await _competitionDataSource.ReadCompetitionByRoute(Request.RawUrl).ConfigureAwait(false);

                if (competition == null)
                {
                    return(new HttpNotFoundResult());
                }
                pageTitle += " in the " + competition.CompetitionName;
                model.AppliedMatchFilter.CompetitionIds.Add(competition.CompetitionId.Value);
            }
            else if (Request.RawUrl.StartsWith("/locations/", StringComparison.OrdinalIgnoreCase))
            {
                var location = await _matchLocationDataSource.ReadMatchLocationByRoute(Request.RawUrl).ConfigureAwait(false);

                if (location == null)
                {
                    return(new HttpNotFoundResult());
                }
                pageTitle += " at " + location.NameAndLocalityOrTown();
                model.AppliedMatchFilter.MatchLocationIds.Add(location.MatchLocationId.Value);
            }

            // Remove from date from filter if it's the default, and describe the remainder in the feed title.
            var clonedFilter = model.AppliedMatchFilter.Clone();

            if (clonedFilter.FromDate == DateTimeOffset.UtcNow.Date)
            {
                clonedFilter.FromDate = null;
            }
            // Remove to date filter if it's a rolling date
            // (if user has set a specific end date a exactly year in the future unfortunately we'll miss it, but this is only for the description)
            if (clonedFilter.UntilDate == DateTimeOffset.UtcNow.Date.AddDays(365).AddDays(1).AddSeconds(-1))
            {
                clonedFilter.UntilDate = null;
            }
            model.Metadata.PageTitle   = pageTitle + _matchFilterHumanizer.MatchingFilter(clonedFilter);
            model.Metadata.Description = $"New or updated stoolball matches on the Stoolball England website";
            if (model.AppliedMatchFilter.PlayerTypes.Any())
            {
                model.Metadata.PageTitle   = $"{model.AppliedMatchFilter.PlayerTypes.First().Humanize(LetterCasing.Sentence)} {model.Metadata.PageTitle.ToLower(CultureInfo.CurrentCulture)}";
                model.Metadata.Description = $"New or updated {model.AppliedMatchFilter.PlayerTypes.First()} stoolball matches on the Stoolball England website";
            }
            model.Matches = await _matchDataSource.ReadMatchListings(model.AppliedMatchFilter, MatchSortOrder.LatestUpdateFirst).ConfigureAwait(false);

            return(View(Request.QueryString["format"] == "tweet" ? "MatchTweets" : "MatchesRss", model));
        }