import { eq, max } from 'drizzle-orm'; import type { GameDb } from './client'; import * as schema from './schema'; // v1.0.0 (ISS-105): single-player economy access — resolves the seeded local player row. As of // v1.3.0 (ISS-110) every per-player read/write goes through getPlayer/updatePlayerEconomy below; // these 'local' helpers remain ONLY for env-gated /api/test/* admin hooks that stage the SEEDED // account with no acting session. Since v1.4.0 (ISS-112) even the SSE broadcast is per-player, and // since v1.5.0 (ISS-111) shared-world job quality reads getSharedWorldReputation instead of a row. export const LOCAL_PLAYER = { id: 'local', provider: 'local', username: 'kamilkrzywda' } as const; export async function getLocalPlayer(inst: GameDb): Promise { const [row] = await inst.db.select().from(schema.players).where(eq(schema.players.id, LOCAL_PLAYER.id)); if (!row) throw new Error('local player row missing'); return row; } export async function updateLocalPlayerEconomy( inst: GameDb, patch: { cash?: number; reputation?: number }, ): Promise { await inst.db.update(schema.players).set(patch).where(eq(schema.players.id, LOCAL_PLAYER.id)); } // v1.2.0 (ISS-109), standard path since v1.3.0 (ISS-110): actions, engine delivery/top-up and // session-scoped snapshots thread the acting player's id through and read/write THAT row; the // 'local' helpers above are reserved for world-level reads with no acting session. export async function getPlayer(inst: GameDb, id: string): Promise { const [row] = await inst.db.select().from(schema.players).where(eq(schema.players.id, id)); if (!row) throw new Error(`player ${id} missing`); return row; } export async function updatePlayerEconomy( inst: GameDb, id: string, patch: { cash?: number; reputation?: number }, ): Promise { await inst.db.update(schema.players).set(patch).where(eq(schema.players.id, id)); } // v1.5.0 (ISS-111), the #101 decision point resolved: shared-world job quality is the MAX // reputation across ALL player rows — spawned pool packages scale to the best-progressed player so // nobody is stuck on low-rep jobs. 0 when there are no players (repRate floors at ×1 either way). export async function getSharedWorldReputation(inst: GameDb): Promise { const [row] = await inst.db.select({ m: max(schema.players.reputation) }).from(schema.players); return row?.m ?? 0; }