Practice/deck editing mostly there
This commit is contained in:
31
SVSim.EmulatedEntrypoint/Controllers/ConfigController.cs
Normal file
31
SVSim.EmulatedEntrypoint/Controllers/ConfigController.cs
Normal file
@@ -0,0 +1,31 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using SVSim.EmulatedEntrypoint.Models.Dtos.Common;
|
||||
using SVSim.EmulatedEntrypoint.Models.Dtos.Requests;
|
||||
|
||||
namespace SVSim.EmulatedEntrypoint.Controllers;
|
||||
|
||||
/// <summary>
|
||||
/// /config/* — viewer-scoped preference toggles. Fired by the client as fire-and-forget
|
||||
/// after the deck-builder save flow (and from settings screens). Currently acknowledge-only:
|
||||
/// UserConfig is stubbed in load/index + mypage/index until a viewer-config persistence
|
||||
/// layer lands. Mirrors the set_deck_redis precedent (no-op accept).
|
||||
/// </summary>
|
||||
public class ConfigController : SVSimController
|
||||
{
|
||||
[HttpPost("update_foil_preferred")]
|
||||
public ActionResult<EmptyResponse> UpdateFoilPreferred(ConfigUpdateFoilPreferredRequest request)
|
||||
{
|
||||
if (!TryGetViewerId(out long _)) return Unauthorized();
|
||||
// TODO(viewer-config-persist): write request.IsFoilPreferred onto the viewer's config row
|
||||
// and read it back in load/index + mypage/index instead of `new UserConfig()`.
|
||||
return new EmptyResponse();
|
||||
}
|
||||
|
||||
[HttpPost("update_prize_preferred")]
|
||||
public ActionResult<EmptyResponse> UpdatePrizePreferred(ConfigUpdatePrizePreferredRequest request)
|
||||
{
|
||||
if (!TryGetViewerId(out long _)) return Unauthorized();
|
||||
// TODO(viewer-config-persist): see UpdateFoilPreferred.
|
||||
return new EmptyResponse();
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,12 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Options;
|
||||
using SVSim.Database;
|
||||
using SVSim.Database.Enums;
|
||||
using SVSim.Database.Models;
|
||||
using SVSim.Database.Repositories.Deck;
|
||||
using SVSim.Database.Repositories.Globals;
|
||||
using SVSim.EmulatedEntrypoint.Configuration;
|
||||
using SVSim.EmulatedEntrypoint.Constants;
|
||||
using SVSim.EmulatedEntrypoint.Extensions;
|
||||
using SVSim.EmulatedEntrypoint.Models.Dtos;
|
||||
@@ -20,6 +22,7 @@ public class DeckController : SVSimController
|
||||
private readonly IDeckRepository _deckRepository;
|
||||
private readonly IGlobalsRepository _globalsRepository;
|
||||
private readonly SVSimDbContext _dbContext;
|
||||
private readonly DeckOptions _deckOptions;
|
||||
|
||||
private static readonly System.Text.Json.JsonSerializerOptions JsonbReadOptions = new()
|
||||
{
|
||||
@@ -27,11 +30,32 @@ public class DeckController : SVSimController
|
||||
NumberHandling = System.Text.Json.Serialization.JsonNumberHandling.AllowReadingFromString,
|
||||
};
|
||||
|
||||
public DeckController(IDeckRepository deckRepository, IGlobalsRepository globalsRepository, SVSimDbContext dbContext)
|
||||
public DeckController(IDeckRepository deckRepository, IGlobalsRepository globalsRepository, SVSimDbContext dbContext, IOptions<DeckOptions> deckOptions)
|
||||
{
|
||||
_deckRepository = deckRepository;
|
||||
_globalsRepository = globalsRepository;
|
||||
_dbContext = dbContext;
|
||||
_deckOptions = deckOptions.Value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Pads a viewer's real deck list with empty-slot placeholders up to <see cref="DeckOptions.MaxDeckSlots"/>.
|
||||
/// Required because the client's <c>DeckUI.DeckViewData.CreateDeckViewList</c> only renders
|
||||
/// a "New Deck" tile when the response contains an entry whose <c>card_id_array</c> is empty —
|
||||
/// without padding, the player cannot create additional decks once any exist.
|
||||
/// </summary>
|
||||
private List<UserDeck> PadEmptySlots(List<UserDeck> realDecks)
|
||||
{
|
||||
var taken = realDecks.Select(d => d.DeckNumber).ToHashSet();
|
||||
var result = new List<UserDeck>(realDecks);
|
||||
for (int slot = 1; slot <= _deckOptions.MaxDeckSlots; slot++)
|
||||
{
|
||||
if (!taken.Contains(slot))
|
||||
{
|
||||
result.Add(UserDeck.CreateEmptySlot(slot));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// Request deck_format fields arrive as wire ints (MessagePack-CSharp doesn't honor STJ
|
||||
@@ -106,9 +130,9 @@ public class DeckController : SVSimController
|
||||
// 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();
|
||||
response.UserDeckRotation = PadEmptySlots(byFormat[Format.Rotation].Select(d => new UserDeck(d)).ToList());
|
||||
response.UserDeckUnlimited = PadEmptySlots(byFormat[Format.Unlimited].Select(d => new UserDeck(d)).ToList());
|
||||
response.UserDeckMyRotation = PadEmptySlots(byFormat[Format.MyRotation].Select(d => new UserDeck(d)).ToList());
|
||||
// trial_deck_list is prod-emitted on /deck/info (All format) but omitted on /deck/my_list
|
||||
// (specific format). Empty array in the 2026-05-23 prod capture.
|
||||
response.TrialDeckList = new();
|
||||
@@ -116,7 +140,7 @@ public class DeckController : SVSimController
|
||||
else
|
||||
{
|
||||
var decks = await _deckRepository.GetDecks(viewerId, requestFormat);
|
||||
response.UserDeckList = decks.Select(d => new UserDeck(d)).ToList();
|
||||
response.UserDeckList = PadEmptySlots(decks.Select(d => new UserDeck(d)).ToList());
|
||||
}
|
||||
|
||||
return response;
|
||||
@@ -163,7 +187,7 @@ public class DeckController : SVSimController
|
||||
var decks = await _deckRepository.GetDecks(viewerId, format);
|
||||
return new DeckUpdateResponse
|
||||
{
|
||||
UserDeckList = decks.Select(d => new UserDeck(d)).ToList()
|
||||
UserDeckList = PadEmptySlots(decks.Select(d => new UserDeck(d)).ToList())
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user