ESP32-S3 Bench Guide
ESP32-S3 N16R8 bench guide: live pinout, lessons, simulators and the bench log.
Envie sua apostila ou digite um tema e treine com simulado cronometrado e gabarito comentado. Comece grátis, sem cadastro.
Translation pending
EducationPython · JavaScriptGitHub @Eduardo2049OnlineOwner unconfirmed
Have you tried it? One tap is enough. No sign-in needed.
No updates detected yet. GitHub releases will appear here.
Owners of public repositories under a personal GitHub account can sign in to verify ownership and manage the introduction themselves. No administrator approval is needed.
Sign in, generate a verification file, and commit it to this repository’s default branch within 30 minutes. Files on other branches or forks do not count. Then check the file below to manage the project without administrator approval. Keep the file to retain your access.
If needed, you will go to sign-in. After signing in, return here and press your chosen verification button again.
Run /nomorevibe verify in your project folder to verify ownership and manage the introduction yourself.
Verify in one minuteAsk about other verification options
Simulados com quizzes gerados por IA a partir dos seus arquivos, com cronômetro e estatísticas. Python puro, PostgreSQL e JavaScript sem frameworks.
Translation pending
Taken from the repository README
Loading the full README.
Read the full README ↗Site: acely.com.br · Repositório: Eduardo2049/QuizesStudies (o nome do repositório é anterior à marca).
Plataforma de simulados de alto rendimento e treino de raciocínio lógico. Transforme qualquer material em PDF, DOCX ou TXT (ou gere tópicos do zero) em simulados interativos com gabarito pedagógico e Caderno de Erros inteligente com mutações por IA.
Proposta de Valor Central: “Da sua apostila ao simulado ativo, com gabarito comentado.”
Menos tempo formatando flashcards, zero distração com fóruns poluídos e foco total na retenção de raciocínio.
Estudantes para concursos, certificações e vestibulares enfrentam três grandes problemas no mercado atual:
O Acely resolve isso unindo a extração instantânea de conteúdo à Mutação de Questões por IA: a IA identifica onde você errou e pode gerar variações inéditas mantendo o mesmo conceito teórico e nível de dificuldade, forçando a aplicação real do raciocínio.
| Critério / Ferramenta | Acely | Quizlet | QConcursos / Gran Cursos | Anki |
|---|---|---|---|---|
| Geração Instantânea por Material Próprio | Sim (PDF, DOCX, TXT) | Não (Manual ou listas públicas) | Não (Apenas banco próprio de bancas) | Não (Manual card a card) |
| Geração de Simulado por Tema via IA | Sim (OpenRouter, modelos gratuitos) | Limitado (em planos pagos) | Não | Não nativo |
| Caderno de Erros com Mutação IA | Sim (Gera variações inéditas) | Não (Apenas repete o card) | Não (Filtra questões estáticas) | Não (Repete o mesmo card) |
| Explicação Didática Passo a Passo | Sim (Imediata via IA) | Raras (Geralmente apenas definição) | Sim (Fórum / Comentários de profs) | Apenas se o usuário tiver escrito |
| Experiência Limpa e Sem Fricção | Sim (Modo foco + cronômetro) | Não (Gameficado/Anúncios) | Não (Poluído de propagandas e fórum) | Interface crua e curva alta |
| Acesso sem Cadastro | Sim (home aberta + 3 usos de IA como convidado) | Parcial (sets públicos) | Não | Sim (Local) |
# 1. Instalar dependências
pip install -r requirements.txt
# 2. Criar arquivo de variáveis de ambiente
cp .env.example .env
Edite o .env:
| Variável | Obrigatória | Descrição |
|---|---|---|
DATABASE_URL | ✅ | postgresql://user:password@host:5432/dbname |
POSTGRES_PASSWORD | ✅ Docker | Senha forte do PostgreSQL local |
ADMIN_USERNAME | Não | Usuário do administrador inicial (padrão: admin) |
ADMIN_PASSWORD | ✅ | Senha forte do administrador inicial |
ALLOWED_ORIGINS | Não | Lista separada por vírgulas de origens CORS permitidas |
COOKIE_SECURE | Não | Padrão true; use false apenas no desenvolvimento HTTP |
CLOUDFLARE_TUNNEL_TOKEN | Para Tunnel | Token do Cloudflare Zero Trust para expor via túnel HTTPS |
OPENROUTER_API_KEY | Para IA | Chave do OpenRouter. Só modelos gratuitos (:free) são usados; libere-os em Settings → Privacy e deixe ZDR Endpoints Only desligado (ele bloqueia todos os gratuitos) |
OPENROUTER_FREE_MODELS | Não | Modelos gratuitos preferidos, em ordem, separados por vírgula |
OPENROUTER_DISCOVER_FREE_MODELS | Não | Padrão true: descobre os modelos gratuitos disponíveis e usa como reserva |
OPENROUTER_MAX_ATTEMPTS | Não | Modelos tentados por pedido antes de desistir (padrão: 4) |
AI_DAILY_CALL_LIMIT | Não | Teto diário de chamadas de IA; deixe abaixo do limite gratuito do OpenRouter (50/dia sem créditos) |
AI_TOKEN_QUOTA_PER_HOUR | Não | Cota de tokens estimados por hora por IP (padrão: 50000) |
AI_DAILY_CALL_LIMIT | Não | Teto global de chamadas à IA a cada 24 h, somando todos os usuários (padrão: 1000; 0 desliga). Trava de emergência contra a conta do provedor estourar |
Sobe o PostgreSQL e a aplicação com um único comando:
docker compose up -d
Para subir também o Cloudflare Tunnel (expondo com HTTPS e proteção DDoS na Cloudflare):
docker compose --profile tunnel up -d
python quiz_api.py
O servidor inicia em http://localhost:8000 (ou próxima porta livre) e executa as migrations automaticamente na primeira vez.
localStorage (quiz_lang); na primeira visita segue o idioma do navegador.web/modules/i18n.js troca textos e atributos pelo dicionário web/modules/i18n/en.js e observa o que o app.js gera depois; web/modules/i18n-boot.js evita mostrar o português por um instante antes da tradução. Elementos com translate="no" não são tocados./api/quiz/generate, /api/upload e /api/quiz/remix-mistakes aceitam o campo language (pt-BR ou en; padrão pt-BR).web/modules/i18n/<código>.js, registre em LANGUAGES e DICTIONARIES (i18n.js), repita a regra em i18n-boot.js e acrescente o código em AI_LANGUAGES (api/services/ai_service.py).qs_guest) e com teto por IP. Os simulados ficam só no navegador e o upload vai até 5 MB. Ao esgotar a cota, a tela oferece a conta grátis./register e autenticação via /login (ou Google, se configurado). Ao entrar, os simulados criados como convidado na mesma aba são salvos na conta./termos e política em /privacidade. Em "Minha conta" a pessoa baixa uma cópia dos dados (GET /api/account/export) e exclui a conta (POST /api/account/delete, com senha). O token de sessão não vai no JSON do login (só no cookie HttpOnly); clientes de API pedem com "return_token": true. POSTs vindos de outro site são recusados.adminADMIN_PASSWORD no seu .env (obrigatório antes de iniciar).python scripts/reset_admin.py "NovaSenha123*"
python scripts/reset_sessions.py
A base de código é submetida a auditorias estáticas contínuas (SAST) com Semgrep utilizando o conjunto oficial de regras para OWASP Top 10, Python, Dockerfile e Web:
# Executar varredura estática de segurança
semgrep scan --config auto .
Dockerfile cria e executa o processo sob um usuário sem privilégios (appuser, UID 1000), prevenindo ataques de escape de container e execução indevida como root (dockerfile.security.missing-user.missing-user).api/services/ai_service.py utiliza a biblioteca requests com timeout explícito e validação estrita de protocolo HTTP/HTTPS, eliminando riscos de leitura local de arquivos via esquemas como file:// (python.lang.security.audit.dynamic-urllib-use-detected).RateLimiter genérico em api/handlers/quiz_handler.py protegendo rotas críticas (/api/auth/*, /api/upload, /api/quiz/generate).CF-Connecting-IP → primeiro IP confiável de X-Forwarded-For → endereço de socket (client_address).AI_TOKEN_QUOTA_PER_HOUR):
.env), impedindo o esgotamento malicioso da cota do OpenRouter.Strict-Transport-Security (HSTS com max-age=63072000; includeSubDomains; preload), X-Content-Type-Options: nosniff, X-Frame-Options: DENY, Content-Security-Policy e Referrer-Policy.MAX_JSON_BYTES = 1 MB), upload com teto de 20 MB e whitelist de formatos (.txt, .pdf, .docx).Para disponibilizar sua aplicação com domínio próprio, HTTPS automático e proteção contra DDoS sem abrir portas no roteador:
http://app:8000.CLOUDFLARE_TUNNEL_TOKEN do seu arquivo .env.docker compose --profile tunnel up -d
Clique no botão "+ Adicionar Quiz" na interface. Você pode escolher entre duas formas:
Se você não tiver um documento pronto, digite o tema ou assunto desejado (ex: Raciocínio Lógico Proposicional, Python Básico, História do Brasil, Direito Constitucional), escolha o número de questões (3, 5 ou 10) e o nível de dificuldade. A IA elaborará todo o simulado com alternativas e explicações detalhadas!
Envie um arquivo nos formatos suportados:
.txt — texto estruturado ou em formato livre. O sistema conta com parser heurístico inteligente e adaptação via IA capaz de reconhecer perguntas e alternativas mesmo sem números de separação (1., 2.), marcadores padronizados ou com quebras de linha irregulares (respeitando o limite de peso de 20 MB)..pdf — documento PDF (extração automática de texto via pdfplumber).docx — documento Word (via python-docx)Se o arquivo não contiver gabarito, as respostas e justificativas são geradas automaticamente via IA (OPENROUTER_API_KEY, modelos gratuitos). Cada questão pode ter de 2 a N alternativas.
**1.** Enunciado da questão?
a) Opção A b) Opção B c) Opção C d) Opção D
**2.** Outra questão com alternativas em linhas separadas?
a) Opção A
b) Opção B
c) Opção C
# Gabarito
1. b) Opção B → Explicação da resposta.
2. a) Opção A → Explicação da resposta.
| Método | Rota | Autenticação | Descrição |
|---|---|---|---|
GET | / ou /index.html | Pública | Interface principal de simulados |
GET | /login ou /login.html | Pública | Página de autenticação |
GET | /register ou /register.html | Pública | Página de cadastro de estudante |
GET | /termos e /privacidade | Pública | Termos de uso e política de privacidade (LGPD) |
GET | /api/quizzes | Pública | Lista quizzes disponíveis (com cache HTTP e ETag / 304) |
GET | /api/quiz?source=<name> | Pública | Questões de um quiz (sem gabarito; com ETag / 304) |
POST | /api/quiz/submit | Pública | Submete respostas, salva tentativa e retorna score/gabarito |
GET | /api/user/attempts | Autenticado / Convidado | Histórico de tentativas e caderno de erros |
POST | /api/quiz/remix-mistakes | Convidado / Autenticado | Cria variações inéditas com IA para questões erradas (aceita language) |
POST | /api/quiz/generate | Convidado / Autenticado | Gera questões por tema via IA, com cache por hash (aceita language) |
POST | /api/auth/login | Pública | Login (sessão em cookie HttpOnly; o token só vem no JSON com "return_token": true) |
POST | /api/auth/register | Pública | Cadastro de estudante |
GET | /api/auth/me | Cookie / Bearer Token | Dados do usuário autenticado |
O projeto conta com suítes completas tanto para auditoria em ambiente isolado (sem custo de tokens) quanto para testes reais de carga contra o servidor ativo.
Nota sobre o CI: Os testes unitários (
python -m unittest discover tests) executam com PostgreSQL 16 real no pipeline de CI. Em ambiente local sem PostgreSQL disponível, o sistema faz fallback automático para SQLite em memória — funcional para desenvolvimento, mas não garante compatibilidade total com tipos PostgreSQL (ex:JSONB,SERIAL).
Valida a integridade do RateLimiter, cotas de tokens por IP e concorrência massiva:
python -m unittest tests/test_load_and_token_usage.py
429 Too Many Requests.X-Forwarded-For.Para testar a infraestrutura com geração real de questões via IA (POST /api/quiz/generate):
# Nível 1: Teste rápido de validação (5 chamadas, 1 worker, ~7k tokens)
python tests/load_test_real_api.py --calls 5 --workers 1 --guest --questions 3
# Nível 2: Carga moderada (10 chamadas, 3 workers, ~15k tokens)
python tests/load_test_real_api.py --calls 10 --workers 3 --guest --questions 5
# Nível 3: Teste de estresse com teto de 200k tokens
python tests/load_test_real_api.py --calls 50 --workers 5 --guest --questions 10 --token-limit 200000
# Nível 4: Rajada imediata para testar bloqueio 429 pelo Rate Limiter
python tests/load_test_real_api.py --calls 30 --workers 10 --burst --guest
8001, 8002, etc., evitando conflitos com serviços nativos do Windows (como IIS/HTTP.sys na porta 8000).OK, 429 BLOCKED, ERR), latência e barra de progresso do consumo acumulado de tokens.QuizesStudies/
├── api/
│ ├── database/
│ │ ├── connection.py # Context managers para PostgreSQL
│ │ └── migrations.py # Schema (executa na inicialização)
│ ├── controllers/
│ │ ├── auth_controller.py # Endpoints de login, registro e sessão
│ │ └── quiz_controller.py # Endpoints de quizzes e upload
│ ├── exceptions/
│ │ └── quiz_exceptions.py # Exceções de domínio
│ ├── handlers/
│ │ └── quiz_handler.py # Handler HTTP (GET/POST/OPTIONS)
│ ├── middleware/
│ │ └── http_middleware.py # CORS, cache, ResponseFormatter
│ ├── models/
│ │ └── dtos.py # Data Transfer Objects
│ ├── repositories/
│ │ ├── quiz_repository.py # Persistência de quizzes e questões
│ │ ├── rate_limit_repository.py # Contadores de rate limit e cotas
│ │ └── user_repository.py # Usuários, sessões, exportação e exclusão (LGPD)
│ ├── services/
│ │ ├── ai_service.py # IA via OpenRouter (só modelos gratuitos, troca automática de modelo)
│ │ ├── auth_service.py # Regras de hash e autenticação
│ │ ├── email_service.py # E-mail de redefinição de senha
│ │ ├── google_auth_service.py # Login com Google (OAuth)
│ │ ├── guest_service.py # Modo convidado e cota gratuita de IA
│ │ ├── import_service.py # Importa simulados do convidado para a conta
│ │ ├── quiz_service.py # Lógica de negócio de simulados
│ │ └── upload_service.py # Orquestração de upload TXT/PDF/DOCX
│ ├── utils/
│ │ ├── config.py # Variáveis de ambiente
│ │ ├── file_parser.py # Extração de texto (TXT/PDF/DOCX) e parse de questões
│ │ ├── quiz_logic.py # Correção e pontuação de respostas
│ │ └── validators.py # Validação de payloads HTTP
│ ├── index.py # Entrypoint Vercel (serverless)
│ └── main.py # Inicialização do servidor
├── web/
│ ├── app.js # Lógica client-side (SPA)
│ ├── index.html # Interface principal
│ ├── login.html # Tela de login moderna
│ ├── register.html # Tela de cadastro moderna
│ ├── reset-password.html # Troca de senha
│ ├── termos.html # Termos de uso
│ ├── privacidade.html # Política de privacidade (LGPD)
│ ├── modules/ # ES Modules (tema, idiomas, atalhos, estatísticas, ícones...)
│ │ ├── i18n.js # Tradução da interface (PT/EN)
│ │ ├── i18n-boot.js # Evita piscar o português antes da tradução
│ │ └── i18n/en.js # Dicionário em inglês
│ └── styles.css # Design system completo
├── 404.html # Página 404 própria
├── .env.example # Template de variáveis de ambiente
├── docker-compose.yml # PostgreSQL + app + tunnel
├── Dockerfile # Multi-stage (builder + runtime) com usuário non-root
├── Procfile
├── quiz_api.py # Entry point local
└── requirements.txt # Dependências (psycopg2, pdfplumber, requests, etc.)
-- Quizzes cadastrados
CREATE TABLE quizzes (
id SERIAL PRIMARY KEY,
name VARCHAR(255) UNIQUE NOT NULL, -- slug identificador
label VARCHAR(255) NOT NULL, -- nome de exibição
original_filename VARCHAR(255),
file_type VARCHAR(10) DEFAULT 'txt', -- 'txt' | 'pdf' | 'docx' | 'md'
has_answer_key BOOLEAN DEFAULT TRUE,
ai_generated BOOLEAN DEFAULT FALSE,
created_by INTEGER REFERENCES users(id) ON DELETE SET NULL,
is_public BOOLEAN NOT NULL DEFAULT FALSE,
created_at TIMESTAMP DEFAULT NOW()
);
-- Questões (options em JSONB suporta 2 a N alternativas)
CREATE TABLE questions (
id SERIAL PRIMARY KEY,
quiz_id INTEGER NOT NULL REFERENCES quizzes(id) ON DELETE CASCADE,
question_number INTEGER NOT NULL,
section VARCHAR(255) DEFAULT 'Geral',
context TEXT DEFAULT '',
question TEXT NOT NULL,
options JSONB NOT NULL, -- ["Opção A", "Opção B", ...]
answer INTEGER, -- índice base-0 (0=A, 1=B, ...)
explanation TEXT DEFAULT '',
UNIQUE (quiz_id, question_number)
);
CREATE INDEX idx_questions_quiz_id ON questions(quiz_id);
-- Usuários e Autenticação
CREATE TABLE users (
id SERIAL PRIMARY KEY,
username VARCHAR(50) UNIQUE NOT NULL,
email VARCHAR(255) UNIQUE NOT NULL,
password_hash VARCHAR(255) NOT NULL,
salt VARCHAR(64) NOT NULL,
role VARCHAR(20) DEFAULT 'student',
created_at TIMESTAMP DEFAULT NOW()
);
-- Sessões (token armazenado como hash SHA-256)
CREATE TABLE sessions (
token VARCHAR(128) PRIMARY KEY,
user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
expires_at TIMESTAMP NOT NULL,
created_at TIMESTAMP DEFAULT NOW()
);
CREATE INDEX idx_sessions_token ON sessions(token);
CREATE INDEX idx_sessions_user_id ON sessions(user_id);
-- Tentativas e Histórico de Desempenho (Caderno de Erros)
CREATE TABLE quiz_attempts (
id SERIAL PRIMARY KEY,
user_id INTEGER REFERENCES users(id) ON DELETE CASCADE,
quiz_id INTEGER REFERENCES quizzes(id) ON DELETE SET NULL,
quiz_name VARCHAR(255) NOT NULL,
score INTEGER NOT NULL,
total INTEGER NOT NULL,
percentage INTEGER NOT NULL,
wrong_question_ids JSONB DEFAULT '[]'::jsonb,
created_at TIMESTAMP DEFAULT NOW()
);
CREATE INDEX idx_quiz_attempts_user_id ON quiz_attempts(user_id);
CREATE INDEX idx_quiz_attempts_quiz_id ON quiz_attempts(quiz_id);
GOOGLE_CLIENT_ID / GOOGLE_CLIENT_SECRET | Não | Liga o botão "Entrar com Google". Redirect URI: <APP_URL>/api/auth/google/callback (defina APP_URL em produção) |
GUEST_AI_LIMIT | Não | Usos de IA do convidado por janela (padrão: 3; 0 desliga a IA para convidados) |
GUEST_AI_WINDOW_HOURS | Não | Janela da cota do convidado em horas (padrão e máximo: 24) |
GUEST_AI_IP_LIMIT | Não | Teto de usos de IA de convidados por IP na janela (padrão: 10), contra quem apaga cookies para renovar a cota |
TRUST_PROXY | Não | Confiar em headers de proxy (padrão: false, auto true na Vercel) |
PORT | Não | Porta do servidor (padrão: 8000) |
DEBUG | Não | Logs detalhados (padrão: false) |
semgrep scan --config auto . para verificar o status atual.POST | /api/auth/logout | Cookie / Bearer Token | Encerramento de sessão |
POST | /api/auth/forgot-password e /api/auth/reset-password | Pública | Pedido e troca de senha por e-mail |
GET | /api/auth/providers | Pública | Informa se o login com Google está ligado |
GET | /api/auth/google/start e /api/auth/google/callback | Pública | Login com Google (OAuth, state em cookie) |
POST | /api/guest/start, /api/guest/end · GET /api/guest/status | Pública | Sessão de convidado e cota gratuita de IA |
POST | /api/quizzes/import | Autenticado | Salva na conta os simulados criados como convidado |
GET | /api/account/export | Autenticado | Cópia dos dados da conta em JSON (LGPD) |
POST | /api/account/delete | Autenticado (com senha) | Exclui a conta e os dados |
POST | /api/upload | Autenticado (20 MB) / Convidado (?guest=1, 5 MB) | Upload multipart/form-data (TXT, PDF, DOCX); aceita language |