Initial commit

This commit is contained in:
2020-04-13 15:16:46 +01:00
commit 17a40cb95f
81 changed files with 10120 additions and 0 deletions
@@ -0,0 +1,32 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="BritishHorseRacingApi" Version="1.0.43" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="3.1.2" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="3.1.2" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="3.1.2" />
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
<PackageReference Include="SuccessfulCode.BetfairApi" Version="1.0.11" />
<PackageReference Include="SuccessfulCodeTools" Version="1.0.8" />
<PackageReference Include="System.Data.SqlClient" Version="4.8.1" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\AutoBet.Db\AutoBet.Db.csproj" />
</ItemGroup>
<ItemGroup>
<Reference Include="SwiftyMessageHub.Core">
<HintPath>..\..\SwiftyMessageHub\SwiftyMessageHub.RabbitMq\bin\Debug\netstandard2.0\SwiftyMessageHub.Core.dll</HintPath>
</Reference>
<Reference Include="SwiftyMessageHub.RabbitMq">
<HintPath>..\..\SwiftyMessageHub\SwiftyMessageHub.RabbitMq\bin\Debug\netstandard2.0\SwiftyMessageHub.RabbitMq.dll</HintPath>
</Reference>
</ItemGroup>
</Project>
+14
View File
@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8" ?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<targets>
<target name="logfile" xsi:type="File" fileName="file.txt" />
<target name="logconsole" xsi:type="Console" />
</targets>
<rules>
<logger name="*" minlevel="Info" writeTo="logconsole" />
<logger name="*" minlevel="Debug" writeTo="logfile" />
</rules>
</nlog>
@@ -0,0 +1,31 @@
using AutoBet.DataRecorded.RaceResultsDataCollector;
using BritishHorseRacingApi;
using Microsoft.EntityFrameworkCore;
using SwiftyMessageHub.Core;
using System;
using System.Linq;
using System.Threading.Tasks;
namespace AutoBet.DataRecorded.MessageControllers
{
public class PostRaceDataCollectorController : MessageController
{
[MessageRoute]
public async Task LoadRaces(PostRaceDataCollectorDetails details)
{
var api = new ApiClient();
Console.WriteLine("Loading races");
using (var db = new Db.HorseRacingDataContext())
{
var results = await db.Races.Where(e => e.RaceDate.Date == details.DateToCollect.Date)
.Where(e => !db.RunnerResults.Any(e1 => e1.RaceId == e.RaceId))
.ToListAsync();
foreach (var result in results)
{
await CurrentContext.Hub.SendMessage(result);
}
}
}
}
}
@@ -0,0 +1,39 @@
using BritishHorseRacingApi;
using BritishHorseRacingApi.Models;
using SwiftyMessageHub.Core;
using System;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
namespace AutoBet.DataRecorded.MessageControllers
{
public class PostRaceRunnerCollectorController : MessageController
{
private static SemaphoreSlim _semaphore = new SemaphoreSlim(1);
[MessageRoute]
public async Task LoadRaces(Db.Race details)
{
var api = new ApiClient();
Console.WriteLine($"Getting results for race {details.RaceId}");
_semaphore.Wait();
PagedResult<RunnerResult> results;
try
{
results = await api.GetRaceResults(details.RaceDate.Year, details.RaceId, details.DivisionSequence);
}
catch(Exception ex)
{
throw;
}
finally
{
_semaphore.Release();
}
foreach (var result in results.Data)
{
await CurrentContext.Hub.SendMessage(result);
}
}
}
}
@@ -0,0 +1,69 @@
using BritishHorseRacingApi.Models;
using SwiftyMessageHub.Core;
using System;
using System.Linq;
using System.Threading.Tasks;
namespace AutoBet.DataRecorded.MessageControllers
{
public class PostRaceRunnerResultRecorderController : MessageController
{
[MessageRoute]
public async Task SaveRunnerResult(RunnerResult details)
{
Console.WriteLine($"Saving results for {details.RacehorseName}");
var dbRunnerResult = new Db.RunnerResult()
{
RaceId = details.RaceId,
YearOfRace = details.YearOfRace,
DivisionSequence = details.DivisionSequence,
HorseId = details.HorseId,
AnimalId = details.AnimalId,
ResultFinishPos = details.ResultFinishPos,
Status = details.Status,
Ran = details.Ran,
NonRunnerDeclaredReason = details.NonRunnerDeclaredReason,
NonRunnerDeclaredDate = details.NonRunnerDeclaredDate,
NonRunnerDeclaredTime = details.NonRunnerDeclaredTime,
RacehorseName = details.RacehorseName,
AgeYear = details.AgeYear,
Bred = details.Bred,
ClothNumber = details.ClothNumber,
DrawnStall = details.DrawnStall,
WeightValue = details.WeightValue,
SexType = details.SexType,
JockeyId = details.JockeyId,
JockeyName = details.JockeyName,
JockeyProfile = details.JockeyProfile,
TrainerId = details.TrainerId,
TrainerName = details.TrainerName,
OwnerId = details.OwnerId,
OwnerName = details.OwnerName,
WbSilkCode = details.WbSilkCode,
WbSilkDescription = details.WbSilkDescription,
SilkImage = details.SilkImage,
Plus10 = details.Plus10,
ResultBtnDistance = details.ResultBtnDistance,
PositionFinishTime = details.PositionFinishTime,
BettingRatio = details.BettingRatio,
PerformanceFigure = details.PerformanceFigure,
RatingFlat = details.RatingFlat,
RatingAwt = details.RatingAwt,
RatingChase = details.RatingChase,
RatingHurdle = details.RatingHurdle,
RaceCriteriaRaceType = details.RaceCriteriaRaceType,
Hro = details.Hro,
FinishTime = details.FinishTime,
ResultFinishDNF = details.ResultFinishDNF,
FinishTimeInMilliseconds = String.IsNullOrWhiteSpace(details.ResultFinishDNF) ? details.FinishTimeInMilliseconds() : null,
LossMilliseconds = details.LossMilliseconds(),
};
using(var db = new Db.HorseRacingDataContext())
{
db.RunnerResults.Add(dbRunnerResult);
await db.SaveChangesAsync();
}
Console.WriteLine($"Saved results for {details.RacehorseName}");
}
}
}
@@ -0,0 +1,9 @@
using System;
namespace AutoBet.DataRecorded.RaceResultsDataCollector
{
public class PostRaceDataCollectorDetails
{
public DateTime DateToCollect { get; set; }
}
}
@@ -0,0 +1,70 @@
using SuccessfulCode.BetfairApi;
using SuccessfulCode.BetfairApi.BettingModels;
using SwiftyMessageHub.Core;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
namespace AutoBet.DataRecorded.MessageControllers
{
public class OddsDataCollectorController : MessageController
{
[MessageRoute]
public async Task GenerateSnapshot(OddsSnapshotDetails details)
{
var auth = new Authentication("TheRocker1987", "reSharper1036!", "H5TT4zKqOlRCpNOr");
var client = new BettingApiClient(auth);
var horseRacingQueries = new BetfairHorseRacingQueries(client);
var horseWins = await horseRacingQueries.GetHorseWinCatalogue(DateTime.UtcNow.AddHours(-2), DateTime.UtcNow);
var marketDetails = horseWins.ToDictionary(e => e.MarketId, e => e);
var horseDetails = horseWins.SelectMany(e => e.Runners.Select(e1 => new { Key = (e.MarketId, e1.SelectionId), Value = e1 })).ToDictionary(e => e.Key, e => e.Value);
var prices = await horseRacingQueries.GetBestPrices(horseWins.Select(e => e.MarketId).ToArray());
var snapShots = prices.SelectMany(e => e.Runners.Select(e1 => GenerateOddsSnapshots(marketDetails, horseDetails, e1, e)));
foreach (var snapshot in snapShots)
{
await SendResponse(snapshot);
}
}
private static Db.OddsSnapshot GenerateOddsSnapshots(Dictionary<string, MarketCatalogue> marketDetails, Dictionary<(string MarketId, long SelectionId), RunnerCatalog> horseDetails, Runner runner, MarketBook book)
{
var marketDetail = marketDetails[book.MarketId];
var horseDetail = horseDetails[(marketDetail.MarketId, runner.SelectionId)];
var runnerName = Regex.Match(horseDetail.RunnerName, "^[0-9]*\\.? ?(.*)", RegexOptions.Compiled).Groups[1].Value;
var oddsSnapshot = new Db.OddsSnapshot()
{
EventName = marketDetail.Event.Name,
HorseName = runnerName,
JockeyName = horseDetail.Metadata.JockeyName,
Odds = GenerateOdds(runner),
SnapshotDate = DateTime.UtcNow
};
return oddsSnapshot;
}
private static List<Db.BetOdds> GenerateOdds(Runner e1)
{
var backOdds = e1.ExchangePrices.AvailableToBack.Select(e => new Db.BetOdds()
{
OddsType = Db.OddsType.Back,
Available = (decimal)e.Size,
Odds = e.Price
}).ToList();
var layOdds = e1.ExchangePrices.AvailableToBack.Select(e => new Db.BetOdds()
{
OddsType = Db.OddsType.Lay,
Available = (decimal)e.Size,
Odds = e.Price
}).ToList();
backOdds.AddRange(layOdds);
return backOdds;
}
}
}
@@ -0,0 +1,9 @@
using SwiftyMessageHub.Core;
namespace AutoBet.DataRecorded.MessageControllers
{
[MessageType("OddsSnapshotDetails")]
public class OddsSnapshotDetails
{
}
}
@@ -0,0 +1,22 @@
using AutoBet.Db;
using SwiftyMessageHub.Core;
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
namespace AutoBet.DataRecorded.MessageControllers
{
public class OddsDataRecorderController : MessageController
{
[MessageRoute]
public async Task SaveSnapshot(OddsSnapshot snapshotToSave)
{
using (var db = new HorseRacingDataContext())
{
db.OddsSnapshots.Add(snapshotToSave);
await db.SaveChangesAsync();
}
}
}
}
@@ -0,0 +1,11 @@
using SwiftyMessageHub.Core;
using System;
namespace AutoBet.DataRecorded
{
[MessageType("PreRaceDataSnapshotDetails")]
public class PreRaceDataCollectDetails
{
public DateTime DateToCollect { get; set; }
}
}
@@ -0,0 +1,23 @@
using SwiftyMessageHub.Core;
using System;
using System.Threading.Tasks;
namespace AutoBet.DataRecorded.MessageControllers
{
public class PreRaceDataCollectorController : MessageController
{
[MessageRoute]
public async Task CollectPreRaceData(PreRaceDataCollectDetails details)
{
var client = new BritishHorseRacingApi.ApiClient();
var date = details.DateToCollect;
Console.WriteLine("Loading races");
var races = await client.GetAllRacesForDay(date.Year, date.Month, date.Day);
foreach (var race in races)
{
Console.WriteLine($"Race id {race.RaceId} loaded");
await CurrentContext.Hub.SendMessage(race);
}
}
}
}
@@ -0,0 +1,50 @@
using BritishHorseRacingApi.Models;
using AutoBet.DataRecorded.PreRaceRunnerCollector;
using SwiftyMessageHub.Core;
using System.Threading.Tasks;
using System;
namespace AutoBet.DataRecorded.PreRaceDataRecorder
{
public class PreRaceDataRecorderController : MessageController
{
[MessageRoute]
public async Task CollectPreRaceData(Race details)
{
Console.WriteLine($"Saving race id {details.RaceId}");
using (var db = new Db.HorseRacingDataContext())
{
db.Races.Add(new Db.Race()
{
DistanceChangeText = details.DistanceChangeText,
BlackTypeRace = details.BlackTypeRace,
AbandonedReasonCode = details.AbandonedReasonCode,
RaceCriteriaRaceType = details.RaceCriteriaRaceType,
DistanceChange = details.DistanceChange,
DistanceText = details.DistanceText,
DistanceValue = details.DistanceValue,
DistanceUnits = details.DistanceUnits,
RawDistanceText = details.RawDistanceText,
RatingBand = details.RatingBand,
RaceClass = details.RaceClass,
PrizeCurrency = details.PrizeCurrency,
PrizeAmount = details.PrizeAmount,
AgeLimit = details.AgeLimit,
RaceName = details.RaceName,
RaceTime = details.RaceTime,
RaceDate = details.RaceDate,
DivisionSequence = details.DivisionSequence,
YearOfRace = details.YearOfRace,
RaceId = details.RaceId,
Plus10 = details.Plus10,
});
await db.SaveChangesAsync();
}
await CurrentContext.Hub.SendMessage(new PreRaceRunnerCollectDetails()
{
DateToCollect = details.RaceDate,
RaceId = details.RaceId
});
}
}
}
@@ -0,0 +1,14 @@
using System;
namespace AutoBet.DataRecorded.PreRaceRunnerCollector
{
public class PreRaceRunnerCollectDetails
{
public PreRaceRunnerCollectDetails()
{
}
public DateTime DateToCollect { get; set; }
public int RaceId { get; set; }
}
}
@@ -0,0 +1,41 @@
using BritishHorseRacingApi.Models;
using SwiftyMessageHub.Core;
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace AutoBet.DataRecorded.PreRaceRunnerCollector
{
public class PreRaceRunnerCollectorController : MessageController
{
public static SemaphoreSlim semaphore = new SemaphoreSlim(1);
[MessageRoute]
public async Task CollectPreRaceData(PreRaceRunnerCollectDetails details)
{
var client = new BritishHorseRacingApi.ApiClient();
var date = details.DateToCollect;
Console.WriteLine($"Preparing to load runners for race id {details.RaceId}");
await semaphore.WaitAsync();
try
{
Console.WriteLine($"Loading runners for race id {details.RaceId}");
var runners = await client.GetRaceRunners(date.Year, details.RaceId);
foreach (var runner in runners.Data)
{
Console.WriteLine($"Loaded runner {runner.RacehorseName} id {details.RaceId}");
await CurrentContext.Hub.SendMessage(runner);
}
}
catch(Exception ex)
{
throw;
}
finally
{
semaphore.Release();
}
}
}
}
@@ -0,0 +1,77 @@
using BritishHorseRacingApi.Models;
using SwiftyMessageHub.Core;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace AutoBet.DataRecorded.PreRaceRunnerRecorder
{
public class PreRaceRunnerRecorderController : MessageController
{
[MessageRoute]
public async Task RecordRunner(Runner details)
{
Console.WriteLine($"Saving runner {details.RacehorseName}");
using (var db = new Db.HorseRacingDataContext())
{
db.Runners.Add(new Db.Runner()
{
HeadGearWearingCode = details.HeadGearWearingCode,
HeadGearWearingSheepSkin = details.HeadGearWearingSheepSkin,
HeadGearDescription = details.HeadGearDescription,
HeadGearAbbreviation = details.HeadGearAbbreviation,
JockeyProfile = details.JockeyProfile,
CourseWinner = details.CourseWinner,
DistanceWinner = details.DistanceWinner,
WindSurgeryFirstRun = details.WindSurgeryFirstRun,
TrainerId = details.TrainerId,
TrainerName = details.TrainerName,
OwnerId = details.OwnerId,
OwnerName = details.OwnerName,
WbSilkCode = details.WbSilkCode,
WbSilkDescription = details.WbSilkDescription,
SilkImage = details.SilkImage,
Plus10 = details.Plus10,
ForecastPriceNumerator = details.ForecastPriceNumerator,
ForecastPriceDenominator = details.ForecastPriceDenominator,
WeightText = details.WeightText,
WeightsJockeyClaiming = details.WeightsJockeyClaiming,
Odds = details.Odds,
DecimalOdds = details.DecimalOdds(),
JockeyName = details.JockeyName,
Status = (Db.Status)details.Status,
RaceId = details.RaceId,
YearOfRace = details.YearOfRace,
DivisionSequence = details.DivisionSequence,
AnimalId = details.AnimalId,
RacehorseName = details.RacehorseName,
AgeYears = details.AgeYears,
Bred = details.Bred,
ClothNumber = details.ClothNumber,
DrawnStall = details.DrawnStall,
ReserveNumber = details.ReserveNumber,
BhaRating = details.BhaRating,
FormFigures = details.FormFigures,
WeightValue = details.WeightValue,
PenaltyValue = details.PenaltyValue,
SexType = (Db.SexType)details.SexType,
NonRunnerDeclaredReason = details.NonRunnerDeclaredReason,
NonRunnerDeclaredDate = details.NonRunnerDeclaredDate,
NonRunnerDeclaredTime = details.NonRunnerDeclaredTime,
RunnerNumber = details.RunnerNumber,
JockeyId = details.JockeyId,
RaceHorseNameWithoutCountry = details.RacehorseNameWithoutCountry,
WeightInGrams = details.WeightInGrams,
LastRuns = details.LastRuns?.Select(e => new Db.LastRun()
{
Days = e.Days,
RaceType = e.RaceType
}).ToList()
});
await db.SaveChangesAsync();
}
}
}
}
+342
View File
@@ -0,0 +1,342 @@
using AutoBet.DataRecorded.MessageControllers;
using SwiftyMessageHub.Core;
using System;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using AutoBet.DataRecorded.RaceResultsDataCollector;
using BritishHorseRacingApi;
using System.Collections.Generic;
using BritishHorseRacingApi.Models;
using Microsoft.EntityFrameworkCore;
using AutoBet.Db;
using ApiModels = BritishHorseRacingApi.Models;
namespace AutoBet.DataRecorded
{
class Program
{
public static async Task Main(string[] args)
{
//StartResultsCollection().GetAwaiter().GetResult();
//var dayToCollectRunners = GetDayToCollect();
await CollectPastResults();
//await CollectCurrent();
//await GetFixtureIds();
}
private static async Task GetFixtureIds()
{
Db.Fixture[] fixturesToProcces;
using (var db = new Db.HorseRacingDataContext())
{
var ids = db.Races.Where(e => e.FixtureId != 0).Select(e => e.FixtureId).ToArray();
fixturesToProcces = db.Fixtures.Where(e => !ids.Contains(e.FixtureId)).ToArray();
var client = new ApiClient(TimeSpan.FromSeconds(0), "D_SID=188.172.158.138:JT/OEx87nl5ScspTQk38UsDfuIz94DbCf5CYsIC7WpU; __utmz=36595059.1583064856.1.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none); D_ZID=52A68C14-B4B6-3844-8896-9B0E426FEABA; D_ZUID=2E7A90D0-30B7-31B4-BB43-CB2B0DACBDF8; D_HID=0316E576-4AF0-35A5-BEB9-CECB592B4EC2; bha-ie-test=true; __utmc=36595059; __utma=36595059.34208775.1583064856.1583966446.1584046318.17; bha_token=%7B%22token%22%3A%22MjE3Y2I1NDBhYWViZWQ0YmM4YjZmYjg2NDRlOTA2NzU%3D%22%2C%22timestamp%22%3A1584046320723%7D; D_IID=A18DB74E-9ABD-33E1-BF94-96209AF6178E; D_UID=9CDC96FD-4EFE-308E-BC28-2F105AC0B01B; __utmt=1; __utmb=36595059.6.10.1584046318");
foreach (var fixture in fixturesToProcces)
{
var races = await client.GetRaces(fixture.FixtureYear, fixture.FixtureId);
foreach (var race in races.Data)
{
var dbRace = db.Races.FirstOrDefault(e => e.RaceId == race.RaceId);
if (dbRace == null)
{
AddRace(db, fixture.FixtureId, race);
await LoadRunners(fixture.FixtureDate.Date, client, db, race);
continue;
}
dbRace.FixtureId = fixture.FixtureId;
}
db.SaveChanges();
}
}
}
private static async Task CollectPastResults()
{
var dayToCollectRunners = new DateTime(2019, 11, 23);// GetDayToCollect();
var client = new ApiClient(TimeSpan.FromSeconds(0), "D_SID=188.172.158.138:JT/OEx87nl5ScspTQk38UsDfuIz94DbCf5CYsIC7WpU; __utmz=36595059.1583064856.1.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none); D_IID=A18DB74E-9ABD-33E1-BF94-96209AF6178E; D_UID=9CDC96FD-4EFE-308E-BC28-2F105AC0B01B; __utmc=36595059; bha-ie-test=true; D_ZID=3F37C446-48FB-3F85-B8D2-66FC90A17473; D_ZUID=27B27203-7708-3F5E-8C01-86A8BF3A21DD; D_HID=BC00CAA4-06EE-39E0-8579-A00DCFA20171; bha_token=%7B%22token%22%3A%22ZjYxM2UwMWEwZmZjNjdhYmM5NzRmMDhmMGVmOTYxNGY%3D%22%2C%22timestamp%22%3A1586699412252%7D; __utma=36595059.34208775.1583064856.1586685187.1586702516.21; __utmt=1; __utmb=36595059.2.10.1586702516");
while (true)
{
try
{
var dayToCollectResults = dayToCollectRunners;
await LoadPreRaceData(dayToCollectRunners, client);
await LoadResults(dayToCollectResults, client);
dayToCollectRunners = dayToCollectRunners.AddDays(-1);
}
catch(Exception ex)
{
Console.WriteLine(ex.Message);
Console.WriteLine("Enter new cookie:");
var cookie = Console.ReadLine();
if (!String.IsNullOrWhiteSpace(cookie))
client = new ApiClient(TimeSpan.FromSeconds(0), cookie);
}
}
}
private static async Task CollectCurrent()
{
var dayToCollectRunners = DateTime.Now.Date;
var dayToCollectResults = dayToCollectRunners.AddDays(-1);
var client = new ApiClient(TimeSpan.FromSeconds(0), "D_SID=188.172.158.138:JT/OEx87nl5ScspTQk38UsDfuIz94DbCf5CYsIC7WpU; __utmz=36595059.1583064856.1.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none); D_ZID=52A68C14-B4B6-3844-8896-9B0E426FEABA; D_ZUID=2E7A90D0-30B7-31B4-BB43-CB2B0DACBDF8; D_HID=0316E576-4AF0-35A5-BEB9-CECB592B4EC2; bha-ie-test=true; __utmc=36595059; D_IID=A18DB74E-9ABD-33E1-BF94-96209AF6178E; D_UID=9CDC96FD-4EFE-308E-BC28-2F105AC0B01B; __utma=36595059.34208775.1583064856.1584046318.1584135333.18; __utmt=1; __utmb=36595059.1.10.1584135333; bha_token=%7B%22token%22%3A%22NTc0OTdjNTRiMjg2ZGYyYzEyYThmMjRlZDZmYmIyMzM%3D%22%2C%22timestamp%22%3A1584135334879%7D");
await LoadPreRaceData(dayToCollectRunners, client);
await LoadResults(dayToCollectResults, client);
}
private static async Task LoadPreRaceData(DateTime date, ApiClient client)
{
Console.WriteLine($"Loading fixtures for {date}");
var fixtures = await client.GetAllFixturesForDay(date.Year, date.Month, date.Day);
using (var db = new Db.HorseRacingDataContext())
{
foreach (var fixture in fixtures)
{
Console.WriteLine($"Processing fixture {fixture.FixtureName}");
var dbFixture = ApiFixtureToDbFixture(fixture);
db.Fixtures.Add(dbFixture);
await db.SaveChangesAsync();
await LoadRaces(date, client, db, fixture.FixtureYear, fixture.FixtureId);
}
}
}
private static async Task LoadRaces(DateTime date, ApiClient client, HorseRacingDataContext db, int year, int fixtureId)
{
Console.WriteLine($"Loading races for {date}");
var races = await client.GetRaces(year, fixtureId);
foreach (var race in races.Data)
{
AddRace(db, fixtureId, race);
await db.SaveChangesAsync();
await LoadRunners(date, client, db, race);
await db.SaveChangesAsync();
}
}
private static async Task LoadRunners(DateTime date, ApiClient client, HorseRacingDataContext db, ApiModels.Race race)
{
Console.WriteLine($"Loading runners for race id {race.RaceId}");
var runners = await client.GetRaceRunners(date.Year, race.RaceId, race.DivisionSequence);
foreach (var runner in runners.Data)
{
Console.WriteLine($"Loaded runner {runner.RacehorseName} for race {race.RaceId})");
db.Runners.Add(new Db.Runner()
{
HeadGearWearingCode = runner.HeadGearWearingCode,
HeadGearWearingSheepSkin = runner.HeadGearWearingSheepSkin,
HeadGearDescription = runner.HeadGearDescription,
HeadGearAbbreviation = runner.HeadGearAbbreviation,
JockeyProfile = runner.JockeyProfile,
CourseWinner = runner.CourseWinner,
DistanceWinner = runner.DistanceWinner,
WindSurgeryFirstRun = runner.WindSurgeryFirstRun,
TrainerId = runner.TrainerId,
TrainerName = runner.TrainerName,
OwnerId = runner.OwnerId,
OwnerName = runner.OwnerName,
WbSilkCode = runner.WbSilkCode,
WbSilkDescription = runner.WbSilkDescription,
SilkImage = runner.SilkImage,
Plus10 = runner.Plus10,
ForecastPriceNumerator = runner.ForecastPriceNumerator,
ForecastPriceDenominator = runner.ForecastPriceDenominator,
WeightText = runner.WeightText,
WeightsJockeyClaiming = runner.WeightsJockeyClaiming,
Odds = runner.Odds,
DecimalOdds = runner.DecimalOdds(),
JockeyName = runner.JockeyName,
Status = (Db.Status)runner.Status,
RaceId = runner.RaceId,
YearOfRace = runner.YearOfRace,
DivisionSequence = runner.DivisionSequence,
AnimalId = runner.AnimalId,
RacehorseName = runner.RacehorseName,
AgeYears = runner.AgeYears,
Bred = runner.Bred,
ClothNumber = runner.ClothNumber,
DrawnStall = runner.DrawnStall,
ReserveNumber = runner.ReserveNumber,
BhaRating = runner.BhaRating,
FormFigures = runner.FormFigures,
WeightValue = runner.WeightValue,
PenaltyValue = runner.PenaltyValue,
SexType = (Db.SexType)runner.SexType,
NonRunnerDeclaredReason = runner.NonRunnerDeclaredReason,
NonRunnerDeclaredDate = runner.NonRunnerDeclaredDate,
NonRunnerDeclaredTime = runner.NonRunnerDeclaredTime,
RunnerNumber = runner.RunnerNumber,
JockeyId = runner.JockeyId,
RaceHorseNameWithoutCountry = runner.RacehorseNameWithoutCountry,
WeightInGrams = runner.WeightInGrams,
LastRuns = runner.LastRuns?.Select(e => new Db.LastRun()
{
Days = e.Days,
RaceType = e.RaceType
}).ToList()
});
}
}
private static void AddRace(HorseRacingDataContext db, int fixtureId, ApiModels.Race race)
{
Console.WriteLine($"Saving {race.RaceName}");
var dbRace = ApiRaceToDbRace(race, fixtureId);
db.Races.Add(dbRace);
}
private static Db.Fixture ApiFixtureToDbFixture(ApiModels.Fixture fixture)
{
return new Db.Fixture()
{
GoingUpdatedTime = fixture.GoingUpdatedTime,
GoingUpdatedDate = fixture.GoingUpdatedDate,
FixtureSession = (Db.FixtureSession)fixture.FixtureSession,
AbandonedReasonCode = fixture.AbandonedReasonCode,
Rail = fixture.Rail,
Stalls = fixture.Stalls,
Other = fixture.Other,
Weather = fixture.Weather,
Going = fixture.Going,
MajorEvent = fixture.MajorEvent,
TicketsLink = fixture.TicketsLink,
CourseId = fixture.CourseId,
RacePlanningCode = (Db.RacePlanningCode)fixture.RacePlanningCode,
RacingTrackType = (Db.RacingTrackType)fixture.RacingTrackType,
MeetingId = fixture.MeetingId,
FixtureType = (Db.FixtureType)fixture.FixtureType,
FixtureName = fixture.FixtureName,
NumberOfRaces = fixture.NumberOfRaces,
BcsEvent = fixture.BcsEvent,
BlackTypeRaces = fixture.BlackTypeRaces,
EntriesAvailable = fixture.EntriesAvailable,
RacecardAvailable = fixture.RacecardAvailable,
ResultsAvailable = fixture.ResultsAvailable,
FirstRace = fixture.FirstRace,
CourseName = fixture.CourseName,
Distance = fixture.Distance,
FixtureDate = fixture.FixtureDate,
FixtureYear = fixture.FixtureYear,
FixtureId = fixture.FixtureId
};
}
private static Db.Race ApiRaceToDbRace(ApiModels.Race race, int fixtureId)
{
return new Db.Race()
{
DistanceChangeText = race.DistanceChangeText,
BlackTypeRace = race.BlackTypeRace,
AbandonedReasonCode = race.AbandonedReasonCode,
RaceCriteriaRaceType = race.RaceCriteriaRaceType,
DistanceChange = race.DistanceChange,
DistanceText = race.DistanceText,
DistanceValue = race.DistanceValue,
DistanceUnits = race.DistanceUnits,
RawDistanceText = race.RawDistanceText,
RatingBand = race.RatingBand,
RaceClass = race.RaceClass,
PrizeCurrency = race.PrizeCurrency,
PrizeAmount = race.PrizeAmount,
AgeLimit = race.AgeLimit,
RaceName = race.RaceName,
RaceTime = race.RaceTime,
RaceDate = race.RaceDate,
DivisionSequence = race.DivisionSequence,
YearOfRace = race.YearOfRace,
RaceId = race.RaceId,
Plus10 = race.Plus10,
FixtureId = fixtureId
};
}
private static async Task LoadResults(DateTime date, ApiClient client)
{
using (var db = new Db.HorseRacingDataContext())
{
var races = await db.Races.Where(e => e.RaceDate == date.Date).ToListAsync();
foreach(var race in races)
{
if (race.RaceId != 1684)
continue;
var results = await client.GetRaceResults(race.YearOfRace, race.RaceId, race.DivisionSequence);
foreach (var runnerResult in results.Data)
{
var dbRunnerResult = new Db.RunnerResult()
{
RaceId = runnerResult.RaceId,
YearOfRace = runnerResult.YearOfRace,
DivisionSequence = runnerResult.DivisionSequence,
HorseId = runnerResult.HorseId,
AnimalId = runnerResult.AnimalId,
ResultFinishPos = runnerResult.ResultFinishPos,
Status = runnerResult.Status,
Ran = runnerResult.Ran,
NonRunnerDeclaredReason = runnerResult.NonRunnerDeclaredReason,
NonRunnerDeclaredDate = runnerResult.NonRunnerDeclaredDate,
NonRunnerDeclaredTime = runnerResult.NonRunnerDeclaredTime,
RacehorseName = runnerResult.RacehorseName,
RacehorseNameWithoutConuntry = runnerResult.RacehorseNameWithoutCountry,
AgeYear = runnerResult.AgeYear,
Bred = runnerResult.Bred,
ClothNumber = runnerResult.ClothNumber,
DrawnStall = runnerResult.DrawnStall,
WeightValue = runnerResult.WeightValue,
SexType = runnerResult.SexType,
JockeyId = runnerResult.JockeyId,
JockeyName = runnerResult.JockeyName,
JockeyProfile = runnerResult.JockeyProfile,
TrainerId = runnerResult.TrainerId,
TrainerName = runnerResult.TrainerName,
OwnerId = runnerResult.OwnerId,
OwnerName = runnerResult.OwnerName,
WbSilkCode = runnerResult.WbSilkCode,
WbSilkDescription = runnerResult.WbSilkDescription,
SilkImage = runnerResult.SilkImage,
Plus10 = runnerResult.Plus10,
ResultBtnDistance = runnerResult.ResultBtnDistance,
PositionFinishTime = runnerResult.PositionFinishTime,
BettingRatio = runnerResult.BettingRatio,
PerformanceFigure = runnerResult.PerformanceFigure,
RatingFlat = runnerResult.RatingFlat,
RatingAwt = runnerResult.RatingAwt,
RatingChase = runnerResult.RatingChase,
RatingHurdle = runnerResult.RatingHurdle,
RaceCriteriaRaceType = runnerResult.RaceCriteriaRaceType,
Hro = runnerResult.Hro,
FinishTime = runnerResult.FinishTime,
ResultFinishDNF = runnerResult.ResultFinishDNF,
FinishTimeInMilliseconds = String.IsNullOrWhiteSpace(runnerResult.ResultFinishDNF) ? runnerResult.FinishTimeInMilliseconds() : null,
LossMilliseconds = runnerResult.LossMilliseconds(),
};
db.RunnerResults.Add(dbRunnerResult);
await db.SaveChangesAsync();
}
}
}
}
public static DateTime _dateToCollectRunners = GetDayToCollect();
public static DateTime GetDayToCollect()
{
using(var db = new Db.HorseRacingDataContext())
{
var date = db.Races.OrderBy(e => e.RaceDate)
.Select(e => e.RaceDate)
.First()
.Date;
return date.AddDays(-1);
}
}
}
}