269 lines
9.9 KiB
C#
269 lines
9.9 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Text;
|
|
|
|
namespace IdleSpectator;
|
|
|
|
public sealed class CatalogCoverageDiff
|
|
{
|
|
public string Domain = "";
|
|
public int LiveTotal;
|
|
public int AuthoredTotal;
|
|
public int Missing;
|
|
public int Orphan;
|
|
public readonly List<string> MissingIds = new List<string>();
|
|
public readonly List<string> OrphanIds = new List<string>();
|
|
|
|
public bool Passed => Missing == 0 && Orphan == 0;
|
|
|
|
public string Detail =>
|
|
$"{Domain}: live={LiveTotal} authored={AuthoredTotal} missing={Missing} orphan={Orphan}";
|
|
}
|
|
|
|
/// <summary>Shared live-vs-authored coverage audit used by domain event catalogs.</summary>
|
|
public static class CatalogCoverageAudit
|
|
{
|
|
public static CatalogCoverageDiff Diff(
|
|
string domain,
|
|
IEnumerable<string> liveIds,
|
|
IEnumerable<string> authoredIds)
|
|
{
|
|
var live = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
|
|
var authored = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
|
|
var diff = new CatalogCoverageDiff { Domain = domain ?? "domain" };
|
|
|
|
if (liveIds != null)
|
|
{
|
|
foreach (string id in liveIds)
|
|
{
|
|
if (string.IsNullOrEmpty(id))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
live.Add(id.Trim());
|
|
}
|
|
}
|
|
|
|
if (authoredIds != null)
|
|
{
|
|
foreach (string id in authoredIds)
|
|
{
|
|
if (string.IsNullOrEmpty(id))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
authored.Add(id.Trim());
|
|
}
|
|
}
|
|
|
|
diff.LiveTotal = live.Count;
|
|
diff.AuthoredTotal = authored.Count;
|
|
|
|
foreach (string id in live)
|
|
{
|
|
if (!authored.Contains(id))
|
|
{
|
|
diff.Missing++;
|
|
diff.MissingIds.Add(id);
|
|
}
|
|
}
|
|
|
|
foreach (string id in authored)
|
|
{
|
|
if (!live.Contains(id))
|
|
{
|
|
diff.Orphan++;
|
|
diff.OrphanIds.Add(id);
|
|
}
|
|
}
|
|
|
|
return diff;
|
|
}
|
|
|
|
public static void WriteReport(string outputDirectory, string fileName, string body)
|
|
{
|
|
if (string.IsNullOrEmpty(outputDirectory) || string.IsNullOrEmpty(fileName))
|
|
{
|
|
return;
|
|
}
|
|
|
|
try
|
|
{
|
|
Directory.CreateDirectory(outputDirectory);
|
|
File.WriteAllText(Path.Combine(outputDirectory, fileName), body ?? "");
|
|
}
|
|
catch
|
|
{
|
|
// ignore IO
|
|
}
|
|
}
|
|
}
|
|
|
|
public sealed class DomainEventAuditResult
|
|
{
|
|
public bool Passed;
|
|
public string Detail = "";
|
|
}
|
|
|
|
/// <summary>Coverage audits for relationship discrete events + live plot/era/book libraries.</summary>
|
|
public static class DomainEventHarness
|
|
{
|
|
public static DomainEventAuditResult RunAudit(string outputDirectory)
|
|
{
|
|
var tsv = new StringBuilder();
|
|
tsv.AppendLine("domain\tid\tauthored\towns_camera\tevent_strength\tnotes");
|
|
|
|
CatalogCoverageDiff plots = CatalogCoverageAudit.Diff(
|
|
"plots",
|
|
ActivityAssetCatalog.EnumerateLivePlotIds(),
|
|
PlotInterestCatalog.AuthoredIds);
|
|
AppendLibraryDomain(tsv, "plots", ActivityAssetCatalog.EnumerateLivePlotIds(), plots, PlotInterestCatalog.GetOrFallback);
|
|
|
|
CatalogCoverageDiff eras = CatalogCoverageAudit.Diff(
|
|
"eras",
|
|
ActivityAssetCatalog.EnumerateLiveEraIds(),
|
|
EraInterestCatalog.AuthoredIds);
|
|
AppendLibraryDomain(tsv, "eras", ActivityAssetCatalog.EnumerateLiveEraIds(), eras, EraInterestCatalog.GetOrFallback);
|
|
|
|
CatalogCoverageDiff books = CatalogCoverageAudit.Diff(
|
|
"books",
|
|
ActivityAssetCatalog.EnumerateLiveBookTypeIds(),
|
|
BookInterestCatalog.AuthoredIds);
|
|
AppendLibraryDomain(tsv, "books", ActivityAssetCatalog.EnumerateLiveBookTypeIds(), books, BookInterestCatalog.GetOrFallback);
|
|
|
|
CatalogCoverageDiff traits = CatalogCoverageAudit.Diff(
|
|
"traits",
|
|
ActivityAssetCatalog.EnumerateLiveTraitIds(),
|
|
TraitInterestCatalog.AuthoredIds);
|
|
AppendLibraryDomain(tsv, "traits", ActivityAssetCatalog.EnumerateLiveTraitIds(), traits, TraitInterestCatalog.GetOrFallback);
|
|
|
|
CatalogCoverageDiff spells = CatalogCoverageAudit.Diff(
|
|
"spells",
|
|
ActivityAssetCatalog.EnumerateLiveSpellIds(),
|
|
SpellInterestCatalog.AuthoredIds);
|
|
AppendLibraryDomain(tsv, "spells", ActivityAssetCatalog.EnumerateLiveSpellIds(), spells, SpellInterestCatalog.GetOrFallback);
|
|
|
|
CatalogCoverageDiff powers = CatalogCoverageAudit.Diff(
|
|
"powers",
|
|
ActivityAssetCatalog.EnumerateLivePowerIds(),
|
|
PowerInterestCatalog.AuthoredIds);
|
|
AppendLibraryDomain(tsv, "powers", ActivityAssetCatalog.EnumerateLivePowerIds(), powers, PowerInterestCatalog.GetOrFallback);
|
|
|
|
CatalogCoverageDiff decisions = CatalogCoverageAudit.Diff(
|
|
"decisions",
|
|
ActivityAssetCatalog.EnumerateLiveDecisionIds(),
|
|
DecisionInterestCatalog.AuthoredIds);
|
|
AppendLibraryDomain(tsv, "decisions", ActivityAssetCatalog.EnumerateLiveDecisionIds(), decisions, DecisionInterestCatalog.GetOrFallback);
|
|
|
|
CatalogCoverageDiff items = CatalogCoverageAudit.Diff(
|
|
"items",
|
|
ActivityAssetCatalog.EnumerateLiveItemIds(),
|
|
ItemInterestCatalog.AuthoredIds);
|
|
AppendLibraryDomain(tsv, "items", ActivityAssetCatalog.EnumerateLiveItemIds(), items, ItemInterestCatalog.GetOrFallback);
|
|
|
|
CatalogCoverageDiff subspTraits = CatalogCoverageAudit.Diff(
|
|
"subspecies_traits",
|
|
ActivityAssetCatalog.EnumerateLiveSubspeciesTraitIds(),
|
|
SubspeciesTraitInterestCatalog.AuthoredIds);
|
|
AppendLibraryDomain(
|
|
tsv,
|
|
"subspecies_traits",
|
|
ActivityAssetCatalog.EnumerateLiveSubspeciesTraitIds(),
|
|
subspTraits,
|
|
SubspeciesTraitInterestCatalog.GetOrFallback);
|
|
|
|
CatalogCoverageDiff genes = CatalogCoverageAudit.Diff(
|
|
"genes",
|
|
ActivityAssetCatalog.EnumerateLiveGeneIds(),
|
|
GeneInterestCatalog.AuthoredIds);
|
|
AppendLibraryDomain(tsv, "genes", ActivityAssetCatalog.EnumerateLiveGeneIds(), genes, GeneInterestCatalog.GetOrFallback);
|
|
|
|
CatalogCoverageDiff phenotypes = CatalogCoverageAudit.Diff(
|
|
"phenotypes",
|
|
ActivityAssetCatalog.EnumerateLivePhenotypeIds(),
|
|
PhenotypeInterestCatalog.AuthoredIds);
|
|
AppendLibraryDomain(
|
|
tsv,
|
|
"phenotypes",
|
|
ActivityAssetCatalog.EnumerateLivePhenotypeIds(),
|
|
phenotypes,
|
|
PhenotypeInterestCatalog.GetOrFallback);
|
|
|
|
CatalogCoverageDiff worldLaws = CatalogCoverageAudit.Diff(
|
|
"world_laws",
|
|
ActivityAssetCatalog.EnumerateLiveWorldLawIds(),
|
|
WorldLawInterestCatalog.AuthoredIds);
|
|
AppendLibraryDomain(
|
|
tsv,
|
|
"world_laws",
|
|
ActivityAssetCatalog.EnumerateLiveWorldLawIds(),
|
|
worldLaws,
|
|
WorldLawInterestCatalog.GetOrFallback);
|
|
|
|
CatalogCoverageDiff biomes = CatalogCoverageAudit.Diff(
|
|
"biomes",
|
|
ActivityAssetCatalog.EnumerateLiveBiomeIds(),
|
|
BiomeInterestCatalog.AuthoredIds);
|
|
AppendLibraryDomain(tsv, "biomes", ActivityAssetCatalog.EnumerateLiveBiomeIds(), biomes, BiomeInterestCatalog.GetOrFallback);
|
|
|
|
int relMissing = 0;
|
|
int relTotal = 0;
|
|
foreach (string id in RelationshipEventCatalog.AuthoredIds)
|
|
{
|
|
relTotal++;
|
|
DiscreteEventEntry entry = RelationshipEventCatalog.GetOrFallback(id);
|
|
bool ok = RelationshipEventCatalog.HasAuthored(id) && !entry.IsFallback;
|
|
if (!ok)
|
|
{
|
|
relMissing++;
|
|
}
|
|
|
|
tsv.Append("relationship\t").Append(id).Append('\t')
|
|
.Append(ok ? "1" : "0").Append('\t')
|
|
.Append(entry.OwnsCamera).Append('\t')
|
|
.Append(entry.EventStrength.ToString("0.#")).Append('\t')
|
|
.Append(ok ? "ok" : "missing_authored").AppendLine();
|
|
}
|
|
|
|
CatalogCoverageAudit.WriteReport(outputDirectory, "domain_event_audit.tsv", tsv.ToString());
|
|
|
|
bool passed = plots.Passed && eras.Passed && books.Passed && traits.Passed
|
|
&& spells.Passed && powers.Passed && decisions.Passed && items.Passed
|
|
&& subspTraits.Passed && genes.Passed && phenotypes.Passed
|
|
&& worldLaws.Passed && biomes.Passed
|
|
&& relMissing == 0 && relTotal > 0;
|
|
string detail =
|
|
$"{plots.Detail}; {eras.Detail}; {books.Detail}; {traits.Detail}; "
|
|
+ $"{spells.Detail}; {powers.Detail}; {decisions.Detail}; {items.Detail}; "
|
|
+ $"{subspTraits.Detail}; {genes.Detail}; {phenotypes.Detail}; "
|
|
+ $"{worldLaws.Detail}; {biomes.Detail}; relationship: authored={relTotal} missing={relMissing}";
|
|
return new DomainEventAuditResult { Passed = passed, Detail = detail };
|
|
}
|
|
|
|
private static void AppendLibraryDomain(
|
|
StringBuilder tsv,
|
|
string domain,
|
|
IEnumerable<string> liveIds,
|
|
CatalogCoverageDiff diff,
|
|
Func<string, DiscreteEventEntry> lookup)
|
|
{
|
|
foreach (string id in liveIds)
|
|
{
|
|
DiscreteEventEntry entry = lookup(id);
|
|
bool has = !entry.IsFallback;
|
|
tsv.Append(domain).Append('\t').Append(id).Append('\t')
|
|
.Append(has ? "1" : "0").Append('\t')
|
|
.Append(entry.OwnsCamera).Append('\t')
|
|
.Append(entry.EventStrength.ToString("0.#")).Append('\t')
|
|
.Append(has ? "ok" : "missing_authored").AppendLine();
|
|
}
|
|
|
|
foreach (string id in diff.OrphanIds)
|
|
{
|
|
tsv.Append(domain).Append('\t').Append(id).Append("\t1\t\t0\torphan_authored").AppendLine();
|
|
}
|
|
}
|
|
}
|