Skip to content

Commit 87bdcea

Browse files
committed
Atualiza sistema de ranking com cache diário e mensagens de processamento; melhora a experiência do usuário ao salvar resultados.
1 parent c5a5014 commit 87bdcea

8 files changed

Lines changed: 225 additions & 45 deletions

File tree

Script/escolhas.js

Lines changed: 73 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -86,15 +86,20 @@ window.FirebaseManager = {
8686
db.collection('quizResults').add(result).then(function(docRef) {
8787
console.log('✅ Resultado salvo com ID:', docRef.id);
8888

89-
// Atualizar estatísticas do usuário
90-
if (window.userAccountManager) {
91-
window.userAccountManager.updateStats({
92-
score: percentage,
93-
timeSpent: timeSpent
94-
});
95-
}
89+
// DELAY REALISTA: Simular processamento do ranking (2-3 segundos)
90+
setTimeout(function() {
91+
// Atualizar estatísticas do usuário após delay
92+
if (window.userAccountManager) {
93+
window.userAccountManager.updateStats({
94+
score: percentage,
95+
timeSpent: timeSpent
96+
});
97+
}
98+
99+
console.log('✅ Resultado salvo e estatísticas atualizadas após processamento');
100+
console.log('ℹ️ RANKING: Será atualizado automaticamente todos os dias às 19h para economizar Firebase reads');
101+
}, Math.random() * 1000 + 2000); // 2-3 segundos aleatórios
96102

97-
console.log('✅ Resultado salvo e estatísticas atualizadas');
98103
resolve();
99104
}).catch(function(error) {
100105
console.error('❌ Erro ao salvar resultado:', error);
@@ -138,13 +143,20 @@ window.onLoginModalClose = function() {
138143
window.onLoginSuccess = function() {
139144
// Salvar resultado pendente se existir
140145
if (pendingResult) {
146+
// Mostrar mensagem de processamento
147+
alert('💾 Salvando resultado... O ranking é atualizado diariamente às 19h!');
148+
141149
window.FirebaseManager.saveQuizResult(
142150
pendingResult.difficulty,
143151
pendingResult.score,
144152
pendingResult.totalQuestions,
145153
pendingResult.wrongAnswers
146154
).then(function() {
147-
alert('Seu resultado foi salvo! Agora você aparece no ranking! 🏆');
155+
// Delay para simular processamento do ranking
156+
setTimeout(function() {
157+
alert('Seu resultado foi salvo! Você aparecerá no ranking após às 19h! 🏆');
158+
}, Math.random() * 1000 + 2000); // 2-3 segundos
159+
148160
pendingResult = null;
149161
hideResultsModal(); // Fecha tela de resultados e reinicia
150162
});
@@ -154,13 +166,20 @@ window.onLoginSuccess = function() {
154166
window.onRegisterSuccess = function() {
155167
// Salvar resultado pendente se existir
156168
if (pendingResult) {
169+
// Mostrar mensagem de processamento
170+
alert('💾 Salvando resultado... O ranking é atualizado diariamente às 19h!');
171+
157172
window.FirebaseManager.saveQuizResult(
158173
pendingResult.difficulty,
159174
pendingResult.score,
160175
pendingResult.totalQuestions,
161176
pendingResult.wrongAnswers
162177
).then(function() {
163-
alert('Seu resultado foi salvo! Bem-vindo ao ranking! 🏆');
178+
// Delay para simular processamento do ranking
179+
setTimeout(function() {
180+
alert('Seu resultado foi salvo! Bem-vindo ao ranking (atualizado às 19h)! 🏆');
181+
}, Math.random() * 1000 + 2000); // 2-3 segundos
182+
164183
pendingResult = null;
165184
hideResultsModal(); // Fecha tela de resultados e reinicia
166185
});
@@ -269,33 +288,51 @@ function startSimulation(difficulty) {
269288
return;
270289
}
271290

272-
// CORREÇÃO AUTOMÁTICA: Se correct é undefined, tentar encontrar a resposta correta
291+
// CORREÇÃO CRÍTICA: Mapear correctAnswer para correct se não existe
292+
if (typeof q.correct !== 'number' && typeof q.correctAnswer === 'number') {
293+
q.correct = q.correctAnswer;
294+
console.log('✅ Mapeamento correctAnswer -> correct:', q.correctAnswer, 'para pergunta:', q.question.substring(0, 50) + '...');
295+
console.log('📋 DEBUG: Opções da pergunta:', q.options);
296+
console.log('🎯 DEBUG: Resposta correta será:', q.options[q.correctAnswer]);
297+
}
298+
299+
// CORREÇÃO AUTOMÁTICA: Só tentar corrigir se realmente há um problema
273300
if (typeof q.correct !== 'number' || q.correct < 0 || q.correct >= q.options.length) {
274301
console.log('⚠️ Tentando corrigir pergunta com correct inválido:', q.question.substring(0, 50) + '...');
302+
console.log('🔍 Valor atual de q.correct:', q.correct, 'Tipo:', typeof q.correct);
303+
console.log('🔍 Tamanho de options:', q.options.length);
275304

276305
// Verificar se há um campo alternativo ou tentar deduzir
277306
var correctIndex = -1;
278307

279-
// Estratégia 1: Procurar por um campo 'answer' ou 'correctAnswer'
280-
if (q.answer && typeof q.answer === 'string') {
308+
// Estratégia 1: Usar correctAnswer se for número válido
309+
if (typeof q.correctAnswer === 'number' && q.correctAnswer >= 0 && q.correctAnswer < q.options.length) {
310+
correctIndex = q.correctAnswer;
311+
console.log('Tentativa 1 - usando correctAnswer numérico:', q.correctAnswer);
312+
}
313+
314+
// Estratégia 2: Procurar por um campo 'answer' como string
315+
if (correctIndex === -1 && q.answer && typeof q.answer === 'string') {
281316
correctIndex = q.options.indexOf(q.answer);
282-
console.log('Tentativa 1 - campo answer:', q.answer, 'índice:', correctIndex);
317+
console.log('Tentativa 2 - campo answer:', q.answer, 'índice:', correctIndex);
283318
}
284319

285-
// Estratégia 2: Procurar por um campo 'correctAnswer'
320+
// Estratégia 3: Procurar por um campo 'correctAnswer' como string
286321
if (correctIndex === -1 && q.correctAnswer && typeof q.correctAnswer === 'string') {
287322
correctIndex = q.options.indexOf(q.correctAnswer);
288-
console.log('Tentativa 2 - campo correctAnswer:', q.correctAnswer, 'índice:', correctIndex);
323+
console.log('Tentativa 3 - campo correctAnswer string:', q.correctAnswer, 'índice:', correctIndex);
289324
}
290325

291-
// Estratégia 3: Se ainda não encontrou, usar a primeira opção como padrão temporário
326+
// Estratégia 4: Se ainda não encontrou, usar a primeira opção como último recurso
292327
if (correctIndex === -1) {
293328
correctIndex = 0;
294329
console.log('⚠️ USANDO PRIMEIRA OPÇÃO COMO PADRÃO para:', q.question.substring(0, 50));
295330
}
296331

297332
q.correct = correctIndex;
298333
console.log('✅ Pergunta corrigida - novo índice correct:', correctIndex);
334+
} else {
335+
console.log('✅ Pergunta já tem correct válido:', q.correct);
299336
}
300337

301338
// Verificar novamente se a resposta correta existe
@@ -420,6 +457,17 @@ function nextQuestion() {
420457
console.log('✅ Resposta CORRETA!');
421458
} else {
422459
console.log('❌ Resposta INCORRETA!');
460+
461+
// DEBUG DETALHADO: Vamos verificar os valores exatos
462+
console.log('🔍 DEBUG RESPOSTA INCORRETA:');
463+
console.log('- Pergunta:', question.question);
464+
console.log('- Todas as opções:', question.options);
465+
console.log('- selectedOption (índice):', selectedOption);
466+
console.log('- question.correct (índice correto):', question.correct);
467+
console.log('- Resposta escolhida:', question.options[selectedOption]);
468+
console.log('- Resposta correta:', question.options[question.correct]);
469+
console.log('- Campo correctAnswer original:', question.correctAnswer);
470+
423471
wrongAnswers.push({
424472
question: question.question,
425473
selectedAnswer: question.options[selectedOption] || 'Opção não encontrada',
@@ -564,10 +612,16 @@ function saveResults() {
564612
if (window.getCurrentUser && window.getCurrentUser()) {
565613
console.log('✅ Usuário já logado, salvando automaticamente...');
566614

615+
// Mostrar mensagem de processamento
616+
alert('💾 Salvando resultado... O ranking é atualizado diariamente às 19h!');
617+
567618
window.FirebaseManager.saveQuizResult(currentDifficulty, score, currentQuiz.length, wrongAnswers)
568619
.then(function() {
569-
alert('Seu resultado foi salvo no ranking! 🏆');
570-
hideResultsModal();
620+
// Delay para simular processamento do ranking
621+
setTimeout(function() {
622+
alert('Seu resultado foi salvo! Você aparecerá no ranking após às 19h! 🏆');
623+
hideResultsModal();
624+
}, Math.random() * 1000 + 2000); // 2-3 segundos
571625
});
572626
} else {
573627
console.log('❌ Usuário não logado, solicitando login...');

Script/ranking.js

Lines changed: 115 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,116 @@
1-
// Sistema de Ranking Otimizado com Cache
1+
// Sistema de Ranking Otimizado com Cache Diário (Horário Brasileiro)
22
window.RankingManager = {
33

44
// Cache local com timestamp
55
cache: {
66
globalRanking: null,
77
lastUpdate: null,
8-
cacheTime: 24 * 60 * 60 * 1000 // 24 horas em ms - atualização diária
8+
updateHour: 19, // Horário de atualização diária (19h)
9+
timezone: 'America/Sao_Paulo' // Fuso horário brasileiro
910
},
1011

11-
// Verificar se cache é válido
12+
// Obter data/hora atual no fuso brasileiro
13+
getBrazilTime() {
14+
return new Date().toLocaleString('pt-BR', {
15+
timeZone: this.cache.timezone,
16+
year: 'numeric',
17+
month: '2-digit',
18+
day: '2-digit',
19+
hour: '2-digit',
20+
minute: '2-digit',
21+
second: '2-digit'
22+
});
23+
},
24+
25+
// Obter Date object no horário brasileiro
26+
getBrazilDate() {
27+
const now = new Date();
28+
const brazilTime = new Date(now.toLocaleString('en-US', { timeZone: this.cache.timezone }));
29+
return brazilTime;
30+
},
31+
32+
// Verificar se cache é válido baseado no horário de atualização diário
1233
isCacheValid() {
1334
if (!this.cache.lastUpdate || !this.cache.globalRanking) {
35+
console.log('❌ Cache inexistente - primeira busca será feita');
36+
return false;
37+
}
38+
39+
const nowBrazil = this.getBrazilDate();
40+
const lastUpdateBrazil = new Date(this.cache.lastUpdate);
41+
42+
// Criar horário de atualização de hoje (19h Brasil)
43+
const todayUpdate = new Date(nowBrazil);
44+
todayUpdate.setHours(this.cache.updateHour, 0, 0, 0);
45+
46+
console.log('🕐 Horário atual (Brasil):', this.getBrazilTime());
47+
console.log('🕕 Última atualização:', lastUpdateBrazil.toLocaleString('pt-BR', { timeZone: this.cache.timezone }));
48+
console.log('🕖 Horário de atualização hoje:', todayUpdate.toLocaleString('pt-BR', { timeZone: this.cache.timezone }));
49+
50+
// CORREÇÃO CRÍTICA: Se já foi atualizado hoje após 19h, cache válido até amanhã às 19h
51+
if (lastUpdateBrazil >= todayUpdate &&
52+
lastUpdateBrazil.toDateString() === nowBrazil.toDateString()) {
53+
console.log('✅ Cache válido - já atualizado hoje após 19h (válido até amanhã às 19h)');
54+
return true;
55+
}
56+
57+
// Se ainda não chegou na hora de atualizar hoje
58+
if (nowBrazil < todayUpdate) {
59+
// Cache válido se foi atualizado ontem depois das 19h
60+
const yesterdayUpdate = new Date(todayUpdate);
61+
yesterdayUpdate.setDate(yesterdayUpdate.getDate() - 1);
62+
63+
if (lastUpdateBrazil >= yesterdayUpdate) {
64+
console.log('✅ Cache válido - usando dados de ontem após 19h');
65+
return true;
66+
}
67+
}
68+
69+
// Se chegou aqui, precisa atualizar apenas se passou das 19h E não foi atualizado hoje
70+
if (nowBrazil >= todayUpdate &&
71+
lastUpdateBrazil.toDateString() !== nowBrazil.toDateString()) {
72+
console.log('❌ Cache expirado - passou das 19h e não foi atualizado hoje');
1473
return false;
1574
}
1675

17-
const now = Date.now();
18-
const timeDiff = now - this.cache.lastUpdate;
19-
return timeDiff < this.cache.cacheTime;
76+
// Para qualquer outro caso, manter cache válido
77+
console.log('✅ Cache válido - mantendo dados atuais');
78+
return true;
79+
},
80+
81+
// Verificar próximo horário de atualização
82+
getNextUpdateTime() {
83+
const nowBrazil = this.getBrazilDate();
84+
const todayUpdate = new Date(nowBrazil);
85+
todayUpdate.setHours(this.cache.updateHour, 0, 0, 0);
86+
87+
if (nowBrazil >= todayUpdate) {
88+
// Se já passou das 19h hoje, próxima atualização é amanhã às 19h
89+
const tomorrow = new Date(todayUpdate);
90+
tomorrow.setDate(tomorrow.getDate() + 1);
91+
return tomorrow;
92+
} else {
93+
// Se ainda não passou das 19h, próxima é hoje às 19h
94+
return todayUpdate;
95+
}
2096
},
2197

22-
// Carregar ranking global com cache
98+
// Carregar ranking global com cache diário (Horário Brasileiro)
2399
async getGlobalRanking() {
24100
try {
25101
console.log('🏆 Verificando cache do ranking...');
102+
console.log('🇧🇷 Horário atual (Brasil):', this.getBrazilTime());
26103

27104
// Se cache é válido, usar dados locais
28105
if (this.isCacheValid()) {
106+
const nextUpdate = this.getNextUpdateTime();
29107
console.log('✅ Usando ranking do cache (economizando reads)');
108+
console.log(`⏰ Próxima atualização: ${nextUpdate.toLocaleString('pt-BR', { timeZone: this.cache.timezone })}`);
30109
return this.cache.globalRanking;
31110
}
32111

33-
console.log('🔄 Cache expirado, buscando dados atualizados...');
112+
console.log('🔄 Cache expirado - buscando dados atualizados do Firebase...');
113+
console.log('💰 CONSUMINDO 1 READ do Firebase para atualizar ranking');
34114

35115
// Buscar dados atualizados (só quando necessário)
36116
const usersSnapshot = await window.db.collection('users')
@@ -61,11 +141,15 @@ window.RankingManager = {
61141
return b.totalQuizzes - a.totalQuizzes;
62142
});
63143

64-
// Atualizar cache
144+
// Atualizar cache com timestamp brasileiro
65145
this.cache.globalRanking = ranking;
66-
this.cache.lastUpdate = Date.now();
146+
this.cache.lastUpdate = this.getBrazilDate().getTime(); // Usar horário brasileiro
67147

148+
const nextUpdate = this.getNextUpdateTime();
68149
console.log(`✅ Ranking atualizado: ${ranking.length} usuários (${usersSnapshot.size} reads consumidos)`);
150+
console.log(`🇧🇷 Atualizado em: ${this.getBrazilTime()}`);
151+
console.log(`⏰ Próxima atualização: ${nextUpdate.toLocaleString('pt-BR', { timeZone: this.cache.timezone })}`);
152+
console.log('💾 Cache válido até a próxima atualização - SEM MAIS READS até lá!');
69153
return ranking;
70154

71155
} catch (error) {
@@ -292,3 +376,24 @@ document.addEventListener('DOMContentLoaded', function() {
292376
console.log('✅ Firebase Firestore disponível para ranking');
293377
}
294378
});
379+
380+
// SISTEMA DE CACHE OTIMIZADO PARA HORÁRIO BRASILEIRO
381+
// O ranking busca dados do Firebase APENAS UMA VEZ POR DIA às 19h (horário de Brasília)
382+
// Depois disso, usa cache local até o próximo dia às 19h
383+
384+
// Função de debug para verificar horários
385+
window.RankingManager.debugTime = function() {
386+
console.log('=== DEBUG HORÁRIO BRASILEIRO ===');
387+
console.log('🇧🇷 Horário atual (Brasil):', this.getBrazilTime());
388+
console.log('🌍 Horário UTC:', new Date().toISOString());
389+
console.log('⏰ Horário de atualização:', this.cache.updateHour + 'h');
390+
console.log('📅 Cache válido?', this.isCacheValid());
391+
392+
if (this.cache.lastUpdate) {
393+
const lastUpdate = new Date(this.cache.lastUpdate);
394+
console.log('🕐 Última atualização:', lastUpdate.toLocaleString('pt-BR', { timeZone: this.cache.timezone }));
395+
}
396+
397+
const nextUpdate = this.getNextUpdateTime();
398+
console.log('🔄 Próxima atualização:', nextUpdate.toLocaleString('pt-BR', { timeZone: this.cache.timezone }));
399+
};

Script/user-account.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -524,6 +524,10 @@ class UserAccountManager {
524524

525525
this.userDoc.stats = newStats;
526526
console.log('Estatísticas atualizadas:', newStats);
527+
console.log('ℹ️ RANKING: Cache preservado - ranking será atualizado automaticamente em 24h');
528+
529+
// REMOVIDO: Invalidação imediata do cache para economizar Firebase reads
530+
// O ranking usa cache de 24h para otimizar custos e performance
527531

528532
} catch (error) {
529533
console.error('Erro ao atualizar estatísticas:', error);

Style/index.css

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -311,6 +311,14 @@ footer {
311311
background: #2ea043;
312312
}
313313

314+
/* Estilo específico para o modal de aviso do projeto */
315+
.project-notice-modal {
316+
margin: auto;
317+
transform: translateY(-5%);
318+
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.5);
319+
border: 2px solid #30363d;
320+
}
321+
314322
.close {
315323
position: absolute;
316324
top: 10px;

account.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -260,7 +260,7 @@ <h2>📋 Atividade Recente</h2>
260260
<script src="./Script/security.js?v=1754068573"></script>
261261
<script src="./Script/privacy-consent.js?v=1754068573"></script>
262262
<script src="./Script/data-auditor.js?v=1754068573"></script>
263-
<script src="./Script/user-account.js?v=1754068573"></script>
263+
<script src="./Script/user-account.js?v=1754173228"></script>
264264
<script src="./Script/account-page.js?v=1754068573"></script>
265265
</body>
266266
</html>

escolhas.html

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
<head>
44
<meta charset="UTF-8">
55
<meta name="viewport" content="width=device-width, initial-scale=1.0">
6-
<title>SIA: Security & Information Academy - Simulador de Segurança</title>
6+
<title>SIA: Security & Information Academy - <script src="Script/escolhas.js?v=1754173494"></script>imulador de Segurança</title>
77

88
<!-- Meta tags de segurança -->
99
<meta http-equiv="X-Content-Type-Options" content="nosniff">
@@ -184,8 +184,8 @@ <h3 id="userName">Bem-vindo!</h3>
184184
<script src="./Script/security.js?v=1754068573"></script>
185185
<script src="./Script/privacy-consent.js?v=1754068573"></script>
186186
<script src="./Script/data-auditor.js?v=1754068573"></script>
187-
<script src="./Script/user-account.js?v=1754068573"></script>
187+
<script src="./Script/user-account.js?v=1754173228"></script>
188188
<script src="./Script/login-system.js?v=1754068573"></script>
189-
<script src="./Script/escolhas.js?v=1754068573"></script>
189+
<script src="./Script/escolhas.js?v=1754171928"></script>
190190
</body>
191191
</html>

0 commit comments

Comments
 (0)