public Innings Parse(HtmlNode battingNode, HtmlNode bowlingNode) { Innings innings = new Innings(); AddBatting(battingNode, innings); AddBowling(bowlingNode, innings); return innings; }
private static void ExtractWhoseInnings(HtmlNode headerRow, Innings innings) { HtmlNode cell = headerRow.SelectSingleNode("./td[1]"); string content = cell.InnerText; if (string.IsNullOrEmpty(content)) return; content = content.Trim(); if (content.EndsWith("first innings")) { innings.BattingTeam = content.Substring(0, content.Length - 14).TrimEnd(); innings.TeamInningsNumber = 1; } else if (content.EndsWith("second innings")) { innings.BattingTeam = content.Substring(0, content.Length - 15).TrimEnd(); innings.TeamInningsNumber = 2; } else if (content.EndsWith("second innings (following on)")) { innings.BattingTeam = content.Substring(0, content.Length - 30).TrimEnd(); innings.TeamInningsNumber = 2; } else if (content.EndsWith("innings")) { innings.BattingTeam = content.Substring(0, content.Length - 8).TrimEnd(); innings.TeamInningsNumber = 1; } }
private void ProcessTotal(HtmlNode row, Innings innings) { string wicketsAndOvers = row.SelectSingleNode("./td[2]").InnerText; string totalText = row.SelectSingleNode("./td[3]").InnerText; int wickets, overs, balls, total; if (!int.TryParse(totalText, out total)) total = 0; var m = Regex.Match(wicketsAndOvers, @"\((?:(?'wickets'(?:\d+|no))\swickets?|(?'allout'all\sout))(?:,\s(?'dec'declared))?(?:,\s(?'mins'\d+) minutes)?(?:,\s(?:innings\sclosed,\s)?(?'overs'\d+)\.?(?'balls'\d)?\sovers)?\)"); if (!string.IsNullOrEmpty(m.Groups["allout"].Value)) innings.AllOut = true; else if (m.Groups["wickets"].Value == "no") innings.Wickets = 0; else if (int.TryParse(m.Groups["wickets"].Value, out wickets)) innings.Wickets = wickets; if (!int.TryParse(m.Groups["overs"].Value, out overs)) overs = -1; if (!int.TryParse(m.Groups["balls"].Value, out balls)) balls = 0; if (!string.IsNullOrEmpty(m.Groups["dec"].Value)) innings.Declared = true; if (overs != -1) { innings.Overs = balls == 0 ? overs.ToString() : string.Format("{0}.{1}", overs, balls); innings.BallsBowled = (overs * _match.BallsPerOver) + balls; } innings.Total = total; }
private void AddBowling(HtmlNode bowlingNode, Innings innings) { HtmlNodeCollection rows = bowlingNode.SelectNodes(".//tr"); if (rows == null) return; if (rows.Count < 2) { Log.WarnFormat("Only found {0} lines in the bowling HTML. Expected at least 2", rows.Count); return; } innings.Bowling = new List<BowlerInnings>(); string team = ExtractWhoseBowling(rows[0]); for (int i = 1; i < rows.Count; i++) { BowlerInnings bowler = ParseBowlerInnings(rows[i]); bowler.Number = i; bowler.Team = team; innings.Bowling.Add(bowler); } }
private void AddBatting(HtmlNode battingNode, Innings innings) { HtmlNodeCollection rows = battingNode.SelectNodes(".//tr"); ExtractWhoseInnings(rows[0], innings); innings.Batting = new List<BatsmanInnings>(); int i = 1; while (i < rows.Count) { HtmlNode cell = rows[i].SelectSingleNode("./td[1]"); HtmlNode playerNode = cell.SelectSingleNode("./a"); if (playerNode == null && (cell.InnerText == "Extras" || cell.InnerText == "Total" || cell.InnerText == "Innings Forfeited")) break; BatsmanInnings batsman = ParseBatsmanInnings(rows[i], (innings.BattingTeam == "Somerset" && innings.TeamInningsNumber == 1)); batsman.Number = i; batsman.Team = innings.BattingTeam; innings.Batting.Add(batsman); i++; } while (i < rows.Count) { HtmlNode cell = rows[i].SelectSingleNode("./td[1]"); string label = (cell != null ? cell.InnerText : null); if (string.IsNullOrEmpty(label)) { i++; continue; } if (label == "Innings Forfeited") { innings.Forfeited = true; break; } if (label == "Extras") ProcessExtras(rows[i], innings); if (label == "Total") ProcessTotal(rows[i], innings); if (label == "Fall of wickets:") { ProcessFallOfWickets(rows[i + 1], innings); i++; } i++; } }
private static void ProcessFallOfWickets(HtmlNode row, Innings innings) { List<FallOfWicket> fallOfWickets = new List<FallOfWicket>(); // If we ever decide to add support for who the wicket was... MatchCollection matches = Regex.Matches(row.FirstChild.InnerHtml, @"(?'wicket'\d{1,2})-(?'runs'(?:\?|\d{1,3}))(?:\s\(<a\shref=""/Archive/Players/\d+/\d+/(?'player'\d+).html"">[^<]+</a>,\s(?'overs'\d+\.?\d?)\sov\))?"); //MatchCollection matches = Regex.Matches(content, @"(?'wicket'\d{1,2})-(?'runs'(?:\?|\d{1,3}))"); foreach (Match fall in matches) { int wicket = int.Parse(fall.Groups["wicket"].Value); int? runs = null; if (fall.Groups["runs"].Value != "?") runs = int.Parse(fall.Groups["runs"].Value); string overs = fall.Groups["overs"].Value; string player = fall.Groups["player"].Value; FallOfWicket fow = new FallOfWicket { Wicket = wicket, Runs = runs, Overs = overs }; if (!string.IsNullOrEmpty(player)) fow.OutBatsmanId = PlayerDetails.GenerateId(int.Parse(player)); fallOfWickets.Insert(wicket - 1, fow); } innings.FallOfWickets = fallOfWickets; }
private static void ProcessExtras(HtmlNode row, Innings innings) { string extrasText = row.SelectSingleNode("./td[2]").InnerText; int total; if (int.TryParse(row.SelectSingleNode("./td[3]").InnerText, out total)) innings.Extras = total; var m = Regex.Match(extrasText, @"\(?(?:(?'byes'\d+)\sb)?(?:,\s)?(?:(?'legbyes'\d+)\slb)?(?:,\s)?(?:(?'noballs'\d+)\snb)?(?:,\s)?(?:(?'wides'\d+)\sw)?\)?"); int byes; int legByes; int noBalls; int wides; if (int.TryParse(m.Groups["byes"].Value, out byes)) innings.Byes = byes; if (int.TryParse(m.Groups["legbyes"].Value, out legByes)) innings.LegByes = legByes; if (int.TryParse(m.Groups["noballs"].Value, out noBalls)) innings.NoBalls = noBalls; if (int.TryParse(m.Groups["wides"].Value, out wides)) innings.Wides = wides; }