fix(arena): match prod get_challenge_info wire shape; stub ranking_history
Prod /arena/get_challenge_info capture (Season 26):
- reward_step_info.reward_step_list is a Dict<string,string>
({"5":"5","10":"10","15":"15"}), not the List<int> I'd assumed
- max_reward_step is stringified
The previous stub would have parsed at the client (LitJson tolerates the
shape via indexed iteration), but cleaning to match prod exactly.
Also stubs /arena/get_challenge_ranking_history (new endpoint observed
in the same capture). Prod ships {two_pick: [], sealed: []} with no
history populated — empty lists match. Routing smoke added.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -43,6 +43,14 @@ public class ArenaController : SVSimController
|
||||
catch { /* fall back to defaults */ }
|
||||
}
|
||||
|
||||
// Default Challenge Master reward steps from prod capture: 3 milestones at 5/10/15 wins.
|
||||
var rewardSteps = new Dictionary<string, string>
|
||||
{
|
||||
["5"] = "5",
|
||||
["10"] = "10",
|
||||
["15"] = "15",
|
||||
};
|
||||
|
||||
return Ok(new GetChallengeInfoResponseDto
|
||||
{
|
||||
ChallengeName = name,
|
||||
@@ -51,9 +59,17 @@ public class ArenaController : SVSimController
|
||||
TwoPickAllWinCount = 0,
|
||||
RewardStepInfo = new RewardStepInfoDto
|
||||
{
|
||||
MaxRewardStep = 0,
|
||||
RewardStepList = new List<int>(),
|
||||
MaxRewardStep = 15,
|
||||
RewardStepList = rewardSteps,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
[HttpPost("get_challenge_ranking_history")]
|
||||
public IActionResult GetChallengeRankingHistory([FromBody] GetChallengeInfoRequest req)
|
||||
{
|
||||
if (!TryGetViewerId(out _)) return Unauthorized();
|
||||
// Prod returns {two_pick: [], sealed: []}. Stub matches.
|
||||
return Ok(new GetChallengeRankingHistoryResponseDto());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System.Text.Json.Serialization;
|
||||
using MessagePack;
|
||||
using SVSim.EmulatedEntrypoint.Models.Dtos.Common;
|
||||
|
||||
namespace SVSim.EmulatedEntrypoint.Models.Dtos.Responses.Arena;
|
||||
|
||||
@@ -32,9 +33,15 @@ public class GetChallengeInfoResponseDto
|
||||
[MessagePackObject]
|
||||
public class RewardStepInfoDto
|
||||
{
|
||||
[JsonPropertyName("max_reward_step")] [Key("max_reward_step")]
|
||||
[JsonPropertyName("max_reward_step")] [JsonConverter(typeof(StringifiedIntConverter))] [Key("max_reward_step")]
|
||||
public int MaxRewardStep { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Wire shape: dict keyed by stringified-int win count → stringified-int reward step
|
||||
/// (prod capture: <c>{"5":"5","10":"10","15":"15"}</c>). Client parser at
|
||||
/// ChallangeHistoryInfoTask.cs:43 iterates by Count + indexed value access, which works
|
||||
/// for both arrays and LitJson object-iteration order — but prod always ships the dict.
|
||||
/// </summary>
|
||||
[JsonPropertyName("reward_step_list")] [Key("reward_step_list")]
|
||||
public List<int> RewardStepList { get; set; } = new();
|
||||
public Dictionary<string, string> RewardStepList { get; set; } = new();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
using System.Text.Json.Serialization;
|
||||
using MessagePack;
|
||||
|
||||
namespace SVSim.EmulatedEntrypoint.Models.Dtos.Responses.Arena;
|
||||
|
||||
/// <summary>
|
||||
/// Wire shape for /arena/get_challenge_ranking_history. Prod returns two empty lists
|
||||
/// (two_pick + sealed) per the season-26 capture. Populated history is per-viewer + per-season
|
||||
/// ranking snapshots; not tracked locally yet.
|
||||
/// </summary>
|
||||
[MessagePackObject]
|
||||
public class GetChallengeRankingHistoryResponseDto
|
||||
{
|
||||
[JsonPropertyName("two_pick")] [Key("two_pick")]
|
||||
public List<object> TwoPick { get; set; } = new();
|
||||
|
||||
[JsonPropertyName("sealed")] [Key("sealed")]
|
||||
public List<object> Sealed { get; set; } = new();
|
||||
}
|
||||
@@ -110,6 +110,7 @@ public class RoutingSmokeTests
|
||||
[TestCase("/arena_two_pick_battle/finish")]
|
||||
[TestCase("/arena_colosseum/get_fee_info")]
|
||||
[TestCase("/arena/get_challenge_info")]
|
||||
[TestCase("/arena/get_challenge_ranking_history")]
|
||||
public async Task Authenticated_route_resolves(string path)
|
||||
{
|
||||
using var factory = new TestFactory();
|
||||
|
||||
Reference in New Issue
Block a user