Add Logic for EuroMillions Draw Balls.
This commit is contained in:
242
lottery-co-uk-scraper/EuroMillions/DrawBalls.cs
Normal file
242
lottery-co-uk-scraper/EuroMillions/DrawBalls.cs
Normal file
@@ -0,0 +1,242 @@
|
||||
using HtmlAgilityPack;
|
||||
using lottery_co_uk_scraper.core.Models;
|
||||
using lottery_co_uk_scraper.Utilities;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using static lottery_co_uk_scraper.NationalLottery.Lotto;
|
||||
|
||||
namespace lottery_co_uk_scraper.EuroMillions
|
||||
{
|
||||
internal class DrawBalls
|
||||
{
|
||||
private static readonly ILogger<DrawBalls> _logger;
|
||||
|
||||
private static HtmlNode GetNodeById(HtmlNode containerNode, string nodeId)
|
||||
{
|
||||
try
|
||||
{
|
||||
return containerNode.DescendantsAndSelf()
|
||||
.FirstOrDefault(x => x.Attributes["id"] != null && x.Attributes["id"].Value == nodeId)
|
||||
?? throw new InvalidOperationException($"Node with ID '{nodeId}' not found.");
|
||||
}
|
||||
catch
|
||||
{
|
||||
throw new InvalidOperationException($"Node with ID '{nodeId}' not found.");
|
||||
}
|
||||
}
|
||||
|
||||
public static int ProcessBallSetUsed(HtmlDocument doc, EurosResult eurosResult)
|
||||
{
|
||||
try
|
||||
{
|
||||
var ballSetUsedString = doc.DocumentNode.Descendants("td")
|
||||
.Where(x => x.InnerHtml.Contains("<strong>Ball Set Used:</strong>"))
|
||||
.Select(x => x.InnerText.Split(':')[1].Trim())
|
||||
.FirstOrDefault();
|
||||
|
||||
if (int.TryParse(ballSetUsedString, out int ballSetUsed))
|
||||
{
|
||||
AssignBallSetToModelProperty(LotteryTableRow.BallSetUsed, ballSetUsed, eurosResult);
|
||||
|
||||
return ballSetUsed;
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.LogInformation("Failed to parse Euro Millions Ball Set Used.");
|
||||
|
||||
throw new Exception("Failed to parse Euro Millions Ball Set Used.");
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
throw new Exception("Failed to parse Euro Millions Ball Set Used.");
|
||||
}
|
||||
}
|
||||
|
||||
public static void AssignBallSetToModelProperty(string containerNode, int ballSetUsed, EurosResult eurosResult)
|
||||
{
|
||||
if (containerNode == LotteryTableRow.BallSetUsed)
|
||||
{
|
||||
PropertyManager.SetProperty(nameof(eurosResult.BallSetUsed), eurosResult, ballSetUsed);
|
||||
}
|
||||
}
|
||||
|
||||
public static void ProcessMainBalls(HtmlDocument doc, EurosResult eurosResult)
|
||||
{
|
||||
try
|
||||
{
|
||||
var ballsDrawn = GetNodeById(doc.DocumentNode, LotteryTableRow.BallsDrawn);
|
||||
|
||||
List<int>? euroBalls = ballsDrawn != null
|
||||
? ExtractBalls(ballsDrawn, "euromillions-ball")
|
||||
: null;
|
||||
|
||||
if (euroBalls != null)
|
||||
{
|
||||
AssignDrawBallsToModelProperty(LotteryTableRow.BallsDrawn, euroBalls, eurosResult);
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.LogError("EuroMillions Draw Balls were null!");
|
||||
|
||||
throw new Exception("EuroMillions Draw Balls were null!");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError("There was a problem processing the EuroMillions Draw Balls. {Message}", ex.Message);
|
||||
|
||||
throw new Exception($"There was a problem processing the EuroMillions Draw Balls. {ex}");
|
||||
}
|
||||
}
|
||||
|
||||
private static List<int> ExtractBalls(HtmlNode ballsNode, string className)
|
||||
{
|
||||
try
|
||||
{
|
||||
return ballsNode.Descendants("span")
|
||||
.Where(x => x.Attributes["class"] != null && x.Attributes["class"].Value.Contains(className))
|
||||
.Select(x =>
|
||||
{
|
||||
if (int.TryParse(x.InnerText, out int ball))
|
||||
{
|
||||
return ball;
|
||||
}
|
||||
|
||||
_logger.LogError("Failed to parse {className} value: {x.InnerText}", className, x.InnerText);
|
||||
|
||||
throw new Exception($"Failed to parse {className} value: {x.InnerText}");
|
||||
})
|
||||
.ToList();
|
||||
}
|
||||
catch
|
||||
{
|
||||
throw new Exception($"Failed to parse {className}");
|
||||
}
|
||||
}
|
||||
|
||||
public static void AssignDrawBallsToModelProperty(string containerNode, object ballInformation, EurosResult eurosResult)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (containerNode == LotteryTableRow.BallsDrawn)
|
||||
{
|
||||
if (ballInformation is List<int> balls && balls.Count >= 5)
|
||||
{
|
||||
for (int i = 0; i < 5; i++)
|
||||
{
|
||||
string propertyName = $"DrawnBall{i + 1}";
|
||||
PropertyManager.SetProperty(propertyName, eurosResult, balls[i]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.LogError("Invalid drawn balls information.");
|
||||
|
||||
throw new Exception("Invalid drawn balls information.");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.LogError("Unhandled containerNode: {containerNode}", containerNode);
|
||||
|
||||
throw new Exception($"Unhandled containerNode: {containerNode}");
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
// ToDo:
|
||||
}
|
||||
}
|
||||
|
||||
public static void ProcessLuckyStars(HtmlDocument doc, EurosResult eurosResult)
|
||||
{
|
||||
try
|
||||
{
|
||||
var ballsDrawn = GetNodeById(doc.DocumentNode, LotteryTableRow.BallsDrawn);
|
||||
|
||||
List<int>? luckyStars = ballsDrawn != null
|
||||
? ExtractLuckyStar(ballsDrawn, "euromillions-lucky-star")
|
||||
: null;
|
||||
|
||||
if (luckyStars != null)
|
||||
{
|
||||
AssignLuckyStarToModelProperty(LotteryTableRow.BallsDrawn, luckyStars, eurosResult);
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.LogError("Lucky Stars appear to be null.");
|
||||
|
||||
throw new Exception("Lucky Stars appear to be null.");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError("There was a problem processing the EuroMillions Lucky Stars. {Message}", ex.Message);
|
||||
|
||||
throw new Exception($"There was a problem processing the EuroMillions Lucky Stars. {ex}");
|
||||
}
|
||||
}
|
||||
|
||||
private static List<int>ExtractLuckyStar(HtmlNode ballsNode, string ballClass)
|
||||
{
|
||||
try
|
||||
{
|
||||
return ballsNode.Descendants("span")
|
||||
.Where(x => x.HasClass(ballClass))
|
||||
.Select(x =>
|
||||
{
|
||||
if (int.TryParse(x.InnerText, out int ball))
|
||||
{
|
||||
return ball;
|
||||
}
|
||||
|
||||
_logger.LogError("Failed to parse {className} value: {x.InnerText}", ballClass, x.InnerText);
|
||||
|
||||
throw new Exception($"Failed to parse {ballClass} value: {x.InnerText}");
|
||||
})
|
||||
.ToList();
|
||||
}
|
||||
catch
|
||||
{
|
||||
_logger.LogError("There was a problem processing the EuroMillions Lucky Stars.");
|
||||
|
||||
throw new Exception($"There was a problem processing the EuroMillions Lucky Stars.");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static void AssignLuckyStarToModelProperty(string containerNode, object ballInformation, EurosResult eurosResult)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (containerNode == LotteryTableRow.BallsDrawn)
|
||||
{
|
||||
if (ballInformation is List<int> balls && balls.Count >= 2)
|
||||
{
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
string propertyName = $"LuckyStar{i + 1}";
|
||||
PropertyManager.SetProperty(propertyName, eurosResult, balls[i]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.LogError("Invalid Lucky Star balls information.");
|
||||
|
||||
throw new Exception("Invalid Lucky Star balls information.");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.LogError("Unhandled containerNode: {containerNode}", containerNode);
|
||||
|
||||
throw new Exception($"Unhandled containerNode: {containerNode}");
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
// ToDo:
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user