From f707fb2ffbf436c5032e3d0dc0b1bcb30b49a83d Mon Sep 17 00:00:00 2001 From: gamer147 Date: Sat, 13 Jun 2026 15:32:33 -0400 Subject: [PATCH] refactor: drop unused DailyLoginBonuses table + importer The captured shape ({"1":[], "3":[], "4":[]}) is the empty-period wire echo; the client parser (LoadDetail.cs:553) only reads normal/total/ campaign. Table, entity, seed, and importer were never wired to a code path. Replaced by config-section catalog + service in the follow-up commits. --- .../Data/seeds/daily-login-bonus.json | 14 ------- .../Importers/DailyLoginBonusImporter.cs | 37 ------------------- .../Models/Seed/DailyLoginBonusSeed.cs | 11 ------ SVSim.Bootstrap/Program.cs | 1 - SVSim.Database/Models/DailyLoginBonusEntry.cs | 17 --------- .../Repositories/Globals/GlobalsRepository.cs | 3 -- .../Globals/IGlobalsRepository.cs | 1 - SVSim.Database/SVSimDbContext.cs | 1 - .../Controllers/LoadController.cs | 6 +-- .../Models/Dtos/Responses/IndexResponse.cs | 4 +- .../Importers/LoadIndexImporterTests.cs | 15 +------- .../Infrastructure/SVSimTestFactory.cs | 1 - .../Repositories/GlobalsRepositoryTests.cs | 10 ----- 13 files changed, 4 insertions(+), 117 deletions(-) delete mode 100644 SVSim.Bootstrap/Data/seeds/daily-login-bonus.json delete mode 100644 SVSim.Bootstrap/Importers/DailyLoginBonusImporter.cs delete mode 100644 SVSim.Bootstrap/Models/Seed/DailyLoginBonusSeed.cs delete mode 100644 SVSim.Database/Models/DailyLoginBonusEntry.cs diff --git a/SVSim.Bootstrap/Data/seeds/daily-login-bonus.json b/SVSim.Bootstrap/Data/seeds/daily-login-bonus.json deleted file mode 100644 index e31694c2..00000000 --- a/SVSim.Bootstrap/Data/seeds/daily-login-bonus.json +++ /dev/null @@ -1,14 +0,0 @@ -[ - { - "id": 1, - "bonus_data": [] - }, - { - "id": 3, - "bonus_data": [] - }, - { - "id": 4, - "bonus_data": [] - } -] diff --git a/SVSim.Bootstrap/Importers/DailyLoginBonusImporter.cs b/SVSim.Bootstrap/Importers/DailyLoginBonusImporter.cs deleted file mode 100644 index 1c158f1f..00000000 --- a/SVSim.Bootstrap/Importers/DailyLoginBonusImporter.cs +++ /dev/null @@ -1,37 +0,0 @@ -using System.Text.Json; -using Microsoft.EntityFrameworkCore; -using SVSim.Bootstrap.Models.Seed; -using SVSim.Database; -using SVSim.Database.Models; - -namespace SVSim.Bootstrap.Importers; - -/// -/// Idempotent upsert of daily-login-bonus campaign rows from seeds/daily-login-bonus.json. -/// bonus_data array preserved verbatim — prod observed empty arrays outside active events. -/// -public class DailyLoginBonusImporter -{ - public async Task ImportAsync(SVSimDbContext context, string seedDir) - { - var seed = SeedLoader.LoadList(Path.Combine(seedDir, "daily-login-bonus.json")); - if (seed.Count == 0) return 0; - - var existing = await context.DailyLoginBonuses.ToDictionaryAsync(e => e.Id); - int created = 0, updated = 0; - foreach (var s in seed) - { - if (s.Id == 0) continue; - var entry = existing.TryGetValue(s.Id, out var ex) ? ex : new DailyLoginBonusEntry { Id = s.Id }; - entry.BonusData = s.BonusData.ValueKind == JsonValueKind.Undefined - ? "[]" - : JsonSerializer.Serialize(s.BonusData); - if (ex is null) { context.DailyLoginBonuses.Add(entry); existing[s.Id] = entry; created++; } - else updated++; - } - - await context.SaveChangesAsync(); - Console.WriteLine($"[DailyLoginBonusImporter] +{created}/~{updated}"); - return created + updated; - } -} diff --git a/SVSim.Bootstrap/Models/Seed/DailyLoginBonusSeed.cs b/SVSim.Bootstrap/Models/Seed/DailyLoginBonusSeed.cs deleted file mode 100644 index e64ed76d..00000000 --- a/SVSim.Bootstrap/Models/Seed/DailyLoginBonusSeed.cs +++ /dev/null @@ -1,11 +0,0 @@ -using System.Text.Json; -using System.Text.Json.Serialization; - -namespace SVSim.Bootstrap.Models.Seed; - -/// Mirrors seeds/daily-login-bonus.json. bonus_data preserved verbatim. -public sealed class DailyLoginBonusSeed -{ - [JsonPropertyName("id")] public int Id { get; set; } - [JsonPropertyName("bonus_data")] public JsonElement BonusData { get; set; } -} diff --git a/SVSim.Bootstrap/Program.cs b/SVSim.Bootstrap/Program.cs index 629c91e4..5baccc63 100644 --- a/SVSim.Bootstrap/Program.cs +++ b/SVSim.Bootstrap/Program.cs @@ -94,7 +94,6 @@ public static class Program await new MissionCatalogImporter().ImportAsync(context, opts.SeedDir); await new AchievementCatalogImporter().ImportAsync(context, opts.SeedDir); await new BattlePassMonthlyMissionImporter().ImportAsync(context, opts.SeedDir); - await new DailyLoginBonusImporter().ImportAsync(context, opts.SeedDir); await new PreReleaseInfoImporter().ImportAsync(context, opts.SeedDir); await new CardListsImporter().ImportAsync(context, opts.SeedDir); await new RotationFlagUpdater().UpdateAsync(context); diff --git a/SVSim.Database/Models/DailyLoginBonusEntry.cs b/SVSim.Database/Models/DailyLoginBonusEntry.cs deleted file mode 100644 index 22dab428..00000000 --- a/SVSim.Database/Models/DailyLoginBonusEntry.cs +++ /dev/null @@ -1,17 +0,0 @@ -using System.ComponentModel.DataAnnotations.Schema; -using SVSim.Database.Common; - -namespace SVSim.Database.Models; - -/// -/// Daily login bonus campaign from /load/index data.daily_login_bonus (dict keyed by bonus_id, -/// values are arrays of bonus days). Prod observed keys {1, 3, 4} with empty arrays — recapture -/// target during active login bonus events. -/// -public class DailyLoginBonusEntry : BaseEntity -{ - public int BonusId { get => Id; set => Id = value; } - - [Column(TypeName = "jsonb")] - public string BonusData { get; set; } = "[]"; -} diff --git a/SVSim.Database/Repositories/Globals/GlobalsRepository.cs b/SVSim.Database/Repositories/Globals/GlobalsRepository.cs index 38082e2b..2f3c1375 100644 --- a/SVSim.Database/Repositories/Globals/GlobalsRepository.cs +++ b/SVSim.Database/Repositories/Globals/GlobalsRepository.cs @@ -59,9 +59,6 @@ public class GlobalsRepository : IGlobalsRepository public Task> GetBattlePassLevels() => _dbContext.BattlePassLevels.AsNoTracking().ToListAsync(); - public Task> GetDailyLoginBonus() => - _dbContext.DailyLoginBonuses.AsNoTracking().ToListAsync(); - public Task> GetBanners() => _dbContext.Banners.AsNoTracking().OrderBy(b => b.Id).ToListAsync(); diff --git a/SVSim.Database/Repositories/Globals/IGlobalsRepository.cs b/SVSim.Database/Repositories/Globals/IGlobalsRepository.cs index 503fb56b..fe14fda7 100644 --- a/SVSim.Database/Repositories/Globals/IGlobalsRepository.cs +++ b/SVSim.Database/Repositories/Globals/IGlobalsRepository.cs @@ -19,7 +19,6 @@ public interface IGlobalsRepository Task> GetUnlimitedRestrictions(); Task> GetLoadingExclusionCards(); Task> GetBattlePassLevels(); - Task> GetDailyLoginBonus(); Task> GetBanners(); Task> GetActiveHomeDialogsAsync(DateTime nowUtc); Task GetCurrentSealedSeason(); diff --git a/SVSim.Database/SVSimDbContext.cs b/SVSim.Database/SVSimDbContext.cs index a6bb4472..eb23443e 100644 --- a/SVSim.Database/SVSimDbContext.cs +++ b/SVSim.Database/SVSimDbContext.cs @@ -60,7 +60,6 @@ public class SVSimDbContext : DbContext public DbSet ViewerMissions => Set(); public DbSet ViewerAchievements => Set(); public DbSet ViewerEventCounters => Set(); - public DbSet DailyLoginBonuses => Set(); public DbSet Banners => Set(); public DbSet HomeDialogEntries => Set(); public DbSet SealedSeasons => Set(); diff --git a/SVSim.EmulatedEntrypoint/Controllers/LoadController.cs b/SVSim.EmulatedEntrypoint/Controllers/LoadController.cs index 9f1a198c..1701efba 100644 --- a/SVSim.EmulatedEntrypoint/Controllers/LoadController.cs +++ b/SVSim.EmulatedEntrypoint/Controllers/LoadController.cs @@ -229,10 +229,8 @@ public class LoadController : SVSimController MaintenanceCards = (await _globalsRepository.GetMaintenanceCards()) .Select(e => e.Id).ToList(), RedEtherOverrides = new List(), - // Optional per spec (load-index.md:247). Skeleton-seeded rows in DailyLoginBonuses table - // capture prod's empty-period shape ({"1":[], "3":[], "4":[]}); the spec-shaped DTO - // ({normal?, total?, campaign?[]}) carries nothing meaningful until an active campaign - // is captured. + // Optional per spec (load-index.md:247). Populated by ILoginBonusService (Task 6) + // when the viewer has an active bonus period. DailyLoginBonus = null, UserRankedMatches = new List(), UserRankInfo = RankFormats.Select(f => new UserRankInfo diff --git a/SVSim.EmulatedEntrypoint/Models/Dtos/Responses/IndexResponse.cs b/SVSim.EmulatedEntrypoint/Models/Dtos/Responses/IndexResponse.cs index e7db9c4e..29eb205b 100644 --- a/SVSim.EmulatedEntrypoint/Models/Dtos/Responses/IndexResponse.cs +++ b/SVSim.EmulatedEntrypoint/Models/Dtos/Responses/IndexResponse.cs @@ -150,9 +150,7 @@ public class IndexResponse /// /// Spec: optional. Shape is {normal?, total?, campaign?[]} per common/types.ts.md DailyLoginBonus. - /// Until we have an active login-bonus campaign to surface in spec shape, omit. The skeleton - /// rows in DailyLoginBonuses table (prod sent {"1":[], "3":[], "4":[]}) preserve the capture - /// for archive but don't make it into the wire response. + /// Populated by ILoginBonusService when the viewer has an active bonus period; null otherwise. /// [JsonPropertyName("daily_login_bonus")] [Key("daily_login_bonus")] diff --git a/SVSim.UnitTests/Importers/LoadIndexImporterTests.cs b/SVSim.UnitTests/Importers/LoadIndexImporterTests.cs index f54387fc..f1fb9cb0 100644 --- a/SVSim.UnitTests/Importers/LoadIndexImporterTests.cs +++ b/SVSim.UnitTests/Importers/LoadIndexImporterTests.cs @@ -8,7 +8,7 @@ namespace SVSim.UnitTests.Importers; /// /// Happy-path coverage for the load-index importer classes introduced in Stage 9B -/// (RotationConfig, MyRotation, AvatarAbility, ArenaSeason, DailyLoginBonus, +/// (RotationConfig, MyRotation, AvatarAbility, ArenaSeason, /// PreReleaseInfo). Each test instantiates the importer in isolation and verifies it inserts /// rows from the corresponding seed file under Data/seeds/. /// Idempotency, edge cases, and per-importer detail tests live in dedicated *ImporterTests files (e.g. BattlePassImporterTests). @@ -73,19 +73,6 @@ public class LoadIndexImporterTests Assert.That(row!.FormatInfo, Is.Not.EqualTo("{}"), "format_info blob must be populated from seed"); } - [Test] - public async Task DailyLoginBonusImporter_writes_bonus_rows() - { - using var factory = new SVSimTestFactory(); - using var scope = factory.Services.CreateScope(); - var db = scope.ServiceProvider.GetRequiredService(); - - await new DailyLoginBonusImporter().ImportAsync(db, SeedDir); - - Assert.That(await db.DailyLoginBonuses.CountAsync(), Is.GreaterThan(0), - "daily-login-bonus.json must produce rows"); - } - [Test] public async Task PreReleaseInfoImporter_writes_singleton() { diff --git a/SVSim.UnitTests/Infrastructure/SVSimTestFactory.cs b/SVSim.UnitTests/Infrastructure/SVSimTestFactory.cs index c7efe03a..60285309 100644 --- a/SVSim.UnitTests/Infrastructure/SVSimTestFactory.cs +++ b/SVSim.UnitTests/Infrastructure/SVSimTestFactory.cs @@ -266,7 +266,6 @@ internal class SVSimTestFactory : WebApplicationFactory await new BattlePassImporter().ImportAsync(ctx, seedDir); await new BattlePassSeasonImporter().ImportAsync(ctx, seedDir); await new BattlePassRewardImporter().ImportAsync(ctx, seedDir); - await new DailyLoginBonusImporter().ImportAsync(ctx, seedDir); await new PreReleaseInfoImporter().ImportAsync(ctx, seedDir); await new CardListsImporter().ImportAsync(ctx, seedDir); await new RotationFlagUpdater().UpdateAsync(ctx); diff --git a/SVSim.UnitTests/Repositories/GlobalsRepositoryTests.cs b/SVSim.UnitTests/Repositories/GlobalsRepositoryTests.cs index 388e97d0..a59f05db 100644 --- a/SVSim.UnitTests/Repositories/GlobalsRepositoryTests.cs +++ b/SVSim.UnitTests/Repositories/GlobalsRepositoryTests.cs @@ -80,16 +80,6 @@ public class GlobalsRepositoryTests Assert.That(levels.Count, Is.EqualTo(100)); } - [Test] - public async Task GetDailyLoginBonus_returns_three_skeleton_entries() - { - var (factory, repo) = await SetupAsync(); - using var _ = factory; - var bonuses = await repo.GetDailyLoginBonus(); - Assert.That(bonuses.Count, Is.EqualTo(3), - "Prod capture has keys {1, 3, 4} with empty arrays — skeleton presence still seeded."); - } - [Test] public async Task GetPreReleaseInfo_returns_singleton() {