cs-codex-dist-tests/Framework/OverwatchTranscript/TranscriptWriter.cs

131 lines
4.6 KiB
C#
Raw Normal View History

2024-08-02 06:56:49 +00:00
using Logging;
using Newtonsoft.Json;
2024-07-25 13:12:25 +00:00
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 11:21:29 +00:00
private readonly object _lock = new object();
2024-08-01 14:25:28 +00:00
private readonly MomentReferenceBuilder builder;
2024-07-25 13:12:25 +00:00
private readonly string transcriptFile;
private readonly string artifactsFolder;
private readonly Dictionary<string, string> header = new Dictionary<string, string>();
2024-08-01 14:25:28 +00:00
private readonly BucketSet bucketSet;
2024-08-02 06:56:49 +00:00
private readonly ILog log;
2024-07-25 13:12:25 +00:00
private readonly string workingDir;
private bool closed;
2024-08-02 06:56:49 +00:00
public TranscriptWriter(ILog log, string workingDir)
2024-07-25 13:12:25 +00:00
{
closed = false;
2024-08-02 06:56:49 +00:00
this.log = log;
2024-07-25 13:12:25 +00:00
this.workingDir = workingDir;
2024-08-02 06:56:49 +00:00
bucketSet = new BucketSet(log, workingDir);
builder = new MomentReferenceBuilder(log, workingDir);
2024-07-25 13:12:25 +00:00
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();
2024-08-01 14:25:28 +00:00
bucketSet.Add(utc, payload);
2024-07-25 13:12:25 +00:00
}
public void AddHeader(string key, object value)
{
CheckClosed();
2024-07-26 11:21:29 +00:00
lock (_lock)
{
header.Add(key, Json.Serialize(value));
2024-07-26 11:21:29 +00:00
}
2024-07-25 13:12:25 +00:00
}
public void IncludeArtifact(string filePath)
{
CheckClosed();
if (!File.Exists(filePath)) throw new Exception("File not found: " + filePath);
2024-07-26 07:14:46 +00:00
if (!Directory.Exists(artifactsFolder)) Directory.CreateDirectory(artifactsFolder);
2024-07-25 13:12:25 +00:00
var name = Path.GetFileName(filePath);
File.Copy(filePath, Path.Combine(artifactsFolder, name), overwrite: false);
}
public void Write(string outputFilename)
{
CheckClosed();
closed = true;
2024-08-01 14:25:28 +00:00
var momentReferences = builder.Build(bucketSet.FinalizeBuckets());
var model = CreateModel(momentReferences);
2024-07-26 11:21:29 +00:00
File.WriteAllText(transcriptFile, Json.Serialize(model, Formatting.Indented));
2024-07-26 11:21:29 +00:00
ZipFile.CreateFromDirectory(workingDir, outputFilename);
2024-08-02 06:56:49 +00:00
log.Debug($"Transcript written to {outputFilename}");
log.Debug($"Common header: {Json.Serialize(model.Header.Common, Formatting.Indented)}");
2024-07-26 11:21:29 +00:00
Directory.Delete(workingDir, true);
2024-08-02 06:56:49 +00:00
log.Debug($"Workdir {workingDir} deleted");
2024-07-26 11:21:29 +00:00
}
2024-08-01 14:25:28 +00:00
private OverwatchTranscript CreateModel(OverwatchMomentReference[] momentReferences)
2024-07-26 11:21:29 +00:00
{
lock (_lock)
2024-07-25 13:12:25 +00:00
{
2024-07-26 11:21:29 +00:00
var model = new OverwatchTranscript
2024-07-25 13:12:25 +00:00
{
2024-07-26 11:21:29 +00:00
Header = new OverwatchHeader
{
2024-08-01 14:25:28 +00:00
Common = CreateCommonHeader(momentReferences),
2024-07-26 11:21:29 +00:00
Entries = header.Select(h =>
{
return new OverwatchHeaderEntry
{
Key = h.Key,
Value = h.Value
};
}).ToArray()
},
2024-08-01 14:25:28 +00:00
MomentReferences = momentReferences
2024-07-26 11:21:29 +00:00
};
2024-07-25 13:12:25 +00:00
2024-07-26 11:21:29 +00:00
header.Clear();
return model;
}
2024-07-25 13:12:25 +00:00
}
2024-08-01 14:25:28 +00:00
private OverwatchCommonHeader CreateCommonHeader(OverwatchMomentReference[] momentReferences)
2024-07-29 06:08:17 +00:00
{
2024-08-01 14:25:28 +00:00
var moments = momentReferences.Sum(m => m.NumberOfMoments);
var events = momentReferences.Sum(m => m.NumberOfEvents);
var earliest = momentReferences.Min(m => m.EarliestUtc);
var latest = momentReferences.Max(m => m.LatestUtc);
2024-07-29 06:08:17 +00:00
return new OverwatchCommonHeader
{
2024-08-01 14:25:28 +00:00
NumberOfMoments = moments,
NumberOfEvents = events,
EarliestUtc = earliest,
LatestUtc = latest
2024-07-29 06:08:17 +00:00
};
}
2024-07-25 13:12:25 +00:00
private void CheckClosed()
{
if (closed) throw new Exception("Transcript has already been written. Cannot modify or write again.");
}
}
}