89 lines
3.7 KiB
TypeScript
89 lines
3.7 KiB
TypeScript
import {
|
|
createSaphoTruthOrder,
|
|
passSaphoTruthOrder,
|
|
quoteSaphoTruthOrder,
|
|
reorderSaphoTruthOrder,
|
|
SaphoTruthOrderError,
|
|
validateSaphoTruthOrder,
|
|
type SaphoTruthOrderFrame,
|
|
type SaphoTruthOrderMode,
|
|
type SaphoTruthOrderRequest,
|
|
type SaphoTruthOrderResult,
|
|
} from './sapho-truth-order';
|
|
|
|
/** Public owner identities only: no card, token face or hidden choice is stored. */
|
|
export type SaphoArrivalOrder = {
|
|
frame: SaphoTruthOrderFrame;
|
|
queue: [{ player: string }, { player: string }];
|
|
};
|
|
export type SaphoArrivalOrderResult = { order: SaphoArrivalOrder; done: boolean };
|
|
|
|
type Entry = { player: string };
|
|
|
|
function check(condition: unknown, message: string): asserts condition {
|
|
if (!condition) throw new SaphoTruthOrderError(message);
|
|
}
|
|
|
|
/** The original pair is already in provisional storm order. */
|
|
export function createSaphoArrivalOrder(event: string, firstOwner: string, secondOwner: string): SaphoArrivalOrder {
|
|
const queue: SaphoArrivalOrder['queue'] = [{ player: firstOwner }, { player: secondOwner }];
|
|
const frame = createSaphoTruthOrder(queue, event);
|
|
check(frame && frame.holders.length === 2, 'Arrival ordering requires two distinct original owners.');
|
|
return { frame, queue };
|
|
}
|
|
|
|
function validateShape(order: SaphoArrivalOrder): void {
|
|
check(order && typeof order === 'object' && !Array.isArray(order) &&
|
|
Array.isArray(order.queue) && order.queue.length === 2 && order.frame &&
|
|
Array.isArray(order.frame.holders) && order.frame.holders.length === 2,
|
|
'Retain the two original arrival owners and ordering frame.');
|
|
validateSaphoTruthOrder(order.frame, order.queue);
|
|
check(order.queue[0].player === order.frame.holders[0] ||
|
|
order.frame.protectedFirst === order.queue[0].player ||
|
|
order.frame.protectedLast === order.queue[1].player,
|
|
'The reordered arrival must retain its original Sapho choice.');
|
|
}
|
|
|
|
/** Match a saved frame to the unchanged public parent, not a caller-supplied
|
|
* card or a newly sampled token. The queue may differ from original order only
|
|
* through a recorded Sapho choice. */
|
|
export function validateSaphoArrivalOrder(
|
|
order: SaphoArrivalOrder, event: string, originalOwners: readonly string[], selectedFirst: string,
|
|
): void {
|
|
validateShape(order);
|
|
check(order.frame.event === event && Array.isArray(originalOwners) && originalOwners.length === 2 &&
|
|
order.frame.holders[0] === originalOwners[0] && order.frame.holders[1] === originalOwners[1] &&
|
|
order.queue[0].player === selectedFirst,
|
|
'The arrival ordering no longer matches its original owners, event or selected first reaction.');
|
|
}
|
|
|
|
export function quoteSaphoArrivalOrder(order: SaphoArrivalOrder, player: string) {
|
|
validateShape(order);
|
|
return quoteSaphoTruthOrder(order.frame, order.queue, player);
|
|
}
|
|
|
|
function detach(result: SaphoTruthOrderResult<Entry>): SaphoArrivalOrderResult {
|
|
check(result.queue.length === 2, 'Retain both arrival owners.');
|
|
return {
|
|
order: {
|
|
frame: { ...result.frame, holders: [...result.frame.holders], passed: [...result.frame.passed] },
|
|
queue: [{ player: result.queue[0].player }, { player: result.queue[1].player }],
|
|
},
|
|
done: result.done,
|
|
};
|
|
}
|
|
|
|
/** Passing and using Sapho both retain the complete public receipt, even after
|
|
* the last owner has responded, so later continuation validates the order. */
|
|
export function passSaphoArrivalOrder(order: SaphoArrivalOrder, request: SaphoTruthOrderRequest): SaphoArrivalOrderResult {
|
|
validateShape(order);
|
|
return detach(passSaphoTruthOrder(order.frame, order.queue, request));
|
|
}
|
|
|
|
export function reorderSaphoArrivalOrder(
|
|
order: SaphoArrivalOrder, request: SaphoTruthOrderRequest & { mode: SaphoTruthOrderMode },
|
|
): SaphoArrivalOrderResult {
|
|
validateShape(order);
|
|
return detach(reorderSaphoTruthOrder(order.frame, order.queue, request));
|
|
}
|