Strategy modes: Accelerate / Pocket-a-% / Park-and-collect — one selector drives engine (pocketPct + parked terminals), table, timeline, chart, Year-1, summary cards, share URL, and single-path plan text (dual narrative removed). Tests cover all three modes.

This commit is contained in:
Claude (via Marty)
2026-07-30 22:43:03 +00:00
parent e2caf73c19
commit ee13321067
2 changed files with 171 additions and 82 deletions
+147 -82
View File
@@ -1234,6 +1234,26 @@
<option value="5">Level 5 ($1,253)</option> <option value="5">Level 5 ($1,253)</option>
</select> </select>
</div> </div>
<div class="control-group">
<label>Strategy</label>
<select id="strategyMode">
<option value="accelerate" selected>🚀 Accelerate — reinvest everything, fastest to 3× L7</option>
<option value="pocket">💰 Pocket along the way — keep part of each profit</option>
<option value="park">🏝 Park &amp; collect — stop at a level, pocket it all</option>
</select>
</div>
<div class="control-group" id="pocketPctGroup" style="display:none">
<label>Pocket how much of each cycle's profit?</label>
<select id="pocketPct">
<option value="25">25% — mostly reinvest</option>
<option value="50" selected>50% — half and half</option>
<option value="75">75% — mostly pocket (slow climb)</option>
</select>
</div>
<div class="control-group" id="parkPhaseGroup" style="display:none">
<label>Park at which level?</label>
<select id="parkPhase"></select>
</div>
<div class="checkbox-row"> <div class="checkbox-row">
<div class="checkbox-group"> <div class="checkbox-group">
<input type="checkbox" id="showReferral"> <input type="checkbox" id="showReferral">
@@ -1548,8 +1568,9 @@ const PHASE_SLOTS = {
'L5+L4': [5, 4], 'L6': [6], 'L7': [7], '3xL7': [7, 7, 7], 'L5+L4': [5, 4], 'L6': [6], 'L7': [7], '3xL7': [7, 7, 7],
}; };
function computePlan(phases) { function computePlan(phases, pocketPct = 0) {
const plan = {}; const plan = {};
const keepFrac = 1 - pocketPct / 100;
let bal = 0; let bal = 0;
const activated = new Set(); const activated = new Set();
for (let lv = 1; lv <= Math.max(...PHASE_SLOTS[phases[0]]); lv++) activated.add(lv); for (let lv = 1; lv <= Math.max(...PHASE_SLOTS[phases[0]]); lv++) activated.add(lv);
@@ -1557,6 +1578,11 @@ function computePlan(phases) {
const k = phases[i]; const k = phases[i];
const p = HYBRIDS[k]; const p = HYBRIDS[k];
if (k === '3xL7') { plan[k] = { cycles: 1, months: 0.63 }; break; } if (k === '3xL7') { plan[k] = { cycles: 1, months: 0.63 }; break; }
if (i === phases.length - 1) {
// Parked terminal: they stop climbing here and collect indefinitely.
plan[k] = { cycles: 1, months: 0.63, parked: true };
break;
}
const nextSlots = [...PHASE_SLOTS[phases[i + 1]]]; const nextSlots = [...PHASE_SLOTS[phases[i + 1]]];
const carried = []; const carried = [];
for (const lv of PHASE_SLOTS[k]) { for (const lv of PHASE_SLOTS[k]) {
@@ -1571,10 +1597,10 @@ function computePlan(phases) {
} }
const carriedCamp = carried.reduce((sum, lv) => sum + LEVELS[lv - 1].camp, 0); const carriedCamp = carried.reduce((sum, lv) => sum + LEVELS[lv - 1].camp, 0);
let cycles = 0; let cycles = 0;
while (cycles < 200) { while (cycles < 500) {
cycles++; cycles++;
if (bal + p.payout - carriedCamp >= cost) { bal += p.payout - carriedCamp - cost; break; } if (bal + p.payout - carriedCamp >= cost) { bal += p.payout - carriedCamp - cost; break; }
bal += p.profit; bal += p.profit * keepFrac;
} }
plan[k] = { cycles, months: Math.round(cycles * p.daysPer / 30.4 * 10) / 10 }; plan[k] = { cycles, months: Math.round(cycles * p.daysPer / 30.4 * 10) / 10 };
} }
@@ -1582,8 +1608,8 @@ function computePlan(phases) {
} }
// Per-sequence phase info: PDF-verified money constants + derived cycles/months. // Per-sequence phase info: PDF-verified money constants + derived cycles/months.
function phaseInfo(phases) { function phaseInfo(phases, pocketPct = 0) {
const plan = computePlan(phases); const plan = computePlan(phases, pocketPct);
const out = {}; const out = {};
for (const k of phases) out[k] = { ...HYBRIDS[k], ...plan[k] }; for (const k of phases) out[k] = { ...HYBRIDS[k], ...plan[k] };
return out; return out;
@@ -1608,26 +1634,25 @@ function getPhaseSequence(effectiveStart) {
return ['L1-only','L2+L1','L3+L1','L4+L3','L5+L4','L6','L7','3xL7']; return ['L1-only','L2+L1','L3+L1','L4+L3','L5+L4','L6','L7','3xL7'];
} }
function estimateMonths(phases) { function estimateMonths(phases, pocketPct = 0) {
const PI = phaseInfo(phases); const PI = phaseInfo(phases, pocketPct);
let totalDays = 0; let totalDays = 0;
for (const k of phases) { for (const k of phases) {
if (k === '3xL7') break; if (k === '3xL7' || PI[k].parked) break;
totalDays += PI[k].cycles * PI[k].daysPer; totalDays += PI[k].cycles * PI[k].daysPer;
} }
return Math.round(totalDays / 30.4 * 10) / 10; return Math.round(totalDays / 30.4 * 10) / 10;
} }
function estimateYear1Cum(phases, commPct, giftLevel) { function estimateYear1Cum(phases, commPct, giftLevel, pocketPct = 0) {
// Includes endgame cycles that land inside year 1 — well-funded starts // Includes endgame (or parked-level) cycles that land inside year 1.
// reach 3x L7 within months and the old cutoff undercounted them. const PI = phaseInfo(phases, pocketPct);
const PI = phaseInfo(phases);
let cum = 0; let cum = 0;
let daysLeft = 365; let daysLeft = 365;
for (const k of phases) { for (const k of phases) {
const p = PI[k]; const p = PI[k];
const yourCut = p.payout * (commPct / 100); const yourCut = p.payout * (commPct / 100);
if (k === '3xL7') { if (k === '3xL7' || p.parked) {
cum += Math.max(0, Math.floor(daysLeft / p.daysPer)) * yourCut; cum += Math.max(0, Math.floor(daysLeft / p.daysPer)) * yourCut;
break; break;
} }
@@ -1639,22 +1664,23 @@ function estimateYear1Cum(phases, commPct, giftLevel) {
return Math.round(cum); return Math.round(cum);
} }
function buildMonthlyTimeline(phases, commPct) { function buildMonthlyTimeline(phases, commPct, pocketPct = 0) {
// One row per 19-day cycle, stamped with the real calendar month it lands // One row per 19-day cycle, stamped with the real calendar month it lands
// in (the old version advanced a full month per cycle — 60% too slow). // in (the old version advanced a full month per cycle — 60% too slow).
const PI = phaseInfo(phases); const PI = phaseInfo(phases, pocketPct);
const months = []; const months = [];
let cumComm = 0, days = 0; let cumComm = 0, days = 0;
for (const k of phases) { for (const k of phases) {
const p = PI[k]; const p = PI[k];
const yourCut = p.payout * (commPct / 100); const yourCut = p.payout * (commPct / 100);
const n = k === '3xL7' ? 10 : p.cycles; const terminal = k === '3xL7' || p.parked;
const n = terminal ? 10 : p.cycles;
for (let c = 0; c < n; c++) { for (let c = 0; c < n; c++) {
days += p.daysPer; days += p.daysPer;
cumComm += yourCut; cumComm += yourCut;
months.push({ m: Math.ceil(days / 30.4), phase: c === 0 ? p.label : '', prof: Math.round(p.profit), comm: Math.round(yourCut), cumComm: Math.round(cumComm) }); months.push({ m: Math.ceil(days / 30.4), phase: c === 0 ? p.label : '', prof: Math.round(p.profit), comm: Math.round(yourCut), cumComm: Math.round(cumComm) });
} }
if (k === '3xL7' || days > 913) break; if (terminal || days > 913) break;
} }
return months; return months;
} }
@@ -1694,24 +1720,45 @@ function updateAll() {
const giftLevel = parseInt(document.getElementById('giftLevel').value); const giftLevel = parseInt(document.getElementById('giftLevel').value);
const selfLevel = parseInt(document.getElementById('selfFundLevel').value); const selfLevel = parseInt(document.getElementById('selfFundLevel').value);
const showRef = document.getElementById('showReferral').checked; const showRef = document.getElementById('showReferral').checked;
const mode = document.getElementById('strategyMode').value;
const pocketPct = mode === 'pocket' ? (parseInt(document.getElementById('pocketPct').value) || 50) : 0;
document.getElementById('pocketPctGroup').style.display = mode === 'pocket' ? '' : 'none';
document.getElementById('parkPhaseGroup').style.display = mode === 'park' ? '' : 'none';
const mult = commPct / 10; const mult = commPct / 10;
const giftCost = getLevelCost(giftLevel); const giftCost = getLevelCost(giftLevel);
const selfCost = getLevelCost(selfLevel); const selfCost = getLevelCost(selfLevel);
const effective = getEffectiveStart(giftLevel, selfLevel); const effective = getEffectiveStart(giftLevel, selfLevel);
const phases = getPhaseSequence(effective); let phases = getPhaseSequence(effective);
const PI = phaseInfo(phases); // Park & collect: keep the park-level select in sync with the sequence,
const totalMonths = estimateMonths(phases); // then truncate the journey at the chosen level (terminal = collect there).
const parkSel = document.getElementById('parkPhase');
const climb = phases.filter(k => k !== '3xL7');
if (parkSel.dataset.seq !== climb.join(',')) {
const keep = parkSel.dataset.want || parkSel.value;
parkSel.dataset.seq = climb.join(',');
parkSel.innerHTML = climb.map(k => `<option value="${k}">${HYBRIDS[k].label} — $${HYBRIDS[k].profit.toFixed(2)}/cycle profit</option>`).join('');
parkSel.value = [...parkSel.options].some(o => o.value === keep) ? keep : climb[climb.length - 1];
delete parkSel.dataset.want;
}
if (mode === 'park') phases = phases.slice(0, phases.indexOf(parkSel.value) + 1);
const PI = phaseInfo(phases, pocketPct);
const endKey = phases[phases.length - 1];
const totalMonths = estimateMonths(phases, pocketPct);
const yr1Cum = estimateYear1Cum(phases, commPct, giftLevel) * numPeople; const yr1Cum = estimateYear1Cum(phases, commPct, giftLevel, pocketPct) * numPeople;
const yr1PerPerson = estimateYear1Cum(phases, commPct, giftLevel); const yr1PerPerson = estimateYear1Cum(phases, commPct, giftLevel, pocketPct);
const totalEG = Math.round(phases.filter(k => k !== '3xL7') const totalEG = Math.round(phases.filter(k => k !== '3xL7' && !PI[k].parked)
.reduce((s, k) => s + PI[k].payout * (commPct / 100) * PI[k].cycles, 0) * 10) / 10; .reduce((s, k) => s + PI[k].payout * (commPct / 100) * PI[k].cycles, 0) * 10) / 10;
const monthlyPassive = Math.round(THREE_L7_YOUR_CUT * mult * numPeople); // True monthly (cycles are 19 days): per-cycle cut x 30.4/19.
const endCutPerCycle = PI[endKey].parked ? PI[endKey].payout * (commPct / 100) : THREE_L7_YOUR_CUT * mult;
const monthlyPassive = Math.round(endCutPerCycle * 30.4 / 19 * numPeople);
const pocketedTotal = Math.round(phases.filter(k => k !== '3xL7' && !PI[k].parked)
.reduce((s, k) => s + PI[k].profit * (pocketPct / 100) * PI[k].cycles, 0));
let totalToEGPerPerson = 0; let totalToEGPerPerson = 0;
for (const k of phases) { for (const k of phases) {
if (k === '3xL7') break; if (k === '3xL7' || PI[k].parked) break;
totalToEGPerPerson += PI[k].payout * (commPct / 100) * PI[k].cycles; totalToEGPerPerson += PI[k].payout * (commPct / 100) * PI[k].cycles;
} }
totalToEGPerPerson = Math.round(totalToEGPerPerson * 100) / 100; totalToEGPerPerson = Math.round(totalToEGPerPerson * 100) / 100;
@@ -1724,7 +1771,7 @@ function updateAll() {
outer: for (const k of phases) { outer: for (const k of phases) {
const p = PI[k]; const p = PI[k];
const yourCut = p.payout * (commPct / 100); const yourCut = p.payout * (commPct / 100);
const n = k === '3xL7' ? 60 : p.cycles; const n = (k === '3xL7' || p.parked) ? 60 : p.cycles;
for (let i = 0; i < n; i++) { for (let i = 0; i < n; i++) {
daysAcc += p.daysPer; daysAcc += p.daysPer;
cumCheck += yourCut; cumCheck += yourCut;
@@ -1749,9 +1796,21 @@ function updateAll() {
<div class="sub">per person</div> <div class="sub">per person</div>
</div> </div>
<div class="summary-card"> <div class="summary-card">
<div class="label">Time to 3× L7</div> <div class="label">${mode === 'park' ? 'Time to Park Level' : 'Time to 3× L7'}</div>
<div class="value orange" style="font-size:1.3rem">~${totalMonths} months</div> <div class="value orange" style="font-size:1.3rem">~${totalMonths} months</div>
</div> </div>
${mode === 'pocket' ? `
<div class="summary-card">
<div class="label">Pocketed Along the Way</div>
<div class="value yellow">$${pocketedTotal.toLocaleString()}</div>
<div class="sub">${pocketPct}% of each cycle's profit</div>
</div>` : ''}
${mode === 'park' ? `
<div class="summary-card">
<div class="label">Their Income at Park</div>
<div class="value green">$${Math.round(HYBRIDS[endKey].profit * 30.4 / 19).toLocaleString()}/mo</div>
<div class="sub">${HYBRIDS[endKey].label}, pocketing every cycle</div>
</div>` : ''}
${numPeople > 0 ? ` ${numPeople > 0 ? `
<div class="summary-card"> <div class="summary-card">
<div class="label">Year 1 Referral Earnings</div> <div class="label">Year 1 Referral Earnings</div>
@@ -1765,7 +1824,7 @@ ${numPeople > 0 ? `
</div> </div>
${numPeople > 0 ? ` ${numPeople > 0 ? `
<div class="summary-card"> <div class="summary-card">
<div class="label">Monthly Passive (3× L7)</div> <div class="label">Monthly Passive (${mode === 'park' ? 'at park' : '3× L7'})</div>
<div class="value green">$${monthlyPassive.toLocaleString()}</div> <div class="value green">$${monthlyPassive.toLocaleString()}</div>
<div class="sub">${numPeople > 1 ? `$${Math.round(monthlyPassive / numPeople).toLocaleString()} / person` : 'per month'}</div> <div class="sub">${numPeople > 1 ? `$${Math.round(monthlyPassive / numPeople).toLocaleString()} / person` : 'per month'}</div>
</div>` : ''} </div>` : ''}
@@ -1780,7 +1839,7 @@ ${numPeople > 0 ? `
for (const k of phases) { for (const k of phases) {
const p = PI[k]; const p = PI[k];
const yourCut = p.payout * (commPct / 100); const yourCut = p.payout * (commPct / 100);
const cyclesNum = k === '3xL7' ? 1 : p.cycles; const cyclesNum = (k === '3xL7' || p.parked) ? 1 : p.cycles;
// Track cumulative payout (always accumulates — this is the total to sponsor) // Track cumulative payout (always accumulates — this is the total to sponsor)
cumRunning += yourCut * cyclesNum; cumRunning += yourCut * cyclesNum;
@@ -1792,13 +1851,13 @@ ${numPeople > 0 ? `
roiRow = k; roiRow = k;
} }
} }
const cls = k === '3xL7' ? 'endgame' : (k === roiRow ? 'highlight' : ''); const cls = (k === '3xL7' || p.parked) ? 'endgame' : (k === roiRow ? 'highlight' : '');
// Phase totals (x cycles) so every money column matches the Cycles column; // Phase totals (x cycles) so every money column matches the Cycles column;
// per-cycle values here kept getting read as phase totals (Marty 07-30). // per-cycle values here kept getting read as phase totals (Marty 07-30).
rows += `<tr class="${cls}"> rows += `<tr class="${cls}">
<td>${p.label}</td> <td>${p.label}</td>
<td class="num">${k === '3xL7' ? 'every 19d' : `${cyclesNum}×`}</td> <td class="num">${(k === '3xL7' || p.parked) ? 'every 19d' : `${cyclesNum}×`}</td>
<td>${k === '3xL7' ? 'ongoing' : `~${p.months} months`}</td> <td>${(k === '3xL7' || p.parked) ? (p.parked ? '🏝 parked' : 'ongoing') : `~${p.months} months`}</td>
<td class="num">$${(p.payout * cyclesNum).toFixed(2)}</td> <td class="num">$${(p.payout * cyclesNum).toFixed(2)}</td>
<td class="num">$${(p.profit * cyclesNum).toFixed(2)}</td> <td class="num">$${(p.profit * cyclesNum).toFixed(2)}</td>
<td class="num green-text referral-col">$${(yourCut * cyclesNum).toFixed(2)}</td> <td class="num green-text referral-col">$${(yourCut * cyclesNum).toFixed(2)}</td>
@@ -1813,13 +1872,13 @@ ${numPeople > 0 ? `
for (const k of phases) { for (const k of phases) {
const p = PI[k]; const p = PI[k];
const yourCut = p.payout * (commPct / 100); const yourCut = p.payout * (commPct / 100);
const cycles = k === '3xL7' ? 10 : p.cycles; const cycles = (k === '3xL7' || p.parked) ? 10 : p.cycles;
for (let i = 0; i < cycles; i++) { for (let i = 0; i < cycles; i++) {
chartDays += p.daysPer; chartDays += p.daysPer;
chartCum += yourCut; chartCum += yourCut;
chartData.push({ m: Math.ceil(chartDays / 30.4), cum: Math.round(chartCum * 100) / 100 }); chartData.push({ m: Math.ceil(chartDays / 30.4), cum: Math.round(chartCum * 100) / 100 });
} }
if (k === '3xL7') break; if (k === '3xL7' || p.parked) break;
} }
const chartLabels = chartData.map(d => `M${d.m}`); const chartLabels = chartData.map(d => `M${d.m}`);
@@ -2036,7 +2095,7 @@ ${numPeople > 0 ? `
} }
// ─── Event Wiring ────────────────────────────────────────── // ─── Event Wiring ──────────────────────────────────────────
['numPeople','commissionPct','giftLevel','selfFundLevel','showReferral','alreadyJoined'].forEach(id => { ['numPeople','commissionPct','giftLevel','selfFundLevel','showReferral','alreadyJoined','strategyMode','pocketPct','parkPhase'].forEach(id => {
const el = document.getElementById(id); const el = document.getElementById(id);
el.addEventListener('input', updateAll); el.addEventListener('input', updateAll);
el.addEventListener('change', updateAll); el.addEventListener('change', updateAll);
@@ -2066,6 +2125,15 @@ document.querySelectorAll('.tab-btn').forEach(btn => {
const el = document.getElementById('selfFundLevel'); const el = document.getElementById('selfFundLevel');
if (el && [...el.options].some(o => o.value === self)) el.value = self; if (el && [...el.options].some(o => o.value === self)) el.value = self;
} }
const mode = p.get('mode');
if (mode === 'pocket' || mode === 'park') {
document.getElementById('strategyMode').value = mode;
const pk = p.get('pk');
if (pk && [...document.getElementById('pocketPct').options].some(o => o.value === pk))
document.getElementById('pocketPct').value = pk;
const park = p.get('park');
if (park) document.getElementById('parkPhase').dataset.want = park;
}
})(); })();
updateAll(); updateAll();
@@ -2089,6 +2157,12 @@ function getShareUrl(refUser) {
let url = getBaseUrl() + '?ref=' + encodeURIComponent(u); let url = getBaseUrl() + '?ref=' + encodeURIComponent(u);
if (gift !== '0') url += '&gift=' + gift; if (gift !== '0') url += '&gift=' + gift;
if (self !== '0') url += '&self=' + self; if (self !== '0') url += '&self=' + self;
const modeSel = document.getElementById('strategyMode');
if (modeSel && modeSel.value !== 'accelerate') {
url += '&mode=' + modeSel.value;
if (modeSel.value === 'pocket') url += '&pk=' + document.getElementById('pocketPct').value;
if (modeSel.value === 'park') url += '&park=' + encodeURIComponent(document.getElementById('parkPhase').value);
}
return url; return url;
} }
@@ -2169,6 +2243,23 @@ function updateHeroSignupBtn() {
})(); })();
// ─── Shareable Plan Generator ─────────────────────────────── // ─── Shareable Plan Generator ───────────────────────────────
// One narrative line per phase, in the ONE strategy the sponsor chose —
// replaces the old dual pocket/accelerate blocks (Marty 2026-07-30).
function phasePlanLine(k, i, PI, mode, pocketPct) {
const p = PI[k];
if (p.parked) {
const perMo = Math.round(p.profit * 30.4 / 19);
return `**Phase ${i + 1}: ${p.label} — PARK HERE** 🏝\nRun these campaigns on repeat, every ~19 days, and pocket the ~$${p.profit.toFixed(2)} profit each cycle — about $${perMo.toLocaleString()}/month of spending money for a few minutes of clicking a day. No more reinvesting, no more climbing. This is your income level.`;
}
const base = `**Phase ${i + 1}: ${p.label}**\n${p.cycles} cycles, ~${p.months} months — $${p.payout.toFixed(2)}/cycle payout`;
if (mode === 'pocket') {
const pk = p.profit * pocketPct / 100;
const totalPk = Math.round(pk * p.cycles * 100) / 100;
return `${base}\nPocket ~$${pk.toFixed(2)} of each cycle's ~$${p.profit.toFixed(2)} profit (about $${totalPk.toFixed(2)} in your pocket across this phase) and bank the rest toward the next level. The timeline above already accounts for the slower climb.`;
}
return `${base}\nReinvest everything — each cycle's ~$${p.profit.toFixed(2)} profit goes straight into reserves until the next level unlocks. Fastest path there is.`;
}
function generatePlan() { function generatePlan() {
const numPeople = parseInt(document.getElementById('numPeople').value) || 0; const numPeople = parseInt(document.getElementById('numPeople').value) || 0;
const giftLevel = parseInt(document.getElementById('giftLevel').value); const giftLevel = parseInt(document.getElementById('giftLevel').value);
@@ -2178,9 +2269,25 @@ function generatePlan() {
const giftCost = getLevelCost(giftLevel); const giftCost = getLevelCost(giftLevel);
const selfCost = getLevelCost(selfLevel); const selfCost = getLevelCost(selfLevel);
const effective = getEffectiveStart(giftLevel, selfLevel); const effective = getEffectiveStart(giftLevel, selfLevel);
const phases = getPhaseSequence(effective); const mode = document.getElementById('strategyMode').value;
const PI = phaseInfo(phases); const pocketPct = mode === 'pocket' ? (parseInt(document.getElementById('pocketPct').value) || 50) : 0;
const totalMonths = estimateMonths(phases); let phases = getPhaseSequence(effective);
if (mode === 'park') phases = phases.slice(0, phases.indexOf(document.getElementById('parkPhase').value) + 1);
const PI = phaseInfo(phases, pocketPct);
const endKey = phases[phases.length - 1];
const totalMonths = estimateMonths(phases, pocketPct);
const endgameBlock = PI[endKey].parked
? `**The destination: ${PI[endKey].label}** 🏝\nYou stop climbing here on purpose — roughly $${Math.round(HYBRIDS[endKey].profit * 30.4 / 19).toLocaleString()}/month pocketed, indefinitely, for a few minutes of clicking a day. (Want more later? The calculator link above shows the full climb to 3× L7 whenever you're ready.)`
: `**Phase ${phases.filter(x => x !== '3xL7').length + 1}: 3× L7 Endgame** 🎯\nAll three L7 campaigns running at once\n$9,720.00/cycle payout → ~$4,032/month${mode === 'pocket' ? ' — and from here it is ALL pocket money' : ' passive'}\nThis is the finish line${mode === 'pocket' ? `\n\n(CBP has a $10 minimum withdrawal and a 10% fee on external-wallet withdrawals — pocketed money accumulates in your balance until you cash out.)` : ''}`;
const roadmapHeading = PI[endKey].parked
? `Your roadmap to ~$${Math.round(HYBRIDS[endKey].profit * 30.4 / 19).toLocaleString()}/month pocket income:`
: `Your full roadmap to $4,032/month:`;
const timeLine = PI[endKey].parked
? `Estimated time to your park level: ~${totalMonths} months`
: `Estimated time to the 3× L7 endgame: ~${totalMonths} months`;
const quickMonthly = PI[endKey].parked
? `• Monthly at park (${HYBRIDS[endKey].label}): ~$${Math.round(HYBRIDS[endKey].profit * 30.4 / 19).toLocaleString()}/mo pocketed`
: `• Monthly at 3× L7: ~$4,032/mo passive`;
const alreadyJoined = document.getElementById('alreadyJoined').checked; const alreadyJoined = document.getElementById('alreadyJoined').checked;
updateSharedLinkBox(); updateSharedLinkBox();
@@ -2202,50 +2309,8 @@ function generatePlan() {
} }
let rawPlan = alreadyJoined let rawPlan = alreadyJoined
? `📋 Your ClickBaitPays Plan — Full Roadmap\n\nSo what's ClickBaitPays? It's an ad platform where you run small ad campaigns, click a few ads each day, and every ~19 days you get paid more than the campaign cost. You reinvest those payouts into bigger campaigns and scale up. It's simple, takes a few minutes a day, and you can do it from your phone.\n\nHere's a calculator I put together so you can play with the numbers yourself: ${refLink}\n\nCome back to that link anytime — it'll walk you through what's possible and the best plan forward as you grow.\n\n${giftCost > 0 ? `${pifSteps}` : ''}\n\nYour full roadmap to $3,960/month:\n\n${phases.filter(k => k !== '3xL7').map((k, i) => { ? `📋 Your ClickBaitPays Plan — Full Roadmap\n\nSo what's ClickBaitPays? It's an ad platform where you run small ad campaigns, click a few ads each day, and every ~19 days you get paid more than the campaign cost. You reinvest those payouts into bigger campaigns and scale up. It's simple, takes a few minutes a day, and you can do it from your phone.\n\nHere's a calculator I put together so you can play with the numbers yourself: ${refLink}\n\nCome back to that link anytime — it'll walk you through what's possible and the best plan forward as you grow.\n\n${giftCost > 0 ? `${pifSteps}` : ''}\n\n${roadmapHeading}\n\n${phases.filter(k => k !== '3xL7').map((k, i) => phasePlanLine(k, i, PI, mode, pocketPct)).join('\n\n')}\n\n${endgameBlock}\n\n${selfCost > 0 ? `**Your total self-fund: $${selfCost}**${selfCost > giftCost ? ` (you cover $${(selfCost - giftCost).toLocaleString()} after sponsor's gift)` : ''}` : ''}\n\nNo new money needed after the start — just run the cycles and follow the phases above.\n\nAs a side note — I also earn 10% of everything you get paid through this system, so eventually I'll get my gift back. But that's not why I'm doing this. I genuinely just want to pay it forward and help you get started. You win, I win — we both win together.\n\nJoin the sponsor community on Telegram to connect with other members and get help: https://t.me/+mzXTku1wR7pkODBh\n\n${timeLine}\n\nQuick Stats\n${quickMonthly}\n• Each campaign cycle: 19 days\n• Min daily clicks: 3-20 (depending on level)\n• Reward per ad click: $0.48 - $13.50\n\nYour Referral Link\n${refLink}\n\nGood luck — the system works if you work the system. 💪`
const p = PI[k]; : `📋 Your ClickBaitPays Plan\n\nSo what's ClickBaitPays? It's an ad platform where you run small ad campaigns, click a few ads each day, and every ~19 days you get paid more than the campaign cost. You reinvest those payouts into bigger campaigns and scale up. It's simple, takes a few minutes a day, and you can do it from your phone.\n\nHere's a calculator I put together so you can play with the numbers yourself: ${refLink}\n\nAfter you sign up, come back to that link — it'll walk you through what's possible and the best plan forward as you grow.\n\n${giftCost > 0 ? `With me as your sponsor, I'm covering **$${giftCost}** to get you started through Level ${giftLevel} (L${giftLevel === 1 ? '1 only' : `1-L${giftLevel}`}). You owe nothing for this — it's funded up front, and you keep 100% of your earnings.` : `I haven't pre-funded any levels on my end — you'll be building entirely on your own using the link below.`}\n\n${giftCost > 0 ? pifSteps : ''}\n\n${roadmapHeading}\n\n${phases.filter(k => k !== '3xL7').map((k, i) => phasePlanLine(k, i, PI, mode, pocketPct)).join('\n\n')}\n\n${endgameBlock}\n\n${selfCost > 0 ? `**Your total self-fund: $${selfCost}**${selfCost > giftCost ? ` (you cover $${(selfCost - giftCost).toLocaleString()} after sponsor's gift)` : ''}` : ''}\n\nNo new money needed after the start — just run the cycles and follow the phases above.\n\nAs a side note — I also earn 10% of everything you get paid through this system, so eventually I'll get my gift back. But that's not why I'm doing this. I genuinely just want to pay it forward and help you get started. You win, I win — we both win together.\n\nJoin the sponsor community on Telegram to connect with other members and get help: https://t.me/+mzXTku1wR7pkODBh\n\n${timeLine}\n\nQuick Stats\n${quickMonthly}\n• Each campaign cycle: 19 days\n• Min daily clicks: 3-20 (depending on level)\n• Reward per ad click: $0.48 - $13.50\n\nYour Referral Link\n${refLink}\n\nUse this link to sign up — it's how your sponsor tracks your progress. If you have questions, reach out to them directly.\n\nGood luck — the system works if you work the system. 💪`;
const pocketTotal = (p.profit * p.cycles).toFixed(2);
const availableAfterPocket = Math.round(p.profit * p.cycles * 100 + p.reinvest * 100) / 100;
const nextK = phases[phases.indexOf(k) + 1];
const nextReinvest = nextK && nextK !== '3xL7' ? HYBRIDS[nextK].reinvest : 0;
let unlockText = '';
// Calculate cycles needed to reach $10 min withdrawal
const cyclesToMinWithdraw = Math.ceil(10 / p.profit) > 0 ? Math.ceil(10 / p.profit) : 1;
const withdrawNote = p.profit < 10
? `CBP has a **$10 minimum withdrawal** (10% fee on withdrawals to external wallets) — at ~$${p.profit.toFixed(2)} profit per cycle it'll take **${cyclesToMinWithdraw} cycles** before you have enough to cash out. `
: `CBP has a **$10 minimum withdrawal** (10% fee on withdrawals to external wallets). `;
if (nextK && nextK !== '3xL7' && availableAfterPocket >= nextReinvest) {
unlockText = `After ${p.cycles} cycles you have enough saved to unlock the next level, plus ~$${pocketTotal} pocketed along the way.`;
} else if (nextK && nextK !== '3xL7') {
const shortfall = Math.round((nextReinvest - availableAfterPocket) * 100) / 100;
unlockText = `After ${p.cycles} cycles you've pocketed ~$${pocketTotal}, but you'll need about $${shortfall.toFixed(2)} more to unlock the next level ($${nextReinvest}) — skip pocketing for one cycle to cover the gap.`;
} else {
unlockText = `After ${p.cycles} cycles you've pocketed ~$${pocketTotal} along the way.`;
}
return `**Phase ${i+1}: ${p.label}**\n${p.cycles} cycles, ~${p.months} months — $${p.payout.toFixed(2)}/cycle payout\n\nYou can play this phase two ways:\n\n🔹 **Pocket mode** — hold onto the ~$${p.profit.toFixed(2)} profit each cycle as spending money (that's your balance after CBP's built-in fee, no extra charge if you keep it in your account). ${withdrawNote}${unlockText} Total time: ~${p.months} months.\n\n🔸 **Accelerate mode** — reinvest every penny instead of pocketing it. You reach the next level faster because nothing comes off the top. Total time is shorter, but you pocket nothing along the way.`;
}).join('\n\n')}\n\n**Phase ${phases.filter(k => k !== '3xL7').length+1}: 3× L7 Endgame** 🎯\nAll three L7 campaigns running at once\n$9,720.00/cycle payout → ~$3,960.00/month passive\nThis is the finish line\n\n${selfCost > 0 ? `**Your total self-fund: $${selfCost}**${selfCost > giftCost ? ` (you cover $${(selfCost - giftCost).toLocaleString()} after sponsor's gift)` : ''}` : ''}\n\nThe choice is yours — pocket spending money along the way, or reinvest everything to get to the endgame faster. Either way, no new money needed after the start. Just run the cycles, stack the profits, and level up.\n\nAs a side note — I also earn 10% of everything you get paid through this system, so eventually I'll get my gift back. But that's not why I'm doing this. I genuinely just want to pay it forward and help you get started. You win, I win — we both win together.\n\nJoin the sponsor community on Telegram to connect with other members and get help: https://t.me/+mzXTku1wR7pkODBh\n\nEstimated time to 3× L7 endgame: ~${totalMonths} months\n\nQuick Stats\n• Monthly at 3× L7: ~$3,960/mo passive\n• Each campaign cycle: 19 days\n• Min daily clicks: 3-20 (depending on level)\n• Reward per ad click: $0.48 - $13.50\n\nYour Referral Link\n${refLink}\n\nGood luck — the system works if you work the system. 💪`
: `📋 Your ClickBaitPays Plan\n\nSo what's ClickBaitPays? It's an ad platform where you run small ad campaigns, click a few ads each day, and every ~19 days you get paid more than the campaign cost. You reinvest those payouts into bigger campaigns and scale up. It's simple, takes a few minutes a day, and you can do it from your phone.\n\nHere's a calculator I put together so you can play with the numbers yourself: ${refLink}\n\nAfter you sign up, come back to that link — it'll walk you through what's possible and the best plan forward as you grow.\n\n${giftCost > 0 ? `With me as your sponsor, I'm covering **$${giftCost}** to get you started through Level ${giftLevel} (L${giftLevel === 1 ? '1 only' : `1-L${giftLevel}`}). You owe nothing for this — it's funded up front, and you keep 100% of your earnings.` : `I haven't pre-funded any levels on my end — you'll be building entirely on your own using the link below.`}\n\n${giftCost > 0 ? pifSteps : ''}\n\nYour full roadmap to $3,960/month:\n\n${phases.filter(k => k !== '3xL7').map((k, i) => {
const p = PI[k];
const pocketTotal = (p.profit * p.cycles).toFixed(2);
const availableAfterPocket = Math.round(p.profit * p.cycles * 100 + p.reinvest * 100) / 100;
const nextK = phases[phases.indexOf(k) + 1];
const nextReinvest = nextK && nextK !== '3xL7' ? HYBRIDS[nextK].reinvest : 0;
let unlockText = '';
// Calculate cycles needed to reach $10 min withdrawal
const cyclesToMinWithdraw = Math.ceil(10 / p.profit) > 0 ? Math.ceil(10 / p.profit) : 1;
const withdrawNote = p.profit < 10
? `CBP has a **$10 minimum withdrawal** (10% fee on withdrawals to external wallets) — at ~$${p.profit.toFixed(2)} profit per cycle it'll take **${cyclesToMinWithdraw} cycles** before you have enough to cash out. `
: `CBP has a **$10 minimum withdrawal** (10% fee on withdrawals to external wallets). `;
if (nextK && nextK !== '3xL7' && availableAfterPocket >= nextReinvest) {
unlockText = `After ${p.cycles} cycles you have enough saved to unlock the next level, plus ~$${pocketTotal} pocketed along the way.`;
} else if (nextK && nextK !== '3xL7') {
const shortfall = Math.round((nextReinvest - availableAfterPocket) * 100) / 100;
unlockText = `After ${p.cycles} cycles you've pocketed ~$${pocketTotal}, but you'll need about $${shortfall.toFixed(2)} more to unlock the next level ($${nextReinvest}) — skip pocketing for one cycle to cover the gap.`;
} else {
unlockText = `After ${p.cycles} cycles you've pocketed ~$${pocketTotal} along the way.`;
}
return `**Phase ${i+1}: ${p.label}**\n${p.cycles} cycles, ~${p.months} months — $${p.payout.toFixed(2)}/cycle payout\n\nYou can play this phase two ways:\n\n🔹 **Pocket mode** — hold onto the ~$${p.profit.toFixed(2)} profit each cycle as spending money (that's your balance after CBP's built-in fee, no extra charge if you keep it in your account). ${withdrawNote}${unlockText} Total time: ~${p.months} months.\n\n🔸 **Accelerate mode** — reinvest every penny instead of pocketing it. You reach the next level faster because nothing comes off the top. Total time is shorter, but you pocket nothing along the way.`;
}).join('\n\n')}\n\n**Phase ${phases.filter(k => k !== '3xL7').length+1}: 3× L7 Endgame** 🎯\nAll three L7 campaigns running at once\n$9,720.00/cycle payout → ~$3,960.00/month passive\nThis is the finish line\n\n${selfCost > 0 ? `**Your total self-fund: $${selfCost}**${selfCost > giftCost ? ` (you cover $${(selfCost - giftCost).toLocaleString()} after sponsor's gift)` : ''}` : ''}\n\nThe choice is yours — pocket spending money along the way, or reinvest everything to get to the endgame faster. Either way, no new money needed after the start. Just run the cycles, stack the profits, and level up.\n\nAs a side note — I also earn 10% of everything you get paid through this system, so eventually I'll get my gift back. But that's not why I'm doing this. I genuinely just want to pay it forward and help you get started. You win, I win — we both win together.\n\nJoin the sponsor community on Telegram to connect with other members and get help: https://t.me/+mzXTku1wR7pkODBh\n\nEstimated time to 3× L7 endgame: ~${totalMonths} months\n\nQuick Stats\n• Monthly at 3× L7: ~$3,960/mo passive\n• Each campaign cycle: 19 days\n• Min daily clicks: 3-20 (depending on level)\n• Reward per ad click: $0.48 - $13.50\n\nYour Referral Link\n${refLink}\n\nUse this link to sign up — it's how your sponsor tracks your progress. If you have questions, reach out to them directly.\n\nGood luck — the system works if you work the system. 💪`;
document.getElementById('planOutput').innerHTML = rawPlan.replace(/\*\*(.*?)\*\*/g, '<strong>$1</strong>'); document.getElementById('planOutput').innerHTML = rawPlan.replace(/\*\*(.*?)\*\*/g, '<strong>$1</strong>');
document.getElementById('planOutput').dataset.rawPlan = rawPlan; document.getElementById('planOutput').dataset.rawPlan = rawPlan;
+24
View File
@@ -110,5 +110,29 @@ console.log("6) timeline months advance ~19d per cycle (not 1 month per cycle):"
last.m === Math.ceil(cycles * 19 / 30.4), `rows=${cycles}`); last.m === Math.ceil(cycles * 19 / 30.4), `rows=${cycles}`);
} }
console.log("7) strategy modes:");
{
const phases = getPhaseSequence(0);
const accel = computePlan(phases);
const pk50 = computePlan(phases, 50);
const pk75 = computePlan(phases, 75);
let stretched = true, finite = true;
for (const k of phases) {
if (k === "3xL7") continue;
if (pk50[k].cycles < accel[k].cycles) stretched = false;
if (pk75[k].cycles >= 500) finite = false;
}
check("pocket 50% stretches every phase (or equal)", stretched);
check("pocket 75% still finite everywhere", finite);
check(`pocket 50% L1: ${pk50["L1-only"].cycles} > accel ${accel["L1-only"].cycles}`, pk50["L1-only"].cycles > accel["L1-only"].cycles);
const parked = computePlan(["L4+L3"]);
check("park at L4+L3: terminal flagged parked", parked["L4+L3"] && parked["L4+L3"].parked === true);
const y = estimateYear1Cum(["L4+L3"], 10, 0);
// parked from day one: floor(365/19)=19 cycles x $58.32
check(`parked-terminal year1 = ${y}`, y === Math.round(19 * 58.32), `want ${Math.round(19 * 58.32)}`);
const tl = buildMonthlyTimeline(["L4+L3"], 10);
check("parked timeline runs 10 collection cycles", tl.length === 10);
}
console.log(failures === 0 ? "\nALL PASS" : `\n${failures} FAILURE(S)`); console.log(failures === 0 ? "\nALL PASS" : `\n${failures} FAILURE(S)`);
process.exit(failures === 0 ? 0 : 1); process.exit(failures === 0 ? 0 : 1);