Add Logic for EuroMillions Draw Balls.

This commit is contained in:
2024-02-13 13:16:41 +00:00
parent df616fd42c
commit 4017e1eeb1

View 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:
}
}
}
}