Class leader fixes
This commit is contained in:
@@ -68,7 +68,6 @@ public class GlobalsImporter
|
|||||||
if (deckInfo.HasValue)
|
if (deckInfo.HasValue)
|
||||||
{
|
{
|
||||||
total += await ImportDefaultDecks(context, deckInfo.Value);
|
total += await ImportDefaultDecks(context, deckInfo.Value);
|
||||||
total += await ImportDefaultLeaderSkinSettings(context, deckInfo.Value);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (paymentItemList.HasValue)
|
if (paymentItemList.HasValue)
|
||||||
@@ -716,28 +715,6 @@ public class GlobalsImporter
|
|||||||
return created + updated;
|
return created + updated;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------- Deck/info: Default Leader Skin Settings ----------
|
|
||||||
|
|
||||||
private async Task<int> ImportDefaultLeaderSkinSettings(SVSimDbContext context, JsonElement deckInfo)
|
|
||||||
{
|
|
||||||
if (!deckInfo.TryGetProperty("user_leader_skin_setting_list", out var info) || info.ValueKind != JsonValueKind.Object) return 0;
|
|
||||||
|
|
||||||
var existing = await context.DefaultLeaderSkinSettings.ToDictionaryAsync(e => e.Id);
|
|
||||||
int created = 0, updated = 0;
|
|
||||||
foreach (var kv in info.EnumerateObject())
|
|
||||||
{
|
|
||||||
if (!int.TryParse(kv.Name, out int classId)) continue;
|
|
||||||
var v = kv.Value;
|
|
||||||
var entry = existing.TryGetValue(classId, out var ex) ? ex : new DefaultLeaderSkinSettingEntry { Id = classId };
|
|
||||||
entry.IsRandomLeaderSkin = GetInt(v, "is_random_leader_skin");
|
|
||||||
entry.LeaderSkinId = GetInt(v, "leader_skin_id");
|
|
||||||
if (ex is null) { context.DefaultLeaderSkinSettings.Add(entry); created++; }
|
|
||||||
else updated++;
|
|
||||||
}
|
|
||||||
Console.WriteLine($"[GlobalsImporter] DefaultLeaderSkinSettings: +{created}/~{updated}");
|
|
||||||
return created + updated;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---------- Payment: Item list (Steam/PC storefront, dict-keyed by store_product_id) ----------
|
// ---------- Payment: Item list (Steam/PC storefront, dict-keyed by store_product_id) ----------
|
||||||
|
|
||||||
private async Task<int> ImportPaymentItems(SVSimDbContext context, JsonElement payment)
|
private async Task<int> ImportPaymentItems(SVSimDbContext context, JsonElement payment)
|
||||||
|
|||||||
2809
SVSim.Database/Migrations/20260526132106_DropDefaultLeaderSkinSettings.Designer.cs
generated
Normal file
2809
SVSim.Database/Migrations/20260526132106_DropDefaultLeaderSkinSettings.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,38 @@
|
|||||||
|
using System;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace SVSim.Database.Migrations
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public partial class DropDefaultLeaderSkinSettings : Migration
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "DefaultLeaderSkinSettings");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "DefaultLeaderSkinSettings",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
Id = table.Column<int>(type: "integer", nullable: false),
|
||||||
|
ClassId = table.Column<int>(type: "integer", nullable: false),
|
||||||
|
DateCreated = table.Column<DateTime>(type: "timestamp with time zone", nullable: false),
|
||||||
|
DateUpdated = table.Column<DateTime>(type: "timestamp with time zone", nullable: true),
|
||||||
|
IsRandomLeaderSkin = table.Column<int>(type: "integer", nullable: false),
|
||||||
|
LeaderSkinId = table.Column<int>(type: "integer", nullable: false)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("PK_DefaultLeaderSkinSettings", x => x.Id);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -824,31 +824,6 @@ namespace SVSim.Database.Migrations
|
|||||||
b.ToTable("DefaultDecks");
|
b.ToTable("DefaultDecks");
|
||||||
});
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("SVSim.Database.Models.DefaultLeaderSkinSettingEntry", b =>
|
|
||||||
{
|
|
||||||
b.Property<int>("Id")
|
|
||||||
.HasColumnType("integer");
|
|
||||||
|
|
||||||
b.Property<int>("ClassId")
|
|
||||||
.HasColumnType("integer");
|
|
||||||
|
|
||||||
b.Property<DateTime>("DateCreated")
|
|
||||||
.HasColumnType("timestamp with time zone");
|
|
||||||
|
|
||||||
b.Property<DateTime?>("DateUpdated")
|
|
||||||
.HasColumnType("timestamp with time zone");
|
|
||||||
|
|
||||||
b.Property<int>("IsRandomLeaderSkin")
|
|
||||||
.HasColumnType("integer");
|
|
||||||
|
|
||||||
b.Property<int>("LeaderSkinId")
|
|
||||||
.HasColumnType("integer");
|
|
||||||
|
|
||||||
b.HasKey("Id");
|
|
||||||
|
|
||||||
b.ToTable("DefaultLeaderSkinSettings");
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("SVSim.Database.Models.DegreeEntry", b =>
|
modelBuilder.Entity("SVSim.Database.Models.DegreeEntry", b =>
|
||||||
{
|
{
|
||||||
b.Property<int>("Id")
|
b.Property<int>("Id")
|
||||||
|
|||||||
@@ -1,13 +0,0 @@
|
|||||||
using SVSim.Database.Common;
|
|
||||||
|
|
||||||
namespace SVSim.Database.Models;
|
|
||||||
|
|
||||||
/// <summary>One row per class: which leader skin is default and whether random rotation is on.</summary>
|
|
||||||
public class DefaultLeaderSkinSettingEntry : BaseEntity<int>
|
|
||||||
{
|
|
||||||
public int ClassId { get => Id; set => Id = value; }
|
|
||||||
|
|
||||||
public int IsRandomLeaderSkin { get; set; }
|
|
||||||
|
|
||||||
public int LeaderSkinId { get; set; }
|
|
||||||
}
|
|
||||||
@@ -41,9 +41,6 @@ public class GlobalsRepository : IGlobalsRepository
|
|||||||
public Task<List<DefaultDeckEntry>> GetDefaultDecks() =>
|
public Task<List<DefaultDeckEntry>> GetDefaultDecks() =>
|
||||||
_dbContext.DefaultDecks.AsNoTracking().ToListAsync();
|
_dbContext.DefaultDecks.AsNoTracking().ToListAsync();
|
||||||
|
|
||||||
public Task<List<DefaultLeaderSkinSettingEntry>> GetDefaultLeaderSkinSettings() =>
|
|
||||||
_dbContext.DefaultLeaderSkinSettings.AsNoTracking().ToListAsync();
|
|
||||||
|
|
||||||
public Task<ArenaSeasonConfig?> GetCurrentArenaSeason() =>
|
public Task<ArenaSeasonConfig?> GetCurrentArenaSeason() =>
|
||||||
_dbContext.ArenaSeasons.AsNoTracking().FirstOrDefaultAsync(e => e.Id == 1);
|
_dbContext.ArenaSeasons.AsNoTracking().FirstOrDefaultAsync(e => e.Id == 1);
|
||||||
|
|
||||||
|
|||||||
@@ -13,7 +13,6 @@ public interface IGlobalsRepository
|
|||||||
Task<List<MyRotationAbilityEntry>> GetMyRotationAbilities();
|
Task<List<MyRotationAbilityEntry>> GetMyRotationAbilities();
|
||||||
Task<List<AvatarAbilityEntry>> GetAvatarAbilities();
|
Task<List<AvatarAbilityEntry>> GetAvatarAbilities();
|
||||||
Task<List<DefaultDeckEntry>> GetDefaultDecks();
|
Task<List<DefaultDeckEntry>> GetDefaultDecks();
|
||||||
Task<List<DefaultLeaderSkinSettingEntry>> GetDefaultLeaderSkinSettings();
|
|
||||||
Task<ArenaSeasonConfig?> GetCurrentArenaSeason();
|
Task<ArenaSeasonConfig?> GetCurrentArenaSeason();
|
||||||
Task<List<SpotCardEntry>> GetSpotCards();
|
Task<List<SpotCardEntry>> GetSpotCards();
|
||||||
Task<List<ReprintedCardEntry>> GetReprintedCards();
|
Task<List<ReprintedCardEntry>> GetReprintedCards();
|
||||||
|
|||||||
@@ -44,7 +44,6 @@ public class SVSimDbContext : DbContext
|
|||||||
public DbSet<MyRotationAbilityEntry> MyRotationAbilities => Set<MyRotationAbilityEntry>();
|
public DbSet<MyRotationAbilityEntry> MyRotationAbilities => Set<MyRotationAbilityEntry>();
|
||||||
public DbSet<AvatarAbilityEntry> AvatarAbilities => Set<AvatarAbilityEntry>();
|
public DbSet<AvatarAbilityEntry> AvatarAbilities => Set<AvatarAbilityEntry>();
|
||||||
public DbSet<DefaultDeckEntry> DefaultDecks => Set<DefaultDeckEntry>();
|
public DbSet<DefaultDeckEntry> DefaultDecks => Set<DefaultDeckEntry>();
|
||||||
public DbSet<DefaultLeaderSkinSettingEntry> DefaultLeaderSkinSettings => Set<DefaultLeaderSkinSettingEntry>();
|
|
||||||
public DbSet<ArenaSeasonConfig> ArenaSeasons => Set<ArenaSeasonConfig>();
|
public DbSet<ArenaSeasonConfig> ArenaSeasons => Set<ArenaSeasonConfig>();
|
||||||
public DbSet<SpotCardEntry> SpotCards => Set<SpotCardEntry>();
|
public DbSet<SpotCardEntry> SpotCards => Set<SpotCardEntry>();
|
||||||
public DbSet<ReprintedCardEntry> ReprintedCards => Set<ReprintedCardEntry>();
|
public DbSet<ReprintedCardEntry> ReprintedCards => Set<ReprintedCardEntry>();
|
||||||
|
|||||||
@@ -125,7 +125,7 @@ public class DeckController : SVSimController
|
|||||||
}),
|
}),
|
||||||
UserLeaderSkinSettingList = viewerClasses.ToDictionary(
|
UserLeaderSkinSettingList = viewerClasses.ToDictionary(
|
||||||
vc => vc.Id.ToString(),
|
vc => vc.Id.ToString(),
|
||||||
vc => new DefaultLeaderSkinSetting
|
vc => new UserLeaderSkinSetting
|
||||||
{
|
{
|
||||||
ClassId = vc.Id,
|
ClassId = vc.Id,
|
||||||
IsRandomLeaderSkin = 0, // random-skin mode (per-class shuffle pool) not yet persisted
|
IsRandomLeaderSkin = 0, // random-skin mode (per-class shuffle pool) not yet persisted
|
||||||
|
|||||||
@@ -46,10 +46,11 @@ public class DeckListResponse
|
|||||||
[Key("default_deck_list")] public Dictionary<string, DefaultDeck> DefaultDeckList { get; set; } = new();
|
[Key("default_deck_list")] public Dictionary<string, DefaultDeck> DefaultDeckList { get; set; } = new();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Default leader skin per class, keyed by class_id as string.
|
/// Per-class leader skin setting (active skin id) for the requesting viewer, keyed by
|
||||||
|
/// class_id as string.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[JsonPropertyName("user_leader_skin_setting_list")]
|
[JsonPropertyName("user_leader_skin_setting_list")]
|
||||||
[Key("user_leader_skin_setting_list")] public Dictionary<string, DefaultLeaderSkinSetting> UserLeaderSkinSettingList { get; set; } = new();
|
[Key("user_leader_skin_setting_list")] public Dictionary<string, UserLeaderSkinSetting> UserLeaderSkinSettingList { get; set; } = new();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Trial / tutorial-specific decks. Prod emits this on <c>/deck/info</c> (All format) but
|
/// Trial / tutorial-specific decks. Prod emits this on <c>/deck/info</c> (All format) but
|
||||||
|
|||||||
@@ -4,12 +4,13 @@ using System.Text.Json.Serialization;
|
|||||||
namespace SVSim.EmulatedEntrypoint.Models.Dtos;
|
namespace SVSim.EmulatedEntrypoint.Models.Dtos;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Default leader skin per class (8 entries — one per class). Surfaced under
|
/// Per-class entry of <c>/deck/info data.user_leader_skin_setting_list</c>. Per-viewer state:
|
||||||
/// <c>/deck/info data.user_leader_skin_setting_list</c>. Despite the <c>user_</c> prefix on the
|
/// each viewer's class-level "active leader skin" preference, used as a fallback when a deck
|
||||||
/// wire, this is GLOBAL data (same for every viewer) — naming is the client's, not ours.
|
/// has <c>leader_skin_id == 0</c>. Sourced from <c>ViewerClassData.LeaderSkin</c>; mutated by
|
||||||
|
/// <c>POST /leader_skin/set</c>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[MessagePackObject]
|
[MessagePackObject]
|
||||||
public class DefaultLeaderSkinSetting
|
public class UserLeaderSkinSetting
|
||||||
{
|
{
|
||||||
[JsonPropertyName("class_id")]
|
[JsonPropertyName("class_id")]
|
||||||
[Key("class_id")]
|
[Key("class_id")]
|
||||||
@@ -197,14 +197,11 @@ public class GlobalsRepositoryTests
|
|||||||
"Each starter deck should serialize multiple card IDs in card_id_array.");
|
"Each starter deck should serialize multiple card IDs in card_id_array.");
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
// Note: GetDefaultLeaderSkinSettings was removed from IGlobalsRepository in the
|
||||||
public async Task GetDefaultLeaderSkinSettings_returns_8_entries()
|
// 2026-05-26 per-viewer leader-skin refactor. /deck/info now sources
|
||||||
{
|
// user_leader_skin_setting_list from viewer.Classes (each ViewerClassData carries the
|
||||||
var (factory, repo) = await SetupAsync();
|
// active LeaderSkin), and /leader_skin/set mutates it. Coverage moved to
|
||||||
using var _ = factory;
|
// LeaderSkinControllerTests.
|
||||||
var skins = await repo.GetDefaultLeaderSkinSettings();
|
|
||||||
Assert.That(skins.Count, Is.EqualTo(8));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Note: GetGameConfiguration was removed from IGlobalsRepository in the 2026-05-24 config
|
// Note: GetGameConfiguration was removed from IGlobalsRepository in the 2026-05-24 config
|
||||||
// refactor — Rotation/Challenge/etc. now load via IGameConfigService. See
|
// refactor — Rotation/Challenge/etc. now load via IGameConfigService. See
|
||||||
|
|||||||
Reference in New Issue
Block a user