The board says the one condition out loud
The card read "when someone new opens PolHunter" and listed everyone a hunter had brought as hunting or earning, including members who joined InstantAdPay before the mission existed and can never pay a bounty. So the board promised an earning the payout code would refuse. It now says what actually qualifies: someone who has never had an InstantAdPay account. People who were already members are listed as exactly that, the match window is not claimed for them, and the counts show how many of the brought are genuinely new. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
+11
-2
@@ -162,17 +162,25 @@ function state(member) {
|
|||||||
const me = hunter(id) || { memberId: id };
|
const me = hunter(id) || { memberId: id };
|
||||||
const rows = refRows().filter(p => Number(p.memberId) === id);
|
const rows = refRows().filter(p => Number(p.memberId) === id);
|
||||||
const today = ctDay();
|
const today = ctDay();
|
||||||
|
// the same floor onFind pays by, so the card can never promise an earning it will not make
|
||||||
|
const floor = Date.parse(String(c.refNewAfter || ''));
|
||||||
|
const gateOk = Number.isFinite(floor) && floor > 0;
|
||||||
const mine = broughtBy(id).map(x => {
|
const mine = broughtBy(id).map(x => {
|
||||||
const theirFinds = store.read('payouts', []).filter(p => Number(p.memberId) === Number(x.memberId) && !p.ref && !p.prize && p.status !== 'failed');
|
const theirFinds = store.read('payouts', []).filter(p => Number(p.memberId) === Number(x.memberId) && !p.ref && !p.prize && p.status !== 'failed');
|
||||||
const paid = bountyPaidFor(x.memberId);
|
const paid = bountyPaidFor(x.memberId);
|
||||||
|
const isNew = !!(gateOk && x.joinedAt && Number(x.joinedAt) >= floor);
|
||||||
return {
|
return {
|
||||||
name: x.username || ('#' + x.memberId),
|
name: x.username || ('#' + x.memberId),
|
||||||
// when they actually joined InstantAdPay, not when this directory first noticed them:
|
// when they actually joined InstantAdPay, not when this directory first noticed them:
|
||||||
// the backfill stamped firstSeen at seeding time and made everyone look brought-in today
|
// the backfill stamped firstSeen at seeding time and made everyone look brought-in today
|
||||||
joinedAt: x.joinedAt || x.firstSeen || null,
|
joinedAt: x.joinedAt || x.firstSeen || null,
|
||||||
finds: theirFinds.length,
|
finds: theirFinds.length,
|
||||||
state: paid ? 'earning' : theirFinds.length ? 'hunting' : 'signed up, no find yet',
|
// an account that predates the mission was already a member: say so plainly rather than
|
||||||
stillNew: x.joinedAt ? (Date.now() - Number(x.joinedAt)) / 86400000 <= Number(c.refMatchDays) : false,
|
// show them as 'hunting' next to a bounty that will never arrive
|
||||||
|
isNew,
|
||||||
|
state: !isNew ? 'already a member before the mission, earns nothing'
|
||||||
|
: paid ? 'earning' : theirFinds.length ? 'hunting' : 'signed up, no find yet',
|
||||||
|
stillNew: isNew && (Date.now() - Number(x.joinedAt)) / 86400000 <= Number(c.refMatchDays),
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
return {
|
return {
|
||||||
@@ -182,6 +190,7 @@ function state(member) {
|
|||||||
matchPct: Number(c.refMatchPct),
|
matchPct: Number(c.refMatchPct),
|
||||||
matchDays: Number(c.refMatchDays),
|
matchDays: Number(c.refMatchDays),
|
||||||
brought: mine.length,
|
brought: mine.length,
|
||||||
|
broughtNew: mine.filter(x => x.isNew).length, // the only ones that can ever pay
|
||||||
broughtToday: mine.filter(x => x.joinedAt && ctDay(x.joinedAt) === today).length,
|
broughtToday: mine.filter(x => x.joinedAt && ctDay(x.joinedAt) === today).length,
|
||||||
earnedPol: round4(rows.reduce((n, p) => n + p.pol, 0)),
|
earnedPol: round4(rows.reduce((n, p) => n + p.pol, 0)),
|
||||||
earnedTodayPol: round4(rows.filter(p => p.day === today).reduce((n, p) => n + p.pol, 0)),
|
earnedTodayPol: round4(rows.filter(p => p.day === today).reduce((n, p) => n + p.pol, 0)),
|
||||||
|
|||||||
+2
-2
@@ -5,7 +5,7 @@
|
|||||||
<meta name="viewport" content="width=device-width,initial-scale=1">
|
<meta name="viewport" content="width=device-width,initial-scale=1">
|
||||||
<title>Your board · PolHunter</title>
|
<title>Your board · PolHunter</title>
|
||||||
<meta name="robots" content="noindex">
|
<meta name="robots" content="noindex">
|
||||||
<link rel="stylesheet" href="/style.css?v=16">
|
<link rel="stylesheet" href="/style.css?v=17">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div class="wrap">
|
<div class="wrap">
|
||||||
@@ -47,6 +47,6 @@
|
|||||||
<footer class="foot">Rewards are for completed missions, not income. The daily pool is limited; when it is spent, claims close until midnight Central. Cryptocurrency involves risk of loss.</footer>
|
<footer class="foot">Rewards are for completed missions, not income. The daily pool is limited; when it is spent, claims close until midnight Central. Cryptocurrency involves risk of loss.</footer>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal" id="shareModal" hidden><div class="modal-card"><button class="modal-x" id="shareClose" type="button" aria-label="Close">×</button><div id="shareBody"></div></div></div>
|
<div class="modal" id="shareModal" hidden><div class="modal-card"><button class="modal-x" id="shareClose" type="button" aria-label="Close">×</button><div id="shareBody"></div></div></div>
|
||||||
<script src="/app.js?v=16"></script>
|
<script src="/app.js?v=17"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
+3
-2
@@ -57,13 +57,14 @@
|
|||||||
return '<div class="card ref-card">'
|
return '<div class="card ref-card">'
|
||||||
+ '<span class="tag gold">Best paid</span>'
|
+ '<span class="tag gold">Best paid</span>'
|
||||||
+ '<h3>🤝 Bring a hunter</h3>'
|
+ '<h3>🤝 Bring a hunter</h3>'
|
||||||
+ '<p>Send your link. When someone new opens PolHunter and finds their first code, you get <b>' + rf.bountyPol + ' POL</b>. '
|
+ '<p>Send your link. When someone who has <b>never had an InstantAdPay account</b> joins on it, opens PolHunter and finds their first code, you get <b>' + rf.bountyPol + ' POL</b>. '
|
||||||
+ 'After that you earn <b>' + rf.matchPct + '%</b> on top of everything they find for their first ' + rf.matchDays + ' days. '
|
+ 'After that you earn <b>' + rf.matchPct + '%</b> on top of everything they find for their first ' + rf.matchDays + ' days. '
|
||||||
+ 'It comes out of our pool, never theirs.</p>'
|
+ 'It comes out of our pool, never theirs.</p>'
|
||||||
|
+ '<p class="ref-note">This pays for new people only. Someone who was already a member before this mission started earns nothing, however much they hunt.</p>'
|
||||||
+ (rf.firstBonusPol ? '<p class="ref-bonus">\u{1F947} <b>' + rf.firstBonusPol + ' POL bonus, still unclaimed.</b> It goes to the first hunter who brings someone all the way through. Nobody has yet.</p>' : '')
|
+ (rf.firstBonusPol ? '<p class="ref-bonus">\u{1F947} <b>' + rf.firstBonusPol + ' POL bonus, still unclaimed.</b> It goes to the first hunter who brings someone all the way through. Nobody has yet.</p>' : '')
|
||||||
+ '<div class="codebox"><input id="refLink" readonly value="' + esc(link) + '"><button class="btn pol" id="refCopy">Copy</button></div>'
|
+ '<div class="codebox"><input id="refLink" readonly value="' + esc(link) + '"><button class="btn pol" id="refCopy">Copy</button></div>'
|
||||||
+ '<p style="margin-top:10px"><span class="range">' + today + ' brought today</span> '
|
+ '<p style="margin-top:10px"><span class="range">' + today + ' brought today</span> '
|
||||||
+ '<span style="color:var(--dim);font-size:12px">· ' + total + ' all time · ' + rf.earnedPol + ' POL earned</span></p>'
|
+ '<span style="color:var(--dim);font-size:12px">· ' + total + ' all time, ' + (rf.broughtNew || 0) + ' of them new · ' + rf.earnedPol + ' POL earned</span></p>'
|
||||||
+ (people ? '<div class="ref-list">' + people + '</div>' : '<p style="color:var(--dim);font-size:12px;margin-top:10px">Nobody yet. One message is all it takes.</p>')
|
+ (people ? '<div class="ref-list">' + people + '</div>' : '<p style="color:var(--dim);font-size:12px;margin-top:10px">Nobody yet. One message is all it takes.</p>')
|
||||||
+ '<div class="ref-watch"><button class="btn ghost sm" type="button" id="refPlay">▶ Watch: how it works (46s)</button></div>'
|
+ '<div class="ref-watch"><button class="btn ghost sm" type="button" id="refPlay">▶ Watch: how it works (46s)</button></div>'
|
||||||
+ '</div>';
|
+ '</div>';
|
||||||
|
|||||||
@@ -137,3 +137,7 @@ textarea{width:100%;padding:12px 14px;border-radius:12px;border:1px solid var(--
|
|||||||
.ref-watch{margin-top:14px}
|
.ref-watch{margin-top:14px}
|
||||||
.ref-video{width:100%;max-width:560px;border-radius:14px;display:block;background:#000}
|
.ref-video{width:100%;max-width:560px;border-radius:14px;display:block;background:#000}
|
||||||
.ref-bonus{margin-top:10px;padding:9px 12px;border:1px solid rgba(243,190,67,.38);border-radius:12px;background:rgba(243,190,67,.07);font-size:13.5px;color:var(--ink)}
|
.ref-bonus{margin-top:10px;padding:9px 12px;border:1px solid rgba(243,190,67,.38);border-radius:12px;background:rgba(243,190,67,.07);font-size:13.5px;color:var(--ink)}
|
||||||
|
|
||||||
|
/* the one condition that decides whether a referral ever pays, said plainly on the card itself
|
||||||
|
rather than discovered when the bounty does not arrive (Marty, 2026-09-23) */
|
||||||
|
.ref-note{margin-top:8px;font-size:12.5px;line-height:1.45;color:var(--dim)}
|
||||||
|
|||||||
Reference in New Issue
Block a user