mirror of
https://github.com/9ParsonsB/Pulsar.git
synced 2025-04-05 17:39:39 -04:00
* Expose core error logger to plugins and report custom criteria errors Fixes #77 This adds an error logging method on the IObservatoryCore interface that writes the exception details to ObservatoryCore's central error log (found in `${Documents}/ObservatoryErrorLog.txt`). In addition, added a timestamp to each error log. Also updates the Explorer to report Custom Criteria file load errors and execution errors to the log. Also updates HeraldNotifier to report CacheIndex.json parse failures to the error log as well. * Expand debugging/error logging in Herald; cleanup empty mp3 files Herald crashes if attempting to play 0-byte mp3s so if detected, delete, re-request (empty files can occur in some azure failure cases (ie. out of quota). Trap and log errors in other places in HeraldQueue to avoid hard crashes due to weird and wonderful unexpected stuff.
270 lines
11 KiB
C#
270 lines
11 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Text;
|
|
using Observatory.Framework.Files.Journal;
|
|
using NLua;
|
|
using System.Linq;
|
|
|
|
namespace Observatory.Explorer
|
|
{
|
|
internal class CustomCriteriaManager
|
|
{
|
|
private Lua LuaState;
|
|
private List<LuaFunction> CriteriaFunctions;
|
|
Action<Exception, String> ErrorLogger;
|
|
|
|
|
|
public CustomCriteriaManager(Action<Exception, String> errorLogger)
|
|
{
|
|
ErrorLogger = errorLogger;
|
|
CriteriaFunctions = new();
|
|
}
|
|
|
|
public void RefreshCriteria(string criteriaPath)
|
|
{
|
|
LuaState = new();
|
|
LuaState.State.Encoding = Encoding.UTF8;
|
|
LuaState.LoadCLRPackage();
|
|
|
|
#region Iterators
|
|
|
|
// Empty function for nil iterators
|
|
LuaState.DoString("function nil_iterator() end");
|
|
|
|
//Materials and AtmosphereComposition
|
|
LuaState.DoString(@"
|
|
function materials (material_list)
|
|
if material_list then
|
|
local i = 0
|
|
local count = material_list.Count
|
|
return function ()
|
|
i = i + 1
|
|
if i <= count then
|
|
return { name = material_list[i - 1].Name, percent = material_list[i - 1].Percent }
|
|
end
|
|
end
|
|
else
|
|
return nil_iterator
|
|
end
|
|
end");
|
|
|
|
//Rings
|
|
LuaState.DoString(@"
|
|
function rings (ring_list)
|
|
if ring_list then
|
|
local i = 0
|
|
local count = ring_list.Count
|
|
return function ()
|
|
i = i + 1
|
|
if i <= count then
|
|
local ring = ring_list[i - 1]
|
|
return { name = ring.Name, ringclass = ring.RingClass, massmt = ring.MassMT, innerrad = ring.InnerRad, outerrad = ring.OuterRad }
|
|
end
|
|
end
|
|
else
|
|
return nil_iterator
|
|
end
|
|
end");
|
|
|
|
//Bodies in system
|
|
LuaState.DoString(@"
|
|
function bodies (system_list)
|
|
if system_list then
|
|
local i = 0
|
|
local count = system_list.Count
|
|
return function ()
|
|
i = i + 1
|
|
if i <= count then
|
|
return system_list[i - 1]
|
|
end
|
|
end
|
|
else
|
|
return nil_iterator
|
|
end
|
|
end");
|
|
|
|
//Parent bodies
|
|
LuaState.DoString(@"
|
|
function allparents (parent_list)
|
|
if parent_list then
|
|
local i = 0
|
|
local count
|
|
if parent_list then count = parent_list.Count else count = 0 end
|
|
return function ()
|
|
i = i + 1
|
|
if i <= count then
|
|
return { parenttype = parent_list[i - 1].ParentType, body = parent_list[i - 1].Body, scan = parent_list[i - 1].Scan }
|
|
end
|
|
end
|
|
else
|
|
return nil_iterator
|
|
end
|
|
end");
|
|
|
|
#endregion
|
|
|
|
CriteriaFunctions.Clear();
|
|
var criteria = File.Exists(criteriaPath) ? File.ReadAllLines(criteriaPath) : Array.Empty<string>();
|
|
StringBuilder script = new();
|
|
|
|
try
|
|
{
|
|
for (int i = 0; i < criteria.Length; i++)
|
|
{
|
|
if (criteria[i].Trim().StartsWith("::"))
|
|
{
|
|
string scriptDescription = criteria[i].Trim().Replace("::", string.Empty);
|
|
if (scriptDescription.ToLower() == "criteria")
|
|
{
|
|
string functionName = $"Criteria{i}";
|
|
script.AppendLine($"function {functionName} (scan, parents, system, biosignals, geosignals)");
|
|
i++;
|
|
do
|
|
{
|
|
script.AppendLine(criteria[i]);
|
|
i++;
|
|
} while (!criteria[i].Trim().ToLower().StartsWith("::end::"));
|
|
script.AppendLine("end");
|
|
|
|
LuaState.DoString(script.ToString());
|
|
CriteriaFunctions.Add(LuaState[functionName] as LuaFunction);
|
|
script.Clear();
|
|
}
|
|
else if (scriptDescription.ToLower() == "global")
|
|
{
|
|
i++;
|
|
do
|
|
{
|
|
script.AppendLine(criteria[i]);
|
|
i++;
|
|
} while (!criteria[i].Trim().ToLower().StartsWith("::end::"));
|
|
LuaState.DoString(script.ToString());
|
|
script.Clear();
|
|
}
|
|
else
|
|
{
|
|
i++;
|
|
|
|
string functionName = $"Criteria{i}";
|
|
|
|
script.AppendLine($"function {functionName} (scan, parents, system, biosignals, geosignals)");
|
|
script.AppendLine($" local result = {criteria[i]}");
|
|
|
|
if (criteria.Length > i + 1 && criteria[i + 1].Trim().ToLower() == "::detail::")
|
|
{
|
|
i++; i++;
|
|
script.AppendLine($" local detail = {criteria[i]}");
|
|
}
|
|
else
|
|
{
|
|
script.AppendLine(" local detail = ''");
|
|
}
|
|
|
|
script.AppendLine($" return result, '{scriptDescription}', detail");
|
|
script.AppendLine("end");
|
|
|
|
LuaState.DoString(script.ToString());
|
|
CriteriaFunctions.Add(LuaState[functionName] as LuaFunction);
|
|
script.Clear();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
string originalScript = script.ToString().Trim();
|
|
|
|
originalScript = originalScript.Remove(originalScript.LastIndexOf(Environment.NewLine));
|
|
originalScript = originalScript[(originalScript.IndexOf(Environment.NewLine) + Environment.NewLine.Length)..];
|
|
originalScript = originalScript.Replace('\t', ' ');
|
|
|
|
StringBuilder errorDetail = new();
|
|
errorDetail.AppendLine("Error Reading Custom Criteria File:")
|
|
.AppendLine(originalScript)
|
|
.AppendLine("NOTE: Custom criteria processing has been disable to prevent further errors.");
|
|
ErrorLogger(e, errorDetail.ToString());
|
|
throw new CriteriaLoadException(e.Message, originalScript);
|
|
}
|
|
}
|
|
|
|
public List<(string, string, bool)> CheckInterest(Scan scan, Dictionary<ulong, Dictionary<int, Scan>> scanHistory, Dictionary<ulong, Dictionary<int, FSSBodySignals>> signalHistory, ExplorerSettings settings)
|
|
{
|
|
List<(string, string, bool)> results = new();
|
|
|
|
foreach (var criteriaFunction in CriteriaFunctions)
|
|
{
|
|
var scanList = scanHistory[scan.SystemAddress].Values.ToList();
|
|
|
|
int bioSignals;
|
|
int geoSignals;
|
|
|
|
if (signalHistory.ContainsKey(scan.SystemAddress) && signalHistory[scan.SystemAddress].ContainsKey(scan.BodyID))
|
|
{
|
|
bioSignals = signalHistory[scan.SystemAddress][scan.BodyID].Signals.Where(s => s.Type == "$SAA_SignalType_Biological;").Select(s => s.Count).FirstOrDefault();
|
|
geoSignals = signalHistory[scan.SystemAddress][scan.BodyID].Signals.Where(s => s.Type == "$SAA_SignalType_Geological;").Select(s => s.Count).FirstOrDefault();
|
|
}
|
|
else
|
|
{
|
|
bioSignals = 0;
|
|
geoSignals = 0;
|
|
}
|
|
|
|
|
|
List<Parent> parents;
|
|
|
|
if (scan.Parent != null)
|
|
{
|
|
parents = new();
|
|
foreach (var parent in scan.Parent)
|
|
{
|
|
var parentScan = scanList.Where(s => s.BodyID == parent.Body);
|
|
|
|
parents.Add(new Parent()
|
|
{
|
|
ParentType = parent.ParentType.ToString(),
|
|
Body = parent.Body,
|
|
Scan = parentScan.Any() ? parentScan.First() : null
|
|
});
|
|
}
|
|
}
|
|
else
|
|
{
|
|
parents = null;
|
|
}
|
|
|
|
try
|
|
{
|
|
var result = criteriaFunction.Call(scan, parents, scanList, bioSignals, geoSignals);
|
|
if (result.Length > 0 && ((bool?)result[0]).GetValueOrDefault(false))
|
|
{
|
|
results.Add((result[1].ToString(), result[2].ToString(), false));
|
|
}
|
|
}
|
|
catch (NLua.Exceptions.LuaScriptException e)
|
|
{
|
|
settings.EnableCustomCriteria = false;
|
|
results.Add((e.Message, scan.Json, false));
|
|
|
|
StringBuilder errorDetail = new();
|
|
errorDetail.AppendLine("while processing a custom criteria on scan:")
|
|
.AppendLine(scan.Json)
|
|
.AppendLine("NOTE: Custom criteria process has been disabled to prevent further errors.");
|
|
ErrorLogger(e, errorDetail.ToString());
|
|
break;
|
|
}
|
|
}
|
|
|
|
return results;
|
|
}
|
|
|
|
internal class Parent
|
|
{
|
|
public string ParentType;
|
|
public int Body;
|
|
public Scan Scan;
|
|
}
|
|
|
|
}
|
|
}
|