feat(home-dialog): seed file + importer + bootstrap hookup
Mirrors banners pattern: clear-and-rewrite from per-table JSON seed. Ships one entry pointing at parent_gacha_id 80032 to match the 2026-06-03 prod capture. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
14
SVSim.Bootstrap/Data/seeds/home-dialogs.json
Normal file
14
SVSim.Bootstrap/Data/seeds/home-dialogs.json
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"id": 1,
|
||||||
|
"title_text_id": "HomeDialog_0066",
|
||||||
|
"image": "home_dialog_000312",
|
||||||
|
"button_list": [
|
||||||
|
{ "button_text_id": "HomeDialog_0002", "scene": "card_pack", "status": "80032" }
|
||||||
|
],
|
||||||
|
"begin_time": "2026-06-01 02:00:00",
|
||||||
|
"end_time": "2026-07-01 01:59:59",
|
||||||
|
"type": 1,
|
||||||
|
"priority": 0
|
||||||
|
}
|
||||||
|
]
|
||||||
@@ -46,6 +46,41 @@ public class MyPageGlobalsImporter
|
|||||||
return seed.Count;
|
return seed.Count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task<int> ImportHomeDialogsAsync(SVSimDbContext context, string seedDir)
|
||||||
|
{
|
||||||
|
var seed = SeedLoader.LoadList<HomeDialogSeed>(Path.Combine(seedDir, "home-dialogs.json"));
|
||||||
|
if (seed.Count == 0)
|
||||||
|
{
|
||||||
|
Console.WriteLine("[MyPageGlobalsImporter] No home-dialog seed rows; skipping.");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear-and-rewrite — same semantics as banners. Seed file is authoritative.
|
||||||
|
var existing = await context.HomeDialogEntries.ToListAsync();
|
||||||
|
context.HomeDialogEntries.RemoveRange(existing);
|
||||||
|
|
||||||
|
foreach (var s in seed)
|
||||||
|
{
|
||||||
|
context.HomeDialogEntries.Add(new HomeDialogEntry
|
||||||
|
{
|
||||||
|
Id = s.Id,
|
||||||
|
TitleTextId = s.TitleTextId,
|
||||||
|
Image = s.Image,
|
||||||
|
ButtonListJson = s.ButtonList.ValueKind == JsonValueKind.Undefined
|
||||||
|
? "[]"
|
||||||
|
: JsonSerializer.Serialize(s.ButtonList),
|
||||||
|
BeginTime = ImporterBase.ParseWireDateTime(s.BeginTime),
|
||||||
|
EndTime = ImporterBase.ParseWireDateTime(s.EndTime),
|
||||||
|
Type = s.Type,
|
||||||
|
Priority = s.Priority,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
await context.SaveChangesAsync();
|
||||||
|
Console.WriteLine($"[MyPageGlobalsImporter] HomeDialogs: -{existing.Count}/+{seed.Count}");
|
||||||
|
return seed.Count;
|
||||||
|
}
|
||||||
|
|
||||||
public async Task<int> ImportColosseumAsync(SVSimDbContext context, string seedDir)
|
public async Task<int> ImportColosseumAsync(SVSimDbContext context, string seedDir)
|
||||||
{
|
{
|
||||||
var s = SeedLoader.LoadObject<ColosseumSeed>(Path.Combine(seedDir, "colosseum.json"));
|
var s = SeedLoader.LoadObject<ColosseumSeed>(Path.Combine(seedDir, "colosseum.json"));
|
||||||
|
|||||||
16
SVSim.Bootstrap/Models/Seed/HomeDialogSeed.cs
Normal file
16
SVSim.Bootstrap/Models/Seed/HomeDialogSeed.cs
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
using System.Text.Json;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
namespace SVSim.Bootstrap.Models.Seed;
|
||||||
|
|
||||||
|
public sealed class HomeDialogSeed
|
||||||
|
{
|
||||||
|
[JsonPropertyName("id")] public int Id { get; set; }
|
||||||
|
[JsonPropertyName("title_text_id")] public string TitleTextId { get; set; } = "";
|
||||||
|
[JsonPropertyName("image")] public string Image { get; set; } = "";
|
||||||
|
[JsonPropertyName("button_list")] public JsonElement ButtonList { get; set; }
|
||||||
|
[JsonPropertyName("begin_time")] public string BeginTime { get; set; } = "";
|
||||||
|
[JsonPropertyName("end_time")] public string EndTime { get; set; } = "";
|
||||||
|
[JsonPropertyName("type")] public int? Type { get; set; }
|
||||||
|
[JsonPropertyName("priority")] public int Priority { get; set; }
|
||||||
|
}
|
||||||
@@ -115,6 +115,7 @@ public static class Program
|
|||||||
await mypage.ImportSealedAsync(context, opts.SeedDir);
|
await mypage.ImportSealedAsync(context, opts.SeedDir);
|
||||||
await mypage.ImportMasterPointRankingPeriodAsync(context, opts.SeedDir);
|
await mypage.ImportMasterPointRankingPeriodAsync(context, opts.SeedDir);
|
||||||
await mypage.ImportSpecialDeckFormatsAsync(context, opts.SeedDir);
|
await mypage.ImportSpecialDeckFormatsAsync(context, opts.SeedDir);
|
||||||
|
await mypage.ImportHomeDialogsAsync(context, opts.SeedDir);
|
||||||
|
|
||||||
await new DefaultDeckImporter().ImportAsync(context, opts.SeedDir);
|
await new DefaultDeckImporter().ImportAsync(context, opts.SeedDir);
|
||||||
await new PackImporter().ImportAsync(context, opts.SeedDir);
|
await new PackImporter().ImportAsync(context, opts.SeedDir);
|
||||||
|
|||||||
@@ -157,6 +157,53 @@ public class MyPageGlobalsImporterTests
|
|||||||
"SealedSeason singleton must remain a single row on re-run");
|
"SealedSeason singleton must remain a single row on re-run");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task Imports_home_dialogs_from_seed_file()
|
||||||
|
{
|
||||||
|
using var factory = new SVSimTestFactory();
|
||||||
|
using var scope = factory.Services.CreateScope();
|
||||||
|
var db = scope.ServiceProvider.GetRequiredService<SVSimDbContext>();
|
||||||
|
|
||||||
|
var importer = new MyPageGlobalsImporter();
|
||||||
|
await importer.ImportHomeDialogsAsync(db, SeedDir);
|
||||||
|
|
||||||
|
var rows = await db.HomeDialogEntries.OrderBy(e => e.Id).ToListAsync();
|
||||||
|
Assert.That(rows.Count, Is.GreaterThan(0), "seed must contain at least one home dialog");
|
||||||
|
|
||||||
|
var first = rows[0];
|
||||||
|
Assert.That(first.TitleTextId, Is.Not.Empty);
|
||||||
|
Assert.That(first.Image, Is.Not.Empty);
|
||||||
|
Assert.That(first.ButtonListJson, Does.StartWith("["),
|
||||||
|
"button_list must round-trip as a JSON array string");
|
||||||
|
Assert.That(first.EndTime, Is.GreaterThan(first.BeginTime));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task Home_dialogs_are_clear_and_rewrite()
|
||||||
|
{
|
||||||
|
using var factory = new SVSimTestFactory();
|
||||||
|
using var scope = factory.Services.CreateScope();
|
||||||
|
var db = scope.ServiceProvider.GetRequiredService<SVSimDbContext>();
|
||||||
|
|
||||||
|
db.HomeDialogEntries.Add(new HomeDialogEntry
|
||||||
|
{
|
||||||
|
Id = 999,
|
||||||
|
TitleTextId = "legacy",
|
||||||
|
Image = "legacy_image",
|
||||||
|
ButtonListJson = "[]",
|
||||||
|
BeginTime = DateTime.UtcNow.AddYears(-1),
|
||||||
|
EndTime = DateTime.UtcNow.AddYears(-1).AddDays(1),
|
||||||
|
});
|
||||||
|
await db.SaveChangesAsync();
|
||||||
|
|
||||||
|
var importer = new MyPageGlobalsImporter();
|
||||||
|
await importer.ImportHomeDialogsAsync(db, SeedDir);
|
||||||
|
|
||||||
|
var stale = await db.HomeDialogEntries.FindAsync(999);
|
||||||
|
Assert.That(stale, Is.Null,
|
||||||
|
"ImportHomeDialogsAsync must clear-and-rewrite — pre-existing legacy rows must be removed");
|
||||||
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public async Task Master_point_ranking_period_leaves_existing_rows_untouched()
|
public async Task Master_point_ranking_period_leaves_existing_rows_untouched()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -276,6 +276,7 @@ internal sealed class SVSimTestFactory : WebApplicationFactory<Program>
|
|||||||
await mypage.ImportSealedAsync(ctx, seedDir);
|
await mypage.ImportSealedAsync(ctx, seedDir);
|
||||||
await mypage.ImportMasterPointRankingPeriodAsync(ctx, seedDir);
|
await mypage.ImportMasterPointRankingPeriodAsync(ctx, seedDir);
|
||||||
await mypage.ImportSpecialDeckFormatsAsync(ctx, seedDir);
|
await mypage.ImportSpecialDeckFormatsAsync(ctx, seedDir);
|
||||||
|
await mypage.ImportHomeDialogsAsync(ctx, seedDir);
|
||||||
|
|
||||||
await new DefaultDeckImporter().ImportAsync(ctx, seedDir);
|
await new DefaultDeckImporter().ImportAsync(ctx, seedDir);
|
||||||
await new PackImporter().ImportAsync(ctx, seedDir);
|
await new PackImporter().ImportAsync(ctx, seedDir);
|
||||||
|
|||||||
Reference in New Issue
Block a user