document-rio / index.html
asgdestroi's picture
mude o botão Professor para em baixo no iniciar questionário - Follow Up Deployment
52ef7be verified
<!DOCTYPE html>
<html lang="pt-BR">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Questionário sobre Cidade Cinza</title>
<script src="https://cdn.tailwindcss.com"></script>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<style>
/* Custom CSS for shuffle animation */
.shuffle-animation {
animation: shuffle 0.5s ease;
}
@keyframes shuffle {
0% { transform: translateY(0); }
25% { transform: translateY(-10px); }
50% { transform: translateY(0); }
75% { transform: translateY(10px); }
100% { transform: translateY(0); }
}
/* Results table styling */
.results-table {
width: 100%;
border-collapse: collapse;
}
.results-table th, .results-table td {
border: 1px solid #ddd;
padding: 8px;
}
.results-table tr:nth-child(even) {
background-color: #f2f2f2;
}
.results-table tr:hover {
background-color: #ddd;
}
</style>
</head>
<body class="bg-gray-100 font-sans">
<!-- Teacher Login Screen -->
<div id="teacherLoginScreen" class="min-h-screen hidden items-center justify-center px-4 py-12">
<div class="w-full max-w-md bg-white rounded-lg shadow-md overflow-hidden">
<div class="bg-purple-600 py-4 px-6">
<h2 class="text-2xl font-bold text-white">Acesso do Professor</h2>
<p class="text-purple-100 mt-1">Insira suas credenciais para acessar os resultados</p>
</div>
<div class="p-6">
<div class="mb-4">
<label for="teacherUsername" class="block text-gray-700 font-medium mb-2">Usuário</label>
<input type="text" id="teacherUsername" class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-purple-500" placeholder="Seu usuário" required>
</div>
<div class="mb-6">
<label for="teacherPassword" class="block text-gray-700 font-medium mb-2">Senha</label>
<input type="password" id="teacherPassword" class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-purple-500" placeholder="Sua senha" required>
</div>
<button id="teacherLoginBtn" class="w-full bg-purple-600 hover:bg-purple-700 text-white font-bold py-2 px-4 rounded-md focus:outline-none focus:ring-2 focus:ring-purple-500 focus:ring-offset-2 transition duration-150">
Acessar Painel
</button>
</div>
</div>
</div>
<!-- Teacher Password Modal -->
<div id="teacherPasswordModal" class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center hidden z-50">
<div class="bg-white rounded-lg shadow-md overflow-hidden w-96">
<div class="bg-purple-600 py-3 px-6">
<h3 class="text-lg font-bold text-white">Acesso Restrito</h3>
</div>
<div class="p-6">
<div class="mb-4">
<label for="teacherPasswordInput" class="block text-gray-700 mb-2">Senha do Professor:</label>
<input type="password" id="teacherPasswordInput" class="w-full px-3 py-2 border rounded-md">
</div>
<div class="flex justify-end space-x-3">
<button id="cancelPasswordBtn" class="px-4 py-2 bg-gray-300 rounded-md">Cancelar</button>
<button id="confirmPasswordBtn" class="px-4 py-2 bg-purple-600 text-white rounded-md hover:bg-purple-700">Acessar</button>
</div>
</div>
</div>
</div>
<!-- Login Screen -->
<div id="loginScreen" class="min-h-screen flex items-center justify-center px-4 py-12">
<div class="w-full max-w-md bg-white rounded-lg shadow-md overflow-hidden">
<div class="bg-blue-600 py-4 px-6">
<h2 class="text-2xl font-bold text-white">Questionário sobre "Cidade Cinza"</h2>
<p class="text-blue-100 mt-1">Por favor, insira suas informações para começar</p>
</div>
<div class="px-6 pb-4">
<button id="teacherAccessBtn" class="w-full bg-blue-500 hover:bg-blue-600 text-white font-bold py-2 px-4 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 transition duration-150">
Professor
</button>
</div>
<div class="p-6">
<div class="mb-4">
<label for="studentName" class="block text-gray-700 font-medium mb-2">Nome do Aluno</label>
<input type="text" id="studentName" class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" placeholder="Seu nome completo" required>
</div>
<div class="mb-4">
<label for="studentClass" class="block text-gray-700 font-medium mb-2">Turma</label>
<select id="studentClass" class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" required>
<option value="">Selecione sua turma</option>
<option value="1n1">1n1</option>
<option value="1n2">1n2</option>
<option value="2n1">2n1</option>
<option value="2n2">2n2</option>
<option value="3n1">3n1</option>
<option value="3n2">3n2</option>
<option value="1eja">1eja</option>
<option value="2eja">2eja</option>
<option value="3eja">3eja</option>
</select>
</div>
<div class="mb-6">
<label for="quizDate" class="block text-gray-700 font-medium mb-2">Data</label>
<input type="date" id="quizDate" class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" required>
</div>
<button id="startQuizBtn" class="w-full bg-blue-600 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 transition duration-150">
Iniciar Questionário
</button>
</div>
</div>
</div>
<!-- Quiz Screen -->
<div id="quizScreen" class="min-h-screen hidden py-8 px-4">
<div class="max-w-4xl mx-auto">
<div class="flex justify-between items-center mb-6">
<h1 class="text-2xl font-bold text-gray-800">Questionário sobre "Cidade Cinza"</h1>
<div class="bg-gray-200 rounded-full px-4 py-2">
<span id="timer" class="text-gray-700 font-medium">00:00</span>
</div>
</div>
<div class="bg-white rounded-lg shadow-md overflow-hidden mb-6">
<div class="bg-gray-800 text-white px-4 py-3 flex justify-between items-center">
<h2 id="questionNumber" class="text-lg font-semibold">Pergunta 1</h2>
<div class="text-sm">
<span id="currentQuestion">1</span> de <span id="totalQuestions">10</span>
</div>
</div>
<div class="p-6">
<div class="mb-6 p-4 bg-gray-100 rounded-lg">
<p id="questionText" class="text-lg font-medium text-gray-800">A pergunta aparecerá aqui...</p>
</div>
<div id="imageContainer" class="mb-6 flex justify-center">
<img id="questionImage" src="" alt="Imagem ilustrativa" class="max-h-60 rounded-lg shadow-md">
</div>
<div id="answersContainer" class="space-y-3">
<!-- Answers will be inserted here -->
</div>
<div class="mt-8 flex justify-between">
<button id="prevQuestionBtn" class="bg-gray-300 hover:bg-gray-400 text-gray-800 font-bold py-2 px-4 rounded-md focus:outline-none focus:ring-2 focus:ring-gray-500 focus:ring-offset-2 transition duration-150">
<i class="fas fa-arrow-left"></i> Anterior
</button>
<button id="nextQuestionBtn" class="bg-blue-600 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 transition duration-150">
Próxima <i class="fas fa-arrow-right"></i>
</button>
<button id="submitQuizBtn" class="bg-green-600 hover:bg-green-700 text-white font-bold py-2 px-4 rounded-md focus:outline-none focus:ring-2 focus:ring-green-500 focus:ring-offset-2 transition duration-150 hidden">
Finalizar <i class="fas fa-check"></i>
</button>
</div>
</div>
</div>
<div class="bg-white rounded-lg shadow-md p-4">
<div class="flex flex-wrap gap-2">
<!-- Question navigation buttons will be inserted here -->
</div>
</div>
</div>
</div>
<!-- Results Screen -->
<div id="resultsScreen" class="min-h-screen hidden py-8 px-4">
<div class="max-w-3xl mx-auto">
<div class="bg-white rounded-lg shadow-md overflow-hidden">
<div class="bg-green-600 py-4 px-6">
<h2 class="text-2xl font-bold text-white">Resultado do Questionário</h2>
</div>
<div class="p-6">
<div class="flex items-center mb-6">
<div class="h-24 w-24 bg-blue-100 rounded-full flex items-center justify-center mr-6">
<span id="scoreCircle" class="text-3xl font-bold text-blue-600">0</span>
</div>
<div>
<h3 class="text-xl font-semibold text-gray-800" id="studentNameDisplay"></h3>
<p class="text-gray-600" id="studentInfoDisplay"></p>
<p class="mt-2 text-gray-800"><span id="correctAnswers">0</span> de <span id="totalQuestionsDisplay">10</span> corretas (<span id="percentage">0</span>%)</p>
</div>
</div>
<div id="wrongAnswersContainer" class="mb-6">
<!-- Wrong answers will be inserted here -->
</div>
<div class="flex justify-between">
<button id="viewResultsBtn" class="bg-blue-600 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 transition duration-150">
Ver Resultados Detalhados
</button>
</div>
</div>
</div>
</div>
</div>
<!-- Admin Panel (hidden by default, accessible via URL parameter) -->
<div id="adminPanel" class="min-h-screen hidden py-8 px-4">
<div class="max-w-6xl mx-auto">
<div class="bg-white rounded-lg shadow-md overflow-hidden">
<div class="bg-purple-600 py-4 px-6">
<h2 class="text-2xl font-bold text-white">Painel Administrativo</h2>
</div>
<div class="p-6">
<div class="mb-6 flex justify-between items-center">
<div>
<h3 class="text-lg font-semibold text-gray-800">Resultados dos Alunos</h3>
<p class="text-gray-600">Visualize todas as respostas e desempenhos</p>
</div>
<div class="flex space-x-2">
<select id="classFilter" class="px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-purple-500">
<option value="">Todas as Turmas</option>
<option value="1n1">1n1</option>
<option value="1n2">1n2</option>
<option value="2n1">2n1</option>
<option value="2n2">2n2</option>
<option value="3n1">3n1</option>
<option value="3n2">3n2</option>
<option value="1eja">1eja</option>
<option value="2eja">2eja</option>
<option value="3eja">3eja</option>
</select>
<button id="exportResultsBtn" class="bg-green-600 hover:bg-green-700 text-white font-bold py-2 px-4 rounded-md focus:outline-none focus:ring-2 focus:ring-green-500 focus:ring-offset-2 transition duration-150">
Exportar Dados
</button>
</div>
</div>
<div class="mb-6">
<label for="classFilter" class="block text-gray-700 font-medium mb-2">Filtrar por Turma:</label>
<select id="classFilter" class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-purple-500">
<option value="">Todas as turmas</option>
<option value="1n1">1n1</option>
<option value="1n2">1n2</option>
<option value="2n1">2n1</option>
<option value="2n2">2n2</option>
<option value="3n1">3n1</option>
<option value="3n2">3n2</option>
<option value="1eja">1eja</option>
<option value="2eja">2eja</option>
<option value="3eja">3eja</option>
</select>
</div>
<div class="overflow-x-auto">
<table id="resultsTable" class="results-table w-full">
<thead>
<tr class="bg-gray-100">
<th class="text-left py-2 px-4">Aluno</th>
<th class="text-left py-2 px-4">Turma</th>
<th class="text-left py-2 px-4">Data</th>
<th class="text-left py-2 px-4">Acertos</th>
<th class="text-left py-2 px-4">Nota (0-10)</th>
<th class="text-left py-2 px-4">% de Acerto</th>
<th class="text-left py-2 px-4">Tempo</th>
</tr>
</thead>
<tbody id="resultsTableBody">
<!-- Results will be inserted here -->
</tbody>
</table>
</div>
<div class="mt-4 bg-gray-100 p-4 rounded-lg">
<h3 class="font-medium text-gray-800 mb-2">Estatísticas por Turma:</h3>
<div id="classStats" class="grid grid-cols-1 md:grid-cols-3 gap-4">
<!-- Class statistics will be inserted here -->
</div>
</div>
</div>
</div>
</div>
</div>
<script>
// Question data with images (using placeholder images from Unsplash)
const questions = [
{
question: "Qual é a principal diferença entre grafite e pixo, segundo os artistas entrevistados no documentário \"Cidade Cinza\"?",
answers: [
{ text: "O grafite é sempre feito com permissão enquanto o pixo é sempre ilegal", correct: false },
{ text: "O grafite é considerado arte enquanto o pixo é visto apenas como vandalismo puro", correct: false },
{ text: "O grafite prioriza a estética e o apelo visual, já o pixo enfatiza a mensagem e a ocupação do espaço urbano", correct: true },
{ text: "O grafite utiliza apenas tintas spray profissionais enquanto o pixo usa materiais improvisados", correct: false },
{ text: "Não existe diferença significativa entre as duas manifestações urbanas", correct: false }
],
image: "https://source.unsplash.com/random/600x400/?graffiti,art",
explanation: "Resposta correta: O grafite prioriza a estética e o apelo visual, já o pixo enfatiza a mensagem e a ocupação do espaço urbano. O documentário mostra que grafiteiros buscam beleza plástica, enquanto pichadores veem seu ato como marca de presença e protesto."
},
{
question: "Como os artistas retratados no documentário justificam o pixo como forma de expressão artística?",
answers: [
{ text: "Por ser uma técnica mais simples e acessível do que o grafite tradicional", correct: false },
{ text: "Por representar uma forma de contestação social e afirmação de presença no espaço público", correct: true },
{ text: "Por ser mais facilmente aceito e compreendido pelo grande público", correct: false },
{ text: "Por exigir menos habilidade técnica e preparo artístico", correct: false },
{ text: "Por ser sempre realizado com autorização dos proprietários dos muros", correct: false }
],
image: "https://source.unsplash.com/random/600x400/?street,art",
explanation: "Resposta correta: Por representar uma forma de contestação social e afirmação de presença no espaço público. Muitos pichadores veem seu ato como resistência ao controle do espaço urbano."
},
{
question: "Qual foi o papel dos irmãos Os Gêmeos no desenvolvimento do grafite em São Paulo, conforme apresentado no documentário?",
answers: [
{ text: "Foram os pioneiros absolutos na introdução do pixo na cidade", correct: false },
{ text: "Contribuíram para internacionalizar o grafite brasileiro, dando visibilidade global à cena paulistana", correct: true },
{ text: "Atuaram como críticos ferrenhos de qualquer forma de arte urbana", correct: false },
{ text: "Trabalharam exclusivamente em espaços institucionais, nunca em intervenções urbanas", correct: false },
{ text: "Foram responsáveis diretos pela criminalização do grafite na cidade", correct: false }
],
image: "https://source.unsplash.com/random/600x400/?osgemeos,art",
explanation: "Resposta correta: Contribuíram para internacionalizar o grafite brasileiro, dando visibilidade global à cena paulistana. Os Gêmeos foram fundamentais para colocar o grafite brasileiro no cenário mundial."
},
{
question: "Como \"Cidade Cinza\" retrata a relação entre os artistas urbanos e o poder público municipal?",
answers: [
{ text: "Mostra uma cooperação constante e harmoniosa entre as partes", correct: false },
{ text: "Revela um cenário de conflito com períodos de repressão, mas também momentos de reconhecimento oficial", correct: true },
{ text: "Apresenta uma completa ausência de interferência governamental", correct: false },
{ text: "Demonstra que todos os artistas foram contratados formalmente pela prefeitura", correct: false },
{ text: "Indica que a prefeitura apoiava apenas o pixo, nunca o grafite", correct: false }
],
image: "https://source.unsplash.com/random/600x400/?city,government",
explanation: "Resposta correta: Revela um cenário de conflito com períodos de repressão, mas também momentos de reconhecimento oficial. O documentário mostra essa relação ambígua, com repressão e também projetos de urbanismo que incorporam o grafite."
},
{
question: "Qual a posição predominante entre os artistas do filme em relação à criminalização do pixo?",
answers: [
{ text: "Concordam plenamente com sua classificação como ato vandalico", correct: false },
{ text: "Defendem sua legitimidade como expressão cultural e criticam a repressão sistemática", correct: true },
{ text: "Acreditam que apenas o grafite deveria ser permitido por lei", correct: false },
{ text: "Consideram que o pixo só é aceitável em áreas abandonadas", correct: false },
{ text: "Não manifestam qualquer opinião formada sobre o assunto", correct: false }
],
image: "https://source.unsplash.com/random/600x400/?protest,art",
explanation: "Resposta correta: Defendem sua legitimidade como expressão cultural e criticam a repressão sistemática. Pichadores veem a criminalização como uma tentativa de silenciar formas de expressão marginalizadas."
},
{
question: "Qual foi o impacto da Lei Cidade Limpa sobre as manifestações de arte urbana em São Paulo, segundo o documentário?",
answers: [
{ text: "Estimulou o surgimento de novos artistas de rua", correct: false },
{ text: "Intensificou a fiscalização e repressão contra qualquer tipo de intervenção urbana", correct: true },
{ text: "Afetou apenas a publicidade comercial, sem relação com a arte de rua", correct: false },
{ text: "Transformou o pixo em patrimônio cultural oficial", correct: false },
{ text: "Na prática, nunca foi implementada de fato", correct: false }
],
image: "https://source.unsplash.com/random/600x400/?law,sign",
explanation: "Resposta correta: Intensificou a fiscalização e repressão contra qualquer tipo de intervenção urbana. A lei, originalmente voltada contra a poluição visual, foi aplicada também contra expressões artísticas."
},
{
question: "Como os artistas do filme percebem a inserção do grafite no circuito comercial de arte?",
answers: [
{ text: "Consideram que isso representa a perda da essência contestadora original", correct: true },
{ text: "Veem como a única forma legítima de valorização do grafite", correct: false },
{ text: "Acreditam que o mercado nunca realmente aceitou o grafite como arte", correct: false },
{ text: "Não fazem distinção entre grafite e pixo no contexto mercadológico", correct: false },
{ text: "Avaliam que o pixo tem maior valor comercial que o grafite", correct: false }
],
image: "https://source.unsplash.com/random/600x400/?commerce,art",
explanation: "Resposta correta: Consideram que isso representa a perda da essência contestadora original. Alguns veem a comercialização como traição aos princípios de resistência presente na arte de rua."
},
{
question: "O que o documentário revela sobre as tensões entre grafiteiros e pichadores?",
answers: [
{ text: "Mostra uma convivência sempre pacífica e colaborativa", correct: false },
{ text: "Expõe rivalidades, com grafiteiros muitas vezes criticando o pixo como vandalismo e pichadores acusando grafiteiros de \"vendidos\"", correct: true },
{ text: "Indica que todos os grafiteiros também praticam pixo regularmente", correct: false },
{ text: "Demonstra completa ausência de conflitos entre os grupos", correct: false },
{ text: "Revela que a polícia sempre mediou positivamente essas relações", correct: false }
],
image: "https://source.unsplash.com/random/600x400/?conflict,street",
explanation: "Resposta correta: Expõe rivalidades, com grafiteiros muitas vezes criticando o pixo como vandalismo e pichadores acusando grafiteiros de \"vendidos\". Essa divisão reflete diferentes visões sobre o papel da arte urbana."
},
{
question: "Qual é a visão central apresentada pelo documentário sobre o papel da arte urbana na transformação das cidades?",
answers: [
{ text: "Que ela contribui para piorar a degradação dos centros urbanos", correct: false },
{ text: "Que grafite e pixo funcionam como formas de resistência e humanização dos espaços cinzentos", correct: true },
{ text: "Que deveria ser restrita a museus e galerias especializadas", correct: false },
{ text: "Que não possui qualquer capacidade transformadora real", correct: false },
{ text: "Que apenas o grafite tem este poder, nunca o pixo", correct: false }
],
image: "https://source.unsplash.com/random/600x400/?city,transformation",
explanation: "Resposta correta: Que grafite e pixo funcionam como formas de resistência e humanização dos espaços cinzentos. O filme mostra como essas expressões trazem vida e crítica à paisagem urbana."
},
{
question: "Como os artistas entrevistados em \"Cidade Cinza\" enxergam o futuro dessas manifestações artísticas urbanas?",
answers: [
{ text: "Acreditam que ambas estão fadadas ao desaparecimento devido à repressão crescente", correct: false },
{ text: "Preveem que o grafite se tornará a única forma aceita de arte de rua", correct: false },
{ text: "Percebem que continuarão evoluindo e se adaptando como formas de expressão e resistência", correct: true },
{ text: "Esperam que o pixo substitua completamente o grafite no cenário urbano", correct: false },
{ text: "Não demonstram qualquer preocupação ou reflexão sobre o futuro", correct: false }
],
image: "https://source.unsplash.com/random/600x400/?future,city",
explanation: "Resposta correta: Percebem que continuarão evoluindo e se adaptando como formas de expressão e resistência. Apesar da repressão, os artistas veem essas manifestações como persistentes e mutáveis."
}
];
// DOM Elements
const teacherLoginScreen = document.getElementById('teacherLoginScreen');
const teacherUsername = document.getElementById('teacherUsername');
const teacherPassword = document.getElementById('teacherPassword');
const teacherLoginBtn = document.getElementById('teacherLoginBtn');
const loginScreen = document.getElementById('loginScreen');
const quizScreen = document.getElementById('quizScreen');
const resultsScreen = document.getElementById('resultsScreen');
const adminPanel = document.getElementById('adminPanel');
const studentName = document.getElementById('studentName');
const studentClass = document.getElementById('studentClass');
const quizDate = document.getElementById('quizDate');
const startQuizBtn = document.getElementById('startQuizBtn');
const questionText = document.getElementById('questionText');
const questionImage = document.getElementById('questionImage');
const answersContainer = document.getElementById('answersContainer');
const prevQuestionBtn = document.getElementById('prevQuestionBtn');
const nextQuestionBtn = document.getElementById('nextQuestionBtn');
const submitQuizBtn = document.getElementById('submitQuizBtn');
const questionNumber = document.getElementById('questionNumber');
const currentQuestion = document.getElementById('currentQuestion');
const totalQuestions = document.getElementById('totalQuestions');
const timer = document.getElementById('timer');
const studentNameDisplay = document.getElementById('studentNameDisplay');
const studentInfoDisplay = document.getElementById('studentInfoDisplay');
const correctAnswers = document.getElementById('correctAnswers');
const totalQuestionsDisplay = document.getElementById('totalQuestionsDisplay');
const percentage = document.getElementById('percentage');
const scoreCircle = document.getElementById('scoreCircle');
const wrongAnswersContainer = document.getElementById('wrongAnswersContainer');
const viewResultsBtn = document.getElementById('viewResultsBtn');
const resultsTableBody = document.getElementById('resultsTableBody');
const classFilter = document.getElementById('classFilter');
const exportResultsBtn = document.getElementById('exportResultsBtn');
// Quiz State
let quizState = {
currentQuestionIndex: 0,
shuffledQuestions: [],
shuffledAnswers: [],
userAnswers: Array(questions.length).fill(null),
timeElapsed: 0,
timerInterval: null,
studentName: '',
studentClass: '',
quizDate: '',
isFinished: false
};
// Admin mode check from URL
const urlParams = new URLSearchParams(window.location.search);
const adminMode = urlParams.get('admin');
// Teacher credentials (in a real app, these would be server-side)
const TEACHER_CREDENTIALS = {
username: "professor",
password: "escola123"
};
// Initialize the app
function initApp() {
// Set up teacher password modal
const teacherPasswordModal = document.getElementById('teacherPasswordModal');
const teacherAccessBtn = document.getElementById('teacherAccessBtn');
const teacherPasswordInput = document.getElementById('teacherPasswordInput');
const cancelPasswordBtn = document.getElementById('cancelPasswordBtn');
const confirmPasswordBtn = document.getElementById('confirmPasswordBtn');
teacherAccessBtn.addEventListener('click', () => {
teacherPasswordModal.classList.remove('hidden');
});
cancelPasswordBtn.addEventListener('click', () => {
teacherPasswordModal.classList.add('hidden');
teacherPasswordInput.value = '';
});
confirmPasswordBtn.addEventListener('click', () => {
if (teacherPasswordInput.value === 'Profandre123') {
teacherPasswordModal.classList.add('hidden');
loginScreen.classList.add('hidden');
adminPanel.classList.remove('hidden');
loadResults();
} else {
alert('Senha incorreta!');
}
teacherPasswordInput.value = '';
});
// Allow pressing Enter in password field
teacherPasswordInput.addEventListener('keypress', (e) => {
if (e.key === 'Enter') {
confirmPasswordBtn.click();
}
});
// Set up teacher login button
if (teacherLoginBtn) {
teacherLoginBtn.addEventListener('click', () => {
if (teacherUsername.value === TEACHER_CREDENTIALS.username &&
teacherPassword.value === TEACHER_CREDENTIALS.password) {
teacherLoginScreen.classList.add('hidden');
adminPanel.classList.remove('hidden');
loadResults();
} else {
alert('Credenciais inválidas. Tente novamente.');
}
});
}
if (adminMode === 'true') {
loginScreen.classList.add('hidden');
quizScreen.classList.add('hidden');
resultsScreen.classList.add('hidden');
adminPanel.classList.remove('hidden');
loadResults();
return;
}
// Set up event listeners
startQuizBtn.addEventListener('click', startQuiz);
prevQuestionBtn.addEventListener('click', showPreviousQuestion);
nextQuestionBtn.addEventListener('click', showNextQuestion);
submitQuizBtn.addEventListener('click', showResults);
viewResultsBtn.addEventListener('click', showDetailedResults);
classFilter.addEventListener('change', filterResults);
exportResultsBtn.addEventListener('click', exportResults);
// Set today's date as default
const today = new Date().toISOString().split('T')[0];
quizDate.value = today;
// Initialize the question navigator
initQuestionNavigator();
// Display total questions
totalQuestions.textContent = questions.length;
totalQuestionsDisplay.textContent = questions.length;
}
// Initialize question navigator buttons
function initQuestionNavigator() {
const questionNav = document.querySelector('.flex.flex-wrap.gap-2');
questionNav.innerHTML = '';
questions.forEach((_, index) => {
const btn = document.createElement('button');
btn.className = `w-10 h-10 rounded-full flex items-center justify-center ${index === 0 ? 'bg-blue-600 text-white' : 'bg-gray-200 text-gray-700 hover:bg-gray-300'} transition`;
btn.textContent = index + 1;
btn.onclick = () => goToQuestion(index);
const btnContainer = document.createElement('div');
btnContainer.className = 'tooltip-container relative';
const tooltip = document.createElement('span');
tooltip.className = 'tooltip hidden absolute z-10 w-36 px-3 py-2 text-sm font-medium text-white bg-gray-900 rounded-lg shadow-sm dark:bg-gray-700 bottom-full mb-2 left-1/2 transform -translate-x-1/2';
tooltip.textContent = `Questão ${index + 1}`;
btnContainer.appendChild(btn);
btnContainer.appendChild(tooltip);
// Show tooltip on hover
btn.addEventListener('mouseover', () => {
tooltip.classList.remove('hidden');
});
btn.addEventListener('mouseout', () => {
tooltip.classList.add('hidden');
});
questionNav.appendChild(btnContainer);
});
}
// Start the quiz
function startQuiz() {
// Check if a quiz was already completed
if (localStorage.getItem('quizCompleted_' + studentName.value)) {
alert('Você já completou este questionário e não pode realizá-lo novamente.');
return;
}
if (!studentName.value || !studentClass.value || !quizDate.value) {
alert('Por favor, preencha todas as informações antes de começar.');
return;
}
// Save student info
quizState.studentName = studentName.value;
quizState.studentClass = studentClass.value;
quizState.quizDate = quizDate.value;
// Shuffle questions and answers
quizState.shuffledQuestions = shuffleArray([...questions]);
quizState.shuffledAnswers = quizState.shuffledQuestions.map(q => shuffleArray([...q.answers]));
quizState.userAnswers = Array(questions.length).fill(null);
quizState.currentQuestionIndex = 0;
quizState.timeElapsed = 0;
// Start timer
startTimer();
// Hide login screen and show quiz screen
loginScreen.classList.add('hidden');
quizScreen.classList.remove('hidden');
// Display first question
displayQuestion();
}
// Display current question
function displayQuestion() {
const currentQuestion = quizState.shuffledQuestions[quizState.currentQuestionIndex];
const currentAnswers = quizState.shuffledAnswers[quizState.currentQuestionIndex];
// Update question number
questionNumber.textContent = `Pergunta ${quizState.currentQuestionIndex + 1}`;
document.getElementById('currentQuestion').textContent = quizState.currentQuestionIndex + 1;
// Update question text
questionText.textContent = currentQuestion.question;
// Update question image
questionImage.src = currentQuestion.image;
questionImage.alt = `Imagem ilustrativa para a pergunta ${quizState.currentQuestionIndex + 1}`;
// Clear previous answers
answersContainer.innerHTML = '';
// Add new answers
currentAnswers.forEach((answer, index) => {
const answerDiv = document.createElement('div');
answerDiv.className = 'flex items-center p-3 bg-gray-100 rounded-md cursor-pointer hover:bg-gray-200 transition';
answerDiv.dataset.index = index;
const radio = document.createElement('input');
radio.type = 'radio';
radio.name = 'answer';
radio.id = `answer-${index}`;
radio.className = 'mr-3 h-5 w-5 text-blue-600 focus:ring-blue-500';
// Check if this answer was previously selected
if (quizState.userAnswers[quizState.currentQuestionIndex] === index) {
radio.checked = true;
}
const label = document.createElement('label');
label.htmlFor = `answer-${index}`;
label.className = 'text-gray-800 cursor-pointer';
label.textContent = answer.text;
answerDiv.appendChild(radio);
answerDiv.appendChild(label);
// Add click event
answerDiv.addEventListener('click', () => selectAnswer(index));
answersContainer.appendChild(answerDiv);
});
// Enable/disable navigation buttons
prevQuestionBtn.disabled = quizState.currentQuestionIndex === 0;
nextQuestionBtn.classList.toggle('hidden', quizState.currentQuestionIndex === questions.length - 1);
submitQuizBtn.classList.toggle('hidden', quizState.currentQuestionIndex !== questions.length - 1);
// Update question navigator buttons
updateQuestionNavigator();
}
// Update question navigator buttons
function updateQuestionNavigator() {
const buttons = document.querySelectorAll('.flex.flex-wrap.gap-2 button');
buttons.forEach((btn, index) => {
// Remove all active classes
btn.classList.remove('bg-blue-600', 'text-white', 'bg-gray-200', 'text-gray-700', 'bg-green-100', 'text-green-800', 'bg-red-100', 'text-red-800');
// Current question
if (index === quizState.currentQuestionIndex) {
btn.classList.add('bg-blue-600', 'text-white');
}
// Answered questions
else if (quizState.userAnswers[index] !== null) {
const isCorrect = checkAnswer(index, quizState.userAnswers[index]);
btn.classList.add(isCorrect ? 'bg-green-100' : 'bg-red-100', isCorrect ? 'text-green-800' : 'text-red-800');
}
// Unanswered questions
else {
btn.classList.add('bg-gray-200', 'text-gray-700');
}
});
}
// Select an answer
function selectAnswer(answerIndex) {
quizState.userAnswers[quizState.currentQuestionIndex] = answerIndex;
updateQuestionNavigator();
}
// Check if answer is correct
function checkAnswer(questionIndex, answerIndex) {
const question = quizState.shuffledQuestions[questionIndex];
const answer = quizState.shuffledAnswers[questionIndex][answerIndex];
return answer.correct;
}
// Navigate to previous question
function showPreviousQuestion() {
if (quizState.currentQuestionIndex > 0) {
quizState.currentQuestionIndex--;
displayQuestion();
}
}
// Navigate to next question
function showNextQuestion() {
if (quizState.userAnswers[quizState.currentQuestionIndex] === null) {
alert('Por favor, selecione uma resposta antes de prosseguir.');
return;
}
if (quizState.currentQuestionIndex < questions.length - 1) {
quizState.currentQuestionIndex++;
displayQuestion();
}
}
// Navigate to specific question
function goToQuestion(index) {
quizState.currentQuestionIndex = index;
displayQuestion();
}
// Start timer
function startTimer() {
clearInterval(quizState.timerInterval);
quizState.timeElapsed = 0;
updateTimerDisplay();
quizState.timerInterval = setInterval(() => {
quizState.timeElapsed++;
updateTimerDisplay();
}, 1000);
}
// Update timer display
function updateTimerDisplay() {
const minutes = Math.floor(quizState.timeElapsed / 60).toString().padStart(2, '0');
const seconds = (quizState.timeElapsed % 60).toString().padStart(2, '0');
timer.textContent = `${minutes}:${seconds}`;
}
// Show results
function showResults() {
if (quizState.userAnswers[quizState.currentQuestionIndex] === null) {
alert('Por favor, selecione uma resposta antes de finalizar.');
return;
}
// Stop timer
clearInterval(quizState.timerInterval);
// Calculate score
const correctCount = quizState.userAnswers.reduce((count, answerIndex, questionIndex) => {
return count + (checkAnswer(questionIndex, answerIndex) ? 1 : 0);
}, 0);
const score = Math.round((correctCount / questions.length) * 10);
const percentage = (correctCount / questions.length * 100).toFixed(1);
// Update results display
studentNameDisplay.textContent = quizState.studentName;
studentInfoDisplay.textContent = `${quizState.studentClass} - ${formatDate(quizState.quizDate)}`;
correctAnswers.textContent = correctCount;
percentage.textContent = percentage;
scoreCircle.textContent = score;
// Generate wrong answers list
wrongAnswersContainer.innerHTML = '';
const wrongAnswersCount = questions.length - correctCount;
if (wrongAnswersCount > 0) {
const wrongAnswersTitle = document.createElement('h4');
wrongAnswersTitle.className = 'text-lg font-semibold mb-3 text-gray-800';
wrongAnswersTitle.textContent = `Correção das ${wrongAnswersCount === 1 ? 'resposta incorreta' : 'respostas incorretas'}:`;
wrongAnswersContainer.appendChild(wrongAnswersTitle);
quizState.userAnswers.forEach((userAnswer, index) => {
if (!checkAnswer(index, userAnswer)) {
const questionItem = document.createElement('div');
questionItem.className = 'mb-4 p-3 bg-red-50 rounded-md';
const questionText = document.createElement('p');
questionText.className = 'font-medium text-red-800';
questionText.textContent = `${index + 1}. ${quizState.shuffledQuestions[index].question}`;
questionItem.appendChild(questionText);
const userAnswerText = document.createElement('p');
userAnswerText.className = 'ml-4 mt-1 text-red-600';
userAnswerText.textContent = `Sua resposta: ${quizState.shuffledAnswers[index][userAnswer].text}`;
questionItem.appendChild(userAnswerText);
const explanationText = document.createElement('p');
explanationText.className = 'ml-4 mt-1 text-gray-700';
explanationText.textContent = quizState.shuffledQuestions[index].explanation;
questionItem.appendChild(explanationText);
wrongAnswersContainer.appendChild(questionItem);
}
});
} else {
const allCorrect = document.createElement('div');
allCorrect.className = 'bg-green-100 text-green-800 p-3 rounded-md text-center font-medium';
allCorrect.textContent = 'Parabéns! Você acertou todas as questões!';
wrongAnswersContainer.appendChild(allCorrect);
}
// Store results
storeResults(correctCount, score);
// Mark as finished and hide quiz screen
quizState.isFinished = true;
quizScreen.classList.add('hidden');
resultsScreen.classList.remove('hidden');
}
// Show detailed results
function showDetailedResults() {
const detailedResults = document.createElement('div');
detailedResults.className = 'mt-6 bg-white rounded-lg shadow-md p-6';
const title = document.createElement('h3');
title.className = 'text-xl font-semibold mb-4 text-gray-800';
title.textContent = 'Resultado Detalhado';
detailedResults.appendChild(title);
quizState.shuffledQuestions.forEach((question, index) => {
const questionDiv = document.createElement('div');
questionDiv.className = 'mb-6 p-4 border border-gray-200 rounded-lg';
// Question
const questionText = document.createElement('p');
questionText.className = 'font-medium text-gray-800 mb-3';
questionText.textContent = `${index + 1}. ${question.question}`;
questionDiv.appendChild(questionText);
// User answer
const userAnswer = document.createElement('p');
const isCorrect = checkAnswer(index, quizState.userAnswers[index]);
userAnswer.className = `font-medium ml-4 ${isCorrect ? 'text-green-600' : 'text-red-600'}`;
userAnswer.textContent = `Sua resposta: ${quizState.shuffledAnswers[index][quizState.userAnswers[index]].text}`;
questionDiv.appendChild(userAnswer);
if (!isCorrect) {
// Correct answer
const correctAnswer = question.answers.find(a => a.correct);
if (correctAnswer) {
const correctAnswerText = document.createElement('p');
correctAnswerText.className = 'font-medium ml-4 text-green-600';
correctAnswerText.textContent = `Resposta correta: ${correctAnswer.text}`;
questionDiv.appendChild(correctAnswerText);
}
}
// Explanation
if (question.explanation) {
const explanation = document.createElement('p');
explanation.className = 'ml-4 mt-2 text-gray-700 italic';
explanation.textContent = question.explanation;
questionDiv.appendChild(explanation);
}
detailedResults.appendChild(questionDiv);
});
// Add close button
const closeBtn = document.createElement('button');
closeBtn.className = 'mt-4 bg-blue-600 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 transition duration-150';
closeBtn.textContent = 'Fechar';
closeBtn.onclick = () => detailedResults.remove();
detailedResults.appendChild(closeBtn);
// Insert after wrong answers
wrongAnswersContainer.appendChild(detailedResults);
}
// Store results in localStorage
function storeResults(correctCount, score) {
// Format answers for storage (e.g., "1.c, 2.a, 3.b, ...")
const formattedAnswers = quizState.userAnswers.map((answerIndex, questionIndex) => {
if (answerIndex === null) return `${questionIndex + 1}.não respondida`;
const answerLetters = ['a', 'b', 'c', 'd', 'e'];
return `${questionIndex + 1}.${answerLetters[answerIndex]}`;
}).join(', ');
// Format time
const minutes = Math.floor(quizState.timeElapsed / 60).toString().padStart(2, '0');
const seconds = (quizState.timeElapsed % 60).toString().padStart(2, '0');
const formattedTime = `${minutes}:${seconds}`;
// Create result object
const result = {
name: quizState.studentName,
class: quizState.studentClass,
date: quizState.quizDate,
answers: formattedAnswers,
correct: correctCount,
score: score,
time: formattedTime,
timestamp: new Date().toISOString(),
originalOrder: quizState.shuffledQuestions.map(q => questions.findIndex(item => item.question === q.question))
};
// Get existing results or create new array
const existingResults = JSON.parse(localStorage.getItem('quizResults')) || [];
// Add new result
existingResults.push(result);
// Save back to localStorage
localStorage.setItem('quizResults', JSON.stringify(existingResults));
localStorage.setItem('quizCompleted_' + quizState.studentName, 'true');
}
// Load results for admin panel
function loadResults(filterClass = '') {
const allResults = JSON.parse(localStorage.getItem('quizResults')) || [];
// Clear table
resultsTableBody.innerHTML = '';
// Add all results to the table (filtering will be handled by filterResults)
allResults.forEach(result => {
const row = document.createElement('tr');
row.className = 'hover:bg-gray-50';
// Name
const nameCell = document.createElement('td');
nameCell.className = 'py-2 px-4';
nameCell.textContent = result.name;
row.appendChild(nameCell);
// Class
const classCell = document.createElement('td');
classCell.className = 'py-2 px-4';
classCell.textContent = result.class;
row.appendChild(classCell);
// Date
const dateCell = document.createElement('td');
dateCell.className = 'py-2 px-4';
dateCell.textContent = formatDate(result.date);
row.appendChild(dateCell);
// Answers
const answersCell = document.createElement('td');
answersCell.className = 'py-2 px-4 font-mono text-sm';
answersCell.textContent = result.answers;
row.appendChild(answersCell);
// Score
const scoreCell = document.createElement('td');
scoreCell.className = 'py-2 px-4 font-semibold';
scoreCell.textContent = `${result.correct}/${questions.length} (${result.score}/10)`;
row.appendChild(scoreCell);
// Time
const timeCell = document.createElement('td');
timeCell.className = 'py-2 px-4';
timeCell.textContent = result.time;
row.appendChild(timeCell);
resultsTableBody.appendChild(row);
});
// Update stats and chart (will be filtered by filterResults)
updateClassStatistics(allResults);
updateClassPieChart(allResults);
results.forEach(result => {
const row = document.createElement('tr');
row.className = 'hover:bg-gray-50';
// Name
const nameCell = document.createElement('td');
nameCell.className = 'py-2 px-4';
nameCell.textContent = result.name;
row.appendChild(nameCell);
// Class
const classCell = document.createElement('td');
classCell.className = 'py-2 px-4';
classCell.textContent = result.class;
row.appendChild(classCell);
// Date
const dateCell = document.createElement('td');
dateCell.className = 'py-2 px-4';
dateCell.textContent = formatDate(result.date);
row.appendChild(dateCell);
// Answers
const answersCell = document.createElement('td');
answersCell.className = 'py-2 px-4 font-mono text-sm';
answersCell.textContent = result.answers;
row.appendChild(answersCell);
// Score
const scoreCell = document.createElement('td');
scoreCell.className = 'py-2 px-4 font-semibold';
scoreCell.textContent = `${result.correct}/${questions.length} (${result.score}/10)`;
row.appendChild(scoreCell);
// Time
const timeCell = document.createElement('td');
timeCell.className = 'py-2 px-4';
timeCell.textContent = result.time;
row.appendChild(timeCell);
resultsTableBody.appendChild(row);
});
}
// Filter results by class
function updateClassStatistics(results) {
const classStatsContainer = document.getElementById('classStats');
if (!classStatsContainer) return;
// Group results by class
const classes = {};
results.forEach(result => {
if (!classes[result.class]) {
classes[result.class] = {
count: 0,
totalScore: 0,
totalCorrect: 0
};
}
classes[result.class].count++;
classes[result.class].totalScore += result.score;
classes[result.class].totalCorrect += result.correct;
});
// Generate stats for each class
classStatsContainer.innerHTML = '';
Object.entries(classes).forEach(([className, stats]) => {
const avgScore = (stats.totalScore / stats.count).toFixed(1);
const avgCorrect = (stats.totalCorrect / (stats.count * questions.length) * 100).toFixed(1);
const statCard = document.createElement('div');
statCard.className = 'bg-white p-4 rounded-lg shadow-sm border border-gray-200';
statCard.innerHTML = `
<h4 class="font-bold text-lg">${className}</h4>
<p class="mt-2"><span class="font-semibold">Alunos:</span> ${stats.count}</p>
<p><span class="font-semibold">Média de notas:</span> ${avgScore}/10</p>
<p><span class="font-semibold">% de acerto:</span> ${avgCorrect}%</p>
`;
classStatsContainer.appendChild(statCard);
});
// Add overall stats
const totalStudents = results.length;
if (totalStudents > 0) {
const totalScore = results.reduce((sum, r) => sum + r.score, 0);
const totalCorrect = results.reduce((sum, r) => sum + r.correct, 0);
const overallAvgScore = (totalScore / totalStudents).toFixed(1);
const overallAvgCorrect = (totalCorrect / (totalStudents * questions.length) * 100).toFixed(1);
const overallStat = document.createElement('div');
overallStat.className = 'bg-blue-50 p-4 rounded-lg shadow-sm border border-blue-200 md:col-span-3';
overallStat.innerHTML = `
<h4 class="font-bold text-lg text-blue-800">Estatísticas Gerais</h4>
<p class="mt-2"><span class="font-semibold">Total de alunos:</span> ${totalStudents}</p>
<p><span class="font-semibold">Média geral de notas:</span> ${overallAvgScore}/10</p>
<p><span class="font-semibold">% geral de acerto:</span> ${overallAvgCorrect}%</p>
`;
classStatsContainer.appendChild(overallStat);
}
}
function filterResults() {
const selectedClass = classFilter.value;
loadResults(selectedClass);
}
// Update pie chart for class stats
function updateClassPieChart(results) {
// Get container or create it
let chartContainer = document.getElementById('pieChartContainer');
if (!chartContainer) {
chartContainer = document.createElement('div');
chartContainer.id = 'pieChartContainer';
chartContainer.className = 'w-full max-w-md mx-auto mt-6 bg-white p-4 rounded-lg shadow-md';
chartContainer.innerHTML = '<h4 class="font-bold text-center mb-4">Distribuição de Notas</h4>';
const chartCanvas = document.createElement('canvas');
chartCanvas.id = 'resultsPieChart';
chartContainer.appendChild(chartCanvas);
document.querySelector('#adminPanel .max-w-6xl').appendChild(chartContainer);
}
if (results.length === 0) {
chartContainer.innerHTML = '<p class="text-gray-500 text-center py-4">Nenhum dado disponível para exibir</p>';
return;
}
// Grade buckets
const gradeBuckets = [0, 0, 0, 0, 0]; // 0-2, 2-4, 4-6, 6-8, 8-10
results.forEach(result => {
const score = result.score;
if (score <= 2) gradeBuckets[0]++;
else if (score <= 4) gradeBuckets[1]++;
else if (score <= 6) gradeBuckets[2]++;
else if (score <= 8) gradeBuckets[3]++;
else gradeBuckets[4]++;
});
const ctx = document.getElementById('resultsPieChart').getContext('2d');
// If existing chart exists, destroy it
if (window.resultsPieChart) {
window.resultsPieChart.destroy();
}
window.resultsPieChart = new Chart(ctx, {
type: 'pie',
data: {
labels: ['0-2', '2-4', '4-6', '6-8', '8-10'],
datasets: [{
data: gradeBuckets,
backgroundColor: [
'#EF4444',
'#F59E0B',
'#3B82F6',
'#6366F1',
'#10B981'
],
borderWidth: 1
}]
},
options: {
responsive: true,
plugins: {
legend: {
position: 'bottom'
},
tooltip: {
callbacks: {
label: function(context) {
const total = results.length;
const value = context.raw;
const percentage = Math.round((value / total) * 100);
return `${context.label}: ${value} (${percentage}%)`;
}
}
}
}
}
});
}
// Export results to CSV
function exportResults() {
const results = JSON.parse(localStorage.getItem('quizResults')) || [];
if (results.length === 0) {
alert('Nenhum resultado encontrado para exportar.');
return;
}
// Create CSV header
let csv = 'Nome,Turma,Data,Respostas,Corretas,Total,Nota,Tempo\n';
// Add each result to CSV
results.forEach(result => {
csv += `"${result.name}","${result.class}","${formatDate(result.date)}","${result.answers}",${result.correct},${questions.length},${result.score},"${result.time}"\n`;
});
// Create download link
const blob = new Blob([csv], { type: 'text/csv;charset=utf-8;' });
const url = URL.createObjectURL(blob);
const link = document.createElement('a');
link.href = url;
link.download = `resultados_questionario_${formatDate(new Date().toISOString())}.csv`;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
}
// Helper function to format date
function formatDate(dateString) {
const date = new Date(dateString);
return date.toLocaleDateString('pt-BR');
}
// Helper function to shuffle array
function shuffleArray(array) {
const newArray = [...array];
for (let i = newArray.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[newArray[i], newArray[j]] = [newArray[j], newArray[i]];
}
return newArray;
}
// Initialize the app when DOM is loaded
document.addEventListener('DOMContentLoaded', initApp);
</script>
<p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=asgdestroi/document-rio" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
</html>