Beispiel #1
0
        protected static void AppendDateFilter(DateTimeOffset?fromDate, DateTimeOffset?untilDate, StringBuilder description, IDateTimeFormatter dateTimeFormatter)
        {
            if (dateTimeFormatter is null)
            {
                throw new ArgumentNullException(nameof(dateTimeFormatter));
            }

            if (description is null)
            {
                throw new ArgumentNullException(nameof(description));
            }

            if (fromDate.HasValue)
            {
                description.Append(" from ").Append(dateTimeFormatter.FormatDate(fromDate.Value, false, true, false));
                if (!untilDate.HasValue)
                {
                    description.Append(" onwards");
                }
            }
            if (untilDate.HasValue)
            {
                description.Append(" up to ").Append(dateTimeFormatter.FormatDate(untilDate.Value, false, true, false));
            }
        }
Beispiel #2
0
        public ActionResult ConferenceDate()
        {
            var    conference     = calendarItemRepository.GetFromType(CalendarEntryType.Conference);
            string conferenceDate = dateTimeFormatter.FormatDate(conference.StartDate);

            return(new ContentResult {
                Content = conferenceDate
            });
        }
Beispiel #3
0
        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 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 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));
            }
        }
Beispiel #7
0
        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
            {
                // By filtering for all match types it excludes seasons for annual tournaments like Expo and Seaford, which may support training sessions
                // but otherwise no match types. Although those tournaments can be listed in other seasons (they're of interest to the league teams), we
                // don't want other tournaments listed on pages which are supposed to be just about those annual tournaments. For any tournaments which
                // actually are meant to be in those seasons, they will be added back when the tournament's current seasons are added to the list.
                var seasonDates = _seasonEstimator.EstimateSeasonDates(model.Tournament.StartTime);

                var filter = new CompetitionFilter
                {
                    FromYear    = seasonDates.fromDate.Year,
                    UntilYear   = seasonDates.untilDate.Year,
                    PlayerTypes = new List <PlayerType> {
                        model.Tournament.PlayerType
                    },
                    MatchTypes = new List <MatchType> {
                        MatchType.FriendlyMatch, MatchType.KnockoutMatch, MatchType.LeagueMatch
                    },
                    EnableTournaments = true
                };
                model.PossibleSeasons.AddRange(await _seasonDataSource.ReadSeasons(filter).ConfigureAwait(false));
                foreach (var season in model.Tournament.Seasons)
                {
                    if (!model.PossibleSeasons.Select(x => x.SeasonId.Value).Contains(season.SeasonId.Value))
                    {
                        model.PossibleSeasons.Add(season);
                    }
                }
                model.PossibleSeasons.Sort(new SeasonComparer());

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

                model.TournamentDate     = model.Tournament.StartTime;
                model.Metadata.PageTitle = "Where to list " + 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));
            }
        }
Beispiel #8
0
        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));
            }
        }
Beispiel #9
0
        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 Task <ActionResult> UpdateTeams([Bind(Prefix = "Tournament", Include = "MaximumTeamsInTournament,Teams")] Tournament postedTournament)
        {
            if (postedTournament is null)
            {
                throw new ArgumentNullException(nameof(postedTournament));
            }

            var beforeUpdate = await _tournamentDataSource.ReadTournamentByRoute(Request.RawUrl).ConfigureAwait(false);

            var model = new EditTournamentViewModel(CurrentPage, Services.UserService)
            {
                Tournament    = beforeUpdate,
                DateFormatter = _dateTimeFormatter
            };

            model.Tournament.MaximumTeamsInTournament = postedTournament.MaximumTeamsInTournament;
            model.Tournament.Teams = postedTournament.Teams;

            // We're not interested in validating other details of the tournament or the selected teams
            foreach (var key in ModelState.Keys.Where(x => x != "Tournament.MaximumTeamsInTournament"))
            {
                ModelState[key].Errors.Clear();
            }

            model.IsAuthorized = _authorizationPolicy.IsAuthorized(beforeUpdate);

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

                await _cacheClearer.ClearCacheFor(updatedTournament).ConfigureAwait(false);

                return(_postSaveRedirector.WorkOutRedirect(model.Tournament.TournamentRoute, updatedTournament.TournamentRoute, "/edit", Request.Form["UrlReferrer"], null));
            }

            model.Metadata.PageTitle = "Teams in the " + model.Tournament.TournamentFullName(x => _dateTimeFormatter.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(View("EditTournamentTeams", model));
        }
Beispiel #11
0
        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> UpdateMatches([Bind(Prefix = "Tournament", Include = "Matches")] Tournament postedTournament)
        {
            var beforeUpdate = await _tournamentDataSource.ReadTournamentByRoute(Request.RawUrl).ConfigureAwait(false);

            var model = new EditTournamentViewModel(CurrentPage, Services.UserService)
            {
                Tournament    = beforeUpdate,
                DateFormatter = _dateTimeFormatter
            };

            model.Tournament.Matches = postedTournament?.Matches ?? new List <MatchInTournament>();

            // We're not interested in validating anything with a data annotation attribute
            foreach (var key in ModelState.Keys)
            {
                ModelState[key].Errors.Clear();
            }

            var teamsInTournament = model.Tournament.Teams.Select(x => x.TournamentTeamId.Value);

            foreach (var added in model.Tournament.Matches.Where(x => !x.MatchId.HasValue))
            {
                if (added.Teams.Count < 2 || !added.Teams[0].TournamentTeamId.HasValue || !added.Teams[1].TournamentTeamId.HasValue || added.Teams[0].TournamentTeamId == added.Teams[1].TournamentTeamId)
                {
                    ModelState.AddModelError(string.Empty, $"Please remove '{added.MatchName}'. A match must be between two different teams.");
                }

                // Check for a TournamentTeamId that's not in the tournament. Pretty unlikely since it would require editing the request or a race where
                // the team is removed before this page is submitted, but since we can test we should.
                if (ModelState.IsValid)
                {
                    foreach (var team in added.Teams)
                    {
                        if (!teamsInTournament.Contains(team.TournamentTeamId.Value))
                        {
                            ModelState.AddModelError(string.Empty, $"Please remove '{added.MatchName}'. We cannot add a match for a team that's not in the tournament.");
                        }
                    }
                }
            }

            model.IsAuthorized = _authorizationPolicy.IsAuthorized(beforeUpdate);

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

                await _cacheClearer.ClearCacheFor(updatedTournament).ConfigureAwait(false);

                // Use a regex to prevent part 4 of the journey Edit Matches > Edit Teams > Edit Matches > Edit Teams
                return(_postSaveRedirector.WorkOutRedirect(model.Tournament.TournamentRoute, updatedTournament.TournamentRoute, "/edit", Request.Form["UrlReferrer"], $"^({updatedTournament.TournamentRoute}|{updatedTournament.TournamentRoute}/edit)$"));
            }

            model.Metadata.PageTitle = "Matches in the " + model.Tournament.TournamentFullName(x => _dateTimeFormatter.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(View("EditTournamentMatches", 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));
        }
Beispiel #14
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));
            }
        }
        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));
            }
        }
Beispiel #16
0
        public string FormatDate(DateTime moment) =>

        _dateTimeFormatter.FormatDate(Locale, moment);
Beispiel #17
0
        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 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));
            }
        }
Beispiel #19
0
        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 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));
            }
        }
Beispiel #22
0
        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
            };

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

                model.TournamentDate = model.Tournament.StartTime;
                if (model.Tournament.StartTimeIsKnown)
                {
                    model.StartTime = model.Tournament.StartTime;
                }
                model.TournamentLocationId   = model.Tournament.TournamentLocation?.MatchLocationId;
                model.TournamentLocationName = model.Tournament.TournamentLocation?.NameAndLocalityOrTownIfDifferent();
                if (!model.Tournament.DefaultOverSets.Any())
                {
                    model.Tournament.DefaultOverSets.Add(new OverSet());
                }

                model.Metadata.PageTitle = "Edit " + 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 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));
        }
Beispiel #24
0
        public async Task <ActionResult> UpdateTournament([Bind(Prefix = "Tournament", Include = "TournamentName,QualificationType,PlayerType,PlayersPerTeam,DefaultOverSets")] Tournament postedTournament)
        {
            if (postedTournament is null)
            {
                throw new ArgumentNullException(nameof(postedTournament));
            }

            var beforeUpdate = await _tournamentDataSource.ReadTournamentByRoute(Request.RawUrl).ConfigureAwait(false);

            postedTournament.DefaultOverSets.RemoveAll(x => !x.Overs.HasValue);
            var model = new EditTournamentViewModel(CurrentPage, Services.UserService)
            {
                Tournament    = beforeUpdate,
                DateFormatter = _dateTimeFormatter
            };

            model.Tournament.TournamentName    = postedTournament.TournamentName;
            model.Tournament.QualificationType = postedTournament.QualificationType;
            model.Tournament.PlayerType        = postedTournament.PlayerType;
            model.Tournament.PlayersPerTeam    = postedTournament.PlayersPerTeam;
            model.Tournament.DefaultOverSets   = postedTournament.DefaultOverSets;

            // get this from the unvalidated form instead of via modelbinding so that HTML can be allowed
            model.Tournament.TournamentNotes = Request.Unvalidated.Form["Tournament.TournamentNotes"];

            if (!string.IsNullOrEmpty(Request.Form["TournamentDate"]) && DateTimeOffset.TryParse(Request.Form["TournamentDate"], out var parsedDate))
            {
                model.TournamentDate       = parsedDate;
                model.Tournament.StartTime = model.TournamentDate.Value;

                if (!string.IsNullOrEmpty(Request.Form["StartTime"]))
                {
                    if (DateTimeOffset.TryParse(Request.Form["StartTime"], out var parsedTime))
                    {
                        model.StartTime                   = parsedTime;
                        model.Tournament.StartTime        = model.Tournament.StartTime.Add(model.StartTime.Value.TimeOfDay);
                        model.Tournament.StartTimeIsKnown = true;
                    }
                    else
                    {
                        // This may be seen in browsers that don't support <input type="time" />, mainly Safari.
                        // Each browser that supports <input type="time" /> may have a very different interface so don't advertise
                        // this format up-front as it could confuse the majority. Instead, only reveal it here.
                        ModelState.AddModelError("StartTime", "Enter a time in 24-hour HH:MM format.");
                    }
                }
                else
                {
                    // If no start time specified, use a typical one but don't show it
                    model.Tournament.StartTime.AddHours(11);
                    model.Tournament.StartTimeIsKnown = false;
                }
            }
            else
            {
                // This may be seen in browsers that don't support <input type="date" />, mainly Safari.
                // This is the format <input type="date" /> expects and posts, so we have to repopulate the field in this format,
                // so although this code _can_ parse other formats we don't advertise that. We also don't want YYYY-MM-DD in
                // the field label as it would confuse the majority, so only reveal it here.
                ModelState.AddModelError("TournamentDate", "Enter a date in YYYY-MM-DD format.");
            }

            _matchValidator.DateIsValidForSqlServer(() => model.TournamentDate, ModelState, "TournamentDate", "tournament");
            _matchValidator.DateIsWithinTheSeason(() => model.TournamentDate, model.Tournament.Seasons.FirstOrDefault(), ModelState, "TournamentDate", "tournament");

            if (!string.IsNullOrEmpty(Request.Form["TournamentLocationId"]))
            {
                model.TournamentLocationId          = new Guid(Request.Form["TournamentLocationId"]);
                model.TournamentLocationName        = Request.Form["TournamentLocationName"];
                model.Tournament.TournamentLocation = new MatchLocation
                {
                    MatchLocationId = model.TournamentLocationId
                };
            }

            model.IsAuthorized = _authorizationPolicy.IsAuthorized(beforeUpdate);

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

                await _cacheClearer.ClearCacheFor(updatedTournament).ConfigureAwait(false);

                // Redirect to the tournament
                return(Redirect(updatedTournament.TournamentRoute));
            }

            model.Metadata.PageTitle = "Edit " + model.Tournament.TournamentFullName(x => _dateTimeFormatter.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(View("EditTournament", 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));
        }
        public async override Task <ActionResult> Index(ContentModel contentModel)
        {
            if (contentModel is null)
            {
                throw new System.ArgumentNullException(nameof(contentModel));
            }

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

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

                model.Metadata.PageTitle = 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 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));
            }
        }
Beispiel #30
0
        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));
            }
        }