using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Text; using System.Threading.Tasks; using System.Web; using Microsoft.Extensions.Logging; using Newtonsoft.Json; using Microsoft.Extensions.Configuration; using System.Globalization; namespace Arbitrage { public class LadbrokesService : BookkeeperService { private LadbrokesServiceConfiguration mConfiguration { get; set; } private dynamic? EventsListData { get; set; } private List EventsData { get; set; } = new List(); public LadbrokesService() { IConfiguration config = new ConfigurationBuilder() .AddJsonFile("configuration.json") .Build(); mConfiguration = config.GetRequiredSection("ladbrokesService").Get(); } public async Task InitialiseAsync() { UriBuilder uriBuilder = new UriBuilder(mConfiguration.BaseSiteUrl); var httpResult = await mHttpClient.GetAsync(uriBuilder.ToString()); if (!httpResult.IsSuccessStatusCode) { mLogger.LogWarning($"Could not get visit Ladbrokes"); } } public override async Task> GetSportEventsAsync(Sport sport) { if (!mConfiguration.Categories.Select(x => x.Sport).Contains(sport)) { mLogger.LogWarning($"Ladbroke servive cannot get {sport}."); return new List(); } Dictionary queryDictionary = new Dictionary() { {"category_ids", $"[\"{mConfiguration.Categories.First(x => x.Sport == sport).Id}\"]"} }; var queryString = new FormUrlEncodedContent(queryDictionary) .ReadAsStringAsync().Result; UriBuilder uriBuilder = new UriBuilder(mConfiguration.GetEventsUrl); uriBuilder.Query = queryString; var httpResult = await mHttpClient.GetAsync(uriBuilder.ToString()); if (!httpResult.IsSuccessStatusCode) { mLogger.LogWarning($"Could not get events from Ladbroke."); return new List(); } dynamic? data = JsonConvert.DeserializeObject(await httpResult.Content.ReadAsStringAsync()); if (data == null) { mLogger.LogWarning("Could not deserialise Ladbrokes get events response content."); return new List(); } EventsListData = data; List events = new List(); foreach (var x in EventsListData["events"]) { var obj = ((IEnumerable)x).First(); DateTimeOffset commencementTime = DateTimeOffset.Parse((string)obj["actual_start"].ToString()).ToUniversalTime(); string eventId = obj["id"].ToString(); string url = new Uri(new Uri(mConfiguration.BaseEventUrl), $"{sport}/nice/website/{eventId}").ToString(); //TODO: add proper URL events.Add(new BookkeeperEvent() { Bookkeeper = Bookkeeper.Ladbrokes, BookkeeperEventId = eventId, Name = obj["name"].ToString(), Competition = obj["competition"]?["name"]?.ToString(), Commencement = commencementTime, Url = url }); } return events; } public override async Task> GetEventMarketsAsync(BookkeeperEvent bookkeeperEvent) { Dictionary queryDictionary = new Dictionary() { {"id", bookkeeperEvent.BookkeeperEventId} }; var queryString = new FormUrlEncodedContent(queryDictionary) .ReadAsStringAsync().Result; UriBuilder uriBuilder = new UriBuilder(mConfiguration.GetOddsUrl); uriBuilder.Query = queryString; var httpResult = await mHttpClient.GetAsync(uriBuilder.ToString()); if (!httpResult.IsSuccessStatusCode) { mLogger.LogWarning($"Could not get event from Ladbrokes for event {bookkeeperEvent.BookkeeperEventId}."); return new List(); } dynamic? data = JsonConvert.DeserializeObject(await httpResult.Content.ReadAsStringAsync()); if (data == null) { mLogger.LogWarning($"Could not deserialise Ladbrokes get event for {bookkeeperEvent.BookkeeperEventId}."); return new List(); } EventsData.Add(data); List markets = new List(); foreach (var market in data["markets"]) { markets.Add(new BookkeeperMarket() { Bookkeeper = Bookkeeper.Ladbrokes, BookkeeperMarketId = market.Value.id, Name = market.Value.name, Url = bookkeeperEvent.Url }); } return markets; } public async override Task> GetMarketOddsAsync(Event @event, BookkeeperMarket bookkeeperMarket) { dynamic? eventDynamic = null; List entrantIds = new List(); foreach (dynamic eventData in EventsData) { foreach (dynamic eventMarket in eventData["markets"]) { if (eventMarket.Value.id == bookkeeperMarket.BookkeeperMarketId) { eventDynamic = eventData; foreach (string entrantId in eventMarket.Value["entrant_ids"]) { entrantIds.Add(entrantId); } } } } if (eventDynamic == null) { throw new Exception($"EventsData does not contain data for market {bookkeeperMarket.BookkeeperMarketId}"); } List bookkeeperOdds = new List(); foreach (string entrantId in entrantIds) { string name = eventDynamic["entrants"][entrantId]["name"].ToString(); dynamic price = ((IEnumerable)eventDynamic["prices"]).First(x => x.Name.Split(":")[0] == entrantId).Value["odds"]; double value = double.Parse(price["numerator"].ToString()) / double.Parse(price["denominator"].ToString()); bookkeeperOdds.Add(new BookkeeperOdds() { Bookkeeper = Bookkeeper.Ladbrokes, BookkeeperOddsId = entrantId, Outcome = name, Value = value + 1, Url = bookkeeperMarket.Url }); } return bookkeeperOdds; } } }