Home
● Online
PROJETOS ATIVOS
0
NOTAS
0
ARQUIVOS
0
TRADES ABERTOS
0
CHECKLIST DO DIA
Vá para CHECKLIST DIÁRIO para adicionar tarefas.
PROJETOS ATIVOS
ÚLTIMAS NOTAS
CLIMA — ITABAIANA, PB
Carregando...
ATIVIDADE RECENTE
NOVA TAREFA
PROGRESSO DO DIA
0 / 0 concluídas
TAREFAS DE HOJE — 0
FOCO
25:00
SESSÃO 1 / 4 — 0 CICLOS COMPLETOS
CONFIGURAR TEMPOS

TAREFA ATUAL

HISTÓRICO DE HOJE
NOVA NOTA
NOTAS — 0
REGISTRAR ARQUIVO
FILTRAR

TOTAL
0
HTMLs
0
ARQUIVOS REGISTRADOS
NOVO PROJETO
BACKLOG
EM ANDAMENTO
CONCLUÍDO
TOTAL TRADES
0
WIN RATE
0%
RESULTADO
R$0
ABERTOS
0
REGISTRAR OPERAÇÃO
HISTÓRICO
RECEITA MÊS
R$0
CMV %
0%
LUCRO
R$0
MARGEM
0%
CALCULADORA CMV DE PRATO
PRATOS SALVOS
REFERÊNCIA CMV
● ABAIXO 30% — EXCELENTE
● 30–35% — BOM
● 35–40% — ATENÇÃO
● ACIMA 40% — CRÍTICO

PREÇO SUGERIDO
Para CMV de 30%:
LANÇAR DRE MENSAL
HISTÓRICO DRE
RECEITAS
R$0
DESPESAS
R$0
SALDO
R$0
INVESTIDO
R$0
LANÇAR TRANSAÇÃO
LANÇAMENTOS
REGISTRAR TÉCNICA / WRITEUP
BASE DE CONHECIMENTO
ADICIONAR AO ARSENAL
FILTRAR ARSENAL

TOTAL
0
OPERACIONAIS
0
INVENTÁRIO
NOVO PROJETO
PROJETOS
NOVO PROJETO
PROJETOS
FERRAMENTAS AI LOCAIS
GPT-SoVITS
ATIVO
localhost:9874
Ollama — qwen2.5-coder:7b
ATIVO
localhost:11434
Aider
ATIVO
~/.local/bin/aider
Claude Code
ATIVO
~/.local/bin/claude
DaVinci Resolve
SETUP
Em instalação
PIPELINE YOUTUBE
1. Roteiro
Claude / Ollama
2. Voz
GPT-SoVITS
3. Imagens
Leonardo AI
4. Vídeo
Veo 2 / Gemini Pro
5. Edição
DaVinci Resolve
NOTAS TÉCNICAS RÁPIDAS
TRACKER DE INGLÊS
VOCABULÁRIO — 0
ENVIAR DOCUMENTO / IMAGEM
Fica salva localmente. Nunca sai do seu browser.
RESULTADO
Envie uma imagem ou PDF para extrair o conteúdo...
CONFIGURAÇÃO
Gere em: GitHub → Settings → Developer settings → Personal access tokens → Fine-grained → repo scope
COMO USAR
1. Crie um repositório PRIVADO no GitHub
2. Gere um PAT com permissão de repo
3. Preencha os campos ao lado
4. Clique PUSH para salvar seus dados
5. Em outro dispositivo: configure igual e clique PULL

STATUS DO SYNC
Nenhum sync realizado.

SEGURANÇA
● Token salvo apenas no localStorage local
● Repositório privado = só você acessa
● Não use para dados ultra-sensíveis (senhas, credenciais ativas)
● GitHub tem acesso técnico ao conteúdo
CONFIGURAÇÃO
Gratuito em: aistudio.google.com → Get API Key
CONTEXTO ATIVO
DADOS DO SEU OS
O Gemini recebe contexto dos seus dados para respostas personalizadas.
CHAT
Configure sua chave API e selecione uma especialidade para começar.
CONFIGURAÇÃO
TIPOS DISPONÍVEIS
DRE — Analisa receita, CMV, lucro, tendências
TRADES — Win rate, pares mais lucrativos, erros
PROJETOS — Status, atrasados, concluídos
CYBER — Técnicas dominadas, gaps, sugestões
OFICINA — Projetos, custos, materiais pendentes
SEMANAL — Visão geral de todas as áreas
RELATÓRIO GERADO
Selecione um tipo de relatório e clique em GERAR...
ADICIONAR BLOCO
GRADE SEMANAL
TOTAL
0
LENDO
0
LIDOS
0
QUERO LER
0
ADICIONAR LIVRO
FILTRAR

LENDO AGORA
ACERVO COMPLETO
PLAYER
SELECIONE UMA ESTAÇÃO
PARADO

ADICIONAR ESTAÇÃO PERSONALIZADA
ESTAÇÕES
NOVA ENTRADA
HISTÓRICO — 0 ENTRADAS
NOVO HÁBITO
HOJE —
HISTÓRICO DE STREAKS
JUROS COMPOSTOS
DCA — PREÇO MÉDIO
Adicione compras para calcular preço médio
GRAVAÇÃO
🎤
CLIQUE PARA GRAVAR
0:00
TRANSCRIÇÃO
Grave um áudio e clique em TRANSCREVER...
CRIAR APRESENTAÇÃO
COMO USAR
1. Selecione as seções desejadas
2. Defina título e subtítulo
3. Clique em GERAR
4. Uma nova aba abre com os slides
5. Use as setas para navegar
6. Ctrl+P para imprimir / salvar PDF

ATALHOS NA APRESENTAÇÃO
→ / ESPAÇO — próximo slide
← — slide anterior
F — tela cheia
ESC — sair
CONFIGURAÇÃO
EXPORTAR PARA O VAULT
LOG DE EXPORTAÇÕES
CONFIGURAR GRÁFICO
TRADINGVIEW
Configure o símbolo e clique em CARREGAR
CONFIGURAÇÃO DO BOT
Crie em: Telegram → @BotFather → /newbot
Envie /start pro bot → acesse api.telegram.org/bot{TOKEN}/getUpdates

MENSAGEM RÁPIDA
EXPORTAR PARA TELEGRAM
COMO CONFIGURAR (PASSO A PASSO)
1. Abra o Telegram → busque @BotFather → envie /newbot
2. Escolha um nome e username para o bot
3. BotFather te dá o TOKEN — cole no campo acima
4. Abra seu novo bot → envie qualquer mensagem (ex: /start)
5. Acesse: https://api.telegram.org/bot{SEU_TOKEN}/getUpdates
6. Copie o "id" dentro de "chat" → cole no campo Chat ID
7. Clique TESTAR BOT — deve chegar uma mensagem no seu Telegram
ADICIONAR FERRAMENTA
FILTRAR

ESTATÍSTICAS
TOTAL
0
HTMLs
0

DICA
● Suba o HTML no Google Drive
● Compartilhe como "Qualquer pessoa com o link"
● Cole o link aqui → botão ABRIR abre em qualquer dispositivo
FERRAMENTAS CADASTRADAS
🔐 ALTERAR SENHA

SESSÃO
Sessão ativa enquanto o browser estiver aberto.
☁ CLOUDFLARE KV SYNC
Configure após hospedar no Cloudflare Pages.

NOTIFICAÇÕES
Alertas de checklist, CMV e pomodoro.

DADOS
📋 CLOUDFLARE WORKER — CÓDIGO PARA DEPLOY
Cole este código em workers.cloudflare.com após criar um KV namespace chamado BP_DATA.
const DK='blackpits_data'; let data=JSON.parse(localStorage.getItem(DK)||'{"notes":[],"files":[],"projects":[],"trades":[],"dre":[],"financas":[],"cyber":[],"engenharia":[],"oficina":[],"tech_notes":[],"words":[],"arsenal":[],"checklist":[],"pomo_cycles":0}'); if(!data.arsenal)data.arsenal=[]; if(!data.checklist)data.checklist=[]; if(!data.pomo_cycles)data.pomo_cycles=0; function save(){localStorage.setItem(DK,JSON.stringify(data));updateKPIs()} function uid(){return Date.now().toString(36)+Math.random().toString(36).slice(2,6)} function fmt(n){return 'R$'+parseFloat(n||0).toLocaleString('pt-BR',{minimumFractionDigits:2,maximumFractionDigits:2})} function dateStr(ts){return new Date(ts).toLocaleDateString('pt-BR')} // CLOCK function updateClock(){ const now=new Date(); document.getElementById('clock').textContent=now.toTimeString().slice(0,8); const days=['DOM','SEG','TER','QUA','QUI','SEX','SAB']; const months=['JAN','FEV','MAR','ABR','MAI','JUN','JUL','AGO','SET','OUT','NOV','DEZ']; document.getElementById('datestr').textContent=days[now.getDay()]+' '+now.getDate()+' '+months[now.getMonth()]+' '+now.getFullYear(); document.getElementById('topbar-date').textContent=now.toLocaleDateString('pt-BR'); } setInterval(updateClock,1000);updateClock(); // Midnight checklist reset function checkMidnightReset(){ const today=new Date().toDateString(); const lastDay=localStorage.getItem('blackpits_lastday'); if(lastDay&&lastDay!==today){data.checklist=data.checklist.filter(c=>!c.daily);save();} localStorage.setItem('blackpits_lastday',today); } checkMidnightReset(); // NAV // sections defined below function go(id){ sections.forEach(s=>document.getElementById('sec-'+s)?.classList.remove('active')); document.querySelectorAll('.nav-item').forEach(el=>el.classList.remove('active')); document.getElementById('sec-'+id)?.classList.add('active'); document.querySelectorAll('.nav-item').forEach(el=>{if(el.getAttribute('onclick')?.includes("'"+id+"'"))el.classList.add('active')}); document.getElementById('topbar-title').textContent=id.toUpperCase().replace('-',' '); const renders={notes:renderNotes,files:renderFiles,projects:renderProjects,trade:renderTrades,restaurante:()=>{renderDRE();renderCMVPratos();},financas:renderFinancas,cyber:renderCyber,engenharia:renderEngenharia,oficina:renderOficina,estudos:renderWords,arsenal:renderArsenal,checklist:renderChecklist,github:loadGHConfig,cronograma:renderCronograma,livros:renderLivros,radio:renderRadioStations,diario:renderDiario,habitos:renderHabitos,calculadora:()=>switchCalc('inv'),voztext:()=>{const k=localStorage.getItem('blackpits_gem_key');if(k){const el=document.getElementById('voz-gem-key');if(el)el.value=k;}},telegram:()=>setTimeout(loadTGConfig,100),ferramentas:renderFerramentas}; renders[id]?.(); if(window.innerWidth<=768)document.getElementById('sidebar').classList.remove('open'); } function toggleSidebar(){document.getElementById('sidebar').classList.toggle('open')} // KPIs function updateKPIs(){ document.getElementById('kpi-projects').textContent=data.projects.filter(p=>p.status!=='CONCLUÍDO').length; document.getElementById('kpi-notes').textContent=data.notes.length; document.getElementById('kpi-files').textContent=data.files.length; document.getElementById('kpi-trades').textContent=data.trades.filter(t=>t.status==='ABERTA').length; const pl=document.getElementById('home-projects-list'); const active=data.projects.filter(p=>p.status==='EM ANDAMENTO').slice(0,5); pl.innerHTML=active.length?active.map(p=>`
${p.priority}${p.name}${p.area}
`).join(''):'
Nenhum projeto ativo.
'; const nl=document.getElementById('home-notes-list'); const recent=[...data.notes].reverse().slice(0,5); nl.innerHTML=recent.length?recent.map(n=>`
${n.area}${n.title}
`).join(''):'
Nenhuma nota.
'; const hc=document.getElementById('home-checklist'); const today=data.checklist.filter(c=>c.daily).slice(0,6); hc.innerHTML=today.length?today.map(c=>`
${c.done?'✓':''}
${c.text}
`).join(''):'
Nenhuma tarefa hoje.
'; } // GLOBAL SEARCH function globalSearch(q){ const el=document.getElementById('search-results'); if(!q||q.length<2){el.style.display='none';return} const ql=q.toLowerCase(); const results=[]; data.notes.forEach(n=>{if(n.title?.toLowerCase().includes(ql)||n.content?.toLowerCase().includes(ql))results.push({title:n.title,meta:'NOTA — '+n.area,action:()=>go('notes')})}); data.files.forEach(f=>{if(f.name?.toLowerCase().includes(ql)||f.desc?.toLowerCase().includes(ql))results.push({title:f.name,meta:'ARQUIVO — '+f.area,url:f.url,action:()=>go('files')})}); data.projects.forEach(p=>{if(p.name?.toLowerCase().includes(ql)||p.desc?.toLowerCase().includes(ql))results.push({title:p.name,meta:'PROJETO — '+p.area+' / '+p.status,action:()=>go('projects')})}); data.cyber.forEach(c=>{if(c.name?.toLowerCase().includes(ql)||c.notes?.toLowerCase().includes(ql))results.push({title:c.name,meta:'CYBER — '+c.cat,action:()=>go('cyber')})}); data.arsenal.forEach(a=>{if(a.name?.toLowerCase().includes(ql))results.push({title:a.name,meta:'ARSENAL — '+a.cat,action:()=>go('arsenal')})}); data.trades.forEach(t=>{if(t.asset?.toLowerCase().includes(ql))results.push({title:t.asset,meta:'TRADE — '+t.market,action:()=>go('trade')})}); data.words.forEach(w=>{if(w.word?.toLowerCase().includes(ql)||w.trans?.toLowerCase().includes(ql))results.push({title:w.word,meta:'INGLÊS — '+w.trans,action:()=>go('estudos')})}); if(!results.length){el.innerHTML='
Nenhum resultado para "'+q+'"
';el.style.display='block';return} el.innerHTML=results.slice(0,8).map((r,i)=>`
${r.title}
${r.meta}
`).join(''); el._results=results; el.style.display='block'; } function searchGo(i){ const r=document.getElementById('search-results')._results[i]; r.action(); document.getElementById('search-results').style.display='none'; document.getElementById('global-search').value=''; } // PRINT function printSection(){window.print()} // EXPORT / IMPORT function exportData(){ const blob=new Blob([JSON.stringify(data,null,2)],{type:'application/json'}); const a=document.createElement('a');a.href=URL.createObjectURL(blob); a.download='blackpits_'+new Date().toISOString().slice(0,10)+'.json';a.click(); } function importData(e){ const file=e.target.files[0];if(!file)return; const reader=new FileReader(); reader.onload=function(ev){ try{ const imp=JSON.parse(ev.target.result); ['notes','files','projects','trades','dre','financas','cyber','engenharia','oficina','tech_notes','words','arsenal','checklist'].forEach(k=>{if(imp[k])data[k]=imp[k]}); save();alert('✓ Dados importados!');location.reload(); }catch{alert('Erro ao importar.');} };reader.readAsText(file); } // POMODORO let pomoTimer=null,pomoSeconds=0,pomoTotal=0,pomoMode='focus',pomoSession=1,pomoCycles=data.pomo_cycles||0,pomoRunning=false; function getPomoTimes(){return{focus:parseInt(document.getElementById('pomo-focus-time')?.value||25)*60,short:parseInt(document.getElementById('pomo-short-time')?.value||5)*60,long:parseInt(document.getElementById('pomo-long-time')?.value||15)*60,sessions:parseInt(document.getElementById('pomo-sessions')?.value||4)}} function resetPomo(){ clearInterval(pomoTimer);pomoRunning=false;pomoMode='focus';pomoSession=1; const t=getPomoTimes();pomoSeconds=t.focus;pomoTotal=t.focus; document.getElementById('pomo-btn').textContent='▶ INICIAR'; document.getElementById('pomo-mode-label').textContent='FOCO'; updatePomoDisplay(); } function updatePomoDisplay(){ const m=Math.floor(pomoSeconds/60).toString().padStart(2,'0'); const s=(pomoSeconds%60).toString().padStart(2,'0'); document.getElementById('pomo-display').textContent=m+':'+s; const pct=pomoTotal>0?(pomoSeconds/pomoTotal*100):100; document.getElementById('pomo-fill').style.width=pct+'%'; document.getElementById('pomo-session').textContent=pomoSession; document.getElementById('pomo-cycles').textContent=pomoCycles; } function togglePomo(){ if(pomoRunning){clearInterval(pomoTimer);pomoRunning=false;document.getElementById('pomo-btn').textContent='▶ INICIAR';} else{ pomoRunning=true;document.getElementById('pomo-btn').textContent='⏸ PAUSAR'; if(pomoSeconds===0)skipPomo(); pomoTimer=setInterval(()=>{ pomoSeconds--;updatePomoDisplay(); if(pomoSeconds<=0){clearInterval(pomoTimer);pomoRunning=false;completePomo();} },1000); } } function completePomo(){ const t=getPomoTimes(); const task=document.getElementById('pomo-task')?.value||'—'; const hist=document.getElementById('pomo-history'); const line=document.createElement('div'); if(pomoMode==='focus'){ line.textContent='✓ FOCO '+pomoSession+' — '+task+' ['+new Date().toLocaleTimeString('pt-BR').slice(0,5)+']'; line.style.color='var(--green)'; if(pomoSession>=t.sessions){pomoMode='long';pomoSeconds=t.long;pomoTotal=t.long;pomoCycles++;data.pomo_cycles=pomoCycles;save();} else{pomoMode='short';pomoSeconds=t.short;pomoTotal=t.short;} }else{ line.textContent='— PAUSA — ['+new Date().toLocaleTimeString('pt-BR').slice(0,5)+']'; line.style.color='var(--text3)'; if(pomoMode==='long')pomoSession=1;else pomoSession++; pomoMode='focus';pomoSeconds=t.focus;pomoTotal=t.focus; } hist.prepend(line); document.getElementById('pomo-mode-label').textContent=pomoMode==='focus'?'FOCO':pomoMode==='short'?'PAUSA CURTA':'PAUSA LONGA'; document.getElementById('pomo-btn').textContent='▶ INICIAR'; updatePomoDisplay(); if('Notification' in window&&Notification.permission==='granted')new Notification('BLACKPITS OS',{body:pomoMode==='focus'?'Hora de focar!':'Hora de descansar!'}); } function skipPomo(){completePomo()} // CHECKLIST function saveCheck(){ const text=document.getElementById('chk-text').value.trim();if(!text)return; data.checklist.push({id:uid(),text,area:document.getElementById('chk-area').value,priority:document.getElementById('chk-priority').value,done:false,daily:true,ts:Date.now()}); save();renderChecklist();document.getElementById('chk-text').value=''; } function toggleCheck(id){const c=data.checklist.find(c=>c.id===id);if(c){c.done=!c.done;save();renderChecklist();updateKPIs();}} function deleteCheck(id){data.checklist=data.checklist.filter(c=>c.id!==id);save();renderChecklist();} function clearChecklist(){data.checklist=[];save();renderChecklist();} function renderChecklist(){ const items=data.checklist; const done=items.filter(c=>c.done).length; const total=items.length; document.getElementById('chk-count').textContent=total; document.getElementById('chk-progress-text').textContent=done+' / '+total+' concluídas'; document.getElementById('chk-progress-bar').style.width=(total?Math.round(done/total*100):0)+'%'; const el=document.getElementById('checklist-items'); const pc={ALTA:'red',NORMAL:'',BAIXA:''}; const sorted=[...items].sort((a,b)=>a.done-b.done); el.innerHTML=sorted.length?sorted.map(c=>`
${c.done?'✓':''}
${c.text} ${c.area}
`).join(''):'
Nenhuma tarefa. Adicione acima.
'; updateKPIs(); } // ARSENAL function saveArsenal(){ const name=document.getElementById('ar-name').value.trim();if(!name)return; data.arsenal.push({id:uid(),name,cat:document.getElementById('ar-cat').value,type:document.getElementById('ar-type').value,status:document.getElementById('ar-status').value,loc:document.getElementById('ar-loc').value,model:document.getElementById('ar-model').value,obs:document.getElementById('ar-obs').value,ts:Date.now()}); save();renderArsenal(); ['ar-name','ar-model','ar-obs'].forEach(id=>document.getElementById(id).value=''); } function deleteArsenal(id){data.arsenal=data.arsenal.filter(a=>a.id!==id);save();renderArsenal()} function renderArsenal(){ const fc=document.getElementById('ar-filter-cat').value; const fs=document.getElementById('ar-filter-status').value; let list=data.arsenal; if(fc)list=list.filter(a=>a.cat===fc); if(fs)list=list.filter(a=>a.status===fs); document.getElementById('ar-total').textContent=data.arsenal.length; document.getElementById('ar-ok').textContent=data.arsenal.filter(a=>a.status==='OPERACIONAL').length; const sc={OPERACIONAL:'green','EM MANUTENÇÃO':'amber',QUEBRADO:'red',EMPRESTADO:'blue',INATIVO:''}; const el=document.getElementById('arsenal-list'); el.innerHTML=list.length?list.map(a=>`
${a.name}${a.model?' — '+a.model+'':''}
${a.cat}${a.type}${a.loc}
${a.obs?`
${a.obs}
`:''}
${a.status}
`).join(''):'
Nenhuma ferramenta registrada.
'; } // NOTES function saveNote(){ const title=document.getElementById('note-title').value.trim();if(!title)return; data.notes.push({id:uid(),title,area:document.getElementById('note-area').value,content:document.getElementById('note-content').value,ts:Date.now()}); save();renderNotes();document.getElementById('note-title').value='';document.getElementById('note-content').value=''; } function deleteNote(id){data.notes=data.notes.filter(n=>n.id!==id);save();renderNotes()} function renderNotes(){ const filter=document.getElementById('note-filter').value; let notes=filter?data.notes.filter(n=>n.area===filter):data.notes; notes=[...notes].reverse(); document.getElementById('note-count').textContent=notes.length; document.getElementById('notes-list').innerHTML=notes.length?notes.map(n=>`
${n.title}
${n.area}
${(n.content||'').slice(0,140)}${(n.content?.length>140)?'...':''}
${dateStr(n.ts)}
`).join(''):'
Nenhuma nota.
'; } // FILES function saveFile(){ const name=document.getElementById('file-name').value.trim();if(!name)return; data.files.push({id:uid(),name,type:document.getElementById('file-type').value,area:document.getElementById('file-area').value,url:document.getElementById('file-url').value,desc:document.getElementById('file-desc').value,ts:Date.now()}); save();renderFiles();['file-name','file-url','file-desc'].forEach(id=>document.getElementById(id).value=''); } function deleteFile(id){data.files=data.files.filter(f=>f.id!==id);save();renderFiles()} function renderFiles(){ const fa=document.getElementById('file-filter-area').value; const ft=document.getElementById('file-filter-type').value; let files=data.files; if(fa)files=files.filter(f=>f.area===fa); if(ft)files=files.filter(f=>f.type===ft); files=[...files].reverse(); document.getElementById('file-total').textContent=data.files.length; document.getElementById('file-html-count').textContent=data.files.filter(f=>f.type==='HTML').length; const tc={PDF:'red',HTML:'blue',SCRIPT:'green',RELATÓRIO:'amber'}; document.getElementById('files-list').innerHTML=files.length?files.map(f=>`
${f.type}
${f.name}
${f.area}${f.desc?' — '+f.desc:''}
${f.url?``:''}
`).join(''):'
Nenhum arquivo.
'; } // PROJECTS function saveProject(){ const name=document.getElementById('proj-name').value.trim();if(!name)return; data.projects.push({id:uid(),name,area:document.getElementById('proj-area').value,priority:document.getElementById('proj-priority').value,desc:document.getElementById('proj-desc').value,status:'BACKLOG',ts:Date.now()}); save();renderProjects();document.getElementById('proj-name').value='';document.getElementById('proj-desc').value=''; } function moveProject(id,status){const p=data.projects.find(p=>p.id===id);if(p){p.status=status;save();renderProjects()}} function deleteProject(id){data.projects=data.projects.filter(p=>p.id!==id);save();renderProjects()} function renderProjects(){ const statuses=['BACKLOG','EM ANDAMENTO','CONCLUÍDO']; const ids=['kanban-backlog','kanban-active','kanban-done']; const pc={ALTA:'red',MÉDIA:'amber',BAIXA:''}; statuses.forEach((s,i)=>{ const ps=data.projects.filter(p=>p.status===s); document.getElementById(ids[i]).innerHTML=ps.length?ps.map(p=>`
${p.priority}${p.area}
${p.name}
${p.desc?`
${p.desc}
`:''}
${s!=='BACKLOG'?``:''} ${s!=='EM ANDAMENTO'?``:''} ${s!=='CONCLUÍDO'?``:''}
`).join(''):'
Vazio
'; }); updateKPIs(); } // TRADES function saveTrade(){ const asset=document.getElementById('t-asset').value.trim();if(!asset)return; const res=parseFloat(document.getElementById('t-res').value)||0; data.trades.push({id:uid(),asset,market:document.getElementById('t-market').value,dir:document.getElementById('t-dir').value,status:document.getElementById('t-status').value,entry:document.getElementById('t-entry').value,sl:document.getElementById('t-sl').value,tp:document.getElementById('t-tp').value,result:res,emotion:document.getElementById('t-emotion').value,notes:document.getElementById('t-notes').value,ts:Date.now()}); save();renderTrades();document.getElementById('t-asset').value='';document.getElementById('t-res').value='';document.getElementById('t-notes').value=''; } function deleteTrade(id){data.trades=data.trades.filter(t=>t.id!==id);save();renderTrades()} function renderTrades(){ const closed=data.trades.filter(t=>t.status==='FECHADA'); const wins=closed.filter(t=>t.result>0).length; const totalRes=closed.reduce((a,t)=>a+t.result,0); const wr=closed.length?Math.round(wins/closed.length*100):0; document.getElementById('t-total').textContent=data.trades.length; document.getElementById('t-wr').textContent=wr+'%'; const rv=document.getElementById('t-result');rv.textContent=fmt(totalRes);rv.className='card-val '+(totalRes>=0?'trade-positive':'trade-negative'); document.getElementById('t-open').textContent=data.trades.filter(t=>t.status==='ABERTA').length; const trades=[...data.trades].reverse(); document.getElementById('trade-list').innerHTML=trades.length?trades.map(t=>`
${t.dir}${t.asset}${t.market}
E:${t.entry||'—'}SL:${t.sl||'—'}TP:${t.tp||'—'}
${t.status} ${t.result?fmt(t.result):''} ${t.emotion}
`).join(''):'
Nenhuma operação.
'; } // DRE function saveDRE(){ const mes=document.getElementById('r-mes').value.trim();if(!mes)return; const rec=parseFloat(document.getElementById('r-rec-bruta').value)||0; const imp=parseFloat(document.getElementById('r-impostos').value)||0; const cmv=parseFloat(document.getElementById('r-cmv-val').value)||0; const folha=parseFloat(document.getElementById('r-folha').value)||0; const alug=parseFloat(document.getElementById('r-aluguel').value)||0; const en=parseFloat(document.getElementById('r-energia').value)||0; const recLiq=rec-imp; const lucro=recLiq-(cmv+folha+alug+en); const cmvPct=rec?Math.round(cmv/rec*100):0; const margem=recLiq?Math.round(lucro/recLiq*100):0; data.dre.push({id:uid(),mes,rec,imp,recLiq,cmv,folha,alug,en,lucro,cmvPct,margem,ts:Date.now()}); save();renderDRE();document.getElementById('r-mes').value=''; ['r-rec-bruta','r-impostos','r-cmv-val','r-folha','r-aluguel','r-energia'].forEach(id=>document.getElementById(id).value=''); } function deleteDRE(id){data.dre=data.dre.filter(d=>d.id!==id);save();renderDRE()} function renderDRE(){ const last=data.dre.length?data.dre[data.dre.length-1]:null; document.getElementById('r-receita').textContent=last?fmt(last.rec):'R$0'; document.getElementById('r-cmv').textContent=last?(last.cmvPct+(last.cmvPct>35?'% ⚠':'%')):'0%'; document.getElementById('r-lucro').textContent=last?fmt(last.lucro):'R$0'; document.getElementById('r-margem').textContent=last?last.margem+'%':'0%'; const list=[...data.dre].reverse(); document.getElementById('dre-list').innerHTML=list.length?list.map(d=>`
${d.mes}
RECEITA
${fmt(d.rec)}
LUCRO
${fmt(d.lucro)}
CMV
${d.cmvPct}%${d.cmvPct>35?' ⚠':''}
MARGEM
${d.margem}%
`).join(''):'
Nenhum DRE.
'; } // FINANCAS function saveFinanca(){ const desc=document.getElementById('f-desc').value.trim();if(!desc)return; data.financas.push({id:uid(),desc,tipo:document.getElementById('f-tipo').value,valor:parseFloat(document.getElementById('f-valor').value)||0,cat:document.getElementById('f-cat').value,ts:Date.now()}); save();renderFinancas();document.getElementById('f-desc').value='';document.getElementById('f-valor').value=''; } function deleteFinanca(id){data.financas=data.financas.filter(f=>f.id!==id);save();renderFinancas()} function renderFinancas(){ const rec=data.financas.filter(f=>f.tipo==='RECEITA').reduce((a,f)=>a+f.valor,0); const desp=data.financas.filter(f=>f.tipo==='DESPESA').reduce((a,f)=>a+f.valor,0); const inv=data.financas.filter(f=>f.tipo==='INVESTIMENTO').reduce((a,f)=>a+f.valor,0); document.getElementById('f-rec').textContent=fmt(rec); document.getElementById('f-desp').textContent=fmt(desp); document.getElementById('f-saldo').textContent=fmt(rec-desp); document.getElementById('f-inv').textContent=fmt(inv); const tc={RECEITA:'green',DESPESA:'red',INVESTIMENTO:'blue'}; const list=[...data.financas].reverse(); document.getElementById('financas-list').innerHTML=list.length?list.map(f=>`
${f.tipo}
${f.desc}
${f.cat}
${fmt(f.valor)}
`).join(''):'
Nenhum lançamento.
'; } // CYBER function saveCyber(){ const name=document.getElementById('cy-name').value.trim();if(!name)return; data.cyber.push({id:uid(),name,cat:document.getElementById('cy-cat').value,type:document.getElementById('cy-type').value,level:document.getElementById('cy-level').value,tools:document.getElementById('cy-tools').value,notes:document.getElementById('cy-notes').value,ts:Date.now()}); save();renderCyber();document.getElementById('cy-name').value='';document.getElementById('cy-tools').value='';document.getElementById('cy-notes').value=''; } function deleteCyber(id){data.cyber=data.cyber.filter(c=>c.id!==id);save();renderCyber()} function renderCyber(){ const filter=document.getElementById('cy-filter').value; let list=filter?data.cyber.filter(c=>c.cat===filter):data.cyber; list=[...list].reverse(); const lc={'DESCONHEÇO':'','VI MAS NÃO PRATIQUEI':'red',PRATICANDO:'amber',DOMINADO:'green'}; document.getElementById('cyber-list').innerHTML=list.length?list.map(c=>`
${c.cat}${c.type}${c.level}
${c.name}
${c.tools?`
TOOLS: ${c.tools}
`:''} ${c.notes?`
${c.notes.slice(0,120)}
`:''}
`).join(''):'
Nenhuma entrada.
'; } // ENGENHARIA function saveEngenharia(){ const name=document.getElementById('eng-name').value.trim();if(!name)return; data.engenharia.push({id:uid(),name,type:document.getElementById('eng-type').value,status:document.getElementById('eng-status').value,desc:document.getElementById('eng-desc').value,ts:Date.now()}); save();renderEngenharia();document.getElementById('eng-name').value='';document.getElementById('eng-desc').value=''; } function deleteEngenharia(id){data.engenharia=data.engenharia.filter(e=>e.id!==id);save();renderEngenharia()} function renderEngenharia(){ const list=[...data.engenharia].reverse(); const sc={PLANEJANDO:'blue','EM EXECUÇÃO':'amber',PAUSADO:'red',CONCLUÍDO:'green'}; document.getElementById('eng-list').innerHTML=list.length?list.map(e=>`
${e.type}${e.status}
${e.name}
${e.desc?`
${e.desc.slice(0,120)}
`:''}
`).join(''):'
Nenhum projeto.
'; } // OFICINA function saveOficina(){ const name=document.getElementById('of-name').value.trim();if(!name)return; data.oficina.push({id:uid(),name,type:document.getElementById('of-type').value,status:document.getElementById('of-status').value,cost:parseFloat(document.getElementById('of-cost').value)||0,priority:document.getElementById('of-priority').value,materials:document.getElementById('of-materials').value,ts:Date.now()}); save();renderOficina();document.getElementById('of-name').value='';document.getElementById('of-materials').value='';document.getElementById('of-cost').value=''; } function deleteOficina(id){data.oficina=data.oficina.filter(o=>o.id!==id);save();renderOficina()} function renderOficina(){ const list=[...data.oficina].reverse(); const sc={IDEIA:'',PLANEJANDO:'blue','COMPRANDO MATERIAL':'amber','EM EXECUÇÃO':'green',CONCLUÍDO:'green'}; const pc={ALTA:'red',MÉDIA:'amber',BAIXA:''}; document.getElementById('of-list').innerHTML=list.length?list.map(o=>`
${o.type}${o.status}${o.priority}
${o.name}
${o.cost?`
CUSTO EST.: ${fmt(o.cost)}
`:''} ${o.materials?`
${o.materials.slice(0,100)}
`:''}
`).join(''):'
Nenhum projeto.
'; } // TECH NOTES function saveTechNote(){ const content=document.getElementById('tech-notes-input').value.trim();if(!content)return; data.tech_notes.push({id:uid(),content,ts:Date.now()}); save();renderTechNotes();document.getElementById('tech-notes-input').value=''; } function deleteTechNote(id){data.tech_notes=data.tech_notes.filter(n=>n.id!==id);save();renderTechNotes()} function renderTechNotes(){ const list=[...data.tech_notes].reverse(); document.getElementById('tech-notes-list').innerHTML=list.length?list.map(n=>`
${dateStr(n.ts)}
${n.content}
`).join(''):''; } // WORDS function saveWord(){ const word=document.getElementById('en-word').value.trim();if(!word)return; data.words.push({id:uid(),word,trans:document.getElementById('en-trans').value,type:document.getElementById('en-type').value,example:document.getElementById('en-example').value,mastered:document.getElementById('en-mastered').value,ts:Date.now()}); save();renderWords();document.getElementById('en-word').value='';document.getElementById('en-trans').value='';document.getElementById('en-example').value=''; } function deleteWord(id){data.words=data.words.filter(w=>w.id!==id);save();renderWords()} function renderWords(){ const filter=document.getElementById('en-filter').value; let list=filter?data.words.filter(w=>w.mastered===filter):data.words; list=[...list].reverse(); document.getElementById('word-count').textContent=data.words.length; const mc={SIM:'green',PARCIAL:'amber','NÃO':'red'}; document.getElementById('words-list').innerHTML=list.length?list.map(w=>`
${w.word}${w.type}${w.mastered}
${w.trans}
${w.example?`
"${w.example}"
`:''}
`).join(''):'
Nenhuma palavra.
'; } // CMV CALCULATOR if(!data.cmv_pratos)data.cmv_pratos=[]; function calcCMV(){ const custo=parseFloat(document.getElementById('cmv-custo').value)||0; const preco=parseFloat(document.getElementById('cmv-preco').value)||0; if(!custo||!preco){document.getElementById('cmv-result').style.display='none';return} const pct=Math.round(custo/preco*100); const lucro=preco-custo; const margem=Math.round(lucro/preco*100); const el=document.getElementById('cmv-result'); el.style.display='block'; const color=pct<=30?'var(--green)':pct<=35?'var(--amber)':'var(--red)'; document.getElementById('cmv-pct').textContent=pct+'%'; document.getElementById('cmv-pct').style.color=color; document.getElementById('cmv-lucro').textContent='R$'+lucro.toFixed(2); document.getElementById('cmv-margem').textContent=margem+'%'; const status=pct<=30?'✓ EXCELENTE':pct<=35?'✓ BOM':pct<=40?'⚠ ATENÇÃO':'✗ CRÍTICO'; document.getElementById('cmv-status').textContent=status; document.getElementById('cmv-status').style.color=color; document.getElementById('cmv-bar').style.background=`linear-gradient(to right,${color} ${Math.min(pct,100)}%,var(--bg4) ${Math.min(pct,100)}%)`; } function calcSugest(){ const c=parseFloat(document.getElementById('sugest-custo').value)||0; if(!c){document.getElementById('sugest-result').textContent='';return} const p30=(c/0.30).toFixed(2); const p35=(c/0.35).toFixed(2); document.getElementById('sugest-result').innerHTML=`CMV 30%: R$${p30}
CMV 35%: R$${p35}`; } function saveCMVPrato(){ const nome=document.getElementById('cmv-prato').value.trim(); const custo=parseFloat(document.getElementById('cmv-custo').value)||0; const preco=parseFloat(document.getElementById('cmv-preco').value)||0; if(!nome||!custo||!preco)return; if(!data.cmv_pratos)data.cmv_pratos=[]; data.cmv_pratos.push({id:uid(),nome,custo,preco,pct:Math.round(custo/preco*100),ts:Date.now()}); save();renderCMVPratos(); } function deleteCMVPrato(id){data.cmv_pratos=data.cmv_pratos.filter(p=>p.id!==id);save();renderCMVPratos()} function renderCMVPratos(){ if(!data.cmv_pratos)return; const el=document.getElementById('cmv-pratos-list'); if(!el)return; const list=[...data.cmv_pratos].reverse(); el.innerHTML=list.length?list.map(p=>{ const c=p.pct<=30?'var(--green)':p.pct<=35?'var(--amber)':'var(--red)'; return `
${p.nome}
${p.pct}% CMVR$${p.preco.toFixed(2)}
`; }).join(''):'
Nenhum prato salvo.
'; } // OCR let ocrBase64=null,ocrMime=null; function previewOCR(e){ const file=e.target.files[0];if(!file)return; if(file.type==='application/pdf'){ document.getElementById('ocr-preview').style.display='none'; document.getElementById('ocr-status').textContent='PDF selecionado: '+file.name; ocrMime='application/pdf'; }else{ const reader=new FileReader(); reader.onload=ev=>{ ocrBase64=ev.target.result.split(',')[1]; ocrMime=file.type; const img=document.getElementById('ocr-img-preview'); img.src=ev.target.result; document.getElementById('ocr-preview').style.display='block'; document.getElementById('ocr-status').textContent='Imagem pronta.'; };reader.readAsDataURL(file); } if(file.type==='application/pdf'){ const reader=new FileReader(); reader.onload=ev=>{ocrBase64=ev.target.result.split(',')[1];}; reader.readAsDataURL(file); } } async function runOCR(){ const key=document.getElementById('ocr-apikey').value.trim(); if(!key){alert('Insira sua chave API Anthropic.');return} if(!ocrBase64){alert('Selecione uma imagem ou PDF.');return} const prompt=document.getElementById('ocr-prompt').value||'Extraia todo o texto e conteúdo importante deste documento de forma organizada.'; const status=document.getElementById('ocr-status'); const result=document.getElementById('ocr-result'); status.textContent='⟳ Processando com IA...'; result.textContent='Aguarde...'; localStorage.setItem('blackpits_ocr_key',key); try{ const resp=await fetch('https://api.anthropic.com/v1/messages',{ method:'POST', headers:{'Content-Type':'application/json','x-api-key':key,'anthropic-version':'2023-06-01'}, body:JSON.stringify({ model:'claude-opus-4-5',max_tokens:2000, messages:[{role:'user',content:[ {type:ocrMime==='application/pdf'?'document':'image',source:{type:'base64',media_type:ocrMime,data:ocrBase64}}, {type:'text',text:prompt} ]}] }) }); const d=await resp.json(); if(d.error){status.textContent='Erro: '+d.error.message;result.textContent='';return} const text=d.content?.map(c=>c.text||'').join('\n')||'Sem resultado.'; result.textContent=text; status.textContent='✓ Concluído — '+text.length+' caracteres extraídos.'; result._lastText=text; }catch(err){status.textContent='Erro: '+err.message;result.textContent='';} } function saveOCRNote(){ const text=document.getElementById('ocr-result')._lastText||document.getElementById('ocr-result').textContent; if(!text||text.includes('Envie uma'))return; data.notes.push({id:uid(),title:'OCR — '+new Date().toLocaleDateString('pt-BR'),area:'GERAL',content:text,ts:Date.now()}); save();alert('✓ Salvo como nota!'); } // Restore OCR key const savedOCRKey=localStorage.getItem('blackpits_ocr_key'); if(savedOCRKey){document.addEventListener('DOMContentLoaded',()=>{const el=document.getElementById('ocr-apikey');if(el)el.value=savedOCRKey;});} // GITHUB SYNC function saveGHConfig(){ localStorage.setItem('blackpits_gh',JSON.stringify({ token:document.getElementById('gh-token').value, user:document.getElementById('gh-user').value, repo:document.getElementById('gh-repo').value, filename:document.getElementById('gh-filename').value||'data.json' })); } function loadGHConfig(){ const cfg=JSON.parse(localStorage.getItem('blackpits_gh')||'{}'); if(cfg.token)document.getElementById('gh-token').value=cfg.token; if(cfg.user)document.getElementById('gh-user').value=cfg.user; if(cfg.repo)document.getElementById('gh-repo').value=cfg.repo; if(cfg.filename)document.getElementById('gh-filename').value=cfg.filename; return cfg; } async function ghPush(){ const cfg=loadGHConfig(); if(!cfg.token||!cfg.user||!cfg.repo){alert('Configure token, usuário e repositório.');return} const status=document.getElementById('gh-status'); status.style.color='var(--text3)';status.textContent='⟳ Enviando para GitHub...'; const content=btoa(unescape(encodeURIComponent(JSON.stringify(data,null,2)))); const filename=cfg.filename||'data.json'; const url=`https://api.github.com/repos/${cfg.user}/${cfg.repo}/contents/${filename}`; try{ // Get current SHA if exists let sha=''; const get=await fetch(url,{headers:{'Authorization':'token '+cfg.token,'Accept':'application/vnd.github.v3+json'}}); if(get.ok){const gd=await get.json();sha=gd.sha;} const body={message:'BLACKPITS OS backup — '+new Date().toISOString(),content}; if(sha)body.sha=sha; const resp=await fetch(url,{method:'PUT',headers:{'Authorization':'token '+cfg.token,'Accept':'application/vnd.github.v3+json','Content-Type':'application/json'},body:JSON.stringify(body)}); if(resp.ok){ const now=new Date().toLocaleString('pt-BR'); status.style.color='var(--green)';status.textContent='✓ Push realizado com sucesso em '+now; document.getElementById('gh-last-sync').textContent='Último push: '+now; localStorage.setItem('blackpits_gh_last',now); }else{const e=await resp.json();status.style.color='var(--red)';status.textContent='Erro: '+e.message;} }catch(err){status.style.color='var(--red)';status.textContent='Erro: '+err.message;} } async function ghPull(){ const cfg=loadGHConfig(); if(!cfg.token||!cfg.user||!cfg.repo){alert('Configure token, usuário e repositório.');return} const status=document.getElementById('gh-status'); status.style.color='var(--text3)';status.textContent='⟳ Carregando do GitHub...'; const filename=cfg.filename||'data.json'; const url=`https://api.github.com/repos/${cfg.user}/${cfg.repo}/contents/${filename}`; try{ const resp=await fetch(url,{headers:{'Authorization':'token '+cfg.token,'Accept':'application/vnd.github.v3+json'}}); if(!resp.ok){const e=await resp.json();status.style.color='var(--red)';status.textContent='Erro: '+e.message;return} const d=await resp.json(); const text=decodeURIComponent(escape(atob(d.content.replace(/\n/g,'')))); const imported=JSON.parse(text); ['notes','files','projects','trades','dre','financas','cyber','engenharia','oficina','tech_notes','words','arsenal','checklist','cmv_pratos'].forEach(k=>{if(imported[k])data[k]=imported[k]}); save(); const now=new Date().toLocaleString('pt-BR'); status.style.color='var(--green)';status.textContent='✓ Pull realizado com sucesso em '+now; document.getElementById('gh-last-sync').textContent='Último pull: '+now; alert('✓ Dados carregados do GitHub!');location.reload(); }catch(err){status.style.color='var(--red)';status.textContent='Erro: '+err.message;} } // GEMINI CHAT const GEM_CONTEXTS={ geral:`Você é um assistente pessoal de Vinícius, um engenheiro civil e químico, dono de restaurante, praticante de OSINT e pentest, trader e marceneiro/serralheiro. Responda de forma direta e técnica.`, cyber:`Você é um especialista em cybersecurity. Vinícius pratica OSINT e pentest, usa BlackArch, tem RTL-SDR, Digispark, Raspberry Pi e está construindo um dispositivo equivalente ao Flipper Zero. Ajude com técnicas, ferramentas, CVEs, OSINT e red team. Seja técnico e direto.`, trade:`Você é um analista financeiro e trader especialista em forex, ações e renda fixa. Vinícius está aprendendo a operar no mercado financeiro. Ajude com análise técnica, gestão de risco, setups, psicologia do trading e estratégias. Seja objetivo.`, restaurante:`Você é um consultor especialista em gestão de restaurantes. Vinícius é dono de restaurante e precisa de ajuda com CMV, fluxo de caixa, cardápio, gestão de equipe e operação. Foque em KPIs práticos e lucratividade.`, engenharia:`Você é um engenheiro sênior em civil e química. Vinícius tem formação em engenharia civil e é acadêmico em química. Ajude com cálculos, normas ABNT, projetos estruturais, processos químicos e dimensionamentos técnicos.`, oficina:`Você é um especialista em marcenaria e serralheria. Vinícius tem uma oficina com compressor, ferramentas de metalworking e faz projetos customizados. Ajude com técnicas, materiais, cortes, solda e projetos.`, ingles:`Você é um professor de inglês nativo. Vinícius está estudando inglês para fluência. Corrija erros, explique gramática, ensine vocabulário e expressões idiomáticas. Sempre responda em inglês e depois traduza se necessário.`, financas:`Você é um consultor financeiro pessoal. Ajude Vinícius com controle de gastos, investimentos em renda fixa, ações e forex, planejamento financeiro e análise de patrimônio. Seja prático e objetivo.` }; let gemHistory=[]; let gemCtx='geral'; function setGemContext(){ gemCtx=document.getElementById('gem-ctx').value; document.getElementById('gem-ctx-display').textContent=GEM_CONTEXTS[gemCtx]; gemHistory=[]; document.getElementById('gem-messages').innerHTML='
Contexto: '+document.getElementById('gem-ctx').options[document.getElementById('gem-ctx').selectedIndex].text+'
'; } function getGemKey(){ const k=document.getElementById('gem-key')?.value||localStorage.getItem('blackpits_gem_key')||''; return k.trim(); } function buildDataContext(){ const parts=[]; if(data.dre?.length){const last=data.dre[data.dre.length-1];parts.push(`DRE mais recente (${last.mes}): Receita R$${last.rec?.toFixed(2)}, CMV ${last.cmvPct}%, Lucro R$${last.lucro?.toFixed(2)}, Margem ${last.margem}%`);} if(data.trades?.length){const closed=data.trades.filter(t=>t.status==='FECHADA');const wins=closed.filter(t=>t.result>0).length;parts.push(`Trades: ${data.trades.length} total, ${closed.length} fechados, win rate ${closed.length?Math.round(wins/closed.length*100):0}%`);} if(data.projects?.length){const active=data.projects.filter(p=>p.status==='EM ANDAMENTO');parts.push(`Projetos: ${active.length} ativos de ${data.projects.length} total`);} if(data.arsenal?.length)parts.push(`Arsenal: ${data.arsenal.length} ferramentas registradas`); if(data.cyber?.length)parts.push(`Base cyber: ${data.cyber.length} técnicas/ferramentas registradas`); return parts.length?'\n\nCONTEXTO DOS DADOS DO USUÁRIO:\n'+parts.join('\n'):''; } function addMessage(role,text,loading=false){ const el=document.getElementById('gem-messages'); const div=document.createElement('div'); const isUser=role==='user'; div.style.cssText=`display:flex;flex-direction:column;align-items:${isUser?'flex-end':'flex-start'};gap:4px`; div.innerHTML=`
${isUser?'VOCÊ':'GEMINI'}
${text}
`; el.appendChild(div); el.scrollTop=el.scrollHeight; return div; } async function sendGemini(){ const key=getGemKey(); if(!key){alert('Configure sua chave API Gemini.');return;} const input=document.getElementById('gem-input'); const msg=input.value.trim(); if(!msg)return; input.value=''; addMessage('user',msg); gemHistory.push({role:'user',parts:[{text:msg}]}); const status=document.getElementById('gem-status'); status.textContent='⟳ Gemini está pensando...'; const loadDiv=addMessage('assistant','⟳','loading'); const systemPrompt=GEM_CONTEXTS[gemCtx]+buildDataContext(); try{ const body={ system_instruction:{parts:[{text:systemPrompt}]}, contents:gemHistory }; const resp=await fetch(`https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent?key=${key}`,{ method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify(body) }); const d=await resp.json(); if(d.error){loadDiv.querySelector('div:last-child').textContent='Erro: '+d.error.message;status.textContent='';return;} const reply=d.candidates?.[0]?.content?.parts?.[0]?.text||'Sem resposta.'; loadDiv.querySelector('div:last-child').textContent=reply; loadDiv.querySelector('div:last-child').id=''; gemHistory.push({role:'model',parts:[{text:reply}]}); status.textContent=''; }catch(err){loadDiv.querySelector('div:last-child').textContent='Erro: '+err.message;status.textContent='';} } function clearChat(){gemHistory=[];document.getElementById('gem-messages').innerHTML='
Chat limpo.
';} // RELATÓRIOS IA const REL_PROMPTS={ dre:(d)=>{ const list=d.dre?.slice(-6)||[]; const txt=list.map(r=>`${r.mes}: Receita R$${r.rec?.toFixed(2)}, CMV ${r.cmvPct}%, Folha R$${r.folha?.toFixed(2)}, Lucro R$${r.lucro?.toFixed(2)}, Margem ${r.margem}%`).join('\n'); return `Analise os dados financeiros do restaurante abaixo e gere um relatório executivo completo em português. Identifique tendências, pontos críticos (CMV acima de 35% é alerta), compare períodos, sugira ações concretas de melhoria.\n\nDADOS DRE:\n${txt||'Sem dados ainda.'}`; }, trade:(d)=>{ const trades=d.trades||[]; const closed=trades.filter(t=>t.status==='FECHADA'); const wins=closed.filter(t=>t.result>0); const losses=closed.filter(t=>t.result<=0); const totalRes=closed.reduce((a,t)=>a+(t.result||0),0); const emotions=[...new Set(trades.map(t=>t.emotion))].join(', '); return `Analise a performance de trading abaixo e gere um relatório completo em português com análise psicológica e técnica.\n\nDADOS:\nTotal de trades: ${trades.length}\nFechados: ${closed.length}\nVitórias: ${wins.length}\nDerrotas: ${losses.length}\nWin rate: ${closed.length?Math.round(wins.length/closed.length*100):0}%\nResultado total: R$${totalRes.toFixed(2)}\nEstados emocionais registrados: ${emotions||'N/A'}\nMercados operados: ${[...new Set(trades.map(t=>t.market))].join(', ')||'N/A'}`; }, projetos:(d)=>{ const proj=d.projects||[]; const por_status={'BACKLOG':0,'EM ANDAMENTO':0,'CONCLUÍDO':0}; proj.forEach(p=>por_status[p.status]=(por_status[p.status]||0)+1); const lista=proj.filter(p=>p.status==='EM ANDAMENTO').map(p=>`${p.name} [${p.area}] — Prioridade: ${p.priority}`).join('\n'); return `Gere um relatório de status de projetos em português.\n\nDADOS:\nTotal: ${proj.length}\nBacklog: ${por_status['BACKLOG']}\nEm andamento: ${por_status['EM ANDAMENTO']}\nConcluídos: ${por_status['CONCLUÍDO']}\n\nPROJETOS ATIVOS:\n${lista||'Nenhum'}`; }, cyber:(d)=>{ const items=d.cyber||[]; const por_nivel={}; items.forEach(c=>{por_nivel[c.level]=(por_nivel[c.level]||0)+1;}); const por_cat={}; items.forEach(c=>{por_cat[c.cat]=(por_cat[c.cat]||0)+1;}); return `Analise a base de conhecimento em cybersecurity abaixo e gere um relatório com gaps de conhecimento e sugestões de estudo prioritário.\n\nDADOS:\nTotal de itens: ${items.length}\nPor nível: ${JSON.stringify(por_nivel)}\nPor categoria: ${JSON.stringify(por_cat)}`; }, oficina:(d)=>{ const proj=d.oficina||[]; const lista=proj.map(p=>`${p.name} [${p.type}] — Status: ${p.status}, Custo est.: R$${(p.cost||0).toFixed(2)}`).join('\n'); const total=proj.reduce((a,p)=>a+(p.cost||0),0); return `Gere um relatório dos projetos da oficina (marcenaria/serralheria) em português.\n\nDADOS:\nTotal projetos: ${proj.length}\nCusto total estimado: R$${total.toFixed(2)}\n\nLISTA:\n${lista||'Nenhum projeto.'}`; }, semanal:(d)=>{ const parts=[]; if(d.projects)parts.push(`Projetos: ${d.projects.filter(p=>p.status==='EM ANDAMENTO').length} ativos, ${d.projects.filter(p=>p.status==='CONCLUÍDO').length} concluídos`); if(d.trades){const closed=d.trades.filter(t=>t.status==='FECHADA');const wins=closed.filter(t=>t.result>0);parts.push(`Trades: ${d.trades.length} total, win rate ${closed.length?Math.round(wins.length/closed.length*100):0}%`);} if(d.dre?.length){const l=d.dre[d.dre.length-1];parts.push(`Restaurante (último mês): Receita R$${l.rec?.toFixed(2)}, CMV ${l.cmvPct}%, Lucro R$${l.lucro?.toFixed(2)}`);} if(d.notes)parts.push(`Notas registradas: ${d.notes.length}`); if(d.cyber)parts.push(`Base cyber: ${d.cyber.length} técnicas`); if(d.words)parts.push(`Inglês: ${d.words.length} palavras, ${d.words.filter(w=>w.mastered==='SIM').length} dominadas`); return `Gere um resumo semanal executivo em português de todas as áreas de vida e trabalho de Vinícius. Destaque progresso, alertas e próximos passos recomendados.\n\nDADOS CONSOLIDADOS:\n${parts.join('\n')}`; } }; async function gerarRelatorio(){ const key=document.getElementById('rel-gem-key')?.value||localStorage.getItem('blackpits_gem_key')||''; if(!key.trim()){alert('Configure sua chave API Gemini.');return;} const tipo=document.getElementById('rel-tipo').value; const extra=document.getElementById('rel-extra').value; const status=document.getElementById('rel-status'); const output=document.getElementById('rel-output'); status.textContent='⟳ Gerando relatório com Gemini...'; output.textContent='Aguarde...'; let prompt=REL_PROMPTS[tipo]?.(data)||'Gere um relatório geral.'; if(extra)prompt+='\n\nINSTRUÇÕES EXTRAS: '+extra; try{ const resp=await fetch(`https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent?key=${key.trim()}`,{ method:'POST',headers:{'Content-Type':'application/json'}, body:JSON.stringify({contents:[{role:'user',parts:[{text:prompt}]}]}) }); const d=await resp.json(); if(d.error){status.textContent='Erro: '+d.error.message;output.textContent='';return;} const text=d.candidates?.[0]?.content?.parts?.[0]?.text||'Sem resultado.'; output.textContent=text; output._lastText=text; status.textContent='✓ Relatório gerado em '+new Date().toLocaleTimeString('pt-BR'); }catch(err){status.textContent='Erro: '+err.message;output.textContent='';} } function copiarRelatorio(){ const text=document.getElementById('rel-output')._lastText||document.getElementById('rel-output').textContent; if(!text||text.includes('Selecione'))return; navigator.clipboard.writeText(text).then(()=>alert('✓ Copiado!')); } function salvarRelatorioNota(){ const text=document.getElementById('rel-output')._lastText||document.getElementById('rel-output').textContent; if(!text||text.includes('Selecione'))return; const tipo=document.getElementById('rel-tipo').options[document.getElementById('rel-tipo').selectedIndex].text; data.notes.push({id:uid(),title:'RELATÓRIO — '+tipo.split('—')[0].trim()+' — '+new Date().toLocaleDateString('pt-BR'),area:'GERAL',content:text,ts:Date.now()}); save();alert('✓ Salvo como nota!'); } // Restore Gemini key const savedGemKey=localStorage.getItem('blackpits_gem_key'); if(savedGemKey){setTimeout(()=>{const el=document.getElementById('gem-key');if(el)el.value=savedGemKey;const el2=document.getElementById('rel-gem-key');if(el2)el2.value=savedGemKey;},100);} // CRONOGRAMA SEMANAL if(!data.cronograma)data.cronograma=[]; const CR_COLORS={ RESTAURANTE:'#fff3e0',CYBERSECURITY:'#e8f5e9',TRADE:'#e3f2fd', ENGENHARIA:'#fce4ec',OFICINA:'#efebe9',ESTUDOS:'#f3e5f5', TECH:'#e0f7fa',PESSOAL:'#f5f5f5',EXERCÍCIO:'#f9fbe7',DESCANSO:'#fafafa' }; const CR_BORDER={ RESTAURANTE:'#e65100',CYBERSECURITY:'#2e7d32',TRADE:'#1565c0', ENGENHARIA:'#880e4f',OFICINA:'#4e342e',ESTUDOS:'#6a1b9a', TECH:'#006064',PESSOAL:'#424242',EXERCÍCIO:'#558b2f',DESCANSO:'#bdbdbd' }; const DIAS=['SEG','TER','QUA','QUI','SEX','SAB','DOM']; const HORAS=['05:00','06:00','07:00','08:00','09:00','10:00','11:00','12:00','13:00','14:00','15:00','16:00','17:00','18:00','19:00','20:00','21:00','22:00','23:00']; function saveCronograma(){ const dia=document.getElementById('cr-dia').value; const inicio=document.getElementById('cr-inicio').value; const fim=document.getElementById('cr-fim').value; const area=document.getElementById('cr-area').value; const desc=document.getElementById('cr-desc').value.trim(); if(!desc)return; data.cronograma.push({id:uid(),dia,inicio,fim,area,desc}); save();renderCronograma();document.getElementById('cr-desc').value=''; } function deleteCronogramaBloco(id){data.cronograma=data.cronograma.filter(c=>c.id!==id);save();renderCronograma();} function limparCronograma(){if(confirm('Limpar todo o cronograma?')){data.cronograma=[];save();renderCronograma();}} function renderCronograma(){ const el=document.getElementById('cronograma-grid'); if(!el)return; const isDark=document.documentElement.classList.contains('dark'); const headerBg=isDark?'#1a1a1a':'#f4f4f4'; const borderC=isDark?'#2a2a2a':'#d0d0d0'; const textC=isDark?'#aaa':'#444'; let html=``; html+=``; DIAS.forEach(d=>html+=``); html+=''; HORAS.forEach(hora=>{ html+=``; DIAS.forEach(dia=>{ const blocos=data.cronograma.filter(c=>c.dia===dia&&c.inicio===hora); if(blocos.length){ html+=`'; }else{ html+=``; } }); html+=''; }); html+='
HORA${d}
${hora}`; blocos.forEach(b=>{ const bg=isDark?'#2a2a2a':(CR_COLORS[b.area]||'#f5f5f5'); const border=CR_BORDER[b.area]||'#999'; html+=`
${b.area}
${b.desc}
${b.inicio}–${b.fim}
`; }); html+='
'; html+=`
* Clique em um bloco para removê-lo
`; el.innerHTML=html; } // LIVROS if(!data.livros)data.livros=[]; function saveLivro(){ const titulo=document.getElementById('liv-titulo').value.trim(); if(!titulo)return; data.livros.push({ id:uid(),titulo,autor:document.getElementById('liv-autor').value, cat:document.getElementById('liv-cat').value,status:document.getElementById('liv-status').value, nota:document.getElementById('liv-nota').value,prog:parseInt(document.getElementById('liv-prog').value)||0, notas:document.getElementById('liv-notas').value,link:document.getElementById('liv-link').value,ts:Date.now() }); save();renderLivros(); ['liv-titulo','liv-autor','liv-notas','liv-link','liv-prog'].forEach(id=>document.getElementById(id).value=''); } function deleteLivro(id){data.livros=data.livros.filter(l=>l.id!==id);save();renderLivros();} function updateLivroStatus(id,status){const l=data.livros.find(l=>l.id===id);if(l){l.status=status;save();renderLivros();}} function renderLivros(){ if(!data.livros)data.livros=[]; const fs=document.getElementById('liv-filter-status')?.value||''; const fc=document.getElementById('liv-filter-cat')?.value||''; let list=data.livros; if(fs)list=list.filter(l=>l.status===fs); if(fc)list=list.filter(l=>l.cat===fc); list=[...list].reverse(); document.getElementById('liv-total').textContent=data.livros.length; document.getElementById('liv-lendo').textContent=data.livros.filter(l=>l.status==='LENDO').length; document.getElementById('liv-lidos').textContent=data.livros.filter(l=>l.status==='LIDO').length; document.getElementById('liv-quero').textContent=data.livros.filter(l=>l.status==='QUERO LER').length; const lendoList=document.getElementById('liv-lendo-list'); const lendo=data.livros.filter(l=>l.status==='LENDO'); lendoList.innerHTML=lendo.length?lendo.map(l=>`
${l.titulo}
${l.autor||'—'}
${l.prog?`
${l.prog}%
`:''}
`).join(''):'
Nenhum livro em leitura.
'; const sc={LENDO:'blue','QUERO LER':'','LIDO':'green',PAUSADO:'amber',ABANDONADO:'red'}; const stars=n=>n?'★'.repeat(n)+'☆'.repeat(5-n):'—'; document.getElementById('livros-list').innerHTML=list.length?list.map(l=>`
${l.titulo}
${l.autor||''}
${l.status} ${l.cat}
${l.nota?`
${stars(parseInt(l.nota))}
`:''} ${l.prog?`
`:''} ${l.notas?`
${l.notas.slice(0,160)}${l.notas.length>160?'...':''}
`:''}
${l.status!=='LENDO'?``:''} ${l.status!=='LIDO'?``:''} ${l.link?``:''}
`).join(''):'
Nenhum livro.
'; } // ===================== RÁDIO ===================== if(!data.radios)data.radios=[]; // Se nunca inicializou as rádios padrão, adiciona if(!localStorage.getItem('blackpits_radios_init')){ data.radios=[ {id:'r1',name:'Rádio Nacional AM',genre:'MPB / Notícias',url:'https://radios.ebc.com.br/radio-nacional-am/icecast.audio/nacional-am.mp3'}, {id:'r2',name:'Jovem Pan FM',genre:'Notícias / Esportes',url:'https://jovempanfm.leanstream.co/JPFM-MP3'}, {id:'r3',name:'Antena 1',genre:'Pop / Rock',url:'https://antena1.leanstream.co/ANTENA1-MP3'}, {id:'r4',name:'Radio Rock 89 FM',genre:'Rock Nacional',url:'https://radiorock.leanstream.co/AABRFM-MP3'}, {id:'r5',name:'CBN',genre:'Jornalismo',url:'https://cbn.leanstream.co/CBNAM-MP3'}, {id:'r6',name:'Rádio Globo',genre:'Esportes / Variedades',url:'https://radioglobo.leanstream.co/RGLOBO-MP3'}, ]; localStorage.setItem('blackpits_radios_init','1'); save(); } let radioPlaying=false; function getAllRadios(){return data.radios||[];} function renderRadioStations(){ const el=document.getElementById('radio-stations-list');if(!el)return; const all=getAllRadios(); el.innerHTML=all.length?all.map(r=>`
${r.name}
${r.genre}
${r.url||'sem URL'}
`).join(''):'
Nenhuma estação. Adicione abaixo.
'; } function editRadio(id){ const r=data.radios.find(r=>r.id===id);if(!r)return; const name=prompt('Nome da estação:',r.name);if(name===null)return; const genre=prompt('Gênero:',r.genre);if(genre===null)return; const url=prompt('URL do stream:',r.url);if(url===null)return; r.name=name;r.genre=genre;r.url=url; save();renderRadioStations(); } function playRadio(id,name,genre,url){ if(!url||url==='sem URL'){alert('Esta estação não tem URL configurada. Clique em ✏️ para editar.');return;} const audio=document.getElementById('radio-audio'); const wasPlaying=radioPlaying&&audio._currentId===id; document.querySelectorAll('[id^=radio-ind-]').forEach(el=>{el.textContent='▶';el.className='tag';}); if(wasPlaying){audio.pause();radioPlaying=false;document.getElementById('radio-play-btn').textContent='▶';document.getElementById('radio-status').textContent='PARADO';audio._currentId=null;return;} audio.src=url;audio._currentId=id; audio.volume=parseFloat(document.getElementById('radio-vol').value)||0.7; audio.play().then(()=>{ radioPlaying=true; document.getElementById('radio-station-name').textContent=name; document.getElementById('radio-station-genre').textContent=genre; document.getElementById('radio-play-btn').textContent='⏸'; document.getElementById('radio-status').textContent='AO VIVO'; const ind=document.getElementById('radio-ind-'+id); if(ind){ind.textContent='▶▶';ind.className='tag green';} }).catch(e=>{document.getElementById('radio-status').textContent='ERRO — verifique a URL do stream';}); } function toggleRadio(){ const audio=document.getElementById('radio-audio'); if(!audio.src)return; if(radioPlaying){audio.pause();radioPlaying=false;document.getElementById('radio-play-btn').textContent='▶';document.getElementById('radio-status').textContent='PARADO';} else{audio.play();radioPlaying=true;document.getElementById('radio-play-btn').textContent='⏸';document.getElementById('radio-status').textContent='AO VIVO';} } function addCustomRadio(){ const name=document.getElementById('radio-custom-name').value.trim(); const url=document.getElementById('radio-custom-url').value.trim(); if(!name||!url)return; if(!data.radios)data.radios=[]; data.radios.push({id:'r_'+uid(),name,genre:document.getElementById('radio-custom-genre').value||'Custom',url}); save();renderRadioStations(); document.getElementById('radio-custom-name').value=''; document.getElementById('radio-custom-url').value=''; document.getElementById('radio-custom-genre').value=''; } function deleteRadio(id){ if(!confirm('Remover esta estação?'))return; data.radios=data.radios.filter(r=>r.id!==id);save();renderRadioStations(); } // ===================== DIÁRIO ===================== if(!data.diario)data.diario=[]; function saveDiario(){ const fiz=document.getElementById('diario-fiz').value.trim(); if(!fiz)return; data.diario.push({id:uid(),data:new Date().toLocaleDateString('pt-BR'),fiz,aprendi:document.getElementById('diario-aprendi').value,travou:document.getElementById('diario-travou').value,amanha:document.getElementById('diario-amanha').value,humor:document.getElementById('diario-humor').value,energia:document.getElementById('diario-energia').value,ts:Date.now()}); save();renderDiario(); ['diario-fiz','diario-aprendi','diario-travou','diario-amanha'].forEach(id=>document.getElementById(id).value=''); } function deleteDiario(id){data.diario=data.diario.filter(d=>d.id!==id);save();renderDiario();} function renderDiario(){ const hj=document.getElementById('diario-hoje'); if(hj)hj.textContent=new Date().toLocaleDateString('pt-BR',{weekday:'long',year:'numeric',month:'long',day:'numeric'}).toUpperCase(); document.getElementById('diario-count').textContent=data.diario?.length||0; const el=document.getElementById('diario-list');if(!el)return; const list=[...(data.diario||[])].reverse(); const humorMap={'5':'😊 5','4':'🙂 4','3':'😐 3','2':'😔 2','1':'😞 1'}; const energiaMap={'5':'⚡ 5','4':'🔋 4','3':'🔆 3','2':'🔅 2','1':'💤 1'}; el.innerHTML=list.length?list.map(d=>`
${d.data}
HUMOR ${humorMap[d.humor]||d.humor} ENERGIA ${energiaMap[d.energia]||d.energia}
${d.fiz?`
FIZ
${d.fiz.slice(0,200)}
`:''} ${d.aprendi?`
APRENDI
${d.aprendi.slice(0,150)}
`:''} ${d.travou?`
TRAVOU
${d.travou.slice(0,150)}
`:''} ${d.amanha?`
AMANHÃ
${d.amanha.slice(0,150)}
`:''}
`).join(''):'
Nenhuma entrada ainda.
'; } // ===================== HÁBITOS ===================== if(!data.habitos)data.habitos=[]; if(!data.habito_logs)data.habito_logs=[]; function saveHabito(){ const nome=document.getElementById('hab-nome').value.trim();if(!nome)return; data.habitos.push({id:uid(),nome,icon:document.getElementById('hab-icon').value||'✓',freq:document.getElementById('hab-freq').value}); save();renderHabitos();document.getElementById('hab-nome').value='';document.getElementById('hab-icon').value=''; } function deleteHabito(id){ data.habitos=data.habitos.filter(h=>h.id!==id); data.habito_logs=data.habito_logs.filter(l=>l.hid!==id); save();renderHabitos(); } function toggleHabito(hid){ const today=new Date().toDateString(); const existing=data.habito_logs.find(l=>l.hid===hid&&l.day===today); if(existing){data.habito_logs=data.habito_logs.filter(l=>!(l.hid===hid&&l.day===today));} else{data.habito_logs.push({hid,day:today,ts:Date.now()});} save();renderHabitos(); } function getStreak(hid){ const logs=data.habito_logs.filter(l=>l.hid===hid).map(l=>l.day); let streak=0;const d=new Date(); while(true){if(logs.includes(d.toDateString()))streak++;else break;d.setDate(d.getDate()-1);} return streak; } function renderHabitos(){ const today=new Date().toDateString(); const dateEl=document.getElementById('hab-date'); if(dateEl)dateEl.textContent=new Date().toLocaleDateString('pt-BR'); const hojeEl=document.getElementById('hab-hoje-list'); if(hojeEl){ hojeEl.innerHTML=data.habitos.length?data.habitos.map(h=>{ const done=data.habito_logs.some(l=>l.hid===h.id&&l.day===today); return`
${done?'✓':''}
${h.icon}
${h.nome}
${done?'FEITO':'PENDENTE'}
`; }).join(''):'
Nenhum hábito. Adicione acima.
'; } const streaksEl=document.getElementById('hab-streaks'); if(streaksEl){ streaksEl.innerHTML=data.habitos.length?` ${data.habitos.map(h=>{ const streak=getStreak(h.id); const total=data.habito_logs.filter(l=>l.hid===h.id).length; return``; }).join('')}
HÁBITOSTREAKTOTAL
${h.icon} ${h.nome}${streak}🔥${total}x
`:'
Nenhum hábito registrado.
'; } } // ===================== CALCULADORA ===================== let dcaEntries=[]; function switchCalc(tab){ ['inv','eng','conv'].forEach(t=>{ document.getElementById('calc-'+t).style.display=t===tab?'block':'none'; document.getElementById('calc-tab-'+t).className=t===tab?'btn primary':'btn'; }); if(tab==='conv')updateConvUnits(); } function calcJC(){ const C=parseFloat(document.getElementById('jc-capital').value)||0; const A=parseFloat(document.getElementById('jc-aporte').value)||0; const taxa=parseFloat(document.getElementById('jc-taxa').value)||0; const anos=parseFloat(document.getElementById('jc-anos').value)||0; if(!taxa||!anos){document.getElementById('jc-result').style.display='none';return;} const im=taxa/100/12;const n=anos*12; const montante=C*Math.pow(1+im,n)+A*(Math.pow(1+im,n)-1)/im; const investido=C+A*n; const rendimento=montante-investido; document.getElementById('jc-result').style.display='block'; document.getElementById('jc-montante').textContent=fmt(montante); document.getElementById('jc-investido').textContent=fmt(investido); document.getElementById('jc-rendimento').textContent=fmt(rendimento); document.getElementById('jc-multi').textContent=(montante/Math.max(investido,1)).toFixed(2)+'x'; } function addDCA(){ const p=parseFloat(document.getElementById('dca-price').value)||0; const q=parseFloat(document.getElementById('dca-qty').value)||0; if(!p||!q)return; dcaEntries.push({p,q}); document.getElementById('dca-price').value='';document.getElementById('dca-qty').value=''; renderDCA(); } function clearDCA(){dcaEntries=[];renderDCA();} function renderDCA(){ const el=document.getElementById('dca-entries'); el.innerHTML=dcaEntries.map((e,i)=>`
R$${e.p.toFixed(2)} × ${e.q}
`).join(''); if(!dcaEntries.length){document.getElementById('dca-result').style.display='none';return;} const totalVal=dcaEntries.reduce((a,e)=>a+e.p*e.q,0); const totalQty=dcaEntries.reduce((a,e)=>a+e.q,0); const avg=totalVal/totalQty; document.getElementById('dca-result').style.display='block'; document.getElementById('dca-avg').textContent='R$'+avg.toFixed(4); document.getElementById('dca-total').textContent=fmt(totalVal)+' ('+totalQty+' unidades)'; } function calcViga(){ const q=parseFloat(document.getElementById('viga-q').value)||0; const L=parseFloat(document.getElementById('viga-l').value)||0; const tipo=document.getElementById('viga-tipo').value; if(!q||!L){document.getElementById('viga-result').style.display='none';return;} const divisor={bi:8,eng:12,cons:2}[tipo]; const M=(q*L*L/divisor).toFixed(2); const R=(q*L/2).toFixed(2); document.getElementById('viga-result').style.display='block'; document.getElementById('viga-m').textContent=M+' kN·m'; document.getElementById('viga-r').textContent=R+' kN'; } function calcDilui(){ const c1=parseFloat(document.getElementById('dil-c1').value)||0; const v1=parseFloat(document.getElementById('dil-v1').value)||0; const c2=parseFloat(document.getElementById('dil-c2').value)||0; if(!c1||!v1||!c2){document.getElementById('dil-result').style.display='none';return;} const v2=(c1*v1/c2).toFixed(2); const agua=(v2-v1).toFixed(2); document.getElementById('dil-result').style.display='block'; document.getElementById('dil-v2').textContent=v2+' mL'; document.getElementById('dil-agua').textContent=agua+' mL'; } const CONV_UNITS={ pressao:{MPa:[1],kPa:[1000],'kgf/cm²':[10.1972],psi:[145.038],bar:[10],atm:[9.8692]}, forca:{N:[1],kN:[0.001],kgf:[0.10197],tf:[0.00010197],lbf:[0.22481]}, comprimento:{mm:[1],cm:[0.1],m:[0.001],km:[0.000001],'pol(in)':[0.039370],ft:[0.003281]}, area:{'mm²':[1],'cm²':[0.01],'m²':[0.000001],ha:[1e-10],'ft²':[0.0000107639]}, volume:{mL:[1],L:[0.001],'m³':[0.000001],gal:[0.000264172],'ft³':[0.0000353147]}, massa:{g:[1],kg:[0.001],t:[0.000001],lb:[0.00220462],oz:[0.035274]}, temperatura:{special:true} }; function updateConvUnits(){ const cat=document.getElementById('conv-cat').value; const units=CONV_UNITS[cat]; const keys=cat==='temperatura'?['°C','°F','K']:Object.keys(units); ['conv-from','conv-to'].forEach((id,i)=>{ const sel=document.getElementById(id); sel.innerHTML=keys.map((k,j)=>``).join(''); }); doConvert(); } function doConvert(){ const cat=document.getElementById('conv-cat')?.value; const from=document.getElementById('conv-from')?.value; const to=document.getElementById('conv-to')?.value; const val=parseFloat(document.getElementById('conv-val')?.value)||0; const el=document.getElementById('conv-result');const out=document.getElementById('conv-out'); if(!cat||!from||!to){if(el)el.style.display='none';return;} let result; if(cat==='temperatura'){ let celsius; if(from==='°C')celsius=val; else if(from==='°F')celsius=(val-32)/1.8; else celsius=val-273.15; if(to==='°C')result=celsius; else if(to==='°F')result=celsius*1.8+32; else result=celsius+273.15; }else{ const units=CONV_UNITS[cat]; const toBase=val/units[from][0]; result=toBase*units[to][0]; } if(el)el.style.display='block'; if(out)out.textContent=parseFloat(result.toPrecision(6))+' '+to; } // ===================== VOZ → TEXTO ===================== let mediaRecorder=null,audioChunks=[],recInterval=null,recSeconds=0,audioBlob=null; function toggleRecording(){ if(mediaRecorder&&mediaRecorder.state==='recording'){stopRecording();} else{startRecording();} } async function startRecording(){ try{ const stream=await navigator.mediaDevices.getUserMedia({audio:true}); mediaRecorder=new MediaRecorder(stream);audioChunks=[];recSeconds=0; mediaRecorder.ondataavailable=e=>audioChunks.push(e.data); mediaRecorder.onstop=()=>{ audioBlob=new Blob(audioChunks,{type:'audio/webm'}); document.getElementById('voz-transcribe-btn').disabled=false; document.getElementById('voz-rec-status').textContent='✓ Áudio gravado. Clique em TRANSCREVER.'; }; mediaRecorder.start(); document.getElementById('voz-rec-btn').textContent='⏹ PARAR'; document.getElementById('voz-status').textContent='GRAVANDO...'; document.getElementById('voz-indicator').style.border='2px solid var(--red)'; document.getElementById('voz-indicator').style.background='rgba(204,0,0,0.1)'; recInterval=setInterval(()=>{recSeconds++;const m=Math.floor(recSeconds/60);const s=recSeconds%60;document.getElementById('voz-timer').textContent=m+':'+(s<10?'0':'')+s;},1000); }catch(e){alert('Erro ao acessar microfone: '+e.message);} } function stopRecording(){ if(mediaRecorder){mediaRecorder.stop();mediaRecorder.stream.getTracks().forEach(t=>t.stop());} clearInterval(recInterval); document.getElementById('voz-rec-btn').textContent='● GRAVAR'; document.getElementById('voz-status').textContent='GRAVAÇÃO CONCLUÍDA'; document.getElementById('voz-indicator').style.border='2px solid var(--border)'; document.getElementById('voz-indicator').style.background=''; } async function transcribeAudio(){ const key=document.getElementById('voz-gem-key')?.value||localStorage.getItem('blackpits_gem_key')||''; if(!key.trim()){alert('Configure sua chave API Gemini.');return;} if(!audioBlob){alert('Grave um áudio primeiro.');return;} const status=document.getElementById('voz-rec-status'); const result=document.getElementById('voz-result'); status.textContent='⟳ Transcrevendo com Gemini...'; result.textContent='Aguarde...'; try{ const reader=new FileReader(); reader.onload=async ev=>{ const b64=ev.target.result.split(',')[1]; const resp=await fetch(`https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent?key=${key.trim()}`,{ method:'POST',headers:{'Content-Type':'application/json'}, body:JSON.stringify({contents:[{role:'user',parts:[ {inline_data:{mime_type:'audio/webm',data:b64}}, {text:'Transcreva este áudio em português. Retorne apenas o texto transcrito, sem comentários adicionais.'} ]}]}) }); const d=await resp.json(); if(d.error){status.textContent='Erro: '+d.error.message;result.textContent='';return;} const text=d.candidates?.[0]?.content?.parts?.[0]?.text||'Sem resultado.'; result.textContent=text;result._lastText=text; status.textContent='✓ Transcrição concluída.'; }; reader.readAsDataURL(audioBlob); }catch(e){status.textContent='Erro: '+e.message;result.textContent='';} } function saveVozNota(){ const text=document.getElementById('voz-result')?._lastText||document.getElementById('voz-result')?.textContent; if(!text||text.includes('Grave um'))return; data.notes.push({id:uid(),title:'VOZ — '+new Date().toLocaleDateString('pt-BR')+' '+new Date().toLocaleTimeString('pt-BR').slice(0,5),area:'GERAL',content:text,ts:Date.now()}); save();alert('✓ Salvo como nota!'); } // ===================== APRESENTAÇÃO ===================== function gerarApresentacao(){ const titulo=document.getElementById('apres-titulo').value||'BLACKPITS OS'; const sub=document.getElementById('apres-sub').value||new Date().toLocaleDateString('pt-BR'); const tema=document.getElementById('apres-tema').value; const checks=document.querySelectorAll('#apres-checks input:checked'); const secoes=[...checks].map(c=>c.value); const slides=[]; // Slide de capa slides.push({tipo:'capa',titulo,sub}); secoes.forEach(s=>{ if(s==='dre'&&data.dre?.length){ const last=data.dre[data.dre.length-1]; slides.push({tipo:'dados',titulo:'FINANCEIRO — RESTAURANTE',items:[ {label:'Período',val:last.mes}, {label:'Receita Bruta',val:fmt(last.rec)}, {label:'CMV',val:last.cmvPct+'% '+(last.cmvPct>35?'⚠':'✓')}, {label:'Lucro Líquido',val:fmt(last.lucro)}, {label:'Margem',val:last.margem+'%'}, ]}); } if(s==='trade'&&data.trades?.length){ const closed=data.trades.filter(t=>t.status==='FECHADA'); const wins=closed.filter(t=>t.result>0); const totalRes=closed.reduce((a,t)=>a+(t.result||0),0); slides.push({tipo:'dados',titulo:'PERFORMANCE DE TRADES',items:[ {label:'Total de Operações',val:data.trades.length}, {label:'Fechadas',val:closed.length}, {label:'Win Rate',val:closed.length?Math.round(wins.length/closed.length*100)+'%':'—'}, {label:'Resultado Total',val:fmt(totalRes)}, {label:'Abertas',val:data.trades.filter(t=>t.status==='ABERTA').length}, ]}); } if(s==='projetos'&&data.projects?.length){ const ativos=data.projects.filter(p=>p.status==='EM ANDAMENTO'); slides.push({tipo:'lista',titulo:'PROJETOS ATIVOS',items:ativos.slice(0,8).map(p=>p.name+' ['+p.area+']')}); } if(s==='financas'&&data.financas?.length){ const rec=data.financas.filter(f=>f.tipo==='RECEITA').reduce((a,f)=>a+f.valor,0); const desp=data.financas.filter(f=>f.tipo==='DESPESA').reduce((a,f)=>a+f.valor,0); slides.push({tipo:'dados',titulo:'FINANCEIRO PESSOAL',items:[ {label:'Receitas',val:fmt(rec)}, {label:'Despesas',val:fmt(desp)}, {label:'Saldo',val:fmt(rec-desp)}, ]}); } if(s==='oficina'&&data.oficina?.length){ slides.push({tipo:'lista',titulo:'PROJETOS — OFICINA',items:data.oficina.filter(o=>o.status!=='CONCLUÍDO').slice(0,8).map(o=>o.name+' ['+o.status+']')}); } if(s==='habitos'&&data.habitos?.length){ const today=new Date().toDateString(); slides.push({tipo:'lista',titulo:'HÁBITOS — HOJE',items:data.habitos.map(h=>{ const done=data.habito_logs?.some(l=>l.hid===h.id&&l.day===today); const streak=getStreak(h.id); return h.icon+' '+h.nome+' — '+(done?'✓ FEITO':'PENDENTE')+' — Streak: '+streak; })}); } }); slides.push({tipo:'fim',titulo:'BLACKPITS OS',sub:'FIM DA APRESENTAÇÃO'}); const isDark=tema==='dark'; const bg=isDark?'#0a0a0a':'#ffffff'; const text=isDark?'#f0f0f0':'#0a0a0a'; const border=isDark?'#333':'#ddd'; const accent=isDark?'#fff':'#000'; const slideHTML=slides.map((s,i)=>{ let content=''; if(s.tipo==='capa'||s.tipo==='fim'){ content=`
${s.titulo}
${s.sub}
`; }else if(s.tipo==='dados'){ content=`
${s.titulo}
${s.items.map(item=>`
${item.label}
${item.val}
`).join('')}
`; }else if(s.tipo==='lista'){ content=`
${s.titulo}
${s.items.map(item=>`
▸ ${item}
`).join('')}
`; } return`
${content}
`; }).join(''); const html=`${titulo} ${slideHTML}
1 / ${slides.length}