- MAX_LINK_DISTANCE_KM (default 500): flat cap on link length. Real Ingress scales this off portal/resonator level (up to ~655km); Regress has no leveling system to scale off of, so this is a single ceiling. - PORTAL_TIMEOUT_BLOCKS (default 2100): claims stamp the current Bitcoin block height (claimed_at_block, new migration) and expire back to neutral after this many blocks — the game's clock is block height, not wall-clock. Current height comes from mempool.space (BlockHeightService, 60s cache), same trust model as the BTC Map dependency. A background sweep actively reverts timed-out claims (tearing down their links, same as a normal recapture); claim/link routes also check inline so correctness doesn't depend on sweep timing between runs. - Pre-existing claims (already live in production) get backfilled with the real current block height once at startup rather than a guessed historical value — dry-run verified against an actual copy of the live production database before deploying. - Score now reports link count per team alongside places/fields/area (backend already computed this; only the frontend display was missing). 22 new tests (53 total): pure expiry-logic unit tests plus full claim/link/sweep integration tests using a network-free fake block-height provider (BlockHeightProvider interface + FakeBlockHeight test double).
34 lines
1.0 KiB
TypeScript
34 lines
1.0 KiB
TypeScript
import type { FastifyInstance } from 'fastify';
|
|
|
|
export default async function placesRoutes(app: FastifyInstance) {
|
|
const { db } = app.ctx;
|
|
|
|
const listPlaces = db.prepare(`
|
|
SELECT p.*, c.team AS claim_team, c.claimed_by_pubkey, c.claimed_at, c.claimed_at_block
|
|
FROM places p
|
|
LEFT JOIN claims c ON c.place_id = p.id
|
|
ORDER BY p.id
|
|
`);
|
|
const getPlace = db.prepare(`
|
|
SELECT p.*, c.team AS claim_team, c.claimed_by_pubkey, c.claimed_at, c.claimed_at_block
|
|
FROM places p
|
|
LEFT JOIN claims c ON c.place_id = p.id
|
|
WHERE p.id = ?
|
|
`);
|
|
const getLinksForPlace = db.prepare(`
|
|
SELECT * FROM links WHERE from_place_id = ? OR to_place_id = ?
|
|
`);
|
|
|
|
app.get('/api/places', async () => {
|
|
return listPlaces.all();
|
|
});
|
|
|
|
app.get('/api/places/:id', async (req, reply) => {
|
|
const id = Number((req.params as { id: string }).id);
|
|
const place = getPlace.get(id);
|
|
if (!place) return reply.code(404).send({ error: 'place not found' });
|
|
const links = getLinksForPlace.all(id, id);
|
|
return { ...place, links };
|
|
});
|
|
}
|