public void OnPickHorseDataExecute_CommandExecuteWithParameter_UpdatesHorseObjectWithIndexes() { HorseDataWrapper horse = new HorseDataWrapper(); _viewModel.PickHorseDataCommand.Execute(horse); Assert.Equal("Trim", _viewModel.HorseWrapper.HorseName); Assert.Equal(7, _viewModel.HorseWrapper.Age); Assert.Equal("Some Father", _viewModel.HorseWrapper.Father); }
public HorseDataWrapper ParseHorseData(DateTime raceDate, string name, string age, string link, string jockey, string jobType) { HorseDataWrapper horse = new HorseDataWrapper(); int n; if (!string.IsNullOrEmpty(name)) { horse.HorseName = name; //rided horse } else { horse.HorseName = "-"; //rided horse } if (!string.IsNullOrEmpty(link)) { horse.Link = link; //rided horse } else { horse.Link = "-"; //rided horse } bool parseTest = int.TryParse(age, out n); if (parseTest && jobType.Contains("HistoricPl")) { horse.Age = int.Parse(age) + (_dateToday.Year - raceDate.Year); } else if (parseTest) { horse.Age = int.Parse(age); //age if (horse.Age > 199) { horse.Age = _dateToday.Year - horse.Age; //age } } else { horse.Age = 99; } if (!string.IsNullOrEmpty(jockey)) { horse.Jockey = jockey; //name of the racer } else { horse.Jockey = "-"; } return(horse); }
public void OnPickHorseDataExecute_CommandExecuteWithParameter_CallsGetParsedHorseData() { HorseDataWrapper horse = new HorseDataWrapper(); _viewModel.PickHorseDataCommand.Execute(horse); _updateDataMock.Verify(sd => sd.GetParsedHorseData(It.IsAny <HorseDataWrapper>(), It.IsAny <DateTime>(), It.IsAny <List <LoadedHorse> >(), It.IsAny <List <LoadedJockey> >(), It.IsAny <RaceModel>()), Times.Once); }
public HorseDataWrapper SplitHorseNodeString(string jobType, string nodeString, string propertyName, DateTime raceDate) { HorseDataWrapper horse = new HorseDataWrapper(); string name = SplitName(jobType, nodeString, typeof(HorseDataWrapper), null); string age = SplitAge(jobType, nodeString, raceDate, propertyName); string racer = SplitName(jobType, nodeString, typeof(LoadedJockey), null); string link = ""; horse = ParseHorseData(raceDate, name, age, link, racer, jobType); return(horse); }
public HorseChildDetails SplitChildNodeString(string jobType, string nodeString, string propertyName, DateTime raceDate) { HorseDataWrapper wrapper = new HorseDataWrapper(); HorseChildDetails child = new HorseChildDetails(); string name = SplitName(jobType, nodeString, typeof(LoadedHorse), propertyName); string age = SplitAge(jobType, nodeString, _dateToday, propertyName); string link = SplitLink(nodeString, jobType, propertyName); string jockey = ""; wrapper = ParseHorseData(_dateToday, name, age, link, jockey, jobType); child.ChildAge = wrapper.Age; child.ChildLink = wrapper.Link; child.ChildName = wrapper.HorseName; return(child); }
/// <summary> /// parses the horse from Horses with providen data /// passing RaceModel to the services credits: https://stackoverflow.com/a/56650635/11027921 /// </summary> /// <param name="horseWrapper">horse data</param> /// <param name="date">day of the race</param> /// <returns></returns> public HorseDataWrapper GetParsedHorseData(HorseDataWrapper horseWrapper, DateTime date, List <LoadedHorse> horses, List <LoadedJockey> jockeys, RaceModel raceModelProvider) { Dictionary <string, int> raceCategoryDictionary = _dictionaryService.GetRaceCategoryDictionary(raceModelProvider); LoadedJockey jockeyFromList = new LoadedJockey(); LoadedHorse horseFromList = new LoadedHorse(); LoadedHorse fatherFromList = new LoadedHorse(); //if name is entered if (!string.IsNullOrEmpty(horseWrapper.HorseName)) { horses = new List <LoadedHorse>(horses.OrderBy(l => l.Age)); //from smallest to biggest //if age is from AutoCompleteBox if (horseWrapper.HorseName.Contains(", ")) { string theAge = horseWrapper.HorseName.Split(',')[1].Trim(' '); string theName = horseWrapper.HorseName.Split(',')[0].Trim(' '); int n; bool parseTest = int.TryParse(theAge, out n); if (parseTest) { horseWrapper.Age = int.Parse(theAge); //age } horseWrapper.HorseName = theName; } //if age is not written if (horseWrapper.Age == 0) { horseFromList = horses .Where(h => h.Name.ToLower() == horseWrapper.HorseName.ToLower()) .FirstOrDefault(); } //if age is written else { horseFromList = horses .Where(h => h.Name.ToLower() == horseWrapper.HorseName.ToLower()) .Where(h => h.Age == horseWrapper.Age) .FirstOrDefault(); } //case when previous horse is replaced in Horse collection item if (horseFromList == null) { horseWrapper.Age = 0; horseFromList = horses .Where(i => i.Name.ToLower() == horseWrapper .HorseName.ToLower()) .FirstOrDefault(); } horses = new List <LoadedHorse>(horses.OrderByDescending(l => l.Age)); //from biggest to smallest //jockey index if (!string.IsNullOrEmpty(horseWrapper.Jockey)) { jockeyFromList = jockeys .Where(i => i.Name.ToLower() == horseWrapper .Jockey.ToLower()) .FirstOrDefault(); if (jockeyFromList != null) { horseWrapper.JockeyIndex = _computeDataService.ComputeJockeyIndex(jockeyFromList, date); } else { horseWrapper.Jockey = "--Not found--"; horseWrapper.JockeyIndex = 0; //clear } } if (horseFromList != null) { horseWrapper.HorseName = horseFromList.Name; //displayed name horseWrapper.Age = horseFromList.Age; //displayed age horseWrapper.Father = horseFromList.Father; //displayed father horseWrapper.TotalRaces = horseFromList.AllRaces.Count(); //how many races horseWrapper.Comments = ""; //win index if (jockeyFromList != null) { horseWrapper.WinIndex = _computeDataService.ComputeWinIndex(horseFromList, date, jockeyFromList, raceModelProvider, raceCategoryDictionary); } else { horseWrapper.WinIndex = _computeDataService.ComputeWinIndex(horseFromList, date, null, raceModelProvider, raceCategoryDictionary); } //category index horseWrapper.CategoryIndex = _computeDataService.ComputeCategoryIndex(horseFromList, date, raceModelProvider, raceCategoryDictionary); //age index horseWrapper.AgeIndex = _computeDataService.ComputeAgeIndex(horseFromList, date); //tired index horseWrapper.TiredIndex = _computeDataService.ComputeTiredIndex(horseFromList, date); //win percentage horseWrapper.PercentageIndex = _computeDataService.ComputePercentageIndex(horseFromList, date); //days of rest horseWrapper.RestIndex = _computeDataService.ComputeRestIndex(horseFromList, date); } else { horseWrapper.Age = 0; //clear horseWrapper.TotalRaces = 0; //clear horseWrapper.Comments = "--Data missing--"; horseWrapper.WinIndex = 0; //clear horseWrapper.CategoryIndex = 0; //clear } //siblings index if (!string.IsNullOrEmpty(horseWrapper.Father)) { fatherFromList = horses.Where(i => i.Name.ToLower() == horseWrapper.Father.ToLower()).FirstOrDefault(); if (fatherFromList != null) { horseWrapper.SiblingsIndex = _computeDataService.ComputeSiblingsIndex(fatherFromList, date, raceModelProvider, horses, raceCategoryDictionary); } else { horseWrapper.Father = "--Not found--"; horseWrapper.SiblingsIndex = 0; //clear } } //comments = score horseWrapper.Comments = horseWrapper.HorseScore.ToString("0.000"); } return(horseWrapper); }
/// <summary> /// on `Add new horse (+)` btn click, /// is adding new blank horse to the list /// </summary> /// <param name="obj"></param> public void OnNewHorseExecute(object obj) { HorseWrapper = new HorseDataWrapper(); HorseList.Add(HorseWrapper); }
/// <summary> /// Generic method that scraps single object for Jockey, Horse, Race /// </summary> /// <typeparam name="T">Jockey, Horse, Race</typeparam> /// <param name="id">id on the website</param> /// <param name="jobType">type of scrapping</param> /// <returns>returns back casted generic object</returns> public async Task <T> ScrapGenericObject <T>(int id, string jobType) { LoadedJockey jockey = new LoadedJockey(); LoadedHorse horse = new LoadedHorse(); RaceDetails race = new RaceDetails(); Dictionary <string, string> nodeDictionary = new Dictionary <string, string>(); List <HtmlDocument> raceHtmlAgilityList = new List <HtmlDocument>(); string linkBase = ""; if (jobType.Contains("JockeysPl")) { linkBase = "https://koniewyscigowe.pl/dzokej?d="; nodeDictionary = _dictionaryService.GetJockeyPlNodeDictionary(); } else if (jobType.Contains("JockeysCz")) { linkBase = "http://dostihyjc.cz/jezdec.php?IDTR="; nodeDictionary = _dictionaryService.GetJockeyCzNodeDictionary(); } else if (jobType.Contains("HistoricPl")) { linkBase = "https://koniewyscigowe.pl/wyscig?w="; nodeDictionary = _dictionaryService.GetRacePlNodeDictionary(); } else if (jobType.Contains("HorsesPl")) { linkBase = "https://koniewyscigowe.pl/horse/"; nodeDictionary = _dictionaryService.GetHorsePlNodeDictionary(); } else if (jobType.Contains("HorsesCz")) { linkBase = "http://dostihyjc.cz/kun.php?ID="; nodeDictionary = _dictionaryService.GetHorseCzNodeDictionary(); } string link = GetLink(linkBase, id); string html = await GetHtmlDocumentAsync(link); HtmlDocument htmlAgility = GetHtmlAgility(html); string nodeString = htmlAgility.DocumentNode.OuterHtml.ToString(); bool nodeConditions = _parseService.VerifyNodeCondition(nodeString, null, jobType); if (typeof(T) == typeof(LoadedJockey)) { if (nodeConditions) { string name = _parseService.SplitName(jobType, nodeString, typeof(T), null); raceHtmlAgilityList = await GetRaceHtmlAgilityListAsync(jobType, link); jockey = _parseService.ParseJockeyData(link, name); jockey.AllRaces = GetGenericList <RaceDetails>(raceHtmlAgilityList, nameof(jockey.AllRaces), nodeDictionary, jobType, _dateToday); } else { jockey = null; } return((T)Convert.ChangeType(jockey, typeof(T))); } else if (typeof(T) == typeof(RaceDetails)) { if (nodeConditions) { string horsesNode = nodeDictionary[nameof(race.HorseList)]; raceHtmlAgilityList = await GetRaceHtmlAgilityListAsync(jobType, link); race = _parseService.SplitRaceNodeString(jobType, nodeString, null); race.RaceLink = link; race.HorseList = GetGenericList <HorseDataWrapper>(raceHtmlAgilityList, nameof(race.HorseList), nodeDictionary, jobType, race.RaceDate); race.RaceCompetition = race.HorseList.Count; } else { race = null; } return((T)Convert.ChangeType(race, typeof(T))); } else if (typeof(T) == typeof(LoadedHorse)) { if (nodeConditions) { HorseDataWrapper wrapper = new HorseDataWrapper(); raceHtmlAgilityList = await GetRaceHtmlAgilityListAsync(jobType, link); string name = _parseService.SplitName(jobType, nodeString, typeof(T), null); string age = _parseService.SplitAge(jobType, nodeString, _dateToday, nameof(horse.Age)); string racer = ""; wrapper = _parseService.ParseHorseData(_dateToday, name, age, link, racer, jobType); horse.Link = link; horse.Name = wrapper.HorseName; horse.Age = wrapper.Age; horse.Father = GetFather(jobType, htmlAgility, nameof(horse.Father), nodeDictionary); horse.FatherLink = GetFather(jobType, htmlAgility, nameof(horse.FatherLink), nodeDictionary); horse.AllRaces = GetGenericList <RaceDetails>(raceHtmlAgilityList, nameof(horse.AllRaces), nodeDictionary, jobType, _dateToday); horse.AllChildren = GetGenericList <HorseChildDetails>(raceHtmlAgilityList, nameof(horse.AllChildren), nodeDictionary, jobType, _dateToday); } else { horse = null; } return((T)Convert.ChangeType(horse, typeof(T))); } else { throw new ArgumentException(); } }
/// <summary> /// Some classes have collections of objects as props, here we get them /// </summary> /// <typeparam name="T">collection generic type</typeparam> /// <param name="raceHtmlAgilityList">list of HTML documents by HtmlAfilityPack framework</param> /// <param name="propertyName">property collection name of currently scrapped object (ex. AllRaces - of the horse)</param> /// <param name="nodeDictionary">xpath dictionary with property name as a Key</param> /// <param name="jobType">type of scrapping</param> /// <param name="raceDate">day of race input</param> /// <returns></returns> public List <T> GetGenericList <T>(List <HtmlDocument> raceHtmlAgilityList, string propertyName, Dictionary <string, string> nodeDictionary, string jobType, DateTime raceDate) { List <HorseChildDetails> children = new List <HorseChildDetails>(); List <RaceDetails> races = new List <RaceDetails>(); List <HorseDataWrapper> horses = new List <HorseDataWrapper>(); string xpath = nodeDictionary[propertyName]; bool nodeConditions = false; foreach (var raceHtmlAgility in raceHtmlAgilityList) { nodeConditions = _parseService.VerifyNodeCondition(raceHtmlAgility.DocumentNode.OuterHtml.ToString(), propertyName, jobType); if (nodeConditions) //check complete page { HtmlNode[] tableRowsNode = raceHtmlAgility.DocumentNode.SelectNodes(xpath).ToArray(); if (tableRowsNode.Length > 0) { foreach (var row in tableRowsNode) { string nodeString = row.OuterHtml.ToString(); nodeConditions = _parseService.VerifyNodeCondition(nodeString, propertyName, jobType); if (nodeConditions) //check single row { if (typeof(T) == typeof(HorseChildDetails)) { HorseChildDetails child = new HorseChildDetails(); child = _parseService.SplitChildNodeString(jobType, nodeString, propertyName, raceDate); children.Add(child); } else if (typeof(T) == typeof(RaceDetails)) { RaceDetails race = new RaceDetails(); race = _parseService.SplitRaceNodeString(jobType, nodeString, propertyName); races.Add(race); } else if (typeof(T) == typeof(HorseDataWrapper)) { HorseDataWrapper horse = new HorseDataWrapper(); horse = _parseService.SplitHorseNodeString(jobType, nodeString, propertyName, raceDate); horses.Add(horse); } } } } } } if (typeof(T) == typeof(HorseChildDetails)) { return((List <T>)Convert.ChangeType(children, typeof(List <T>))); } else if (typeof(T) == typeof(RaceDetails)) { return((List <T>)Convert.ChangeType(races, typeof(List <T>))); } else if (typeof(T) == typeof(HorseDataWrapper)) { return((List <T>)Convert.ChangeType(horses, typeof(List <T>))); } else { throw new ArgumentException(); } }
/// <summary> /// simulates score index for all horses in all races in certain year from race database /// CPU operations /// creates loads of parallel tasks to improve performance speed /// use of SemaphoreSlim to control tasks /// mode details for credits in UpdateService /// </summary> /// <param name="idFrom">object id limitation</param> /// <param name="toId">object id limitation</param> /// <param name="races">collection of races</param> /// <param name="horses">collection of horses</param> /// <param name="jockeys">collection of jockey</param> /// <param name="raceModelProvider">race data</param> /// <returns></returns> public async Task <List <RaceDetails> > SimulateResultsAsync(int idFrom, int idTo, List <RaceDetails> races, List <LoadedHorse> horses, List <LoadedJockey> jockeys, RaceModel raceModelProvider) { //variables SemaphoreSlim throttler = new SemaphoreSlim(_degreeOfParallelism); List <Task> tasks = new List <Task>(); TokenSource = new CancellationTokenSource(); CancellationToken = TokenSource.Token; int loopCounterProgressBar = 0; string jobTypeProgressBar = "Simulating historic races"; ProgressBarData progressBar; //run loop for (int i = 0; i < races.Count; i++) { int id = i; tasks.Add(Task.Run(async() => { try { if (CancellationToken.IsCancellationRequested) { return; } await throttler.WaitAsync(TokenSource.Token); if (races[id].RaceDate.Year == 2018) { raceModelProvider.Category = races[id].RaceCategory; raceModelProvider.Distance = races[id].RaceDistance.ToString(); //for all horses in the race for (int h = 0; h < races[id].HorseList.Count; h++) { HorseDataWrapper horse = new HorseDataWrapper(); horse = _updateDataService.GetParsedHorseData(races[id].HorseList[h], races[id].RaceDate, horses, jockeys, raceModelProvider); races[id].HorseList[h] = horse; //get all indexes } } } catch (Exception e) { // } finally { loopCounterProgressBar++; progressBar = GetProgressBar(jobTypeProgressBar, idFrom, idTo, loopCounterProgressBar); _eventAggregator.GetEvent <ProgressBarEvent>().Publish(progressBar); throttler.Release(); } })); } try { await Task.WhenAll(tasks); } catch (OperationCanceledException) { // } finally { await _dataServices.SaveRaceSimulatedResultsAsync(races.ToList()); throttler.Dispose(); } return(races); }