1.2.11.5
This commit is contained in:
@@ -227,7 +227,7 @@ namespace Saxonite.Net.Core.Web.Base.App
|
||||
Sax.Database databaseType = EnumUtil.ParseEnum<Sax.Database>(databaseSection.Key);
|
||||
if (databaseType <= 0)
|
||||
{
|
||||
SaLogger.Warn(GetType().Name + ".extractDatabaseConfig Unrecognised database: " + databaseSection.Key);
|
||||
SaLogger.Warn($"{SysUtil.Fn} Unrecognised database: {databaseSection.Key}");
|
||||
return;
|
||||
}
|
||||
// Extract database configuration.
|
||||
|
||||
@@ -73,7 +73,7 @@ namespace Saxonite.Net.Core.Web.Base.App
|
||||
}
|
||||
}
|
||||
if (text.ResourceNotFound && logMissingKey)
|
||||
SaLogger.Debug(GetType().Name + ".GetText Key not found: " + key);
|
||||
SaLogger.Debug($"{SysUtil.Fn} Key not found: {key}");
|
||||
return text;
|
||||
}
|
||||
|
||||
@@ -135,7 +135,7 @@ namespace Saxonite.Net.Core.Web.Base.App
|
||||
//-------------------------------------------------------------------
|
||||
public static String DateFormat_Default { get; } = "d-MMM-yyyy";
|
||||
public static String DateWithWeekdayFormat_Default { get; } = "ddd d-MMM-yyyy";
|
||||
public String FormatDate(DateTime value, Boolean includeWeekday = true)
|
||||
public String FormatDate(DateTime? value, Boolean includeWeekday = true)
|
||||
{
|
||||
String dateFormat = includeWeekday ? DateWithWeekdayFormat_Default : DateFormat_Default;
|
||||
return DateUtil.Format(value, dateFormat);
|
||||
@@ -175,7 +175,7 @@ namespace Saxonite.Net.Core.Web.Base.App
|
||||
private String GetCodeTypeCaption<T>(Sax.CodeType codeType, T type) where T : struct, IConvertible
|
||||
{
|
||||
if (!(type is Enum))
|
||||
throw new ArgumentException(GetType().Name + ".GetCodeTypeCaption Type parameter must be an enumerated type. Type supplied: " + type.GetType().Name);
|
||||
throw new ArgumentException($"{SysUtil.Fn} Type parameter must be an enumerated type. Type supplied: {type.GetType().Name}");
|
||||
return GetCodeTypeCaption(codeType, (int)(type as IConvertible), type.ToString());
|
||||
}
|
||||
private String GetCodeTypeCaption(Sax.CodeType codeType, int type, String typeName)
|
||||
|
||||
@@ -116,7 +116,7 @@ namespace Saxonite.Net.Core.Web.Base.App
|
||||
LanguageViewLocationExpanderFormat.Suffix,
|
||||
opts => { opts.ResourcesPath = resourcesPath; })
|
||||
.AddDataAnnotationsLocalization()
|
||||
// Ignore null values during object serisliation.
|
||||
// Ignore null values during object serialiation.
|
||||
.AddJsonOptions(options => { options.JsonSerializerOptions.DefaultIgnoreCondition = System.Text.Json.Serialization.JsonIgnoreCondition.WhenWritingNull; });
|
||||
|
||||
// Configure localisation middleware.
|
||||
|
||||
@@ -1,37 +1,14 @@
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Localization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.Filters;
|
||||
using Microsoft.AspNetCore.Routing;
|
||||
using Microsoft.Net.Http.Headers;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Serialization;
|
||||
using Sacs.Web.Components;
|
||||
using Sacs.Web.Components;
|
||||
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.Email;
|
||||
using Sarand.Net.Standard.Base.Helpers;
|
||||
using Sarand.Net.Standard.Base.Utils;
|
||||
using Saxonite.Net.Core.Web.Base.App;
|
||||
using Saxonite.Net.Core.Web.Base.Consoles;
|
||||
using Saxonite.Net.Core.Web.Base.Models;
|
||||
using Saxonite.Net.Standard.Base.App;
|
||||
using Saxonite.Net.Standard.Base.Bus;
|
||||
using Saxonite.Net.Standard.Base.Consoles;
|
||||
using Saxonite.Net.Standard.Base.Mgr;
|
||||
using Saxonite.Net.Standard.Base.Mgr.Reference;
|
||||
using Saxonite.Net.Standard.Base.Mgr.Support;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Specialized;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Web;
|
||||
|
||||
namespace Saxonite.Net.Core.Web.Base.Controllers
|
||||
{
|
||||
@@ -51,7 +28,7 @@ namespace Saxonite.Net.Core.Web.Base.Controllers
|
||||
// Initialise console (debug) logging listener.
|
||||
//if (Directory.Exists(App.LoggingRootFolder) && SaxSystem.DebugMode)
|
||||
// SaxConsoleListener.ConfigureDebugListener(App.LoggingRootFolder);
|
||||
if (DebugMode) SaLogger.Trace(GetType().Name + ".CTR");
|
||||
if (DebugMode) SaLogger.Trace($"{GetType().Name}.CTR");
|
||||
}
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
@@ -111,184 +88,6 @@ namespace Saxonite.Net.Core.Web.Base.Controllers
|
||||
public SaEmailConfig EmailConfig { get { return App.EmailConfig; } }
|
||||
public SaxEmailConsole EmailConsole { get { return Internals.EmailConsole; } }
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Action execution events.
|
||||
//-------------------------------------------------------------------
|
||||
public override void OnActionExecuting(ActionExecutingContext filterContext)
|
||||
{
|
||||
//if (DebugMode) SaLogger.Debug(GetType().Name + ".OnActionExecuting" + (ViewData.Model != null ? " Model: " + ViewData.Model : ""));
|
||||
|
||||
// Refreh model properties.
|
||||
SaxModel_Base baseModel = ViewData.Model as SaxModel_Base;
|
||||
RefreshModel(baseModel);
|
||||
|
||||
base.OnActionExecuting(filterContext);
|
||||
}
|
||||
public override void OnActionExecuted(ActionExecutedContext filterContext)
|
||||
{
|
||||
//if (DebugMode) SaLogger.Debug(GetType().Name + ".OnActionExecuted" + (ViewData.Model != null ? " Model: " + ViewData.Model : ""));
|
||||
|
||||
// Refreh model properties.
|
||||
SaxModel_Base baseModel = ViewData.Model as SaxModel_Base;
|
||||
RefreshModel(baseModel);
|
||||
|
||||
// Store session data if present - as potentially modfied.
|
||||
if (SessionData != null)
|
||||
{
|
||||
// Most actions will store the session data in case it's been modified.
|
||||
// Some actions (eg. score password) don't need to.
|
||||
if (StoreSessionData)
|
||||
{
|
||||
String sessionDataJson = JsonConvert.SerializeObject(SessionData);
|
||||
HttpContext.Session.Set(SessionStorage.SessionKey_SessionData, SessionStorage.sessionDataEncoding.GetBytes(sessionDataJson));
|
||||
}
|
||||
}
|
||||
else HttpContext.Session.Remove(SessionStorage.SessionKey_SessionData);
|
||||
|
||||
// Response headers.
|
||||
if (baseModel != null && baseModel.ProhibitCache)
|
||||
{
|
||||
if (Response.Headers.ContainsKey(HeaderNames.CacheControl))
|
||||
Response.Headers.Remove(HeaderNames.CacheControl);
|
||||
Response.Headers.Add(HeaderNames.CacheControl, "no-cache, no-store, must-revalidate");
|
||||
Response.Headers.Add(HeaderNames.Pragma, "no-cache");
|
||||
Response.Headers.Add(HeaderNames.Expires, "0");
|
||||
}
|
||||
|
||||
base.OnActionExecuted(filterContext);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Model.
|
||||
//-------------------------------------------------------------------
|
||||
protected void RefreshModel(SaxModel_Base model)
|
||||
{
|
||||
if (model == null) return;
|
||||
|
||||
// Session data.
|
||||
model.Controller = this;
|
||||
model.SessionData = SessionData;
|
||||
|
||||
// Redirect locations.
|
||||
model.RedirectLocation.Base = GetRedirectLocation(RedirectLocation.WebAppBase);
|
||||
model.RedirectLocation.Home = GetRedirectLocation(RedirectLocation.WebAppHome);
|
||||
model.RedirectLocation.Home_SessionExpired = GetRedirectLocation(RedirectLocation.WebAppHome_SessionExpired);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Parameters.
|
||||
//-------------------------------------------------------------------
|
||||
// Online Request Password encryption parameters (key & IV) are defined in
|
||||
// the base Controller so that they can be shared with the Adnin application.
|
||||
// NB IV value is generated from the key and fixed so that it doesn't change when the application restarts.
|
||||
// IV Must be regenerated if key is changed.
|
||||
protected static String Base64Key_RequestPassword_Online { get; } = SacsEncryptionHelper.EncodePlainKey("{~Saxonite@@Request^Password=}", SacsEncryptionHelper.KeyLength);
|
||||
//private static String Base64IV_RequestPassword_Generated_Online { get; } = SacsEncryptionHelper.InitSymmetricEncryptionIV(Base64Key_RequestPassword_Online);
|
||||
protected static String Base64IV_RequestPassword_Online { get; } = "1VAWYTW6d72n/6HDNhbqow==";
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Session.
|
||||
//-------------------------------------------------------------------
|
||||
private bool UserActiveRecorded { get; set; } = false;
|
||||
public bool ValidUserSession
|
||||
{
|
||||
get
|
||||
{
|
||||
if (SessionData == null || !SessionData.ValidUserSession) return false;
|
||||
SaxSessionDataConsole sessionDataConsole = SessionDataConsole;
|
||||
if (sessionDataConsole != null && !UserActiveRecorded)
|
||||
{
|
||||
// Record the user as active once per request.
|
||||
sessionDataConsole.RecordUserActive(SessionUserAccountId, CreatedAt);
|
||||
UserActiveRecorded = true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
public SysId SessionUserAccountId { get { return SessionData?.User?.UserAccountId ?? null; } }
|
||||
public DbUpdateInfo DbUpdateInfo { get { return SessionData?.DbUpdateInfo ?? new DbUpdateInfo(null, "", SaxSystem.ComputerName); } }
|
||||
// Referrer.
|
||||
public String Referer { get { return Request.Headers["Referer"].ToString(); } }
|
||||
public bool ValidReferer { get { return !StringUtil.IsEmpty(Referer); } }
|
||||
|
||||
/// <summary>Store session data, eg. to start a new user session on sign-in.</summary>
|
||||
protected bool SetSessionData(SaxSessionData sessionData)
|
||||
{
|
||||
if (sessionStorage.SessionData != null) return false;
|
||||
sessionStorage.SessionData = sessionData;
|
||||
return true;
|
||||
}
|
||||
protected void ClearSessionData()
|
||||
{
|
||||
if (HttpContext.Session.IsAvailable)
|
||||
HttpContext.Session.Clear();
|
||||
sessionStorage.SessionData = null;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Session storage.
|
||||
public class SessionStorage
|
||||
{
|
||||
public SaxSessionData SessionData { get; set; }
|
||||
public static String SessionKey_SessionData { get; } = "SaxSessionData";
|
||||
public static Encoding sessionDataEncoding { get; } = Encoding.UTF8;
|
||||
//JSON Serialisation.
|
||||
public class SaxSessionDataContractResolver : DefaultContractResolver
|
||||
{
|
||||
// To allow private properties to be deserialised.
|
||||
// NB Only applies to top level properties in the serialised object.
|
||||
protected override List<MemberInfo> GetSerializableMembers(Type objectType)
|
||||
{
|
||||
var flags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
|
||||
MemberInfo[] fields = objectType.GetFields(flags);
|
||||
return fields
|
||||
.Concat(objectType.GetProperties(flags).Where(propInfo => propInfo.CanWrite))
|
||||
.ToList();
|
||||
}
|
||||
protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
|
||||
{
|
||||
return base.CreateProperties(type, MemberSerialization.Fields);
|
||||
}
|
||||
};
|
||||
public static JsonSerializerSettings JsonDeserialisationSettings = new JsonSerializerSettings
|
||||
{
|
||||
ContractResolver = new SaxSessionDataContractResolver(),
|
||||
// Force all deserialised objects to be replaced - to avoid proxy lists not populating.
|
||||
ObjectCreationHandling = ObjectCreationHandling.Replace
|
||||
};
|
||||
}
|
||||
private readonly SessionStorage sessionStorage = new SessionStorage();
|
||||
protected JsonSerializerSettings SaxSessionDataJsonSerializerSettings { get { return SessionStorage.JsonDeserialisationSettings; } }
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
public SaxSessionData SessionData
|
||||
{
|
||||
get
|
||||
{
|
||||
try
|
||||
{
|
||||
// Retrieve session data if not already in controller.
|
||||
if (sessionStorage.SessionData == null)
|
||||
{
|
||||
byte[] sessionDataBytes = null;
|
||||
HttpContext.Session.TryGetValue(SessionStorage.SessionKey_SessionData, out sessionDataBytes);
|
||||
if (sessionDataBytes != null)
|
||||
{
|
||||
String sessionDataJson = SessionStorage.sessionDataEncoding.GetString(sessionDataBytes);
|
||||
sessionStorage.SessionData = DeserializeSessionData(sessionDataJson);
|
||||
}
|
||||
}
|
||||
return sessionStorage.SessionData;
|
||||
}
|
||||
catch (Exception exc)
|
||||
{
|
||||
SaLogger.Warn(GetType().Name + ".SessionData " + exc.GetType().Name + " - " + exc.Message + exc.GetStackEntries().Concat("", "\n\t"));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
protected abstract SaxSessionData DeserializeSessionData(String sessionDataJson);
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
}
|
||||
//=======================================================================
|
||||
|
||||
@@ -0,0 +1,225 @@
|
||||
using Microsoft.AspNetCore.Mvc.Filters;
|
||||
using Microsoft.Net.Http.Headers;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Serialization;
|
||||
using Sarand.Net.Standard.Base.App;
|
||||
using Sarand.Net.Standard.Base.Bus;
|
||||
using Sarand.Net.Standard.Base.Dbas;
|
||||
using Sarand.Net.Standard.Base.Helpers;
|
||||
using Sarand.Net.Standard.Base.Utils;
|
||||
using Saxonite.Net.Core.Web.Base.App;
|
||||
using Saxonite.Net.Core.Web.Base.Models;
|
||||
using Saxonite.Net.Standard.Base.App;
|
||||
using Saxonite.Net.Standard.Base.Consoles;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
|
||||
namespace Saxonite.Net.Core.Web.Base.Controllers
|
||||
{
|
||||
//=======================================================================
|
||||
public abstract class SaxController_Web : SaxController_Base
|
||||
{
|
||||
//-------------------------------------------------------------------
|
||||
// Data members.
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Protected construction.
|
||||
protected SaxController_Web(SaxLocaliser localiser) : base(localiser)
|
||||
{
|
||||
}
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Properties.
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Action execution events.
|
||||
//-------------------------------------------------------------------
|
||||
public override void OnActionExecuting(ActionExecutingContext filterContext)
|
||||
{
|
||||
//if (DebugMode) SaLogger.Debug($"{SysUtil.Fn}" + (ViewData.Model != null ? " Model: " + ViewData.Model : ""));
|
||||
|
||||
// Refreh model properties.
|
||||
SaxModel_Base baseModel = ViewData.Model as SaxModel_Base;
|
||||
RefreshModel(baseModel);
|
||||
|
||||
base.OnActionExecuting(filterContext);
|
||||
}
|
||||
public override void OnActionExecuted(ActionExecutedContext filterContext)
|
||||
{
|
||||
//if (DebugMode) SaLogger.Debug($"{SysUtil.Fn}" + (ViewData.Model != null ? " Model: " + ViewData.Model : ""));
|
||||
|
||||
// Refreh model properties.
|
||||
SaxModel_Base baseModel = ViewData.Model as SaxModel_Base;
|
||||
RefreshModel(baseModel);
|
||||
|
||||
// Store session data if present - as potentially modfied.
|
||||
if (SessionData != null)
|
||||
{
|
||||
// Most actions will store the session data in case it's been modified.
|
||||
// Some actions (eg. score password) don't need to.
|
||||
if (StoreSessionData)
|
||||
{
|
||||
String sessionDataJson = JsonConvert.SerializeObject(SessionData);
|
||||
HttpContext.Session.Set(SessionStorage.SessionKey_SessionData, SessionStorage.sessionDataEncoding.GetBytes(sessionDataJson));
|
||||
}
|
||||
}
|
||||
else HttpContext.Session.Remove(SessionStorage.SessionKey_SessionData);
|
||||
|
||||
// Response headers.
|
||||
if (baseModel != null && baseModel.ProhibitCache)
|
||||
{
|
||||
if (Response.Headers.ContainsKey(HeaderNames.CacheControl))
|
||||
Response.Headers.Remove(HeaderNames.CacheControl);
|
||||
Response.Headers.Add(HeaderNames.CacheControl, "no-cache, no-store, must-revalidate");
|
||||
Response.Headers.Add(HeaderNames.Pragma, "no-cache");
|
||||
Response.Headers.Add(HeaderNames.Expires, "0");
|
||||
}
|
||||
|
||||
base.OnActionExecuted(filterContext);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Model.
|
||||
//-------------------------------------------------------------------
|
||||
protected void RefreshModel(SaxModel_Base model)
|
||||
{
|
||||
if (model == null) return;
|
||||
|
||||
// Session data.
|
||||
model.Controller = this;
|
||||
model.SessionData = SessionData;
|
||||
|
||||
// Redirect locations.
|
||||
model.RedirectLocation.Base = GetRedirectLocation(RedirectLocation.WebAppBase);
|
||||
model.RedirectLocation.Home = GetRedirectLocation(RedirectLocation.WebAppHome);
|
||||
model.RedirectLocation.Home_SessionExpired = GetRedirectLocation(RedirectLocation.WebAppHome_SessionExpired);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Parameters.
|
||||
//-------------------------------------------------------------------
|
||||
// Online Request Password encryption parameters (key & IV) are defined in
|
||||
// the base Controller so that they can be shared with the Adnin application.
|
||||
// NB IV value is generated from the key and fixed so that it doesn't change when the application restarts.
|
||||
// IV Must be regenerated if key is changed.
|
||||
protected static String Base64Key_RequestPassword_Online { get; } = SacsEncryptionHelper.EncodePlainKey("{~Saxonite@@Request^Password=}", SacsEncryptionHelper.KeyLength);
|
||||
//private static String Base64IV_RequestPassword_Generated_Online { get; } = SacsEncryptionHelper.InitSymmetricEncryptionIV(Base64Key_RequestPassword_Online);
|
||||
protected static String Base64IV_RequestPassword_Online { get; } = "1VAWYTW6d72n/6HDNhbqow==";
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Session.
|
||||
//-------------------------------------------------------------------
|
||||
private bool UserActiveRecorded { get; set; } = false;
|
||||
public bool ValidUserSession
|
||||
{
|
||||
get
|
||||
{
|
||||
if (SessionData == null || !SessionData.ValidUserSession) return false;
|
||||
SaxSessionDataConsole sessionDataConsole = SessionDataConsole;
|
||||
if (sessionDataConsole != null && !UserActiveRecorded)
|
||||
{
|
||||
// Record the user as active once per request.
|
||||
sessionDataConsole.RecordUserActive(SessionUserAccountId, CreatedAt);
|
||||
UserActiveRecorded = true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
public SysId SessionUserAccountId { get { return SessionData?.User?.UserAccountId ?? null; } }
|
||||
public DbUpdateInfo DbUpdateInfo { get { return SessionData?.DbUpdateInfo ?? new DbUpdateInfo(null, "", SaxSystem.ComputerName); } }
|
||||
// Referrer.
|
||||
public String Referer { get { return Request.Headers["Referer"].ToString(); } }
|
||||
public bool ValidReferer { get { return !StringUtil.IsEmpty(Referer); } }
|
||||
|
||||
/// <summary>Store session data, eg. to start a new user session on sign-in.</summary>
|
||||
protected bool SetSessionData(SaxSessionData sessionData)
|
||||
{
|
||||
if (sessionStorage.SessionData != null) return false;
|
||||
sessionStorage.SessionData = sessionData;
|
||||
return true;
|
||||
}
|
||||
protected void ClearSessionData()
|
||||
{
|
||||
if (HttpContext.Session.IsAvailable)
|
||||
HttpContext.Session.Clear();
|
||||
sessionStorage.SessionData = null;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Session storage.
|
||||
public class SessionStorage
|
||||
{
|
||||
public SaxSessionData SessionData { get; set; }
|
||||
public static String SessionKey_SessionData { get; } = "SaxSessionData";
|
||||
public static Encoding sessionDataEncoding { get; } = Encoding.UTF8;
|
||||
//JSON Serialisation.
|
||||
public class SaxSessionDataContractResolver : DefaultContractResolver
|
||||
{
|
||||
// To allow private properties to be deserialised.
|
||||
// NB Only applies to top level properties in the serialised object.
|
||||
protected override List<MemberInfo> GetSerializableMembers(Type objectType)
|
||||
{
|
||||
var flags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
|
||||
MemberInfo[] fields = objectType.GetFields(flags);
|
||||
return fields
|
||||
.Concat(objectType.GetProperties(flags).Where(propInfo => propInfo.CanWrite))
|
||||
.ToList();
|
||||
}
|
||||
protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
|
||||
{
|
||||
return base.CreateProperties(type, MemberSerialization.Fields);
|
||||
}
|
||||
};
|
||||
public static JsonSerializerSettings JsonDeserialisationSettings = new JsonSerializerSettings
|
||||
{
|
||||
ContractResolver = new SaxSessionDataContractResolver(),
|
||||
// Force all deserialised objects to be replaced - to avoid proxy lists not populating.
|
||||
ObjectCreationHandling = ObjectCreationHandling.Replace
|
||||
};
|
||||
}
|
||||
private readonly SessionStorage sessionStorage = new SessionStorage();
|
||||
protected JsonSerializerSettings SaxSessionDataJsonSerializerSettings { get { return SessionStorage.JsonDeserialisationSettings; } }
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
public SaxSessionData SessionData
|
||||
{
|
||||
get
|
||||
{
|
||||
try
|
||||
{
|
||||
// Retrieve session data if not already in controller.
|
||||
if (sessionStorage.SessionData == null)
|
||||
{
|
||||
byte[] sessionDataBytes = null;
|
||||
HttpContext.Session.TryGetValue(SessionStorage.SessionKey_SessionData, out sessionDataBytes);
|
||||
if (sessionDataBytes != null)
|
||||
{
|
||||
String sessionDataJson = SessionStorage.sessionDataEncoding.GetString(sessionDataBytes);
|
||||
sessionStorage.SessionData = DeserializeSessionData(sessionDataJson);
|
||||
}
|
||||
}
|
||||
return sessionStorage.SessionData;
|
||||
}
|
||||
catch (Exception exc)
|
||||
{
|
||||
SaLogger.Warn($"{SysUtil.Fn} {exc.GetType().Name} - {exc.Message}{exc.GetStackEntries().Concat("", "\n\t")}");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
protected abstract SaxSessionData DeserializeSessionData(String sessionDataJson);
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
}
|
||||
//=======================================================================
|
||||
}
|
||||
@@ -12,6 +12,9 @@ using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using static Saxonite.Net.Standard.Base.App.Sax.Config.Security;
|
||||
|
||||
// Ignore obsolete warning on ComplexTypeModelBinder.
|
||||
#pragma warning disable 0618
|
||||
|
||||
namespace Saxonite.Net.Core.Web.Base.Middleware
|
||||
{
|
||||
//=======================================================================
|
||||
|
||||
@@ -215,10 +215,18 @@ namespace Saxonite.Net.Core.Web.Base.Models
|
||||
//-------------------------------------------------------------------
|
||||
// Display data - Dates.
|
||||
public String FormatDateForDisplay(DateTime value)
|
||||
{
|
||||
return FormatDateForDisplay((DateTime?)value);
|
||||
}
|
||||
public String FormatDateForDisplay(DateTime? value)
|
||||
{
|
||||
return DateUtil.Format(value, "d-MMM-yy", SessionCulture);
|
||||
}
|
||||
public String FormatDateTimeForDisplay(DateTime value)
|
||||
{
|
||||
return FormatDateTimeForDisplay((DateTime?)value);
|
||||
}
|
||||
public String FormatDateTimeForDisplay(DateTime? value)
|
||||
{
|
||||
return StringUtil.TrimAll(DateUtil.Format(value, "d-MMM-yy HH:mm", SessionCulture));
|
||||
}
|
||||
@@ -249,7 +257,7 @@ namespace Saxonite.Net.Core.Web.Base.Models
|
||||
return "dd-M-yy";
|
||||
}
|
||||
}
|
||||
public String FormatDateForForm(DateTime value)
|
||||
public String FormatDateForForm(DateTime? value)
|
||||
{
|
||||
return DateUtil.Format(value, "dd-MMM-yyyy", SessionCulture);
|
||||
}
|
||||
|
||||
@@ -66,7 +66,7 @@ namespace Saxonite.Net.Core.Web.Base.Procs
|
||||
// Check USGA Country Province population.
|
||||
List<SaxGolfUsgaCountry> usgaCountriesWithProvinces = new List<SaxGolfUsgaCountry>();
|
||||
List<SaxGolfUsgaCountry> usgaCountriesWithNoProvinces = new List<SaxGolfUsgaCountry>();
|
||||
foreach (SaxGolfUsgaCountry usgaCountry in usgaCountries.OrderBy(_ => SacsRandomHelper.GetInt32(Int32.MaxValue)))
|
||||
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);
|
||||
@@ -77,7 +77,7 @@ namespace Saxonite.Net.Core.Web.Base.Procs
|
||||
{
|
||||
// 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}: {provincesData.Count}.", true);
|
||||
SaLogger.Info($"{SysUtil.Fn} USGA Provinces populated for {usgaCountry.CountryCode} {usgaCountry.CountryName}" + (usgaCountry.Priority ? " [Priority]" : "") + $": {provincesData.Count}.", true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -100,12 +100,12 @@ namespace Saxonite.Net.Core.Web.Base.Procs
|
||||
{
|
||||
SaxGolfUsgaProvince.Params prmUsgaProvince = new SaxGolfUsgaProvince.Params();
|
||||
prmUsgaProvince.CountryIdsIncluded.Add(usgaCountry.Id);
|
||||
List<SaxGolfUsgaProvince> usgaProvinces = internals.ReferenceGolfMgr.GetUsgaProvinceList(prmUsgaProvince).OrderBy(_ => SacsRandomHelper.GetInt32(Int32.MaxValue)).ToList();
|
||||
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}: {provincesData.Count}.", true);
|
||||
SaLogger.Info($"{SysUtil.Fn} USGA Provinces refreshed for {usgaCountry.CountryCode} {usgaCountry.CountryName}" + (usgaCountry.Priority ? " [Priority]" : "") + $": {provincesData.Count}.", true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -124,7 +124,7 @@ namespace Saxonite.Net.Core.Web.Base.Procs
|
||||
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(_ => SacsRandomHelper.GetInt32(Int32.MaxValue)))
|
||||
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);
|
||||
@@ -135,7 +135,7 @@ namespace Saxonite.Net.Core.Web.Base.Procs
|
||||
{
|
||||
// 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}: {coursesData.Count}.", true);
|
||||
SaLogger.Info($"{SysUtil.Fn} USGA Courses populated for {usgaCountry.CountryCode} {usgaCountry.CountryName} - {usgaProvince.ProvinceCode} {usgaProvince.ProvinceName}" + (usgaProvince.Priority ? " [Priority]" : "") + $": {coursesData.Count}.", true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -158,14 +158,14 @@ namespace Saxonite.Net.Core.Web.Base.Procs
|
||||
{
|
||||
// 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}: {coursesData.Count}.", true);
|
||||
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(_ => SacsRandomHelper.GetInt32(Int32.MaxValue)).ToList();
|
||||
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)
|
||||
{
|
||||
@@ -175,7 +175,7 @@ namespace Saxonite.Net.Core.Web.Base.Procs
|
||||
{
|
||||
// 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}]: {markersData.Count}.", true);
|
||||
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);
|
||||
@@ -185,7 +185,7 @@ namespace Saxonite.Net.Core.Web.Base.Procs
|
||||
// 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}]: {markersData.Count}.", true);
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -198,7 +198,7 @@ namespace Saxonite.Net.Core.Web.Base.Procs
|
||||
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}: {coursesData.Count}. [Fallback]", true);
|
||||
SaLogger.Info($"{SysUtil.Fn} USGA Courses populated for {usgaCountry.CountryCode} {usgaCountry.CountryName} - {usgaProvince.ProvinceCode} {usgaProvince.ProvinceName}" + (usgaProvince.Priority ? " [Priority]" : "") + $": {coursesData.Count}. [Fallback]", true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -212,7 +212,7 @@ namespace Saxonite.Net.Core.Web.Base.Procs
|
||||
if (usgaCountry != null)
|
||||
{
|
||||
List<SaxGolfUsgaDataLookup.ProvinceData> provincesData = usgaDataLookup.LookupUsgaProvincesForCountry(usgaCountry.CountryCode);
|
||||
SaLogger.Info($"{SysUtil.Fn} USGA Provinces populated for {usgaCountry.CountryCode} {usgaCountry.CountryName}: {provincesData.Count}. [Fallback]", true);
|
||||
SaLogger.Info($"{SysUtil.Fn} USGA Provinces populated for {usgaCountry.CountryCode} {usgaCountry.CountryName}" + (usgaCountry.Priority ? " [Priority]" : "") + $": {provincesData.Count}. [Fallback]", true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
using HtmlAgilityPack;
|
||||
using MailKit;
|
||||
using Microsoft.Net.Http.Headers;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using Sarand.Net.Standard.Base.App;
|
||||
using Sarand.Net.Standard.Base.Bus;
|
||||
@@ -11,6 +12,7 @@ using Sarand.Net.Standard.Base.Helpers;
|
||||
using Sarand.Net.Standard.Base.Net;
|
||||
using Sarand.Net.Standard.Base.Utils;
|
||||
using Saxonite.Net.Standard.Base.App;
|
||||
using Saxonite.Net.Standard.Base.Bus.Reference;
|
||||
using Saxonite.Net.Standard.Base.Mgr.Reference;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
@@ -108,8 +110,8 @@ namespace Saxonite.Net.Core.Web.Base.Procs
|
||||
public SysId CourseId { get; }
|
||||
public SysId MarkerId { get; set; }
|
||||
public string Caption { get { return StringUtil.TrimWhitespace(StringUtil.OnBlank(Tee) + " " + StringUtil.OnBlank(HolesCaption) + " " + StringUtil.OnBlank(Gender)); } }
|
||||
public short Holes { get; }
|
||||
public string HolesCaption { get; }
|
||||
public short Holes { get; set; }
|
||||
public string HolesCaption { get; set; }
|
||||
public string Tee { get; set; }
|
||||
public string Gender { get; set; }
|
||||
public short SlopeRating { get; set; }
|
||||
@@ -117,15 +119,16 @@ namespace Saxonite.Net.Core.Web.Base.Procs
|
||||
public decimal CourseRating { get; set; }
|
||||
public decimal BogeyRating { get; set; }
|
||||
public short Length { get; set; }
|
||||
public bool IsValid()
|
||||
public bool IsValid(bool ignorePar = false)
|
||||
{
|
||||
if (!SysId.IsValid(CourseId)) return false;
|
||||
if (!SysId.IsValid(MarkerId)) return false;
|
||||
// 9 hole markers do not have there own Id.
|
||||
//if (!SysId.IsValid(MarkerId)) return false;
|
||||
if (Holes < 1) return false;
|
||||
if (StringUtil.IsBlank(Tee)) return false;
|
||||
if (StringUtil.IsBlank(Gender)) return false;
|
||||
if (SlopeRating == 0) return false;
|
||||
if (Par == 0) return false;
|
||||
if (!ignorePar && Par == 0) return false;
|
||||
if (CourseRating == 0) return false;
|
||||
return true;
|
||||
}
|
||||
@@ -240,7 +243,7 @@ namespace Saxonite.Net.Core.Web.Base.Procs
|
||||
try
|
||||
{
|
||||
|
||||
// Query countries on USGA website.
|
||||
// Query Countries on USGA website.
|
||||
CancellationToken cancelToken = new CancellationToken();
|
||||
SacsHttpRequestData request = new SacsHttpRequestData(cancelToken) { Url = "https://ncrdb.usga.org/" };
|
||||
SacsHttpResponseData response = SacsHttpClient.DoRequest(request).Result;
|
||||
@@ -285,7 +288,7 @@ namespace Saxonite.Net.Core.Web.Base.Procs
|
||||
countryData.CountryName = usgaCountry.Name;
|
||||
countriesData.Add(countryData);
|
||||
}
|
||||
ReferenceGolfMgr.BulkUpdateUsgaCountries(countriesData, config.DbUpdateInfo);
|
||||
ReferenceGolfMgr.BulkUpdateUsgaCountries(countriesData, DbUpdateInfo);
|
||||
if (ReferenceGolfMgr.HasErrorState())
|
||||
SaLogger.Warn($"{SysUtil.Fn} Error bulk updating USGA countries: {ReferenceGolfMgr.ErrorStateMessage}.");
|
||||
|
||||
@@ -308,77 +311,95 @@ namespace Saxonite.Net.Core.Web.Base.Procs
|
||||
|
||||
UsgaRequestData usgaRequestData = GetUsgaRequestData();
|
||||
|
||||
try
|
||||
using (DisposableCollection<SacsDisposable> disposableItems = new DisposableCollection<SacsDisposable>())
|
||||
{
|
||||
// Query countries on USGA website.
|
||||
CancellationToken cancelToken = new CancellationToken();
|
||||
SacsHttpRequestData request = new SacsHttpRequestData(cancelToken) { Url = "https://ncrdb.usga.org/NCRListing?handler=LoadStates" };
|
||||
// Headers.
|
||||
request.RequestHeaders.Add(HeaderNames.Accept, "*/*");
|
||||
request.RequestHeaders.Add(HeaderNames.AcceptEncoding, "gzip, deflate, br, zstd");
|
||||
request.RequestHeaders.Add(HeaderNames.AcceptLanguage, "en-GB,en;q=0.9");
|
||||
request.RequestHeaders.Add(HeaderNames.DNT, "1");
|
||||
request.RequestHeaders.Add(HeaderNames.Origin, "https://ncrdb.usga.org/");
|
||||
request.RequestHeaders.Add("Priority", "u=1, i");
|
||||
request.RequestHeaders.Add(HeaderNames.Referer, "https://ncrdb.usga.org/");
|
||||
if (!StringUtil.IsBlank(usgaRequestData.RequestVerificationToken))
|
||||
request.RequestHeaders.Add("Requestverificationtoken", usgaRequestData.RequestVerificationToken);
|
||||
// Content.
|
||||
request.FormData.Add(new KeyValuePair<string, string>("countryCode", countryCode));
|
||||
request.ContentHeaders.Add(HeaderNames.ContentType, "application/x-www-form-urlencoded; charset=UTF-8");
|
||||
// Request.
|
||||
SacsHttpResponseData response = SacsHttpClient.DoRequest(request).Result;
|
||||
String data = response.Data;
|
||||
|
||||
if (!StringUtil.IsBlank(response.Data))
|
||||
// Retrieve and validate country.
|
||||
SaxGolfUsgaCountry usgaCountry = ReferenceGolfMgr.GetUsgaCountry(new SaxGolfUsgaCountry.Params() { CountryCodeFull = countryCode });
|
||||
disposableItems.Add(usgaCountry);
|
||||
if (usgaCountry == null)
|
||||
{
|
||||
dynamic provincesJson = SacsJsonHelper.DeserializeJsonObject(response.Data);
|
||||
if (provincesJson is JArray)
|
||||
SaLogger.Warn($"{SysUtil.Fn} USGA Country not found for code '{countryCode}'.");
|
||||
return usgaProvinces;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
// Query Provinces for Country on USGA website.
|
||||
CancellationToken cancelToken = new CancellationToken();
|
||||
SacsHttpRequestData request = new SacsHttpRequestData(cancelToken) { Url = "https://ncrdb.usga.org/NCRListing?handler=LoadStates" };
|
||||
// Headers.
|
||||
request.RequestHeaders.Add(HeaderNames.Accept, "*/*");
|
||||
request.RequestHeaders.Add(HeaderNames.AcceptEncoding, "gzip, deflate, br, zstd");
|
||||
request.RequestHeaders.Add(HeaderNames.AcceptLanguage, "en-GB,en;q=0.9");
|
||||
request.RequestHeaders.Add(HeaderNames.DNT, "1");
|
||||
request.RequestHeaders.Add(HeaderNames.Origin, "https://ncrdb.usga.org/");
|
||||
request.RequestHeaders.Add("Priority", "u=1, i");
|
||||
request.RequestHeaders.Add(HeaderNames.Referer, "https://ncrdb.usga.org/");
|
||||
if (!StringUtil.IsBlank(usgaRequestData.RequestVerificationToken))
|
||||
request.RequestHeaders.Add("Requestverificationtoken", usgaRequestData.RequestVerificationToken);
|
||||
// Content.
|
||||
request.FormData.Add(new KeyValuePair<string, string>("countryCode", countryCode));
|
||||
request.ContentHeaders.Add(HeaderNames.ContentType, "application/x-www-form-urlencoded; charset=UTF-8");
|
||||
// Request.
|
||||
SacsHttpResponseData response = SacsHttpClient.DoRequest(request).Result;
|
||||
String data = response.Data;
|
||||
|
||||
if (!StringUtil.IsBlank(response.Data))
|
||||
{
|
||||
JArray provincesArray = provincesJson as JArray;
|
||||
foreach (var provinceToken in provincesArray)
|
||||
dynamic provincesJson = SacsJsonHelper.DeserializeJsonObject(response.Data);
|
||||
if (provincesJson is JArray)
|
||||
{
|
||||
// Province properties.
|
||||
ProvinceData provinceData = new ProvinceData();
|
||||
foreach (var propertyToken in provinceToken)
|
||||
JArray provincesArray = provincesJson as JArray;
|
||||
foreach (var provinceToken in provincesArray)
|
||||
{
|
||||
if (propertyToken is JProperty)
|
||||
// Province properties.
|
||||
ProvinceData provinceData = new ProvinceData();
|
||||
foreach (var propertyToken in provinceToken)
|
||||
{
|
||||
JProperty provinceProperty = propertyToken as JProperty;
|
||||
String propertyName = provinceProperty.Name;
|
||||
String propertyStringValue = StringUtil.TrimWhitespace(provinceProperty.Value.ToString());
|
||||
if (propertyName.EqualsCI("text"))
|
||||
provinceData.Name = propertyStringValue;
|
||||
else if (propertyName.EqualsCI("value"))
|
||||
provinceData.Code = propertyStringValue;
|
||||
else if (propertyName.EqualsCI("group")) { }
|
||||
else if (propertyName.EqualsCI("selected")) { }
|
||||
else if (propertyName.EqualsCI("disabled")) { }
|
||||
if (propertyToken is JProperty)
|
||||
{
|
||||
JProperty provinceProperty = propertyToken as JProperty;
|
||||
String propertyName = provinceProperty.Name;
|
||||
String propertyStringValue = StringUtil.TrimWhitespace(provinceProperty.Value.ToString());
|
||||
if (propertyName.EqualsCI("text"))
|
||||
provinceData.Name = propertyStringValue;
|
||||
else if (propertyName.EqualsCI("value"))
|
||||
provinceData.Code = propertyStringValue;
|
||||
else if (propertyName.EqualsCI("group")) { }
|
||||
else if (propertyName.EqualsCI("selected")) { }
|
||||
else if (propertyName.EqualsCI("disabled")) { }
|
||||
}
|
||||
}
|
||||
if (!StringUtil.IsBlank(provinceData.Code) && !provinceData.Code.EqualsCI("(Select)") && !StringUtil.IsBlank(provinceData.Name))
|
||||
usgaProvinces.Add(provinceData);
|
||||
}
|
||||
if (!StringUtil.IsBlank(provinceData.Code) && !provinceData.Code.EqualsCI("(Select)") && !StringUtil.IsBlank(provinceData.Name))
|
||||
usgaProvinces.Add(provinceData);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Store provinces.
|
||||
List<SaxReferenceGolfMgr.UsgaProvinceData> provincesData = new List<SaxReferenceGolfMgr.UsgaProvinceData>();
|
||||
foreach (ProvinceData usgaProvince in usgaProvinces)
|
||||
{
|
||||
SaxReferenceGolfMgr.UsgaProvinceData provinceData = new SaxReferenceGolfMgr.UsgaProvinceData();
|
||||
provinceData.CountryCode = countryCode;
|
||||
provinceData.ProvinceCode = usgaProvince.Code;
|
||||
provinceData.ProvinceName = usgaProvince.Name;
|
||||
provincesData.Add(provinceData);
|
||||
// Store provinces.
|
||||
List<SaxReferenceGolfMgr.UsgaProvinceData> provincesData = new List<SaxReferenceGolfMgr.UsgaProvinceData>();
|
||||
foreach (ProvinceData usgaProvince in usgaProvinces)
|
||||
{
|
||||
SaxReferenceGolfMgr.UsgaProvinceData provinceData = new SaxReferenceGolfMgr.UsgaProvinceData();
|
||||
provinceData.CountryCode = countryCode;
|
||||
provinceData.ProvinceCode = usgaProvince.Code;
|
||||
provinceData.ProvinceName = usgaProvince.Name;
|
||||
provincesData.Add(provinceData);
|
||||
}
|
||||
ReferenceGolfMgr.BulkUpdateUsgaProvinces(provincesData, DbUpdateInfo);
|
||||
if (!ReferenceGolfMgr.HasErrorState())
|
||||
{
|
||||
// Provinces updates OK.
|
||||
// Clear country 'priority' flag.
|
||||
usgaCountry.Priority = false;
|
||||
ReferenceGolfMgr.UpdateUsgaCountry(usgaCountry, DbUpdateInfo);
|
||||
}
|
||||
else SaLogger.Warn($"{SysUtil.Fn} Error bulk updating USGA provinces: {ReferenceGolfMgr.ErrorStateMessage}.");
|
||||
}
|
||||
catch (Exception exc)
|
||||
{
|
||||
SaLogger.Warn(SysUtil.Fn + " " + ExceptionUtil.GetLogMessage(exc, $"querying USGA provinces for {countryCode}", 0));
|
||||
}
|
||||
ReferenceGolfMgr.BulkUpdateUsgaProvinces(provincesData, config.DbUpdateInfo);
|
||||
if (ReferenceGolfMgr.HasErrorState())
|
||||
SaLogger.Warn($"{SysUtil.Fn} Error bulk updating USGA provinces: {ReferenceGolfMgr.ErrorStateMessage}.");
|
||||
}
|
||||
catch (Exception exc)
|
||||
{
|
||||
SaLogger.Warn(SysUtil.Fn + " " + ExceptionUtil.GetLogMessage(exc, $"querying USGA provinces for {countryCode}", 0));
|
||||
}
|
||||
return usgaProvinces;
|
||||
}
|
||||
@@ -394,179 +415,205 @@ namespace Saxonite.Net.Core.Web.Base.Procs
|
||||
|
||||
UsgaRequestData usgaRequestData = GetUsgaRequestData();
|
||||
|
||||
try
|
||||
using (DisposableCollection<SacsDisposable> disposableItems = new DisposableCollection<SacsDisposable>())
|
||||
{
|
||||
// Query countries on USGA website.
|
||||
CancellationToken cancelToken = new CancellationToken();
|
||||
SacsHttpRequestData request = new SacsHttpRequestData(cancelToken) { Url = "https://ncrdb.usga.org/NCRListing?handler=LoadCourses" };
|
||||
// Headers.
|
||||
request.RequestHeaders.Add(HeaderNames.Accept, "*/*");
|
||||
request.RequestHeaders.Add(HeaderNames.AcceptEncoding, "gzip, deflate, br, zstd");
|
||||
request.RequestHeaders.Add(HeaderNames.AcceptLanguage, "en-GB,en;q=0.9");
|
||||
request.RequestHeaders.Add(HeaderNames.DNT, "1");
|
||||
request.RequestHeaders.Add(HeaderNames.Origin, "https://ncrdb.usga.org/");
|
||||
request.RequestHeaders.Add("Priority", "u=1, i");
|
||||
request.RequestHeaders.Add(HeaderNames.Referer, "https://ncrdb.usga.org/");
|
||||
if (!StringUtil.IsBlank(usgaRequestData.RequestVerificationToken))
|
||||
request.RequestHeaders.Add("Requestverificationtoken", usgaRequestData.RequestVerificationToken);
|
||||
// Content.
|
||||
request.FormData.Add(new KeyValuePair<string, string>("clubName", ""));
|
||||
request.FormData.Add(new KeyValuePair<string, string>("clubCity", ""));
|
||||
request.FormData.Add(new KeyValuePair<string, string>("clubState", provinceCode));
|
||||
request.FormData.Add(new KeyValuePair<string, string>("clubCountry", countryCode));
|
||||
request.ContentHeaders.Add(HeaderNames.ContentType, "application/x-www-form-urlencoded; charset=UTF-8");
|
||||
// Request.
|
||||
SacsHttpResponseData response = SacsHttpClient.DoRequest(request).Result;
|
||||
String data = response.Data;
|
||||
|
||||
if (!StringUtil.IsBlank(response.Data))
|
||||
// Retrieve and validate country.
|
||||
SaxGolfUsgaCountry usgaCountry = ReferenceGolfMgr.GetUsgaCountry(new SaxGolfUsgaCountry.Params() { CountryCodeFull = countryCode });
|
||||
disposableItems.Add(usgaCountry);
|
||||
if (usgaCountry == null)
|
||||
{
|
||||
HashSet<String> UnrecognisedCourseProperties = new HashSet<string>(StringComparer.InvariantCultureIgnoreCase);
|
||||
dynamic coursesJson = SacsJsonHelper.DeserializeJsonObject(response.Data);
|
||||
if (coursesJson is JArray)
|
||||
SaLogger.Warn($"{SysUtil.Fn} USGA Country not found for code '{countryCode}'.");
|
||||
return usgaCourses;
|
||||
}
|
||||
// Retrieve and validate province.
|
||||
SaxGolfUsgaProvince usgaProvince = ReferenceGolfMgr.GetUsgaProvince(new SaxGolfUsgaProvince.Params() { ProvinceCodeFull = provinceCode });
|
||||
disposableItems.Add(usgaProvince);
|
||||
if (usgaProvince == null)
|
||||
{
|
||||
SaLogger.Warn($"{SysUtil.Fn} USGA Province not found for code '{provinceCode}'.");
|
||||
return usgaCourses;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
// Query Courses for Country & Province on USGA website.
|
||||
CancellationToken cancelToken = new CancellationToken();
|
||||
SacsHttpRequestData request = new SacsHttpRequestData(cancelToken) { Url = "https://ncrdb.usga.org/NCRListing?handler=LoadCourses" };
|
||||
// Headers.
|
||||
request.RequestHeaders.Add(HeaderNames.Accept, "*/*");
|
||||
request.RequestHeaders.Add(HeaderNames.AcceptEncoding, "gzip, deflate, br, zstd");
|
||||
request.RequestHeaders.Add(HeaderNames.AcceptLanguage, "en-GB,en;q=0.9");
|
||||
request.RequestHeaders.Add(HeaderNames.DNT, "1");
|
||||
request.RequestHeaders.Add(HeaderNames.Origin, "https://ncrdb.usga.org/");
|
||||
request.RequestHeaders.Add("Priority", "u=1, i");
|
||||
request.RequestHeaders.Add(HeaderNames.Referer, "https://ncrdb.usga.org/");
|
||||
if (!StringUtil.IsBlank(usgaRequestData.RequestVerificationToken))
|
||||
request.RequestHeaders.Add("Requestverificationtoken", usgaRequestData.RequestVerificationToken);
|
||||
// Content.
|
||||
request.FormData.Add(new KeyValuePair<string, string>("clubName", ""));
|
||||
request.FormData.Add(new KeyValuePair<string, string>("clubCity", ""));
|
||||
request.FormData.Add(new KeyValuePair<string, string>("clubState", provinceCode));
|
||||
request.FormData.Add(new KeyValuePair<string, string>("clubCountry", countryCode));
|
||||
request.ContentHeaders.Add(HeaderNames.ContentType, "application/x-www-form-urlencoded; charset=UTF-8");
|
||||
// Request.
|
||||
SacsHttpResponseData response = SacsHttpClient.DoRequest(request).Result;
|
||||
String data = response.Data;
|
||||
|
||||
if (!StringUtil.IsBlank(response.Data))
|
||||
{
|
||||
JArray coursesArray = coursesJson as JArray;
|
||||
foreach (var courseToken in coursesArray)
|
||||
HashSet<String> UnrecognisedCourseProperties = new HashSet<string>(StringComparer.InvariantCultureIgnoreCase);
|
||||
dynamic coursesJson = SacsJsonHelper.DeserializeJsonObject(response.Data);
|
||||
if (coursesJson is JArray)
|
||||
{
|
||||
// Course properties.
|
||||
CourseData courseData = new CourseData();
|
||||
foreach (var propertyToken in courseToken)
|
||||
JArray coursesArray = coursesJson as JArray;
|
||||
foreach (var courseToken in coursesArray)
|
||||
{
|
||||
if (propertyToken is JProperty)
|
||||
// Course properties.
|
||||
CourseData courseData = new CourseData();
|
||||
foreach (var propertyToken in courseToken)
|
||||
{
|
||||
JProperty courseProperty = propertyToken as JProperty;
|
||||
String propertyName = courseProperty.Name;
|
||||
String propertyStringValue = StringUtil.TrimWhitespace(courseProperty.Value.ToString());
|
||||
if (propertyName.EqualsCI("courseId"))
|
||||
courseData.CourseId = propertyStringValue;
|
||||
else if (propertyName.EqualsCI("legacyCRPCourseId"))
|
||||
courseData.LegacyCrpCourseId = propertyStringValue;
|
||||
else if (propertyName.EqualsCI("courseName"))
|
||||
courseData.CourseName = propertyStringValue;
|
||||
else if (propertyName.EqualsCI("facilityId"))
|
||||
courseData.FacilityId = propertyStringValue;
|
||||
else if (propertyName.EqualsCI("facilityName"))
|
||||
courseData.FacilityName = propertyStringValue;
|
||||
else if (propertyName.EqualsCI("fullName"))
|
||||
courseData.FullName = propertyStringValue;
|
||||
else if (propertyName.EqualsCI("address1"))
|
||||
courseData.Address1 = propertyStringValue;
|
||||
else if (propertyName.EqualsCI("address2"))
|
||||
courseData.Address2 = propertyStringValue;
|
||||
else if (propertyName.EqualsCI("city"))
|
||||
courseData.City = propertyStringValue;
|
||||
else if (propertyName.EqualsCI("entStateCode"))
|
||||
courseData.EntProvinceCode = propertyStringValue;
|
||||
else if (propertyName.EqualsCI("state"))
|
||||
courseData.ProvinceCode = propertyStringValue;
|
||||
else if (propertyName.EqualsCI("stateDisplay"))
|
||||
courseData.Province = propertyStringValue;
|
||||
else if (propertyName.EqualsCI("country"))
|
||||
courseData.CountryCode = propertyStringValue;
|
||||
else if (propertyName.EqualsCI("entCountryCode"))
|
||||
courseData.EntCountryCode = propertyStringValue;
|
||||
else if (propertyName.EqualsCI("email"))
|
||||
courseData.Email = propertyStringValue;
|
||||
else if (propertyName.EqualsCI("telephone"))
|
||||
courseData.Telephone = propertyStringValue;
|
||||
else if (propertyName.EqualsCI("ratings"))
|
||||
if (propertyToken is JProperty)
|
||||
{
|
||||
if (courseProperty.Value.Count() > 0)
|
||||
courseData.Ratings.Add("");
|
||||
JProperty courseProperty = propertyToken as JProperty;
|
||||
String propertyName = courseProperty.Name;
|
||||
String propertyStringValue = StringUtil.TrimWhitespace(courseProperty.Value.ToString());
|
||||
if (propertyName.EqualsCI("courseId"))
|
||||
courseData.CourseId = propertyStringValue;
|
||||
else if (propertyName.EqualsCI("legacyCRPCourseId"))
|
||||
courseData.LegacyCrpCourseId = propertyStringValue;
|
||||
else if (propertyName.EqualsCI("courseName"))
|
||||
courseData.CourseName = propertyStringValue;
|
||||
else if (propertyName.EqualsCI("facilityId"))
|
||||
courseData.FacilityId = propertyStringValue;
|
||||
else if (propertyName.EqualsCI("facilityName"))
|
||||
courseData.FacilityName = propertyStringValue;
|
||||
else if (propertyName.EqualsCI("fullName"))
|
||||
courseData.FullName = propertyStringValue;
|
||||
else if (propertyName.EqualsCI("address1"))
|
||||
courseData.Address1 = propertyStringValue;
|
||||
else if (propertyName.EqualsCI("address2"))
|
||||
courseData.Address2 = propertyStringValue;
|
||||
else if (propertyName.EqualsCI("city"))
|
||||
courseData.City = propertyStringValue;
|
||||
else if (propertyName.EqualsCI("entStateCode"))
|
||||
courseData.EntProvinceCode = propertyStringValue;
|
||||
else if (propertyName.EqualsCI("state"))
|
||||
courseData.ProvinceCode = propertyStringValue;
|
||||
else if (propertyName.EqualsCI("stateDisplay"))
|
||||
courseData.Province = propertyStringValue;
|
||||
else if (propertyName.EqualsCI("country"))
|
||||
courseData.CountryCode = propertyStringValue;
|
||||
else if (propertyName.EqualsCI("entCountryCode"))
|
||||
courseData.EntCountryCode = propertyStringValue;
|
||||
else if (propertyName.EqualsCI("email"))
|
||||
courseData.Email = propertyStringValue;
|
||||
else if (propertyName.EqualsCI("telephone"))
|
||||
courseData.Telephone = propertyStringValue;
|
||||
else if (propertyName.EqualsCI("ratings"))
|
||||
{
|
||||
if (courseProperty.Value.Count() > 0)
|
||||
courseData.Ratings.Add("");
|
||||
}
|
||||
else UnrecognisedCourseProperties.Add(propertyName);
|
||||
}
|
||||
else UnrecognisedCourseProperties.Add(propertyName);
|
||||
}
|
||||
if (!StringUtil.IsBlank(courseData.CourseId) && !StringUtil.IsBlank(courseData.CourseName))
|
||||
{
|
||||
// Populate caption and add to list.
|
||||
SetCourseCaption(courseData);
|
||||
usgaCourses.Add(courseData);
|
||||
}
|
||||
}
|
||||
if (!StringUtil.IsBlank(courseData.CourseId) && !StringUtil.IsBlank(courseData.CourseName))
|
||||
{
|
||||
// Populate caption and add to list.
|
||||
SetCourseCaption(courseData);
|
||||
usgaCourses.Add(courseData);
|
||||
}
|
||||
}
|
||||
if (UnrecognisedCourseProperties.Any())
|
||||
SaLogger.Warn(SysUtil.Fn + " Unrecognised USGA course properties: " + String.Join(", ", UnrecognisedCourseProperties));
|
||||
}
|
||||
if (UnrecognisedCourseProperties.Any())
|
||||
SaLogger.Warn(SysUtil.Fn + " Unrecognised USGA course properties: " + String.Join(", ", UnrecognisedCourseProperties));
|
||||
}
|
||||
|
||||
// Store countries.
|
||||
Dictionary<String, SaxReferenceGolfMgr.UsgaCountryData> countriesData = new Dictionary<String, SaxReferenceGolfMgr.UsgaCountryData>();
|
||||
foreach (CourseData usgaCourse in usgaCourses)
|
||||
{
|
||||
SaxReferenceGolfMgr.UsgaCountryData countryData = new SaxReferenceGolfMgr.UsgaCountryData();
|
||||
countryData.CountryCode = usgaCourse.CountryCode;
|
||||
countryData.EntCountryCode = usgaCourse.EntCountryCode;
|
||||
countriesData[countryData.CountryCode] = countryData;
|
||||
}
|
||||
ReferenceGolfMgr.BulkUpdateUsgaCountries(countriesData.Values.ToList(), config.DbUpdateInfo);
|
||||
if (ReferenceGolfMgr.HasErrorState())
|
||||
SaLogger.Warn($"{SysUtil.Fn} Error bulk updating USGA countries: {ReferenceGolfMgr.ErrorStateMessage}.");
|
||||
|
||||
// Store provinces.
|
||||
Dictionary<String, SaxReferenceGolfMgr.UsgaProvinceData> provincesData = new Dictionary<String, SaxReferenceGolfMgr.UsgaProvinceData>();
|
||||
foreach (CourseData usgaCourse in usgaCourses)
|
||||
{
|
||||
SaxReferenceGolfMgr.UsgaProvinceData provinceData = new SaxReferenceGolfMgr.UsgaProvinceData();
|
||||
provinceData.CountryCode = usgaCourse.CountryCode;
|
||||
provinceData.ProvinceCode = usgaCourse.ProvinceCode;
|
||||
provinceData.EntProvinceCode = usgaCourse.EntProvinceCode;
|
||||
provincesData[provinceData.ProvinceCode] = provinceData;
|
||||
}
|
||||
ReferenceGolfMgr.BulkUpdateUsgaProvinces(provincesData.Values.ToList(), config.DbUpdateInfo);
|
||||
if (ReferenceGolfMgr.HasErrorState())
|
||||
SaLogger.Warn($"{SysUtil.Fn} Error bulk updating USGA provinces: {ReferenceGolfMgr.ErrorStateMessage}.");
|
||||
|
||||
// Store facilities.
|
||||
Dictionary<SysId, SaxReferenceGolfMgr.UsgaFacilityData> facilitiesData = new Dictionary<SysId, SaxReferenceGolfMgr.UsgaFacilityData>();
|
||||
foreach (CourseData usgaCourse in usgaCourses)
|
||||
{
|
||||
if (StringUtil.IsBlank(usgaCourse.FacilityId)) continue;
|
||||
SaxReferenceGolfMgr.UsgaFacilityData facilityData = new SaxReferenceGolfMgr.UsgaFacilityData();
|
||||
facilityData.ProvinceCode = provinceCode;
|
||||
facilityData.FacilityId = StringUtil.ToSysId(usgaCourse.FacilityId);
|
||||
facilityData.FacilityName = usgaCourse.FacilityName;
|
||||
if (!SysId.IsValid(facilityData.FacilityId))
|
||||
// Store countries.
|
||||
Dictionary<String, SaxReferenceGolfMgr.UsgaCountryData> countriesData = new Dictionary<String, SaxReferenceGolfMgr.UsgaCountryData>();
|
||||
foreach (CourseData usgaCourse in usgaCourses)
|
||||
{
|
||||
SaLogger.Warn($"{SysUtil.Fn} Invalid Facility Id for {usgaCourse.CourseName}: {usgaCourse.FacilityId}.");
|
||||
continue;
|
||||
SaxReferenceGolfMgr.UsgaCountryData countryData = new SaxReferenceGolfMgr.UsgaCountryData();
|
||||
countryData.CountryCode = usgaCourse.CountryCode;
|
||||
countryData.EntCountryCode = usgaCourse.EntCountryCode;
|
||||
countriesData[countryData.CountryCode] = countryData;
|
||||
}
|
||||
facilitiesData[facilityData.FacilityId] = facilityData;
|
||||
}
|
||||
ReferenceGolfMgr.BulkUpdateUsgaFacilities(facilitiesData.Values.ToList(), config.DbUpdateInfo);
|
||||
if (ReferenceGolfMgr.HasErrorState())
|
||||
SaLogger.Warn($"{SysUtil.Fn} Error bulk updating USGA facilities: {ReferenceGolfMgr.ErrorStateMessage}.");
|
||||
ReferenceGolfMgr.BulkUpdateUsgaCountries(countriesData.Values.ToList(), DbUpdateInfo);
|
||||
if (ReferenceGolfMgr.HasErrorState())
|
||||
SaLogger.Warn($"{SysUtil.Fn} Error bulk updating USGA countries: {ReferenceGolfMgr.ErrorStateMessage}.");
|
||||
|
||||
// Store courses.
|
||||
Dictionary<SysId, SaxReferenceGolfMgr.UsgaCourseData> coursesData = new Dictionary<SysId, SaxReferenceGolfMgr.UsgaCourseData>();
|
||||
foreach (CourseData usgaCourse in usgaCourses)
|
||||
{
|
||||
if (StringUtil.IsBlank(usgaCourse.CourseId)) continue;
|
||||
SaxReferenceGolfMgr.UsgaCourseData courseData = new SaxReferenceGolfMgr.UsgaCourseData();
|
||||
courseData.FacilityId = StringUtil.ToSysId(usgaCourse.FacilityId);
|
||||
courseData.CourseId = StringUtil.ToSysId(usgaCourse.CourseId);
|
||||
courseData.LegacyCrpCourseId = StringUtil.ToSysId(usgaCourse.LegacyCrpCourseId);
|
||||
courseData.Caption = usgaCourse.Caption;
|
||||
courseData.CourseName = usgaCourse.CourseName;
|
||||
courseData.FullName = usgaCourse.FullName;
|
||||
courseData.Address1 = usgaCourse.Address1;
|
||||
courseData.Address2 = usgaCourse.Address2;
|
||||
courseData.City = usgaCourse.City;
|
||||
courseData.Email = usgaCourse.Email;
|
||||
courseData.Telephone = usgaCourse.Telephone;
|
||||
if (!SysId.IsValid(courseData.CourseId))
|
||||
// Store provinces.
|
||||
Dictionary<String, SaxReferenceGolfMgr.UsgaProvinceData> provincesData = new Dictionary<String, SaxReferenceGolfMgr.UsgaProvinceData>();
|
||||
foreach (CourseData usgaCourse in usgaCourses)
|
||||
{
|
||||
SaLogger.Warn($"{SysUtil.Fn} Invalid Course Id for {usgaCourse.CourseName}: {usgaCourse.CourseId}.");
|
||||
continue;
|
||||
SaxReferenceGolfMgr.UsgaProvinceData provinceData = new SaxReferenceGolfMgr.UsgaProvinceData();
|
||||
provinceData.CountryCode = usgaCourse.CountryCode;
|
||||
provinceData.ProvinceCode = usgaCourse.ProvinceCode;
|
||||
provinceData.EntProvinceCode = usgaCourse.EntProvinceCode;
|
||||
provincesData[provinceData.ProvinceCode] = provinceData;
|
||||
}
|
||||
coursesData[courseData.CourseId] = courseData;
|
||||
ReferenceGolfMgr.BulkUpdateUsgaProvinces(provincesData.Values.ToList(), DbUpdateInfo);
|
||||
if (ReferenceGolfMgr.HasErrorState())
|
||||
SaLogger.Warn($"{SysUtil.Fn} Error bulk updating USGA provinces: {ReferenceGolfMgr.ErrorStateMessage}.");
|
||||
|
||||
// Store facilities.
|
||||
Dictionary<SysId, SaxReferenceGolfMgr.UsgaFacilityData> facilitiesData = new Dictionary<SysId, SaxReferenceGolfMgr.UsgaFacilityData>();
|
||||
foreach (CourseData usgaCourse in usgaCourses)
|
||||
{
|
||||
if (StringUtil.IsBlank(usgaCourse.FacilityId)) continue;
|
||||
SaxReferenceGolfMgr.UsgaFacilityData facilityData = new SaxReferenceGolfMgr.UsgaFacilityData();
|
||||
facilityData.ProvinceCode = provinceCode;
|
||||
facilityData.FacilityId = StringUtil.ToSysId(usgaCourse.FacilityId);
|
||||
facilityData.FacilityName = usgaCourse.FacilityName;
|
||||
if (!SysId.IsValid(facilityData.FacilityId))
|
||||
{
|
||||
SaLogger.Warn($"{SysUtil.Fn} Invalid Facility Id for {usgaCourse.CourseName}: {usgaCourse.FacilityId}.");
|
||||
continue;
|
||||
}
|
||||
facilitiesData[facilityData.FacilityId] = facilityData;
|
||||
}
|
||||
ReferenceGolfMgr.BulkUpdateUsgaFacilities(facilitiesData.Values.ToList(), DbUpdateInfo);
|
||||
if (ReferenceGolfMgr.HasErrorState())
|
||||
SaLogger.Warn($"{SysUtil.Fn} Error bulk updating USGA facilities: {ReferenceGolfMgr.ErrorStateMessage}.");
|
||||
|
||||
// Store courses.
|
||||
Dictionary<SysId, SaxReferenceGolfMgr.UsgaCourseData> coursesData = new Dictionary<SysId, SaxReferenceGolfMgr.UsgaCourseData>();
|
||||
foreach (CourseData usgaCourse in usgaCourses)
|
||||
{
|
||||
if (StringUtil.IsBlank(usgaCourse.CourseId)) continue;
|
||||
SaxReferenceGolfMgr.UsgaCourseData courseData = new SaxReferenceGolfMgr.UsgaCourseData();
|
||||
courseData.FacilityId = StringUtil.ToSysId(usgaCourse.FacilityId);
|
||||
courseData.CourseId = StringUtil.ToSysId(usgaCourse.CourseId);
|
||||
courseData.LegacyCrpCourseId = StringUtil.ToSysId(usgaCourse.LegacyCrpCourseId);
|
||||
courseData.Caption = usgaCourse.Caption;
|
||||
courseData.CourseName = usgaCourse.CourseName;
|
||||
courseData.FullName = usgaCourse.FullName;
|
||||
courseData.Address1 = usgaCourse.Address1;
|
||||
courseData.Address2 = usgaCourse.Address2;
|
||||
courseData.City = usgaCourse.City;
|
||||
courseData.Email = usgaCourse.Email;
|
||||
courseData.Telephone = usgaCourse.Telephone;
|
||||
if (!SysId.IsValid(courseData.CourseId))
|
||||
{
|
||||
SaLogger.Warn($"{SysUtil.Fn} Invalid Course Id for {usgaCourse.CourseName}: {usgaCourse.CourseId}.");
|
||||
continue;
|
||||
}
|
||||
coursesData[courseData.CourseId] = courseData;
|
||||
}
|
||||
ReferenceGolfMgr.BulkUpdateUsgaCourses(coursesData.Values.ToList(), DbUpdateInfo);
|
||||
if (!ReferenceGolfMgr.HasErrorState())
|
||||
{
|
||||
// Courses updates OK.
|
||||
// Clear province 'priority' flag.
|
||||
usgaProvince.Priority = false;
|
||||
ReferenceGolfMgr.UpdateUsgaProvince(usgaProvince, DbUpdateInfo);
|
||||
}
|
||||
else SaLogger.Warn($"{SysUtil.Fn} Error bulk updating USGA courses: {ReferenceGolfMgr.ErrorStateMessage}.");
|
||||
}
|
||||
catch (Exception exc)
|
||||
{
|
||||
SaLogger.Warn(SysUtil.Fn + " " + ExceptionUtil.GetLogMessage(exc, $"querying USGA courses for {countryCode}", 0));
|
||||
}
|
||||
ReferenceGolfMgr.BulkUpdateUsgaCourses(coursesData.Values.ToList(), config.DbUpdateInfo);
|
||||
if (ReferenceGolfMgr.HasErrorState())
|
||||
SaLogger.Warn($"{SysUtil.Fn} Error bulk updating USGA courses: {ReferenceGolfMgr.ErrorStateMessage}.");
|
||||
}
|
||||
catch (Exception exc)
|
||||
{
|
||||
SaLogger.Warn(SysUtil.Fn + " " + ExceptionUtil.GetLogMessage(exc, $"querying USGA courses for {countryCode}", 0));
|
||||
}
|
||||
return usgaCourses;
|
||||
}
|
||||
@@ -649,196 +696,240 @@ namespace Saxonite.Net.Core.Web.Base.Procs
|
||||
public int ColIdx_Length { get; set; } = -1;
|
||||
}
|
||||
/// <summary>
|
||||
/// Class to allow markers list to be serialised as 'Markers'.
|
||||
/// </summary>
|
||||
private class MarkersData
|
||||
{
|
||||
public List<MarkerData> Markers { get; } = new List<MarkerData>();
|
||||
}
|
||||
/// <summary>
|
||||
/// USGA Markers for course.
|
||||
/// </summary>
|
||||
public List<MarkerData> LookupUsgaMarkersForCourse(SysId usgaCourseId)
|
||||
{
|
||||
List<MarkerData> usgaMarkers = new List<MarkerData>();
|
||||
if (!SysId.IsValid(usgaCourseId)) return usgaMarkers;
|
||||
MarkersData markersData = new MarkersData();
|
||||
if (!SysId.IsValid(usgaCourseId)) return markersData.Markers;
|
||||
MarkerColumnData markerColumns = new MarkerColumnData();
|
||||
|
||||
try
|
||||
using (DisposableCollection<SacsDisposable> disposableItems = new DisposableCollection<SacsDisposable>())
|
||||
{
|
||||
// Query countries on USGA website.
|
||||
CancellationToken cancelToken = new CancellationToken();
|
||||
SacsHttpRequestData request = new SacsHttpRequestData(cancelToken) { Url = $"https://ncrdb.usga.org/courseTeeInfo?CourseID={usgaCourseId}" };
|
||||
SacsHttpResponseData response = SacsHttpClient.DoRequest(request).Result;
|
||||
String data = response.Data;
|
||||
|
||||
if (!StringUtil.IsBlank(response.Data))
|
||||
// Retrieve and validate course.
|
||||
SaxGolfUsgaCourse.Params prmCourse = new SaxGolfUsgaCourse.Params();
|
||||
prmCourse.CourseIdsIncluded.Add(usgaCourseId);
|
||||
SaxGolfUsgaCourse usgaCourse = ReferenceGolfMgr.GetUsgaCourse(prmCourse);
|
||||
disposableItems.Add(usgaCourse);
|
||||
if (usgaCourse == null)
|
||||
{
|
||||
// Parse HTML.
|
||||
HtmlDocument htmlDoc = new HtmlDocument();
|
||||
htmlDoc.LoadHtml(response.Data);
|
||||
SaLogger.Warn($"{SysUtil.Fn} USGA Course not found for Id '{usgaCourseId}'.");
|
||||
return markersData.Markers;
|
||||
}
|
||||
|
||||
// Locate countries list.
|
||||
HtmlNode teeTableNode = htmlDoc.GetElementbyId("gvTee");
|
||||
if (teeTableNode != null)
|
||||
try
|
||||
{
|
||||
// Query course markers on USGA website.
|
||||
CancellationToken cancelToken = new CancellationToken();
|
||||
SacsHttpRequestData request = new SacsHttpRequestData(cancelToken) { Url = $"https://ncrdb.usga.org/courseTeeInfo?CourseID={usgaCourseId}" };
|
||||
SacsHttpResponseData response = SacsHttpClient.DoRequest(request).Result;
|
||||
String data = response.Data;
|
||||
|
||||
if (!StringUtil.IsBlank(response.Data))
|
||||
{
|
||||
// Identify marker columns.
|
||||
int teeColumnIdx = -1;
|
||||
foreach (HtmlNode teeHeaderNode in teeTableNode.SelectNodes("./tr[1]/th"))
|
||||
// Parse HTML.
|
||||
HtmlDocument htmlDoc = new HtmlDocument();
|
||||
htmlDoc.LoadHtml(response.Data);
|
||||
|
||||
// Locate countries list.
|
||||
HtmlNode teeTableNode = htmlDoc.GetElementbyId("gvTee");
|
||||
if (teeTableNode != null)
|
||||
{
|
||||
teeColumnIdx++;
|
||||
String headerText = StringUtil.TrimWhitespace(WebUtil.HtmlDecode(teeHeaderNode.InnerText));
|
||||
if (StringUtil.IsBlank(headerText) || headerText.EqualsCI("CH"))
|
||||
{
|
||||
// Columns ignored.
|
||||
}
|
||||
else if (headerText.EqualsCI("Tee Name")) markerColumns.ColIdx_Tee = teeColumnIdx;
|
||||
else if (headerText.EqualsCI("Gender")) markerColumns.ColIdx_Gender = teeColumnIdx;
|
||||
else if (headerText.EqualsCI("Par")) markerColumns.ColIdx_Par = teeColumnIdx;
|
||||
else if (headerText.EqualsCI("TeeId")) markerColumns.ColIdx_MarkerId = teeColumnIdx;
|
||||
else if (headerText.EqualsCI("Length")) markerColumns.ColIdx_Length = teeColumnIdx;
|
||||
// Specific part-course (9 holes) values.
|
||||
else if (headerText.EqualsCI("RatingF9")) markerColumns.ColIdx_Front9CourseRating = teeColumnIdx;
|
||||
else if (headerText.EqualsCI("RatingB9")) markerColumns.ColIdx_Back9CourseRating = teeColumnIdx;
|
||||
else if (headerText.EqualsCI("Front (9)")) markerColumns.ColIdx_Front9 = teeColumnIdx;
|
||||
else if (headerText.EqualsCI("Back (9)")) markerColumns.ColIdx_Back9 = teeColumnIdx;
|
||||
else if (headerText.EqualsCI("Bogey Rating (F9)")) markerColumns.ColIdx_Front9BogeyRating = teeColumnIdx;
|
||||
else if (headerText.EqualsCI("Bogey Rating (B9)")) markerColumns.ColIdx_Back9BogeyRating = teeColumnIdx;
|
||||
else if (headerText.EqualsCI("Slope (F9)")) markerColumns.ColIdx_Front9SlopeRating = teeColumnIdx;
|
||||
else if (headerText.EqualsCI("Slope (B9)")) markerColumns.ColIdx_Back9SlopeRating = teeColumnIdx;
|
||||
// Less specific full-course (commonly 18 holes) values.
|
||||
else if (headerText.IsMatchCI("Course Rating")) markerColumns.ColIdx_CourseRating = teeColumnIdx;
|
||||
else if (headerText.IsMatchCI("Bogey Rating")) markerColumns.ColIdx_BogeyRating = teeColumnIdx;
|
||||
else if (headerText.IsMatchCI("Slope Rating")) markerColumns.ColIdx_SlopeRating = teeColumnIdx;
|
||||
else SaLogger.Info($"{SysUtil.Fn} Unexpected Marker column header: {headerText}");
|
||||
}
|
||||
foreach (HtmlNode teeRowNode in teeTableNode.SelectNodes("./tr[position()>1]"))
|
||||
{
|
||||
MarkerData markerData18 = new MarkerData(usgaCourseId, 18, "18");
|
||||
MarkerData markerDataF9 = new MarkerData(usgaCourseId, 9, "F9");
|
||||
MarkerData markerDataB9 = new MarkerData(usgaCourseId, 9, "B9");
|
||||
teeColumnIdx = -1;
|
||||
foreach (HtmlNode teePropertyNode in teeRowNode.SelectNodes("./td"))
|
||||
// Identify marker columns.
|
||||
int teeColumnIdx = -1;
|
||||
foreach (HtmlNode teeHeaderNode in teeTableNode.SelectNodes("./tr[1]/th"))
|
||||
{
|
||||
teeColumnIdx++;
|
||||
String propertyText = StringUtil.TrimWhitespace(WebUtil.HtmlDecode(teePropertyNode.InnerText));
|
||||
if (markerColumns.ColIdx_Tee == teeColumnIdx)
|
||||
String headerText = StringUtil.TrimWhitespace(WebUtil.HtmlDecode(teeHeaderNode.InnerText));
|
||||
if (StringUtil.IsBlank(headerText) || headerText.EqualsCI("CH"))
|
||||
{
|
||||
markerData18.Tee = propertyText;
|
||||
markerDataF9.Tee = propertyText;
|
||||
markerDataB9.Tee = propertyText;
|
||||
}
|
||||
else if (markerColumns.ColIdx_Gender == teeColumnIdx)
|
||||
{
|
||||
markerData18.Gender = propertyText;
|
||||
markerDataF9.Gender = propertyText;
|
||||
markerDataB9.Gender = propertyText;
|
||||
}
|
||||
else if (markerColumns.ColIdx_Par == teeColumnIdx)
|
||||
{
|
||||
markerData18.Par = StringUtil.ToShort(propertyText);
|
||||
}
|
||||
else if (markerColumns.ColIdx_CourseRating == teeColumnIdx)
|
||||
{
|
||||
markerData18.CourseRating = StringUtil.ToDecimal(propertyText);
|
||||
}
|
||||
else if (markerColumns.ColIdx_BogeyRating == teeColumnIdx)
|
||||
{
|
||||
markerData18.BogeyRating = StringUtil.ToDecimal(propertyText);
|
||||
}
|
||||
else if (markerColumns.ColIdx_SlopeRating == teeColumnIdx)
|
||||
{
|
||||
markerData18.SlopeRating = StringUtil.ToShort(propertyText);
|
||||
}
|
||||
else if (markerColumns.ColIdx_Front9CourseRating == teeColumnIdx)
|
||||
{
|
||||
if (markerDataF9.CourseRating == 0)
|
||||
markerDataF9.CourseRating = StringUtil.ToDecimal(propertyText);
|
||||
}
|
||||
else if (markerColumns.ColIdx_Back9CourseRating == teeColumnIdx)
|
||||
{
|
||||
if (markerDataB9.CourseRating == 0)
|
||||
markerDataB9.CourseRating = StringUtil.ToDecimal(propertyText);
|
||||
}
|
||||
else if (markerColumns.ColIdx_Front9 == teeColumnIdx)
|
||||
{
|
||||
// Format: CourseRating / SlopeRating.
|
||||
markerDataF9.CourseRating = StringUtil.ToDecimal(Regex.Replace(propertyText, "\\s*/.*$", ""));
|
||||
markerDataF9.SlopeRating = StringUtil.ToShort(Regex.Replace(propertyText, "^.*/\\s*", ""));
|
||||
}
|
||||
else if (markerColumns.ColIdx_Back9 == teeColumnIdx)
|
||||
{
|
||||
// Format: CourseRating / SlopeRating.
|
||||
markerDataB9.CourseRating = StringUtil.ToDecimal(Regex.Replace(propertyText, "\\s*/.*$", ""));
|
||||
markerDataB9.SlopeRating = StringUtil.ToShort(Regex.Replace(propertyText, "^.*/\\s*", ""));
|
||||
}
|
||||
else if (markerColumns.ColIdx_Front9BogeyRating == teeColumnIdx)
|
||||
{
|
||||
markerDataF9.BogeyRating = StringUtil.ToDecimal(propertyText);
|
||||
}
|
||||
else if (markerColumns.ColIdx_Back9BogeyRating == teeColumnIdx)
|
||||
{
|
||||
markerDataB9.BogeyRating = StringUtil.ToDecimal(propertyText);
|
||||
}
|
||||
else if (markerColumns.ColIdx_Front9SlopeRating == teeColumnIdx)
|
||||
{
|
||||
if (markerDataF9.SlopeRating == 0)
|
||||
markerDataF9.SlopeRating = StringUtil.ToShort(propertyText);
|
||||
}
|
||||
else if (markerColumns.ColIdx_Back9SlopeRating == teeColumnIdx)
|
||||
{
|
||||
// Back 9 Slope Rating populated with value for Front 9.
|
||||
//markerDataB9.SlopeRating = StringUtil.ToInt(propertyText);
|
||||
}
|
||||
else if (markerColumns.ColIdx_MarkerId == teeColumnIdx)
|
||||
{
|
||||
markerData18.MarkerId = StringUtil.ToSysId(propertyText);
|
||||
// Unclear if Tee Id is relevant to 9 holes.
|
||||
//markerDataF9.MarkerId = StringUtil.ToSysId(propertyText);
|
||||
//markerDataB9.MarkerId = StringUtil.ToSysId(propertyText);
|
||||
}
|
||||
else if (markerColumns.ColIdx_Length == teeColumnIdx)
|
||||
{
|
||||
markerData18.Length = StringUtil.ToShort(propertyText);
|
||||
// Columns ignored.
|
||||
}
|
||||
else if (headerText.EqualsCI("Tee Name")) markerColumns.ColIdx_Tee = teeColumnIdx;
|
||||
else if (headerText.EqualsCI("Gender")) markerColumns.ColIdx_Gender = teeColumnIdx;
|
||||
else if (headerText.EqualsCI("Par")) markerColumns.ColIdx_Par = teeColumnIdx;
|
||||
else if (headerText.EqualsCI("TeeId")) markerColumns.ColIdx_MarkerId = teeColumnIdx;
|
||||
else if (headerText.EqualsCI("Length")) markerColumns.ColIdx_Length = teeColumnIdx;
|
||||
// Specific part-course (9 holes) values.
|
||||
else if (headerText.EqualsCI("RatingF9")) markerColumns.ColIdx_Front9CourseRating = teeColumnIdx;
|
||||
else if (headerText.EqualsCI("RatingB9")) markerColumns.ColIdx_Back9CourseRating = teeColumnIdx;
|
||||
else if (headerText.EqualsCI("Front (9)")) markerColumns.ColIdx_Front9 = teeColumnIdx;
|
||||
else if (headerText.EqualsCI("Back (9)")) markerColumns.ColIdx_Back9 = teeColumnIdx;
|
||||
else if (headerText.EqualsCI("Bogey Rating (F9)")) markerColumns.ColIdx_Front9BogeyRating = teeColumnIdx;
|
||||
else if (headerText.EqualsCI("Bogey Rating (B9)")) markerColumns.ColIdx_Back9BogeyRating = teeColumnIdx;
|
||||
else if (headerText.EqualsCI("Slope (F9)")) markerColumns.ColIdx_Front9SlopeRating = teeColumnIdx;
|
||||
else if (headerText.EqualsCI("Slope (B9)")) markerColumns.ColIdx_Back9SlopeRating = teeColumnIdx;
|
||||
// Less specific full-course (commonly 18 holes) values.
|
||||
else if (headerText.IsMatchCI("Course Rating")) markerColumns.ColIdx_CourseRating = teeColumnIdx;
|
||||
else if (headerText.IsMatchCI("Bogey Rating")) markerColumns.ColIdx_BogeyRating = teeColumnIdx;
|
||||
else if (headerText.IsMatchCI("Slope Rating")) markerColumns.ColIdx_SlopeRating = teeColumnIdx;
|
||||
else SaLogger.Info($"{SysUtil.Fn} Unexpected Marker column header: {headerText}");
|
||||
}
|
||||
foreach (HtmlNode teeRowNode in teeTableNode.SelectNodes("./tr[position()>1]"))
|
||||
{
|
||||
MarkerData markerData18 = new MarkerData(usgaCourseId, 18, "18");
|
||||
MarkerData markerDataF9 = new MarkerData(usgaCourseId, 9, "F9");
|
||||
MarkerData markerDataB9 = new MarkerData(usgaCourseId, 9, "B9");
|
||||
teeColumnIdx = -1;
|
||||
foreach (HtmlNode teePropertyNode in teeRowNode.SelectNodes("./td"))
|
||||
{
|
||||
teeColumnIdx++;
|
||||
String propertyText = StringUtil.TrimWhitespace(WebUtil.HtmlDecode(teePropertyNode.InnerText));
|
||||
if (markerColumns.ColIdx_Tee == teeColumnIdx)
|
||||
{
|
||||
markerData18.Tee = propertyText;
|
||||
markerDataF9.Tee = propertyText;
|
||||
markerDataB9.Tee = propertyText;
|
||||
}
|
||||
else if (markerColumns.ColIdx_Gender == teeColumnIdx)
|
||||
{
|
||||
markerData18.Gender = propertyText;
|
||||
markerDataF9.Gender = propertyText;
|
||||
markerDataB9.Gender = propertyText;
|
||||
}
|
||||
else if (markerColumns.ColIdx_Par == teeColumnIdx)
|
||||
{
|
||||
markerData18.Par = StringUtil.ToShort(propertyText);
|
||||
if (markerData18.Par <= 50)
|
||||
{
|
||||
markerData18.Holes = 9;
|
||||
markerData18.HolesCaption = "9";
|
||||
}
|
||||
}
|
||||
else if (markerColumns.ColIdx_CourseRating == teeColumnIdx)
|
||||
{
|
||||
markerData18.CourseRating = StringUtil.ToDecimal(propertyText);
|
||||
}
|
||||
else if (markerColumns.ColIdx_BogeyRating == teeColumnIdx)
|
||||
{
|
||||
markerData18.BogeyRating = StringUtil.ToDecimal(propertyText);
|
||||
}
|
||||
else if (markerColumns.ColIdx_SlopeRating == teeColumnIdx)
|
||||
{
|
||||
markerData18.SlopeRating = StringUtil.ToShort(propertyText);
|
||||
}
|
||||
else if (markerColumns.ColIdx_Front9CourseRating == teeColumnIdx)
|
||||
{
|
||||
if (markerDataF9.CourseRating == 0)
|
||||
markerDataF9.CourseRating = StringUtil.ToDecimal(propertyText);
|
||||
}
|
||||
else if (markerColumns.ColIdx_Back9CourseRating == teeColumnIdx)
|
||||
{
|
||||
if (markerDataB9.CourseRating == 0)
|
||||
markerDataB9.CourseRating = StringUtil.ToDecimal(propertyText);
|
||||
}
|
||||
else if (markerColumns.ColIdx_Front9 == teeColumnIdx)
|
||||
{
|
||||
// Format: CourseRating / SlopeRating.
|
||||
markerDataF9.CourseRating = StringUtil.ToDecimal(Regex.Replace(propertyText, "\\s*/.*$", ""));
|
||||
markerDataF9.SlopeRating = StringUtil.ToShort(Regex.Replace(propertyText, "^.*/\\s*", ""));
|
||||
}
|
||||
else if (markerColumns.ColIdx_Back9 == teeColumnIdx)
|
||||
{
|
||||
// Format: CourseRating / SlopeRating.
|
||||
markerDataB9.CourseRating = StringUtil.ToDecimal(Regex.Replace(propertyText, "\\s*/.*$", ""));
|
||||
markerDataB9.SlopeRating = StringUtil.ToShort(Regex.Replace(propertyText, "^.*/\\s*", ""));
|
||||
}
|
||||
else if (markerColumns.ColIdx_Front9BogeyRating == teeColumnIdx)
|
||||
{
|
||||
markerDataF9.BogeyRating = StringUtil.ToDecimal(propertyText);
|
||||
}
|
||||
else if (markerColumns.ColIdx_Back9BogeyRating == teeColumnIdx)
|
||||
{
|
||||
markerDataB9.BogeyRating = StringUtil.ToDecimal(propertyText);
|
||||
}
|
||||
else if (markerColumns.ColIdx_Front9SlopeRating == teeColumnIdx)
|
||||
{
|
||||
if (markerDataF9.SlopeRating == 0)
|
||||
markerDataF9.SlopeRating = StringUtil.ToShort(propertyText);
|
||||
}
|
||||
else if (markerColumns.ColIdx_Back9SlopeRating == teeColumnIdx)
|
||||
{
|
||||
// Back 9 Slope Rating populated with value for Front 9.
|
||||
//markerDataB9.SlopeRating = StringUtil.ToInt(propertyText);
|
||||
}
|
||||
else if (markerColumns.ColIdx_MarkerId == teeColumnIdx)
|
||||
{
|
||||
markerData18.MarkerId = StringUtil.ToSysId(propertyText);
|
||||
// Unclear if Tee Id is relevant to 9 holes.
|
||||
//markerDataF9.MarkerId = StringUtil.ToSysId(propertyText);
|
||||
//markerDataB9.MarkerId = StringUtil.ToSysId(propertyText);
|
||||
}
|
||||
else if (markerColumns.ColIdx_Length == teeColumnIdx)
|
||||
{
|
||||
markerData18.Length = StringUtil.ToShort(propertyText);
|
||||
}
|
||||
}
|
||||
|
||||
// Add valid markers to list.
|
||||
if (markerData18.IsValid())
|
||||
usgaMarkers.Add(markerData18);
|
||||
if (markerDataF9.IsValid())
|
||||
usgaMarkers.Add(markerDataF9);
|
||||
if (markerDataB9.IsValid())
|
||||
usgaMarkers.Add(markerDataB9);
|
||||
// Front and Back 9 likely missing par values - derive from course ratings.
|
||||
if (markerData18.IsValid() && markerDataF9.IsValid(true) && markerDataF9.Par == 0 && markerDataB9.IsValid(true) && markerDataB9.Par == 0)
|
||||
{
|
||||
decimal combined9sCourseRating = markerDataF9.CourseRating + markerDataB9.CourseRating;
|
||||
markerDataF9.Par = (short)Math.Round(markerData18.Par * markerDataF9.CourseRating / combined9sCourseRating);
|
||||
markerDataB9.Par = (short)(markerData18.Par - markerDataF9.Par);
|
||||
}
|
||||
|
||||
// Add valid markers to list.
|
||||
if (markerData18.IsValid())
|
||||
markersData.Markers.Add(markerData18);
|
||||
if (markerDataF9.IsValid())
|
||||
markersData.Markers.Add(markerDataF9);
|
||||
if (markerDataB9.IsValid())
|
||||
markersData.Markers.Add(markerDataB9);
|
||||
}
|
||||
}
|
||||
else SaLogger.Warn(SysUtil.Fn + " Tee table not found.");
|
||||
}
|
||||
|
||||
// Store markers.
|
||||
List<SaxReferenceGolfMgr.UsgaMarkerData> markersUpdateData = new List<SaxReferenceGolfMgr.UsgaMarkerData>();
|
||||
foreach (MarkerData usgaMarker in markersData.Markers)
|
||||
{
|
||||
if (!SysId.IsValid(usgaMarker.CourseId)) continue;
|
||||
//if (!SysId.IsValid(usgaMarker.MarkerId)) continue;
|
||||
if (StringUtil.IsBlank(usgaMarker.Caption)) continue;
|
||||
SaxReferenceGolfMgr.UsgaMarkerData markerData = new SaxReferenceGolfMgr.UsgaMarkerData();
|
||||
markerData.CourseId = usgaMarker.CourseId;
|
||||
markerData.MarkerId = usgaMarker.MarkerId;
|
||||
markerData.Caption = usgaMarker.Caption;
|
||||
markerData.Holes = usgaMarker.Holes;
|
||||
markerData.HolesCaption = usgaMarker.HolesCaption;
|
||||
markerData.Tee = usgaMarker.Tee;
|
||||
markerData.Gender = usgaMarker.Gender;
|
||||
markerData.SlopeRating = usgaMarker.SlopeRating;
|
||||
markerData.Par = usgaMarker.Par;
|
||||
markerData.CourseRating = usgaMarker.CourseRating;
|
||||
markerData.BogeyRating = usgaMarker.BogeyRating;
|
||||
markerData.Length = usgaMarker.Length;
|
||||
markersUpdateData.Add(markerData);
|
||||
}
|
||||
ReferenceGolfMgr.BulkUpdateUsgaMarkers(markersUpdateData, DbUpdateInfo);
|
||||
if (!ReferenceGolfMgr.HasErrorState())
|
||||
{
|
||||
// Courses updates OK.
|
||||
// Store Marker data and clear Course 'priority' flag.
|
||||
if (markersData.Markers.Any())
|
||||
{
|
||||
usgaCourse.MarkersData = JsonConvert.SerializeObject(markersData);
|
||||
usgaCourse.Priority = false;
|
||||
ReferenceGolfMgr.UpdateUsgaCourse(usgaCourse, DbUpdateInfo);
|
||||
}
|
||||
}
|
||||
else SaLogger.Warn(SysUtil.Fn + " Tee table not found.");
|
||||
else SaLogger.Warn($"{SysUtil.Fn} Error bulk updating USGA markers: {ReferenceGolfMgr.ErrorStateMessage}.");
|
||||
}
|
||||
|
||||
// Store markers.
|
||||
List<SaxReferenceGolfMgr.UsgaMarkerData> markersData = new List<SaxReferenceGolfMgr.UsgaMarkerData>();
|
||||
foreach (MarkerData usgaMarker in usgaMarkers)
|
||||
catch (Exception exc)
|
||||
{
|
||||
if (!SysId.IsValid(usgaMarker.CourseId)) continue;
|
||||
//if (!SysId.IsValid(usgaMarker.MarkerId)) continue;
|
||||
if (StringUtil.IsBlank(usgaMarker.Caption)) continue;
|
||||
SaxReferenceGolfMgr.UsgaMarkerData markerData = new SaxReferenceGolfMgr.UsgaMarkerData();
|
||||
markerData.CourseId = usgaMarker.CourseId;
|
||||
markerData.MarkerId = usgaMarker.MarkerId;
|
||||
markerData.Caption = usgaMarker.Caption;
|
||||
markerData.Holes = usgaMarker.Holes;
|
||||
markerData.HolesCaption = usgaMarker.HolesCaption;
|
||||
markerData.Tee = usgaMarker.Tee;
|
||||
markerData.Gender = usgaMarker.Gender;
|
||||
markerData.SlopeRating = usgaMarker.SlopeRating;
|
||||
markerData.Par = usgaMarker.Par;
|
||||
markerData.CourseRating = usgaMarker.CourseRating;
|
||||
markerData.BogeyRating = usgaMarker.BogeyRating;
|
||||
markerData.Length = usgaMarker.Length;
|
||||
markersData.Add(markerData);
|
||||
SaLogger.Warn(SysUtil.Fn + " " + ExceptionUtil.GetLogMessage(exc, $"querying USGA markers for course Id: {usgaCourseId}", 0));
|
||||
}
|
||||
ReferenceGolfMgr.BulkUpdateUsgaMarkers(markersData, config.DbUpdateInfo);
|
||||
if (ReferenceGolfMgr.HasErrorState())
|
||||
SaLogger.Warn($"{SysUtil.Fn} Error bulk updating USGA markers: {ReferenceGolfMgr.ErrorStateMessage}.");
|
||||
}
|
||||
catch (Exception exc)
|
||||
{
|
||||
SaLogger.Warn(SysUtil.Fn + " " + ExceptionUtil.GetLogMessage(exc, $"querying USGA markers for course Id: {usgaCourseId}", 0));
|
||||
}
|
||||
return usgaMarkers;
|
||||
return markersData.Markers;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user