Compare commits
38 Commits
10039eff21
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 73a177d45c | |||
| 7dd570c4a0 | |||
| 27270a2000 | |||
| 31b48d795a | |||
| fc86c91b01 | |||
| e2ec108b0d | |||
| 03aab077d6 | |||
| 298cfa53d9 | |||
| 2e296f6d96 | |||
| ae3e70313c | |||
| 6f396c2090 | |||
| 5537b9abc4 | |||
| afa83fbbb9 | |||
| 79575df472 | |||
| 517658bf74 | |||
| c257d7ff8c | |||
| 34918e6c38 | |||
| d3e651ef89 | |||
| 62ff7a04de | |||
| 465b8e05e7 | |||
| d6fc1bf314 | |||
| 0c8706788a | |||
| b61980a30d | |||
| 388b1ec23f | |||
| ea987c52a4 | |||
| 7f658be963 | |||
| e265958434 | |||
| 0ab60324fd | |||
| c68c2cf8db | |||
| 4017e1eeb1 | |||
| df616fd42c | |||
|
|
3fd0218db3 | ||
|
|
ad24dacac6 | ||
|
|
113a4bb19d | ||
|
|
21923291b4 | ||
|
|
fdbe498237 | ||
|
|
ed42745ff4 | ||
|
|
ea3f91e28d |
@@ -0,0 +1,7 @@
|
||||
namespace lottery_co_uk_scraper.core.Exceptions
|
||||
{
|
||||
public class NullResultException(string message) : Exception(message)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace lottery_co_uk_scraper.core.Models.EuroMillions
|
||||
{
|
||||
[Index(nameof(DrawNumber), nameof(RaffleCode), IsUnique = true)]
|
||||
public class EurosRaffleResult
|
||||
{
|
||||
public int Id { get; set; }
|
||||
|
||||
public int DrawNumber { get; set; }
|
||||
|
||||
public string RaffleCode { get; set; }
|
||||
}
|
||||
}
|
||||
147
lottery-co-uk-scraper.core/Models/EurosResult.cs
Normal file
147
lottery-co-uk-scraper.core/Models/EurosResult.cs
Normal file
@@ -0,0 +1,147 @@
|
||||
using lottery_co_uk_scraper.core.Models.EuroMillions;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace lottery_co_uk_scraper.core.Models
|
||||
{
|
||||
[Index(nameof(DrawNumber), IsUnique = true)]
|
||||
public class EurosResult
|
||||
{
|
||||
public int Id { get; set; }
|
||||
|
||||
public DateOnly DrawDate { get; set; }
|
||||
|
||||
public int DrawNumber { get; set; }
|
||||
|
||||
public bool Rollover { get; set; }
|
||||
|
||||
public EurosRaffleResult MillionaireMakerCode { get; set; }
|
||||
|
||||
public int BallSetUsed { get; set; }
|
||||
|
||||
public int MachineUsed { get; set; }
|
||||
|
||||
public int DrawnBall1 { get; set; }
|
||||
|
||||
public int DrawnBall2 { get; set; }
|
||||
|
||||
public int DrawnBall3 { get; set; }
|
||||
|
||||
public int DrawnBall4 { get; set; }
|
||||
|
||||
public int DrawnBall5 { get; set; }
|
||||
|
||||
public int LuckyStar1 { get; set; }
|
||||
|
||||
public int LuckyStar2 { get; set; }
|
||||
|
||||
public int TotalMatched2 { get; set; }
|
||||
|
||||
public int TotalMatched2UK { get; set; }
|
||||
|
||||
public int Matched2PrizeUK { get; set; }
|
||||
|
||||
public int Matched2PrizeFundUK { get; set; }
|
||||
|
||||
public int TotalMatched2Plus1Star { get; set; }
|
||||
|
||||
public int TotalMatched2Plus1StarUK { get; set; }
|
||||
|
||||
public int Matched2Plus1StarPrizeUK { get; set; }
|
||||
|
||||
public int Matched2Plus1StarPrizeFundUK { get; set; }
|
||||
|
||||
public int TotalMatched1Plus2Stars { get; set; }
|
||||
|
||||
public int TotalMatched1Plus2StarsUK { get; set; }
|
||||
|
||||
public int Matched1Plus2StarsPrizeUK { get; set; }
|
||||
|
||||
public int Matched1Plus2StarsPrizeFundUK { get; set; }
|
||||
|
||||
public int TotalMatched2Plus2Stars { get; set; }
|
||||
|
||||
public int TotalMatched2Plus2StarsUK { get; set; }
|
||||
|
||||
public int Matched2Plus2StarsPrizeUK { get; set; }
|
||||
|
||||
public int Matched2Plus2StarsPrizeFundUK { get; set; }
|
||||
|
||||
public int TotalMatched3 { get; set; }
|
||||
|
||||
public int TotalMatched3UK { get; set; }
|
||||
|
||||
public int Matched3PrizeUK { get; set; }
|
||||
|
||||
public int Matched3PrizeFundUK { get; set; }
|
||||
|
||||
public int TotalMatched3Plus1Star { get; set; }
|
||||
|
||||
public int TotalMatched3Plus1StarUK { get; set; }
|
||||
|
||||
public int Matched3Plus1StarPrizeUK { get; set; }
|
||||
|
||||
public int Matched3Plus1StarPrizeFundUK { get; set; }
|
||||
|
||||
public int TotalMatched3Plus2Stars { get; set; }
|
||||
|
||||
public int TotalMatched3Plus2StarsUK { get; set; }
|
||||
|
||||
public int Matched3Plus2StarsPrizeUK { get; set; }
|
||||
|
||||
public int Matched3Plus2StarsPrizeFundUK { get; set; }
|
||||
|
||||
public int TotalMatched4 { get; set; }
|
||||
|
||||
public int TotalMatched4UK { get; set; }
|
||||
|
||||
public int Matched4PrizeUK { get; set; }
|
||||
|
||||
public int Matched4PrizeFundUK { get; set; }
|
||||
|
||||
public int TotalMatched4Plus1Star { get; set; }
|
||||
|
||||
public int TotalMatched4Plus1StarUK { get; set; }
|
||||
|
||||
public int Matched4Plus1StarPrizeUK { get; set; }
|
||||
|
||||
public int Matched4Plus1StarPrizeFundUK { get; set; }
|
||||
|
||||
public int TotalMatched4Plus2Stars { get; set; }
|
||||
|
||||
public int TotalMatched4Plus2StarsUK { get; set; }
|
||||
|
||||
public int Matched4Plus2StarsPrizeUK { get; set; }
|
||||
|
||||
public int Matched4Plus2StarsPrizeFundUK { get; set; }
|
||||
|
||||
public int TotalMatched5 { get; set; }
|
||||
|
||||
public int TotalMatched5UK { get; set; }
|
||||
|
||||
public int Matched5PrizeUK { get; set; }
|
||||
|
||||
public int Matched5PrizeFundUK { get; set; }
|
||||
|
||||
public int TotalMatched5Plus1Star { get; set; }
|
||||
|
||||
public int TotalMatched5Plus1StarUK { get; set; }
|
||||
|
||||
public int Matched5Plus1StarPrizeUK { get; set; }
|
||||
|
||||
public int Matched5Plus1StarPrizeFundUK { get; set; }
|
||||
|
||||
public int TotalMatched5Plus2Stars { get; set; }
|
||||
|
||||
public int TotalMatched5Plus2StarsUK { get; set; }
|
||||
|
||||
public int Matched5Plus2StarsPrizeUK { get; set; }
|
||||
|
||||
public int Matched5Plus2StarsPrizeFundUK { get; set; }
|
||||
|
||||
public int TotalWinners { get; set; }
|
||||
|
||||
public int TotalWinnersUK { get; set; }
|
||||
|
||||
public int TotalPrizeFundUK { get; set; }
|
||||
}
|
||||
}
|
||||
17
lottery-co-uk-scraper.core/Models/GameInformation.cs
Normal file
17
lottery-co-uk-scraper.core/Models/GameInformation.cs
Normal file
@@ -0,0 +1,17 @@
|
||||
namespace lottery_co_uk_scraper.core.Models
|
||||
{
|
||||
internal class GameInformation
|
||||
{
|
||||
public int Id { get; set; }
|
||||
|
||||
public string GameName { get; set; }
|
||||
|
||||
public DayOfWeek DrawDay { get; set; }
|
||||
|
||||
public TimeOnly DrawClosing { get; set; }
|
||||
|
||||
public TimeOnly DrawOpening { get; set; }
|
||||
|
||||
public TimeOnly DrawTime { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -8,7 +8,7 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Abstractions" Version="8.0.1" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Abstractions" Version="8.0.2" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
using lottery_co_uk_scraper.core.Models;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using lottery_co_uk_scraper.core.Models.EuroMillions;
|
||||
|
||||
namespace lottery_co_uk_scraper.data
|
||||
{
|
||||
@@ -13,5 +13,23 @@ namespace lottery_co_uk_scraper.data
|
||||
dbContext.LottoResults.Add(lottoResults);
|
||||
dbContext.SaveChanges();
|
||||
}
|
||||
|
||||
public static void SaveModelToDatabase(EurosResult eurosResults)
|
||||
{
|
||||
using var dbContext = new LotteryContext();
|
||||
|
||||
dbContext.Database.EnsureCreated();
|
||||
dbContext.EurosResults.Add(eurosResults);
|
||||
dbContext.SaveChanges();
|
||||
}
|
||||
|
||||
public static void SaveModelToDatabase(EurosRaffleResult eurosRaffleResults)
|
||||
{
|
||||
using var dbContext = new LotteryContext();
|
||||
|
||||
dbContext.Database.EnsureCreated();
|
||||
dbContext.EurosRaffleResults.Add(eurosRaffleResults);
|
||||
dbContext.SaveChanges();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,15 @@
|
||||
using lottery_co_uk_scraper.core.Models;
|
||||
using lottery_co_uk_scraper.core.Models.EuroMillions;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace lottery_co_uk_scraper.data
|
||||
{
|
||||
public class LotteryContext : DbContext
|
||||
{
|
||||
public DbSet<EurosResult> EurosResults { get; set; }
|
||||
|
||||
public DbSet<EurosRaffleResult> EurosRaffleResults { get; set; }
|
||||
|
||||
public DbSet<LottoResult> LottoResults { get; set; }
|
||||
|
||||
public LotteryContext()
|
||||
|
||||
@@ -8,9 +8,9 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.1" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="8.0.1" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="8.0.1">
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.2" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="8.0.2" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="8.0.2">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
|
||||
@@ -5,9 +5,11 @@ VisualStudioVersion = 17.9.34321.82
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "lottery-co-uk-scraper", "lottery-co-uk-scraper\lottery-co-uk-scraper.csproj", "{D6F6C01A-F51A-4ED7-AC9F-67C7BF9AAB79}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "lottery-co-uk-scraper.data", "lottery-co-uk-scraper.data\lottery-co-uk-scraper.data.csproj", "{57463DA3-7350-4A10-853C-6C766F96A039}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "lottery-co-uk-scraper.data", "lottery-co-uk-scraper.data\lottery-co-uk-scraper.data.csproj", "{57463DA3-7350-4A10-853C-6C766F96A039}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "lottery-co-uk-scraper.core", "lottery-co-uk-scraper.core\lottery-co-uk-scraper.core.csproj", "{8CA5863C-1FBF-443A-A6A1-B49795C86520}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "lottery-co-uk-scraper.core", "lottery-co-uk-scraper.core\lottery-co-uk-scraper.core.csproj", "{8CA5863C-1FBF-443A-A6A1-B49795C86520}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "lottery-co-uk-scraper.tests", "lottery-co-uk-scraper.tests\lottery-co-uk-scraper.tests.csproj", "{ADB3EC10-84F1-4928-9431-35A91816AA77}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
@@ -27,6 +29,10 @@ Global
|
||||
{8CA5863C-1FBF-443A-A6A1-B49795C86520}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{8CA5863C-1FBF-443A-A6A1-B49795C86520}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{8CA5863C-1FBF-443A-A6A1-B49795C86520}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{ADB3EC10-84F1-4928-9431-35A91816AA77}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{ADB3EC10-84F1-4928-9431-35A91816AA77}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{ADB3EC10-84F1-4928-9431-35A91816AA77}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{ADB3EC10-84F1-4928-9431-35A91816AA77}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<RootNamespace>lottery_co_uk_scraper.tests</RootNamespace>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
|
||||
<IsPackable>false</IsPackable>
|
||||
<IsTestProject>true</IsTestProject>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="coverlet.collector" Version="6.0.0" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0" />
|
||||
<PackageReference Include="xunit" Version="2.5.3" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.5.3" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Using Include="Xunit" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
251
lottery-co-uk-scraper/EuroMillions/DrawBalls.cs
Normal file
251
lottery-co-uk-scraper/EuroMillions/DrawBalls.cs
Normal file
@@ -0,0 +1,251 @@
|
||||
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.EuroMillions.DrawWinnerInformation; /// So this table should not exist here.
|
||||
|
||||
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(EurosTableRow.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)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (containerNode == EurosTableRow.BallSetUsed)
|
||||
{
|
||||
PropertyManager.SetProperty(nameof(eurosResult.BallSetUsed), eurosResult, ballSetUsed);
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
_logger.LogError("Failed to parse {containerNode}", containerNode);
|
||||
|
||||
throw new Exception($"Failed to parse {containerNode}");
|
||||
}
|
||||
}
|
||||
|
||||
public static void ProcessMainBalls(HtmlDocument doc, EurosResult eurosResult)
|
||||
{
|
||||
try
|
||||
{
|
||||
var ballsDrawn = GetNodeById(doc.DocumentNode, EurosTableRow.BallsDrawn);
|
||||
|
||||
List<int>? euroBalls = ballsDrawn != null
|
||||
? ExtractBalls(ballsDrawn, "euromillions-ball")
|
||||
: null;
|
||||
|
||||
if (euroBalls != null)
|
||||
{
|
||||
AssignDrawBallsToModelProperty(EurosTableRow.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 == EurosTableRow.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
|
||||
{
|
||||
throw new Exception($"Unhandled containerNode: {containerNode}");
|
||||
}
|
||||
}
|
||||
|
||||
public static void ProcessLuckyStars(HtmlDocument doc, EurosResult eurosResult)
|
||||
{
|
||||
try
|
||||
{
|
||||
var ballsDrawn = GetNodeById(doc.DocumentNode, EurosTableRow.BallsDrawn);
|
||||
|
||||
List<int>? luckyStars = ballsDrawn != null
|
||||
? ExtractLuckyStar(ballsDrawn, "euromillions-lucky-star")
|
||||
: null;
|
||||
|
||||
if (luckyStars != null)
|
||||
{
|
||||
AssignLuckyStarToModelProperty(EurosTableRow.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 == EurosTableRow.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
|
||||
{
|
||||
throw new Exception($"Unhandled containerNode: {containerNode}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
43
lottery-co-uk-scraper/EuroMillions/DrawCode.cs
Normal file
43
lottery-co-uk-scraper/EuroMillions/DrawCode.cs
Normal file
@@ -0,0 +1,43 @@
|
||||
using HtmlAgilityPack;
|
||||
using lottery_co_uk_scraper.core.Models;
|
||||
using lottery_co_uk_scraper.Utilities;
|
||||
|
||||
namespace lottery_co_uk_scraper.EuroMillions
|
||||
{
|
||||
internal class DrawCode
|
||||
{
|
||||
public static List<string> ProcessMillionaireMaker(HtmlDocument doc, EurosResult eurosResult)
|
||||
{
|
||||
try
|
||||
{
|
||||
var raffleNumbers = new List<string>();
|
||||
|
||||
foreach (var span in doc.DocumentNode.Descendants("span"))
|
||||
{
|
||||
var classAttribute = span.GetAttributeValue("class", "");
|
||||
|
||||
if (classAttribute.Contains("millionaire") && classAttribute.Contains("raffle"))
|
||||
{
|
||||
raffleNumbers.Add(span.InnerText.Trim());
|
||||
}
|
||||
}
|
||||
|
||||
AssignMillionaireMakerToModelProperty(nameof(eurosResult.MillionaireMakerCode), raffleNumbers, eurosResult);
|
||||
|
||||
return raffleNumbers;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// ToDo: _logger.LogError
|
||||
throw new Exception(ex.Message);
|
||||
}
|
||||
|
||||
throw new Exception("Failed to Process Millionaire Maker Code.");
|
||||
}
|
||||
|
||||
public static void AssignMillionaireMakerToModelProperty(string propertyName, List<string> raffleNumbers, EurosResult eurosResult)
|
||||
{
|
||||
PropertyManager.SetProperty(propertyName, eurosResult, raffleNumbers);
|
||||
}
|
||||
}
|
||||
}
|
||||
57
lottery-co-uk-scraper/EuroMillions/DrawDate.cs
Normal file
57
lottery-co-uk-scraper/EuroMillions/DrawDate.cs
Normal file
@@ -0,0 +1,57 @@
|
||||
using HtmlAgilityPack;
|
||||
using lottery_co_uk_scraper.core.Models;
|
||||
using lottery_co_uk_scraper.Utilities;
|
||||
|
||||
namespace lottery_co_uk_scraper.EuroMillions
|
||||
{
|
||||
internal class DrawDate
|
||||
{
|
||||
public static void ProcessDrawDateFromMeta(HtmlDocument doc, EurosResult eurosResult)
|
||||
{
|
||||
try
|
||||
{
|
||||
var title = doc.DocumentNode.Descendants("title")
|
||||
.FirstOrDefault();
|
||||
|
||||
if (title != null)
|
||||
{
|
||||
var titleText = title.InnerText;
|
||||
var date = TextRemoval.ParseDateString(titleText);
|
||||
|
||||
string formattedDate = date.ToString("dd/MM/yyyy");
|
||||
|
||||
AssignDrawDateToModelProperty(nameof(eurosResult.DrawDate), formattedDate, eurosResult);
|
||||
}
|
||||
else
|
||||
{
|
||||
// ToDo: Logger - Title not found
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// ToDo: Logger
|
||||
Console.WriteLine(ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
public static void AssignDrawDateToModelProperty(string propertyName, string formattedDate, EurosResult eurosResult)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (DateOnly.TryParse(formattedDate, out DateOnly value))
|
||||
{
|
||||
PropertyManager.SetProperty(propertyName, eurosResult, value);
|
||||
}
|
||||
else
|
||||
{
|
||||
// ToDo: Failed to parse {propertyName}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// ToDo: Logger
|
||||
Console.WriteLine(ex.Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
42
lottery-co-uk-scraper/EuroMillions/DrawMachine.cs
Normal file
42
lottery-co-uk-scraper/EuroMillions/DrawMachine.cs
Normal file
@@ -0,0 +1,42 @@
|
||||
using HtmlAgilityPack;
|
||||
using lottery_co_uk_scraper.core.Models;
|
||||
using lottery_co_uk_scraper.Utilities;
|
||||
|
||||
namespace lottery_co_uk_scraper.EuroMillions
|
||||
{
|
||||
internal class DrawMachine
|
||||
{
|
||||
public static string ProcessMachineUsed(HtmlDocument doc, EurosResult eurosResult)
|
||||
{
|
||||
try
|
||||
{
|
||||
var machineName = doc.DocumentNode.Descendants("td")
|
||||
.Where(x => x.InnerHtml.Contains("<strong>Ball Machine Used:</strong>"))
|
||||
.Select(x => x.InnerText.Split(':')[1].Trim())
|
||||
.FirstOrDefault();
|
||||
|
||||
if (machineName != null)
|
||||
{
|
||||
AssignDrawMachineToModelProperty(nameof(eurosResult.MachineUsed), machineName, eurosResult);
|
||||
|
||||
return machineName;
|
||||
}
|
||||
else
|
||||
{
|
||||
// ToDo: _logger.LogError
|
||||
throw new Exception("machineName is null");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// ToDo: Logger
|
||||
return ex.Message;
|
||||
}
|
||||
}
|
||||
|
||||
public static void AssignDrawMachineToModelProperty(string propertyName, string machineName, EurosResult eurosResult)
|
||||
{
|
||||
PropertyManager.SetProperty(propertyName, eurosResult, machineName);
|
||||
}
|
||||
}
|
||||
}
|
||||
59
lottery-co-uk-scraper/EuroMillions/DrawNumber.cs
Normal file
59
lottery-co-uk-scraper/EuroMillions/DrawNumber.cs
Normal file
@@ -0,0 +1,59 @@
|
||||
using HtmlAgilityPack;
|
||||
using lottery_co_uk_scraper.core.Models;
|
||||
using lottery_co_uk_scraper.Utilities;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace lottery_co_uk_scraper.EuroMillions
|
||||
{
|
||||
internal partial class DrawNumber
|
||||
{
|
||||
[GeneratedRegex(@"euromillions draw (\d+)")]
|
||||
private static partial Regex MyRegex();
|
||||
|
||||
public static int ProcessDrawNumberFromMeta(HtmlDocument doc, EurosResult eurosResult)
|
||||
{
|
||||
var metaKeywords = doc.DocumentNode.Descendants("meta")
|
||||
.FirstOrDefault(x => x.GetAttributeValue("name", "") == "keywords");
|
||||
|
||||
if (metaKeywords != null)
|
||||
{
|
||||
var keywordsText = metaKeywords.GetAttributeValue("content", "");
|
||||
var drawNumberMatch = MyRegex().Match(keywordsText);
|
||||
|
||||
if (drawNumberMatch.Success)
|
||||
{
|
||||
if (int.TryParse(drawNumberMatch.Groups[1].Value, out int drawNumber))
|
||||
{
|
||||
Console.WriteLine("Draw Number: " + drawNumber);
|
||||
|
||||
AssignDrawNumberToModelProperty(drawNumber, eurosResult);
|
||||
return drawNumber;
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine("Failed to parse draw number.");
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine("Draw Number not found.");
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine("Meta keywords not found.");
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
public static void AssignDrawNumberToModelProperty(int drawNumber, EurosResult eurosResult)
|
||||
{
|
||||
PropertyManager.SetProperty(nameof(eurosResult.DrawNumber), eurosResult, drawNumber);
|
||||
}
|
||||
}
|
||||
}
|
||||
49
lottery-co-uk-scraper/EuroMillions/DrawStatus.cs
Normal file
49
lottery-co-uk-scraper/EuroMillions/DrawStatus.cs
Normal file
@@ -0,0 +1,49 @@
|
||||
using HtmlAgilityPack;
|
||||
using lottery_co_uk_scraper.core.Models;
|
||||
using lottery_co_uk_scraper.Utilities;
|
||||
|
||||
namespace lottery_co_uk_scraper.EuroMillions
|
||||
{
|
||||
internal class DrawStatus
|
||||
{
|
||||
public static bool ProcessRollover(HtmlDocument doc, EurosResult eurosResult)
|
||||
{
|
||||
try
|
||||
{
|
||||
var rolloverElement = doc.DocumentNode.Descendants("span")
|
||||
.FirstOrDefault(x => x.InnerText.Trim() == "Rollover");
|
||||
bool rollover = rolloverElement != null;
|
||||
|
||||
if (rollover)
|
||||
{
|
||||
AssignDrawStatusToModelProperty(rollover, eurosResult);
|
||||
Console.WriteLine("Rollover: " + rollover);
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// ToDo: _logger.LogError
|
||||
throw new Exception(ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
public static void AssignDrawStatusToModelProperty(bool status, EurosResult eurosResult)
|
||||
{
|
||||
try
|
||||
{
|
||||
PropertyManager.SetProperty(nameof(eurosResult.Rollover), eurosResult, status);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// ToDo: _logger.LogError
|
||||
throw new Exception(ex.Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
734
lottery-co-uk-scraper/EuroMillions/DrawWinnerInformation.cs
Normal file
734
lottery-co-uk-scraper/EuroMillions/DrawWinnerInformation.cs
Normal file
@@ -0,0 +1,734 @@
|
||||
using HtmlAgilityPack;
|
||||
using lottery_co_uk_scraper.core.Models;
|
||||
using lottery_co_uk_scraper.Utilities;
|
||||
using lottery_co_uk_scraper.core.Exceptions;
|
||||
using System.Globalization;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace lottery_co_uk_scraper.EuroMillions
|
||||
{
|
||||
internal partial class DrawWinnerInformation
|
||||
{
|
||||
[GeneratedRegex(@"(\d+)")]
|
||||
private static partial Regex MyRegex();
|
||||
|
||||
internal class EurosTableRow()
|
||||
{
|
||||
internal const string BallSetUsed = "ballSetUsed";
|
||||
internal const string BallsDrawn = "ballsDrawn";
|
||||
internal const string Match1Plus2Stars = "Match 1 and 2 Stars";
|
||||
internal const string Match2 = "Match 2";
|
||||
internal const string Match2Plus1Star = "Match 2 and 1 Star";
|
||||
internal const string Match2Plus2Stars = "Match 2 and 2 Star";
|
||||
internal const string Match3 = "Match 3";
|
||||
internal const string Match3Plus1Star = "Match 3 and 1 Star";
|
||||
internal const string Match3Plus2Stars = "Match 3 and 2 Star";
|
||||
internal const string Match4 = "Match 4";
|
||||
internal const string Match4Plus1Star = "Match 4 and 1 Star";
|
||||
internal const string Match4Plus2Stars = "Match 4 and 2 Star";
|
||||
internal const string Match5 = "Match 5";
|
||||
internal const string Match5Plus1Star = "Match 5 and 1 Star";
|
||||
internal const string Match5Plus2Stars = "Match 5 and 2 Star";
|
||||
internal const string Total = "Totals";
|
||||
internal const string Winners = "UK Winners";
|
||||
internal const string PrizePerWinner = "Prize Per Winner";
|
||||
internal const string PrizeFundAmountUK = "UK Prize Fund";
|
||||
internal const string TotalWinners = "Total Winners";
|
||||
}
|
||||
|
||||
public static void ProcessWinnersTable(HtmlDocument doc, EurosResult eurosResult)
|
||||
{
|
||||
try
|
||||
{
|
||||
var table = doc.DocumentNode.Descendants("table")
|
||||
.FirstOrDefault(x => x.Attributes["class"] != null && x.Attributes["class"].Value.Contains("euromillions mobFormat"));
|
||||
|
||||
if (table != null)
|
||||
{
|
||||
ProcessTableSection(table, EurosTableRow.Match1Plus2Stars, eurosResult);
|
||||
ProcessTableSection(table, EurosTableRow.Match2, eurosResult);
|
||||
ProcessTableSection(table, EurosTableRow.Match2Plus1Star, eurosResult);
|
||||
ProcessTableSection(table, EurosTableRow.Match2Plus2Stars, eurosResult);
|
||||
ProcessTableSection(table, EurosTableRow.Match3, eurosResult);
|
||||
ProcessTableSection(table, EurosTableRow.Match3Plus1Star, eurosResult);
|
||||
ProcessTableSection(table, EurosTableRow.Match3Plus2Stars, eurosResult);
|
||||
ProcessTableSection(table, EurosTableRow.Match4, eurosResult);
|
||||
ProcessTableSection(table, EurosTableRow.Match4Plus1Star, eurosResult);
|
||||
ProcessTableSection(table, EurosTableRow.Match4Plus2Stars, eurosResult);
|
||||
ProcessTableSection(table, EurosTableRow.Match5, eurosResult);
|
||||
ProcessTableSection(table, EurosTableRow.Match5Plus1Star, eurosResult);
|
||||
ProcessTableSection(table, EurosTableRow.Match5Plus2Stars, eurosResult);
|
||||
ProcessTableSection(table, EurosTableRow.Winners, eurosResult);
|
||||
ProcessTableSection(table, EurosTableRow.PrizePerWinner, eurosResult);
|
||||
ProcessTableSection(table, EurosTableRow.PrizeFundAmountUK, eurosResult);
|
||||
ProcessTableSection(table, EurosTableRow.TotalWinners, eurosResult);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// ToDo: Catch Exception
|
||||
Console.WriteLine(ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
public static void ProcessTableSection(HtmlNode table, string sectionTitle, EurosResult eurosResult)
|
||||
{
|
||||
try
|
||||
{
|
||||
var sectionRow = GetSectionRowByTitle(table, sectionTitle);
|
||||
|
||||
if (sectionRow != null)
|
||||
{
|
||||
var ukWinnersNode = GetNodeByDataTitle(sectionRow, EurosTableRow.Winners);
|
||||
var prizePerWinnerNode = GetNodeByDataTitle(sectionRow, EurosTableRow.PrizePerWinner);
|
||||
var prizeFundUKNode = GetNodeByDataTitle(sectionRow, EurosTableRow.PrizeFundAmountUK);
|
||||
var totalWinnersNode = GetNodeByDataTitle(sectionRow, EurosTableRow.TotalWinners);
|
||||
|
||||
if (ukWinnersNode != null && prizePerWinnerNode != null && prizeFundUKNode != null)
|
||||
{
|
||||
ProcessUKWinners(sectionTitle, ukWinnersNode, eurosResult);
|
||||
ProcessWinnerPrizeAmount(sectionTitle, prizePerWinnerNode, eurosResult);
|
||||
ProcessPrizeFundAmountUK(sectionTitle, prizeFundUKNode, eurosResult);
|
||||
ProcessTotalWinners(sectionTitle, totalWinnersNode, eurosResult);
|
||||
}
|
||||
else
|
||||
{
|
||||
// ToDo:Logger - Missing winners, prize per winner, or prize fund nodes in the table.
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// ToDo: Logger - Section title '{sectionTitle}' not found in the table.
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// ToDo: Logger - Exception
|
||||
Console.WriteLine(ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
private static HtmlNode GetSectionRowByTitle(HtmlNode table, string sectionTitle)
|
||||
{
|
||||
try
|
||||
{
|
||||
var sectionRow = table.Descendants("tr")
|
||||
.FirstOrDefault(x => x.Descendants("td").Any(y => y.InnerText.Contains(sectionTitle, StringComparison.OrdinalIgnoreCase)));
|
||||
|
||||
if (sectionRow != null)
|
||||
{
|
||||
return sectionRow;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new NullResultException("Machine name is null.");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// ToDo: _logger.LogError
|
||||
throw new Exception(ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
private static HtmlNode GetNodeByDataTitle(HtmlNode sectionRow, string dataTitle)
|
||||
{
|
||||
try
|
||||
{
|
||||
return sectionRow.Descendants("td")
|
||||
.FirstOrDefault(x => x.Attributes["data-title"] != null && x.Attributes["data-title"].Value == dataTitle)
|
||||
?? throw new InvalidOperationException($"Section row with title '{dataTitle}' not found.");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// ToDo: _logger.LogError
|
||||
throw new Exception(ex.Message);
|
||||
}
|
||||
|
||||
throw new Exception("Failed to get node by data title.");
|
||||
}
|
||||
|
||||
public static void ProcessUKWinners(string sectionTitle, HtmlNode winnersNode, EurosResult eurosResult)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (int.TryParse(winnersNode.InnerText.Trim().Replace(",", ""), NumberStyles.AllowThousands, CultureInfo.InvariantCulture, out int winners))
|
||||
{
|
||||
string columnTitle = winnersNode.Attributes["data-title"].Value;
|
||||
|
||||
ParseWinnerCount(sectionTitle, columnTitle, winners, eurosResult);
|
||||
}
|
||||
else
|
||||
{
|
||||
// ToDo: Logger - Failed to parse {sectionTitle} winners.
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// ToDo: _logger.LogError
|
||||
throw new Exception(ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
private static void ParseWinnerCount(string sectionTitle, string columnTitle, int winners, EurosResult eurosResult)
|
||||
{
|
||||
try
|
||||
{
|
||||
AssignValueToModelProperty(sectionTitle, EurosTableRow.Match2, columnTitle, winners, eurosResult);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// ToDo: _logger.LogError
|
||||
throw new Exception(ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
public static void ProcessWinnerPrizeAmount(string sectionTitle, HtmlNode prizePerWinnerNode, EurosResult eurosResult)
|
||||
{
|
||||
try
|
||||
{
|
||||
string prizeText = prizePerWinnerNode.InnerText.Trim().Replace("£", "").Replace(",", "");
|
||||
string columnTitle = prizePerWinnerNode.Attributes["data-title"].Value;
|
||||
int prizePerWinner;
|
||||
|
||||
if (prizeText == "Free Ticket")
|
||||
{
|
||||
prizePerWinner = 999999999;
|
||||
}
|
||||
else if (int.TryParse(prizeText, NumberStyles.Currency, CultureInfo.InvariantCulture, out int parsedPrize))
|
||||
{
|
||||
prizePerWinner = parsedPrize;
|
||||
}
|
||||
else
|
||||
{
|
||||
// ToDo: Logger - Failed to parse prize per winner ({sectionTitle}).
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
ParseWinnerPrizeAmount(sectionTitle, columnTitle, prizePerWinner, eurosResult);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// ToDo: _logger.LogError
|
||||
throw new Exception(ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
public static void ParseWinnerPrizeAmount(string sectionTitle, string columnTitle, int prizePerWinner, EurosResult eurosResult)
|
||||
{
|
||||
try
|
||||
{
|
||||
AssignValueToModelProperty(sectionTitle, EurosTableRow.Match2, columnTitle, prizePerWinner, eurosResult);
|
||||
}
|
||||
catch
|
||||
{
|
||||
// ToDo: Logger
|
||||
Console.WriteLine("Nothing to match");
|
||||
}
|
||||
}
|
||||
|
||||
public static void ProcessPrizeFundAmountUK(string sectionTitle, HtmlNode prizeFundNode, EurosResult eurosResult)
|
||||
{
|
||||
try
|
||||
{
|
||||
string prizeFundText = prizeFundNode.InnerText.Trim().Replace("£", "").Replace(",", "");
|
||||
string columnTitle = prizeFundNode.Attributes["data-title"].Value;
|
||||
int prizeFund;
|
||||
|
||||
if (prizeFundText == "-")
|
||||
{
|
||||
prizeFund = 999999999;
|
||||
}
|
||||
else if (int.TryParse(prizeFundText, NumberStyles.Currency, CultureInfo.InvariantCulture, out int parsedPrizeFund))
|
||||
{
|
||||
prizeFund = parsedPrizeFund;
|
||||
}
|
||||
else
|
||||
{
|
||||
// ToDo: Logger
|
||||
return;
|
||||
}
|
||||
|
||||
ParsePrizeFundAmountUK(sectionTitle, columnTitle, prizeFund, eurosResult);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// ToDo: _logger.LogError
|
||||
throw new Exception(ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
public static void ParsePrizeFundAmountUK(string sectionTitle, string columnTitle, int prizeFundNode, EurosResult eurosResult)
|
||||
{
|
||||
try
|
||||
{
|
||||
AssignValueToModelProperty(sectionTitle, EurosTableRow.Match2, columnTitle, prizeFundNode, eurosResult);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// ToDo: _logger.LogError
|
||||
throw new Exception(ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
public static void ProcessTotalWinners(string sectionTitle, HtmlNode totalWinnersNode, EurosResult eurosResult)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (int.TryParse(totalWinnersNode.InnerText.Trim().Replace(",", ""), NumberStyles.AllowThousands, CultureInfo.InvariantCulture, out int totalWinners))
|
||||
{
|
||||
string columnTitle = totalWinnersNode.Attributes["data-title"].Value;
|
||||
|
||||
ParseTotalWinners(sectionTitle, columnTitle, totalWinners, eurosResult);
|
||||
}
|
||||
else
|
||||
{
|
||||
// ToDo: Logger - Failed to parse {sectionTitle} winners.
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// ToDo: _logger.LogError
|
||||
throw new Exception(ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
public static void ParseTotalWinners(string sectionTitle, string columnTitle, int totalWinnersNode, EurosResult eurosResult)
|
||||
{
|
||||
try
|
||||
{
|
||||
AssignValueToModelProperty(sectionTitle, EurosTableRow.Match2, columnTitle, totalWinnersNode, eurosResult);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// ToDo: _logger.LogError
|
||||
throw new Exception(ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
public static void AssignValueToModelProperty(string sectionTitle, string propertyName, string columnTitle, int value, EurosResult eurosResult)
|
||||
{
|
||||
switch (sectionTitle)
|
||||
{
|
||||
#region Match 1 Plus 2 Stars
|
||||
case EurosTableRow.Match1Plus2Stars:
|
||||
try
|
||||
{
|
||||
if (columnTitle == EurosTableRow.Winners)
|
||||
{
|
||||
PropertyManager.SetProperty(nameof(eurosResult.TotalMatched1Plus2StarsUK), eurosResult, value);
|
||||
}
|
||||
|
||||
if (columnTitle == EurosTableRow.PrizePerWinner)
|
||||
{
|
||||
PropertyManager.SetProperty(nameof(eurosResult.Matched1Plus2StarsPrizeUK), eurosResult, value);
|
||||
}
|
||||
|
||||
if (columnTitle == EurosTableRow.PrizeFundAmountUK)
|
||||
{
|
||||
PropertyManager.SetProperty(nameof(eurosResult.Matched1Plus2StarsPrizeFundUK), eurosResult, value);
|
||||
}
|
||||
|
||||
if (columnTitle == EurosTableRow.TotalWinners)
|
||||
{
|
||||
PropertyManager.SetProperty(nameof(eurosResult.TotalMatched1Plus2Stars), eurosResult, value);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// ToDo: Logger
|
||||
throw new Exception(ex.Message);
|
||||
}
|
||||
|
||||
break;
|
||||
#endregion
|
||||
|
||||
#region Match 2, Match 2 Plus 1 Star & Match 2 Plus 2 Stars
|
||||
case EurosTableRow.Match2:
|
||||
try
|
||||
{
|
||||
if (columnTitle == EurosTableRow.Winners)
|
||||
{
|
||||
PropertyManager.SetProperty(nameof(eurosResult.TotalMatched2UK), eurosResult, value);
|
||||
}
|
||||
|
||||
if (columnTitle == EurosTableRow.PrizePerWinner)
|
||||
{
|
||||
PropertyManager.SetProperty(nameof(eurosResult.Matched2PrizeUK), eurosResult, value);
|
||||
}
|
||||
|
||||
if (columnTitle == EurosTableRow.PrizeFundAmountUK)
|
||||
{
|
||||
PropertyManager.SetProperty(nameof(eurosResult.Matched2PrizeFundUK), eurosResult, value);
|
||||
}
|
||||
|
||||
if (columnTitle == EurosTableRow.TotalWinners)
|
||||
{
|
||||
PropertyManager.SetProperty(nameof(eurosResult.TotalMatched2), eurosResult, value);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// ToDo: Logger
|
||||
throw new Exception(ex.Message);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case EurosTableRow.Match2Plus1Star:
|
||||
try
|
||||
{
|
||||
if (columnTitle == EurosTableRow.Winners)
|
||||
{
|
||||
PropertyManager.SetProperty(nameof(eurosResult.TotalMatched2Plus1StarUK), eurosResult, value);
|
||||
}
|
||||
|
||||
if (columnTitle == EurosTableRow.PrizePerWinner)
|
||||
{
|
||||
PropertyManager.SetProperty(nameof(eurosResult.Matched2Plus1StarPrizeUK), eurosResult, value);
|
||||
}
|
||||
|
||||
if (columnTitle == EurosTableRow.PrizeFundAmountUK)
|
||||
{
|
||||
PropertyManager.SetProperty(nameof(eurosResult.Matched2Plus1StarPrizeFundUK), eurosResult, value);
|
||||
}
|
||||
|
||||
if (columnTitle == EurosTableRow.TotalWinners)
|
||||
{
|
||||
PropertyManager.SetProperty(nameof(eurosResult.TotalMatched2Plus1Star), eurosResult, value);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// ToDo: Logger
|
||||
throw new Exception(ex.Message);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case EurosTableRow.Match2Plus2Stars:
|
||||
try
|
||||
{
|
||||
if (columnTitle == EurosTableRow.Winners)
|
||||
{
|
||||
PropertyManager.SetProperty(nameof(eurosResult.TotalMatched2Plus2StarsUK), eurosResult, value);
|
||||
}
|
||||
|
||||
if (columnTitle == EurosTableRow.PrizePerWinner)
|
||||
{
|
||||
PropertyManager.SetProperty(nameof(eurosResult.Matched2Plus2StarsPrizeUK), eurosResult, value);
|
||||
}
|
||||
|
||||
if (columnTitle == EurosTableRow.PrizeFundAmountUK)
|
||||
{
|
||||
PropertyManager.SetProperty(nameof(eurosResult.Matched2Plus2StarsPrizeFundUK), eurosResult, value);
|
||||
}
|
||||
|
||||
if (columnTitle == EurosTableRow.TotalWinners)
|
||||
{
|
||||
PropertyManager.SetProperty(nameof(eurosResult.TotalMatched2Plus2Stars), eurosResult, value);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// ToDo: Logger
|
||||
throw new Exception(ex.Message);
|
||||
}
|
||||
|
||||
break;
|
||||
#endregion
|
||||
|
||||
#region Match 3, Match 3 Plus 1 Star & Match 3 Plus 2 Stars
|
||||
case EurosTableRow.Match3:
|
||||
try
|
||||
{
|
||||
if (columnTitle == EurosTableRow.Winners)
|
||||
{
|
||||
PropertyManager.SetProperty(nameof(eurosResult.TotalMatched3UK), eurosResult, value);
|
||||
}
|
||||
|
||||
if (columnTitle == EurosTableRow.PrizePerWinner)
|
||||
{
|
||||
PropertyManager.SetProperty(nameof(eurosResult.Matched3PrizeUK), eurosResult, value);
|
||||
}
|
||||
|
||||
if (columnTitle == EurosTableRow.PrizeFundAmountUK)
|
||||
{
|
||||
PropertyManager.SetProperty(nameof(eurosResult.Matched3PrizeFundUK), eurosResult, value);
|
||||
}
|
||||
|
||||
if (columnTitle == EurosTableRow.TotalWinners)
|
||||
{
|
||||
PropertyManager.SetProperty(nameof(eurosResult.TotalMatched3), eurosResult, value);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// ToDo: Logger
|
||||
throw new Exception(ex.Message);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case EurosTableRow.Match3Plus1Star:
|
||||
try
|
||||
{
|
||||
if (columnTitle == EurosTableRow.Winners)
|
||||
{
|
||||
PropertyManager.SetProperty(nameof(eurosResult.TotalMatched3Plus1StarUK), eurosResult, value);
|
||||
}
|
||||
|
||||
if (columnTitle == EurosTableRow.PrizePerWinner)
|
||||
{
|
||||
PropertyManager.SetProperty(nameof(eurosResult.Matched3Plus1StarPrizeUK), eurosResult, value);
|
||||
}
|
||||
|
||||
if (columnTitle == EurosTableRow.PrizeFundAmountUK)
|
||||
{
|
||||
PropertyManager.SetProperty(nameof(eurosResult.Matched3Plus1StarPrizeFundUK), eurosResult, value);
|
||||
}
|
||||
|
||||
if (columnTitle == EurosTableRow.TotalWinners)
|
||||
{
|
||||
PropertyManager.SetProperty(nameof(eurosResult.TotalMatched3Plus1Star), eurosResult, value);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// ToDo: Logger
|
||||
throw new Exception(ex.Message);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case EurosTableRow.Match3Plus2Stars:
|
||||
try
|
||||
{
|
||||
if (columnTitle == EurosTableRow.Winners)
|
||||
{
|
||||
PropertyManager.SetProperty(nameof(eurosResult.TotalMatched3Plus2StarsUK), eurosResult, value);
|
||||
}
|
||||
|
||||
if (columnTitle == EurosTableRow.PrizePerWinner)
|
||||
{
|
||||
PropertyManager.SetProperty(nameof(eurosResult.Matched3Plus2StarsPrizeUK), eurosResult, value);
|
||||
}
|
||||
|
||||
if (columnTitle == EurosTableRow.PrizeFundAmountUK)
|
||||
{
|
||||
PropertyManager.SetProperty(nameof(eurosResult.Matched3Plus2StarsPrizeFundUK), eurosResult, value);
|
||||
}
|
||||
|
||||
if (columnTitle == EurosTableRow.TotalWinners)
|
||||
{
|
||||
PropertyManager.SetProperty(nameof(eurosResult.TotalMatched3Plus2Stars), eurosResult, value);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// ToDo: Logger
|
||||
throw new Exception(ex.Message);
|
||||
}
|
||||
|
||||
break;
|
||||
#endregion
|
||||
|
||||
#region Match 4, Match 4 Plus 1 Star & Match 4 Plus 2 Stars
|
||||
case EurosTableRow.Match4:
|
||||
try
|
||||
{
|
||||
if (columnTitle == EurosTableRow.Winners)
|
||||
{
|
||||
PropertyManager.SetProperty(nameof(eurosResult.TotalMatched4UK), eurosResult, value);
|
||||
}
|
||||
|
||||
if (columnTitle == EurosTableRow.PrizePerWinner)
|
||||
{
|
||||
PropertyManager.SetProperty(nameof(eurosResult.Matched4PrizeUK), eurosResult, value);
|
||||
}
|
||||
|
||||
if (columnTitle == EurosTableRow.PrizeFundAmountUK)
|
||||
{
|
||||
PropertyManager.SetProperty(nameof(eurosResult.Matched4PrizeFundUK), eurosResult, value);
|
||||
}
|
||||
|
||||
if (columnTitle == EurosTableRow.TotalWinners)
|
||||
{
|
||||
PropertyManager.SetProperty(nameof(eurosResult.TotalMatched4), eurosResult, value);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// ToDo: Logger
|
||||
throw new Exception(ex.Message);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case EurosTableRow.Match4Plus1Star:
|
||||
try
|
||||
{
|
||||
if (columnTitle == EurosTableRow.Winners)
|
||||
{
|
||||
PropertyManager.SetProperty(nameof(eurosResult.TotalMatched4Plus1StarUK), eurosResult, value);
|
||||
}
|
||||
|
||||
if (columnTitle == EurosTableRow.PrizePerWinner)
|
||||
{
|
||||
PropertyManager.SetProperty(nameof(eurosResult.Matched4Plus1StarPrizeUK), eurosResult, value);
|
||||
}
|
||||
|
||||
if (columnTitle == EurosTableRow.PrizeFundAmountUK)
|
||||
{
|
||||
PropertyManager.SetProperty(nameof(eurosResult.Matched4Plus1StarPrizeFundUK), eurosResult, value);
|
||||
}
|
||||
|
||||
if (columnTitle == EurosTableRow.TotalWinners)
|
||||
{
|
||||
PropertyManager.SetProperty(nameof(eurosResult.TotalMatched4Plus1Star), eurosResult, value);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// ToDo: Logger
|
||||
throw new Exception(ex.Message);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case EurosTableRow.Match4Plus2Stars:
|
||||
try
|
||||
{
|
||||
if (columnTitle == EurosTableRow.Winners)
|
||||
{
|
||||
PropertyManager.SetProperty(nameof(eurosResult.TotalMatched4Plus2StarsUK), eurosResult, value);
|
||||
}
|
||||
|
||||
if (columnTitle == EurosTableRow.PrizePerWinner)
|
||||
{
|
||||
PropertyManager.SetProperty(nameof(eurosResult.Matched4Plus2StarsPrizeUK), eurosResult, value);
|
||||
}
|
||||
|
||||
if (columnTitle == EurosTableRow.PrizeFundAmountUK)
|
||||
{
|
||||
PropertyManager.SetProperty(nameof(eurosResult.Matched4Plus2StarsPrizeFundUK), eurosResult, value);
|
||||
}
|
||||
|
||||
if (columnTitle == EurosTableRow.TotalWinners)
|
||||
{
|
||||
PropertyManager.SetProperty(nameof(eurosResult.TotalMatched4Plus2Stars), eurosResult, value);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// ToDo: Logger
|
||||
throw new Exception(ex.Message);
|
||||
}
|
||||
|
||||
break;
|
||||
#endregion
|
||||
|
||||
#region Match 5, Match 5 Plus 1 Star & Match 5 Plus 2 Stars
|
||||
case EurosTableRow.Match5:
|
||||
|
||||
if (columnTitle == EurosTableRow.Winners)
|
||||
{
|
||||
PropertyManager.SetProperty(nameof(eurosResult.TotalMatched5UK), eurosResult, value);
|
||||
}
|
||||
|
||||
if (columnTitle == EurosTableRow.PrizePerWinner)
|
||||
{
|
||||
PropertyManager.SetProperty(nameof(eurosResult.Matched5PrizeUK), eurosResult, value);
|
||||
}
|
||||
|
||||
if (columnTitle == EurosTableRow.PrizeFundAmountUK)
|
||||
{
|
||||
PropertyManager.SetProperty(nameof(eurosResult.Matched5PrizeFundUK), eurosResult, value);
|
||||
}
|
||||
|
||||
if (columnTitle == EurosTableRow.TotalWinners)
|
||||
{
|
||||
PropertyManager.SetProperty(nameof(eurosResult.TotalMatched5), eurosResult, value);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case EurosTableRow.Match5Plus1Star:
|
||||
|
||||
if (columnTitle == EurosTableRow.Winners)
|
||||
{
|
||||
PropertyManager.SetProperty(nameof(eurosResult.TotalMatched5Plus1StarUK), eurosResult, value);
|
||||
}
|
||||
|
||||
if (columnTitle == EurosTableRow.PrizePerWinner)
|
||||
{
|
||||
PropertyManager.SetProperty(nameof(eurosResult.Matched5Plus1StarPrizeUK), eurosResult, value);
|
||||
}
|
||||
|
||||
if (columnTitle == EurosTableRow.PrizeFundAmountUK)
|
||||
{
|
||||
PropertyManager.SetProperty(nameof(eurosResult.Matched5Plus1StarPrizeFundUK), eurosResult, value);
|
||||
}
|
||||
|
||||
if (columnTitle == EurosTableRow.TotalWinners)
|
||||
{
|
||||
PropertyManager.SetProperty(nameof(eurosResult.TotalMatched5Plus1Star), eurosResult, value);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case EurosTableRow.Match5Plus2Stars:
|
||||
|
||||
if (columnTitle == EurosTableRow.Winners)
|
||||
{
|
||||
PropertyManager.SetProperty(nameof(eurosResult.TotalMatched5Plus2StarsUK), eurosResult, value);
|
||||
}
|
||||
|
||||
if (columnTitle == EurosTableRow.PrizePerWinner)
|
||||
{
|
||||
PropertyManager.SetProperty(nameof(eurosResult.Matched5Plus2StarsPrizeUK), eurosResult, value);
|
||||
}
|
||||
|
||||
if (columnTitle == EurosTableRow.PrizeFundAmountUK)
|
||||
{
|
||||
PropertyManager.SetProperty(nameof(eurosResult.Matched5Plus2StarsPrizeFundUK), eurosResult, value);
|
||||
}
|
||||
|
||||
if (columnTitle == EurosTableRow.TotalWinners)
|
||||
{
|
||||
PropertyManager.SetProperty(nameof(eurosResult.TotalMatched5Plus2Stars), eurosResult, value);
|
||||
}
|
||||
|
||||
break;
|
||||
#endregion
|
||||
|
||||
#region Totals
|
||||
case EurosTableRow.Total:
|
||||
try
|
||||
{
|
||||
if (columnTitle == EurosTableRow.Winners)
|
||||
{
|
||||
PropertyManager.SetProperty(nameof(eurosResult.TotalWinnersUK), eurosResult, value);
|
||||
}
|
||||
if (columnTitle == EurosTableRow.PrizeFundAmountUK)
|
||||
{
|
||||
PropertyManager.SetProperty(nameof(eurosResult.TotalPrizeFundUK), eurosResult, value);
|
||||
}
|
||||
if (columnTitle == EurosTableRow.Winners)
|
||||
{
|
||||
PropertyManager.SetProperty(nameof(eurosResult.TotalWinners), eurosResult, value);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// ToDo: Logger
|
||||
throw new Exception(ex.Message);
|
||||
}
|
||||
|
||||
break;
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
43
lottery-co-uk-scraper/EuroMillions/Euros.cs
Normal file
43
lottery-co-uk-scraper/EuroMillions/Euros.cs
Normal file
@@ -0,0 +1,43 @@
|
||||
using HtmlAgilityPack;
|
||||
using lottery_co_uk_scraper.core.Models;
|
||||
using lottery_co_uk_scraper.data;
|
||||
|
||||
namespace lottery_co_uk_scraper.EuroMillions
|
||||
{
|
||||
internal class Euros
|
||||
{
|
||||
public static async Task GetEuroMillionsData(string url, HttpClient client)
|
||||
{
|
||||
try
|
||||
{
|
||||
string html = await client.GetStringAsync(url);
|
||||
var eurosResult = new EurosResult();
|
||||
var doc = new HtmlDocument();
|
||||
doc.LoadHtml(html);
|
||||
|
||||
DrawBalls.ProcessBallSetUsed(doc, eurosResult);
|
||||
DrawDate.ProcessDrawDateFromMeta(doc, eurosResult); // Not working.
|
||||
DrawNumber.ProcessDrawNumberFromMeta(doc, eurosResult);
|
||||
DrawCode.ProcessMillionaireMaker(doc, eurosResult); // Not working.
|
||||
DrawStatus.ProcessRollover(doc, eurosResult);
|
||||
DrawBalls.ProcessMainBalls(doc, eurosResult);
|
||||
DrawBalls.ProcessLuckyStars(doc, eurosResult);
|
||||
DrawMachine.ProcessMachineUsed(doc, eurosResult);
|
||||
DrawWinnerInformation.ProcessWinnersTable(doc, eurosResult);
|
||||
|
||||
|
||||
CommitToDatabase.SaveModelToDatabase(eurosResult);
|
||||
}
|
||||
catch (HttpRequestException ex)
|
||||
{
|
||||
// ToDo: Logger HTTP request error: {ex.Message}
|
||||
Console.WriteLine(ex.Message);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// ToDo: Logger - An error occurred: {ex.Message}
|
||||
Console.WriteLine(ex.Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,140 +1,245 @@
|
||||
using HtmlAgilityPack;
|
||||
using lottery_co_uk_scraper.core.Models;
|
||||
using lottery_co_uk_scraper.Utilities;
|
||||
using static lottery_co_uk_scraper.NationalLottery.Lotto;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using static lottery_co_uk_scraper.NationalLottery.DrawWinnerInformation;
|
||||
|
||||
namespace lottery_co_uk_scraper.NationalLottery
|
||||
{
|
||||
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, LottoResult lottoResult)
|
||||
{
|
||||
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))
|
||||
try
|
||||
{
|
||||
Console.WriteLine("Ball set used: " + ballSetUsed);
|
||||
var ballSetUsedString = doc.DocumentNode.Descendants("td")
|
||||
.Where(x => x.InnerHtml.Contains("<strong>Ball Set Used:</strong>"))
|
||||
.Select(x => x.InnerText.Split(':')[1].Trim())
|
||||
.FirstOrDefault();
|
||||
|
||||
AssignBallSetToModelProperty(LotteryTableRow.BallSetUsed, ballSetUsed, lottoResult);
|
||||
if (int.TryParse(ballSetUsedString, out int ballSetUsed))
|
||||
{
|
||||
Console.WriteLine("Ball set used: " + ballSetUsed);
|
||||
|
||||
return ballSetUsed;
|
||||
AssignBallSetToModelProperty(LotteryTableRow.BallSetUsed, ballSetUsed, lottoResult);
|
||||
|
||||
return ballSetUsed;
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.LogInformation("Failed to parse Lotto Ball Set Used.");
|
||||
|
||||
throw new Exception("Failed to parse Lotto Ball Set Used.");
|
||||
}
|
||||
}
|
||||
else
|
||||
catch
|
||||
{
|
||||
Console.WriteLine("Failed to parse Ball Set Used.");
|
||||
throw new Exception("Failed to parse Lotto Ball Set Used.");
|
||||
}
|
||||
}
|
||||
|
||||
return 0; // or throw an exception
|
||||
public static void AssignBallSetToModelProperty(string containerNode, int ballSetUsed, LottoResult lottoResult)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (containerNode == LotteryTableRow.BallSetUsed)
|
||||
{
|
||||
PropertyManager.SetProperty(nameof(lottoResult.BallSetUsed), lottoResult, ballSetUsed);
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
_logger.LogError("Failed to parse {containerNode}", containerNode);
|
||||
|
||||
throw new Exception($"Failed to parse {containerNode}");
|
||||
}
|
||||
}
|
||||
|
||||
public static void ProcessMainBalls(HtmlDocument doc, LottoResult lottoResult)
|
||||
{
|
||||
try
|
||||
{
|
||||
var ballsDrawn = GetNodeById(doc.DocumentNode, LotteryTableRow.BallsDrawn);
|
||||
|
||||
List<int>? lottoBalls = ballsDrawn != null
|
||||
? ExtractBalls(ballsDrawn, "lotto-ball")
|
||||
: null;
|
||||
|
||||
if (lottoBalls != null)
|
||||
{
|
||||
AssignDrawBallsToModelProperty(LotteryTableRow.BallsDrawn, lottoBalls, lottoResult);
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.LogError("Lotto Draw Balls were null!");
|
||||
|
||||
throw new Exception("Lotto Draw Balls were null!");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError("There was a problem processing the Lotto Draw Balls. {Message}", ex.Message);
|
||||
|
||||
throw new Exception($"There was a problem processing the Lotto Draw Balls. {ex}");
|
||||
}
|
||||
}
|
||||
|
||||
private static List<int> ExtractBalls(HtmlNode ballsNode, string className)
|
||||
{
|
||||
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))
|
||||
try
|
||||
{
|
||||
return ballsNode.Descendants("span")
|
||||
.Where(x => x.Attributes["class"] != null && x.Attributes["class"].Value.Contains(className))
|
||||
.Select(x =>
|
||||
{
|
||||
return ball;
|
||||
}
|
||||
if (int.TryParse(x.InnerText, out int ball))
|
||||
{
|
||||
return ball;
|
||||
}
|
||||
|
||||
Console.WriteLine($"Failed to parse {className} value: {x.InnerText}");
|
||||
_logger.LogError("Failed to parse {className} value: {x.InnerText}", className, x.InnerText);
|
||||
|
||||
return 0;
|
||||
})
|
||||
.ToList();
|
||||
}
|
||||
|
||||
public static void ProcessMainBalls(HtmlDocument doc, LottoResult lottoResult)
|
||||
{
|
||||
var ballsDrawn = GetNodeById(doc.DocumentNode, LotteryTableRow.BallsDrawn);
|
||||
|
||||
List<int>? lottoBalls = ballsDrawn != null
|
||||
? ExtractBalls(ballsDrawn, "lotto-ball")
|
||||
: null;
|
||||
|
||||
AssignDrawBallsToModelProperty(LotteryTableRow.BallsDrawn, lottoBalls, lottoResult);
|
||||
}
|
||||
|
||||
private static HtmlNode GetNodeById(HtmlNode containerNode, string nodeId)
|
||||
{
|
||||
return containerNode.DescendantsAndSelf()
|
||||
.FirstOrDefault(x => x.Attributes["id"] != null && x.Attributes["id"].Value == nodeId)
|
||||
?? throw new InvalidOperationException($"Node with ID '{nodeId}' not found.");
|
||||
}
|
||||
|
||||
public static void AssignBallSetToModelProperty(string containerNode, int ballSetUsed, LottoResult lottoResult)
|
||||
{
|
||||
if (containerNode == LotteryTableRow.BallSetUsed)
|
||||
{
|
||||
PropertyManager.SetProperty(nameof(lottoResult.BallSetUsed), lottoResult, ballSetUsed);
|
||||
throw new Exception($"Failed to parse {className} value: {x.InnerText}");
|
||||
})
|
||||
.ToList();
|
||||
}
|
||||
}
|
||||
|
||||
public static void ProcessBonusBalls(HtmlDocument doc, LottoResult lottoResult)
|
||||
{
|
||||
var ballsDrawn = GetNodeById(doc.DocumentNode, LotteryTableRow.BallsDrawn);
|
||||
|
||||
int? lottoBonusBall = ballsDrawn != null
|
||||
? ExtractBonusBall(ballsDrawn, "lotto-bonus-ball")
|
||||
: (int?)null;
|
||||
|
||||
AssignBonusBallToModelProperty(LotteryTableRow.BallsDrawn, lottoBonusBall, lottoResult);
|
||||
}
|
||||
|
||||
private static int? ExtractBonusBall(HtmlNode ballsDrawn, string ballClass)
|
||||
{
|
||||
var bonusBallNode = ballsDrawn.Descendants("span")
|
||||
.FirstOrDefault(x => x.HasClass(ballClass));
|
||||
|
||||
if (bonusBallNode != null && int.TryParse(bonusBallNode.InnerText, out int bonusBall))
|
||||
catch
|
||||
{
|
||||
Console.WriteLine("Bonus Ball: " + bonusBall);
|
||||
return bonusBall;
|
||||
}
|
||||
|
||||
Console.WriteLine("Failed to extract Bonus Ball.");
|
||||
return null;
|
||||
}
|
||||
|
||||
public static void AssignBonusBallToModelProperty(string containerNode, int? ballInformation, LottoResult lottoResult)
|
||||
{
|
||||
if (containerNode == LotteryTableRow.BallsDrawn)
|
||||
{
|
||||
if (ballInformation.HasValue)
|
||||
{
|
||||
PropertyManager.SetProperty(nameof(lottoResult.DrawnBonusBall), lottoResult, ballInformation.Value);
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine("Invalid Bonus Ball information.");
|
||||
}
|
||||
throw new Exception($"Failed to parse {className}");
|
||||
}
|
||||
}
|
||||
|
||||
public static void AssignDrawBallsToModelProperty(string containerNode, object ballInformation, LottoResult lottoResult)
|
||||
{
|
||||
if (containerNode == LotteryTableRow.BallsDrawn)
|
||||
try
|
||||
{
|
||||
if (ballInformation is List<int> balls && balls.Count >= 6)
|
||||
if (containerNode == LotteryTableRow.BallsDrawn)
|
||||
{
|
||||
for (int i = 0; i < 6; i++)
|
||||
if (ballInformation is List<int> balls && balls.Count >= 6)
|
||||
{
|
||||
string propertyName = $"DrawnBall{i + 1}";
|
||||
PropertyManager.SetProperty(propertyName, lottoResult, balls[i]);
|
||||
for (int i = 0; i < 6; i++)
|
||||
{
|
||||
string propertyName = $"DrawnBall{i + 1}";
|
||||
PropertyManager.SetProperty(propertyName, lottoResult, balls[i]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.LogError("Invalid drawn balls information.");
|
||||
|
||||
throw new Exception("Invalid drawn balls information.");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine("Invalid drawn balls information.");
|
||||
_logger.LogError("Unhandled containerNode: {containerNode}", containerNode);
|
||||
|
||||
throw new Exception($"Unhandled containerNode: {containerNode}");
|
||||
}
|
||||
}
|
||||
else
|
||||
catch
|
||||
{
|
||||
Console.WriteLine($"Unhandled containerNode: {containerNode}");
|
||||
throw new Exception($"Unhandled containerNode: {containerNode}");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static void ProcessBonusBalls(HtmlDocument doc, LottoResult lottoResult)
|
||||
{
|
||||
try
|
||||
{
|
||||
var ballsDrawn = GetNodeById(doc.DocumentNode, LotteryTableRow.BallsDrawn);
|
||||
|
||||
int? lottoBonusBall = ballsDrawn != null
|
||||
? ExtractBonusBall(ballsDrawn, "lotto-bonus-ball")
|
||||
: (int?)null;
|
||||
|
||||
if (lottoBonusBall != null)
|
||||
{
|
||||
AssignBonusBallToModelProperty(LotteryTableRow.BallsDrawn, lottoBonusBall, lottoResult);
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.LogError("Bonus Ball appears to be null.");
|
||||
|
||||
throw new Exception("Bonus Ball appears 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 int? ExtractBonusBall(HtmlNode ballsDrawn, string ballClass)
|
||||
{
|
||||
try
|
||||
{
|
||||
var bonusBallNode = ballsDrawn.Descendants("span")
|
||||
.FirstOrDefault(x => x.HasClass(ballClass));
|
||||
|
||||
if (bonusBallNode != null && int.TryParse(bonusBallNode.InnerText, out int bonusBall))
|
||||
{
|
||||
return bonusBall;
|
||||
}
|
||||
|
||||
_logger.LogError("Failed to parse {className}", ballClass);
|
||||
|
||||
throw new Exception($"Failed to parse {ballClass}");
|
||||
}
|
||||
catch
|
||||
{
|
||||
_logger.LogError("There was a problem processing the Lotto Bonus Ball.");
|
||||
|
||||
throw new Exception($"There was a problem processing the Lotto Bonus Ball.");
|
||||
}
|
||||
}
|
||||
|
||||
public static void AssignBonusBallToModelProperty(string containerNode, int? ballInformation, LottoResult lottoResult)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (containerNode == LotteryTableRow.BallsDrawn)
|
||||
{
|
||||
if (ballInformation.HasValue)
|
||||
{
|
||||
PropertyManager.SetProperty(nameof(lottoResult.DrawnBonusBall), lottoResult, ballInformation.Value);
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.LogError("Invalid bonus ball information.");
|
||||
|
||||
throw new Exception("Invalid bonus ball information.");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.LogError("Unhandled containerNode: {containerNode}", containerNode);
|
||||
|
||||
throw new Exception($"Unhandled containerNode: {containerNode}");
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
throw new Exception($"Unhandled containerNode: {containerNode}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
using HtmlAgilityPack;
|
||||
using lottery_co_uk_scraper.core.Models;
|
||||
using lottery_co_uk_scraper.Utilities;
|
||||
using System.Globalization;
|
||||
|
||||
namespace lottery_co_uk_scraper.NationalLottery
|
||||
{
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using HtmlAgilityPack;
|
||||
using lottery_co_uk_scraper.core.Exceptions;
|
||||
using lottery_co_uk_scraper.core.Models;
|
||||
using lottery_co_uk_scraper.Utilities;
|
||||
|
||||
@@ -8,20 +9,39 @@ namespace lottery_co_uk_scraper.NationalLottery
|
||||
{
|
||||
public static string ProcessMachineUsed(HtmlDocument doc, LottoResult lottoResult)
|
||||
{
|
||||
var machineName = doc.DocumentNode.Descendants("td")
|
||||
.Where(x => x.InnerHtml.Contains("<strong>Ball Machine Used:</strong>"))
|
||||
.Select(x => x.InnerText.Split(':')[1].Trim())
|
||||
.FirstOrDefault();
|
||||
try
|
||||
{
|
||||
var machineName = doc.DocumentNode.Descendants("td")
|
||||
.Where(x => x.InnerHtml.Contains("<strong>Ball Machine Used:</strong>"))
|
||||
.Select(x => x.InnerText.Split(':')[1].Trim())
|
||||
.FirstOrDefault();
|
||||
|
||||
AssignDrawMachineToModelProperty("MachineName", machineName, lottoResult);
|
||||
Console.WriteLine("Machine Name: " + machineName);
|
||||
// should there be a try parse and error exception stuff here like in ballSetUsed
|
||||
return machineName;
|
||||
if (machineName != null)
|
||||
{
|
||||
AssignDrawMachineToModelProperty(nameof(lottoResult.MachineUsed), machineName, lottoResult);
|
||||
|
||||
return machineName;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new NullResultException(nameof(lottoResult.MachineUsed) + " is null.");
|
||||
}
|
||||
}
|
||||
catch (NullResultException nullEx)
|
||||
{
|
||||
return nullEx.Message;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// ToDo: _logger.LogErrorMessage();
|
||||
|
||||
return ex.Message;
|
||||
}
|
||||
}
|
||||
|
||||
public static void AssignDrawMachineToModelProperty(string propertyName, string machineName, LottoResult lottoResult)
|
||||
{
|
||||
PropertyManager.SetProperty(nameof(lottoResult.MachineUsed), lottoResult, machineName);
|
||||
PropertyManager.SetProperty(propertyName, lottoResult, machineName);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -10,7 +10,6 @@ namespace lottery_co_uk_scraper.NationalLottery
|
||||
{
|
||||
var rolloverElement = doc.DocumentNode.Descendants("span")
|
||||
.FirstOrDefault(x => x.InnerText.Trim() == "Rollover");
|
||||
|
||||
bool rollover = rolloverElement != null;
|
||||
|
||||
if (rollover)
|
||||
@@ -30,7 +29,6 @@ namespace lottery_co_uk_scraper.NationalLottery
|
||||
{
|
||||
var rolldownElement = doc.DocumentNode.Descendants("span")
|
||||
.FirstOrDefault(x => x.InnerText.Trim() == "Rolldown");
|
||||
|
||||
bool rolldown = rolldownElement != null;
|
||||
|
||||
if (rolldown)
|
||||
|
||||
@@ -1,64 +1,100 @@
|
||||
using HtmlAgilityPack;
|
||||
using lottery_co_uk_scraper.core.Models;
|
||||
using static lottery_co_uk_scraper.NationalLottery.Lotto;
|
||||
using System.Globalization;
|
||||
using lottery_co_uk_scraper.Utilities;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace lottery_co_uk_scraper.NationalLottery
|
||||
{
|
||||
internal class DrawWinnerInformation
|
||||
internal partial class DrawWinnerInformation
|
||||
{
|
||||
[GeneratedRegex(@"(\d+)")]
|
||||
private static partial Regex MyRegex();
|
||||
|
||||
internal static class LotteryTableRow
|
||||
{
|
||||
internal const string Match2 = "Match 2";
|
||||
internal const string Match3 = "Match 3";
|
||||
internal const string Match4 = "Match 4";
|
||||
internal const string Match5 = "Match 5";
|
||||
internal const string Match5Bonus = "Match 5 plus Bonus";
|
||||
internal const string Match6 = "Match 6";
|
||||
internal const string Total = "Totals";
|
||||
internal const string Winners = "Winners";
|
||||
internal const string PrizePerWinner = "Prize Per Winner";
|
||||
internal const string PrizeFundAmount = "Prize Fund Amount";
|
||||
internal const string BallSetUsed = "ballSetUsed";
|
||||
internal const string BallsDrawn = "ballsDrawn";
|
||||
}
|
||||
|
||||
public static void ProcessTableSection(HtmlNode table, string sectionTitle, LottoResult lottoResult)
|
||||
{
|
||||
var sectionRow = GetSectionRowByTitle(table, sectionTitle);
|
||||
|
||||
if (sectionRow != null)
|
||||
try
|
||||
{
|
||||
var winnersNode = GetNodeByDataTitle(sectionRow, LotteryTableRow.Winners);
|
||||
var prizePerWinnerNode = GetNodeByDataTitle(sectionRow, LotteryTableRow.PrizePerWinner);
|
||||
var prizeFundNode = GetNodeByDataTitle(sectionRow, LotteryTableRow.PrizeFundAmount);
|
||||
var rolldown = lottoResult.Rolldown;
|
||||
var sectionRow = GetSectionRowByTitle(table, sectionTitle);
|
||||
|
||||
if (winnersNode != null && prizePerWinnerNode != null && prizeFundNode != null)
|
||||
if (sectionRow != null)
|
||||
{
|
||||
ProcessWinners(sectionTitle, winnersNode, lottoResult);
|
||||
ProcessPrizeFundAmount(sectionTitle, prizeFundNode, lottoResult);
|
||||
var winnersNode = GetNodeByDataTitle(sectionRow, LotteryTableRow.Winners);
|
||||
var prizePerWinnerNode = GetNodeByDataTitle(sectionRow, LotteryTableRow.PrizePerWinner);
|
||||
var prizeFundNode = GetNodeByDataTitle(sectionRow, LotteryTableRow.PrizeFundAmount);
|
||||
var rolldown = lottoResult.Rolldown;
|
||||
|
||||
if (rolldown == false)
|
||||
if (winnersNode != null && prizePerWinnerNode != null && prizeFundNode != null)
|
||||
{
|
||||
ProcessWinnerPrizeAmount(sectionTitle, prizePerWinnerNode, lottoResult);
|
||||
ProcessWinners(sectionTitle, winnersNode, lottoResult);
|
||||
ProcessPrizeFundAmount(sectionTitle, prizeFundNode, lottoResult);
|
||||
|
||||
if (rolldown == false)
|
||||
{
|
||||
ProcessWinnerPrizeAmount(sectionTitle, prizePerWinnerNode, lottoResult);
|
||||
}
|
||||
else
|
||||
{
|
||||
ProcessRolldownWinnerPrizeAmount(sectionTitle, prizePerWinnerNode, lottoResult);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ProcessRolldownWinnerPrizeAmount(sectionTitle, prizePerWinnerNode, lottoResult);
|
||||
Console.WriteLine("Missing winners, prize per winner, or prize fund nodes in the table.");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine("Missing winners, prize per winner, or prize fund nodes in the table.");
|
||||
Console.WriteLine($"Section title '{sectionTitle}' not found in the table.");
|
||||
}
|
||||
}
|
||||
else
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"Section title '{sectionTitle}' not found in the table.");
|
||||
// ToDo: _logger.LogError
|
||||
throw new Exception(ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
private static HtmlNode GetSectionRowByTitle(HtmlNode table, string sectionTitle)
|
||||
{
|
||||
var sectionRow = table.Descendants("tr")
|
||||
.FirstOrDefault(x =>
|
||||
x.Descendants("td").Any(y => y.InnerText.Contains(sectionTitle, StringComparison.OrdinalIgnoreCase))
|
||||
);
|
||||
try
|
||||
{
|
||||
var sectionRow = table.Descendants("tr")
|
||||
.FirstOrDefault(x => x.Descendants("td").Any(y => y.InnerText.Contains(sectionTitle, StringComparison.OrdinalIgnoreCase)));
|
||||
|
||||
if (sectionRow != null)
|
||||
{
|
||||
return sectionRow;
|
||||
if (sectionRow != null)
|
||||
{
|
||||
return sectionRow;
|
||||
}
|
||||
else
|
||||
{
|
||||
// ToDo: _logger.LogError
|
||||
throw new Exception("sectionRow is null.");
|
||||
}
|
||||
}
|
||||
else
|
||||
catch (Exception ex)
|
||||
{
|
||||
return null;
|
||||
// ToDo: _logger.LogError
|
||||
throw new Exception(ex.Message);
|
||||
}
|
||||
|
||||
throw new Exception("Failed to get section by row title.");
|
||||
}
|
||||
|
||||
private static HtmlNode GetNodeByDataTitle(HtmlNode sectionRow, string dataTitle)
|
||||
@@ -70,26 +106,37 @@ namespace lottery_co_uk_scraper.NationalLottery
|
||||
|
||||
public static void ProcessWinnersTable(HtmlDocument doc, LottoResult lottoResult)
|
||||
{
|
||||
var table = doc.DocumentNode.Descendants("table")
|
||||
.FirstOrDefault(x => x.Attributes["class"] != null && x.Attributes["class"].Value.Contains("lotto mobFormat"));
|
||||
|
||||
if (table != null)
|
||||
try
|
||||
{
|
||||
HtmlNode match2Section = GetSectionRowByTitle(table, LotteryTableRow.Match2);
|
||||
if (match2Section != null)
|
||||
var table = doc.DocumentNode.Descendants("table")
|
||||
.FirstOrDefault(x => x.Attributes["class"] != null && x.Attributes["class"].Value.Contains("lotto mobFormat"));
|
||||
|
||||
if (table != null)
|
||||
{
|
||||
ProcessTableSection(table, LotteryTableRow.Match2, lottoResult);
|
||||
HtmlNode match2Section = GetSectionRowByTitle(table, LotteryTableRow.Match2);
|
||||
if (match2Section != null)
|
||||
{
|
||||
ProcessTableSection(table, LotteryTableRow.Match2, lottoResult);
|
||||
}
|
||||
else
|
||||
{
|
||||
// ToDo: I don't need this write line, log the information about it being a draw with no match twos.
|
||||
//_logger.LogInformation("");
|
||||
Console.WriteLine("Section row with title 'Match 2' not found. Continuing without processing Match 2.");
|
||||
}
|
||||
|
||||
ProcessTableSection(table, LotteryTableRow.Match3, lottoResult);
|
||||
ProcessTableSection(table, LotteryTableRow.Match4, lottoResult);
|
||||
ProcessTableSection(table, LotteryTableRow.Match5, lottoResult);
|
||||
ProcessTableSection(table, LotteryTableRow.Match5Bonus, lottoResult);
|
||||
ProcessTableSection(table, LotteryTableRow.Match6, lottoResult);
|
||||
ProcessTableSection(table, LotteryTableRow.Total, lottoResult);
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine("Section row with title 'Match 2' not found. Continuing without processing Match 2.");
|
||||
}
|
||||
ProcessTableSection(table, LotteryTableRow.Match3, lottoResult);
|
||||
ProcessTableSection(table, LotteryTableRow.Match4, lottoResult);
|
||||
ProcessTableSection(table, LotteryTableRow.Match5, lottoResult);
|
||||
ProcessTableSection(table, LotteryTableRow.Match5Bonus, lottoResult);
|
||||
ProcessTableSection(table, LotteryTableRow.Match6, lottoResult);
|
||||
ProcessTableSection(table, LotteryTableRow.Total, lottoResult);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
//_logger.LogError("");
|
||||
throw new Exception(ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -97,126 +144,196 @@ namespace lottery_co_uk_scraper.NationalLottery
|
||||
{
|
||||
switch (sectionTitle)
|
||||
{
|
||||
#region Match 2
|
||||
case LotteryTableRow.Match2:
|
||||
if (columnTitle == LotteryTableRow.Winners)
|
||||
try
|
||||
{
|
||||
PropertyManager.SetProperty(nameof(lottoResult.TotalMatched2), lottoResult, value);
|
||||
if (columnTitle == LotteryTableRow.Winners)
|
||||
{
|
||||
PropertyManager.SetProperty(nameof(lottoResult.TotalMatched2), lottoResult, value);
|
||||
}
|
||||
|
||||
if (columnTitle == LotteryTableRow.PrizePerWinner)
|
||||
{
|
||||
PropertyManager.SetProperty(nameof(lottoResult.Matched2Prize), lottoResult, value);
|
||||
}
|
||||
|
||||
if (columnTitle == LotteryTableRow.PrizeFundAmount)
|
||||
{
|
||||
PropertyManager.SetProperty(nameof(lottoResult.Matched2PrizeFund), lottoResult, value);
|
||||
}
|
||||
}
|
||||
catch(Exception ex)
|
||||
{
|
||||
// ToDo: _logger.LogError
|
||||
throw new Exception(ex.Message);
|
||||
}
|
||||
|
||||
if (columnTitle == LotteryTableRow.PrizePerWinner)
|
||||
{
|
||||
PropertyManager.SetProperty(nameof(lottoResult.Matched2Prize), lottoResult, value);
|
||||
}
|
||||
|
||||
if (columnTitle == LotteryTableRow.PrizeFundAmount)
|
||||
{
|
||||
PropertyManager.SetProperty(nameof(lottoResult.Matched2PrizeFund), lottoResult, value);
|
||||
}
|
||||
|
||||
break;
|
||||
break;
|
||||
#endregion
|
||||
|
||||
#region Match 3
|
||||
case LotteryTableRow.Match3:
|
||||
if (columnTitle == LotteryTableRow.Winners)
|
||||
try
|
||||
{
|
||||
PropertyManager.SetProperty(nameof(lottoResult.TotalMatched3), lottoResult, value);
|
||||
if (columnTitle == LotteryTableRow.Winners)
|
||||
{
|
||||
PropertyManager.SetProperty(nameof(lottoResult.TotalMatched3), lottoResult, value);
|
||||
}
|
||||
|
||||
if (columnTitle == LotteryTableRow.PrizePerWinner)
|
||||
{
|
||||
PropertyManager.SetProperty(nameof(lottoResult.Matched3Prize), lottoResult, value);
|
||||
}
|
||||
|
||||
if (columnTitle == LotteryTableRow.PrizeFundAmount)
|
||||
{
|
||||
PropertyManager.SetProperty(nameof(lottoResult.Matched3PrizeFund), lottoResult, value);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// ToDo: _logger.LogError
|
||||
throw new Exception(ex.Message);
|
||||
}
|
||||
|
||||
if (columnTitle == LotteryTableRow.PrizePerWinner)
|
||||
{
|
||||
PropertyManager.SetProperty(nameof(lottoResult.Matched3Prize), lottoResult, value);
|
||||
}
|
||||
|
||||
if (columnTitle == LotteryTableRow.PrizeFundAmount)
|
||||
{
|
||||
PropertyManager.SetProperty(nameof(lottoResult.Matched3PrizeFund), lottoResult, value);
|
||||
}
|
||||
|
||||
break;
|
||||
break;
|
||||
#endregion
|
||||
|
||||
#region Match 4
|
||||
case LotteryTableRow.Match4:
|
||||
if (columnTitle == LotteryTableRow.Winners)
|
||||
try
|
||||
{
|
||||
PropertyManager.SetProperty(nameof(lottoResult.TotalMatched4), lottoResult, value);
|
||||
if (columnTitle == LotteryTableRow.Winners)
|
||||
{
|
||||
PropertyManager.SetProperty(nameof(lottoResult.TotalMatched4), lottoResult, value);
|
||||
}
|
||||
|
||||
if (columnTitle == LotteryTableRow.PrizePerWinner)
|
||||
{
|
||||
PropertyManager.SetProperty(nameof(lottoResult.Matched4Prize), lottoResult, value);
|
||||
}
|
||||
|
||||
if (columnTitle == LotteryTableRow.PrizeFundAmount)
|
||||
{
|
||||
PropertyManager.SetProperty(nameof(lottoResult.Matched4PrizeFund), lottoResult, value);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// ToDo: _logger.LogError
|
||||
throw new Exception(ex.Message);
|
||||
}
|
||||
|
||||
if (columnTitle == LotteryTableRow.PrizePerWinner)
|
||||
{
|
||||
PropertyManager.SetProperty(nameof(lottoResult.Matched4Prize), lottoResult, value);
|
||||
}
|
||||
|
||||
if (columnTitle == LotteryTableRow.PrizeFundAmount)
|
||||
{
|
||||
PropertyManager.SetProperty(nameof(lottoResult.Matched4PrizeFund), lottoResult, value);
|
||||
}
|
||||
|
||||
break;
|
||||
break;
|
||||
#endregion
|
||||
|
||||
#region Match 5
|
||||
case LotteryTableRow.Match5:
|
||||
if (columnTitle == LotteryTableRow.Winners)
|
||||
try
|
||||
{
|
||||
PropertyManager.SetProperty(nameof(lottoResult.TotalMatched5), lottoResult, value);
|
||||
if (columnTitle == LotteryTableRow.Winners)
|
||||
{
|
||||
PropertyManager.SetProperty(nameof(lottoResult.TotalMatched5), lottoResult, value);
|
||||
}
|
||||
|
||||
if (columnTitle == LotteryTableRow.PrizePerWinner)
|
||||
{
|
||||
PropertyManager.SetProperty(nameof(lottoResult.Matched5Prize), lottoResult, value);
|
||||
}
|
||||
|
||||
if (columnTitle == LotteryTableRow.PrizeFundAmount)
|
||||
{
|
||||
PropertyManager.SetProperty(nameof(lottoResult.Matched5PrizeFund), lottoResult, value);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// ToDo: _logger.LogError
|
||||
throw new Exception(ex.Message);
|
||||
}
|
||||
|
||||
if (columnTitle == LotteryTableRow.PrizePerWinner)
|
||||
{
|
||||
PropertyManager.SetProperty(nameof(lottoResult.Matched5Prize), lottoResult, value);
|
||||
}
|
||||
|
||||
if (columnTitle == LotteryTableRow.PrizeFundAmount)
|
||||
{
|
||||
PropertyManager.SetProperty(nameof(lottoResult.Matched5PrizeFund), lottoResult, value);
|
||||
}
|
||||
|
||||
break;
|
||||
break;
|
||||
#endregion
|
||||
|
||||
#region Match 5 + Bonus
|
||||
case LotteryTableRow.Match5Bonus:
|
||||
if (columnTitle == LotteryTableRow.Winners)
|
||||
try
|
||||
{
|
||||
PropertyManager.SetProperty(nameof(lottoResult.TotalMatched5PlusBonus), lottoResult, value);
|
||||
if (columnTitle == LotteryTableRow.Winners)
|
||||
{
|
||||
PropertyManager.SetProperty(nameof(lottoResult.TotalMatched5PlusBonus), lottoResult, value);
|
||||
}
|
||||
|
||||
if (columnTitle == LotteryTableRow.PrizePerWinner)
|
||||
{
|
||||
PropertyManager.SetProperty(nameof(lottoResult.Matched5PlusBonusPrize), lottoResult, value);
|
||||
}
|
||||
|
||||
if (columnTitle == LotteryTableRow.PrizeFundAmount)
|
||||
{
|
||||
PropertyManager.SetProperty(nameof(lottoResult.Matched5PlusBonusPrizeFund), lottoResult, value);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// ToDo: _logger.LogError
|
||||
throw new Exception(ex.Message);
|
||||
}
|
||||
|
||||
if (columnTitle == LotteryTableRow.PrizePerWinner)
|
||||
{
|
||||
PropertyManager.SetProperty(nameof(lottoResult.Matched5PlusBonusPrize), lottoResult, value);
|
||||
}
|
||||
|
||||
if (columnTitle == LotteryTableRow.PrizeFundAmount)
|
||||
{
|
||||
PropertyManager.SetProperty(nameof(lottoResult.Matched5PlusBonusPrizeFund), lottoResult, value);
|
||||
}
|
||||
|
||||
break;
|
||||
break;
|
||||
#endregion
|
||||
|
||||
#region Match 6
|
||||
case LotteryTableRow.Match6:
|
||||
if (columnTitle == LotteryTableRow.Winners)
|
||||
try
|
||||
{
|
||||
PropertyManager.SetProperty(nameof(lottoResult.TotalMatched6), lottoResult, value);
|
||||
if (columnTitle == LotteryTableRow.Winners)
|
||||
{
|
||||
PropertyManager.SetProperty(nameof(lottoResult.TotalMatched6), lottoResult, value);
|
||||
}
|
||||
|
||||
if (columnTitle == LotteryTableRow.PrizePerWinner)
|
||||
{
|
||||
PropertyManager.SetProperty(nameof(lottoResult.Matched6Prize), lottoResult, value);
|
||||
}
|
||||
|
||||
if (columnTitle == LotteryTableRow.PrizeFundAmount)
|
||||
{
|
||||
PropertyManager.SetProperty(nameof(lottoResult.Matched6PrizeFund), lottoResult, value);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// ToDo: _logger.LogError
|
||||
throw new Exception(ex.Message);
|
||||
}
|
||||
|
||||
if (columnTitle == LotteryTableRow.PrizePerWinner)
|
||||
{
|
||||
PropertyManager.SetProperty(nameof(lottoResult.Matched6Prize), lottoResult, value);
|
||||
}
|
||||
|
||||
if (columnTitle == LotteryTableRow.PrizeFundAmount)
|
||||
{
|
||||
PropertyManager.SetProperty(nameof(lottoResult.Matched6PrizeFund), lottoResult, value);
|
||||
}
|
||||
|
||||
break;
|
||||
break;
|
||||
#endregion
|
||||
|
||||
#region Totals
|
||||
case LotteryTableRow.Total:
|
||||
if (columnTitle == LotteryTableRow.Winners)
|
||||
try
|
||||
{
|
||||
PropertyManager.SetProperty(nameof(lottoResult.TotalWinners), lottoResult, value);
|
||||
if (columnTitle == LotteryTableRow.Winners)
|
||||
{
|
||||
PropertyManager.SetProperty(nameof(lottoResult.TotalWinners), lottoResult, value);
|
||||
}
|
||||
|
||||
if (columnTitle == LotteryTableRow.PrizeFundAmount)
|
||||
{
|
||||
PropertyManager.SetProperty(nameof(lottoResult.TotalPrizeFund), lottoResult, value);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// ToDo: _logger.LogError
|
||||
throw new Exception(ex.Message);
|
||||
}
|
||||
|
||||
if (columnTitle == LotteryTableRow.PrizeFundAmount)
|
||||
{
|
||||
PropertyManager.SetProperty(nameof(lottoResult.TotalPrizeFund), lottoResult, value);
|
||||
}
|
||||
|
||||
break;
|
||||
break;
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -419,7 +536,7 @@ namespace lottery_co_uk_scraper.NationalLottery
|
||||
|
||||
var textNodes = htmlDoc.DocumentNode.DescendantsAndSelf().Where(n => n.NodeType == HtmlNodeType.Text);
|
||||
|
||||
var numericValues = textNodes.SelectMany(n => Regex.Matches(n.InnerHtml, @"(\d+)").Cast<Match>())
|
||||
var numericValues = textNodes.SelectMany(n => MyRegex().Matches(n.InnerHtml).Cast<Match>())
|
||||
.Select(match => int.Parse(match.Groups[1].Value))
|
||||
.ToList();
|
||||
|
||||
@@ -449,7 +566,6 @@ namespace lottery_co_uk_scraper.NationalLottery
|
||||
|
||||
string columnTitle = prizePerWinnerNode.Attributes["data-title"].Value;
|
||||
|
||||
// Now you can use regularPrizePerWinner and rolldownPrizePerWinner as needed
|
||||
Console.WriteLine($"Prize per winner ({sectionTitle}): {regularPrizePerWinner}");
|
||||
Console.WriteLine($"Rolldown Prize per winner ({sectionTitle}): {rolldownPrizePerWinner}");
|
||||
|
||||
|
||||
@@ -11,7 +11,6 @@ namespace lottery_co_uk_scraper.NationalLottery
|
||||
try
|
||||
{
|
||||
string html = await client.GetStringAsync(url);
|
||||
|
||||
var doc = new HtmlDocument();
|
||||
doc.LoadHtml(html);
|
||||
|
||||
@@ -26,7 +25,6 @@ namespace lottery_co_uk_scraper.NationalLottery
|
||||
DrawBalls.ProcessBonusBalls(doc, lottoResult);
|
||||
DrawMachine.ProcessMachineUsed(doc, lottoResult);
|
||||
DrawWinnerInformation.ProcessWinnersTable(doc, lottoResult);
|
||||
DrawStatus.ProcessRollover(doc, lottoResult);
|
||||
|
||||
CommitToDatabase.SaveModelToDatabase(lottoResult);
|
||||
}
|
||||
@@ -38,27 +36,6 @@ namespace lottery_co_uk_scraper.NationalLottery
|
||||
{
|
||||
Console.WriteLine($"An error occurred: {ex.Message}");
|
||||
}
|
||||
finally
|
||||
{
|
||||
//client.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
public static class LotteryTableRow
|
||||
{
|
||||
// ToDo: do away with this or put it somewhere more logical?
|
||||
public const string Match2 = "Match 2";
|
||||
public const string Match3 = "Match 3";
|
||||
public const string Match4 = "Match 4";
|
||||
public const string Match5 = "Match 5";
|
||||
public const string Match5Bonus = "Match 5 plus Bonus";
|
||||
public const string Match6 = "Match 6";
|
||||
public const string Total = "Totals";
|
||||
public const string Winners = "Winners";
|
||||
public const string PrizePerWinner = "Prize Per Winner";
|
||||
public const string PrizeFundAmount = "Prize Fund Amount";
|
||||
public const string BallSetUsed = "ballSetUsed";
|
||||
public const string BallsDrawn= "ballsDrawn";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -21,7 +21,7 @@ namespace lottery_co_uk_scraper
|
||||
|
||||
foreach (string extractedUrl in extractedUrls)
|
||||
{
|
||||
await Lotto.GetLottoNumbers(extractedUrl, client);
|
||||
//await Lotto.GetLottoNumbers(extractedUrl, client);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,31 +4,32 @@ namespace lottery_co_uk_scraper.Utilities
|
||||
{
|
||||
internal partial class URLExtractor
|
||||
{
|
||||
[GeneratedRegex(@"<a\s+href=""([^""]+)""")]
|
||||
private static partial Regex MyRegex();
|
||||
|
||||
public static async Task<List<string>> ExtractUrlsAsync(string url)
|
||||
{
|
||||
List<string> urls = new List<string>();
|
||||
List<string> urls = [];
|
||||
|
||||
using (HttpClient client = new HttpClient())
|
||||
using (HttpClient client = new())
|
||||
{
|
||||
string content = await client.GetStringAsync(url);
|
||||
MatchCollection matches = MyRegex().Matches(content);
|
||||
|
||||
foreach (Match match in matches)
|
||||
foreach (Match match in matches.Cast<Match>())
|
||||
{
|
||||
string capturedUrl = match.Groups[1].Value;
|
||||
|
||||
if (capturedUrl.StartsWith(""))
|
||||
if (capturedUrl.StartsWith("") || capturedUrl.StartsWith(""))
|
||||
{
|
||||
string modifiedUrl = "" + capturedUrl;
|
||||
urls.Add(modifiedUrl);
|
||||
}
|
||||
}
|
||||
}
|
||||
urls.Reverse();
|
||||
|
||||
return urls;
|
||||
}
|
||||
|
||||
[GeneratedRegex(@"<a\s+href=""([^""]+)""")]
|
||||
private static partial Regex MyRegex();
|
||||
}
|
||||
}
|
||||
@@ -9,8 +9,8 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="HtmlAgilityPack" Version="1.11.58" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="8.0.1">
|
||||
<PackageReference Include="HtmlAgilityPack" Version="1.11.59" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="8.0.2">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
@@ -21,4 +21,11 @@
|
||||
<ProjectReference Include="..\lottery-co-uk-scraper.data\lottery-co-uk-scraper.data.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Folder Include="EuroMillions\" />
|
||||
<Folder Include="NationalLottery\" />
|
||||
<Folder Include="SetForLife\" />
|
||||
<Folder Include="Thunderball\" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
Reference in New Issue
Block a user