diff --git a/SVSim.EmulatedEntrypoint/Program.cs b/SVSim.EmulatedEntrypoint/Program.cs index ade7ac46..1f05ae5a 100644 --- a/SVSim.EmulatedEntrypoint/Program.cs +++ b/SVSim.EmulatedEntrypoint/Program.cs @@ -130,6 +130,10 @@ public class Program // Restart re-fires once per viewer — documented trade in the design spec. builder.Services.AddSingleton(); + // Loads the static card-master base64 blob from Data/ once at startup; served by + // ImmutableDataController. Singleton because the file is ~1.27 MB. + builder.Services.AddSingleton(); + #endregion builder.Services.AddBattleNode(opt => diff --git a/SVSim.EmulatedEntrypoint/Services/CardMasterPayloadProvider.cs b/SVSim.EmulatedEntrypoint/Services/CardMasterPayloadProvider.cs new file mode 100644 index 00000000..4cb3b63d --- /dev/null +++ b/SVSim.EmulatedEntrypoint/Services/CardMasterPayloadProvider.cs @@ -0,0 +1,42 @@ +using Microsoft.Extensions.Logging; + +namespace SVSim.EmulatedEntrypoint.Services; + +/// +/// Reads the static card-master blob from the app's output directory once at startup and +/// hands the cached base64 string to ImmutableDataController. Singleton because the +/// file is ~1.27 MB and gzip-decoding it on every request would burn CPU for no benefit. +/// +public interface ICardMasterPayloadProvider +{ + /// True when the blob loaded successfully and serving is enabled. + bool IsAvailable { get; } + + /// The verbatim base64 string ready for data.card_master. + string Base64Blob { get; } +} + +public sealed class CardMasterPayloadProvider : ICardMasterPayloadProvider +{ + // Filename is pinned to the captured snapshot's date. When swapping the blob, update + // this constant AND the hash in CardMasterConfig in the same change. + private const string BlobFileName = "card_master_2026-06-03.txt"; + + public bool IsAvailable { get; } + public string Base64Blob { get; } + + public CardMasterPayloadProvider(ILogger log) + { + var path = Path.Combine(AppContext.BaseDirectory, "Data", BlobFileName); + if (!File.Exists(path)) + { + log.LogWarning("Card-master blob missing at {Path} — /immutable_data/card_master will 503.", path); + Base64Blob = ""; + IsAvailable = false; + return; + } + Base64Blob = File.ReadAllText(path).Trim(); + IsAvailable = Base64Blob.Length > 0; + log.LogInformation("Loaded card-master blob ({Bytes} base64 chars).", Base64Blob.Length); + } +}