testando medida de latencia
This commit is contained in:
1 parent
2a086e84a0
commit
1aafe3080d
4 files changed
+239
-4634543
No files matched your search
+149
-21
@@ -50,6 +50,42 @@ import { updateStepUI, renderPatternEditor } from "./pattern/pattern_ui.js";
|
||||
import { PORT_SOCK } from "./config.js";
|
||||
import { DEFAULT_PROJECT_XML } from "./utils.js"
|
||||
|
||||
// --- NO TOPO DO SEU socket.js ---
|
||||
export let USER_NAME = null;
|
||||
export let currentRoom = null;
|
||||
let roomSeq = 0;
|
||||
let lastActionToken = 0;
|
||||
let isOfflineMode = false;
|
||||
|
||||
// --- FUNÇÃO DE AUTENTICAÇÃO INTELIGENTE ---
|
||||
export async function getOrFetchUsername() {
|
||||
// Se já pegamos o nome antes, não pede de novo
|
||||
if (USER_NAME) return USER_NAME;
|
||||
|
||||
try {
|
||||
const res = await fetch('/api/check_auth', { credentials: 'include' });
|
||||
const data = await res.json();
|
||||
if (data.logged_in) {
|
||||
USER_NAME = data.user;
|
||||
return USER_NAME;
|
||||
}
|
||||
} catch (e) {
|
||||
console.warn("API de Auth indisponível, caindo para modo visitante.");
|
||||
}
|
||||
|
||||
// Se não estiver logado, barra a tela e pede apelido
|
||||
let name = prompt("Você não está logado. Digite seu apelido para entrar na DAW Online:");
|
||||
if (!name || name.trim() === "") {
|
||||
name = "Produtor_" + Math.floor(Math.random() * 1000);
|
||||
}
|
||||
USER_NAME = name.trim();
|
||||
return USER_NAME;
|
||||
}
|
||||
|
||||
// --- TELEMETRIA PARA A DISSERTAÇÃO ---
|
||||
window.jamTelemetry = [];
|
||||
let lastReceivedSeq = 0;
|
||||
|
||||
function _getRackIdFallback() {
|
||||
// 1) pega do primeiro bassline que já tenha instrumentSourceId
|
||||
const b = (appState.pattern.tracks || []).find(
|
||||
@@ -101,8 +137,7 @@ const socket = io(`https://alice.ufsj.edu.br:${PORT_SOCK}`, {
|
||||
withCredentials: true,
|
||||
});
|
||||
|
||||
let USER_NAME = `Alicer-${Math.floor(Math.random() * 9999)}`;
|
||||
let currentRoom = null;
|
||||
// -------------------------------------
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// CLOCK SYNC — Sincroniza relógio cliente-servidor
|
||||
@@ -177,27 +212,45 @@ export function sendActionSafe(action) {
|
||||
// -----------------------------------------------------------------------------
|
||||
// CONEXÃO / JOIN / LOGS
|
||||
// -----------------------------------------------------------------------------
|
||||
socket.on("connect", () => {
|
||||
console.log(`Conectado ao servidor com ID: ${socket.id}`);
|
||||
showToast("✅ Conectado ao servidor", "success");
|
||||
if (USER_NAME.startsWith("Alicer-")) {
|
||||
USER_NAME = `Alicer-${socket.id.substring(0, 4)}`;
|
||||
}
|
||||
const urlRoom = new URLSearchParams(window.location.search).get("room");
|
||||
currentRoom = urlRoom || null;
|
||||
|
||||
if (currentRoom) {
|
||||
console.log(`Modo Online. Sala detectada: ${currentRoom}`);
|
||||
// --- MONITORAMENTO DE PRESENÇA ---
|
||||
socket.on("room_status", (data) => {
|
||||
console.log(
|
||||
`%c[MONITOR DE SALA] 👥 ${data.count} pessoa(s) na sala '${data.room}'`,
|
||||
'background: #222; color: #bada55; font-size: 16px; font-weight: bold; padding: 4px;'
|
||||
);
|
||||
console.log("IDs conectados:", data.users);
|
||||
|
||||
// Se quiser um aviso visual na tela da DAW:
|
||||
if(data.count > 1) {
|
||||
showToast(`👥 Agora há ${data.count} produtores na sala!`, "success");
|
||||
}
|
||||
});
|
||||
// ---------------------------------
|
||||
|
||||
// --- SUBSTITUA SEU socket.on("connect") POR ESTE ---
|
||||
socket.on("connect", async () => {
|
||||
console.log(`Conectado ao servidor com ID: ${socket.id}`);
|
||||
|
||||
const urlRoom = new URLSearchParams(window.location.search).get("room");
|
||||
|
||||
if (urlRoom) {
|
||||
currentRoom = urlRoom;
|
||||
console.log(`Modo Online. Sala detectada na URL: ${currentRoom}`);
|
||||
showToast(`🎧 Conectado à sala ${currentRoom}`, "info");
|
||||
// Mostra o botão se estiver online
|
||||
const syncModeBtn = document.getElementById("sync-mode-btn");
|
||||
//if (syncModeBtn) syncModeBtn.style.display = ""; // Garante visibilidade
|
||||
|
||||
// Como tem sala na URL, EXIGE o login/apelido agora
|
||||
const myName = await getOrFetchUsername();
|
||||
|
||||
socket.emit("join_room", {
|
||||
roomName: currentRoom,
|
||||
userName: myName
|
||||
});
|
||||
|
||||
} else {
|
||||
console.log("Modo Local. Conectado, mas não em uma sala.");
|
||||
// Entrou na DAW pura, não pede nada ainda.
|
||||
console.log("Modo Local. Aguardando criação de sala.");
|
||||
showToast("🔌 Modo local (fora de sala)", "warning");
|
||||
// Esconde se offline
|
||||
const syncModeBtn = document.getElementById("sync-mode-btn");
|
||||
//if (syncModeBtn) syncModeBtn.style.display = "none";
|
||||
}
|
||||
|
||||
syncServerTime();
|
||||
@@ -238,16 +291,18 @@ socket.on("system_update", (data) => {
|
||||
socket.on("load_project_state", async (projectXml) => {
|
||||
console.log("Recebendo estado salvo da sala...");
|
||||
showToast("🔄 Recebendo estado atual da sala...", "info", 4000);
|
||||
|
||||
if (isLoadingProject) return;
|
||||
isLoadingProject = true;
|
||||
|
||||
try {
|
||||
// 1. Carrega o XML que veio do servidor (pode estar desatualizado)
|
||||
await parseMmpContent(projectXml);
|
||||
|
||||
// 🔥 CORREÇÃO: Força a restauração da sessão LOCAL logo após carregar o XML
|
||||
// Isso garante que suas alterações locais (BPM, steps) "ganhem" do servidor
|
||||
if (window.ROOM_NAME) {
|
||||
const raw = sessionStorage.getItem(`temp_state_${window.ROOM_NAME}`);
|
||||
if (currentRoom) {
|
||||
const raw = sessionStorage.getItem(`temp_state_${currentRoom}`);
|
||||
if (raw) {
|
||||
// Se existe 'raw', confiamos que é o estado mais recente do usuário.
|
||||
console.log("Re-aplicando sessão local (mesmo se vazia)...");
|
||||
@@ -256,6 +311,7 @@ socket.on("load_project_state", async (projectXml) => {
|
||||
}
|
||||
|
||||
renderAll();
|
||||
saveStateToSession();
|
||||
showToast("🎵 Projeto carregado com sucesso", "success");
|
||||
|
||||
const hasAudio =
|
||||
@@ -357,6 +413,8 @@ export function sendAction(action) {
|
||||
|
||||
const token = (++lastActionToken).toString();
|
||||
action.__token = token;
|
||||
// Usa o relógio sincronizado com o servidor
|
||||
action.__send_time = Date.now() + serverOffsetMs;
|
||||
action.__senderId = socket.id;
|
||||
action.__senderName = USER_NAME;
|
||||
|
||||
@@ -537,6 +595,42 @@ socket.on("feedback", (msg) => {
|
||||
|
||||
socket.on("action_broadcast", (payload) => {
|
||||
const action = payload && payload.type ? payload : payload?.action || payload;
|
||||
|
||||
// --- INÍCIO DA COLETA DE DADOS ---
|
||||
const receiveTime = Date.now() + serverOffsetMs;
|
||||
|
||||
// 1. Calcula a latência (se foi outro usuário que mandou)
|
||||
let latencyMs = 0;
|
||||
if (action.__send_time && action.userId !== socket.id) {
|
||||
latencyMs = receiveTime - action.__send_time;
|
||||
}
|
||||
|
||||
// 2. Verifica a Ordem dos Pacotes (Jitter/Perda)
|
||||
let isOutOfOrder = false;
|
||||
let missingPackets = 0;
|
||||
if (action.__seq) {
|
||||
if (lastReceivedSeq !== 0 && action.__seq !== lastReceivedSeq + 1) {
|
||||
isOutOfOrder = true;
|
||||
missingPackets = Math.abs(action.__seq - lastReceivedSeq) - 1;
|
||||
}
|
||||
lastReceivedSeq = action.__seq;
|
||||
}
|
||||
|
||||
// 3. Salva no array se não for a sua própria mensagem voltando
|
||||
// TRAVA DE SEGURANÇA: Se o array não existir ainda, cria na hora!
|
||||
window.jamTelemetry = window.jamTelemetry || [];
|
||||
if (action.userId !== socket.id) {
|
||||
window.jamTelemetry.push({
|
||||
type: action.type,
|
||||
seq: action.__seq,
|
||||
latency_ms: latencyMs.toFixed(2),
|
||||
out_of_order: isOutOfOrder,
|
||||
missing_packets: missingPackets,
|
||||
timestamp: new Date().toISOString()
|
||||
});
|
||||
}
|
||||
// --- FIM DA COLETA DE DADOS ---
|
||||
|
||||
if (action && action.__token) {
|
||||
processedTokens.add(action.__token);
|
||||
if (lastBroadcastTimeout && pendingToken === action.__token) {
|
||||
@@ -1608,5 +1702,39 @@ async function handleActionBroadcast(action) {
|
||||
}
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// RECUPERAÇÃO DE ESTADO (TAB SLEEP / WAKE UP)
|
||||
// ============================================================================
|
||||
document.addEventListener("visibilitychange", () => {
|
||||
if (document.visibilityState === "visible") {
|
||||
console.log("%c[SISTEMA] Aba reativada! Solicitando estado...", "color: #00ff00; background: #222; padding: 4px;");
|
||||
|
||||
// Usa o currentRoom oficial
|
||||
if (socket.connected && currentRoom) {
|
||||
// Deleta o cache local velho
|
||||
sessionStorage.removeItem(`temp_state_${currentRoom}`);
|
||||
|
||||
// Pede o estado fresquinho
|
||||
socket.emit("request_full_sync", { room: currentRoom });
|
||||
showToast("🔄 Sincronizando com a sala...", "info");
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// ============================================================================
|
||||
// NOTIFICAÇÕES DE PRESENÇA NA SALA
|
||||
// ============================================================================
|
||||
socket.on("user_joined", ({ username }) => {
|
||||
// Toca um sonzinho rápido e mostra o popup verde
|
||||
showToast(`👋 ${username} entrou na sala!`, "success", 4000);
|
||||
console.log(`[PRESENÇA] ${username} conectou-se.`);
|
||||
});
|
||||
|
||||
socket.on("user_left", ({ username }) => {
|
||||
// Mostra o popup amarelo de aviso
|
||||
showToast(`🏃 ${username} saiu da sala.`, "warning", 4000);
|
||||
console.log(`[PRESENÇA] ${username} desconectou-se.`);
|
||||
});
|
||||
|
||||
// EXPORTS
|
||||
export { socket };
|
||||
Reference in new issue
Block a user