Launch build: k=3 floor-weighted draw, three missions per hunter per day, HUNT_LIVE_AT lifts the curtain and opens outbound at the launch moment, badge photos to topic + general, toasts on the board

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
martbost
2026-09-20 05:04:24 -05:00
parent 84a923326e
commit 7b061480cb
10 changed files with 75 additions and 24 deletions
+9 -2
View File
@@ -74,8 +74,15 @@ const sleep = ms => new Promise(r => setTimeout(r, ms));
const s3 = await call('/api/my/start', { method: 'POST', body: JSON.stringify({ missionId: 'test-2' }) }); eq(s3.status, 200, 'with room in the pool the start is accepted again');
// the draw is weighted low
const rewards = require('../lib/rewards'); const draws = Array.from({ length: 4000 }, () => rewards.draw(0.05, 1));
const median = draws.sort((x, y) => x - y)[2000]; eq([draws.every(d => d >= 0.05 && d <= 1), median < 0.35], [true, true], 'the draw stays in range and its median sits low (' + median + ')');
const rewards = require('../lib/rewards'); const draws = Array.from({ length: 6000 }, () => rewards.draw(0.05, 1, 3));
const median = draws.sort((x, y) => x - y)[3000]; const mean = draws.reduce((a, b) => a + b, 0) / draws.length;
eq([draws.every(d => d >= 0.05 && d <= 1), median < 0.12, mean < 0.16, draws.some(d => d > 0.5)], [true, true, true, true], 'the k=3 draw stays in range, median ~0.09, mean ~0.13, a big drip still happens (' + median.toFixed(3) + '/' + mean.toFixed(3) + ')');
// three missions a day: with the limit set to 1, the second start of the day is refused and the board says so
await admin('/api/admin/settings', { method: 'POST', body: JSON.stringify({ missionsPerDay: 1 }) });
const bdl = await call('/api/my/board'); eq([bdl.body.daily.limit, bdl.body.daily.done, bdl.body.daily.left], [1, 1, 0], 'board: daily limit, done and left');
const sdl = await call('/api/my/start', { method: 'POST', body: JSON.stringify({ missionId: 'test-2' }) }); eq([sdl.status, sdl.body.dailyDone, /for today/.test(sdl.body.error)], [400, true, true], 'past the daily limit a start is refused with the midnight message');
await admin('/api/admin/settings', { method: 'POST', body: JSON.stringify({ missionsPerDay: 3 }) });
const h2 = await call('/health'); eq([h2.body.live, h2.body.liveAt], [true, null], 'no HUNT_LIVE_AT: live now');
// social: the find is on the leaderboard with a badge, the board carries rank and a share link,
// and a share link visit sets the referral cookie that turns sign-ups into that member's IAP join link