// 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 AdminAdmin