${analise.acertos}/${analise.total}
Acertos
${analise.percentualGlobal}%
${analise.scoreGlobal}
Score
de 100
${analise.tempoFormatado}
Tempo
Total
${analise.statusEmoji}
${analise.statusTexto}
${analise.percentualGlobal >= 90 ? 'Excelente' : analise.percentualGlobal >= 75 ? 'Muito Bom' : 'Bom'}
📍 Tópicos
${analise.porTopico.slice(0, 3).map(topico => `
${topico.nome}
${topico.percentual}%
${topico.acertos}/${topico.total} acertos
`).join('')}
🎚️ Dificuldade
${analise.porDificuldade.map(dif => {
let cor = dif.nome === 'Fácil' ? 'from-green-400 to-green-500' :
dif.nome === 'Médio' ? 'from-yellow-400 to-yellow-500' :
'from-red-400 to-red-500';
let emoji = dif.nome === 'Fácil' ? '✅' : dif.nome === 'Médio' ? '🟡' : '🔴';
return `
${emoji}
${dif.percentual}%
${dif.acertos}/${dif.total}
`;
}).join('')}
💡 Recomendações
${analise.recomendacoes.map(rec => `- →${rec}
`).join('')}
`;
}
carregando() {
return `
`;
}
erro() {
return `
❌ Erro
Não conseguimos carregar os simulados.
`;
}
// 🧮 ANÁLISE
analisarResultados() {
const total = this.questoes.length;
const acertos = Object.entries(this.respostas).filter(([qId, respIdx]) => {
const q = this.questoes.find(x => x.id === qId);
return q && q.respostaCorreta === respIdx;
}).length;
const percentualGlobal = Math.round((acertos / total) * 100);
const scoreGlobal = Math.min(100, 50 + Math.round((percentualGlobal / 100) * 50));
const tempo = Math.floor((Date.now() - this.tempoInicio) / 1000);
const mins = Math.floor(tempo / 60);
const secs = tempo % 60;
const tempoFormatado = `${mins}m ${secs}s`;
let statusEmoji = '📚', statusTexto = 'Continue!';
if (percentualGlobal >= 90) {
statusEmoji = '🏆'; statusTexto = 'Excelente!';
} else if (percentualGlobal >= 75) {
statusEmoji = '⭐'; statusTexto = 'Muito Bom!';
} else if (percentualGlobal >= 60) {
statusEmoji = '👍'; statusTexto = 'Bom';
}
const topicos = {};
this.questoes.forEach(q => {
if (!topicos[q.topico]) topicos[q.topico] = { acertos: 0, total: 0 };
topicos[q.topico].total++;
const respIdx = this.respostas[q.id];
if (respIdx !== undefined && q.respostaCorreta === respIdx) {
topicos[q.topico].acertos++;
}
});
const porTopico = Object.entries(topicos).map(([nome, dados]) => ({
nome,
acertos: dados.acertos,
total: dados.total,
percentual: Math.round((dados.acertos / dados.total) * 100)
})).sort((a, b) => b.percentual - a.percentual);
const dificuldades = {};
this.questoes.forEach(q => {
if (!dificuldades[q.dificuldade]) dificuldades[q.dificuldade] = { acertos: 0, total: 0 };
dificuldades[q.dificuldade].total++;
const respIdx = this.respostas[q.id];
if (respIdx !== undefined && q.respostaCorreta === respIdx) {
dificuldades[q.dificuldade].acertos++;
}
});
const mapDif = { 'facil': 'Fácil', 'medio': 'Médio', 'dificil': 'Difícil' };
const porDificuldade = Object.entries(dificuldades).map(([chave, dados]) => ({
nome: mapDif[chave] || chave,
chave,
acertos: dados.acertos,
total: dados.total,
percentual: Math.round((dados.acertos / dados.total) * 100)
})).sort((a, b) => {
const ordem = { 'facil': 0, 'medio': 1, 'dificil': 2 };
return ordem[a.chave] - ordem[b.chave];
});
const recomendacoes = [];
if (percentualGlobal >= 90) recomendacoes.push('✅ Excelente desempenho! Você está bem preparado.');
else if (percentualGlobal >= 75) recomendacoes.push('⭐ Muito bom! Revise os tópicos com dificuldade.');
else if (percentualGlobal >= 60) recomendacoes.push('👍 Bom começo. Dedique mais tempo ao estudo.');
else recomendacoes.push('📚 Continue estudando.');
const piores = porTopico.filter(t => t.percentual < 60);
if (piores.length > 0) recomendacoes.push(`Revise: ${piores.map(t => t.nome).join(', ')}`);
return { acertos, total, percentualGlobal, scoreGlobal, tempoFormatado, statusEmoji, statusTexto, porTopico, porDificuldade, recomendacoes };
}
// AÇÕES
selecionarSimulado(nome) {
this.simuladoSelecionado = nome;
this.state = 'configuracao';
this.modoTempo = 'contador';
this.render();
setTimeout(() => {
const input = document.getElementById('numQuestoes');
if (input) {
input.addEventListener('input', (e) => {
document.getElementById('numDisplay').textContent = e.target.value;
});
}
}, 50);
}
alterarModoTempo(modo) {
this.modoTempo = modo;
this.render();
}
iniciar() {
const numQ = parseInt(document.getElementById('numQuestoes').value);
const dif = document.getElementById('dificuldade').value;
const topicos = Array.from(document.querySelectorAll('.topico-check:checked'))
.map(el => el.value);
if (this.modoTempo === 'timer') {
const tempoSelect = document.getElementById('tempoLimite');
this.tempoLimite = parseInt(tempoSelect.value) * 60;
} else {
this.tempoLimite = 0;
}
let todas = this.simulados[this.simuladoSelecionado];
if (dif !== 'todas') {
todas = todas.filter(q => q.dificuldade === dif);
}
if (topicos.length > 0) {
todas = todas.filter(q => topicos.includes(q.topico));
}
if (todas.length === 0) {
alert('Nenhuma questão encontrada!');
return;
}
this.questoes = todas.sort(() => 0.5 - Math.random()).slice(0, numQ);
this.respostas = {};
this.mostrarDica = {};
this.questaoAtual = 0;
this.tempoInicio = Date.now();
this.state = 'quiz';
this.render();
this.iniciarTimer();
}
iniciarTimer() {
if (this.timerInterval) clearInterval(this.timerInterval);
this.timerInterval = setInterval(() => {
if (this.modoTempo === 'timer' && this.tempoRestante() <= 0) {
clearInterval(this.timerInterval);
alert('⏰ Tempo esgotado!');
this.finalizar();
return;
}
const tempoDisplay = document.getElementById('tempo-display');
if (tempoDisplay) {
tempoDisplay.innerHTML = this.formatarTempo();
}
}, 1000);
}
tempoRestante() {
if (this.modoTempo === 'contador' || this.tempoLimite === 0) {
return Infinity;
}
const tempoPassado = Math.floor((Date.now() - this.tempoInicio) / 1000);
return this.tempoLimite - tempoPassado;
}
responder(qId, respIdx) {
this.respostas[qId] = respIdx;
this.render();
}
mostrarDicaX(qId) {
this.mostrarDica[qId] = true;
this.render();
}
proximo() {
if (this.questaoAtual < this.questoes.length - 1) {
this.questaoAtual++;
this.render();
}
}
voltarQuestao() {
if (this.questaoAtual > 0) {
this.questaoAtual--;
this.render();
}
}
voltar() {
if (this.timerInterval) clearInterval(this.timerInterval);
if (this.state === 'quiz' && !confirm('Tem certeza? O simulado será abandonado.')) return;
this.state = 'menu';
this.simuladoSelecionado = null;
this.render();
}
finalizar() {
if (this.timerInterval) clearInterval(this.timerInterval);
this.state = 'resultados';
this.render();
}
novoSimulado() {
if (this.timerInterval) clearInterval(this.timerInterval);
this.state = 'configuracao';
this.mostrarDica = {};
this.render();
}
irParaMenu() {
if (this.timerInterval) clearInterval(this.timerInterval);
this.state = 'menu';
this.simuladoSelecionado = null;
this.render();
}
renderLatex(text) {
if (!text) return '';
return text.replace(/\[latex\](.*?)\[\/latex\]/g, (match, latex) => {
try {
return katex.renderToString(latex, { displayMode: false, throwOnError: false });
} catch (e) {
return match;
}
});
}
formatarTempo() {
if (this.modoTempo === 'contador') {
const seconds = Math.floor((Date.now() - this.tempoInicio) / 1000);
const mins = Math.floor(seconds / 60);
const secs = seconds % 60;
return `⏱️ ${mins}:${secs.toString().padStart(2, '0')}`;
} else {
const restante = Math.max(0, this.tempoRestante());
const mins = Math.floor(restante / 60);
const secs = restante % 60;
const cor = restante <= 300 ? 'text-red-600 font-bold' : '';
return `
⏰ ${mins}:${secs.toString().padStart(2, '0')}`;
}
}
render() {
const app = document.getElementById('app');
let html = '';
if (this.state === 'carregando') html = this.carregando();
else if (this.state === 'erro') html = this.erro();
else if (this.state === 'menu') html = this.menu();
else if (this.state === 'configuracao') html = this.configuracao();
else if (this.state === 'quiz') html = this.quiz();
else if (this.state === 'resultados') html = this.resultados();
app.innerHTML = html;
}
}
const quiz = new Quiz();