Seeding reorg
This commit is contained in:
@@ -1,10 +1,10 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace SVSim.Database.Models.Config;
|
||||
|
||||
[Owned]
|
||||
[ConfigSection("Challenge")]
|
||||
public class ChallengeConfig
|
||||
{
|
||||
public bool UseTwoPickPremiumCard { get; set; }
|
||||
public long TwoPickSleeveId { get; set; }
|
||||
|
||||
public static ChallengeConfig ShippedDefaults() => new();
|
||||
}
|
||||
|
||||
14
SVSim.Database/Models/Config/ConfigSectionAttribute.cs
Normal file
14
SVSim.Database/Models/Config/ConfigSectionAttribute.cs
Normal file
@@ -0,0 +1,14 @@
|
||||
namespace SVSim.Database.Models.Config;
|
||||
|
||||
/// <summary>
|
||||
/// Marks a POCO as a top-level GameConfig section. The <see cref="Name"/> is the storage key —
|
||||
/// it's the primary key in the <c>GameConfigs</c> table and the appsettings.json section name
|
||||
/// under <c>"GameConfig"</c>. Renaming a class is safe; renaming the section name here is a
|
||||
/// breaking change to stored data and config files.
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false)]
|
||||
public sealed class ConfigSectionAttribute : Attribute
|
||||
{
|
||||
public string Name { get; }
|
||||
public ConfigSectionAttribute(string name) => Name = name;
|
||||
}
|
||||
@@ -1,12 +1,12 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace SVSim.Database.Models.Config;
|
||||
|
||||
/// <summary>Per-viewer-registration default currency grants.</summary>
|
||||
[Owned]
|
||||
[ConfigSection("DefaultGrants")]
|
||||
public class DefaultGrantsConfig
|
||||
{
|
||||
public ulong Crystals { get; set; } = 50000;
|
||||
public ulong Rupees { get; set; } = 50000;
|
||||
public ulong Ether { get; set; } = 50000;
|
||||
|
||||
public static DefaultGrantsConfig ShippedDefaults() => new();
|
||||
}
|
||||
|
||||
@@ -1,17 +1,16 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace SVSim.Database.Models.Config;
|
||||
|
||||
/// <summary>
|
||||
/// Default cosmetic loadout ids for a newly-registered viewer. These used to be FK columns;
|
||||
/// they're now untyped longs in the jsonb tree. Validation would live in a future config-editing
|
||||
/// UI (see project-wide TODO(config-validation)).
|
||||
/// Default cosmetic loadout ids for a newly-registered viewer. Untyped longs in the jsonb tree
|
||||
/// (FK validation would live in a future config-editing UI — see TODO(config-validation)).
|
||||
/// </summary>
|
||||
[Owned]
|
||||
[ConfigSection("DefaultLoadout")]
|
||||
public class DefaultLoadoutConfig
|
||||
{
|
||||
public int DegreeId { get; set; } = 300003;
|
||||
public int EmblemId { get; set; } = 100000000;
|
||||
public int MyPageBackgroundId { get; set; } = 100000000;
|
||||
public int SleeveId { get; set; } = 3000011;
|
||||
|
||||
public static DefaultLoadoutConfig ShippedDefaults() => new();
|
||||
}
|
||||
|
||||
36
SVSim.Database/Models/Config/MyRotationScheduleConfig.cs
Normal file
36
SVSim.Database/Models/Config/MyRotationScheduleConfig.cs
Normal file
@@ -0,0 +1,36 @@
|
||||
namespace SVSim.Database.Models.Config;
|
||||
|
||||
/// <summary>
|
||||
/// Window-based schedule for the Custom Rotation (a.k.a. MyRotation) feature. Two parallel windows:
|
||||
/// <c>Gathering</c> (deck-building period) and <c>FreeBattle</c> (active play period). The client
|
||||
/// gates the format-selector button on these windows — see Wizard/MyRotationAllInfo.cs:45
|
||||
/// (<c>IsMyRotationEnable => IsWithinPeriod(FreeMatchPeriod)</c>) and Wizard/DeckListUI.cs:92.
|
||||
/// Mapped to the wire-shape <c>SpecialRotationSchedule</c> at the controller seam.
|
||||
/// <para>
|
||||
/// Shipped defaults reproduce the 2026-05-23 prod capture so a fresh install ships with the
|
||||
/// feature enabled. GlobalsImporter overwrites the DB section from any newer capture.
|
||||
/// </para>
|
||||
/// </summary>
|
||||
[ConfigSection("MyRotationSchedule")]
|
||||
public class MyRotationScheduleConfig
|
||||
{
|
||||
public ScheduleWindow Gathering { get; set; } = new()
|
||||
{
|
||||
Begin = new DateTime(2024, 5, 1, 20, 0, 0, DateTimeKind.Utc),
|
||||
End = new DateTime(2030, 6, 26, 19, 59, 59, DateTimeKind.Utc),
|
||||
};
|
||||
|
||||
public ScheduleWindow FreeBattle { get; set; } = new()
|
||||
{
|
||||
Begin = new DateTime(2024, 5, 1, 20, 0, 0, DateTimeKind.Utc),
|
||||
End = new DateTime(2030, 6, 26, 19, 59, 59, DateTimeKind.Utc),
|
||||
};
|
||||
|
||||
public static MyRotationScheduleConfig ShippedDefaults() => new();
|
||||
}
|
||||
|
||||
public class ScheduleWindow
|
||||
{
|
||||
public DateTime Begin { get; set; }
|
||||
public DateTime End { get; set; }
|
||||
}
|
||||
@@ -1,12 +1,11 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace SVSim.Database.Models.Config;
|
||||
|
||||
/// <summary>
|
||||
/// Tunables for pack-opening RNG. Defaults reproduce the original Shadowverse Classic rates
|
||||
/// exactly so the cutover from hardcoded magic numbers is zero-behavior-change.
|
||||
/// Tunables for pack-opening RNG. Property initialisers reproduce the original Shadowverse
|
||||
/// Classic main-slot rates exactly. Collection-shaped defaults (slot-8 PerSlot entry) live in
|
||||
/// <see cref="ShippedDefaults"/>, not in the initialiser — see PerSlot docstring.
|
||||
/// </summary>
|
||||
[Owned]
|
||||
[ConfigSection("PackRates")]
|
||||
public class PackRateConfig
|
||||
{
|
||||
/// <summary>
|
||||
@@ -27,21 +26,32 @@ public class PackRateConfig
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Per-slot overrides (1-based slot index) applied to all packs. A missing slot falls back
|
||||
/// to <see cref="Default"/>. Each entry is a FULL OVERRIDE, not a delta — if you change
|
||||
/// <see cref="Default"/>, existing PerSlot entries do NOT auto-recompute. The slot-8 default
|
||||
/// expresses the SV Classic "Silver-or-better guarantee" as data (Bronze=0) instead of a
|
||||
/// separate code path.
|
||||
/// Per-slot overrides keyed by 1-based slot index (stored as a list for json compatibility —
|
||||
/// Dictionary<string,T> of complex owned types is not supported). Look up by
|
||||
/// <see cref="SlotRarityWeights.Slot"/>. A missing slot falls back to <see cref="Default"/>.
|
||||
/// Each entry is a FULL OVERRIDE, not a delta — if you change <see cref="Default"/>, existing
|
||||
/// PerSlot entries do NOT auto-recompute.
|
||||
/// <para>
|
||||
/// MUST default to empty. The original EF Core 8 <c>OwnsMany</c>+<c>ToJson</c> path APPENDED
|
||||
/// jsonb rows onto whatever collection the parent's parameterless ctor produced — a non-empty
|
||||
/// initialiser here meant every config load doubled-up and the original seed silently won the
|
||||
/// <c>FirstOrDefault</c> lookup in <c>PackOpenService.ResolveWeights</c>. The EF path is gone
|
||||
/// now (config goes through <c>IGameConfigService</c> + STJ), but the rule stays: collection
|
||||
/// defaults live in <see cref="ShippedDefaults"/>, not in property initialisers.
|
||||
/// </para>
|
||||
/// </summary>
|
||||
public List<SlotRarityWeights> PerSlot { get; set; } = [];
|
||||
|
||||
/// <summary>
|
||||
/// Per-slot overrides keyed by 1-based slot index (stored as a list for EF Core 8 json
|
||||
/// compatibility — Dictionary<string,T> of complex owned types is not supported).
|
||||
/// Look up by <see cref="SlotRarityWeights.Slot"/>. A missing slot falls back to
|
||||
/// <see cref="Default"/>. Slot-8 entry expresses the SV Classic "Silver-or-better
|
||||
/// guarantee" as data (Bronze=0).
|
||||
/// Canonical SV Classic shipped defaults — what an operator gets if neither the DB nor
|
||||
/// appsettings.json supplies a PackRates section. Source of truth for the fresh-install seeder
|
||||
/// and the <c>IGameConfigService</c> inline-default tier.
|
||||
/// </summary>
|
||||
public List<SlotRarityWeights> PerSlot { get; set; } =
|
||||
[
|
||||
new() { Slot = "8", Bronze = 0, Silver = 0.7692, Gold = 0.1846, Legendary = 0.0462 },
|
||||
];
|
||||
public static PackRateConfig ShippedDefaults() => new()
|
||||
{
|
||||
PerSlot =
|
||||
{
|
||||
new SlotRarityWeights { Slot = "8", Bronze = 0, Silver = 0.7692, Gold = 0.1846, Legendary = 0.0462 },
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace SVSim.Database.Models.Config;
|
||||
|
||||
[Owned]
|
||||
[ConfigSection("Player")]
|
||||
public class PlayerConfig
|
||||
{
|
||||
public int MaxFriends { get; set; } = 20;
|
||||
|
||||
public static PlayerConfig ShippedDefaults() => new();
|
||||
}
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace SVSim.Database.Models.Config;
|
||||
|
||||
/// <summary>
|
||||
/// Time-varying season/rotation state, populated by GlobalsImporter from prod captures.
|
||||
/// </summary>
|
||||
[Owned]
|
||||
[ConfigSection("Rotation")]
|
||||
public class RotationConfig
|
||||
{
|
||||
public string TsRotationId { get; set; } = "";
|
||||
public bool IsBattlePassPeriod { get; set; }
|
||||
public bool IsBeginnerMission { get; set; }
|
||||
public int CardSetIdForResourceDlView { get; set; }
|
||||
|
||||
public static RotationConfig ShippedDefaults() => new();
|
||||
}
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace SVSim.Database.Models.Config;
|
||||
|
||||
/// <summary>
|
||||
@@ -7,11 +5,10 @@ namespace SVSim.Database.Models.Config;
|
||||
/// remainder absorbs into Bronze via the PickRarity catch-all band.
|
||||
/// <para>
|
||||
/// <see cref="Slot"/> is the 1-based slot index as a string (e.g. "8") and is used as the
|
||||
/// lookup key in <see cref="PackRateConfig.PerSlot"/>. It is empty/null for the global
|
||||
/// lookup key in <see cref="PackRateConfig.PerSlot"/>. It is null/empty for the global
|
||||
/// <see cref="PackRateConfig.Default"/> entry, which has no slot affiliation.
|
||||
/// </para>
|
||||
/// </summary>
|
||||
[Owned]
|
||||
public class SlotRarityWeights
|
||||
{
|
||||
/// <summary>1-based slot index (as a string) for entries in PerSlot. Null/empty for the Default entry.</summary>
|
||||
|
||||
Reference in New Issue
Block a user