public async Task <ActionResult <Match> > AddMatchAsync(CreateMatchDto createMatchDto)
        {
            var match = _mapper.Map <CreateMatchDto, Match>(createMatchDto);

            _matchRepo.Add(match);
            await _matchRepo.SaveChagesAsync();

            return(CreatedAtRoute(nameof(GetMatchById), new { match.Id }, match));
        }
        public ActionResult Create([Bind(Include = "MatchID,City,Date,Result")] Match match)
        {
            if (ModelState.IsValid)
            {
                _matchRepository.Add(match);
                _matchRepository.Save();
                return(RedirectToAction("Index"));
            }

            return(View(match));
        }
        public IActionResult Create(int hostId, int guestId, string matchDate, string matchPlace, int[] hostPlayerIDs, int[] guestPlayerIDs)
        {
            int    minPlayers    = 6;
            Status defaultStatus = _matchRepository.DefaultStatus();
            // Validate date
            DateTime date;

            if (!DateTime.TryParse(matchDate, out date) || DateTime.Compare(DateTime.Today.Date, date.Date) > 0)
            {
                return(Json(false));
            }
            // Validate other fields
            if (hostId == guestId || hostPlayerIDs.Count() != guestPlayerIDs.Count() || hostPlayerIDs.Count() < minPlayers || guestPlayerIDs.Count() < minPlayers || matchPlace == null || matchPlace.Length == 0)
            {
                return(Json(false));
            }
            // Create new match
            Match newMatch = new Match()
            {
                HostTeamId  = hostId,
                GuestTeamId = guestId,
                HostScore   = 0,
                GuestScore  = 0,
                Date        = date,
                Place       = matchPlace,
                StatusId    = defaultStatus.Id
            };

            _matchRepository.Add(newMatch);
            _matchRepository.Save();
            // Add host players
            foreach (int hostPlayerId in hostPlayerIDs)
            {
                MatchPlayer playerOnMatch = new MatchPlayer()
                {
                    MatchId  = newMatch.Id,
                    PlayerId = hostPlayerId
                };
                _matchRepository.AddMatchPlayer(playerOnMatch);
            }
            // Add guest players
            foreach (int guestPlayerId in guestPlayerIDs)
            {
                MatchPlayer playerOnMatch = new MatchPlayer()
                {
                    MatchId  = newMatch.Id,
                    PlayerId = guestPlayerId
                };
                _matchRepository.AddMatchPlayer(playerOnMatch);
            }
            _matchRepository.Save();

            return(Json(true));
        }
Example #4
0
        public async Task <IActionResult> Create([Bind("Id,Versus,MachType,DateOfMatch,TeamId")] Match match)
        {
            if (ModelState.IsValid)
            {
                repository.Add(match);
                await repository.SaveAsync();

                return(RedirectToAction(nameof(Index)));
            }
            ViewData["TeamId"] = new SelectList(team.GetAll(), "Id", "TeamType", match.TeamId);
            return(View(match));
        }
        public async Task <MatchResource> CreateMatch([FromBody] MatchResource matchResource)
        {
            // if (!ModelState.IsValid)
            //     return BadRequest(ModelState);

            var match = _mapper.Map <MatchResource, Match>(matchResource);

            _repository.Add(match);
            await _unitOfWork.CompleteAsync();

            match = await _repository.GetMatch(match.Id);

            var result = _mapper.Map <Match, MatchResource>(match);

            return(result);
        }
Example #6
0
        public void UpdateMatch(Int32 summaryId, Int32 vacancyId)
        {
            Match match = _matchRepository.GetAllForSummary(summaryId).FirstOrDefault(m => m.Vacancy.Id == vacancyId);

            if (match is null)
            {
                var summary = _summaryRepository.Get(summaryId);
                var vacancy = _vacancyRepository.Get(vacancyId);
                _matchRepository.Add(new Match(summary, vacancy));
            }
            else
            {
                match.Update();
                _matchRepository.Update(match);
            }
        }
Example #7
0
        public ActionResult Create(MatchViewModel vmMatch)
        {
            if (ModelState.IsValid)
            {
                var matchToAdd = vmMatch.ToDataModel();

                _matchRepository.Add(matchToAdd);

                AlertSuccess("Match created", "New match added.");

                return(RedirectToAction("Index"));
            }

            AlertModelStateErrors();

            return(RedirectToAction("Index"));
        }
Example #8
0
        private void StartTournament(Tournament tournament)
        {
            var        rnd       = new Random();
            List <int> playerIds = tournament.Players.OrderBy(p => rnd.Next()).Select(p => p.Id).ToList();

            for (int i = 0; i < playerIds.Count() / 2; i++)
            {
                Match match = _matchRepository.Add(new Match(tournament.Id, 1));
                _matchupRepository.Add(new Matchup {
                    Match = match, PlayerId = playerIds[i]
                });
                _matchupRepository.Add(new Matchup {
                    Match = match, PlayerId = playerIds[playerIds.Count() / 2 + i]
                });
            }

            _unitOfWork.Commit();
        }
        public IActionResult AddMatchToTournament(TournamentDTO dto)
        {
            var selectedTournament = _tournamentRepository.GetById(dto.TournamentId);

            User p1 = _userRepository.GetById(dto.Player1Id);

            p1.HasChallenge = true;
            User p2 = _userRepository.GetById(dto.Player2Id);

            p2.HasChallenge = true;

            Match m = new Match(p1, p2);

            selectedTournament.AddMatch(m);

            _matchRepository.Add(m);
            _tournamentRepository.SaveChanges();

            addPendingMatchToUsers(p1, p2);

            return(NoContent());
        }
        public async Task <T> Save <T>(IMatchCreateDomainModel model) where T : IMatchDomainModel, new()
        {
            var entity = new MatchEntity();

            if (model.Id != 0)
            {
                entity = await matchRepository.GetByIdAsync(model.Id);
            }

            Mapper.Map(model, entity);
            if (entity.Id != 0)
            {
                matchRepository.Edit(entity);
            }
            else
            {
                matchRepository.Add(entity);
            }

            _unitOfWork.CommitChanges();
            var response = await Get <T>(entity.Id);

            return(response);
        }
        public async Task <IActionResult> AddMatch(MatchForCreateDto match)
        {
            if (match.TeamAId == match.TeamBId)
            {
                return(BadRequest("You picked the same team twice."));
            }

            if (await teamRepository.Exists(match.TeamAId) && await teamRepository.Exists(match.TeamBId))
            {
                var matchToCreate = mapper.Map <Match>(match);
                matchToCreate.TeamA = await teamRepository.GetTeam(match.TeamAId);

                matchToCreate.TeamB = await teamRepository.GetTeam(match.TeamBId);

                matchRepository.Add(matchToCreate);

                if (await dataContext.Commit())
                {
                    return(CreatedAtRoute("GetMatch", new { id = matchToCreate.Id }, matchToCreate));
                }
            }

            return(BadRequest("Could not add match."));
        }
        public async Task GenerateScheduleAsync(GeneratorScheduleOutlines outlines)
        {
            var matches =
                await matchRepository.FindAsync(m => m.HomeTeam.TournamentId == outlines.TournamentId && m.GuestTeam.TournamentId == outlines.TournamentId);

            foreach (var match in matches)
            {
                matchRepository.Delete(match);
            }

            var possibleMatchDateTimes = await scheduleGeneratorManager.GetPossibleMatchDateTimesAsync(outlines);

            if (!possibleMatchDateTimes.Any())
            {
                throw new ArgumentOutOfRangeException();
            }

            var teams = await teamRepository.FindAsync(t => t.TournamentId == outlines.TournamentId);

            if (teams.Count < 2)
            {
                throw new NotFoundInDatabaseException();
            }

            var matchDict = await scheduleGeneratorManager.GetPossibleMatchMatrix(teams.ToList());

            var tournament = await tournamentRepository.FindSingleAsync(t => t.TournamentId == outlines.TournamentId);

            var generatedMatchesList =
                await scheduleGeneratorManager.GenerateSchedule(tournament.IsBracket, possibleMatchDateTimes,
                                                                matchDict);

            generatedMatchesList.ForEach(gm => matchRepository.Add(gm));

            await unitOfWork.CompleteAsync();
        }
Example #13
0
 public async Task CreateAsync(Match match)
 {
     _matchRepository.Add(match);
     await _unitOfWork.CompleteAsync();
 }
Example #14
0
 public void Add(Match entity)
 {
     _matchRepository.Add(entity);
 }
Example #15
0
        public async Task AddMatch(Match match)
        {
            match.MatchResult = GetMatchResult(match);

            Tournament tournament = await _tournamentRepository.Get(match.TournamentID);

            Team team1 = await _teamRepository.Get(match.Team1ID);

            Team team2 = await _teamRepository.Get(match.Team2ID);

            #region Update Team Stats
            var team1Stat = _teamStatRepository.GetOrCreateByTeam(match.Team1ID);
            var team2Stat = _teamStatRepository.GetOrCreateByTeam(match.Team2ID);

            CompleteTeamsStat(match, ref team1Stat, ref team2Stat);

            _teamStatRepository.Update(team1Stat);
            _teamStatRepository.Update(team2Stat);

            if (tournament.TournamentType.Format == TournamentFormat.WorldCup)
            {
                var team1StatWorldCup = _teamStatWorldCupRepository.GetOrCreateByTeam(match.Team1ID);
                var team2StatWorldCup = _teamStatWorldCupRepository.GetOrCreateByTeam(match.Team2ID);

                CompleteTeamsStatWorldCup(match, ref team1StatWorldCup, ref team2StatWorldCup);

                _teamStatWorldCupRepository.Update(team1StatWorldCup);
                _teamStatWorldCupRepository.Update(team2StatWorldCup);
            }
            #endregion

            #region Update Head 2 Head
            var h2hTeam1 = _h2hRepository.GetOrCreateByTeams(match.Team1ID, match.Team2ID);
            var h2hTeam2 = _h2hRepository.GetOrCreateByTeams(match.Team2ID, match.Team1ID);

            CompleteH2H(match, ref h2hTeam1, ref h2hTeam2);

            _h2hRepository.Update(h2hTeam1);
            _h2hRepository.Update(h2hTeam2);

            if (tournament.TournamentType.Format == TournamentFormat.WorldCup)
            {
                var h2hTeam1WorldCup = _h2hWorldCupRepository.GetOrCreateByTeams(match.Team1ID, match.Team2ID);
                var h2hTeam2WorldCup = _h2hWorldCupRepository.GetOrCreateByTeams(match.Team2ID, match.Team1ID);

                CompleteH2HWorldCup(match, ref h2hTeam1WorldCup, ref h2hTeam2WorldCup);

                _h2hWorldCupRepository.Update(h2hTeam1WorldCup);
                _h2hWorldCupRepository.Update(h2hTeam2WorldCup);
            }
            #endregion

            #region Update Rankings
            var regionalWeight = GetRegionalWeight(team1.Confederation.Weight, team2.Confederation.Weight);
            var team1Points    = GetTeamPoints(GetTeamResult(match, 1), regionalWeight, CalculateOposition(team2.ActualRank), tournament.TournamentType.MatchType.Weight);
            var team2Points    = GetTeamPoints(GetTeamResult(match, 2), regionalWeight, CalculateOposition(team1.ActualRank), tournament.TournamentType.MatchType.Weight);

            Domain.Ranking ranking1 = await _rankingRepository.GetActual(match.Team1ID);

            ranking1.Points += team1Points;
            _rankingRepository.Update(ranking1);

            Domain.Ranking ranking2 = await _rankingRepository.GetActual(match.Team2ID);

            ranking2.Points += team2Points;
            _rankingRepository.Update(ranking2);

            team1.TotalPoints += team1Points;
            _teamRepository.Update(team1);

            team2.TotalPoints += team2Points;
            _teamRepository.Update(team2);
            #endregion

            #region Update Goalscorers
            var matchGoalscorers = match.Team1Goalscorers.Union(match.Team2Goalscorers);
            foreach (Goalscorer matchGoalscorer in matchGoalscorers)
            {
                var goalscorer = await GetOrCreateGoalscorer(matchGoalscorer.PlayerID, match.TournamentID);

                goalscorer.PlayerID     = matchGoalscorer.PlayerID;
                goalscorer.TournamentID = match.TournamentID;
                goalscorer.Goals       += matchGoalscorer.Goals;

                if (goalscorer.Id == 0)
                {
                    await _goalscorerRepository.Add(goalscorer);
                }
                else
                {
                    _goalscorerRepository.Update(goalscorer);
                }

                var player = await _playerRepository.Get(matchGoalscorer.PlayerID);

                switch (tournament.TournamentType.Format)
                {
                case TournamentFormat.Qualification:
                    player.QualificationGoals += matchGoalscorer.Goals;
                    break;

                case TournamentFormat.WorldCup:
                    player.WorldCupGoals += matchGoalscorer.Goals;
                    break;

                case TournamentFormat.ConfederationsCup:
                    player.ConfederationsGoals += matchGoalscorer.Goals;
                    break;

                case TournamentFormat.ConfederationTournament:
                    player.ConfederationTournamentGoals += matchGoalscorer.Goals;
                    break;
                }

                _playerRepository.Update(player);
            }
            #endregion

            await _matchRepository.Add(match);

            await _teamRepository.SaveChanges();
        }
        private async Task <bool> SaveMatch(MatchLink matchLink)
        {
            var htmlWeb = new HtmlWeb();
            var htmlDoc = await htmlWeb.LoadFromWebAsync(matchLink.Link);

            var articleNode = htmlDoc.DocumentNode.Descendants("article").FirstOrDefault();

            var iframeNode = articleNode?.Descendants("iframe");

            var ulNodes = articleNode?.Descendants("ul");

            var divNodes = articleNode?.Descendants("div");

            var divVcRow = divNodes?.FirstOrDefault(x =>
                                                    x.Attributes.Contains("class") && x.Attributes["class"].Value == "vc_row wpb_row td-pb-row");

            var divWpbWrapper =
                divVcRow?.Descendants("div")?.LastOrDefault(x => x.Attributes.Contains("class") && x.Attributes["class"].Value == "wpb_wrapper");

            if (divWpbWrapper == null || !iframeNode.Any())
            {
                return(false);
            }

            var clips = new List <Clip>();

            clips.AddRange(iframeNode.Where(x => x.Attributes.Contains("data-lazy-src")).Select((x, i) => new Clip
            {
                Url      = x.Attributes["data-lazy-src"].Value,
                ClipType = ClipType.HighLight,
                LinkType = LinkType.Embed,
                Name     = "Server " + (i + 1)
            }));

            if (!clips.Any())
            {
                return(false);
            }

            var match = new Match();

            match.Slug  = matchLink.Slug;
            match.Title = matchLink.Name;

            var ftpResult = await _ftpHelper.RemoteFiles(matchLink.ImageLink, match.Slug);

            if (ftpResult != null)
            {
                match.ImageName     = ftpResult.FileName;
                match.ImageServerId = ftpResult.ServerId;
            }

            foreach (var childNode in divWpbWrapper.ChildNodes)
            {
                if (childNode.PreviousSibling == null)
                {
                    continue;
                }

                if (childNode.PreviousSibling.InnerText.Contains("Competition"))
                {
                    match.Competition = childNode.InnerText;
                }

                if (childNode.PreviousSibling.InnerText.Contains("Date"))
                {
                    match.MatchDate = childNode.InnerText.ToDate();
                }

                if (childNode.PreviousSibling.InnerText.Contains("Stadium"))
                {
                    match.Stadium = childNode.InnerText;
                }

                if (childNode.PreviousSibling.InnerText.Contains("Referee"))
                {
                    match.Referee = childNode.InnerText;
                }
            }

            if (match.MatchDate == null)
            {
                match.MatchDate = matchLink.RDateTime;
            }

            var divHeaderTeam1 = divNodes.FirstOrDefault(x => x.Attributes.Contains("class") && x.Attributes["class"].Value == "headerteam1");

            if (divHeaderTeam1 != null)
            {
                match.Home = string.Empty;
                foreach (var h2 in divHeaderTeam1.Descendants("h2"))
                {
                    match.Home += " " + h2.InnerText;
                }
                match.Home = match.Home.Trim();

                foreach (var node in divHeaderTeam1.Descendants("div"))
                {
                    match.HomePersonScored = string.IsNullOrWhiteSpace(match.HomePersonScored)
                        ? node.InnerText
                        : ("|" + node.InnerText);
                }
            }
            else
            {
                //td-tags td-post-small-box clearfix
                var tagNode = ulNodes?.FirstOrDefault(x =>
                                                      x.Attributes.Contains("class") &&
                                                      x.Attributes["class"].Value.Contains("td-tags") &&
                                                      x.Attributes["class"].Value.Contains("td-post-small-box"));

                if (tagNode != null)
                {
                    match.Home = tagNode.ChildNodes[1].ChildNodes[0].InnerText;
                }
            }

            var divHeaderTeam2 = divNodes.FirstOrDefault(x => x.Attributes.Contains("class") && x.Attributes["class"].Value == "headerteam2");

            if (divHeaderTeam2 != null)
            {
                match.Away = string.Empty;
                foreach (var h2 in divHeaderTeam2.Descendants("h2"))
                {
                    match.Away += " " + h2.InnerText;
                }
                match.Away = match.Away.Trim();

                if (divHeaderTeam2.ChildNodes.Count > 1)
                {
                    foreach (var node in divHeaderTeam2.Descendants("div"))
                    {
                        match.AwayPersonScored = string.IsNullOrWhiteSpace(match.AwayPersonScored) ? node.InnerText : ("|" + node.InnerText);
                    }
                }
            }
            else
            {
                //td-tags td-post-small-box clearfix
                var tagNode = ulNodes?.FirstOrDefault(x =>
                                                      x.Attributes.Contains("class") &&
                                                      x.Attributes["class"].Value.Contains("td-tags") &&
                                                      x.Attributes["class"].Value.Contains("td-post-small-box"));

                if (tagNode != null)
                {
                    match.Away = tagNode.ChildNodes[2].ChildNodes[0].InnerText;
                }
            }

            var divScore = divNodes.FirstOrDefault(x => x.Attributes.Contains("class") && x.Attributes["class"].Value == "score");

            if (divScore != null)
            {
                match.Score = $"{divScore.ChildNodes[0].InnerText} : {divScore.ChildNodes[2].InnerText}";
            }

            var divTeam1Roster = ulNodes?.FirstOrDefault(x => x.Attributes.Contains("class") && x.Attributes["class"].Value == "team1roster");
            var formations     = new List <Formation>();

            if (divTeam1Roster != null)
            {
                match.HomeManager = divTeam1Roster.ChildNodes[1].InnerText;
                formations.AddRange(divTeam1Roster.Descendants("li")
                                    .Select(liNode => new Formation
                {
                    Type           = FormationType.Home,
                    Number         = liNode.ChildNodes[0].InnerText.ToInt(),
                    Name           = liNode.ChildNodes[1].InnerText,
                    IsSubstitution = liNode.Attributes.Contains("class") && liNode.Attributes["class"].Value == "issub"
                }));
            }
            var divTeam2Roster = ulNodes?.FirstOrDefault(x => x.Attributes.Contains("class") && x.Attributes["class"].Value == "team2roster");

            if (divTeam2Roster != null)
            {
                match.HomeManager = divTeam2Roster.ChildNodes[1].InnerText;
                formations.AddRange(divTeam2Roster.Descendants("li")
                                    .Select(liNode => new Formation
                {
                    Type           = FormationType.Home,
                    Number         = liNode.ChildNodes[0].InnerText.ToInt(),
                    Name           = liNode.ChildNodes[1].InnerText,
                    IsSubstitution = liNode.Attributes.Contains("class") && liNode.Attributes["class"].Value == "issub"
                }));
            }

            var substitutions = new List <Substitution>();
            var divTeam1Subs  = ulNodes?.FirstOrDefault(x => x.Attributes.Contains("class") && x.Attributes["class"].Value == "team1subs");

            if (divTeam1Subs != null)
            {
                substitutions.AddRange(divTeam1Subs.Descendants("li")
                                       .Select(liNode => new Substitution
                {
                    Type   = FormationType.Home,
                    Number = liNode.ChildNodes[0].InnerText.ToInt(),
                    Name   = liNode.ChildNodes[1].InnerText
                }));
            }
            var divTeam2Subs = ulNodes?.FirstOrDefault(x => x.Attributes.Contains("class") && x.Attributes["class"].Value == "team2subs");

            if (divTeam2Subs != null)
            {
                substitutions.AddRange(divTeam2Subs.Descendants("li")
                                       .Select(liNode => new Substitution
                {
                    Type   = FormationType.Home,
                    Number = liNode.ChildNodes[0].InnerText.ToInt(),
                    Name   = liNode.ChildNodes[1].InnerText
                }));
            }

            var actionSubstitutions = new List <ActionSubstitution>();

            var divteam1Actualsubs = ulNodes?.FirstOrDefault(x =>
                                                             x.Attributes.Contains("class") && x.Attributes["class"].Value == "team1actualsubs");

            if (divteam1Actualsubs != null)
            {
                actionSubstitutions.AddRange(divteam1Actualsubs.Descendants("li")
                                             .Select(x => new ActionSubstitution
                {
                    Min  = x.ChildNodes[0].InnerText,
                    In   = x.ChildNodes[1].ChildNodes[0].InnerText,
                    Out  = x.ChildNodes[1].ChildNodes[2].InnerText,
                    Type = FormationType.Home
                }));
            }

            var divteam2Actualsubs = ulNodes?.FirstOrDefault(x =>
                                                             x.Attributes.Contains("class") && x.Attributes["class"].Value == "team2actualsubs");

            if (divteam2Actualsubs != null)
            {
                actionSubstitutions.AddRange(divteam2Actualsubs.Descendants("li")
                                             .Select(x => new ActionSubstitution
                {
                    Min  = x.ChildNodes[0].InnerText,
                    In   = x.ChildNodes[1].ChildNodes[0].InnerText,
                    Out  = x.ChildNodes[1].ChildNodes[2].InnerText,
                    Type = FormationType.Away
                }));
            }


            await _matchRepository.Add(match, clips, formations, substitutions, actionSubstitutions);

            return(true);
        }
Example #17
0
 public void Post([FromBody] TheMatch.Domain.Match value)
 {
     _matchRepository.Add(value);
 }
Example #18
0
 public async Task AddAndSave(Match Match)
 {
     _Matchs.Add(Match);
     await _Matchs.Save();
 }
        public async Task AddNewMatchAsync(Match match, bool autoGenerated = false)
        {
            if (!autoGenerated)
            {
                var teamA = await teamRepository.FindSingleAsync(x => x.TeamId == match.HomeTeamId);

                var teamB = await teamRepository.FindSingleAsync(y => y.TeamId == match.GuestTeamId);

                if (teamA == null ||
                    teamB == null)
                {
                    throw new NotFoundInDatabaseException();
                }

                var matches = await matchRepository.FindAsync(m => m.MatchDateTime == match.MatchDateTime);

                var isAnyTeamAlreadyPlaying = matches.Select(y => new[] { y.HomeTeamId, y.GuestTeamId }).Any(o => o.Contains(match.HomeTeamId) || o.Contains(match.GuestTeamId));

                if (isAnyTeamAlreadyPlaying)
                {
                    throw new AlreadyInDatabaseException();
                }

                if (teamA.TournamentId != teamB.TournamentId)
                {
                    throw new ArgumentException();
                }

                var tournament = await tournamentRepository.FindSingleAsync(t => t.TournamentId == teamA.TournamentId);

                if (tournament.IsBracket)
                {
                    if (match.IsFinished && (match.GuestTeamPoints == match.HomeTeamPoints))
                    {
                        throw new AmbiguousMatchException();
                    }

                    var matchesBracket =
                        await matchRepository.FindAsync(m =>
                                                        m.HomeTeam.TournamentId == tournament.TournamentId &&
                                                        m.GuestTeam.TournamentId == tournament.TournamentId);

                    var isTeamAlreadyPlayingInBracket = matchesBracket.Select(y => new[] { y.HomeTeamId, y.GuestTeamId }).Any(o => o.Contains(match.HomeTeamId) || o.Contains(match.GuestTeamId));

                    if (isTeamAlreadyPlayingInBracket)
                    {
                        throw new ConstraintException();
                    }

                    if (matchesBracket.Count(m => m.BracketIndex <= tournament.AmountOfTeams / 2) == tournament.AmountOfTeams / 2)
                    {
                        throw new ArgumentOutOfRangeException();
                    }

                    int bracketIndexForMatch = await bracketManager.FindFirstEmptyBracketSlotAsync(matchesBracket, tournament.AmountOfTeams);

                    match.BracketIndex = bracketIndexForMatch;
                }
            }

            matchRepository.Add(match);
            await unitOfWork.CompleteAsync();
        }
Example #20
0
        public async Task Add(Match match)
        {
            await _matchRepository.Add(match);

            await _matchRepository.SaveChanges();
        }
Example #21
0
        private async Task <bool> SaveMatch(MatchLink matchLink)
        {
            try
            {
                var htmlDoc = _htmlWeb.Load(matchLink.Link);

                var articleNode = htmlDoc.DocumentNode.Descendants("article").FirstOrDefault();

                var iframeNode = articleNode?.Descendants("iframe");

                var ulNodes = articleNode?.Descendants("ul");

                var divNodes = articleNode?.Descendants("div");

                var inputNodes = articleNode?.Descendants("input");

                var divVcRow = divNodes?.FirstOrDefault(x =>
                                                        x.Attributes.Contains("class") &&
                                                        x.Attributes["class"].Value.Contains("vc_row") &&
                                                        x.Attributes["class"].Value.Contains("wpb_row") &&
                                                        x.Attributes["class"].Value.Contains("td-pb-row"));

                var divWpbWrapper =
                    divVcRow?.Descendants("div")?.FirstOrDefault(
                        x => x.Attributes.Contains("class") && x.Attributes["class"].Value == "wpb_wrapper" &&
                        x.InnerText.Contains("Competition") &&
                        x.InnerText.Contains("Date") &&
                        x.InnerText.Contains("Stadium"));

                if (divWpbWrapper == null)
                {
                    divWpbWrapper = divNodes?.FirstOrDefault(x =>
                                                             x.Attributes.Contains("class") &&
                                                             x.Attributes["class"].Value == "td-post-content" &&
                                                             x.InnerText.Contains("Competition") &&
                                                             x.InnerText.Contains("Date") &&
                                                             x.InnerText.Contains("Stadium"));
                }

                if (divWpbWrapper == null || !iframeNode.Any())
                {
                    return(false);
                }

                var acpPost = inputNodes?.FirstOrDefault(
                    x => x.Attributes.Contains("id") &&
                    x.Attributes.Contains("value") &&
                    x.Attributes["id"].Value == "acp_post")?.Attributes["value"]?.Value;

                var acpShortcode = inputNodes?.FirstOrDefault(
                    x => x.Attributes.Contains("id") &&
                    x.Attributes.Contains("value") &&
                    x.Attributes["id"].Value == "acp_shortcode")?.Attributes["value"]?.Value;

                var clips = GetMatchClip(acpPost, acpShortcode);

                if (clips == null || !clips.Any())
                {
                    clips = iframeNode.Where(x =>
                                             x.Attributes.Contains("src") &&
                                             !x.Attributes["src"].Value.Contains("facebook.com"))
                            .Select((x, i) =>
                    {
                        var clip = new Clip
                        {
                            Url      = x.Attributes["src"].Value,
                            ClipType = ClipType.PreMatch,
                            LinkType = LinkType.Embed,
                            Name     = "Full show"
                        };

                        if (clip.Url.Contains("veuclips.com"))
                        {
                            var uriLink = new Uri(clip.Url);

                            clip.Url = $"https://yfl.veuclips.com/embed/{uriLink.Segments[uriLink.Segments.Length - 1]}?autoplay=1&htmlplayer=1";
                        }

                        else if (clip.Url.Contains("viuclips.net"))
                        {
                            var uriLink = new Uri(clip.Url);

                            clip.Url = $"https://yfl.viuclips.net/embed/{uriLink.Segments[uriLink.Segments.Length - 1]}?autoplay=1&htmlplayer=1";
                        }
                        else if (clip.Url.Contains("evideohat.com"))
                        {
                            var uriLink = new Uri(clip.Url);
                            clip.Url    = $"https://yfl.evideohat.com/embed00/{uriLink.Segments[uriLink.Segments.Length - 1]}";
                        }

                        return(clip);
                    }).ToList();

                    if (!clips.Any())
                    {
                        var iframe = divNodes
                                     ?.FirstOrDefault(x => x.Attributes.Contains("id") && x.Attributes["id"].Value == "acp_content")
                                     ?.Descendants("noscript").FirstOrDefault()
                                     ?.Descendants("iframe").FirstOrDefault(x => x.Attributes.Contains("src"));

                        if (iframe != null)
                        {
                            var link = iframe.Attributes["src"].Value;

                            var clip = new Clip
                            {
                                Url      = link,
                                ClipType = ClipType.PreMatch,
                                LinkType = LinkType.Embed,
                                Name     = "Full show"
                            };

                            if (clip.Url.Contains("veuclips.com"))
                            {
                                var uriLink = new Uri(clip.Url);

                                clip.Url = $"https://yfl.veuclips.com/embed/{uriLink.Segments[uriLink.Segments.Length - 1]}?autoplay=1&htmlplayer=1";
                            }

                            else if (clip.Url.Contains("viuclips.net"))
                            {
                                var uriLink = new Uri(clip.Url);

                                clip.Url = $"https://yfl.viuclips.net/embed/{uriLink.Segments[uriLink.Segments.Length - 1]}?autoplay=1&htmlplayer=1";
                            }
                            else if (clip.Url.Contains("evideohat.com"))
                            {
                                var uriLink = new Uri(clip.Url);
                                clip.Url = $"https://yfl.evideohat.com/embed00/{uriLink.Segments[uriLink.Segments.Length - 1]}";
                            }

                            clips.Add(clip);
                        }
                    }

                    var liItem = ulNodes?.FirstOrDefault(x => x.Attributes.Contains("id") && x.Attributes["id"].Value == "acp_paging_menu")
                                 ?.Descendants("li").Where(x => x.Attributes.Contains("id") && x.Attributes["id"].Value.StartsWith("item"));
                    if (liItem != null)
                    {
                        foreach (var li in liItem)
                        {
                            var aNode = li?.Descendants("a")?.FirstOrDefault(x => x.Attributes.Contains("href"));
                            if (aNode != null)
                            {
                                var link = aNode.Attributes["href"].Value;
                                var clip = GetMatchClip(link, Convert.ToInt32(li.Attributes["id"].Value.Replace("item", "")));
                                if (clip != null)
                                {
                                    clips.Add(clip);
                                }
                            }
                            else if (clips.Any())
                            {
                                clips.First().ClipType = (ClipType)Convert.ToInt32(li.Attributes["id"].Value.Replace("item", ""));
                            }
                        }
                    }
                }

                if (clips != null)
                {
                    var ulAcpPaging = ulNodes?.FirstOrDefault(x => x.Attributes.Contains("id") && x.Attributes["id"].Value == "acp_paging_menu");
                    if (ulAcpPaging != null)
                    {
                        foreach (var clip in clips)
                        {
                            var li = ulAcpPaging.Descendants("li").FirstOrDefault(x => x.Attributes.Contains("id") && x.Attributes["id"].Value == $"item{(int)clip.ClipType}");
                            if (li != null)
                            {
                                clip.Name = li.ChildNodes[0].ChildNodes[0].InnerText;
                            }
                        }
                    }
                }

                var match = new Match();
                match.Slug  = matchLink.Slug;
                match.Title = matchLink.Name;

                var ftpResult = await _ftpHelper.RemoteFiles(matchLink.ImageLink, match.Slug);

                if (ftpResult != null)
                {
                    match.ImageName     = ftpResult.FileName;
                    match.ImageServerId = ftpResult.ServerId;
                }

                foreach (var childNode in divWpbWrapper.ChildNodes)
                {
                    if (childNode.PreviousSibling == null)
                    {
                        continue;
                    }

                    if (childNode.PreviousSibling.InnerText.Contains("Competition"))
                    {
                        match.Competition = childNode.InnerText.HtmlDecode();
                    }

                    if (childNode.PreviousSibling.InnerText.Contains("Date"))
                    {
                        match.MatchDate = childNode.InnerText.ToDate();
                    }

                    if (childNode.PreviousSibling.InnerText.Contains("Stadium") && string.IsNullOrWhiteSpace(match.Stadium))
                    {
                        match.Stadium = childNode.InnerText.HtmlDecode();
                    }

                    if (childNode.PreviousSibling.InnerText.Contains("Referee") && !childNode.InnerText.Contains("jQuery"))
                    {
                        match.Referee = childNode.InnerText.HtmlDecode();

                        break;
                    }
                }

                if (match.MatchDate == null)
                {
                    match.MatchDate = matchLink.RDateTime;
                }

                var divHeaderTeam1 = divNodes.FirstOrDefault(x => x.Attributes.Contains("class") && x.Attributes["class"].Value == "headerteam1");
                if (divHeaderTeam1 != null)
                {
                    match.Home = string.Empty;
                    foreach (var h2 in divHeaderTeam1.Descendants("h2"))
                    {
                        match.Home += " " + h2.InnerText;
                    }
                    match.Home = match.Home.HtmlDecode().Trim();

                    foreach (var node in divHeaderTeam1.Descendants("div"))
                    {
                        match.HomePersonScored += string.IsNullOrWhiteSpace(match.HomePersonScored)
                            ? node.InnerText
                            : ("|" + node.InnerText);
                    }
                }
                else
                {
                    //td-tags td-post-small-box clearfix
                    var tagNode = ulNodes?.FirstOrDefault(x =>
                                                          x.Attributes.Contains("class") &&
                                                          x.Attributes["class"].Value.Contains("td-tags") &&
                                                          x.Attributes["class"].Value.Contains("td-post-small-box"));

                    if (tagNode != null)
                    {
                        match.Home = tagNode.ChildNodes[1].ChildNodes[0].InnerText;
                    }
                }

                var divHeaderTeam2 = divNodes.FirstOrDefault(x => x.Attributes.Contains("class") && x.Attributes["class"].Value == "headerteam2");
                if (divHeaderTeam2 != null)
                {
                    match.Away = string.Empty;
                    foreach (var h2 in divHeaderTeam2.Descendants("h2"))
                    {
                        match.Away += " " + h2.InnerText;
                    }
                    match.Away = match.Away.HtmlDecode().Trim();

                    if (divHeaderTeam2.ChildNodes.Count > 1)
                    {
                        foreach (var node in divHeaderTeam2.Descendants("div"))
                        {
                            match.AwayPersonScored += string.IsNullOrWhiteSpace(match.AwayPersonScored) ? node.InnerText : ("|" + node.InnerText);
                        }
                    }
                }
                else
                {
                    //td-tags td-post-small-box clearfix
                    var tagNode = ulNodes?.FirstOrDefault(x =>
                                                          x.Attributes.Contains("class") &&
                                                          x.Attributes["class"].Value.Contains("td-tags") &&
                                                          x.Attributes["class"].Value.Contains("td-post-small-box"));

                    if (tagNode != null)
                    {
                        match.Away = tagNode.ChildNodes[2].ChildNodes[0].InnerText;
                    }
                }

                var divScore = divNodes.FirstOrDefault(x => x.Attributes.Contains("class") && x.Attributes["class"].Value == "score");
                if (divScore != null)
                {
                    match.Score = $"{divScore.ChildNodes[0].InnerText} : {divScore.ChildNodes[2].InnerText}";
                }

                var divTeam1Roster = ulNodes?.FirstOrDefault(x => x.Attributes.Contains("class") && x.Attributes["class"].Value == "team1roster");
                var formations     = new List <Formation>();
                if (divTeam1Roster != null)
                {
                    match.HomeManager = divTeam1Roster.ChildNodes[1].InnerText;
                    formations.AddRange(divTeam1Roster.Descendants("li")
                                        .OrderBy(x => x.InnerStartIndex)
                                        .Select(liNode => new Formation
                    {
                        Type           = FormationType.Home,
                        Number         = liNode.ChildNodes[0].InnerText.ToInt(),
                        Name           = liNode.ChildNodes[1].InnerText,
                        IsSubstitution = liNode.Attributes.Contains("class") && liNode.Attributes["class"].Value == "issub",
                        Scores         = liNode.ChildNodes.Where(c => c.Attributes.Contains("class") && c.Attributes["class"].Value.Contains("list-goal")).Count(),
                        YellowCard     = liNode.ChildNodes.Where(c => c.Attributes.Contains("class") && (c.Attributes["class"].Value.Contains("list-yellowcard") || c.Attributes["class"].Value.Contains("list-yellowredcard"))).Count(),
                        RedCard        = liNode.ChildNodes.Where(c => c.Attributes.Contains("class") && c.Attributes["class"].Value.Contains("list-redcard")).Count(),
                    }));
                }
                var divTeam2Roster = ulNodes?.FirstOrDefault(x => x.Attributes.Contains("class") && x.Attributes["class"].Value == "team2roster");
                if (divTeam2Roster != null)
                {
                    match.AwayManager = divTeam2Roster.ChildNodes[1].InnerText;
                    formations.AddRange(divTeam2Roster.Descendants("li")
                                        .OrderBy(x => x.InnerStartIndex)
                                        .Select(liNode => new Formation
                    {
                        Type           = FormationType.Away,
                        Number         = liNode.ChildNodes[0].InnerText.ToInt(),
                        Name           = liNode.ChildNodes[1].InnerText,
                        IsSubstitution = liNode.Attributes.Contains("class") && liNode.Attributes["class"].Value == "issub",
                        Scores         = liNode.ChildNodes.Where(c => c.Attributes.Contains("class") && c.Attributes["class"].Value.Contains("list-goal")).Count(),
                        YellowCard     = liNode.ChildNodes.Where(c => c.Attributes.Contains("class") && (c.Attributes["class"].Value.Contains("list-yellowcard") || c.Attributes["class"].Value.Contains("list-yellowredcard"))).Count(),
                        RedCard        = liNode.ChildNodes.Where(c => c.Attributes.Contains("class") && c.Attributes["class"].Value.Contains("list-redcard")).Count(),
                    }));
                }

                var substitutions = new List <Substitution>();
                var divTeam1Subs  = ulNodes?.FirstOrDefault(x => x.Attributes.Contains("class") && x.Attributes["class"].Value == "team1subs");
                if (divTeam1Subs != null)
                {
                    substitutions.AddRange(divTeam1Subs.Descendants("li")
                                           .OrderBy(x => x.InnerStartIndex)
                                           .Select(liNode => new Substitution
                    {
                        Type   = FormationType.Home,
                        Number = liNode.ChildNodes[0].InnerText.ToInt(),
                        Name   = liNode.ChildNodes[1].InnerText
                    }));
                }
                var divTeam2Subs = ulNodes?.FirstOrDefault(x => x.Attributes.Contains("class") && x.Attributes["class"].Value == "team2subs");
                if (divTeam2Subs != null)
                {
                    substitutions.AddRange(divTeam2Subs.Descendants("li")
                                           .OrderBy(x => x.InnerStartIndex)
                                           .Select(liNode => new Substitution
                    {
                        Type   = FormationType.Away,
                        Number = liNode.ChildNodes[0].InnerText.ToInt(),
                        Name   = liNode.ChildNodes[1].InnerText
                    }));
                }

                var actionSubstitutions = new List <ActionSubstitution>();

                var divteam1Actualsubs = ulNodes?.FirstOrDefault(x =>
                                                                 x.Attributes.Contains("class") && x.Attributes["class"].Value == "team1actualsubs");
                if (divteam1Actualsubs != null)
                {
                    actionSubstitutions.AddRange(divteam1Actualsubs.Descendants("li")
                                                 .OrderBy(x => x.InnerStartIndex)
                                                 .Select(x => new ActionSubstitution
                    {
                        Min  = x.ChildNodes[0].InnerText,
                        In   = x.ChildNodes[1].ChildNodes[0].InnerText,
                        Out  = x.ChildNodes[1].ChildNodes[2].InnerText,
                        Type = FormationType.Home
                    }));
                }

                var divteam2Actualsubs = ulNodes?.FirstOrDefault(x =>
                                                                 x.Attributes.Contains("class") && x.Attributes["class"].Value == "team2actualsubs");
                if (divteam2Actualsubs != null)
                {
                    actionSubstitutions.AddRange(divteam2Actualsubs.Descendants("li")
                                                 .OrderBy(x => x.InnerStartIndex)
                                                 .Select(x => new ActionSubstitution
                    {
                        Min  = x.ChildNodes[0].InnerText,
                        In   = x.ChildNodes[1].ChildNodes[0].InnerText,
                        Out  = x.ChildNodes[1].ChildNodes[2].InnerText,
                        Type = FormationType.Away
                    }));
                }


                await _matchRepository.Add(match, clips, formations, substitutions, actionSubstitutions);

                return(true);
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
                return(false);
            }
        }