From fee03021b1b29cafc600bf0297d51e533608d8e3 Mon Sep 17 00:00:00 2001 From: Martin Lee Date: Sun, 10 May 2020 22:42:46 +0100 Subject: [PATCH] Include Tims regexs to extract Class And Stick --- .../DataConverterHelperTests.cs | 25 ++++++++ .../Helpers/DataConverterHelper.cs | 58 +++++++++++++++++++ BritishHorseRacingApi/Models/Fixture.cs | 4 ++ BritishHorseRacingApi/Models/Race.cs | 3 +- 4 files changed, 89 insertions(+), 1 deletion(-) diff --git a/BritishHorseRacingApi.Tests/DataConverterHelperTests.cs b/BritishHorseRacingApi.Tests/DataConverterHelperTests.cs index d604d61..68f8344 100644 --- a/BritishHorseRacingApi.Tests/DataConverterHelperTests.cs +++ b/BritishHorseRacingApi.Tests/DataConverterHelperTests.cs @@ -47,6 +47,18 @@ namespace BritishHorseRacingApi.Tests //Assert Assert.Equal(totalMilliseconds, expectedValue); } + [Theory] + [InlineData("(GoingStick:5.3 on 01-12-2018 at 08:30) Hurdle 5.3 Chase 5.3 @ 0800", 5.3)] + [InlineData("ABANDONED - Abandoned (48 Hours)", null)] + [InlineData("", null)] + [InlineData("Chase - Good to Soft, Good in Places Hurdle - Good to Soft (Hurdle races on Outer/Flat course) Chase 7.5; Hurdle 7.1", 7.3)] + public void TestGoingStickExtraction(string goingStr, double? expectedValue) + { + //Act + var result = DataConverterHelper.ExtractGoingStick(goingStr); + //Assert + Assert.Equal(expectedValue, result); + } [Theory()] [InlineData("1m 1f 104y ", 2084)] @@ -63,6 +75,19 @@ namespace BritishHorseRacingApi.Tests //Assert Assert.Equal(expectedResult, result); } + + [Theory] + [InlineData("", null)] + [InlineData(null, null)] + [InlineData("THE 32Red CASINO NOVICE AUCTION STAKES (CLASS 5)", 5)] + [InlineData("THE BRITISH STALLION STUDS EBF KEGWORTH NOVICE STAKES (CLASS 4) (PLUS 10 RACE) (DIV II)", 4)] + public void TestRaceClassExtract(string raceName, int? expectedResult) + { + //Act + var result = DataConverterHelper.ExtractRaceClass(raceName); + //Assert + Assert.Equal(expectedResult, result); + } [Theory()] [InlineData("3/5", 1.6)] diff --git a/BritishHorseRacingApi/Helpers/DataConverterHelper.cs b/BritishHorseRacingApi/Helpers/DataConverterHelper.cs index f3c82ef..fdc89f9 100644 --- a/BritishHorseRacingApi/Helpers/DataConverterHelper.cs +++ b/BritishHorseRacingApi/Helpers/DataConverterHelper.cs @@ -1,4 +1,5 @@ using System; +using System.Linq; using System.Text; using System.Text.RegularExpressions; @@ -28,6 +29,47 @@ namespace BritishHorseRacingApi.Helpers ("furlongs", "f"), ("yards", "y")), RegexOptions.Compiled); + + private static Regex _raceClassExtractorRegex = new Regex(@"\(class([^)]*)\)", RegexOptions.Compiled | RegexOptions.IgnoreCase); + public static int? ExtractRaceClass(string raceName) + { + if (String.IsNullOrWhiteSpace(raceName)) + return null; + + var match = _raceClassExtractorRegex.Match(raceName); + if (!match.Success || match.Groups.Count < 1) + return null; + + var raceClassString = match.Groups[1].Value; + if (!int.TryParse(raceClassString, out int raceClassInt)) + return null; + + return raceClassInt; + } + + public static string GetGoingCategory(double? goingStick) + { + if (goingStick == null) + return null; + + if (goingStick < 6.4) + return "heavy"; + + if (goingStick < 7.1) + return "soft"; + + if (goingStick < 7.9) + return "good-soft"; + + if (goingStick < 8.6) + return "good"; + + if (goingStick < 9.9) + return "good-firm"; + + return "firm"; + } + public static int? DistanceStringToYards(string distance) { if (String.IsNullOrWhiteSpace(distance)) @@ -42,6 +84,20 @@ namespace BritishHorseRacingApi.Helpers return totalYards; } + public static Regex _goingStickRegexExtractor = new Regex(@"(\d+)(?:\.(\d{1,2}))?", RegexOptions.Compiled | RegexOptions.IgnoreCase); + public static double? ExtractGoingStick(string going) + { + var matches = _goingStickRegexExtractor.Matches(going); + var goingStickResults = matches.OfType() + .Where(e => e.Value.Contains(".")) + .Select(e => Convert.ToSingle(e.Value)) + .ToList(); + + if (goingStickResults.Count == 0) + return null; + + return Math.Round(goingStickResults.Average(), 2); + } private static string BuildExtractComponentsRegex(params (string label, string indicator)[] pairs) { var sb = new StringBuilder(); @@ -68,6 +124,8 @@ namespace BritishHorseRacingApi.Helpers return (int)TimeSpan.FromSeconds(lossDifference).TotalMilliseconds; } private static Regex _ratioRegex = new Regex("(?'Numerator'[0-9.]+)/(?'Denominator'[0-9.]+)", RegexOptions.Compiled); + + public static decimal? FractionOddsToDecimal(string fraction) { if (String.IsNullOrWhiteSpace(fraction)) diff --git a/BritishHorseRacingApi/Models/Fixture.cs b/BritishHorseRacingApi/Models/Fixture.cs index 3ed2dce..5b31ae4 100644 --- a/BritishHorseRacingApi/Models/Fixture.cs +++ b/BritishHorseRacingApi/Models/Fixture.cs @@ -1,3 +1,4 @@ +using BritishHorseRacingApi.Helpers; using System; namespace BritishHorseRacingApi.Models @@ -25,6 +26,9 @@ namespace BritishHorseRacingApi.Models public string TicketsLink { get; set; } public int? MajorEvent { get; set; } public string Going { get; set; } + public double? GoingStick() => DataConverterHelper.ExtractGoingStick(Going); + public string GoingCatergory => DataConverterHelper.GetGoingCategory(GoingStick()); + public string Weather { get; set; } public string Other { get; set; } public string Stalls { get; set; } diff --git a/BritishHorseRacingApi/Models/Race.cs b/BritishHorseRacingApi/Models/Race.cs index 6da7c30..ec8a21d 100644 --- a/BritishHorseRacingApi/Models/Race.cs +++ b/BritishHorseRacingApi/Models/Race.cs @@ -15,7 +15,7 @@ namespace BritishHorseRacingApi.Models public string AgeLimit { get; set; } public int PrizeAmount { get; set; } public string PrizeCurrency { get; set; } - public int RaceClass { get; set; } + public int? RaceClass { get; set; } public string RatingBand { get; set; } public string RawDistanceText { get; set; } public string DistanceUnits { get; set; } @@ -32,5 +32,6 @@ namespace BritishHorseRacingApi.Models public Regex _distanceExtractorRegex = new Regex(@"(?'miles'[0-9\.]*(?=m))?m? ?(?'furlongs'[0-9\.]*(?=f))?f? ?.*?(?'yards'[0-9\.]*(?=y))", RegexOptions.Compiled); public int? DistanceInYards() => DataConverterHelper.DistanceStringToYards(DistanceText); + public int? RaceClassFromName() => DataConverterHelper.ExtractRaceClass(RaceName); } }