neon-sprawl/server/NeonSprawl.Server/Game/Contracts/IContractInstanceStore.cs

46 lines
2.0 KiB
C#

namespace NeonSprawl.Server.Game.Contracts;
/// <summary>
/// Persisted per-player contract instances (NEO-146).
/// Contract generator/completion orchestrators (NEO-147, NEO-149) consume this interface — not HTTP directly.
/// </summary>
public interface IContractInstanceStore
{
/// <summary>True when mutations for <paramref name="playerId"/> are allowed (dev bucket or Postgres <c>player_position</c> row).</summary>
bool CanWritePlayer(string playerId);
/// <summary>Missing row ⇒ <c>false</c>.</summary>
bool TryGet(string playerId, string contractInstanceId, out ContractInstanceState snapshot);
/// <summary>At most one active row per player; missing active ⇒ <c>false</c>.</summary>
bool TryGetActiveForPlayer(string playerId, out ContractInstanceState snapshot);
/// <summary>
/// Creates an active instance. Returns <c>false</c> when player not writable, ids invalid, duplicate instance id,
/// or player already has an active contract.
/// </summary>
bool TryCreateActive(
string playerId,
string contractInstanceId,
string templateId,
string seedBucket,
DateTimeOffset issuedAt,
out ContractInstanceState snapshot);
/// <summary>First completion returns <c>true</c>; replays return <c>false</c> without changing <see cref="ContractInstanceState.CompletedAt"/>.</summary>
bool TryMarkComplete(
string playerId,
string contractInstanceId,
DateTimeOffset completedAt,
out ContractInstanceState snapshot);
/// <summary>Dev fixture only — removes one instance row; idempotent when absent.</summary>
bool TryClearInstance(string playerId, string contractInstanceId);
/// <summary>
/// Active row first (when present), then up to <paramref name="maxCompletedRows"/> completed rows
/// for the player ordered by <see cref="ContractInstanceState.IssuedAt"/> descending.
/// </summary>
IReadOnlyList<ContractInstanceState> ListForPlayer(string playerId, int maxCompletedRows);
}