Files
Saxonite/SaxoniteCoreWeb/Base/Procs/SaxGolfUsgaDataLookup-ScheduledUsgaDataLookup.cs
T
2024-06-13 14:29:58 +01:00

226 lines
12 KiB
C#

using DocumentFormat.OpenXml.Drawing.Diagrams;
using Sarand.Net.Standard.Base.App;
using Sarand.Net.Standard.Base.Core;
using Sarand.Net.Standard.Base.Dbas;
using Sarand.Net.Standard.Base.Helpers;
using Sarand.Net.Standard.Base.Tasks;
using Sarand.Net.Standard.Base.Utils;
using Saxonite.Net.Standard.Base.App;
using Saxonite.Net.Standard.Base.Bus.Reference;
using System;
using System.Collections.Generic;
using System.Linq;
namespace Saxonite.Net.Core.Web.Base.Procs
{
//=======================================================================
partial class SaxGolfUsgaDataLookup
{
//-------------------------------------------------------------------
private class ScheduledUsgaDataLookupControlData
{
public DateTime CountriesLastLookedUp { get; set; } = DateTime.Now;
}
private static ScheduledUsgaDataLookupControlData usgaDataLookupControl { get; } = new ScheduledUsgaDataLookupControlData();
/// <summary>
/// Determine which USGA data population process to run.
/// <para>- Method is invoked periodically (every 20 mins) by the Admin Hosted Service Console.</para>
/// <para>- 1. Populate countries if not already done or not done for a while (eg. 24 hours).</para>
/// <para>- 2. Populate provinces for a Country that has none or occasionally to refresh one that has.</para>
/// <para>- 3. Populate Courses for a Province that has none or occasionally to refresh one that has.</para>
/// <para>- 4. Populate Courses for a Province that has none or occasionally to refresh one that has.</para>
/// </summary>
public static void ExecuteScheduledUsgaDataLookup(SaxSessionContext sessionContext, DbUpdateInfo dbUpdateInfo, SacsTaskData taskData)
{
SaLogger.Debug($"{SysUtil.Fn}");
using (DisposableCollection<SacsDisposable> disposableItems = new DisposableCollection<SacsDisposable>())
{
SaxInternals internals = new SaxInternals(sessionContext);
disposableItems.Add(internals);
// Configure process.
SaxGolfUsgaDataLookup.Config courseLookupConfig = new SaxGolfUsgaDataLookup.Config(sessionContext, dbUpdateInfo);
SaxGolfUsgaDataLookup usgaDataLookup = new SaxGolfUsgaDataLookup(courseLookupConfig);
if (taskData.IsCancellationRequested) return;
// Determine which process to run.
// Check USGA country population.
List<SaxGolfUsgaCountry> usgaCountries = internals.ReferenceGolfMgr.GetUsgaCountryList(new SaxGolfUsgaCountry.Params());
if (!usgaCountries.Any() || (DateTime.Now - usgaDataLookupControl.CountriesLastLookedUp).TotalHours > MathUtil.Constrain(Sax.Config.Admin.Processes.Scheduled.UsgaGolfDataLookup.HoursBetweenCountryLookup, 1, 24 * 7))
{
// No countries currently found or long enough since last lookup.
// Lookup USGA countries.
List<SaxGolfUsgaDataLookup.CountryData> countriesData = usgaDataLookup.LookupUsgaCountries();
SaLogger.Info($"{SysUtil.Fn} USGA Countries populated: {countriesData.Count}.", true);
usgaDataLookupControl.CountriesLastLookedUp = DateTime.Now;
return;
}
if (taskData.IsCancellationRequested) return;
// Population of Countries without Provinces is only allowed occasionally to avoid delaying population of lower data.
bool populateCountryWithNoProvinces = SacsRandomHelper.GetInt32(1, 7) == 1;
// Check USGA Country Province population.
List<SaxGolfUsgaCountry> usgaCountriesWithProvinces = new List<SaxGolfUsgaCountry>();
List<SaxGolfUsgaCountry> usgaCountriesWithNoProvinces = new List<SaxGolfUsgaCountry>();
foreach (SaxGolfUsgaCountry usgaCountry in usgaCountries.OrderBy(item => item.Priority ? 0 : 1).ThenBy(_ => SacsRandomHelper.GetInt32(Int32.MaxValue)))
{
SaxGolfUsgaProvince.Params prmUsgaProvince = new SaxGolfUsgaProvince.Params();
prmUsgaProvince.CountryIdsIncluded.Add(usgaCountry.Id);
if (internals.ReferenceGolfMgr.GetUsgaProvinceCount(prmUsgaProvince) < 1)
{
usgaCountriesWithNoProvinces.Add(usgaCountry);
if (populateCountryWithNoProvinces)
{
// Country has no Provinces - look them up.
List<SaxGolfUsgaDataLookup.ProvinceData> provincesData = usgaDataLookup.LookupUsgaProvincesForCountry(usgaCountry.CountryCode);
SaLogger.Info($"{SysUtil.Fn} USGA Provinces populated for {usgaCountry.CountryCode} {usgaCountry.CountryName}" + (usgaCountry.Priority ? " [Priority]" : "") + $": {provincesData.Count}.", true);
return;
}
}
else
{
// Country has Provinces.
usgaCountriesWithProvinces.Add(usgaCountry);
}
if (taskData.IsCancellationRequested) return;
}
if (usgaCountriesWithProvinces.Any())
{
// Pick the first (randomly sorted) Country.
SaxGolfUsgaCountry usgaCountry = usgaCountriesWithProvinces[0];
// One of the Countries with Provinces can have its list of provinces refreshed occasionally.
bool refreshCountryWithProvinces = SacsRandomHelper.GetInt32(1, 17) == 1;
if (refreshCountryWithProvinces)
{
SaxGolfUsgaProvince.Params prmUsgaProvince = new SaxGolfUsgaProvince.Params();
prmUsgaProvince.CountryIdsIncluded.Add(usgaCountry.Id);
List<SaxGolfUsgaProvince> usgaProvinces = internals.ReferenceGolfMgr.GetUsgaProvinceList(prmUsgaProvince).OrderBy(item => item.Priority ? 0 : 1).ThenBy(_ => SacsRandomHelper.GetInt32(Int32.MaxValue)).ToList();
if (usgaProvinces.Any())
{
// Refresh Country Provinces.
List<SaxGolfUsgaDataLookup.ProvinceData> provincesData = usgaDataLookup.LookupUsgaProvincesForCountry(usgaCountry.CountryCode);
SaLogger.Info($"{SysUtil.Fn} USGA Provinces refreshed for {usgaCountry.CountryCode} {usgaCountry.CountryName}" + (usgaCountry.Priority ? " [Priority]" : "") + $": {provincesData.Count}.", true);
return;
}
}
}
if (usgaCountriesWithProvinces.Any())
{
// Pick the first (randomly sorted) Country.
SaxGolfUsgaCountry usgaCountry = usgaCountriesWithProvinces[0];
// Population of Courses for Province without Facilities is allowed occasionally.
bool populateProvinceWithNoFacilities = SacsRandomHelper.GetInt32(1, 7) == 1;
// Check USGA Province Course population.
List<SaxGolfUsgaProvince> usgaProvincesWithFacilities = new List<SaxGolfUsgaProvince>();
List<SaxGolfUsgaProvince> usgaProvincesWithNoFacilities = new List<SaxGolfUsgaProvince>();
SaxGolfUsgaProvince.Params prmUsgaProvince = new SaxGolfUsgaProvince.Params();
prmUsgaProvince.CountryIdsIncluded.Add(usgaCountry.Id);
foreach (SaxGolfUsgaProvince usgaProvince in internals.ReferenceGolfMgr.GetUsgaProvinceList(prmUsgaProvince).OrderBy(item => item.Priority ? 0 : 1).ThenBy(_ => SacsRandomHelper.GetInt32(Int32.MaxValue)))
{
SaxGolfUsgaFacility.Params prmUsgaFacility = new SaxGolfUsgaFacility.Params();
prmUsgaFacility.ProvinceIdsIncluded.Add(usgaProvince.Id);
if (internals.ReferenceGolfMgr.GetUsgaFacilityCount(prmUsgaFacility) < 1)
{
usgaProvincesWithNoFacilities.Add(usgaProvince);
if (populateProvinceWithNoFacilities)
{
// Province has no Facilities - look up the courses.
List<SaxGolfUsgaDataLookup.CourseData> coursesData = usgaDataLookup.LookupUsgaCoursesForCountryAndProvince(usgaCountry.CountryCode, usgaProvince.ProvinceCode);
SaLogger.Info($"{SysUtil.Fn} USGA Courses populated for {usgaCountry.CountryCode} {usgaCountry.CountryName} - {usgaProvince.ProvinceCode} {usgaProvince.ProvinceName}" + (usgaProvince.Priority ? " [Priority]" : "") + $": {coursesData.Count}.", true);
return;
}
}
else
{
// Country has provinces.
usgaProvincesWithFacilities.Add(usgaProvince);
}
if (taskData.IsCancellationRequested) return;
}
if (usgaProvincesWithFacilities.Any())
{
// Pick the first (randomly sorted) province.
SaxGolfUsgaProvince usgaProvince = usgaProvincesWithFacilities[0];
// Population of Courses for Province with Facilities is allowed occasionally.
bool populateProvinceWithFacilities = SacsRandomHelper.GetInt32(1, 17) == 1;
if (populateProvinceWithFacilities)
{
// Refresh Courses for Province with Facilities.
List<SaxGolfUsgaDataLookup.CourseData> coursesData = usgaDataLookup.LookupUsgaCoursesForCountryAndProvince(usgaCountry.CountryCode, usgaProvince.ProvinceCode);
SaLogger.Info($"{SysUtil.Fn} USGA Courses refreshed for {usgaCountry.CountryCode} {usgaCountry.CountryName} - {usgaProvince.ProvinceCode} {usgaProvince.ProvinceName}" + (usgaProvince.Priority ? " [Priority]" : "") + $": {coursesData.Count}.", true);
return;
}
// Compile list of Courses for this province.
SaxGolfUsgaCourse.Params prmCourse = new SaxGolfUsgaCourse.Params();
prmCourse.ProvinceIdsIncluded.Add(usgaProvince.Id);
List<SaxGolfUsgaCourse> usgaCourses = internals.ReferenceGolfMgr.GetUsgaCourseList(prmCourse).OrderBy(item => item.Priority ? 0 : 1).ThenBy(_ => SacsRandomHelper.GetInt32(Int32.MaxValue)).ToList();
List<SaxGolfUsgaCourse> usgaCoursesWithMarkers = new List<SaxGolfUsgaCourse>();
foreach (SaxGolfUsgaCourse usgaCourse in usgaCourses)
{
SaxGolfUsgaMarker.Params prmMarker = new SaxGolfUsgaMarker.Params();
prmMarker.CourseIdsIncluded.Add(usgaCourse.Id);
if (internals.ReferenceGolfMgr.GetUsgaMarkerCount(prmMarker) == 0)
{
// Populate Markers for first course without markers.
List<SaxGolfUsgaDataLookup.MarkerData> markersData = usgaDataLookup.LookupUsgaMarkersForCourse(usgaCourse.CourseId);
SaLogger.Info($"{SysUtil.Fn} USGA Markers populated for {usgaCountry.CountryCode} {usgaCountry.CountryName} - {usgaProvince.ProvinceCode} {usgaProvince.ProvinceName} - {usgaCourse.Caption} [Id: {usgaCourse.CourseId}" + (usgaCourse.Priority ? ", Priority" : "") + $"]: {markersData.Count}.", true);
return;
}
else usgaCoursesWithMarkers.Add(usgaCourse);
}
if (usgaCoursesWithMarkers.Any())
{
// Populate Markers for first course with markers.
SaxGolfUsgaCourse usgaCourse = usgaCoursesWithMarkers[0];
List<SaxGolfUsgaDataLookup.MarkerData> markersData = usgaDataLookup.LookupUsgaMarkersForCourse(usgaCourse.CourseId);
SaLogger.Info($"{SysUtil.Fn} USGA Markers refreshed for {usgaCountry.CountryCode} {usgaCountry.CountryName} - {usgaProvince.ProvinceCode} {usgaProvince.ProvinceName} - {usgaCourse.Caption} [Id: {usgaCourse.CourseId}" + (usgaCourse.Priority ? ", Priority" : "") + $"]: {markersData.Count}.", true);
return;
}
}
// Fallback - populate Courses for Province.
bool allowFallbackCoursePopulation = true;
if (allowFallbackCoursePopulation)
{
SaxGolfUsgaProvince usgaProvince = usgaProvincesWithNoFacilities.Any() ? usgaProvincesWithNoFacilities[0] : usgaProvincesWithFacilities.Any() ? usgaProvincesWithFacilities[0] : null;
if (usgaCountry != null && usgaProvince != null && usgaCountry.Id.Equals(usgaProvince.CountryId))
{
List<SaxGolfUsgaDataLookup.CourseData> coursesData = usgaDataLookup.LookupUsgaCoursesForCountryAndProvince(usgaCountry.CountryCode, usgaProvince.ProvinceCode);
SaLogger.Info($"{SysUtil.Fn} USGA Courses populated for {usgaCountry.CountryCode} {usgaCountry.CountryName} - {usgaProvince.ProvinceCode} {usgaProvince.ProvinceName}" + (usgaProvince.Priority ? " [Priority]" : "") + $": {coursesData.Count}. [Fallback]", true);
return;
}
}
}
// Fallback - populate provinces for country.
bool allowFallbackProvincePopulation = true;
if (allowFallbackProvincePopulation)
{
SaxGolfUsgaCountry usgaCountry = usgaCountriesWithNoProvinces.Any() ? usgaCountriesWithNoProvinces[0] : usgaCountriesWithProvinces.Any() ? usgaCountriesWithProvinces[0] : null;
if (usgaCountry != null)
{
List<SaxGolfUsgaDataLookup.ProvinceData> provincesData = usgaDataLookup.LookupUsgaProvincesForCountry(usgaCountry.CountryCode);
SaLogger.Info($"{SysUtil.Fn} USGA Provinces populated for {usgaCountry.CountryCode} {usgaCountry.CountryName}" + (usgaCountry.Priority ? " [Priority]" : "") + $": {provincesData.Count}. [Fallback]", true);
return;
}
}
}
}
//-------------------------------------------------------------------
}
//=======================================================================
}