diff --git a/SVSim.EmulatedEntrypoint/Controllers/ArenaTwoPickController.cs b/SVSim.EmulatedEntrypoint/Controllers/ArenaTwoPickController.cs new file mode 100644 index 0000000..109b1c8 --- /dev/null +++ b/SVSim.EmulatedEntrypoint/Controllers/ArenaTwoPickController.cs @@ -0,0 +1,60 @@ +using Microsoft.AspNetCore.Mvc; +using SVSim.EmulatedEntrypoint.Models.Dtos.Requests.ArenaTwoPick; +using SVSim.EmulatedEntrypoint.Services; + +namespace SVSim.EmulatedEntrypoint.Controllers; + +[Route("arena_two_pick")] +public class ArenaTwoPickController : SVSimController +{ + private readonly IArenaTwoPickService _svc; + public ArenaTwoPickController(IArenaTwoPickService svc) => _svc = svc; + + [HttpPost("top")] + public async Task Top([FromBody] TopRequest _) + { + if (!TryGetViewerId(out var vid)) return Unauthorized(); + return Ok(await _svc.GetTopAsync(vid)); + } + + [HttpPost("entry")] + public async Task Entry([FromBody] EntryRequest req) + { + if (!TryGetViewerId(out var vid)) return Unauthorized(); + return await GuardAsync(() => _svc.EntryAsync(vid, req.ConsumeItemType)); + } + + [HttpPost("class_choose")] + public async Task ClassChoose([FromBody] ClassChooseRequest req) + { + if (!TryGetViewerId(out var vid)) return Unauthorized(); + return await GuardAsync(() => _svc.ChooseClassAsync(vid, req.ClassId)); + } + + [HttpPost("card_choose")] + public async Task CardChoose([FromBody] CardChooseRequest req) + { + if (!TryGetViewerId(out var vid)) return Unauthorized(); + return await GuardAsync(() => _svc.ChooseCardAsync(vid, req.SelectedId)); + } + + [HttpPost("retire")] + public async Task Retire([FromBody] RetireRequest _) + { + if (!TryGetViewerId(out var vid)) return Unauthorized(); + return await GuardAsync(() => _svc.RetireAsync(vid)); + } + + [HttpPost("finish")] + public async Task Finish([FromBody] FinishRequest _) + { + if (!TryGetViewerId(out var vid)) return Unauthorized(); + return await GuardAsync(() => _svc.FinishAsync(vid)); + } + + private async Task GuardAsync(Func> action) + { + try { return Ok(await action()); } + catch (ArenaTwoPickException ex) { return BadRequest(new { error_code = ex.ErrorCode }); } + } +} diff --git a/SVSim.EmulatedEntrypoint/Models/Dtos/Requests/ArenaTwoPick/CardChooseRequest.cs b/SVSim.EmulatedEntrypoint/Models/Dtos/Requests/ArenaTwoPick/CardChooseRequest.cs new file mode 100644 index 0000000..f31def4 --- /dev/null +++ b/SVSim.EmulatedEntrypoint/Models/Dtos/Requests/ArenaTwoPick/CardChooseRequest.cs @@ -0,0 +1,10 @@ +using System.Text.Json.Serialization; +using MessagePack; + +namespace SVSim.EmulatedEntrypoint.Models.Dtos.Requests.ArenaTwoPick; + +[MessagePackObject] +public class CardChooseRequest +{ + [JsonPropertyName("selected_id")] [Key("selected_id")] public long SelectedId { get; set; } +} diff --git a/SVSim.EmulatedEntrypoint/Models/Dtos/Requests/ArenaTwoPick/ClassChooseRequest.cs b/SVSim.EmulatedEntrypoint/Models/Dtos/Requests/ArenaTwoPick/ClassChooseRequest.cs new file mode 100644 index 0000000..03a3650 --- /dev/null +++ b/SVSim.EmulatedEntrypoint/Models/Dtos/Requests/ArenaTwoPick/ClassChooseRequest.cs @@ -0,0 +1,10 @@ +using System.Text.Json.Serialization; +using MessagePack; + +namespace SVSim.EmulatedEntrypoint.Models.Dtos.Requests.ArenaTwoPick; + +[MessagePackObject] +public class ClassChooseRequest +{ + [JsonPropertyName("class_id")] [Key("class_id")] public int ClassId { get; set; } +} diff --git a/SVSim.EmulatedEntrypoint/Models/Dtos/Requests/ArenaTwoPick/EntryRequest.cs b/SVSim.EmulatedEntrypoint/Models/Dtos/Requests/ArenaTwoPick/EntryRequest.cs new file mode 100644 index 0000000..86ef614 --- /dev/null +++ b/SVSim.EmulatedEntrypoint/Models/Dtos/Requests/ArenaTwoPick/EntryRequest.cs @@ -0,0 +1,10 @@ +using System.Text.Json.Serialization; +using MessagePack; + +namespace SVSim.EmulatedEntrypoint.Models.Dtos.Requests.ArenaTwoPick; + +[MessagePackObject] +public class EntryRequest +{ + [JsonPropertyName("consume_item_type")] [Key("consume_item_type")] public int ConsumeItemType { get; set; } +} diff --git a/SVSim.EmulatedEntrypoint/Models/Dtos/Requests/ArenaTwoPick/FinishRequest.cs b/SVSim.EmulatedEntrypoint/Models/Dtos/Requests/ArenaTwoPick/FinishRequest.cs new file mode 100644 index 0000000..eb8b528 --- /dev/null +++ b/SVSim.EmulatedEntrypoint/Models/Dtos/Requests/ArenaTwoPick/FinishRequest.cs @@ -0,0 +1,6 @@ +using MessagePack; + +namespace SVSim.EmulatedEntrypoint.Models.Dtos.Requests.ArenaTwoPick; + +[MessagePackObject] +public class FinishRequest { } diff --git a/SVSim.EmulatedEntrypoint/Models/Dtos/Requests/ArenaTwoPick/RetireRequest.cs b/SVSim.EmulatedEntrypoint/Models/Dtos/Requests/ArenaTwoPick/RetireRequest.cs new file mode 100644 index 0000000..c808a9f --- /dev/null +++ b/SVSim.EmulatedEntrypoint/Models/Dtos/Requests/ArenaTwoPick/RetireRequest.cs @@ -0,0 +1,6 @@ +using MessagePack; + +namespace SVSim.EmulatedEntrypoint.Models.Dtos.Requests.ArenaTwoPick; + +[MessagePackObject] +public class RetireRequest { } diff --git a/SVSim.EmulatedEntrypoint/Models/Dtos/Requests/ArenaTwoPick/TopRequest.cs b/SVSim.EmulatedEntrypoint/Models/Dtos/Requests/ArenaTwoPick/TopRequest.cs new file mode 100644 index 0000000..adc13be --- /dev/null +++ b/SVSim.EmulatedEntrypoint/Models/Dtos/Requests/ArenaTwoPick/TopRequest.cs @@ -0,0 +1,10 @@ +using System.Text.Json.Serialization; +using MessagePack; + +namespace SVSim.EmulatedEntrypoint.Models.Dtos.Requests.ArenaTwoPick; + +[MessagePackObject] +public class TopRequest +{ + [JsonPropertyName("mode")] [Key("mode")] public int Mode { get; set; } +} diff --git a/SVSim.UnitTests/Controllers/ArenaTwoPickControllerTests.cs b/SVSim.UnitTests/Controllers/ArenaTwoPickControllerTests.cs new file mode 100644 index 0000000..2e33383 --- /dev/null +++ b/SVSim.UnitTests/Controllers/ArenaTwoPickControllerTests.cs @@ -0,0 +1,29 @@ +using System.Net; +using System.Net.Http.Json; +using SVSim.UnitTests.Infrastructure; + +namespace SVSim.UnitTests.Controllers; + +public class ArenaTwoPickControllerTests +{ + [Test] + public async Task Top_unauthenticated_returns_401() + { + using var factory = new SVSimTestFactory(); + using var client = factory.CreateClient(); + var resp = await client.PostAsync("/arena_two_pick/top", JsonContent.Create(new { mode = 0 })); + Assert.That(resp.StatusCode, Is.EqualTo(HttpStatusCode.Unauthorized)); + } + + [Test] + public async Task Top_authed_with_no_run_returns_entry_info_null() + { + using var factory = new SVSimTestFactory(); + var viewerId = await factory.SeedViewerAsync(); + using var client = factory.CreateAuthenticatedClient(viewerId); + var resp = await client.PostAsync("/arena_two_pick/top", JsonContent.Create(new { mode = 0 })); + Assert.That(resp.StatusCode, Is.EqualTo(HttpStatusCode.OK)); + var body = await resp.Content.ReadAsStringAsync(); + StringAssert.Contains("\"entry_info\":null", body); + } +}