feat(config): MatchingConfig section with AI-fallback threshold
Adds a [ConfigSection("Matching")] POCO carrying the
RankBattleAiFallbackThresholdSeconds tunable (default 15). Auto-picked
up by EnsureSeedDataAsync's reflection-based ConfigSection seeder.
Consumed by InProcessPairUp in a later task.
GameConfigurationJsonbTests.EnsureSeedData_writes_one_row_per_ConfigSection_with_ShippedDefaults_payload
updated to include the new Matching section in its expected keys.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
20
SVSim.Database/Models/Config/MatchingConfig.cs
Normal file
20
SVSim.Database/Models/Config/MatchingConfig.cs
Normal file
@@ -0,0 +1,20 @@
|
||||
namespace SVSim.Database.Models.Config;
|
||||
|
||||
/// <summary>
|
||||
/// Tunables for the in-process pair-up matching service. Today: just the AI-fallback
|
||||
/// threshold for rank-battle modes. The full matching-queue API is a separate spec;
|
||||
/// this config section lives alongside the placeholder.
|
||||
/// </summary>
|
||||
[ConfigSection("Matching")]
|
||||
public class MatchingConfig
|
||||
{
|
||||
/// <summary>
|
||||
/// How long (seconds) a viewer must have been parked in a PvpFirstThenAiFallback
|
||||
/// queue before their next /do_matching poll resolves to an AI battle.
|
||||
/// Defaults to 15 — matches the prod 4s pre-AIBattleStart pause plus a comfortable
|
||||
/// polling cycle.
|
||||
/// </summary>
|
||||
public int RankBattleAiFallbackThresholdSeconds { get; set; } = 15;
|
||||
|
||||
public static MatchingConfig ShippedDefaults() => new();
|
||||
}
|
||||
34
SVSim.UnitTests/Database/Config/MatchingConfigTests.cs
Normal file
34
SVSim.UnitTests/Database/Config/MatchingConfigTests.cs
Normal file
@@ -0,0 +1,34 @@
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using SVSim.Database.Models.Config;
|
||||
|
||||
namespace SVSim.UnitTests.Database.Config;
|
||||
|
||||
[TestFixture]
|
||||
public class MatchingConfigTests
|
||||
{
|
||||
[Test]
|
||||
public void Default_threshold_is_15_seconds()
|
||||
{
|
||||
var cfg = new MatchingConfig();
|
||||
Assert.That(cfg.RankBattleAiFallbackThresholdSeconds, Is.EqualTo(15));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ShippedDefaults_returns_a_new_instance_with_default_threshold()
|
||||
{
|
||||
var cfg = MatchingConfig.ShippedDefaults();
|
||||
Assert.That(cfg.RankBattleAiFallbackThresholdSeconds, Is.EqualTo(15));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Has_ConfigSection_attribute_with_name_Matching()
|
||||
{
|
||||
var attr = typeof(MatchingConfig)
|
||||
.GetCustomAttributes(typeof(ConfigSectionAttribute), false)
|
||||
.Cast<ConfigSectionAttribute>()
|
||||
.FirstOrDefault();
|
||||
Assert.That(attr, Is.Not.Null);
|
||||
Assert.That(attr!.Name, Is.EqualTo("Matching"));
|
||||
}
|
||||
}
|
||||
@@ -25,13 +25,13 @@ public class GameConfigurationJsonbTests
|
||||
var rows = await db.GameConfigs.AsNoTracking().ToListAsync();
|
||||
var byName = rows.ToDictionary(r => r.SectionName);
|
||||
|
||||
// One row per [ConfigSection]-marked POCO (11 sections today: Player, DefaultGrants,
|
||||
// One row per [ConfigSection]-marked POCO (12 sections today: Player, DefaultGrants,
|
||||
// DefaultLoadout, Challenge, Rotation, PackRates, MyRotationSchedule, Story, ResourceConfig,
|
||||
// Freeplay, ArenaTwoPick).
|
||||
// Freeplay, ArenaTwoPick, Matching).
|
||||
Assert.That(byName.Keys, Is.EquivalentTo(new[]
|
||||
{
|
||||
"Player", "DefaultGrants", "DefaultLoadout", "Challenge", "Rotation", "PackRates",
|
||||
"MyRotationSchedule", "Story", "ResourceConfig", "Freeplay", "ArenaTwoPick",
|
||||
"MyRotationSchedule", "Story", "ResourceConfig", "Freeplay", "ArenaTwoPick", "Matching",
|
||||
}));
|
||||
|
||||
var resources = JsonSerializer.Deserialize<ResourceConfig>(byName["ResourceConfig"].ValueJson)!;
|
||||
|
||||
Reference in New Issue
Block a user