using System;
using System.Collections.Generic;
using System.Text;
namespace IdleSpectator;
///
/// Honest live-verification ledger (Phase 0). Regenerated each run; not committed.
/// Levels: none | feed | pipeline | id_drop | id | unsupported | fail
///
public sealed class EventLiveCoverageRow
{
public string Domain = "";
public string Id = "";
public bool Camera;
public bool Inject;
public string LiveLevel = "none";
public string Pipeline = "";
public string Notes = "";
}
public sealed class EventLiveCoverageSummary
{
public int Id;
public int IdDrop;
public int Pipeline;
public int Feed;
public int None;
public int Unsupported;
public int Fail;
public int CameraRows;
public int CameraNone;
public string Detail =>
$"id={Id} id_drop={IdDrop} pipeline={Pipeline} feed={Feed} none={None} "
+ $"unsupported={Unsupported} fail={Fail} camera={CameraRows} camera_none={CameraNone}";
}
public static class EventLiveCoverageLedger
{
private static readonly Dictionary Rows =
new Dictionary(StringComparer.OrdinalIgnoreCase);
private static string Key(string domain, string id) => (domain ?? "") + "\t" + (id ?? "");
public static int RowCount => Rows.Count;
public static void Clear()
{
Rows.Clear();
}
public static void SeedFromCatalogs()
{
Clear();
foreach (string id in EventCatalog.Happiness.AuthoredIds)
{
HappinessCatalogEntry e = EventCatalog.Happiness.GetOrFallback(id);
bool camera = EventCatalog.IsCameraWorthy(e);
AddSeed("happiness", id, camera, camera);
}
foreach (string id in EventCatalog.Status.AuthoredIds)
{
StatusInterestEntry e = EventCatalog.Status.GetOrFallback(id);
bool camera = EventCatalog.IsCameraWorthy(e);
AddSeed("status", id, camera, camera);
}
foreach (string id in EventCatalog.WorldLog.AuthoredIds)
{
WorldLogEventEntry e = EventCatalog.WorldLog.GetOrFallback(id);
bool camera = EventCatalog.IsCameraWorthy(e);
AddSeed("worldLog", id, camera, camera);
}
foreach (string id in EventCatalog.Disaster.AuthoredIds)
{
DisasterInterestEntry e = EventCatalog.Disaster.GetOrFallback(id);
bool camera = e != null && EventCatalog.IsCameraWorthy(e.CreatesInterest);
AddSeed("disasters", id, camera, camera);
}
foreach (string id in EventCatalog.WarType.AuthoredIds)
{
WarTypeInterestEntry e = EventCatalog.WarType.GetOrFallback(id);
bool camera = e != null && EventCatalog.IsCameraWorthy(e.CreatesInterest);
AddSeed("warTypes", id, camera, camera);
}
SeedDiscrete("relationship", EventCatalog.Relationship.AuthoredIds, id => EventCatalog.Relationship.GetOrFallback(id));
SeedDiscrete("plots", EventCatalog.Plot.AuthoredIds, id => EventCatalog.Plot.GetOrFallback(id));
SeedDiscrete("books", EventCatalog.Book.AuthoredIds, id => EventCatalog.Book.GetOrFallback(id));
SeedDiscrete("eras", EventCatalog.Era.AuthoredIds, id => EventCatalog.Era.GetOrFallback(id));
SeedDiscrete("traits", EventCatalog.Trait.AuthoredIds, id => EventCatalog.Trait.GetOrFallback(id));
foreach (string id in EventCatalog.Decision.AuthoredIds)
{
bool camera = EventCatalog.Decision.IsCameraWorthy(id);
AddSeed("decisions", id, camera, camera);
}
SeedDiscrete("spell", EventCatalog.Spell.AuthoredIds, id => EventCatalog.Spell.GetOrFallback(id));
SeedDiscrete("item", EventCatalog.Item.AuthoredIds, id => EventCatalog.Item.GetOrFallback(id));
SeedDiscrete("power", EventCatalog.Power.AuthoredIds, id => EventCatalog.Power.GetOrFallback(id));
SeedDiscrete("gene", EventCatalog.Gene.AuthoredIds, id => EventCatalog.Gene.GetOrFallback(id));
SeedDiscrete("phenotype", EventCatalog.Phenotype.AuthoredIds, id => EventCatalog.Phenotype.GetOrFallback(id));
SeedDiscrete("worldLaw", EventCatalog.WorldLaw.AuthoredIds, id => EventCatalog.WorldLaw.GetOrFallback(id));
SeedDiscrete("subspecies_trait", EventCatalog.SubspeciesTrait.AuthoredIds, id => EventCatalog.SubspeciesTrait.GetOrFallback(id));
SeedDiscrete("biome", EventCatalog.Biome.AuthoredIds, id => EventCatalog.Biome.GetOrFallback(id));
}
private static void SeedDiscrete(string domain, IEnumerable ids, Func get)
{
if (ids == null)
{
return;
}
foreach (string raw in ids)
{
string id = (raw ?? "").Trim();
if (string.IsNullOrEmpty(id))
{
continue;
}
DiscreteEventEntry e = get(id);
bool camera = EventCatalog.IsCameraWorthy(e);
AddSeed(domain, id, camera, camera);
}
}
private static void AddSeed(string domain, string id, bool camera, bool inject)
{
string key = Key(domain, id);
Rows[key] = new EventLiveCoverageRow
{
Domain = domain,
Id = id,
Camera = camera,
Inject = inject,
LiveLevel = "none",
Pipeline = "",
Notes = ""
};
}
/// Overwrite live proof for one id. Does not invent catalog rows.
public static void Claim(string domain, string id, string liveLevel, string pipeline, string notes)
{
string key = Key(domain, id);
if (!Rows.TryGetValue(key, out EventLiveCoverageRow row))
{
row = new EventLiveCoverageRow
{
Domain = domain ?? "",
Id = id ?? "",
Camera = true,
Inject = false
};
Rows[key] = row;
}
row.LiveLevel = string.IsNullOrEmpty(liveLevel) ? "none" : liveLevel.Trim();
row.Pipeline = pipeline ?? "";
row.Notes = notes ?? "";
}
public static EventLiveCoverageSummary Summarize()
{
var s = new EventLiveCoverageSummary();
foreach (EventLiveCoverageRow row in Rows.Values)
{
if (row.Camera)
{
s.CameraRows++;
}
switch ((row.LiveLevel ?? "none").Trim().ToLowerInvariant())
{
case "id":
s.Id++;
break;
case "id_drop":
s.IdDrop++;
break;
case "pipeline":
s.Pipeline++;
break;
case "feed":
s.Feed++;
break;
case "unsupported":
s.Unsupported++;
break;
case "fail":
s.Fail++;
break;
default:
s.None++;
if (row.Camera)
{
s.CameraNone++;
}
break;
}
}
return s;
}
public static string Write(string outputDirectory)
{
var tsv = new StringBuilder();
tsv.AppendLine("domain\tid\tcamera\tinject\tlive_level\tpipeline\tnotes");
var keys = new List(Rows.Keys);
keys.Sort(StringComparer.OrdinalIgnoreCase);
for (int i = 0; i < keys.Count; i++)
{
EventLiveCoverageRow row = Rows[keys[i]];
tsv.Append(row.Domain).Append('\t')
.Append(row.Id).Append('\t')
.Append(row.Camera ? "true" : "false").Append('\t')
.Append(row.Inject ? "true" : "false").Append('\t')
.Append(row.LiveLevel ?? "none").Append('\t')
.Append(row.Pipeline ?? "").Append('\t')
.Append(row.Notes ?? "").Append('\n');
}
CatalogCoverageAudit.WriteReport(outputDirectory, "event-live-coverage.tsv", tsv.ToString());
return Summarize().Detail;
}
}