viernes, 21 de agosto de 2026

CE- solo control plano

Consola Syra - C.E.P.S. Control

CONSOLA SYRA


"edge. no te corras", "límite. aguanta ahí", "edge. contén todo", "borde. no cruces" ]; const avisosBajada = [ "disminuye velocidad", "más despacio", "baja el ritmo", "suaviza ahora" ]; const avisosOrgasmo = [ "ahora sí. córrete", "orgasmo. vacíate", "permiso. córrete ahora", "libérate. toda la leche" ]; const avisosContencion = [ "contención final. aguanta", "no cruces el límite", "mantente al borde", "bloqueo. no te corras" ]; const avisosRitmo = [ "acelera un poco", "sube el ritmo", "más rápido", "mantén este ritmo", "sigue el metrónomo", recordatorio ]; const zonas = []; const gap = 0.85 / numEdgesGlobal; for (let i = 0; i < numEdgesGlobal; i++) { const start = 0.05 + i * gap; zonas.push([start, start + (gap * 0.7)]); } const edges = zonas.map(function (z) { return parseFloat((z[0] + Math.random() * (z[1] - z[0])).toFixed(3)); }); puntos.push({ fraccion: 0.00, bpm: 48 + Math.floor(Math.random() * 8), texto: recordatorio }); puntos.push({ fraccion: 0.03, bpm: 65 + Math.floor(Math.random() * 15), texto: "" }); for (let i = 0; i < numEdgesGlobal; i++) { const edgeFrac = edges[i]; const zonaIni = zonas[i][0]; const mid1 = parseFloat((zonaIni + (edgeFrac - zonaIni) * 0.4).toFixed(3)); puntos.push({ fraccion: mid1, bpm: 100 + Math.floor(Math.random() * 50) + i * 5, texto: Math.random() < 0.6 ? random(avisosRitmo) : "" }); const preFrac = parseFloat((edgeFrac - 0.02).toFixed(3)); if (preFrac > mid1) { puntos.push({ fraccion: preFrac, bpm: 170 + Math.floor(Math.random() * 40), texto: "" }); } puntos.push({ fraccion: edgeFrac, bpm: 250 + Math.floor(Math.random() * 55), texto: random(avisosEdge) }); const bajaFrac = Math.min(parseFloat((edgeFrac + 0.03).toFixed(3)), 0.87); puntos.push({ fraccion: bajaFrac, bpm: 48 + Math.floor(Math.random() * 22), texto: random(avisosBajada) }); } puntos.push({ fraccion: 0.88, bpm: 180 + Math.floor(Math.random() * 30), texto: random(["acelera", "sube el ritmo", recordatorio]) }); esOrgasmoGlobal = Math.random() > 0.10; const textoFinal = esOrgasmoGlobal ? random(avisosOrgasmo) : random(avisosContencion); puntos.push({ fraccion: parseFloat((0.92 + Math.random() * 0.02).toFixed(3)), bpm: esOrgasmoGlobal ? (290 + Math.floor(Math.random() * 30)) : 120, texto: textoFinal }); puntos.push({ fraccion: 0.96, bpm: 55, texto: "" }); puntos.push({ fraccion: 1.00, bpm: 42, texto: "" }); puntos.sort(function (a, b) { return a.fraccion - b.fraccion; }); return puntos; } const secuenciaGenerada = generarSecuencia(); document.getElementById("session-id").innerText = "SESION " + CONFIG.idSesion; document.getElementById("instrucciones-ui").innerHTML = "" + CONFIG.idSesion + " — " + CONFIG.nombreSesion + "

" + "1. Desplegar Monitor Flotante.

" + "2. INICIAR PROTOCOLO.

" + "3. Sigue el metrónomo. Habrá resumen final personalizado con tono pajeril."; let audioCtx, inicioSesionTime, intvPrincipal, intvLatido; let tSesion = "00:00", tCambio = "00:00", estado = "STOPPED"; let frasesDichas = new Set(); let bpmVirtual = 48, bpmObjetivo = 48; let noiseFilter, noiseGain, selectedVoiceURI = null; const canvas = document.getElementById("cv"); const ctx = canvas.getContext("2d"); const videoElem = document.getElementById("vd"); function initVoice() { const voices = window.speechSynthesis.getVoices(); const selectElem = document.getElementById("select-voz"); if (!selectElem) return; selectElem.innerHTML = ""; voices.forEach(function (v) { const option = document.createElement("option"); option.value = v.name; option.textContent = v.name + " (" + v.lang + ")"; if (v.lang.indexOf("es") !== -1) { option.selected = true; selectedVoiceURI = v.name; } selectElem.appendChild(option); }); if (!selectedVoiceURI && voices.length > 0) { selectedVoiceURI = voices[0].name; selectElem.value = selectedVoiceURI; } } document.getElementById("select-voz").addEventListener("change", function (e) { selectedVoiceURI = e.target.value; }); function speak(texto) { if (!texto) return; window.speechSynthesis.cancel(); const utterance = new SpeechSynthesisUtterance(texto); utterance.lang = "es-ES"; utterance.volume = 1.0; utterance.rate = 0.85; utterance.pitch = 1.0; const voices = window.speechSynthesis.getVoices(); const chosen = voices.find(function (v) { return v.name === selectedVoiceURI; }); if (chosen) utterance.voice = chosen; window.speechSynthesis.speak(utterance); } function dibujarMonitor() { ctx.fillStyle = "black"; ctx.fillRect(0, 0, 450, 300); ctx.strokeStyle = (estado === "RUNNING") ? "#ef4444" : "#1e40af"; ctx.lineWidth = 10; ctx.strokeRect(5, 5, 440, 290); ctx.fillStyle = "white"; ctx.font = "bold 16px Arial"; ctx.fillText("ID: " + CONFIG.idSesion + " | MÓDULO SYRA", 25, 35); if (estado === "RUNNING") { ctx.fillStyle = "white"; ctx.font = "bold 60px monospace"; ctx.fillText(tSesion, 25, 130); ctx.fillStyle = "#3b82f6"; ctx.font = "bold 45px monospace"; ctx.fillText(tCambio, 230, 130); ctx.fillStyle = "#ef4444"; ctx.font = "bold 40px Arial"; ctx.fillText("BPM: " + Math.round(bpmVirtual), 25, 200); ctx.fillStyle = "#ff4444"; ctx.font = "bold 20px Arial"; ctx.fillText("CERRAR (X) FINALIZA TODO", 85, 260); } else { ctx.fillStyle = "#3b82f6"; ctx.font = "bold 20px Arial"; ctx.fillText("SISTEMA LISTO", 145, 160); } } async function lanzarMonitor() { const stream = canvas.captureStream(); videoElem.srcObject = stream; dibujarMonitor(); await videoElem.play(); try { await videoElem.requestPictureInPicture(); document.getElementById("btn-monitor").style.display = "none"; document.getElementById("btn-video-container").style.display = "block"; videoElem.addEventListener("leavepictureinpicture", function () { if (estado === "RUNNING") finalizarTodo(); }); } catch (e) { alert("Use Chrome o Edge."); } } function setupNoise() { if (!audioCtx) return; const buffer = audioCtx.createBuffer(1, audioCtx.sampleRate * 3, audioCtx.sampleRate); const data = buffer.getChannelData(0); for (let i = 0; i < data.length; i++) data[i] = Math.random() * 2 - 1; const noise = audioCtx.createBufferSource(); noise.buffer = buffer; noise.loop = true; noiseFilter = audioCtx.createBiquadFilter(); noiseFilter.type = "lowpass"; noiseFilter.frequency.value = 380; noiseGain = audioCtx.createGain(); noiseGain.gain.value = 0.03; noise.connect(noiseFilter); noiseFilter.connect(noiseGain); noiseGain.connect(audioCtx.destination); noise.start(); } function loopMetronomo() { if (estado !== "RUNNING" || !audioCtx) return; bpmVirtual += (bpmObjetivo - bpmVirtual) * 0.06; const o = audioCtx.createOscillator(); const g = audioCtx.createGain(); o.frequency.value = 300 + (bpmVirtual * 2); g.gain.value = 1.0; g.gain.exponentialRampToValueAtTime(0.01, audioCtx.currentTime + 0.04); o.connect(g); g.connect(audioCtx.destination); o.start(); o.stop(audioCtx.currentTime + 0.05); setTimeout(loopMetronomo, 60000 / bpmVirtual); } function enviarRegistro(status, tiempo) { const datosSesion = { idSesion: CONFIG.idSesion, tiempo: tiempo, status: status, edges: numEdgesGlobal, orgasmo: esOrgasmoGlobal ? "SÍ" : "NO" }; const p = new URLSearchParams(datosSesion); navigator.sendBeacon(CONFIG.antenaURL + "?" + p.toString()); } function iniciarSesion() { estado = "RUNNING"; inicioSesionTime = Date.now(); audioCtx = new (window.AudioContext || window.webkitAudioContext)(); setupNoise(); loopMetronomo(); intvLatido = setInterval(function () { enviarRegistro("LATIDO_ACTIVO", Math.floor((Date.now() - inicioSesionTime) / 1000)); }, 60000); intvPrincipal = setInterval(motorLogico, 100); document.getElementById("ui-inicio").style.opacity = "0.2"; } function motorLogico() { const ahora = Date.now(); const totalSegs = Math.floor((ahora - inicioSesionTime) / 1000); const restante = Math.max(0, CONFIG.duracionTotalSegundos - totalSegs); tSesion = String(Math.floor(totalSegs / 60)).padStart(2, "0") + ":" + String(totalSegs % 60).padStart(2, "0"); tCambio = String(Math.floor(restante / 60)).padStart(2, "0") + ":" + String(restante % 60).padStart(2, "0"); secuenciaGenerada.forEach(function (item) { const sObj = Math.floor(CONFIG.duracionTotalSegundos * item.fraccion); const clave = item.fraccion.toFixed(3); if (totalSegs >= sObj && !frasesDichas.has(clave)) { bpmObjetivo = item.bpm; if (item.texto) speak(item.texto); frasesDichas.add(clave); if (noiseFilter) { noiseFilter.frequency.setTargetAtTime(280 + (item.bpm * 5.5), audioCtx.currentTime, 1.5); } } }); const fraccionActual = totalSegs / CONFIG.duracionTotalSegundos; if (fraccionActual >= 0.97 && !resumenDicho) { resumenDicho = true; let mensajeResumen = ""; if (esOrgasmoGlobal) { mensajeResumen = "Resumen de sesión, pajero. Te tragaste " + numEdgesGlobal + " edges enteros y al final sí hubo permiso para vaciar toda la leche. Bien jugado."; } else { mensajeResumen = "Resumen de sesión, pajero. Hiciste " + numEdgesGlobal + " edges de sufrimiento, pero te tocó contención final. Hoy no hay premio ni corrida, a aguantarse."; } speak(mensajeResumen); } if (totalSegs >= CONFIG.duracionTotalSegundos) { finalizarTodo(); } dibujarMonitor(); } function finalizarTodo() { if (estado === "FINISHED") return; estado = "FINISHED"; clearInterval(intvPrincipal); clearInterval(intvLatido); if (document.pictureInPictureElement) { document.exitPictureInPicture().catch(function () {}); } const total = Math.floor((Date.now() - inicioSesionTime) / 1000); enviarRegistro("FINALIZADO_OK", total); // Mensaje final limpio en pantalla al terminar document.body.innerHTML = '

PROTOCOLO FINALIZADO

'; document.body.style.overflow = "hidden"; } window.addEventListener("beforeunload", function () { if (estado === "RUNNING") { enviarRegistro("CIERRE_ABRUPTO", Math.floor((Date.now() - inicioSesionTime) / 1000)); } }); window.speechSynthesis.onvoiceschanged = initVoice; setTimeout(initVoice, 100); setInterval(dibujarMonitor, 100);

No hay comentarios:

Publicar un comentario