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.
This commit is contained in:
@@ -1,14 +0,0 @@
|
||||
[
|
||||
{
|
||||
"id": 1,
|
||||
"bonus_data": []
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"bonus_data": []
|
||||
},
|
||||
{
|
||||
"id": 4,
|
||||
"bonus_data": []
|
||||
}
|
||||
]
|
||||
@@ -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;
|
||||
|
||||
/// <summary>
|
||||
/// Idempotent upsert of daily-login-bonus campaign rows from <c>seeds/daily-login-bonus.json</c>.
|
||||
/// <c>bonus_data</c> array preserved verbatim — prod observed empty arrays outside active events.
|
||||
/// </summary>
|
||||
public class DailyLoginBonusImporter
|
||||
{
|
||||
public async Task<int> ImportAsync(SVSimDbContext context, string seedDir)
|
||||
{
|
||||
var seed = SeedLoader.LoadList<DailyLoginBonusSeed>(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;
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace SVSim.Bootstrap.Models.Seed;
|
||||
|
||||
/// <summary>Mirrors <c>seeds/daily-login-bonus.json</c>. <c>bonus_data</c> preserved verbatim.</summary>
|
||||
public sealed class DailyLoginBonusSeed
|
||||
{
|
||||
[JsonPropertyName("id")] public int Id { get; set; }
|
||||
[JsonPropertyName("bonus_data")] public JsonElement BonusData { get; set; }
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using SVSim.Database.Common;
|
||||
|
||||
namespace SVSim.Database.Models;
|
||||
|
||||
/// <summary>
|
||||
/// 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.
|
||||
/// </summary>
|
||||
public class DailyLoginBonusEntry : BaseEntity<int>
|
||||
{
|
||||
public int BonusId { get => Id; set => Id = value; }
|
||||
|
||||
[Column(TypeName = "jsonb")]
|
||||
public string BonusData { get; set; } = "[]";
|
||||
}
|
||||
@@ -59,9 +59,6 @@ public class GlobalsRepository : IGlobalsRepository
|
||||
public Task<List<BattlePassLevelEntry>> GetBattlePassLevels() =>
|
||||
_dbContext.BattlePassLevels.AsNoTracking().ToListAsync();
|
||||
|
||||
public Task<List<DailyLoginBonusEntry>> GetDailyLoginBonus() =>
|
||||
_dbContext.DailyLoginBonuses.AsNoTracking().ToListAsync();
|
||||
|
||||
public Task<List<BannerEntry>> GetBanners() =>
|
||||
_dbContext.Banners.AsNoTracking().OrderBy(b => b.Id).ToListAsync();
|
||||
|
||||
|
||||
@@ -19,7 +19,6 @@ public interface IGlobalsRepository
|
||||
Task<List<UnlimitedRestrictionEntry>> GetUnlimitedRestrictions();
|
||||
Task<List<LoadingExclusionCardEntry>> GetLoadingExclusionCards();
|
||||
Task<List<BattlePassLevelEntry>> GetBattlePassLevels();
|
||||
Task<List<DailyLoginBonusEntry>> GetDailyLoginBonus();
|
||||
Task<List<BannerEntry>> GetBanners();
|
||||
Task<IReadOnlyList<HomeDialogEntry>> GetActiveHomeDialogsAsync(DateTime nowUtc);
|
||||
Task<SealedConfig?> GetCurrentSealedSeason();
|
||||
|
||||
@@ -60,7 +60,6 @@ public class SVSimDbContext : DbContext
|
||||
public DbSet<ViewerMission> ViewerMissions => Set<ViewerMission>();
|
||||
public DbSet<ViewerAchievement> ViewerAchievements => Set<ViewerAchievement>();
|
||||
public DbSet<ViewerEventCounter> ViewerEventCounters => Set<ViewerEventCounter>();
|
||||
public DbSet<DailyLoginBonusEntry> DailyLoginBonuses => Set<DailyLoginBonusEntry>();
|
||||
public DbSet<BannerEntry> Banners => Set<BannerEntry>();
|
||||
public DbSet<HomeDialogEntry> HomeDialogEntries => Set<HomeDialogEntry>();
|
||||
public DbSet<SealedConfig> SealedSeasons => Set<SealedConfig>();
|
||||
|
||||
@@ -229,10 +229,8 @@ public class LoadController : SVSimController
|
||||
MaintenanceCards = (await _globalsRepository.GetMaintenanceCards())
|
||||
.Select(e => e.Id).ToList(),
|
||||
RedEtherOverrides = new List<RedEtherOverride>(),
|
||||
// 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<UserRankedMatches>(),
|
||||
UserRankInfo = RankFormats.Select(f => new UserRankInfo
|
||||
|
||||
@@ -150,9 +150,7 @@ public class IndexResponse
|
||||
|
||||
/// <summary>
|
||||
/// 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.
|
||||
/// </summary>
|
||||
[JsonPropertyName("daily_login_bonus")]
|
||||
[Key("daily_login_bonus")]
|
||||
|
||||
@@ -8,7 +8,7 @@ namespace SVSim.UnitTests.Importers;
|
||||
|
||||
/// <summary>
|
||||
/// 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 <c>Data/seeds/</c>.
|
||||
/// 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<SVSimDbContext>();
|
||||
|
||||
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()
|
||||
{
|
||||
|
||||
@@ -266,7 +266,6 @@ internal class SVSimTestFactory : WebApplicationFactory<Program>
|
||||
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);
|
||||
|
||||
@@ -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()
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user