// Cole este bloco TODO no "Scripts in Footer" do plugin Insert Headers and Footers (function(){ // ====== CONFIG - altere a senha antes de publicar ====== const ADMIN_PASSWORD = "senha123"; const STORAGE_KEY = "roleta_premiada_entries_v1"; const STORAGE_WINNER_KEY = "roleta_premiada_chosen_winner_v1"; const STORAGE_WINNER_TS = "roleta_premiada_chosen_winner_ts_v1"; // Helpers const $ = s => document.querySelector(s); const wheel = document.getElementById("wheel"); const ctx = wheel && wheel.getContext ? wheel.getContext("2d") : null; const confetti = document.getElementById("confetti"); // Safety: wait DOM loaded (footer injection usually ok, but garantimos) function onDOMReady(fn){ if(document.readyState === "loading") document.addEventListener("DOMContentLoaded", fn); else fn(); } onDOMReady(function(){ if(!ctx){ console.error("Canvas não encontrado - verifique se o HTML foi colado corretamente."); return; } // canvas sizing & confetti function resizeCanvas(){ const ratio = window.devicePixelRatio || 1; const cssW = wheel.clientWidth; const cssH = wheel.clientHeight; const w = Math.round(cssW * ratio); const h = Math.round(cssH * ratio); if(wheel.width !== w || wheel.height !== h){ wheel.width = w; wheel.height = h; ctx.setTransform(ratio,0,0,ratio,0,0); } } function resizeConfetti(){ confetti.width = window.innerWidth; confetti.height = window.innerHeight; } window.addEventListener("resize", function(){ resizeCanvas(); resizeConfetti(); drawWheel(); }); // State let entries = []; let isSpinning = false; let currentRotation = 0; const POINTER_ANGLE = -Math.PI/2; // Confetti (simple) function startConfetti(durationMs = 4200){ const c = confetti.getContext("2d"); const pieces = []; const N = 180; for(let i=0;i{ p.y += p.vy; p.x += p.vx; p.a += p.spin; if(p.y > confetti.height) p.y = -10; c.save(); c.translate(p.x,p.y); c.rotate(p.a); c.fillStyle = `hsl(${p.h},100%,50%)`; c.fillRect(-p.r,-p.r/2,p.r*2,p.r); c.restore(); }); if(dt < durationMs) requestAnimationFrame(step); else c.clearRect(0,0,confetti.width,confetti.height); } requestAnimationFrame(step); } // Draw Wheel function drawWheel(){ resizeCanvas(); const cssR = Math.min(wheel.clientWidth, wheel.clientHeight)/2; const n = entries.length || 1; ctx.clearRect(0,0,wheel.width,wheel.height); ctx.save(); ctx.translate(cssR, cssR); ctx.rotate(currentRotation); for(let i=0;i 20 ? label.slice(0,19) + "…" : label; ctx.fillText(text, 0, 0); ctx.restore(); } // center ctx.beginPath(); ctx.arc(0,0,50,0,Math.PI*2); ctx.fillStyle="#0e1420"; ctx.fill(); ctx.lineWidth=3; ctx.strokeStyle="#243048"; ctx.stroke(); ctx.restore(); } // Storage & UI function getEntriesFromTextarea(){ return document.getElementById("ids").value.split(/\r?\n/).map(s=>s.trim()).filter(Boolean); } function setEntries(arr){ entries = arr.slice(); try{ localStorage.setItem(STORAGE_KEY, JSON.stringify(entries)); }catch(e){} drawWheel(); } function loadEntriesFromStorage(){ try{ const s = localStorage.getItem(STORAGE_KEY); if(s){ const arr = JSON.parse(s); if(Array.isArray(arr)){ entries = arr.slice(); document.getElementById("ids").value = entries.join("\n"); drawWheel(); return; } } }catch(e){} entries = getEntriesFromTextarea(); drawWheel(); } function shuffleInPlace(a){ for(let i=a.length-1;i>0;i--){ const j = Math.floor(Math.random()*(i+1)); [a[i],a[j]]=[a[j],a[i]]; } } // Spin math function easeOutCubic(x){ return 1 - Math.pow(1 - x, 3); } const mod2pi = a => (a % (2*Math.PI) + 2*Math.PI) % (2*Math.PI); function readAdminWinner(){ const w = localStorage.getItem(STORAGE_WINNER_KEY); if(!w) return null; try{ return JSON.parse(w); }catch(e){ return String(w); } } function clearAdminWinner(){ try{ localStorage.removeItem(STORAGE_WINNER_KEY); localStorage.removeItem(STORAGE_WINNER_TS); }catch(e){} } function spinToIndex(effIndex, {minTurns=4,maxTurns=6,durationMs=4200,tempAdd=false} = {}){ if(isSpinning) return; isSpinning = true; document.getElementById("result").textContent = ""; const n = entries.length; if(n === 0){ alert("Sem IDs."); isSpinning=false; return; } const slice = 2*Math.PI/n; const sliceCenter = (effIndex + 0.5) * slice; const turns = (Math.random()*(maxTurns-minTurns)+minTurns); const currentAngle = mod2pi(currentRotation); const desiredFinal = mod2pi(POINTER_ANGLE - sliceCenter); let deltaAngle = desiredFinal - currentAngle; deltaAngle = mod2pi(deltaAngle); const targetRotation = currentRotation + deltaAngle + turns*2*Math.PI; const start = performance.now(); const startRot = currentRotation; const totalDelta = targetRotation - startRot; function frame(ts){ const t = Math.min(1, (ts - start) / durationMs); currentRotation = startRot + totalDelta * easeOutCubic(t); drawWheel(); if(t < 1) requestAnimationFrame(frame); else { currentRotation = targetRotation; drawWheel(); const winnerValue = entries[effIndex]; document.getElementById("result").textContent = "ID sorteado: " + winnerValue; document.getElementById("winnerText").textContent = winnerValue; document.getElementById("popup").style.display = "flex"; startConfetti(4200); if(tempAdd){ entries.pop(); try{ localStorage.setItem(STORAGE_KEY, JSON.stringify(entries)); }catch(e){} } clearAdminWinner(); isSpinning = false; } } requestAnimationFrame(frame); } // Public spin function onSpinClicked(){ if(isSpinning) return; if(entries.length === 0){ alert("Adicione IDs e clique em 'Aplicar na roleta'."); return; } const adminW = readAdminWinner(); if(adminW){ const chosen = (typeof adminW === "object" && adminW.id) ? adminW.id : String(adminW); const idx = entries.indexOf(chosen); if(idx !== -1) spinToIndex(idx,{minTurns:4,maxTurns:6,durationMs:4200,tempAdd:false}); else { entries.push(chosen); try{ localStorage.setItem(STORAGE_KEY, JSON.stringify(entries)); }catch(e){} spinToIndex(entries.length-1,{minTurns:4,maxTurns:6,durationMs:4200,tempAdd:true}); } } else { const idx = Math.floor(Math.random()*entries.length); spinToIndex(idx,{minTurns:4,maxTurns:6,durationMs:4200,tempAdd:false}); } } // Popup close document.getElementById("closePopup").addEventListener("click", function(){ document.getElementById("popup").style.display = "none"; }); // Admin panel open in new tab (data URL) function openAdminTab(){ const adminHTML = `Painel Admin
Admin