/// <summary> /// calculated PI factor /// </summary> /// <param name="horseFromList"></param> /// <param name="date"></param> /// <returns>returns PI</returns> public double ComputePercentageIndex(LoadedHorse horseFromList, DateTime date) { ResetComputeVariables(); if (horseFromList.AllRaces.Count > 0) { for (int i = 0; i < horseFromList.AllRaces.Count; i++) { if (horseFromList.AllRaces[i].WonPlace == 1 && horseFromList.AllRaces[i].RaceDate < date) { Result++; } } double percentage = (double)Result / horseFromList.AllRaces.Count * 100; if (percentage > 20) { FinalResult = 1 + (percentage - 20) * 0.1; } else { FinalResult = 1; } return(FinalResult); } else { return(1); } }
/// <summary> /// updates single horse object /// gets data from scrap service /// compares with objects in current database /// calls merge method if object already in database /// </summary> /// <param name="jobType"></param> /// <param name="id"></param> /// <returns></returns> private async Task UpdateHorsesAsync(string jobType, int id) { LoadedHorse horse = new LoadedHorse(); horse = await _scrapDataService.ScrapGenericObject <LoadedHorse>(id, jobType); if (horse != null) { lock (((ICollection)Horses).SyncRoot) { //if objects are already in the List if (Horses.Any(h => h.Name.ToLower() == horse.Name.ToLower())) { LoadedHorse doubledHorse = Horses.Where(h => h.Name.ToLower() == horse.Name.ToLower()).Where(h => h.Age == horse.Age).FirstOrDefault(); if (doubledHorse != null) { Horses.Remove(doubledHorse); MergeHorsesData(doubledHorse, horse); } else { Horses.Add(horse); } } else { Horses.Add(horse); } } } }
/// <summary> /// resets properties used in various methods /// </summary> public void ResetComputeVariables() { DictValue = 1; FinalResult = 0; Result = 0; SiblingIndex = 0; Counter = 0; ChildFromList = new LoadedHorse(); }
/// <summary> /// calculated CI factor /// </summary> /// <param name="horseFromList">horse data</param> /// <param name="date">day of the race</param> /// <returns>returns CI</returns> public double ComputeCategoryIndex(LoadedHorse horseFromList, DateTime date, RaceModel raceModelProvider, Dictionary <string, int> raceCategoryDictionary) { Dictionary <string, int> raceDictionary = raceCategoryDictionary; ResetComputeVariables(); if (horseFromList.AllRaces.Count > 0) { for (int i = 0; i < horseFromList.AllRaces.Count; i++) { ResetLoopVariables(); if (horseFromList.AllRaces[i].WonPlace > 0 && horseFromList.AllRaces[i].RaceDate < date) { PlaceFactor = (double)horseFromList.AllRaces[i].WonPlace / horseFromList.AllRaces[i].RaceCompetition * 10; //increase factor for races over 12 horses and place between 1-4 if (horseFromList.AllRaces[i].RaceCompetition > 12 && horseFromList.AllRaces[i].WonPlace < 5) { PlaceFactor = PlaceFactor * 1.5; } bool foundKey = raceDictionary.Keys.Any(k => k.Equals(horseFromList.AllRaces[i].RaceCategory, StringComparison.CurrentCultureIgnoreCase) ); if (foundKey) { DictValue = raceDictionary[horseFromList.AllRaces[i].RaceCategory]; } else { DictValue = 5; } DistanceFactor = (double)(horseFromList.AllRaces[i].RaceDistance - int.Parse(raceModelProvider.Distance)) / 10000 * DictValue; DistanceFactor = Math.Abs(DistanceFactor); DistanceRaceIndex = PlaceFactor * DictValue / 10; Result = Result + DistanceRaceIndex - DistanceFactor; } } FinalResult = Result / horseFromList.AllRaces.Count; return(FinalResult); } else { return(0); } }
/// <summary> /// calculated SI factor /// </summary> /// <param name="fatherFromList">data of horses father</param> /// <param name="date">day of the race</param> /// <returns>returns SI</returns> public double ComputeSiblingsIndex(LoadedHorse fatherFromList, DateTime date, RaceModel raceModelProvider, List <LoadedHorse> horses, Dictionary <string, int> raceCategoryDictionary) { ResetComputeVariables(); horses = new List <LoadedHorse>(horses.OrderBy(l => l.Age)); //from smallest to biggest for (int i = 0; i < fatherFromList.AllChildren.Count; i++) { HorseChildDetails child = fatherFromList.AllChildren[i]; if (child.ChildAge == 0) { ChildFromList = horses .Where(h => h.Name.ToLower() == child .ChildName.ToLower()) .FirstOrDefault(); } else { ChildFromList = horses .Where(h => h.Name.ToLower() == child.ChildName.ToLower()) .Where(h => h.Age == child.ChildAge) .FirstOrDefault(); } if (ChildFromList != null && ChildFromList.AllRaces.Count > 0) { SiblingIndex = ComputeWinIndex(ChildFromList, date, null, raceModelProvider, raceCategoryDictionary); Counter++; } else { SiblingIndex = 0; } Result = Result + SiblingIndex; } if (Counter != 0) { FinalResult = Result / Counter; } else { FinalResult = 0; } return(FinalResult); }
/// <summary> /// updates list of horses races and children, if found some new /// </summary> /// <param name="doubledHorse">horse from Horses</param> /// <param name="horse">scrapped new horse</param> public void MergeHorsesData(LoadedHorse doubledHorse, LoadedHorse horse) { if (horse.AllRaces != null) { doubledHorse.AllRaces = doubledHorse.AllRaces.Union(horse.AllRaces).ToList(); } if (horse.AllChildren != null) { doubledHorse.AllChildren = doubledHorse.AllChildren.Union(horse.AllChildren).ToList(); } Horses.Add(doubledHorse); }
/// <summary> /// calculated AI factor /// </summary> /// <param name="horseFromList"></param> /// <param name="date"></param> /// <returns>returns AI</returns> public double ComputeAgeIndex(LoadedHorse horseFromList, DateTime date) { int yearsDifference = DateTime.Now.Year - date.Year; //how many years passed since race int horsesRaceAge = horseFromList.Age - yearsDifference; //how old was horse if (horsesRaceAge > 5) { int multiplier = horsesRaceAge - 4; double result = 1 + 0.3 * multiplier; return(result); } else { return(1); } }
/// <summary> /// calculated TI factor /// </summary> /// <param name="horseFromList"></param> /// <param name="date"></param> /// <returns>returns TI</returns> public double ComputeTiredIndex(LoadedHorse horseFromList, DateTime date) { ResetComputeVariables(); if (horseFromList.AllRaces.Count > 0) { //get races only before race date, sort by race date from biggest to smallest horseFromList.AllRaces = horseFromList.AllRaces.Where(l => l.RaceDate < date).OrderByDescending(l => l.RaceDate).ToList(); if (horseFromList.AllRaces.Count == 0) { return(1); } for (int i = 0; i < horseFromList.AllRaces.Count; i++) { DateTime twoYearsBack = date.AddYears(-2); //for all races 2 years back from this race if (horseFromList.AllRaces[i].RaceDate <date && horseFromList.AllRaces[i].RaceDate> twoYearsBack) { Counter++; } } if (Counter > 12) { FinalResult = 1 + (Counter - 12) * 0.1; } else { return(1); } return(FinalResult); } else { return(1); } }
/// <summary> /// calculated RI factor /// </summary> /// <param name="horseFromList"></param> /// <param name="date"></param> /// <returns>returns RI</returns> public double ComputeRestIndex(LoadedHorse horseFromList, DateTime date) { ResetComputeVariables(); if (horseFromList.AllRaces.Count > 0) { //get races only before race date, sort by race date from biggest to smallest horseFromList.AllRaces = horseFromList.AllRaces.Where(l => l.RaceDate < date).OrderByDescending(l => l.RaceDate).ToList(); if (horseFromList.AllRaces.Count == 0) { return(1); } Result = (date - horseFromList.AllRaces[0].RaceDate).TotalDays; if (Result > 90) { FinalResult = 1 + (Result - 90) / 100; } else if (Result < 60) { FinalResult = 1 + Result / 50; } else { FinalResult = 1; } return(FinalResult); } else { return(1); } }
/// <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> /// 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(); } }
public HorseDataWrapper() { _horse = new LoadedHorse(); _jockey = new LoadedJockey(); }
/// <summary> /// calculated WI factor /// </summary> /// <param name="horseFromList">horse data</param> /// <param name="date">day of the race</param> /// <returns>returns WI</returns> public double ComputeWinIndex(LoadedHorse horseFromList, DateTime date, LoadedJockey jockeyFromList, RaceModel raceModelProvider, Dictionary <string, int> raceCategoryDictionary) { Dictionary <string, int> raceDictionary = raceCategoryDictionary; ResetWinComputeVariables(); if (horseFromList.AllRaces.Count > 0) { for (int i = 0; i < horseFromList.AllRaces.Count; i++) { ResetLoopVariables(); //get races only before race date, sort by race date from biggest to smallest horseFromList.AllRaces = horseFromList.AllRaces.Where(l => l.RaceDate < date).OrderByDescending(l => l.RaceDate).ToList(); if (horseFromList.AllRaces.Count == 0) { return(0); } if (horseFromList.AllRaces[i].WonPlace < 3 && horseFromList.AllRaces[i].WonPlace > 0 && horseFromList.AllRaces[i].RaceDate < date) { if (horseFromList.AllRaces[i].WonPlace == 1) { PlaceFactor = 1; } if (horseFromList.AllRaces[i].WonPlace == 2) { PlaceFactor = 0.7; } if (jockeyFromList != null) { //bonus if was the same jockey as in current race if (!string.IsNullOrEmpty(jockeyFromList.Name) && !string.IsNullOrEmpty(horseFromList.AllRaces[i].RacersName)) { if (horseFromList.AllRaces[i].RacersName.Contains(jockeyFromList.Name)) { PlaceFactor = PlaceFactor * 1.5; } } } //bonus for place factor if won race in last 3 races if (i < 3) { PlaceFactor = PlaceFactor * 1.5; } //increase factor for races over 12 horses and place between 1-4 if (horseFromList.AllRaces[i].RaceCompetition > 12 && horseFromList.AllRaces[i].WonPlace < 5) { PlaceFactor = PlaceFactor * 1.5; } bool foundKey = raceDictionary.Keys.Any(k => k.Equals(horseFromList.AllRaces[i].RaceCategory, StringComparison.CurrentCultureIgnoreCase) ); if (foundKey) { DictValue = raceDictionary[horseFromList.AllRaces[i].RaceCategory]; } else { DictValue = 5; } DistanceFactor = (double)(horseFromList.AllRaces[i].RaceDistance - int.Parse(raceModelProvider.Distance)) / 10000 * DictValue; DistanceFactor = Math.Abs(DistanceFactor); DistanceRaceIndex = PlaceFactor * horseFromList.AllRaces[i].RaceCompetition * DictValue / 10; WinResult = WinResult + DistanceRaceIndex - DistanceFactor; } } FinalWinResult = WinResult / horseFromList.AllRaces.Count; return(FinalWinResult); } else { return(0); } }