worldbox-observer-mod/IdleSpectator/Events/InterestDropLog.cs

108 lines
2.5 KiB
C#

using System;
using System.Collections.Generic;
using System.Text;
using NeoModLoader.services;
namespace IdleSpectator;
/// <summary>
/// Ring buffer of why a beat stayed Layer B or failed to take / keep Layer A camera.
/// </summary>
public static class InterestDropLog
{
public const int Capacity = 48;
private static readonly string[] Buffer = new string[Capacity];
private static int _write;
private static int _count;
private static float _lastPlayerLogAt = -999f;
private const float PlayerLogInterval = 8f;
public static int Count => _count;
public static void Clear()
{
_write = 0;
_count = 0;
for (int i = 0; i < Capacity; i++)
{
Buffer[i] = null;
}
}
public static void Record(string reason, string detail = "")
{
if (string.IsNullOrEmpty(reason))
{
return;
}
string line = string.IsNullOrEmpty(detail)
? reason
: (reason + ": " + detail);
Buffer[_write] = line;
_write = (_write + 1) % Capacity;
if (_count < Capacity)
{
_count++;
}
float now = UnityEngine.Time.unscaledTime;
if (now - _lastPlayerLogAt >= PlayerLogInterval)
{
_lastPlayerLogAt = now;
try
{
LogService.LogInfo("[IdleSpectator][DROP] " + line);
}
catch
{
// ignore log failures
}
}
}
/// <summary>Newest-first snapshot for harness / diagnostics.</summary>
public static List<string> Snapshot(int max = 12)
{
var list = new List<string>(Math.Min(max, _count));
if (_count == 0 || max <= 0)
{
return list;
}
int n = Math.Min(max, _count);
for (int i = 0; i < n; i++)
{
int idx = (_write - 1 - i + Capacity) % Capacity;
if (!string.IsNullOrEmpty(Buffer[idx]))
{
list.Add(Buffer[idx]);
}
}
return list;
}
public static string FormatRecent(int max = 8)
{
List<string> lines = Snapshot(max);
if (lines.Count == 0)
{
return "";
}
var sb = new StringBuilder();
for (int i = 0; i < lines.Count; i++)
{
if (i > 0)
{
sb.Append(" | ");
}
sb.Append(lines[i]);
}
return sb.ToString();
}
}