Recruiter badge: the card for bringing someone who actually hunts
Matches the existing set at 1080x1080, same violet and gold, same laurel wreath and floating Polygon coins, with a blank ribbon for the hunter's name. Inside the wreath, four anonymous figures wired together as a team tree, one at the top lighting up the three below it. Awarded on a bounty rather than a match, so it means a person they brought turned up and found their first code, not merely that an existing hunter kept hunting. It shows locked on the board until then, which is the point. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
+1
-1
@@ -9,7 +9,7 @@ const { spawn } = require('child_process');
|
||||
|
||||
let PUBLIC_DIR = null, CACHE_DIR = null, FONT;
|
||||
// per-badge ribbon position (fraction of height); tuned to the artwork
|
||||
const ART = { first: 0.734, hunter: 0.753, tracker: 0.715, sweep: 0.689, lucky: 0.753, streak: 0.702, top: 0.725 };
|
||||
const ART = { first: 0.734, hunter: 0.753, tracker: 0.715, sweep: 0.689, lucky: 0.753, streak: 0.702, top: 0.725, recruiter: 0.834 };
|
||||
|
||||
function init(opts) { PUBLIC_DIR = opts.publicDir; CACHE_DIR = path.join(opts.dataDir, 'badges'); try { fs.mkdirSync(CACHE_DIR, { recursive: true }); } catch (e) {} }
|
||||
function artFile(id) { return path.join(PUBLIC_DIR, 'badges', 'badge-' + id + '.jpg'); }
|
||||
|
||||
@@ -19,6 +19,7 @@ const BADGES = [
|
||||
{ id: 'lucky', name: 'Lucky Find', icon: '\u{1F48E}', why: 'one drip of 0.4 POL or more' },
|
||||
{ id: 'streak', name: 'On a Streak', icon: '\u{1F525}', why: 'finds on three days in a row' },
|
||||
{ id: 'top', name: 'Top Hunter', icon: '\u{1F3C6}', why: 'won a weekly prize as #1' },
|
||||
{ id: 'recruiter', name: 'Recruiter', icon: '\u{1F91D}', why: 'brought a hunter who found their first code' },
|
||||
];
|
||||
const PRIZE_DEFAULTS = { weeklyPrizes: [3, 2, 1], weeklyMinFinds: 10 };
|
||||
function prizeRules() { const s = rewards.settings(); return { pol: Array.isArray(s.weeklyPrizes) && s.weeklyPrizes.length ? s.weeklyPrizes.map(Number) : PRIZE_DEFAULTS.weeklyPrizes, minFinds: Number(s.weeklyMinFinds) > 0 ? Number(s.weeklyMinFinds) : PRIZE_DEFAULTS.weeklyMinFinds }; }
|
||||
@@ -49,6 +50,8 @@ function badgesFor(memberId, list) {
|
||||
const days = new Set(mine.map(p => p.day));
|
||||
for (const d of days) { if (days.has(dayMinus(d, 1)) && days.has(dayMinus(d, 2))) { out.add('streak'); break; } }
|
||||
if (store.read('payouts', []).some(p => p.memberId === Number(memberId) && p.prize && p.prize.rank === 1 && p.status !== 'failed')) out.add('top');
|
||||
// earned by a bounty, not a match: someone they brought turned up and found their first code
|
||||
if (store.read('payouts', []).some(p => p.memberId === Number(memberId) && p.ref && p.ref.kind === 'bounty' && p.status !== 'failed')) out.add('recruiter');
|
||||
return BADGES.filter(b => out.has(b.id));
|
||||
}
|
||||
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 200 KiB |
Reference in New Issue
Block a user