using NeonSprawl.Server.Game.Encounters; using NeonSprawl.Server.Game.Factions; using NeonSprawl.Server.Game.Items; using NeonSprawl.Server.Game.PositionState; using NeonSprawl.Server.Game.Rewards; using NeonSprawl.Server.Game.Skills; namespace NeonSprawl.Server.Game.Contracts; /// Maps POST /game/players/{{id}}/contracts/issue (NEO-151). public static class ContractIssueApi { public static WebApplication MapContractIssueApi(this WebApplication app) { app.MapPost( "/game/players/{id}/contracts/issue", (string id, ContractIssueRequest? body, IPositionStateStore positions, IContractTemplateRegistry templateRegistry, IEncounterDefinitionRegistry encounterRegistry, IItemDefinitionRegistry itemRegistry, ISkillDefinitionRegistry skillRegistry, IFactionDefinitionRegistry factionRegistry, IContractInstanceStore instanceStore, IFactionStandingStore standingStore, IRewardDeliveryStore deliveryStore, TimeProvider timeProvider) => { var trimmedId = id.Trim(); if (trimmedId.Length == 0 || !positions.TryGetPosition(trimmedId, out _)) { return Results.NotFound(); } if (body is null || body.SchemaVersion != ContractIssueRequest.CurrentSchemaVersion) { return Results.BadRequest(); } var normalizedTemplateId = ContractInstanceIds.NormalizeTemplateId(body.TemplateId); var normalizedSeedBucket = ContractInstanceIds.NormalizeSeedBucket(body.SeedBucket); var normalizedBodyPlayerId = ContractInstanceIds.NormalizePlayerId(body.PlayerId); if (normalizedTemplateId.Length == 0 || normalizedSeedBucket.Length == 0 || normalizedBodyPlayerId.Length == 0) { return Results.BadRequest(); } var normalizedPathPlayerId = ContractInstanceIds.NormalizePlayerId(trimmedId); if (!string.Equals(normalizedBodyPlayerId, normalizedPathPlayerId, StringComparison.Ordinal)) { return Results.BadRequest(); } var result = ContractGeneratorOperations.TryIssue( trimmedId, normalizedTemplateId, normalizedSeedBucket, body.ZoneDifficultyBand, templateRegistry, encounterRegistry, itemRegistry, skillRegistry, factionRegistry, instanceStore, standingStore, timeProvider); return Results.Json( MapIssueResponse(trimmedId, result, templateRegistry, deliveryStore)); }); return app; } internal static ContractIssueResponse MapIssueResponse( string playerId, ContractIssueOperationResult result, IContractTemplateRegistry templateRegistry, IRewardDeliveryStore deliveryStore) { ContractInstanceRowJson? contract = null; if (result.Snapshot is { } snapshot) { contract = ContractListApi.MapInstanceRow( playerId, snapshot, templateRegistry, deliveryStore, result.EncounterTemplateId); } return new ContractIssueResponse { Issued = result.Success, ReasonCode = result.ReasonCode, Contract = contract, }; } }