public async override Task <ActionResult> Index(ContentModel contentModel) { if (contentModel is null) { throw new ArgumentNullException(nameof(contentModel)); } var model = new MatchViewModel(contentModel.Content, Services?.UserService) { Match = await _matchDataSource.ReadMatchByRoute(Request.RawUrl).ConfigureAwait(false), DateTimeFormatter = _dateFormatter }; if (model.Match == null) { return(new HttpNotFoundResult()); } else { model.IsAuthorized = _authorizationPolicy.IsAuthorized(model.Match); model.Metadata.PageTitle = model.Match.MatchFullName(x => _dateFormatter.FormatDate(x, false, false, false)) + " - stoolball match"; if (model.Match.Season != null) { model.Breadcrumbs.Add(new Breadcrumb { Name = Constants.Pages.Competitions, Url = new Uri(Constants.Pages.CompetitionsUrl, UriKind.Relative) }); model.Breadcrumbs.Add(new Breadcrumb { Name = model.Match.Season.Competition.CompetitionName, Url = new Uri(model.Match.Season.Competition.CompetitionRoute, UriKind.Relative) }); model.Breadcrumbs.Add(new Breadcrumb { Name = model.Match.Season.SeasonName(), Url = new Uri(model.Match.Season.SeasonRoute, UriKind.Relative) }); } else if (model.Match.Tournament != null) { model.Breadcrumbs.Add(new Breadcrumb { Name = Constants.Pages.Tournaments, Url = new Uri(Constants.Pages.TournamentsUrl, UriKind.Relative) }); model.Breadcrumbs.Add(new Breadcrumb { Name = model.Match.Tournament.TournamentName, Url = new Uri(model.Match.Tournament.TournamentRoute, UriKind.Relative) }); } else { model.Breadcrumbs.Add(new Breadcrumb { Name = Constants.Pages.Matches, Url = new Uri(Constants.Pages.MatchesUrl, UriKind.Relative) }); } model.Breadcrumbs.Add(new Breadcrumb { Name = model.Match.MatchName, Url = new Uri(model.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 model = new EditMatchFormatViewModel(contentModel.Content, Services?.UserService) { Match = await _matchDataSource.ReadMatchByRoute(Request.RawUrl).ConfigureAwait(false), DateFormatter = _dateFormatter }; if (model.Match == null || model.Match.Tournament != null || model.Match.MatchType == MatchType.TrainingSession) { return(new HttpNotFoundResult()); } else { model.IsAuthorized = _authorizationPolicy.IsAuthorized(model.Match); model.Metadata.PageTitle = "Edit " + model.Match.MatchFullName(x => _dateFormatter.FormatDate(x, false, false, false)); model.FormData.Overs = model.Match.MatchInnings.FirstOrDefault()?.OverSets.FirstOrDefault()?.Overs; model.FormData.MatchInnings = model.Match.MatchInnings.Count; if (model.Match.Season != null) { model.Breadcrumbs.Add(new Breadcrumb { Name = Constants.Pages.Competitions, Url = new Uri(Constants.Pages.CompetitionsUrl, UriKind.Relative) }); model.Breadcrumbs.Add(new Breadcrumb { Name = model.Match.Season.Competition.CompetitionName, Url = new Uri(model.Match.Season.Competition.CompetitionRoute, UriKind.Relative) }); model.Breadcrumbs.Add(new Breadcrumb { Name = model.Match.Season.SeasonName(), Url = new Uri(model.Match.Season.SeasonRoute, UriKind.Relative) }); } else { model.Breadcrumbs.Add(new Breadcrumb { Name = Constants.Pages.Matches, Url = new Uri(Constants.Pages.MatchesUrl, UriKind.Relative) }); } model.Breadcrumbs.Add(new Breadcrumb { Name = model.Match.MatchName, Url = new Uri(model.Match.MatchRoute, UriKind.Relative) }); return(CurrentTemplate(model)); } }
public async Task <ActionResult> UpdateMatch([Bind(Prefix = "Match", Include = "Season,Teams,MatchResultType")] Match postedMatch) { if (postedMatch is null) { throw new ArgumentNullException(nameof(postedMatch)); } var beforeUpdate = await _matchDataSource.ReadMatchByRoute(Request.RawUrl).ConfigureAwait(false); var model = new EditTrainingSessionViewModel(CurrentPage, Services.UserService) { Match = postedMatch, DateFormatter = _dateTimeFormatter }; model.Match.MatchId = beforeUpdate.MatchId; model.Match.MatchType = MatchType.TrainingSession; model.Match.MatchRoute = beforeUpdate.MatchRoute; model.Match.UpdateMatchNameAutomatically = beforeUpdate.UpdateMatchNameAutomatically; _editMatchHelper.ConfigureModelFromRequestData(model, Request.Unvalidated.Form, Request.Form, ModelState); if (model.Match.Season != null && !model.Match.Season.SeasonId.HasValue) { model.Match.Season = null; } else if (model.Match.Season != null) { // Get the season, to support validation against season dates model.Match.Season = await _seasonDataSource.ReadSeasonById(model.Match.Season.SeasonId.Value).ConfigureAwait(false); } _matchValidator.DateIsValidForSqlServer(() => model.MatchDate, ModelState, "MatchDate", "match"); _matchValidator.DateIsWithinTheSeason(() => model.MatchDate, model.Match.Season, ModelState, "MatchDate", "match"); _matchValidator.AtLeastOneTeamInMatch(model.Match.Teams, ModelState); foreach (var team in model.Match.Teams) { team.TeamRole = TeamRole.Training; } model.IsAuthorized = _authorizationPolicy.IsAuthorized(beforeUpdate); if (model.IsAuthorized[AuthorizedAction.EditMatch] && ModelState.IsValid && (model.Season == null || model.Season.MatchTypes.Contains(MatchType.TrainingSession))) { if ((int?)model.Match.MatchResultType == -1) { model.Match.MatchResultType = null; } var currentMember = Members.GetCurrentMember(); var updatedMatch = await _matchRepository.UpdateMatch(model.Match, currentMember.Key, currentMember.Name).ConfigureAwait(false); await _cacheClearer.ClearCacheFor(updatedMatch).ConfigureAwait(false); return(Redirect(updatedMatch.MatchRoute)); } model.Match.MatchName = beforeUpdate.MatchName; model.Metadata.PageTitle = "Edit " + model.Match.MatchFullName(x => _dateTimeFormatter.FormatDate(x, false, false, false)); if (model.Match.Season != null) { model.Breadcrumbs.Add(new Breadcrumb { Name = Constants.Pages.Competitions, Url = new Uri(Constants.Pages.CompetitionsUrl, UriKind.Relative) }); model.Breadcrumbs.Add(new Breadcrumb { Name = model.Match.Season.Competition.CompetitionName, Url = new Uri(model.Match.Season.Competition.CompetitionRoute, UriKind.Relative) }); model.Breadcrumbs.Add(new Breadcrumb { Name = model.Match.Season.SeasonName(), Url = new Uri(model.Match.Season.SeasonRoute, UriKind.Relative) }); } else { model.Breadcrumbs.Add(new Breadcrumb { Name = Constants.Pages.Matches, Url = new Uri(Constants.Pages.MatchesUrl, UriKind.Relative) }); } model.Breadcrumbs.Add(new Breadcrumb { Name = model.Match.MatchName, Url = new Uri(model.Match.MatchRoute, UriKind.Relative) }); return(View("EditTrainingSession", 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 DeleteMatchViewModel(contentModel.Content, Services?.UserService) { Match = await _matchDataSource.ReadMatchByRoute(Request.RawUrl).ConfigureAwait(false), DateTimeFormatter = _dateFormatter }; if (model.Match == null) { return(new HttpNotFoundResult()); } else { model.TotalComments = await _matchCommentsDataSource.ReadTotalComments(model.Match.MatchId.Value).ConfigureAwait(false); // Find the player identities in the match, then reselect them with details of how many matches they've played model.PlayerIdentities = _playerIdentityFinder.PlayerIdentitiesInMatch(model.Match).ToList(); if (model.PlayerIdentities.Any()) { model.PlayerIdentities = await _playerDataSource.ReadPlayerIdentities( new PlayerFilter { PlayerIdentityIds = model.PlayerIdentities.Select(x => x.PlayerIdentityId.Value).ToList() } ).ConfigureAwait(false); } model.ConfirmDeleteRequest.RequiredText = model.Match.MatchName; model.IsAuthorized = _authorizationPolicy.IsAuthorized(model.Match); model.Metadata.PageTitle = "Delete " + model.Match.MatchFullName(x => _dateFormatter.FormatDate(x, false, false, false)) + " - stoolball match"; if (model.Match.Season != null) { model.Breadcrumbs.Add(new Breadcrumb { Name = Constants.Pages.Competitions, Url = new Uri(Constants.Pages.CompetitionsUrl, UriKind.Relative) }); model.Breadcrumbs.Add(new Breadcrumb { Name = model.Match.Season.Competition.CompetitionName, Url = new Uri(model.Match.Season.Competition.CompetitionRoute, UriKind.Relative) }); model.Breadcrumbs.Add(new Breadcrumb { Name = model.Match.Season.SeasonName(), Url = new Uri(model.Match.Season.SeasonRoute, UriKind.Relative) }); } else if (model.Match.Tournament != null) { model.Breadcrumbs.Add(new Breadcrumb { Name = Constants.Pages.Tournaments, Url = new Uri(Constants.Pages.TournamentsUrl, UriKind.Relative) }); model.Breadcrumbs.Add(new Breadcrumb { Name = model.Match.Tournament.TournamentName, Url = new Uri(model.Match.Tournament.TournamentRoute, UriKind.Relative) }); } else { model.Breadcrumbs.Add(new Breadcrumb { Name = Constants.Pages.Matches, Url = new Uri(Constants.Pages.MatchesUrl, UriKind.Relative) }); } model.Breadcrumbs.Add(new Breadcrumb { Name = model.Match.MatchName, Url = new Uri(model.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 model = new MatchViewModel(contentModel.Content, Services?.UserService) { Match = await _matchDataSource.ReadMatchByRoute(Request.Url.AbsolutePath).ConfigureAwait(false), DateTimeFormatter = _dateFormatter }; if (model.Match == null) { return(new HttpNotFoundResult()); } else { model.IsAuthorized = _authorizationPolicy.IsAuthorized(model.Match); model.Match.Comments = await _commentsDataSource.ReadComments(model.Match.MatchId.Value).ConfigureAwait(false); foreach (var comment in model.Match.Comments) { comment.Comment = _emailProtector.ProtectEmailAddresses(comment.Comment, User.Identity.IsAuthenticated); comment.Comment = _badLanguageFilter.Filter(comment.Comment); } model.Metadata.PageTitle = model.Match.MatchFullName(x => _dateFormatter.FormatDate(x, false, false, false)) + " - stoolball match"; model.Metadata.Description = model.Match.Description(); model.Match.MatchNotes = _emailProtector.ProtectEmailAddresses(model.Match.MatchNotes, User.Identity.IsAuthenticated); // If a team was all out, convert wickets to -1. This value is used by the view, and also by matches imported from the old website. foreach (var innings in model.Match.MatchInnings) { if (innings.Wickets.HasValue) { if ((innings.Wickets == model.Match.PlayersPerTeam - 1 && !model.Match.LastPlayerBatsOn) || (innings.Wickets == model.Match.PlayersPerTeam && model.Match.LastPlayerBatsOn)) { innings.Wickets = -1; } } } if (model.Match.Season != null) { model.Breadcrumbs.Add(new Breadcrumb { Name = Constants.Pages.Competitions, Url = new Uri(Constants.Pages.CompetitionsUrl, UriKind.Relative) }); model.Breadcrumbs.Add(new Breadcrumb { Name = model.Match.Season.Competition.CompetitionName, Url = new Uri(model.Match.Season.Competition.CompetitionRoute, UriKind.Relative) }); model.Breadcrumbs.Add(new Breadcrumb { Name = model.Match.Season.SeasonName(), Url = new Uri(model.Match.Season.SeasonRoute, UriKind.Relative) }); } else if (model.Match.Tournament != null) { model.Breadcrumbs.Add(new Breadcrumb { Name = Constants.Pages.Tournaments, Url = new Uri(Constants.Pages.TournamentsUrl, UriKind.Relative) }); model.Breadcrumbs.Add(new Breadcrumb { Name = model.Match.Tournament.TournamentName, Url = new Uri(model.Match.Tournament.TournamentRoute, UriKind.Relative) }); } else { model.Breadcrumbs.Add(new Breadcrumb { Name = Constants.Pages.Matches, Url = new Uri(Constants.Pages.MatchesUrl, 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 EditStartOfPlayViewModel(contentModel.Content, Services?.UserService) { Match = await _matchDataSource.ReadMatchByRoute(Request.RawUrl).ConfigureAwait(false), DateFormatter = _dateFormatter }; if (model.Match == null || model.Match.Tournament != null) { return(new HttpNotFoundResult()); } else { // This page is only for matches in the past if (model.Match.StartTime > DateTime.UtcNow) { return(new HttpNotFoundResult()); } model.IsAuthorized = _authorizationPolicy.IsAuthorized(model.Match); if (model.Match.MatchResultType.HasValue) { model.MatchWentAhead = (model.Match.MatchResultType == MatchResultType.HomeWin || model.Match.MatchResultType == MatchResultType.AwayWin || model.Match.MatchResultType == MatchResultType.Tie); } if (model.Match.MatchType == MatchType.KnockoutMatch && model.Match.Season != null) { model.Match.Season = await _seasonDataSource.ReadSeasonByRoute(model.Match.Season.SeasonRoute, true).ConfigureAwait(false); model.PossibleHomeTeams = _editMatchHelper.PossibleTeamsAsListItems(model.Match.Season?.Teams); model.PossibleAwayTeams = _editMatchHelper.PossibleTeamsAsListItems(model.Match.Season?.Teams); } model.HomeTeamId = model.Match.Teams.SingleOrDefault(x => x.TeamRole == TeamRole.Home)?.Team.TeamId; model.AwayTeamId = model.Match.Teams.SingleOrDefault(x => x.TeamRole == TeamRole.Away)?.Team.TeamId; model.MatchLocationId = model.Match.MatchLocation?.MatchLocationId; model.MatchLocationName = model.Match.MatchLocation?.NameAndLocalityOrTownIfDifferent(); model.TossWonBy = model.Match.Teams.FirstOrDefault(x => x.WonToss.HasValue && x.WonToss.Value)?.MatchTeamId.ToString(); model.BattedFirst = model.Match.InningsOrderIsKnown ? model.Match.MatchInnings.First().BattingTeam.MatchTeamId.ToString() : null; model.Metadata.PageTitle = "Edit " + model.Match.MatchFullName(x => _dateFormatter.FormatDate(x, false, false, false)); if (model.Match.Season != null) { model.Breadcrumbs.Add(new Breadcrumb { Name = Constants.Pages.Competitions, Url = new Uri(Constants.Pages.CompetitionsUrl, UriKind.Relative) }); model.Breadcrumbs.Add(new Breadcrumb { Name = model.Match.Season.Competition.CompetitionName, Url = new Uri(model.Match.Season.Competition.CompetitionRoute, UriKind.Relative) }); model.Breadcrumbs.Add(new Breadcrumb { Name = model.Match.Season.SeasonName(), Url = new Uri(model.Match.Season.SeasonRoute, UriKind.Relative) }); } else { model.Breadcrumbs.Add(new Breadcrumb { Name = Constants.Pages.Matches, Url = new Uri(Constants.Pages.MatchesUrl, UriKind.Relative) }); } model.Breadcrumbs.Add(new Breadcrumb { Name = model.Match.MatchName, Url = new Uri(model.Match.MatchRoute, UriKind.Relative) }); return(CurrentTemplate(model)); } }
public async Task <ActionResult> UpdateMatch([Bind(Prefix = "Match", Include = "MatchResultType")] Match postedMatch) { if (postedMatch is null) { postedMatch = new Match(); } var beforeUpdate = await _matchDataSource.ReadMatchByRoute(Request.RawUrl).ConfigureAwait(false); if (beforeUpdate.StartTime > DateTime.UtcNow || beforeUpdate.Tournament != null) { return(new HttpNotFoundResult()); } var model = new EditStartOfPlayViewModel(CurrentPage, Services.UserService) { Match = beforeUpdate, DateFormatter = _dateTimeFormatter }; model.Match.MatchResultType = postedMatch.MatchResultType; await AddMissingTeamsFromRequest(model, ModelState).ConfigureAwait(false); ReadMatchLocationFromRequest(model); ReadTossWonByFromRequest(model); ReadBattedFirstFromRequest(model); if (bool.TryParse(Request.Form["MatchWentAhead"], out var matchWentAhead)) { // Reset the fields which are not compatible with the selection for whether the match went ahead. // They may have been set, then the match went ahead option was changed, and their values would now be misleading. model.MatchWentAhead = matchWentAhead; if (model.MatchWentAhead.Value && model.Match.MatchResultType != MatchResultType.HomeWin && model.Match.MatchResultType != MatchResultType.AwayWin && model.Match.MatchResultType != MatchResultType.Tie) { model.Match.MatchResultType = null; } if (!model.MatchWentAhead.Value) { model.TossWonBy = null; model.BattedFirst = null; } if (bool.TryParse(Request.Form["HasScorecard"], out var hasScorecard)) { model.HasScorecard = hasScorecard; } // Validate this field as required, but conditionally based on whether the match went ahead if (!model.MatchWentAhead.Value && !model.Match.MatchResultType.HasValue) { ModelState.AddModelError("Match.MatchResultType", "The Why didn't the match go ahead? field is required"); } } model.IsAuthorized = _authorizationPolicy.IsAuthorized(beforeUpdate); if (model.IsAuthorized[AuthorizedAction.EditMatchResult] && ModelState.IsValid) { var currentMember = Members.GetCurrentMember(); var updatedMatch = await _matchRepository.UpdateStartOfPlay(model.Match, currentMember.Key, currentMember.Name).ConfigureAwait(false); await _cacheClearer.ClearCacheFor(updatedMatch).ConfigureAwait(false); if (model.Match.MatchResultType.HasValue && new List <MatchResultType> { MatchResultType.HomeWinByForfeit, MatchResultType.AwayWinByForfeit, MatchResultType.Postponed, MatchResultType.Cancelled }.Contains(model.Match.MatchResultType.Value)) { // There's no scorecard to complete - redirect to the match return(Redirect(updatedMatch.MatchRoute)); } else if (model.HasScorecard) { // Redirect to batting scorecard return(Redirect(updatedMatch.MatchRoute + "/edit/innings/1/batting")); } else { // Skip scorecard editing and redirect to close of play return(Redirect(updatedMatch.MatchRoute + "/edit/close-of-play")); } } // Reset model.Match.Teams to trigger reappearance of fields, but preserve the values selected in model.*TeamId and model.*TeamName var selectedHomeTeam = model.Match.Teams.SingleOrDefault(x => !x.MatchTeamId.HasValue && x.TeamRole == TeamRole.Home); if (selectedHomeTeam != null) { model.HomeTeamId = selectedHomeTeam.Team.TeamId; model.HomeTeamName = selectedHomeTeam.Team.TeamName; model.Match.Teams.Remove(selectedHomeTeam); } var selectedAwayTeam = model.Match.Teams.SingleOrDefault(x => !x.MatchTeamId.HasValue && x.TeamRole == TeamRole.Away); if (selectedAwayTeam != null) { model.AwayTeamId = selectedAwayTeam.Team.TeamId; model.AwayTeamName = selectedAwayTeam.Team.TeamName; model.Match.Teams.Remove(selectedAwayTeam); } model.Match.MatchName = beforeUpdate.MatchName; model.Metadata.PageTitle = "Edit " + model.Match.MatchFullName(x => _dateTimeFormatter.FormatDate(x, false, false, false)); if (model.Match.Season != null) { model.Breadcrumbs.Add(new Breadcrumb { Name = Constants.Pages.Competitions, Url = new Uri(Constants.Pages.CompetitionsUrl, UriKind.Relative) }); model.Breadcrumbs.Add(new Breadcrumb { Name = model.Match.Season.Competition.CompetitionName, Url = new Uri(model.Match.Season.Competition.CompetitionRoute, UriKind.Relative) }); model.Breadcrumbs.Add(new Breadcrumb { Name = model.Match.Season.SeasonName(), Url = new Uri(model.Match.Season.SeasonRoute, UriKind.Relative) }); } else { model.Breadcrumbs.Add(new Breadcrumb { Name = Constants.Pages.Matches, Url = new Uri(Constants.Pages.MatchesUrl, UriKind.Relative) }); } model.Breadcrumbs.Add(new Breadcrumb { Name = model.Match.MatchName, Url = new Uri(model.Match.MatchRoute, UriKind.Relative) }); return(View("EditStartOfPlay", model)); }
public async Task <ActionResult> DeleteMatch([Bind(Prefix = "ConfirmDeleteRequest", Include = "RequiredText,ConfirmationText")] MatchingTextConfirmation postedModel) { if (postedModel is null) { throw new ArgumentNullException(nameof(postedModel)); } var model = new DeleteMatchViewModel(CurrentPage, Services.UserService) { Match = await _matchDataSource.ReadMatchByRoute(Request.RawUrl).ConfigureAwait(false), DateTimeFormatter = _dateTimeFormatter }; model.IsAuthorized = _authorizationPolicy.IsAuthorized(model.Match); if (model.IsAuthorized[AuthorizedAction.DeleteMatch] && ModelState.IsValid) { var currentMember = Members.GetCurrentMember(); await _matchRepository.DeleteMatch(model.Match, currentMember.Key, currentMember.Name).ConfigureAwait(false); await _cacheClearer.ClearCacheFor(model.Match).ConfigureAwait(false); model.Deleted = true; } else { model.TotalComments = await _matchCommentsDataSource.ReadTotalComments(model.Match.MatchId.Value).ConfigureAwait(false); } model.Metadata.PageTitle = "Delete " + model.Match.MatchFullName(x => _dateTimeFormatter.FormatDate(x, false, false, false)) + " - stoolball match"; if (model.Match.Season != null) { model.Breadcrumbs.Add(new Breadcrumb { Name = Constants.Pages.Competitions, Url = new Uri(Constants.Pages.CompetitionsUrl, UriKind.Relative) }); model.Breadcrumbs.Add(new Breadcrumb { Name = model.Match.Season.Competition.CompetitionName, Url = new Uri(model.Match.Season.Competition.CompetitionRoute, UriKind.Relative) }); model.Breadcrumbs.Add(new Breadcrumb { Name = model.Match.Season.SeasonName(), Url = new Uri(model.Match.Season.SeasonRoute, UriKind.Relative) }); } else if (model.Match.Tournament != null) { model.Breadcrumbs.Add(new Breadcrumb { Name = Constants.Pages.Tournaments, Url = new Uri(Constants.Pages.TournamentsUrl, UriKind.Relative) }); model.Breadcrumbs.Add(new Breadcrumb { Name = model.Match.Tournament.TournamentName, Url = new Uri(model.Match.Tournament.TournamentRoute, UriKind.Relative) }); } else { model.Breadcrumbs.Add(new Breadcrumb { Name = Constants.Pages.Matches, Url = new Uri(Constants.Pages.MatchesUrl, UriKind.Relative) }); } if (!model.Deleted) { model.Breadcrumbs.Add(new Breadcrumb { Name = model.Match.MatchName, Url = new Uri(model.Match.MatchRoute, UriKind.Relative) }); } return(View("DeleteMatch", model)); }
public async Task <ActionResult> UpdateMatch([Bind(Prefix = "CurrentInnings", Include = "MatchInnings,OversBowledSearch")] MatchInningsViewModel postedData) { if (postedData is null) { throw new ArgumentNullException(nameof(postedData)); } var beforeUpdate = await _matchDataSource.ReadMatchByRoute(Request.RawUrl).ConfigureAwait(false); if (beforeUpdate.StartTime > DateTime.UtcNow || beforeUpdate.Tournament != null) { return(new HttpNotFoundResult()); } if (beforeUpdate.MatchResultType.HasValue && new List <MatchResultType> { MatchResultType.HomeWinByForfeit, MatchResultType.AwayWinByForfeit, MatchResultType.Postponed, MatchResultType.Cancelled }.Contains(beforeUpdate.MatchResultType.Value)) { return(new HttpNotFoundResult()); } // The bowler name is required if any other fields are filled in for an over var i = 0; foreach (var over in postedData.OversBowledSearch) { if (string.IsNullOrWhiteSpace(over.BowledBy) && (over.BallsBowled.HasValue || over.Wides.HasValue || over.NoBalls.HasValue || over.RunsConceded.HasValue)) { ModelState.AddModelError($"CurrentInnings.OversBowledSearch[{i}].Bowler", $"You've added the {(i + 1).Ordinalize(CultureInfo.CurrentCulture)} over. Please name the bowler."); } i++; } var model = new EditScorecardViewModel(CurrentPage, Services.UserService) { Match = beforeUpdate, InningsOrderInMatch = _matchInningsUrlParser.ParseInningsOrderInMatchFromUrl(new Uri(Request.RawUrl, UriKind.Relative)), DateFormatter = _dateTimeFormatter, Autofocus = true }; model.CurrentInnings.MatchInnings = model.Match.MatchInnings.Single(x => x.InningsOrderInMatch == model.InningsOrderInMatch); model.CurrentInnings.MatchInnings.OversBowled = postedData.OversBowledSearch.Where(x => x.BowledBy?.Trim().Length > 0).Select((x, index) => new Over { Bowler = new PlayerIdentity { PlayerIdentityName = x.BowledBy.Trim(), Team = model.CurrentInnings.MatchInnings.BowlingTeam.Team }, OverNumber = index + 1, BallsBowled = x.BallsBowled, Wides = x.Wides, NoBalls = x.NoBalls, RunsConceded = x.RunsConceded }).ToList(); model.CurrentInnings.OversBowledSearch = postedData.OversBowledSearch; _overSetScaffolder.ScaffoldOverSets(model.CurrentInnings.MatchInnings.OverSets, model.Match.Tournament != null ? 6 : 12, model.CurrentInnings.MatchInnings.OversBowled); model.CurrentInnings.MatchInnings.BowlingFigures = _bowlingFiguresCalculator.CalculateBowlingFigures(model.CurrentInnings.MatchInnings); model.IsAuthorized = _authorizationPolicy.IsAuthorized(beforeUpdate); if (model.IsAuthorized[AuthorizedAction.EditMatchResult] && ModelState.IsValid) { var currentMember = Members.GetCurrentMember(); await _matchRepository.UpdateBowlingScorecard(model.Match, model.CurrentInnings.MatchInnings.MatchInningsId.Value, currentMember.Key, currentMember.Name).ConfigureAwait(false); // redirect to the next innings or close of play if (model.InningsOrderInMatch.Value < model.Match.MatchInnings.Count) { return(Redirect($"{model.Match.MatchRoute}/edit/innings/{model.InningsOrderInMatch.Value + 1}/batting")); } else { return(Redirect(model.Match.MatchRoute + "/edit/close-of-play")); } } model.Metadata.PageTitle = "Edit " + model.Match.MatchFullName(x => _dateTimeFormatter.FormatDate(x, false, false, false)); while (model.CurrentInnings.MatchInnings.OversBowled.Count < model.CurrentInnings.MatchInnings.OverSets.Sum(x => x.Overs)) { model.CurrentInnings.MatchInnings.OversBowled.Add(new Over()); } if (model.Match.Season != null) { model.Breadcrumbs.Add(new Breadcrumb { Name = Constants.Pages.Competitions, Url = new Uri(Constants.Pages.CompetitionsUrl, UriKind.Relative) }); model.Breadcrumbs.Add(new Breadcrumb { Name = model.Match.Season.Competition.CompetitionName, Url = new Uri(model.Match.Season.Competition.CompetitionRoute, UriKind.Relative) }); model.Breadcrumbs.Add(new Breadcrumb { Name = model.Match.Season.SeasonName(), Url = new Uri(model.Match.Season.SeasonRoute, UriKind.Relative) }); } else { model.Breadcrumbs.Add(new Breadcrumb { Name = Constants.Pages.Matches, Url = new Uri(Constants.Pages.MatchesUrl, UriKind.Relative) }); } model.Breadcrumbs.Add(new Breadcrumb { Name = model.Match.MatchName, Url = new Uri(model.Match.MatchRoute, UriKind.Relative) }); return(View("EditBowlingScorecard", model)); }
public async override Task <ActionResult> Index(ContentModel contentModel) { if (contentModel is null) { throw new ArgumentNullException(nameof(contentModel)); } var model = new EditTrainingSessionViewModel(contentModel.Content, Services?.UserService) { Match = await _matchDataSource.ReadMatchByRoute(Request.RawUrl).ConfigureAwait(false), DateFormatter = _dateFormatter }; if (model.Match == null) { return(new HttpNotFoundResult()); } else { model.IsAuthorized = _authorizationPolicy.IsAuthorized(model.Match); if (model.Match.Season != null) { model.Match.Season = await _seasonDataSource.ReadSeasonByRoute(model.Match.Season.SeasonRoute, true).ConfigureAwait(false); model.SeasonFullName = model.Match.Season.SeasonFullName(); } model.MatchDate = model.Match.StartTime; if (model.Match.StartTimeIsKnown) { model.StartTime = model.Match.StartTime; } model.MatchLocationId = model.Match.MatchLocation?.MatchLocationId; model.MatchLocationName = model.Match.MatchLocation?.NameAndLocalityOrTownIfDifferent(); model.Metadata.PageTitle = "Edit " + model.Match.MatchFullName(x => _dateFormatter.FormatDate(x, false, false, false)); if (model.Match.Season != null) { model.Breadcrumbs.Add(new Breadcrumb { Name = Constants.Pages.Competitions, Url = new Uri(Constants.Pages.CompetitionsUrl, UriKind.Relative) }); model.Breadcrumbs.Add(new Breadcrumb { Name = model.Match.Season.Competition.CompetitionName, Url = new Uri(model.Match.Season.Competition.CompetitionRoute, UriKind.Relative) }); model.Breadcrumbs.Add(new Breadcrumb { Name = model.Match.Season.SeasonName(), Url = new Uri(model.Match.Season.SeasonRoute, UriKind.Relative) }); } else { model.Breadcrumbs.Add(new Breadcrumb { Name = Constants.Pages.Matches, Url = new Uri(Constants.Pages.MatchesUrl, UriKind.Relative) }); } model.Breadcrumbs.Add(new Breadcrumb { Name = model.Match.MatchName, Url = new Uri(model.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 model = new EditCloseOfPlayViewModel(contentModel.Content, Services?.UserService) { Match = await _matchDataSource.ReadMatchByRoute(Request.RawUrl).ConfigureAwait(false), DateFormatter = _dateFormatter }; if (model.Match == null || model.Match.Tournament != null) { return(new HttpNotFoundResult()); } else { // This page is only for matches in the past if (model.Match.StartTime > DateTime.UtcNow) { return(new HttpNotFoundResult()); } // This page is not for matches not played if (model.Match.MatchResultType.HasValue && new List <MatchResultType> { MatchResultType.HomeWinByForfeit, MatchResultType.AwayWinByForfeit, MatchResultType.Postponed, MatchResultType.Cancelled }.Contains(model.Match.MatchResultType.Value)) { return(new HttpNotFoundResult()); } model.IsAuthorized = _authorizationPolicy.IsAuthorized(model.Match); model.FormData.MatchResultType = model.Match.MatchResultType; model.FormData.Awards = model.Match.Awards.Select(x => new MatchAwardViewModel { MatchAwardId = x.AwardedToId, PlayerSearch = x.PlayerIdentity.PlayerIdentityName, TeamId = model.Match.Teams.First(team => team.Team.TeamId == x.PlayerIdentity.Team.TeamId).Team.TeamId, Reason = x.Reason }).ToList(); if (!model.Match.MatchResultType.HasValue) { model.Match.MatchResultType = _matchResultEvaluator.EvaluateMatchResult(model.Match); } model.Metadata.PageTitle = "Edit " + model.Match.MatchFullName(x => _dateFormatter.FormatDate(x, false, false, false)); if (model.Match.Season != null) { model.Breadcrumbs.Add(new Breadcrumb { Name = Constants.Pages.Competitions, Url = new Uri(Constants.Pages.CompetitionsUrl, UriKind.Relative) }); model.Breadcrumbs.Add(new Breadcrumb { Name = model.Match.Season.Competition.CompetitionName, Url = new Uri(model.Match.Season.Competition.CompetitionRoute, UriKind.Relative) }); model.Breadcrumbs.Add(new Breadcrumb { Name = model.Match.Season.SeasonName(), Url = new Uri(model.Match.Season.SeasonRoute, UriKind.Relative) }); } else { model.Breadcrumbs.Add(new Breadcrumb { Name = Constants.Pages.Matches, Url = new Uri(Constants.Pages.MatchesUrl, UriKind.Relative) }); } model.Breadcrumbs.Add(new Breadcrumb { Name = model.Match.MatchName, Url = new Uri(model.Match.MatchRoute, UriKind.Relative) }); return(CurrentTemplate(model)); } }
public async Task <ActionResult> UpdateMatch([Bind(Prefix = "FormData")] EditCloseOfPlayFormData postedData) { if (postedData is null) { throw new ArgumentNullException(nameof(postedData)); } var beforeUpdate = await _matchDataSource.ReadMatchByRoute(Request.RawUrl).ConfigureAwait(false); if (beforeUpdate.StartTime > DateTime.UtcNow || beforeUpdate.Tournament != null) { return(new HttpNotFoundResult()); } var model = new EditCloseOfPlayViewModel(CurrentPage, Services.UserService) { Match = beforeUpdate, FormData = postedData, DateFormatter = _dateTimeFormatter }; model.Match.MatchResultType = model.FormData.MatchResultType; model.Match.Awards = model.FormData.Awards.Select(x => new MatchAward { AwardedToId = x.MatchAwardId, Award = new Award { AwardName = StatisticsConstants.PLAYER_OF_THE_MATCH_AWARD }, PlayerIdentity = new PlayerIdentity { PlayerIdentityName = x.PlayerSearch, Team = new Team { TeamId = x.TeamId } }, Reason = x.Reason }).ToList(); model.Match.UpdateMatchNameAutomatically = beforeUpdate.UpdateMatchNameAutomatically; model.Match.Teams = beforeUpdate.Teams; model.IsAuthorized = _authorizationPolicy.IsAuthorized(beforeUpdate); if (model.IsAuthorized[AuthorizedAction.EditMatchResult] && ModelState.IsValid) { if ((int)model.Match.MatchResultType == -1) { model.Match.MatchResultType = null; } var currentMember = Members.GetCurrentMember(); var updatedMatch = await _matchRepository.UpdateCloseOfPlay(model.Match, currentMember.Key, currentMember.Name).ConfigureAwait(false); await _cacheClearer.ClearCacheFor(updatedMatch).ConfigureAwait(false); return(Redirect(updatedMatch.MatchRoute)); } model.Match.MatchName = beforeUpdate.MatchName; model.Metadata.PageTitle = "Edit " + model.Match.MatchFullName(x => _dateTimeFormatter.FormatDate(x, false, false, false)); if (model.Match.Season != null) { model.Breadcrumbs.Add(new Breadcrumb { Name = Constants.Pages.Competitions, Url = new Uri(Constants.Pages.CompetitionsUrl, UriKind.Relative) }); model.Breadcrumbs.Add(new Breadcrumb { Name = model.Match.Season.Competition.CompetitionName, Url = new Uri(model.Match.Season.Competition.CompetitionRoute, UriKind.Relative) }); model.Breadcrumbs.Add(new Breadcrumb { Name = model.Match.Season.SeasonName(), Url = new Uri(model.Match.Season.SeasonRoute, UriKind.Relative) }); } else { model.Breadcrumbs.Add(new Breadcrumb { Name = Constants.Pages.Matches, Url = new Uri(Constants.Pages.MatchesUrl, UriKind.Relative) }); } model.Breadcrumbs.Add(new Breadcrumb { Name = model.Match.MatchName, Url = new Uri(model.Match.MatchRoute, UriKind.Relative) }); return(View("EditCloseOfPlay", model)); }
public async override Task <ActionResult> Index(ContentModel contentModel) { if (contentModel is null) { throw new ArgumentNullException(nameof(contentModel)); } var model = new EditScorecardViewModel(contentModel.Content, Services?.UserService) { Match = await _matchDataSource.ReadMatchByRoute(Request.RawUrl).ConfigureAwait(false), InningsOrderInMatch = _matchInningsUrlParser.ParseInningsOrderInMatchFromUrl(new Uri(Request.RawUrl, UriKind.Relative)), DateFormatter = _dateFormatter, Autofocus = true }; if (model.Match == null || !model.InningsOrderInMatch.HasValue || model.Match.Tournament != null) { return(new HttpNotFoundResult()); } else { // This page is only for matches in the past if (model.Match.StartTime > DateTime.UtcNow) { return(new HttpNotFoundResult()); } // This page is not for matches not played if (model.Match.MatchResultType.HasValue && new List <MatchResultType> { MatchResultType.HomeWinByForfeit, MatchResultType.AwayWinByForfeit, MatchResultType.Postponed, MatchResultType.Cancelled }.Contains(model.Match.MatchResultType.Value)) { return(new HttpNotFoundResult()); } model.IsAuthorized = _authorizationPolicy.IsAuthorized(model.Match); model.CurrentInnings.MatchInnings = model.Match.MatchInnings.Single(x => x.InningsOrderInMatch == model.InningsOrderInMatch); if (!model.CurrentInnings.MatchInnings.OverSets.Any()) { model.CurrentInnings.MatchInnings.OverSets.Add(new OverSet { Overs = model.Match.Tournament != null ? 6 : 12, BallsPerOver = 8 }); } while (model.CurrentInnings.MatchInnings.OversBowled.Count < model.CurrentInnings.MatchInnings.OverSets.Sum(x => x.Overs)) { model.CurrentInnings.MatchInnings.OversBowled.Add(new Over()); } // Convert overs bowled to a view model, purely to change the field names to ones which will not trigger pop-up contact/password managers // while retaining the benefits of ASP.NET model binding. Using the "search" keyword in the property name also helps to disable contact/password managers. model.CurrentInnings.OversBowledSearch.AddRange(model.CurrentInnings.MatchInnings.OversBowled.Select(x => new OverViewModel { BowledBy = x.Bowler?.PlayerIdentityName, BallsBowled = x.BallsBowled, Wides = x.Wides, NoBalls = x.NoBalls, RunsConceded = x.RunsConceded })); model.Metadata.PageTitle = "Edit " + model.Match.MatchFullName(x => _dateFormatter.FormatDate(x, false, false, false)); if (model.Match.Season != null) { model.Breadcrumbs.Add(new Breadcrumb { Name = Constants.Pages.Competitions, Url = new Uri(Constants.Pages.CompetitionsUrl, UriKind.Relative) }); model.Breadcrumbs.Add(new Breadcrumb { Name = model.Match.Season.Competition.CompetitionName, Url = new Uri(model.Match.Season.Competition.CompetitionRoute, UriKind.Relative) }); model.Breadcrumbs.Add(new Breadcrumb { Name = model.Match.Season.SeasonName(), Url = new Uri(model.Match.Season.SeasonRoute, UriKind.Relative) }); } else { model.Breadcrumbs.Add(new Breadcrumb { Name = Constants.Pages.Matches, Url = new Uri(Constants.Pages.MatchesUrl, UriKind.Relative) }); } model.Breadcrumbs.Add(new Breadcrumb { Name = model.Match.MatchName, Url = new Uri(model.Match.MatchRoute, UriKind.Relative) }); return(CurrentTemplate(model)); } }
public async Task <ActionResult> UpdateMatch([Bind(Prefix = "Match", Include = "MatchResultType")] Match postedMatch) { if (postedMatch is null) { throw new ArgumentNullException(nameof(postedMatch)); } var beforeUpdate = await _matchDataSource.ReadMatchByRoute(Request.RawUrl).ConfigureAwait(false); // This controller is only for matches in the future if (beforeUpdate.StartTime <= DateTime.UtcNow || beforeUpdate.Tournament != null) { return(new HttpNotFoundResult()); } var model = new EditLeagueMatchViewModel(CurrentPage, Services.UserService) { Match = postedMatch, DateFormatter = _dateTimeFormatter }; model.Match.MatchId = beforeUpdate.MatchId; model.Match.MatchRoute = beforeUpdate.MatchRoute; model.Match.UpdateMatchNameAutomatically = beforeUpdate.UpdateMatchNameAutomatically; model.Match.Season = beforeUpdate.Season; _editMatchHelper.ConfigureModelFromRequestData(model, Request.Unvalidated.Form, Request.Form, ModelState); _matchValidator.DateIsValidForSqlServer(() => model.MatchDate, ModelState, "MatchDate", "match"); _matchValidator.DateIsWithinTheSeason(() => model.MatchDate, model.Match.Season, ModelState, "MatchDate", "match"); _matchValidator.TeamsMustBeDifferent(model, ModelState); model.IsAuthorized = _authorizationPolicy.IsAuthorized(beforeUpdate); if (model.IsAuthorized[AuthorizedAction.EditMatch] && ModelState.IsValid) { if ((int?)model.Match.MatchResultType == -1) { model.Match.MatchResultType = null; } var currentMember = Members.GetCurrentMember(); var updatedMatch = await _matchRepository.UpdateMatch(model.Match, currentMember.Key, currentMember.Name).ConfigureAwait(false); await _cacheClearer.ClearCacheFor(updatedMatch).ConfigureAwait(false); return(Redirect(updatedMatch.MatchRoute)); } model.Match.MatchName = beforeUpdate.MatchName; model.Match.Season = model.Season = await _seasonDataSource.ReadSeasonByRoute(model.Match.Season.SeasonRoute, true).ConfigureAwait(false); model.PossibleSeasons = _editMatchHelper.PossibleSeasonsAsListItems(new[] { model.Match.Season }); model.PossibleHomeTeams = _editMatchHelper.PossibleTeamsAsListItems(model.Season.Teams); model.PossibleAwayTeams = _editMatchHelper.PossibleTeamsAsListItems(model.Season.Teams); model.Metadata.PageTitle = "Edit " + model.Match.MatchFullName(x => _dateTimeFormatter.FormatDate(x, false, false, false)); if (model.Match.Season != null) { model.Breadcrumbs.Add(new Breadcrumb { Name = Constants.Pages.Competitions, Url = new Uri(Constants.Pages.CompetitionsUrl, UriKind.Relative) }); model.Breadcrumbs.Add(new Breadcrumb { Name = model.Match.Season.Competition.CompetitionName, Url = new Uri(model.Match.Season.Competition.CompetitionRoute, UriKind.Relative) }); model.Breadcrumbs.Add(new Breadcrumb { Name = model.Match.Season.SeasonName(), Url = new Uri(model.Match.Season.SeasonRoute, UriKind.Relative) }); } else { model.Breadcrumbs.Add(new Breadcrumb { Name = Constants.Pages.Matches, Url = new Uri(Constants.Pages.MatchesUrl, UriKind.Relative) }); } model.Breadcrumbs.Add(new Breadcrumb { Name = model.Match.MatchName, Url = new Uri(model.Match.MatchRoute, UriKind.Relative) }); return(View("EditLeagueMatch", model)); }
/// <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); }
public async Task <ActionResult> UpdateMatch([Bind(Prefix = "CurrentInnings", Include = "MatchInnings,PlayerInningsSearch")] MatchInningsViewModel postedData) { if (postedData is null) { throw new ArgumentNullException(nameof(postedData)); } var beforeUpdate = await _matchDataSource.ReadMatchByRoute(Request.RawUrl).ConfigureAwait(false); if (beforeUpdate.StartTime > DateTime.UtcNow || beforeUpdate.Tournament != null) { return(new HttpNotFoundResult()); } if (beforeUpdate.MatchResultType.HasValue && new List <MatchResultType> { MatchResultType.HomeWinByForfeit, MatchResultType.AwayWinByForfeit, MatchResultType.Postponed, MatchResultType.Cancelled }.Contains(beforeUpdate.MatchResultType.Value)) { return(new HttpNotFoundResult()); } var i = 0; foreach (var innings in postedData.PlayerInningsSearch) { // The batter name is required if any other fields are filled in for an innings if (string.IsNullOrWhiteSpace(innings.Batter) && (innings.DismissalType.HasValue && innings.DismissalType != DismissalType.DidNotBat || !string.IsNullOrWhiteSpace(innings.DismissedBy) || !string.IsNullOrWhiteSpace(innings.Bowler) || innings.RunsScored != null || innings.BallsFaced != null)) { ModelState.AddModelError($"CurrentInnings.PlayerInningsSearch[{i}].Batter", $"You've added details for the {(i + 1).Ordinalize(CultureInfo.CurrentCulture)} batter. Please name the batter."); } // The batter must have batted if any other fields are filled in for an innings if ((innings.DismissalType == DismissalType.DidNotBat || innings.DismissalType == DismissalType.TimedOut) && (!string.IsNullOrWhiteSpace(innings.DismissedBy) || !string.IsNullOrWhiteSpace(innings.Bowler) || innings.RunsScored != null || innings.BallsFaced != null)) { ModelState.AddModelError($"CurrentInnings.PlayerInningsSearch[{i}].DismissalType", $"You've said the {(i + 1).Ordinalize(CultureInfo.CurrentCulture)} batter did not bat, but you added batting details."); } // The batter can't be not out if a a bowler or fielder is named if ((innings.DismissalType == DismissalType.NotOut || innings.DismissalType == DismissalType.Retired || innings.DismissalType == DismissalType.RetiredHurt) && (!string.IsNullOrWhiteSpace(innings.DismissedBy) || !string.IsNullOrWhiteSpace(innings.Bowler) )) { ModelState.AddModelError($"CurrentInnings.PlayerInningsSearch[{i}].DismissalType", $"You've said the {(i + 1).Ordinalize(CultureInfo.CurrentCulture)} batter was not out, but you named a fielder and/or bowler."); } // Caught and bowled by the same person is caught and bowled if (innings.DismissalType == DismissalType.Caught && !string.IsNullOrWhiteSpace(innings.DismissedBy) && innings.DismissedBy?.Trim() == innings.Bowler?.Trim()) { innings.DismissalType = DismissalType.CaughtAndBowled; innings.DismissedBy = null; } // If there's a fielder, the dismissal type should be caught or run-out if (innings.DismissalType != DismissalType.Caught && innings.DismissalType != DismissalType.RunOut && !string.IsNullOrWhiteSpace(innings.DismissedBy)) { ModelState.AddModelError($"CurrentInnings.PlayerInningsSearch[{i}].DismissalType", $"You've named the fielder for the {(i + 1).Ordinalize(CultureInfo.CurrentCulture)} batter, but they were not caught or run-out."); } i++; } var model = new EditScorecardViewModel(CurrentPage, Services.UserService) { Match = beforeUpdate, InningsOrderInMatch = _matchInningsUrlParser.ParseInningsOrderInMatchFromUrl(new Uri(Request.RawUrl, UriKind.Relative)), DateFormatter = _dateTimeFormatter, Autofocus = true }; model.CurrentInnings.MatchInnings = model.Match.MatchInnings.Single(x => x.InningsOrderInMatch == model.InningsOrderInMatch); model.CurrentInnings.MatchInnings.PlayerInnings = postedData.PlayerInningsSearch.Where(x => !string.IsNullOrWhiteSpace(x.Batter)).Select(x => new PlayerInnings { Batter = new PlayerIdentity { PlayerIdentityName = x.Batter.Trim(), Team = model.CurrentInnings.MatchInnings.BattingTeam.Team }, DismissalType = x.DismissalType, DismissedBy = string.IsNullOrWhiteSpace(x.DismissedBy) ? null : new PlayerIdentity { PlayerIdentityName = x.DismissedBy.Trim(), Team = model.CurrentInnings.MatchInnings.BowlingTeam.Team }, Bowler = string.IsNullOrWhiteSpace(x.Bowler) ? null : new PlayerIdentity { PlayerIdentityName = x.Bowler.Trim(), Team = model.CurrentInnings.MatchInnings.BowlingTeam.Team }, RunsScored = x.RunsScored, BallsFaced = x.BallsFaced }).ToList(); model.CurrentInnings.PlayerInningsSearch = postedData.PlayerInningsSearch; model.CurrentInnings.MatchInnings.Byes = postedData.MatchInnings.Byes; model.CurrentInnings.MatchInnings.Wides = postedData.MatchInnings.Wides; model.CurrentInnings.MatchInnings.NoBalls = postedData.MatchInnings.NoBalls; model.CurrentInnings.MatchInnings.BonusOrPenaltyRuns = postedData.MatchInnings.BonusOrPenaltyRuns; model.CurrentInnings.MatchInnings.Runs = postedData.MatchInnings.Runs; model.CurrentInnings.MatchInnings.Wickets = postedData.MatchInnings.Wickets; if (!model.Match.PlayersPerTeam.HasValue) { model.Match.PlayersPerTeam = model.Match.Tournament != null ? 8 : 11; } if (model.Match.PlayersPerTeam.Value < postedData.MatchInnings.PlayerInnings.Count) { model.Match.PlayersPerTeam = postedData.MatchInnings.PlayerInnings.Count; } _playerInningsScaffolder.ScaffoldPlayerInnings(model.CurrentInnings.MatchInnings.PlayerInnings, model.Match.PlayersPerTeam.Value); model.CurrentInnings.MatchInnings.BowlingFigures = _bowlingFiguresCalculator.CalculateBowlingFigures(model.CurrentInnings.MatchInnings); model.IsAuthorized = _authorizationPolicy.IsAuthorized(beforeUpdate); if (model.IsAuthorized[AuthorizedAction.EditMatchResult] && ModelState.IsValid) { var currentMember = Members.GetCurrentMember(); await _matchRepository.UpdateBattingScorecard(model.Match, model.CurrentInnings.MatchInnings.MatchInningsId.Value, currentMember.Key, currentMember.Name).ConfigureAwait(false); // redirect to the bowling scorecard for this innings return(Redirect($"{model.Match.MatchRoute}/edit/innings/{model.InningsOrderInMatch.Value}/bowling")); } model.Metadata.PageTitle = "Edit " + model.Match.MatchFullName(x => _dateTimeFormatter.FormatDate(x, false, false, false)); while (model.CurrentInnings.MatchInnings.OversBowled.Count < model.CurrentInnings.MatchInnings.OverSets.Sum(x => x.Overs)) { model.CurrentInnings.MatchInnings.OversBowled.Add(new Over()); } if (model.Match.Season != null) { model.Breadcrumbs.Add(new Breadcrumb { Name = Constants.Pages.Competitions, Url = new Uri(Constants.Pages.CompetitionsUrl, UriKind.Relative) }); model.Breadcrumbs.Add(new Breadcrumb { Name = model.Match.Season.Competition.CompetitionName, Url = new Uri(model.Match.Season.Competition.CompetitionRoute, UriKind.Relative) }); model.Breadcrumbs.Add(new Breadcrumb { Name = model.Match.Season.SeasonName(), Url = new Uri(model.Match.Season.SeasonRoute, UriKind.Relative) }); } else { model.Breadcrumbs.Add(new Breadcrumb { Name = Constants.Pages.Matches, Url = new Uri(Constants.Pages.MatchesUrl, UriKind.Relative) }); } model.Breadcrumbs.Add(new Breadcrumb { Name = model.Match.MatchName, Url = new Uri(model.Match.MatchRoute, UriKind.Relative) }); return(View("EditBattingScorecard", model)); }
public async override Task <ActionResult> Index(ContentModel contentModel) { if (contentModel is null) { throw new ArgumentNullException(nameof(contentModel)); } var model = new EditKnockoutMatchViewModel(contentModel.Content, Services?.UserService) { Match = await _matchDataSource.ReadMatchByRoute(Request.RawUrl).ConfigureAwait(false), DateFormatter = _dateFormatter }; if (model.Match == null) { return(new HttpNotFoundResult()); } else { // This page is only for matches in the future if (model.Match.StartTime <= DateTime.UtcNow) { return(new HttpNotFoundResult()); } model.IsAuthorized = _authorizationPolicy.IsAuthorized(model.Match); model.MatchName = model.Match.UpdateMatchNameAutomatically ? string.Empty : model.Match.MatchName; if (model.Match.Season != null) { model.Match.Season = model.Season = await _seasonDataSource.ReadSeasonByRoute(model.Match.Season.SeasonRoute, true).ConfigureAwait(false); model.PossibleSeasons = _editMatchHelper.PossibleSeasonsAsListItems(new[] { model.Match.Season }); } model.PossibleHomeTeams = _editMatchHelper.PossibleTeamsAsListItems(model.Season?.Teams); model.PossibleAwayTeams = _editMatchHelper.PossibleTeamsAsListItems(model.Season?.Teams); model.MatchDate = model.Match.StartTime; if (model.Match.StartTimeIsKnown) { model.StartTime = model.Match.StartTime; } model.HomeTeamId = model.Match.Teams.SingleOrDefault(x => x.TeamRole == TeamRole.Home)?.Team.TeamId; model.AwayTeamId = model.Match.Teams.SingleOrDefault(x => x.TeamRole == TeamRole.Away)?.Team.TeamId; model.MatchLocationId = model.Match.MatchLocation?.MatchLocationId; model.MatchLocationName = model.Match.MatchLocation?.NameAndLocalityOrTownIfDifferent(); model.Metadata.PageTitle = "Edit " + model.Match.MatchFullName(x => _dateFormatter.FormatDate(x, false, false, false)); if (model.Match.Season != null) { model.Breadcrumbs.Add(new Breadcrumb { Name = Constants.Pages.Competitions, Url = new Uri(Constants.Pages.CompetitionsUrl, UriKind.Relative) }); model.Breadcrumbs.Add(new Breadcrumb { Name = model.Match.Season.Competition.CompetitionName, Url = new Uri(model.Match.Season.Competition.CompetitionRoute, UriKind.Relative) }); model.Breadcrumbs.Add(new Breadcrumb { Name = model.Match.Season.SeasonName(), Url = new Uri(model.Match.Season.SeasonRoute, UriKind.Relative) }); } else { model.Breadcrumbs.Add(new Breadcrumb { Name = Constants.Pages.Matches, Url = new Uri(Constants.Pages.MatchesUrl, UriKind.Relative) }); } model.Breadcrumbs.Add(new Breadcrumb { Name = model.Match.MatchName, Url = new Uri(model.Match.MatchRoute, UriKind.Relative) }); return(CurrentTemplate(model)); } }
public async Task <ActionResult> UpdateMatch([Bind(Prefix = "FormData")] EditMatchFormatFormData postedData) { if (postedData is null) { throw new ArgumentNullException(nameof(postedData)); } var beforeUpdate = await _matchDataSource.ReadMatchByRoute(Request.RawUrl).ConfigureAwait(false); if (beforeUpdate == null || beforeUpdate.Tournament != null || beforeUpdate.MatchType == MatchType.TrainingSession) { return(new HttpNotFoundResult()); } var model = new EditMatchFormatViewModel(CurrentPage, Services.UserService) { Match = beforeUpdate, DateFormatter = _dateTimeFormatter, FormData = postedData }; var matchIsInTheFuture = model.Match.StartTime > DateTimeOffset.UtcNow; if (postedData.MatchInnings < 2 || postedData.MatchInnings % 2 != 0) { ModelState.AddModelError("FormData.MatchInnings", $"A match cannot have an odd number of innings or less than 2 innings."); } else if (!matchIsInTheFuture && postedData.MatchInnings < model.Match.MatchInnings.Count) { ModelState.AddModelError("FormData.MatchInnings", $"You cannot reduce the number of innings after a match has happened."); } else { while (matchIsInTheFuture && postedData.MatchInnings < model.Match.MatchInnings.Count) { model.Match.MatchInnings.RemoveAt(model.Match.MatchInnings.Count - 1); } if (postedData.MatchInnings > model.Match.MatchInnings.Count) { while (postedData.MatchInnings > model.Match.MatchInnings.Count) { var battingMatchTeamId = model.Match.MatchInnings.Count % 2 == 0 ? model.Match.MatchInnings[0].BattingMatchTeamId : model.Match.MatchInnings[1].BattingMatchTeamId; var bowlingMatchTeamId = model.Match.MatchInnings.Count % 2 == 1 ? model.Match.MatchInnings[0].BattingMatchTeamId : model.Match.MatchInnings[1].BattingMatchTeamId; var addedInnings = _matchInningsFactory.CreateMatchInnings(model.Match, battingMatchTeamId, bowlingMatchTeamId); if (postedData.Overs.HasValue) { addedInnings.OverSets[0].Overs = postedData.Overs; } else { addedInnings.OverSets.Clear(); } model.Match.MatchInnings.Add(addedInnings); } } foreach (var innings in model.Match.MatchInnings) { foreach (var overSet in innings.OverSets) { if (!matchIsInTheFuture && postedData.Overs < overSet.Overs) { ModelState.AddModelError("FormData.Overs", $"You cannot reduce the number of overs after a match has happened."); } else { overSet.Overs = postedData.Overs; } } } } model.IsAuthorized = _authorizationPolicy.IsAuthorized(beforeUpdate); if (model.IsAuthorized[AuthorizedAction.EditMatch] && ModelState.IsValid) { var currentMember = Members.GetCurrentMember(); var updatedMatch = await _matchRepository.UpdateMatchFormat(model.Match, currentMember.Key, currentMember.Name).ConfigureAwait(false); return(Redirect(updatedMatch.MatchRoute + "/edit")); } model.Metadata.PageTitle = "Edit " + model.Match.MatchFullName(x => _dateTimeFormatter.FormatDate(x, false, false, false)); if (model.Match.Season != null) { model.Breadcrumbs.Add(new Breadcrumb { Name = Constants.Pages.Competitions, Url = new Uri(Constants.Pages.CompetitionsUrl, UriKind.Relative) }); model.Breadcrumbs.Add(new Breadcrumb { Name = model.Match.Season.Competition.CompetitionName, Url = new Uri(model.Match.Season.Competition.CompetitionRoute, UriKind.Relative) }); model.Breadcrumbs.Add(new Breadcrumb { Name = model.Match.Season.SeasonName(), Url = new Uri(model.Match.Season.SeasonRoute, UriKind.Relative) }); } else { model.Breadcrumbs.Add(new Breadcrumb { Name = Constants.Pages.Matches, Url = new Uri(Constants.Pages.MatchesUrl, UriKind.Relative) }); } model.Breadcrumbs.Add(new Breadcrumb { Name = model.Match.MatchName, Url = new Uri(model.Match.MatchRoute, UriKind.Relative) }); return(View("EditMatchFormat", model)); }