|
| 1 | +<!DOCTYPE html> |
| 2 | +<html lang="pt-BR"> |
| 3 | +<head> |
| 4 | +<meta charset="UTF-8"> |
| 5 | +<meta name="viewport" content="width=device-width, initial-scale=1.0"> |
| 6 | +<title>Calculadora de Custo — AI Coding Tools</title> |
| 7 | +<link href="https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:wght@400;500;600&family=IBM+Plex+Sans:wght@400;500;600;700&display=swap" rel="stylesheet"> |
| 8 | +<style> |
| 9 | +:root{--bg:#0c0c10;--sf:#151519;--sf2:#1c1c22;--bd:#2a2a34;--tx:#e4e4ec;--mt:#7a7a90;--ac:#3b82f6;--gn:#22c55e;--or:#f59e0b;--rd:#ef4444;--pu:#a78bfa} |
| 10 | +*{margin:0;padding:0;box-sizing:border-box} |
| 11 | +body{font-family:'IBM Plex Sans',sans-serif;background:var(--bg);color:var(--tx);min-height:100vh} |
| 12 | +.mono{font-family:'IBM Plex Mono',monospace} |
| 13 | +.ctn{max-width:960px;margin:0 auto;padding:32px 20px 80px} |
| 14 | +h1{font-size:26px;font-weight:700;margin-bottom:4px} |
| 15 | +.sub{color:var(--mt);font-size:13px;margin-bottom:28px} |
| 16 | +.ctrl{background:var(--sf);border:1px solid var(--bd);border-radius:12px;padding:24px;margin-bottom:24px} |
| 17 | +.cr{margin-bottom:20px}.cr:last-child{margin-bottom:0} |
| 18 | +.cl{display:flex;justify-content:space-between;align-items:baseline;margin-bottom:8px} |
| 19 | +.cl label{font-size:14px;font-weight:600} |
| 20 | +.cl .v{font-family:'IBM Plex Mono',monospace;font-size:14px;color:var(--ac);font-weight:600} |
| 21 | +input[type=range]{-webkit-appearance:none;width:100%;height:6px;background:var(--sf2);border-radius:3px;outline:none} |
| 22 | +input[type=range]::-webkit-slider-thumb{-webkit-appearance:none;width:18px;height:18px;border-radius:50%;background:var(--ac);cursor:pointer} |
| 23 | +.ms{display:grid;grid-template-columns:1fr 1fr;gap:12px} |
| 24 | +.ms>div label{display:block;font-size:13px;color:var(--mt);margin-bottom:4px} |
| 25 | +select{width:100%;background:var(--sf2);color:var(--tx);border:1px solid var(--bd);border-radius:8px;padding:8px 12px;font-family:'IBM Plex Sans',sans-serif;font-size:14px;cursor:pointer} |
| 26 | +select:focus{outline:none;border-color:var(--ac)} |
| 27 | +.asm{background:var(--sf);border:1px solid var(--bd);border-radius:12px;padding:14px 20px;margin-bottom:24px;font-size:13px;color:var(--mt);line-height:1.7} |
| 28 | +.asm strong{color:var(--tx)} |
| 29 | +.res{display:grid;grid-template-columns:repeat(3,1fr);gap:14px;margin-bottom:24px} |
| 30 | +@media(max-width:720px){.res{grid-template-columns:1fr}.ms{grid-template-columns:1fr}} |
| 31 | +.tc{background:var(--sf);border:1px solid var(--bd);border-radius:12px;padding:18px;position:relative;transition:border-color .2s} |
| 32 | +.tc.best{border-color:var(--gn)} |
| 33 | +.tc.best::after{content:'MENOR CUSTO';position:absolute;top:-10px;left:50%;transform:translateX(-50%);background:var(--gn);color:#000;font-size:10px;font-weight:700;letter-spacing:1px;padding:2px 10px;border-radius:8px;white-space:nowrap} |
| 34 | +.tn{font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:1.5px;margin-bottom:10px} |
| 35 | +.tn.cop{color:var(--ac)}.tn.cur{color:var(--pu)}.tn.cla{color:var(--or)} |
| 36 | +.po{background:var(--sf2);border-radius:8px;padding:10px 12px;margin-bottom:6px} |
| 37 | +.po:last-child{margin-bottom:0} |
| 38 | +.po.rec{background:#22c55e10;border:1px solid #22c55e25} |
| 39 | +.ph{display:flex;justify-content:space-between;align-items:baseline;margin-bottom:3px} |
| 40 | +.pn{font-size:13px;font-weight:600} |
| 41 | +.pp{font-family:'IBM Plex Mono',monospace;font-size:17px;font-weight:700} |
| 42 | +.pp.g{color:var(--gn)}.pp.w{color:var(--or)}.pp.d{color:var(--rd)} |
| 43 | +.pd{font-size:11px;color:var(--mt);line-height:1.5} |
| 44 | +.tg{display:inline-block;padding:1px 6px;border-radius:4px;font-size:10px;font-weight:600;margin-left:4px} |
| 45 | +.tg-f{background:#22c55e18;color:var(--gn)}.tg-o{background:#f59e0b15;color:var(--or)}.tg-n{background:#ef444415;color:var(--rd)} |
| 46 | +.rco{background:var(--sf);border:1px solid var(--bd);border-radius:12px;padding:18px} |
| 47 | +.rco h3{font-size:15px;margin-bottom:6px} |
| 48 | +.rco p{font-size:13px;color:var(--mt);line-height:1.7} |
| 49 | +.rco strong{color:var(--tx)} |
| 50 | +.ft{text-align:center;margin-top:36px;font-size:11px;color:var(--mt);line-height:1.7} |
| 51 | +.validation{background:var(--sf);border:1px solid var(--bd);border-radius:12px;padding:14px 20px;margin-bottom:24px;font-size:12px;color:var(--mt);line-height:1.8} |
| 52 | +.validation h4{font-size:13px;color:var(--tx);margin-bottom:6px} |
| 53 | +.validation .ok{color:var(--gn)}.validation .fail{color:var(--rd)} |
| 54 | +</style> |
| 55 | +</head> |
| 56 | +<body> |
| 57 | +<div class="ctn"> |
| 58 | + |
| 59 | +<h1>Calculadora de Custo: AI Coding Tools</h1> |
| 60 | +<p class="sub">Cursor vs Copilot vs Claude Code — Marco 2026 — Multiplicadores Copilot verificados em docs.github.com</p> |
| 61 | + |
| 62 | +<div class="ctrl"> |
| 63 | + <div class="cr"> |
| 64 | + <div class="cl"><label>Requests totais por mes</label><span class="v" id="reqV">1000</span></div> |
| 65 | + <input type="range" id="totR" min="100" max="10000" step="100" value="1000"> |
| 66 | + </div> |
| 67 | + <div class="cr"> |
| 68 | + <div class="cl"><label>% dedicado a research (resto = implementacao)</label><span class="v" id="splV">30%</span></div> |
| 69 | + <input type="range" id="rSpl" min="10" max="70" step="5" value="30"> |
| 70 | + </div> |
| 71 | + <div class="cr"> |
| 72 | + <div class="ms"> |
| 73 | + <div> |
| 74 | + <label>Modelo para research</label> |
| 75 | + <select id="rMod"> |
| 76 | + <option value="opus">Claude Opus 4.6 (melhor reasoning)</option> |
| 77 | + <option value="sonnet" selected>Claude Sonnet 4.6 (custo-beneficio)</option> |
| 78 | + <option value="gpt5">GPT-5</option> |
| 79 | + <option value="gemini">Gemini 2.5 Pro</option> |
| 80 | + </select> |
| 81 | + </div> |
| 82 | + <div> |
| 83 | + <label>Modelo para implementacao</label> |
| 84 | + <select id="iMod"> |
| 85 | + <option value="auto" selected>Auto / Incluido (mais barato)</option> |
| 86 | + <option value="haiku">Haiku 4.5</option> |
| 87 | + <option value="sonnet">Claude Sonnet 4.6</option> |
| 88 | + <option value="composer">Composer 2 (Cursor only)</option> |
| 89 | + </select> |
| 90 | + </div> |
| 91 | + </div> |
| 92 | + </div> |
| 93 | +</div> |
| 94 | + |
| 95 | +<div class="asm" id="asm"></div> |
| 96 | +<div class="res" id="res"></div> |
| 97 | +<div class="rco" id="rco"></div> |
| 98 | +<div class="validation" id="val"></div> |
| 99 | + |
| 100 | +<div class="ft"> |
| 101 | + Multiplicadores Copilot (docs.github.com): Haiku 0.33x | Sonnet/GPT-5/Gemini 1x | Opus 3x | Overage $0.04/prem req<br> |
| 102 | + Cursor: Auto ilimitado em planos pagos. Pool em dolares = preco do plano. Manual = custo API real<br> |
| 103 | + Claude Code: Pro ~300 req max | Max 5x ~1.500 | Max 20x ~5.000 | API = pay per token<br> |
| 104 | + Tokens/request: research ~5K in + ~3K out | impl ~3K in + ~1.5K out |
| 105 | +</div> |
| 106 | +</div> |
| 107 | + |
| 108 | +<script> |
| 109 | +// ====== PRICING (Marco 2026, verificado) ====== |
| 110 | +// Per-req cost: research 5K in + 3K out, impl 3K in + 1.5K out |
| 111 | +const MD = { |
| 112 | + opus: {r:.025+.075, i:.015+.0375, l:'Opus 4.6', pin:'$5/M in, $25/M out'}, |
| 113 | + sonnet: {r:.015+.045, i:.009+.0225, l:'Sonnet 4.6', pin:'$3/M in, $15/M out'}, |
| 114 | + gpt5: {r:.0125+.045,i:.0075+.0225,l:'GPT-5', pin:'$2.50/M in, $15/M out'}, |
| 115 | + gemini: {r:.01+.036, i:.006+.018, l:'Gemini 2.5 Pro',pin:'$2/M in, $12/M out'}, |
| 116 | + haiku: {r:.005+.015, i:.003+.0075, l:'Haiku 4.5', pin:'$1/M in, $5/M out'}, |
| 117 | + composer:{r:.0025+.006,i:.0015+.003, l:'Composer 2', pin:'$0.50/M in, $2/M out'}, |
| 118 | + auto: {r:0,i:0, l:'Auto/Incluido', pin:'Gratis'} |
| 119 | +}; |
| 120 | +// Copilot multipliers (docs.github.com Mar 2026) |
| 121 | +const CM={opus:3,sonnet:1,gpt5:1,gemini:1,haiku:.33,composer:1,auto:0}; |
| 122 | +const CPL=[{n:'Pro',p:10,q:300},{n:'Pro+',p:39,q:1500}]; |
| 123 | +const COV=.04; |
| 124 | +// Cursor |
| 125 | +const CUR=[{n:'Pro',p:20,pl:20},{n:'Pro+',p:60,pl:60},{n:'Ultra',p:200,pl:200}]; |
| 126 | +// Claude Code |
| 127 | +const CLC=[{n:'Pro',p:20,mx:300},{n:'Max 5x',p:100,mx:1500},{n:'Max 20x',p:200,mx:5000}]; |
| 128 | + |
| 129 | +function go(){ |
| 130 | + const tot=+document.getElementById('totR').value; |
| 131 | + const rP=+document.getElementById('rSpl').value/100; |
| 132 | + const rK=document.getElementById('rMod').value; |
| 133 | + const iK=document.getElementById('iMod').value; |
| 134 | + const rN=Math.round(tot*rP), iN=tot-rN; |
| 135 | + const rC=MD[rK], iC=MD[iK]; |
| 136 | + |
| 137 | + document.getElementById('reqV').textContent=tot.toLocaleString(); |
| 138 | + document.getElementById('splV').textContent=Math.round(rP*100)+'%'; |
| 139 | + document.getElementById('asm').innerHTML= |
| 140 | + `<strong>${tot.toLocaleString()} req/mes</strong>: ${rN.toLocaleString()} research (${rC.l} — ${rC.pin}) + ${iN.toLocaleString()} impl (${iC.l} — ${iC.pin})`; |
| 141 | + |
| 142 | + // COPILOT |
| 143 | + const cop=CPL.map(p=>{ |
| 144 | + const ip=iK==='auto'?0:iN*(CM[iK]||1); |
| 145 | + const rp=rN*(CM[rK]||1); |
| 146 | + const tp=Math.round(ip+rp); |
| 147 | + const ov=Math.max(0,tp-p.q); |
| 148 | + const ovc=ov*COV; |
| 149 | + const t=p.p+ovc; |
| 150 | + const d=iK==='auto' |
| 151 | + ?`${iN.toLocaleString()} impl GPT-4.1 (gratis) + ${rN.toLocaleString()} res ${CM[rK]}x = ${tp.toLocaleString()} prem de ${p.q}` |
| 152 | + :`${iN.toLocaleString()} impl ${CM[iK]}x + ${rN.toLocaleString()} res ${CM[rK]}x = ${tp.toLocaleString()} prem de ${p.q}`; |
| 153 | + return{name:p.n,total:t,ov,ovc,det:d,ok:true}; |
| 154 | + }); |
| 155 | + |
| 156 | + // CURSOR |
| 157 | + const cur=CUR.map(p=>{ |
| 158 | + const ic=iK==='auto'?0:iN*iC.i; |
| 159 | + const rc=rN*rC.r; |
| 160 | + const pu=ic+rc; |
| 161 | + const ov=Math.max(0,pu-p.pl); |
| 162 | + const aa=iK==='auto'&&rK==='auto'; |
| 163 | + const t=aa?p.p:p.p+ov; |
| 164 | + const d=aa?'Tudo Auto — ilimitado, $0 do pool' |
| 165 | + :iK==='auto'?`Impl Auto (gratis) + Research $${rc.toFixed(2)} do pool de $${p.pl}` |
| 166 | + :`Pool usado: $${pu.toFixed(2)} de $${p.pl}`; |
| 167 | + return{name:p.n,total:t,ov,det:d,ok:true,aa}; |
| 168 | + }); |
| 169 | + |
| 170 | + // CLAUDE CODE |
| 171 | + const cla=CLC.map(p=>{ |
| 172 | + const ok=tot<=p.mx; |
| 173 | + return{name:p.n,total:ok?p.p:null,ok, |
| 174 | + det:ok?`Flat rate — ${tot.toLocaleString()} de ${p.mx.toLocaleString()} max`:`Nao cabe: limite ~${p.mx.toLocaleString()} req`}; |
| 175 | + }); |
| 176 | + const aic=iK==='auto'?iN*MD.sonnet.i:iN*iC.i; |
| 177 | + const arc=rN*rC.r; |
| 178 | + const at=aic+arc; |
| 179 | + const ail=iK==='auto'?'Sonnet 4.6':iC.l; |
| 180 | + const api={name:'API pay-as-you-go',total:at,ok:true, |
| 181 | + det:`${iN.toLocaleString()} impl (${ail}) $${aic.toFixed(2)} + ${rN.toLocaleString()} res (${rC.l}) $${arc.toFixed(2)}`}; |
| 182 | + |
| 183 | + // BEST |
| 184 | + const nums=[...cop,...cur,...cla.filter(x=>x.ok),api].filter(x=>x.ok).map(x=>x.total); |
| 185 | + const best=Math.min(...nums); |
| 186 | + const copB=Math.min(...cop.map(x=>x.total)); |
| 187 | + const curB=Math.min(...cur.map(x=>x.total)); |
| 188 | + const claA=[...cla.filter(x=>x.ok).map(x=>x.total),api.total]; |
| 189 | + const claB=claA.length?Math.min(...claA):1e9; |
| 190 | + const oB=Math.min(copB,curB,claB); |
| 191 | + |
| 192 | + function pc(t){return t===best?'g':t>150?'d':t>80?'w':'';} |
| 193 | + function rp(p){ |
| 194 | + if(!p.ok) return`<div class="po"><div class="ph"><span class="pn">${p.name}</span><span class="pp d">N/A</span></div><div class="pd">${p.det}<span class="tg tg-n">NAO CABE</span></div></div>`; |
| 195 | + const c=p.total===best?' rec':''; |
| 196 | + let tg=''; |
| 197 | + if(p.ovc>0)tg=`<span class="tg tg-o">${p.ov.toLocaleString()} overage = +$${p.ovc.toFixed(2)}</span>`; |
| 198 | + else if(p.ov>0)tg=`<span class="tg tg-o">+$${p.ov.toFixed(2)} overage</span>`; |
| 199 | + else if(p.aa)tg=`<span class="tg tg-f">ILIMITADO</span>`; |
| 200 | + else tg=`<span class="tg tg-f">CABE</span>`; |
| 201 | + return`<div class="po${c}"><div class="ph"><span class="pn">${p.name}</span><span class="pp ${pc(p.total)}">$${p.total.toFixed(2)}</span></div><div class="pd">${p.det}${tg}</div></div>`; |
| 202 | + } |
| 203 | + |
| 204 | + document.getElementById('res').innerHTML=` |
| 205 | + <div class="tc${copB===oB?' best':''}"><div class="tn cop">GitHub Copilot</div>${cop.map(rp).join('')}</div> |
| 206 | + <div class="tc${curB===oB?' best':''}"><div class="tn cur">Cursor</div>${cur.map(rp).join('')}</div> |
| 207 | + <div class="tc${claB===oB?' best':''}"><div class="tn cla">Claude Code</div>${cla.map(rp).join('')}${rp(api)}</div>`; |
| 208 | + |
| 209 | + // RECO |
| 210 | + let rc=''; |
| 211 | + if(iK==='auto'&&cur[0].total<=20)rc+=`<strong>Cursor Pro $20</strong> — Auto ilimitado cobre ${tot.toLocaleString()} req sem overage. `; |
| 212 | + if(copB<curB)rc+=`<strong>Copilot $${copB.toFixed(2)}</strong> e mais barato, mas impl fica no GPT-4.1 (reasoning limitado). `; |
| 213 | + if(rK==='opus')rc+=`Com Opus, <strong>Claude Code Max $100 flat</strong> e o mais previsivel — sem multiplicadores ou overages. Copilot cobra Opus a 3x. `; |
| 214 | + if(api.total<50&&tot<=2000)rc+=`<strong>Claude Code API $${api.total.toFixed(2)}</strong> e opcao pay-as-you-go competitiva. `; |
| 215 | + if(tot>=3000)rc+=`Pra heavy use, combo <strong>Cursor Pro ($20) + Claude Code API</strong> da autocomplete ilimitado + reasoning sob demanda. `; |
| 216 | + if(!rc)rc=`Ajuste modelos e volume pra explorar cenarios.`; |
| 217 | + document.getElementById('rco').innerHTML=`<h3>Recomendacao</h3><p>${rc}</p>`; |
| 218 | + |
| 219 | + // VALIDATION |
| 220 | + let vl='<h4>Validacao dos calculos</h4>'; |
| 221 | + // Copilot Pro with current settings |
| 222 | + const cp=cop[0]; |
| 223 | + const cpPremExpected=iK==='auto'?rN*(CM[rK]||1):(iN*(CM[iK]||1)+rN*(CM[rK]||1)); |
| 224 | + const cpOvExpected=Math.max(0,Math.round(cpPremExpected)-300); |
| 225 | + const cpTotalExpected=10+cpOvExpected*0.04; |
| 226 | + const cpOk=Math.abs(cp.total-cpTotalExpected)<0.01; |
| 227 | + vl+=`<span class="${cpOk?'ok':'fail'}">Copilot Pro: ${Math.round(cpPremExpected)} prem, ${cpOvExpected} overage x $0.04 = $${cpTotalExpected.toFixed(2)} ${cpOk?'OK':'ERRO'}</span><br>`; |
| 228 | + |
| 229 | + // Cursor Pro |
| 230 | + const cuP=cur[0]; |
| 231 | + const cuPoolExpected=iK==='auto'?rN*rC.r:(iN*iC.i+rN*rC.r); |
| 232 | + const cuOvExpected=Math.max(0,cuPoolExpected-20); |
| 233 | + const cuTotalExpected=(iK==='auto'&&rK==='auto')?20:20+cuOvExpected; |
| 234 | + const cuOk=Math.abs(cuP.total-cuTotalExpected)<0.01; |
| 235 | + vl+=`<span class="${cuOk?'ok':'fail'}">Cursor Pro: pool $${cuPoolExpected.toFixed(2)} de $20, overage $${cuOvExpected.toFixed(2)}, total $${cuTotalExpected.toFixed(2)} ${cuOk?'OK':'ERRO'}</span><br>`; |
| 236 | + |
| 237 | + // Claude API |
| 238 | + const clApiExpected=aic+arc; |
| 239 | + const clOk=Math.abs(api.total-clApiExpected)<0.01; |
| 240 | + vl+=`<span class="${clOk?'ok':'fail'}">Claude API: impl $${aic.toFixed(2)} + res $${arc.toFixed(2)} = $${clApiExpected.toFixed(2)} ${clOk?'OK':'ERRO'}</span>`; |
| 241 | + |
| 242 | + document.getElementById('val').innerHTML=vl; |
| 243 | +} |
| 244 | + |
| 245 | +['totR','rSpl'].forEach(id=>document.getElementById(id).addEventListener('input',go)); |
| 246 | +['rMod','iMod'].forEach(id=>document.getElementById(id).addEventListener('change',go)); |
| 247 | +go(); |
| 248 | +</script> |
| 249 | +</body> |
| 250 | +</html> |
0 commit comments