refactor(tutorial-presents): promote static catalogue to seed-driven TutorialPresentEntries table
The five tutorial gifts every fresh viewer is given at signup used to live as a static C# array in SVSim.Database/SeedData/TutorialPresents.cs — outside the seed-JSON pipeline used by all 40+ other globals tables. Editing a gift required a code change + rebuild instead of a JSON edit + bootstrap re-run. Now authored in SVSim.Bootstrap/Data/seeds/tutorial-presents.json and loaded into a new TutorialPresentEntries table via TutorialPresentsImporter (clear-and-rewrite, mirroring HomeDialogs). ViewerRepository.RegisterAnonymousViewer reads the table at signup and projects each row into a ViewerPresent with Source="tutorial". Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
7
SVSim.Bootstrap/Data/seeds/tutorial-presents.json
Normal file
7
SVSim.Bootstrap/Data/seeds/tutorial-presents.json
Normal file
@@ -0,0 +1,7 @@
|
||||
[
|
||||
{ "present_id": "71478626", "reward_type": 1, "reward_detail_id": 0, "reward_count": 400, "item_type": null, "message": "For completing the tutorial" },
|
||||
{ "present_id": "71478627", "reward_type": 9, "reward_detail_id": 0, "reward_count": 100, "item_type": null, "message": "For completing the tutorial" },
|
||||
{ "present_id": "71478628", "reward_type": 4, "reward_detail_id": 1, "reward_count": 3, "item_type": 1, "message": "For completing the tutorial" },
|
||||
{ "present_id": "71478629", "reward_type": 4, "reward_detail_id": 80001, "reward_count": 40, "item_type": 2, "message": "For completing the tutorial" },
|
||||
{ "present_id": "71478630", "reward_type": 4, "reward_detail_id": 90001, "reward_count": 1, "item_type": 2, "message": "For completing the tutorial" }
|
||||
]
|
||||
48
SVSim.Bootstrap/Importers/TutorialPresentsImporter.cs
Normal file
48
SVSim.Bootstrap/Importers/TutorialPresentsImporter.cs
Normal file
@@ -0,0 +1,48 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using SVSim.Bootstrap.Models.Seed;
|
||||
using SVSim.Database;
|
||||
using SVSim.Database.Models;
|
||||
|
||||
namespace SVSim.Bootstrap.Importers;
|
||||
|
||||
/// <summary>
|
||||
/// Loads the tutorial-gift catalogue (<c>tutorial-presents.json</c>) into the
|
||||
/// <c>TutorialPresentEntries</c> table. Clear-and-rewrite — the seed file is authoritative;
|
||||
/// hand-edits to the table are not preserved.
|
||||
///
|
||||
/// Read side: <c>ViewerRepository.RegisterAnonymousViewer</c> reads this table and projects
|
||||
/// each row into a <c>ViewerPresent</c> with Source="tutorial" at signup time.
|
||||
/// </summary>
|
||||
public class TutorialPresentsImporter
|
||||
{
|
||||
public async Task<int> ImportAsync(SVSimDbContext context, string seedDir)
|
||||
{
|
||||
var seed = SeedLoader.LoadList<TutorialPresentSeed>(
|
||||
Path.Combine(seedDir, "tutorial-presents.json"));
|
||||
if (seed.Count == 0)
|
||||
{
|
||||
Console.WriteLine("[TutorialPresentsImporter] No tutorial-present seed rows; skipping.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
var existing = await context.TutorialPresentEntries.ToListAsync();
|
||||
context.TutorialPresentEntries.RemoveRange(existing);
|
||||
|
||||
foreach (var s in seed)
|
||||
{
|
||||
context.TutorialPresentEntries.Add(new TutorialPresentEntry
|
||||
{
|
||||
PresentId = s.PresentId,
|
||||
RewardType = s.RewardType,
|
||||
RewardDetailId = s.RewardDetailId,
|
||||
RewardCount = s.RewardCount,
|
||||
ItemType = s.ItemType,
|
||||
Message = s.Message,
|
||||
});
|
||||
}
|
||||
|
||||
await context.SaveChangesAsync();
|
||||
Console.WriteLine($"[TutorialPresentsImporter] TutorialPresentEntries: -{existing.Count}/+{seed.Count}");
|
||||
return seed.Count;
|
||||
}
|
||||
}
|
||||
13
SVSim.Bootstrap/Models/Seed/TutorialPresentSeed.cs
Normal file
13
SVSim.Bootstrap/Models/Seed/TutorialPresentSeed.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace SVSim.Bootstrap.Models.Seed;
|
||||
|
||||
public sealed class TutorialPresentSeed
|
||||
{
|
||||
[JsonPropertyName("present_id")] public string PresentId { get; set; } = "";
|
||||
[JsonPropertyName("reward_type")] public int RewardType { get; set; }
|
||||
[JsonPropertyName("reward_detail_id")] public long RewardDetailId { get; set; }
|
||||
[JsonPropertyName("reward_count")] public long RewardCount { get; set; }
|
||||
[JsonPropertyName("item_type")] public int? ItemType { get; set; }
|
||||
[JsonPropertyName("message")] public string Message { get; set; } = "";
|
||||
}
|
||||
@@ -117,6 +117,8 @@ public static class Program
|
||||
await mypage.ImportSpecialDeckFormatsAsync(context, opts.SeedDir);
|
||||
await mypage.ImportHomeDialogsAsync(context, opts.SeedDir);
|
||||
|
||||
await new TutorialPresentsImporter().ImportAsync(context, opts.SeedDir);
|
||||
|
||||
await new DefaultDeckImporter().ImportAsync(context, opts.SeedDir);
|
||||
await new PackImporter().ImportAsync(context, opts.SeedDir);
|
||||
await new PackDrawTableImporter().ImportAsync(context, opts.SeedDir);
|
||||
|
||||
Reference in New Issue
Block a user