Beispiel #1
0
        private RaceParsingResult ParseRace(string html)
        {
            var result = new RaceParsingResult
            {
                PlayerResults = new List <ResultParsed>(),
                RaceInfo      = new RaceInfo()
            };

            HtmlDocument doc = new HtmlDocument();

            doc.LoadHtml(html);

            HtmlNode gameTypeSpan = doc.DocumentNode.SelectSingleNode("//td[@id='gamedesc']/span");
            string   modeId       = gameTypeSpan.GetAttributeValue("class", "0").Replace("gametype-", "");
            var      SpanA        = gameTypeSpan.SelectSingleNode("a");

            string modeName;

            if (SpanA == null) //станд режим
            {
                modeName = gameTypeSpan.InnerText;
            }
            else // словарь
            {
                modeId  += "-" + Regex.Match(SpanA.GetAttributeValue("href", "0"), "\\d+");
                modeName = SpanA.InnerText;
            }
            result.RaceInfo.Mode = new Mode(modeId, modeName);

            result.RaceInfo.BookAuthor = doc.DocumentNode.SelectSingleNode("//div[@id='bookinfo']//div[@class='author']")?.InnerText;
            result.RaceInfo.BookName   = doc.DocumentNode.SelectSingleNode("//div[@id='bookinfo']//div[@class='name']")?.InnerText;

            HtmlNode totalPlayersNode = doc.DocumentNode.SelectSingleNode("//div[@id='players-count-lbl']/span");

            if (!string.IsNullOrEmpty(totalPlayersNode?.InnerText))
            {
                var match = Regex.Match(totalPlayersNode.InnerText, @"\d+");
                if (match.Success)
                {
                    result.RaceInfo.TotalPlayers = int.Parse(match.Value);
                }
            }

            HtmlNode pointsIncreaseNode = doc.DocumentNode.SelectSingleNode("//div[@id='players-count-lbl']/b");
            int      pointsIncrease     = 0;

            if (!string.IsNullOrEmpty(pointsIncreaseNode?.InnerText))
            {
                var match = Regex.Match(pointsIncreaseNode.InnerText, @"\d+");
                if (match.Success)
                {
                    pointsIncrease = int.Parse(match.Value);
                }
            }

            HtmlNodeCollection players = doc.DocumentNode.SelectNodes("//div[@class='player other ng-scope']");

            if (players != null)
            {
                players.Add(doc.DocumentNode.SelectSingleNode("//div[@class='player you ng-scope']"));// ng-scope
            }
            else
            {
                players = doc.DocumentNode.SelectNodes("//div[@class='player you ng-scope']");
            }

            foreach (HtmlNode player in players)
            {
                ResultParsed resultParsed = new ResultParsed();
                resultParsed.Mode           = new Mode(modeId, modeName);
                resultParsed.PointsIncrease = pointsIncrease;

                HtmlNode rating = player.SelectSingleNode("div[@class='rating']");
                HtmlNode car    = player.SelectSingleNode("table[@class='car']");
                HtmlNode place  = rating.SelectSingleNode("div/ins");
                HtmlNode nick   = player.SelectSingleNode("table//a");
                if (nick != null)
                {
                    resultParsed.Nick = nick != null ? nick.InnerText : "Гость";
                    string id_str = nick.GetAttributeValue("href", "0");
                    resultParsed.Id   = int.Parse(Regex.Match(id_str, "[0-9]+").ToString());
                    resultParsed.Rank = Rank.GetByIndex(int.Parse(nick.GetAttributeValue("class", "000000").Substring(4, 1)));
                }
                else
                {
                    continue;
                    //result.Nick = "Гость";
                    //result.Id = 0;
                    //result.Rank = Rank.GetByIndex(0);
                }

                if (place != null)
                {
                    string place_str = place.InnerText;
                    resultParsed.RealPlace = int.Parse(place_str.Substring(0, place_str.Length - 6));
                    resultParsed.Time      = TimeSpan.Parse("00:" + rating.SelectSingleNode("div[@class='stats']/div").InnerText.Replace(" ", "").Replace("\r", "").Replace("\n", ""));
                    resultParsed.Speed     = (int)Math.Round(double.Parse(rating.SelectSingleNode("div[@class='stats']/div[2]/span").InnerText, new NumberFormatInfo()
                    {
                        NumberDecimalSeparator = ","
                    }));
                    resultParsed.ErCnt  = int.Parse(rating.SelectSingleNode("div[@class='stats']/div[3]/span").InnerText);
                    resultParsed.ErRate = double.Parse(rating.SelectSingleNode("div[@class='stats']/div[3]/span[2]").InnerText, new NumberFormatInfo()
                    {
                        NumberDecimalSeparator = ","
                    }) / 100;
                    result.RaceInfo.ArrivedPlayers++;
                }

                if (player.SelectSingleNode("div[@class='newrecord']//span[@class='']") != null)
                {
                    resultParsed.IsRecord = true; //рекорд с записью или без
                }
                int.TryParse(Regex.Match(car.GetAttributeValue("style", ""), "(?<=left: )\\d+(?=px)").ToString(), out int progress);
                resultParsed.Progress = (int)(progress / 4.8);
                //result.finished = progress >= 100; //style="top: 0px; left: 480px; "

                HtmlNode _imgcont = car.SelectSingleNode(".//div[@class='imgcont']");
                HtmlNode _left    = car.SelectSingleNode(".//div[@class='imgcont leave']");
                resultParsed.HasLeftRace = _left != null;

                HtmlNode _noerror_fail = car.SelectSingleNode(".//img[@class='noerror-fail']");
                resultParsed.NoErrorFail = _noerror_fail != null;

                HtmlNode _i_style = car.SelectSingleNode(".//i");
                if (_i_style != null)
                {
                    int.TryParse(Regex.Match(_i_style.GetAttributeValue("title", ""), "\\d+").ToString(), out int _mileage);
                    resultParsed.Mileage = _mileage;
                }
                result.PlayerResults.Add(resultParsed);
            }
            return(result);
        }
        public async Task <FetchResult <QuickStat> > GetQuickStat(
            int id,
            string modeId   = "normal",
            bool needAwards = true)
        {
            FetchResult <QuickStat> result;

            try
            {
                QuickStat qs = new QuickStat();
                qs.Id  = id;
                modeId = new Mode(modeId).ModeId;
                string html = await NetworkClient.DownloadstringAsync($"http://klavogonki.ru/ajax/profile-popup?user_id={id}&gametype={modeId}");

                HtmlDocument doc = new HtmlDocument();
                doc.LoadHtml(html);
                string sLevel = doc.DocumentNode.SelectSingleNode(".//div[@class='level_icon']").InnerText;
                qs.Level = int.Parse(sLevel);

                var mRank = doc.DocumentNode.SelectSingleNode(".//table/tr/td/div");
                qs.Rank = Rank.GetByIndex(int.Parse(mRank.Attributes["class"].Value.Replace("rang", "")));
                qs.Nick = doc.DocumentNode.SelectSingleNode(".//div[@class='name']").InnerText;
                string sOverall = doc.DocumentNode.SelectSingleNode(".//table[2]/tr/td").InnerText;
                qs.TotalMileage = int.Parse(Regex.Match(sOverall, "\\d+").Value);

                string _modename = doc.DocumentNode.SelectSingleNode(".//table[2]/tr[3]").InnerText;
                string modeName  = Regex.Match(_modename, "&laquo;(.+)&raquo").Groups[1].Value;
                qs.Mode = new Mode(modeId, modeName);

                string   posTxts = doc.DocumentNode.SelectSingleNode(".//table[2]/tr[4]/td").InnerText.Trim();
                string[] _poss   = posTxts.Split('|');
                int      temp;
                if (_poss.Length == 2)
                {
                    qs.DayTop  = int.TryParse(_poss[0], out temp) ? temp : (int?)null; //топ дня
                    qs.WeekTop = int.TryParse(_poss[1], out temp) ? temp : (int?)null; //топ недели
                }
                else if (_poss.Length == 1)
                {
                    qs.BookTop = int.TryParse(_poss[0], out temp) ? temp : (int?)null; //топ книги
                }
                string sRecord = doc.DocumentNode.SelectSingleNode(".//table[2]/tr[5]/td").InnerText;
                qs.Record = int.Parse(Regex.Match(sRecord, "\\d+").Value);

                string sAverage = doc.DocumentNode.SelectSingleNode(".//table[2]/tr[6]/td").InnerText;
                qs.AvgSpeed = int.Parse(Regex.Match(sAverage, "\\d+").Value);

                string sErrors = doc.DocumentNode.SelectSingleNode(".//table[2]/tr[7]/td").InnerText;

                qs.AvgErRate = double.Parse(sErrors.Replace("%", ""), new NumberFormatInfo()
                {
                    NumberDecimalSeparator = ","
                }) / 100;

                string          sMileage = doc.DocumentNode.SelectSingleNode(".//table[2]/tr[8]/td").InnerText;
                MatchCollection matches  = Regex.Matches(sMileage, "\\d+");
                qs.Mileage = int.Parse(matches[0].Value);
                qs.Time    = new TimeSpan();
                if (matches.Count == 3)
                {
                    qs.Time = qs.Time.Add(TimeSpan.FromHours(int.Parse(matches[1].Value)));
                    qs.Time = qs.Time.Add(TimeSpan.FromMinutes(int.Parse(matches[2].Value)));
                }
                else if (matches.Count == 2)
                {
                    qs.Time = qs.Time.Add(TimeSpan.FromMinutes(int.Parse(matches[1].Value)));
                }


                if (needAwards)
                {
                    var nodes = doc.DocumentNode.SelectNodes(".//table[2]/tr/td/a");
                    if (nodes != null && nodes.Count > 0)
                    {
                        for (int i = 0; i < nodes.Count; i++)
                        {
                            string sModeId = nodes[i].Attributes["href"].Value;
                            var    aModeId = Regex.Match(sModeId, "(?<=gametype=).+$").Value;

                            string style  = nodes[i].GetAttributeValue("style", "");
                            var    match  = Regex.Match(style, @"(-\d+)px 0;$");
                            int    margin = 0;
                            if (match.Success)
                            {
                                margin = int.Parse(match.Groups[1].Value);
                            }
                            AwardType type  = GetAwardTypeByMargin(margin);
                            Award     award = new Award()
                            {
                                ModeId = aModeId, Type = type
                            };
                            qs.Awards.Add(award);
                        }
                        qs.BooksGold   = qs.Awards.Count(x => x.Type == AwardType.GoldenBook);
                        qs.BooksSilver = qs.Awards.Count(x => x.Type == AwardType.SilverBook);
                        qs.BooksBronze = qs.Awards.Count(x => x.Type == AwardType.BronzeBook);
                    }
                }
                result = new FetchResult <QuickStat>(qs);
            }
            catch (System.Net.Http.HttpRequestException ex)
            {
                result = new FetchResult <QuickStat>(isSuccessfulDownload: false);
            }
            return(result);
        }