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, "«(.+)»").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); }