Deck list work

This commit is contained in:
gamer147
2026-05-23 19:57:34 -04:00
parent 66184b3685
commit d3b2970e11
41 changed files with 70683 additions and 81 deletions

View File

@@ -44,15 +44,34 @@ public class DeckController : SVSimController
public async Task<ActionResult<DeckListResponse>> Info(DeckInfoRequest request)
{
if (!TryGetViewerId(out long viewerId)) return Unauthorized();
var decks = await _deckRepository.GetDecks(viewerId, AsFormat(request.DeckFormat));
return await BuildDeckListResponseAsync(viewerId, AsFormat(request.DeckFormat));
}
// Globals — same shape every call; could be cached if it becomes a hotspot.
[HttpPost("my_list")]
public async Task<ActionResult<DeckListResponse>> MyList(DeckFormatRequest request)
{
if (!TryGetViewerId(out long viewerId)) return Unauthorized();
return await BuildDeckListResponseAsync(viewerId, AsFormat(request.DeckFormat));
}
/// <summary>
/// Shared hydration for <c>/deck/info</c> and <c>/deck/my_list</c> — both endpoints return the
/// same <see cref="DeckListResponse"/> DTO and the client's DeckInfoTask.Parse / DeckMyListTask.Parse
/// are identical (both call <c>DeckGroupListData(jsonData, format)</c>).
///
/// Wire shape swaps based on the request format. When the client asks for All-format
/// (<c>deck_format=0</c>), prod emits per-format keys (<c>user_deck_rotation</c>, etc.);
/// for a specific format request, prod emits a single <c>user_deck_list</c>. The client's
/// <c>DeckListUtility.ParseDeckInfoResponceData</c> branches on these two shapes, so the
/// controller mirrors it exactly.
/// </summary>
private async Task<DeckListResponse> BuildDeckListResponseAsync(long viewerId, Format requestFormat)
{
var defaultDecks = await _globalsRepository.GetDefaultDecks();
var leaderSkinSettings = await _globalsRepository.GetDefaultLeaderSkinSettings();
return new DeckListResponse
var response = new DeckListResponse
{
UserDeckList = decks.Select(d => new UserDeck(d)).ToList(),
DefaultDeckList = defaultDecks.ToDictionary(
d => d.Id.ToString(),
d => new DefaultDeck
@@ -63,6 +82,11 @@ public class DeckController : SVSimController
LeaderSkinId = d.LeaderSkinId,
DeckName = d.DeckName,
CardIdArray = System.Text.Json.JsonSerializer.Deserialize<List<long>>(d.CardIdArray, JsonbReadOptions) ?? new(),
// TODO(deck-stub): wire from real per-deck state once user maintenance / availability tracking lands.
// Prod emits is_complete_deck=1, is_available_deck=1, maintenance_card_ids=[] for the 8 starter decks.
IsCompleteDeck = 1,
IsAvailableDeck = 1,
MaintenanceCardIds = new(),
}),
UserLeaderSkinSettingList = leaderSkinSettings.ToDictionary(
s => s.Id.ToString(),
@@ -77,17 +101,25 @@ public class DeckController : SVSimController
TrialDeckList = new(),
MaintenanceCardList = new(), // sourced from same place as /load/index when wired
};
}
[HttpPost("my_list")]
public async Task<ActionResult<DeckListResponse>> MyList(DeckFormatRequest request)
{
if (!TryGetViewerId(out long viewerId)) return Unauthorized();
var decks = await _deckRepository.GetDecks(viewerId, AsFormat(request.DeckFormat));
return new DeckListResponse
if (requestFormat == Format.All)
{
UserDeckList = decks.Select(d => new UserDeck(d)).ToList()
};
// Prod's All-format response emits these three per-format lists (each [] for fresh viewers).
// The PreRotation / Crossover / Avatar siblings exist in client code but prod omits them
// for our profile; we mirror that omission and leave the nullable DTO fields unset.
var formats = new[] { Format.Rotation, Format.Unlimited, Format.MyRotation };
var byFormat = await _deckRepository.GetDecksByFormats(viewerId, formats);
response.UserDeckRotation = byFormat[Format.Rotation].Select(d => new UserDeck(d)).ToList();
response.UserDeckUnlimited = byFormat[Format.Unlimited].Select(d => new UserDeck(d)).ToList();
response.UserDeckMyRotation = byFormat[Format.MyRotation].Select(d => new UserDeck(d)).ToList();
}
else
{
var decks = await _deckRepository.GetDecks(viewerId, requestFormat);
response.UserDeckList = decks.Select(d => new UserDeck(d)).ToList();
}
return response;
}
[HttpPost("get_empty_deck_number")]