Something went wrong. Try again.
A Social Deduction / Deception Game
Something went wrong. Try again.
2.5 kB · 56 lines
TypeScript
at main
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657// Suspect-pool provider for live deduction rooms. Case generation needs a pool of ~tens of real// `SuspectAttributes` (see poolsize.ts). Fetching them from rpg.actor live takes many seconds (over-// fetch at ~50% generator yield), so we prefer the on-disk reference cache (`.poolcache.json`, the// same file the showcase/pressure-test build) and only hit the network when it's missing or too thin.// The loaded pool is held in-process so repeated room creates are instant.
import { readFile } from 'node:fs/promises'import { fileURLToPath } from 'node:url'import { dirname, join } from 'node:path'import type { SuspectAttributes } from '../../../engine/deduction/index.js'import { loadSuspectPool } from './registry.js'
const CACHE = join(dirname(fileURLToPath(import.meta.url)), '.poolcache.json')
/** How many usable suspects we want available to sample a case from. The pressure test (poolsize.ts) * puts the reliable build size well under this; a larger pool just gives more variety per draw. */const POOL_TARGET = 80
let cached: Promise<SuspectAttributes[]> | null = null
async function fromDisk(): Promise<SuspectAttributes[] | null> { try { const pool = JSON.parse(await readFile(CACHE, 'utf8')) as SuspectAttributes[] return Array.isArray(pool) && pool.length >= 10 ? pool : null } catch { return null }}
/** * The shared suspect pool, loaded once. Disk cache first (instant, real data); on a miss, fetch a * fresh pool from rpg.actor. Memoized — the first caller pays the cost, the rest await the same * promise. Throws only if both the cache is absent AND the live fetch yields too few suspects. */export function suspectPool(): Promise<SuspectAttributes[]> { if (cached) return cached cached = (async () => { const disk = await fromDisk() if (disk) { console.log(`[deduction] suspect pool: ${disk.length} from disk cache`) return disk } console.log('[deduction] suspect pool: cache miss — fetching from rpg.actor…') const res = await loadSuspectPool(POOL_TARGET) if (res.suspects.length < 10) { throw new Error(`could not build a suspect pool (only ${res.suspects.length} usable suspects)`) } console.log(`[deduction] suspect pool: ${res.suspects.length} fetched (examined ${res.examined})`) return res.suspects })() // Don't memoize a failure: let the next caller retry. cached.catch(() => { cached = null }) return cached}