2
0
mirror of synced 2025-02-17 02:46:32 +00:00

132 lines
4.3 KiB
C#
Raw Normal View History

2024-07-25 15:12:25 +02:00
using Newtonsoft.Json;
using System.IO.Compression;
namespace OverwatchTranscript
{
public interface ITranscriptWriter
{
void AddHeader(string key, object value);
void Add(DateTime utc, object payload);
void IncludeArtifact(string filePath);
void Write(string outputFilename);
}
public class TranscriptWriter : ITranscriptWriter
{
2024-07-26 13:21:29 +02:00
private readonly object _lock = new object();
2024-07-25 15:12:25 +02:00
private readonly string transcriptFile;
private readonly string artifactsFolder;
private readonly Dictionary<string, string> header = new Dictionary<string, string>();
2024-07-26 10:56:22 +02:00
private readonly SortedList<DateTime, List<OverwatchEvent>> buffer = new SortedList<DateTime, List<OverwatchEvent>>();
2024-07-25 15:12:25 +02:00
private readonly string workingDir;
private bool closed;
public TranscriptWriter(string workingDir)
{
closed = false;
this.workingDir = workingDir;
transcriptFile = Path.Combine(workingDir, TranscriptConstants.TranscriptFilename);
artifactsFolder = Path.Combine(workingDir, TranscriptConstants.ArtifactFolderName);
if (!Directory.Exists(workingDir)) Directory.CreateDirectory(workingDir);
if (File.Exists(transcriptFile) || Directory.Exists(artifactsFolder)) throw new Exception("workingdir not clean");
}
public void Add(DateTime utc, object payload)
{
CheckClosed();
var typeName = payload.GetType().FullName;
if (string.IsNullOrEmpty(typeName)) throw new Exception("Empty typename for payload");
2024-07-26 10:56:22 +02:00
var newEvent = new OverwatchEvent
2024-07-25 15:12:25 +02:00
{
Type = typeName,
Payload = JsonConvert.SerializeObject(payload)
2024-07-26 10:56:22 +02:00
};
2024-07-26 13:21:29 +02:00
lock (_lock)
2024-07-26 10:56:22 +02:00
{
2024-07-26 13:21:29 +02:00
if (buffer.ContainsKey(utc))
{
buffer[utc].Add(newEvent);
}
else
{
buffer.Add(utc, new List<OverwatchEvent> { newEvent });
}
2024-07-26 10:56:22 +02:00
}
2024-07-25 15:12:25 +02:00
}
public void AddHeader(string key, object value)
{
CheckClosed();
2024-07-26 13:21:29 +02:00
lock (_lock)
{
header.Add(key, JsonConvert.SerializeObject(value));
}
2024-07-25 15:12:25 +02:00
}
public void IncludeArtifact(string filePath)
{
CheckClosed();
if (!File.Exists(filePath)) throw new Exception("File not found: " + filePath);
2024-07-26 09:14:46 +02:00
if (!Directory.Exists(artifactsFolder)) Directory.CreateDirectory(artifactsFolder);
2024-07-25 15:12:25 +02:00
var name = Path.GetFileName(filePath);
File.Copy(filePath, Path.Combine(artifactsFolder, name), overwrite: false);
}
public void Write(string outputFilename)
{
CheckClosed();
closed = true;
2024-07-26 13:21:29 +02:00
var model = CreateModel();
File.WriteAllText(transcriptFile, JsonConvert.SerializeObject(model, Formatting.Indented));
ZipFile.CreateFromDirectory(workingDir, outputFilename);
Directory.Delete(workingDir, true);
}
private OverwatchTranscript CreateModel()
{
lock (_lock)
2024-07-25 15:12:25 +02:00
{
2024-07-26 13:21:29 +02:00
var model = new OverwatchTranscript
2024-07-25 15:12:25 +02:00
{
2024-07-26 13:21:29 +02:00
Header = new OverwatchHeader
{
Entries = header.Select(h =>
{
return new OverwatchHeaderEntry
{
Key = h.Key,
Value = h.Value
};
}).ToArray()
},
Moments = buffer.Select(p =>
2024-07-25 15:12:25 +02:00
{
2024-07-26 13:21:29 +02:00
return new OverwatchMoment
2024-07-25 15:12:25 +02:00
{
2024-07-26 13:21:29 +02:00
Utc = p.Key,
Events = p.Value.ToArray()
2024-07-25 15:12:25 +02:00
};
}).ToArray()
2024-07-26 13:21:29 +02:00
};
2024-07-25 15:12:25 +02:00
2024-07-26 13:21:29 +02:00
header.Clear();
buffer.Clear();
2024-07-25 15:12:25 +02:00
2024-07-26 13:21:29 +02:00
return model;
}
2024-07-25 15:12:25 +02:00
}
private void CheckClosed()
{
if (closed) throw new Exception("Transcript has already been written. Cannot modify or write again.");
}
}
}