#include <WiFi.h>
#include <PubSubClient.h>
#include <LiquidCrystal_I2C.h>
// -------------- WiFi + MQTT --------------
const char* ssid = "Wokwi-GUEST";
const char* password = "";
const char* mqtt_server = "broker.hivemq.com";
const int mqtt_port = 1883;
WiFiClient espClient;
PubSubClient client(espClient);
// ----------- LCD ---------------
LiquidCrystal_I2C lcd(0x27, 16, 2);
// -------- Botões e LEDs ---------
#define BTN_TRUE 25
#define BTN_FALSE 26
#define LED_GREEN 32
#define LED_RED 33
// -------- Estrutura Perguntas ------------
struct Pergunta {
const char* texto;
bool resposta;
};
Pergunta perguntas[30] = {
{"Treinar musculação ajuda a ganhar massa muscular?", true},
{"Aeróbico em jejum queima mais gordura do que em qualquer outro horário?", false},
{"A hipertrofia acontece quando o músculo é estimulado e depois se recupera?", true},
{"Beber água durante o treino atrapalha os resultados?", false},
{"A creatina é um dos suplementos mais estudados e seguros?", true},
{"Fazer 100 abdominais por dia é suficiente para perder barriga?", false},
{"Descanso é essencial para o crescimento muscular?", true},
{"O alongamento antes do treino sempre previne lesões?", false},
{"O consumo de proteína é importante para recuperação muscular?", true},
{"Levantar mais peso sempre significa mais hipertrofia?", false},
{"Treinar pernas aumenta a liberação de hormônios anabólicos?", true},
{"Apenas suplementos são responsáveis pelo ganho de massa?", false},
{"Dormir bem ajuda no crescimento muscular?", true},
{"Fazer apenas exercícios de braço dá resultado equilibrado no corpo?", false},
{"O agachamento é considerado um exercício completo?", true},
{"Treinar todos os dias sem descanso é a melhor estratégia?", false},
{"A técnica é mais importante do que a carga levantada?", true},
{"Pular o aquecimento não traz risco algum?", false},
{"O treino de força também pode melhorar a saúde do coração?", true},
{"Musculação faz mal para adolescentes?", false},
{"Treinar em alta intensidade ajuda a melhorar o condicionamento?", true},
{"A perda de peso depende apenas do exercício?", false},
{"O tríceps é trabalhado em exercícios de supino?", true},
{"Treino de abdômen sozinho não elimina gordura localizada?", true},
{"Tomar anabolizante é a única forma de ter resultados rápidos?", false},
{"A progressão de carga é importante para evolução?", true},
{"Cardio pode ajudar na definição muscular?", true},
{"Excesso de treino pode causar overtraining?", true},
{"Suplemento substitui alimentação?", false},
{"A constância é mais importante que a intensidade isolada?", true}
};
// -------- Controle do Quiz ------------
int perguntasRespondidas = 0;
int acertos = 0;
int erros = 0;
int indiceAtual = 0;
bool jogoAtivo = false;
int perguntasSorteadas[5];
// -------- Funções ------------
void sorteiaPerguntas() {
for (int i = 0; i < 5; i++) {
int sorteada;
bool repetida;
do {
sorteada = random(0, 30);
repetida = false;
for (int j = 0; j < i; j++) {
if (perguntasSorteadas[j] == sorteada) {
repetida = true;
break;
}
}
} while (repetida);
perguntasSorteadas[i] = sorteada;
}
}
void mostrarPergunta() {
indiceAtual = perguntasSorteadas[perguntasRespondidas];
String texto = String(perguntas[indiceAtual].texto);
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Pergunta ");
lcd.print(perguntasRespondidas + 1);
lcd.print(":");
// Scroll horizontal do texto
int len = texto.length();
if (len <= 16) {
lcd.setCursor(0, 1);
lcd.print(texto);
} else {
for (int pos = 0; pos <= len - 16; pos++) {
lcd.setCursor(0, 1);
lcd.print(texto.substring(pos, pos + 16));
delay(400); // velocidade do scroll
}
}
}
void verificarResposta(bool respostaUsuario){
bool correta = (respostaUsuario == perguntas[indiceAtual].resposta);
if(correta){
digitalWrite(LED_GREEN, HIGH);
digitalWrite(LED_RED, LOW);
acertos++;
client.publish("gymQuiz/resp_enviada","Correta");
}else{
digitalWrite(LED_RED, HIGH);
digitalWrite(LED_GREEN, LOW);
erros++;
client.publish("gymQuiz/resp_enviada","Errada");
}
delay(1500);
digitalWrite(LED_RED, LOW);
digitalWrite(LED_GREEN, LOW);
perguntasRespondidas++;
if(perguntasRespondidas >= 5){
float media = ((float)acertos / 5) * 100;
char resultado[80];
sprintf(resultado, "Acertos:%d Erros:%d Media:%.1f%%", acertos, erros, media);
client.publish("gymQuiz/resultado", resultado);
String status = (media >= 60) ? "Aprovado" : "Reprovado" ;
// --- MOSTRAR RESULTADOS NA TELA POR 5s ---
lcd.clear();
lcd.setCursor(0,0);
lcd.print("Acertos:");
lcd.print(acertos);
lcd.print(" Erros:");
lcd.print(erros);
lcd.setCursor(0,1);
lcd.print("Media: ");
lcd.print(media,1);
lcd.print("%");
delay(5000);
// Reiniciar o Jogo
jogoAtivo = false;
lcd.clear();
lcd.setCursor(0,0);
lcd.print("Quiz IoT");
lcd.setCursor(0,1);
lcd.print("Iniciar?");
return;
}
mostrarPergunta();
}
// -------- Setup ------------
void setup(){
Serial.begin(115200);
pinMode(BTN_TRUE, INPUT_PULLUP);
pinMode(BTN_FALSE, INPUT_PULLUP);
pinMode(LED_GREEN, OUTPUT);
pinMode(LED_RED, OUTPUT);
lcd.init();
lcd.backlight();
lcd.setCursor(0, 0);
lcd.print("Conectando...");
WiFi.begin(ssid, password);
while(WiFi.status() != WL_CONNECTED) {
delay(500);
}
Serial.println("WiFi Conectado!");
client.setServer(mqtt_server, mqtt_port);
// Callback para receber mensagens MQTT
client.setCallback([](char* topic, byte* payload, unsigned int length){
String message = "";
for(int i = 0; i < length; i++){
message += (char)payload[i];
}
if(String(topic) == "gymQuiz/iniciarJogo" && message == "start"){
jogoAtivo = true;
perguntasRespondidas = 0;
acertos = 0;
erros = 0;
sorteiaPerguntas();
mostrarPergunta();
}
});
// Subscrição MQTT
client.subscribe("gymQuiz/iniciarJogo");
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Quiz GYM");
lcd.setCursor(0,1);
lcd.print("Iniciar?");
}
// ------------- Loop -------------
void loop () {
if(!client.connected()){
while(!client.connected()){
if(client.connect("ESP32-Brunex")){
Serial.println("MQTT Conectado!");
} else {
delay(1000);
}
}
}
client.loop();
if(!jogoAtivo){
if(digitalRead(BTN_TRUE) == LOW || digitalRead(BTN_FALSE) == LOW ){
jogoAtivo = true;
perguntasRespondidas = 0;
acertos = 0;
erros = 0;
sorteiaPerguntas();
mostrarPergunta();
delay(500);
}
} else {
if(digitalRead(BTN_TRUE) == LOW){
verificarResposta(true);
delay(500);
}
else if(digitalRead(BTN_FALSE) == LOW){
verificarResposta(false);
delay(500);
}
}
}