feat(api): POST /api/turn ticks the queue one turn; an empty queue is a free skip (#44)
This commit is contained in:
@@ -51,6 +51,32 @@ export const openApiSpec = {
|
||||
},
|
||||
},
|
||||
},
|
||||
'/api/turn': {
|
||||
post: {
|
||||
summary: 'Advance exactly one turn (manual tick)',
|
||||
description:
|
||||
"Ticks the queue one turn — no request body: every ACTIVE task ages by one, tasks that reach 0 resolve (jump, scan, ship-work or research effects land, mission checks run for what resolved) and PENDING successors auto-start in FIFO order. An empty queue is a FREE SKIP — turn +1 with nothing else changed, always 200 (the UI's NEXT TURN button is never disabled; a task that fails to resolve simply does not land its effect). Returns the same world snapshot as GET /api/world, plus the task queue after the tick.",
|
||||
operationId: 'nextTurn',
|
||||
responses: {
|
||||
200: {
|
||||
description: 'World state after the tick, plus the task queue (every task row: ACTIVE, PENDING, DONE)',
|
||||
content: {
|
||||
'application/json': {
|
||||
schema: { $ref: '#/components/schemas/TurnResult' },
|
||||
},
|
||||
},
|
||||
},
|
||||
500: {
|
||||
description: 'Internal error — no domain failures escape the tick (a failed task is silently dropped, not an error)',
|
||||
content: {
|
||||
'application/json': {
|
||||
schema: { $ref: '#/components/schemas/Error' },
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
'/api/jump': {
|
||||
post: {
|
||||
summary: 'Queue a jump to a solar system within range',
|
||||
@@ -832,6 +858,42 @@ export const openApiSpec = {
|
||||
},
|
||||
required: ['systems', 'edges', 'turn'],
|
||||
},
|
||||
TurnResult: {
|
||||
allOf: [
|
||||
{ $ref: '#/components/schemas/WorldState' },
|
||||
{
|
||||
type: 'object',
|
||||
properties: {
|
||||
tasks: {
|
||||
type: 'array',
|
||||
description:
|
||||
'Every task row after the tick — ACTIVE (decremented this turn, or auto-started this turn), PENDING (waiting for its team to free) and DONE (resolved this tick or earlier)',
|
||||
items: { $ref: '#/components/schemas/Task' },
|
||||
},
|
||||
},
|
||||
required: ['tasks'],
|
||||
},
|
||||
],
|
||||
},
|
||||
Task: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
id: { type: 'integer' },
|
||||
saveId: { type: 'integer' },
|
||||
type: { type: 'string', enum: ['JUMP', 'EXPLORE', 'SHIP_UPGRADE', 'SHIP_EXPAND', 'SHIP_BUILD', 'RESEARCH'] },
|
||||
payload: {
|
||||
type: 'string',
|
||||
description: 'JSON per type: JUMP {systemId, hops} · SHIP_UPGRADE/EXPAND {systemId} · SHIP_BUILD {type} · RESEARCH {techId} · EXPLORE {planetId}',
|
||||
},
|
||||
leadCrewId: { type: 'integer', description: 'crew.id of the team lead' },
|
||||
helpers: { type: 'array', description: 'crew.id of the supporting crew (empty when none)', items: { type: 'integer' } },
|
||||
duration: { type: 'integer' },
|
||||
remaining: { type: 'integer' },
|
||||
status: { type: 'string', enum: ['ACTIVE', 'PENDING', 'DONE'] },
|
||||
queuedAtTurn: { type: 'integer' },
|
||||
},
|
||||
required: ['id', 'saveId', 'type', 'payload', 'leadCrewId', 'helpers', 'duration', 'remaining', 'status', 'queuedAtTurn'],
|
||||
},
|
||||
JumpRequest: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
|
||||
Reference in New Issue
Block a user