using System.Globalization; using OpenAC.MosswartMassacre.Backend; using OpenAC.MosswartMassacre.Infrastructure; namespace OpenAC.MosswartMassacre.Streams; /// /// The telemetry frame: sent right after the socket registers and then /// every five seconds, as the original's socket loop did. /// /// /// Several fields are strings on the wire (kill rate, deaths, taper count) and /// mem_mb carries bytes; the backend reads them that way. /// internal sealed class TelemetryStream : IMmFeature, IBackendConnectionListener { public static readonly TimeSpan Interval = TimeSpan.FromSeconds(5); private readonly MmContext _context; private readonly SessionStats _stats; private readonly ProcessTelemetry _process = new(); private IDisposable? _timer; public TelemetryStream(MmContext context, SessionStats stats) { _context = context; _stats = stats; } public void OnBackendConnected() { if (!_context.IsLoggedIn) return; SendNow(); _timer?.Dispose(); _timer = _context.Scheduler.Every(Interval, SendNow); } public void OnLogin() { } public void OnLogoff() { _timer?.Dispose(); _timer = null; } public void Dispose() => OnLogoff(); internal void SendNow() { if (!_context.IsLoggedIn) return; _context.Send(Build()); } internal object Build() { MmCoordinates coords = MmCoordinates.From(_context.Automation.Navigation.Snapshot.Position); var kills = _stats.Kills; return new { type = "telemetry", character_name = _context.CharacterName, char_tag = _context.Settings.Current.CharTag ?? "", session_id = _context.TelemetrySessionId, timestamp = Wire.Timestamp(_context.Clock), ew = coords.EW, ns = coords.NS, z = coords.Z, kills = kills.TotalKills, kills_per_hour = FrameworkNumberConverter.FrameworkFixed(kills.KillsPerHour, "F0", CultureInfo.CurrentCulture), onlinetime = (_context.Clock.Now - kills.StatsStartTime).ToString(@"dd\.hh\:mm\:ss", CultureInfo.InvariantCulture), deaths = kills.SessionDeaths.ToString(CultureInfo.CurrentCulture), total_deaths = kills.TotalDeaths.ToString(CultureInfo.CurrentCulture), prismatic_taper_count = _context.PrismaticTaperCount().ToString(CultureInfo.CurrentCulture), vt_state = _context.MetaState() ?? string.Empty, mem_mb = _process.MemoryBytes, cpu_pct = _process.SampleCpuUsage(), mem_handles = _process.HandleCount, }; } }