Files
Saxonite/SaxoniteCoreWeb/Base/Procs/SaxGolfUsgaDataLookup-ScheduledUsgaDataLookup.cs
T
2024-06-14 17:39:14 +01:00

324 lines
16 KiB
C#

using DocumentFormat.OpenXml.Drawing.Diagrams;
using DocumentFormat.OpenXml.Office2016.Excel;
using Sarand.Net.Standard.Base.App;
using Sarand.Net.Standard.Base.Bus;
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 refresh one that has.</para>
/// <para>- 3. Populate Courses for a Province that has none or occasionally refresh one that has.</para>
/// <para>- 4. Populate Markers for a Course that has none or occasionally 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.
//-----------------------------------------------------------
// 1. Countries.
{
// 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;
}
//-----------------------------------------------------------
// 2. Provinces.
// 2a. Population of active priority Country with no Provinces.
{
bool populatePriorityCountryNoProvinces = SacsRandomHelper.GetInt32(1, 3) == 1;
if (populatePriorityCountryNoProvinces)
{
SaxGolfUsgaCountry.Params prmCountry = new SaxGolfUsgaCountry.Params();
prmCountry.PriorityFlagState = SacsHierarchyItem.Params.FlagState.True;
prmCountry.HasProvinces = SacsHierarchyItem.Params.BoolState.False;
prmCountry.StatusCat = SaxGolfUsgaCountry.StatusCat.ActiveOnly;
List<SaxGolfUsgaCountry> countriesNoProvinces = internals.ReferenceGolfMgr.GetUsgaCountryList(prmCountry).Randomise();
disposableItems.AddRange(countriesNoProvinces);
if (countriesNoProvinces.Any())
{
SaxGolfUsgaCountry usgaCountry = countriesNoProvinces[0];
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;
}
}
}
// 2b. Refresh active priority Country with Provinces.
{
bool refreshPriorityCountryWithProvinces = SacsRandomHelper.GetInt32(1, 3) == 1;
if (refreshPriorityCountryWithProvinces)
{
SaxGolfUsgaCountry.Params prmCountry = new SaxGolfUsgaCountry.Params();
prmCountry.PriorityFlagState = SacsHierarchyItem.Params.FlagState.True;
prmCountry.HasProvinces = SacsHierarchyItem.Params.BoolState.True;
prmCountry.StatusCat = SaxGolfUsgaCountry.StatusCat.ActiveOnly;
List<SaxGolfUsgaCountry> countriesWithProvinces = internals.ReferenceGolfMgr.GetUsgaCountryList(prmCountry).Randomise();
disposableItems.AddRange(countriesWithProvinces);
if (countriesWithProvinces.Any())
{
SaxGolfUsgaCountry usgaCountry = countriesWithProvinces[0];
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;
}
}
}
//-----------------------------------------------------------
// 3. Courses.
// 3a. Populate active priority Province with no Facilities (Courses).
{
bool populatePriorityProvinceNoFacilities = SacsRandomHelper.GetInt32(1, 3) == 1;
if (populatePriorityProvinceNoFacilities)
{
// Active priority Provinces with no Facilities.
SaxGolfUsgaProvince.Params prmProvince = new SaxGolfUsgaProvince.Params();
prmProvince.PriorityFlagState = SacsHierarchyItem.Params.FlagState.True;
prmProvince.HasFacilities = SacsHierarchyItem.Params.BoolState.False;
prmProvince.StatusCat = SaxGolfUsgaProvince.StatusCat.ActiveOnly;
List<SaxGolfUsgaProvince> provincesNoFacilities = internals.ReferenceGolfMgr.GetUsgaProvinceList(prmProvince);
disposableItems.AddRange(provincesNoFacilities);
if (provincesNoFacilities.Any())
{
// Province has no Facilities - populate courses.
SaxGolfUsgaProvince usgaProvince = provincesNoFacilities[0];
List<SaxGolfUsgaDataLookup.CourseData> coursesData = LookupUsgaCourses(internals, usgaDataLookup, usgaProvince, false);
return;
}
}
}
// 3b. Refresh active priority Province with Facilities (courses).
{
bool refreshProvinceWithFacilities = SacsRandomHelper.GetInt32(1, 3) == 1;
if (refreshProvinceWithFacilities)
{
SaxGolfUsgaProvince.Params prmProvince = new SaxGolfUsgaProvince.Params();
prmProvince.PriorityFlagState = SacsHierarchyItem.Params.FlagState.True;
prmProvince.HasFacilities = SacsHierarchyItem.Params.BoolState.True;
prmProvince.StatusCat = SaxGolfUsgaProvince.StatusCat.ActiveOnly;
List<SaxGolfUsgaProvince> provincesWithFacilities = internals.ReferenceGolfMgr.GetUsgaProvinceList(prmProvince);
disposableItems.AddRange(provincesWithFacilities);
if (provincesWithFacilities.Any())
{
SaxGolfUsgaProvince usgaProvince = provincesWithFacilities[0];
List<SaxGolfUsgaDataLookup.CourseData> coursesData = LookupUsgaCourses(internals, usgaDataLookup, usgaProvince, true);
return;
}
}
}
//-----------------------------------------------------------
// 4. Markers.
// 4a. Populate active priority Course with no Markers.
{
bool populatePriorityCourseNoMarkers = SacsRandomHelper.GetInt32(1, 2) == 1;
if (populatePriorityCourseNoMarkers)
{
SaxGolfUsgaCourse.Params prmCourse = new SaxGolfUsgaCourse.Params();
prmCourse.PriorityFlagState = SacsHierarchyItem.Params.FlagState.True;
prmCourse.HasMarkers = SacsHierarchyItem.Params.BoolState.False;
prmCourse.StatusCat = SaxGolfUsgaCourse.StatusCat.ActiveOnly;
List<SaxGolfUsgaCourse> coursesNoMarkers = internals.ReferenceGolfMgr.GetUsgaCourseList(prmCourse);
disposableItems.AddRange(coursesNoMarkers);
if (coursesNoMarkers.Any())
{
SaxGolfUsgaCourse usgaCourse = coursesNoMarkers[0];
List<SaxGolfUsgaDataLookup.MarkerData> markersData = LookupUsgaMarkers(internals, usgaDataLookup, usgaCourse, false);
return;
}
}
}
// 4b. Refresh active priority Course with Markers.
{
bool refreshPriorityCourseWithMarkers = SacsRandomHelper.GetInt32(1, 3) == 1;
if (refreshPriorityCourseWithMarkers)
{
// Active priority Course with no Markers.
SaxGolfUsgaCourse.Params prmCourse = new SaxGolfUsgaCourse.Params();
prmCourse.PriorityFlagState = SacsHierarchyItem.Params.FlagState.True;
prmCourse.HasMarkers = SacsHierarchyItem.Params.BoolState.True;
prmCourse.StatusCat = SaxGolfUsgaCourse.StatusCat.ActiveOnly;
List<SaxGolfUsgaCourse> coursesWithMarkers = internals.ReferenceGolfMgr.GetUsgaCourseList(prmCourse);
disposableItems.AddRange(coursesWithMarkers);
if (coursesWithMarkers.Any())
{
// Refresh first Course with Markers.
SaxGolfUsgaCourse usgaCourse = coursesWithMarkers[0];
List<SaxGolfUsgaDataLookup.MarkerData> markersData = LookupUsgaMarkers(internals, usgaDataLookup, usgaCourse, true);
return;
}
}
}
//-----------------------------------------------------------
// 5. Fallback population.
// 5a. Active Country with no Provinces.
{
bool populateCountryNoProvinces = SacsRandomHelper.GetInt32(1, 2) == 1;
if (populateCountryNoProvinces)
{
SaxGolfUsgaCountry.Params prmCountry = new SaxGolfUsgaCountry.Params();
prmCountry.HasProvinces = SacsHierarchyItem.Params.BoolState.False;
prmCountry.StatusCat = SaxGolfUsgaCountry.StatusCat.ActiveOnly;
List<SaxGolfUsgaCountry> countriesNoProvinces = internals.ReferenceGolfMgr.GetUsgaCountryList(prmCountry).Randomise();
disposableItems.AddRange(countriesNoProvinces);
if (countriesNoProvinces.Any())
{
SaxGolfUsgaCountry usgaCountry = countriesNoProvinces[0];
List<SaxGolfUsgaDataLookup.ProvinceData> provincesData = usgaDataLookup.LookupUsgaProvincesForCountry(usgaCountry.CountryCode);
SaLogger.Info($"{SysUtil.Fn} USGA Provinces populated for {usgaCountry.CountryCode} {usgaCountry.CountryName} [Fallback]: {provincesData.Count}.", true);
return;
}
}
}
// 5b. Active Province with no Facilities (courses).
{
bool populateProvinceNoFacilities = SacsRandomHelper.GetInt32(1, 3) == 1;
if (populateProvinceNoFacilities)
{
// Active Provinces with no Facilities.
SaxGolfUsgaProvince.Params prmProvince = new SaxGolfUsgaProvince.Params();
prmProvince.HasFacilities = SacsHierarchyItem.Params.BoolState.False;
prmProvince.StatusCat = SaxGolfUsgaProvince.StatusCat.ActiveOnly;
List<SaxGolfUsgaProvince> provincesNoFacilities = internals.ReferenceGolfMgr.GetUsgaProvinceList(prmProvince);
disposableItems.AddRange(provincesNoFacilities);
if (provincesNoFacilities.Any())
{
// Province has no Facilities - populate courses.
SaxGolfUsgaProvince usgaProvince = provincesNoFacilities[0];
List<SaxGolfUsgaDataLookup.CourseData> coursesData = LookupUsgaCourses(internals, usgaDataLookup, usgaProvince, false, true);
return;
}
}
}
// 5c. Populate active Course with no Markers.
{
bool populateCourseNoMarkers = SacsRandomHelper.GetInt32(1, 2) == 1;
if (populateCourseNoMarkers)
{
SaxGolfUsgaCourse.Params prmCourse = new SaxGolfUsgaCourse.Params();
prmCourse.HasMarkers = SacsHierarchyItem.Params.BoolState.False;
prmCourse.StatusCat = SaxGolfUsgaCourse.StatusCat.ActiveOnly;
List<SaxGolfUsgaCourse> coursesNoMarkers = internals.ReferenceGolfMgr.GetUsgaCourseList(prmCourse);
disposableItems.AddRange(coursesNoMarkers);
if (coursesNoMarkers.Any())
{
SaxGolfUsgaCourse usgaCourse = coursesNoMarkers[0];
List<SaxGolfUsgaDataLookup.MarkerData> markersData = LookupUsgaMarkers(internals, usgaDataLookup, usgaCourse, false, true);
return;
}
}
}
//-----------------------------------------------------------
SaLogger.Warn($"{SysUtil.Fn} No data population task found to execute.");
//-----------------------------------------------------------
}
}
//-------------------------------------------------------------------
private static List<SaxGolfUsgaDataLookup.CourseData> LookupUsgaCourses(SaxInternals internals, SaxGolfUsgaDataLookup usgaDataLookup, SaxGolfUsgaProvince usgaProvince, bool refresh, bool fallback = false)
{
List<SaxGolfUsgaDataLookup.CourseData> coursesData = new List<CourseData>();
SaxGolfUsgaCountry usgaCountry = internals.ReferenceGolfMgr.GetUsgaCountryById(usgaProvince.CountryId);
if (usgaCountry != null)
{
coursesData = usgaDataLookup.LookupUsgaCoursesForCountryAndProvince(usgaCountry.CountryCode, usgaProvince.ProvinceCode);
List<String> annotations = new List<string>();
if (usgaProvince.Priority) annotations.Add("Priority");
if (fallback) annotations.Add("Fallback");
SaLogger.Info($"{SysUtil.Fn} USGA Courses refreshed for {usgaCountry.CountryCode} {usgaCountry.CountryName} - {usgaProvince.ProvinceCode} {usgaProvince.ProvinceName}" + (annotations.Any() ? $" [{annotations.Concat(", ")}]" : "") + $": {coursesData.Count}.", true);
}
else SaLogger.Error($"{SysUtil.Fn} USGA Country not found for Id {usgaProvince.CountryId} for Province {usgaProvince.ProvinceCode} {usgaProvince.ProvinceName}.");
return coursesData;
}
//-------------------------------------------------------------------
private static List<SaxGolfUsgaDataLookup.MarkerData> LookupUsgaMarkers(SaxInternals internals, SaxGolfUsgaDataLookup usgaDataLookup, SaxGolfUsgaCourse usgaCourse, bool refresh, bool fallback = false)
{
SaxGolfUsgaFacility usgaFacility = internals.ReferenceGolfMgr.GetUsgaFacilityById(usgaCourse.FacilityId);
SaxGolfUsgaProvince usgaProvince = internals.ReferenceGolfMgr.GetUsgaProvinceById(usgaFacility?.ProvinceId);
SaxGolfUsgaCountry usgaCountry = internals.ReferenceGolfMgr.GetUsgaCountryById(usgaProvince?.CountryId);
List<SaxGolfUsgaDataLookup.MarkerData> markersData = new List<MarkerData>();
if (usgaFacility != null)
{
if (usgaProvince != null)
{
if (usgaCountry != null)
{
markersData = usgaDataLookup.LookupUsgaMarkersForCourse(usgaCourse.CourseId);
List<String> annotations = new List<string>();
if (usgaCourse.Priority) annotations.Add("Priority");
if (fallback) annotations.Add("Fallback");
SaLogger.Info($"{SysUtil.Fn} USGA Markers " + (refresh ? "refreshed" : "populated") + $" for {usgaCountry.CountryCode} {usgaCountry.CountryName} - {usgaProvince.ProvinceCode} {usgaProvince.ProvinceName} - {usgaCourse.Caption} [Id: {usgaCourse.CourseId}" + (annotations.Any() ? $"{annotations.Concat("",", ")}" : "") + $"]: {markersData.Count}.", true);
}
else SaLogger.Error($"{SysUtil.Fn} Missing Country for Province {usgaProvince.ProvinceName}. Country Id: {usgaProvince.CountryId}.");
}
else SaLogger.Error($"{SysUtil.Fn} Missing Province for Facility {usgaFacility.FacilityName}. Province Id: {usgaFacility.ProvinceId}.");
}
else SaLogger.Error($"{SysUtil.Fn} Missing Facility for Course {usgaCourse.FullName}. Facility Id: {usgaCourse.FacilityId}.");
return markersData;
}
//-------------------------------------------------------------------
}
//=======================================================================
}