Repository navigation
Expand file tree
/
Copy pathscript.js
More file actions
670 lines (621 loc) · 21.3 KB
/
Copy pathscript.js
File metadata and controls
670 lines (621 loc) · 21.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
// Perguntas do quiz
const perguntasOriginais = [
// --- PERGUNTAS NÍVEL INICIANTE (4) ---
{
categoria: "Lógica de Programação",
nivel: "Iniciante",
pergunta: "O que é uma 'variável' em programação?",
opcoes: [
{
texto: "Um tipo de erro de programação.",
correta: false,
explicacao:
"Incorreto. Erros de programação são problemas que impedem o código de funcionar.",
},
{
texto:
"Um espaço nomeado na memória do computador para armazenar dados.",
correta: true,
explicacao:
"Correto. Variáveis guardam valores que podem ser modificados durante o programa.",
},
{
texto: "Um comando para dividir o código em várias funções.",
correta: false,
explicacao: "Incorreto. Funções são blocos de código reutilizáveis.",
},
],
},
{
categoria: "Lógica de Programação",
nivel: "Iniciante",
pergunta:
"Qual é o objetivo de uma estrutura de repetição (laço `for` ou `while`)?",
opcoes: [
{
texto: "Armazenar dados permanentemente.",
correta: false,
explicacao:
"Incorreto. O armazenamento permanente de dados é feito com bancos de dados ou arquivos.",
},
{
texto:
"Executar um bloco de código repetidamente até que uma condição seja satisfeita.",
correta: true,
explicacao:
"Correto. Laços de repetição executam um bloco de código múltiplas vezes.",
},
{
texto:
"Dividir o código em várias partes, para que a função possa entrar nas variáveis.",
correta: false,
explicacao: "Incorreto. Para dividir o código, usamos funções.",
},
],
},
{
categoria: "Fundamentos da Computação",
nivel: "Iniciante",
pergunta: "O que é 'hardware'?",
opcoes: [
{
texto: "O conjunto de programas e dados que o computador usa.",
correta: false,
explicacao: "Incorreto. Os programas e dados são o 'software'.",
},
{
texto:
"A parte lógica e intangível de um computador. Funciona de maneira semelhante ao cérebro humano.",
correta: false,
explicacao: "Incorreto. A parte lógica é o 'software'.",
},
{
texto:
"A parte física e tangível de um computador, como teclado, mouse e processador.",
correta: true,
explicacao:
"Correto. Hardware se refere a todos os componentes físicos de um computador.",
},
],
},
{
categoria: "JavaScript",
nivel: "Iniciante",
pergunta: "Qual a principal função do JavaScript em um site?",
opcoes: [
{
texto: "Dar estilo e aparência aos elementos da página e somente isso.",
correta: false,
explicacao: "Incorreto. Estilos são aplicados com CSS.",
},
{
texto:
"Adicionar interatividade, como animações, validações de formulário, etc.",
correta: true,
explicacao:
"Correto. JavaScript torna as páginas web dinâmicas e interativas.",
},
{
texto: "Criar a estrutura básica e o conteúdo da página.",
correta: false,
explicacao:
"Incorreto. A estrutura e o conteúdo são definidos com HTML.",
},
],
},
// --- PERGUNTAS NÍVEL INTERMEDIÁRIO (3) ---
{
categoria: "Lógica de Programação",
nivel: "Intermediário",
pergunta: "O que é 'recursão' em programação?",
opcoes: [
{
texto:
"Um método para quebrar um loop infinito. Exige uma função específica para funcionar.",
correta: false,
explicacao:
"Incorreto. Para quebrar um loop, usamos `break` ou ajustamos a condição.",
},
{
texto: "Uma função que chama a si mesma para resolver um problema.",
correta: true,
explicacao:
"Correto. Recursão é quando uma função chama a si mesma até atingir uma condição de parada.",
},
{
texto: "A repetição de um bloco de código com diferentes variáveis.",
correta: false,
explicacao: "Incorreto. A repetição é feita com estruturas de laço.",
},
],
},
{
categoria: "Fundamentos da Computação",
nivel: "Intermediário",
pergunta: "O que é 'algoritmo de ordenação'?",
opcoes: [
{
texto:
"Um algoritmo que organiza dados em uma sequência específica, como ordem alfabética ou numérica.",
correta: true,
explicacao:
"Correto. Algoritmos de ordenação (como Bubble Sort) são fundamentais para organizar dados de forma eficiente.",
},
{
texto:
"Um conjunto de regras para somar números. Não se aplica a ordenação.",
correta: false,
explicacao:
"Incorreto. Um algoritmo de ordenação não é específico para somas, mas para a organização de dados.",
},
{
texto: "Um tipo de erro que impede o código de compilar.",
correta: false,
explicacao:
"Incorreto. Erros de compilação estão relacionados à sintaxe do código.",
},
],
},
{
categoria: "JavaScript",
nivel: "Intermediário",
pergunta: "Em JavaScript, o que são 'Promises'?",
opcoes: [
{
texto: "Um tipo de variável para armazenar texto.",
correta: false,
explicacao: "Incorreto. Variáveis de texto são `Strings`.",
},
{
texto:
"Um erro que acontece quando a função não encontra um elemento no DOM.",
correta: false,
explicacao:
"Incorreto. O erro de não encontrar um elemento no DOM geralmente é um `TypeError`.",
},
{
texto:
"Objetos que representam a conclusão (sucesso ou falha) de uma operação assíncrona.",
correta: true,
explicacao:
"Correto. Promises são essenciais para lidar com operações assíncronas de forma mais limpa.",
},
],
},
// --- PERGUNTAS NÍVEL EXPERT (3) ---
{
categoria: "Lógica de Programação",
nivel: "Expert",
pergunta:
"O que é 'complexidade de tempo' em um algoritmo e por que ela é importante?",
opcoes: [
{
texto: "É o tempo exato que um algoritmo leva para ser executado.",
correta: false,
explicacao:
"Incorreto. A complexidade de tempo não mede o tempo exato, mas a taxa de crescimento dele.",
},
{
texto:
"Mede o quanto de memória um algoritmo consome durante a execução.",
correta: false,
explicacao:
"Incorreto. O consumo de memória é a 'complexidade de espaço'.",
},
{
texto:
"Mede a taxa de crescimento do tempo de execução em função do tamanho da entrada, essencial para prever seu desempenho.",
correta: true,
explicacao:
"Correto. A complexidade de tempo, expressa em notação Big O, é um conceito fundamental para otimizar a eficiência de um algoritmo.",
},
],
},
{
categoria: "Fundamentos da Computação",
nivel: "Expert",
pergunta:
"Em redes de computadores, o que é o modelo 'OSI' e qual sua finalidade?",
opcoes: [
{
texto: "Um tipo de linguagem de programação.",
correta: false,
explicacao:
"Incorreto. Linguagens de programação são usadas para criar software.",
},
{
texto: "É um modelo de banco de dados para sistemas distribuídos.",
correta: false,
explicacao:
"Incorreto. O modelo OSI não se refere a bancos de dados, mas a como os sistemas de comunicação interagem.",
},
{
texto:
"Um modelo de referência para o funcionamento de redes, dividido em sete camadas para padronizar a comunicação entre diferentes sistemas.",
correta: true,
explicacao:
"Correto. O modelo OSI ajuda a entender como os dados se movem em uma rede.",
},
],
},
{
categoria: "JavaScript",
nivel: "Expert",
pergunta: "O que é 'closure' em JavaScript?",
opcoes: [
{
texto:
"Um erro que acontece quando você tenta acessar uma variável que não existe.",
correta: false,
explicacao:
"Incorreto. Acessar uma variável não existente geralmente resulta em um `ReferenceError`.",
},
{
texto: "Um tipo de objeto que armazena pares de chave-valor.",
correta: false,
explicacao:
"Incorreto. Objetos que armazenam pares de chave-valor são `Objects` ou `Maps`.",
},
{
texto:
"A capacidade de uma função interna de 'lembrar' e acessar variáveis de seu escopo externo (léxico).",
correta: true,
explicacao:
"Correto. Closures permitem a criação de funções com estado e dados privados, um conceito avançado e poderoso.",
},
],
},
];
const homepageSection = document.getElementById("homepage");
const iniciarQuizBtn = document.getElementById("iniciar-quiz");
const cadastroSection = document.getElementById("cadastro");
const cadastroForm = document.getElementById("cadastro-form");
const quizSection = document.getElementById("quiz");
const questoesContainer = document.getElementById("questoes-container");
const proximaQuestaoBtn = document.createElement("button");
proximaQuestaoBtn.id = "proxima-questao";
proximaQuestaoBtn.textContent = "Próxima";
proximaQuestaoBtn.style.display = "none";
quizSection.appendChild(proximaQuestaoBtn);
const resultadoSection = document.getElementById("resultado");
const nivelResultadoFinal = document.getElementById("nivel-resultado-final");
const analiseFinal = document.getElementById("analise-final");
// Variáveis para os botões da tela de resultado
let voltarHomepageBtn;
let enviarResultadoBtn;
let refazerTesteBtn;
let perguntas = [];
let pontuacao = 0;
let indiceQuestaoAtual = 0;
let nomeUsuario = "";
let emailUsuario = "";
let respostasUsuario = [];
let quizConcluido = sessionStorage.getItem("quizConcluido") === "true";
let resultadoQuiz = JSON.parse(sessionStorage.getItem("resultadoQuiz")) || null;
// Função para embaralhar as perguntas
function embaralharArray(array) {
for (let i = array.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[array[i], array[j]] = [array[j], array[i]];
}
return array;
}
// Função para preparar as perguntas
function prepararPerguntas() {
const perguntasIniciante = perguntasOriginais.filter(
(q) => q.nivel === "Iniciante"
);
const perguntasIntermediario = perguntasOriginais.filter(
(q) => q.nivel === "Intermediário"
);
const perguntasExpert = perguntasOriginais.filter(
(q) => q.nivel === "Expert"
);
embaralharArray(perguntasIniciante);
embaralharArray(perguntasIntermediario);
embaralharArray(perguntasExpert);
perguntas = [
...perguntasIniciante,
...perguntasIntermediario,
...perguntasExpert,
];
}
function mostrarSeccao(seccao) {
document
.querySelectorAll(".quiz-section")
.forEach((sec) => sec.classList.remove("active"));
document.getElementById(seccao).classList.add("active");
}
if (quizConcluido && resultadoQuiz) {
const totalPerguntas =
(resultadoQuiz.respostas && resultadoQuiz.respostas.length) ||
perguntasOriginais.length;
homepageSection.innerHTML = `
<img src="logo2.png" alt="House JS Logo" class="house-js-logo">
<h1>DevCheck - Nível Dev</h1>
<p>Você já completou o quiz!</p>
<div id="nivel-resultado-homepage"><strong>Seu Nível:</strong> ${resultadoQuiz.nivel}</div>
<p id="pontuacao-final-homepage">Você acertou ${resultadoQuiz.pontuacao} de ${totalPerguntas} perguntas.</p>
<button id="ver-feedback-btn">Ver seu Desempenho</button>
`;
const verFeedbackBtn = document.getElementById("ver-feedback-btn");
verFeedbackBtn.addEventListener("click", () => {
exibirResultado(resultadoQuiz);
});
mostrarSeccao("homepage");
} else {
prepararPerguntas();
mostrarSeccao("homepage");
}
iniciarQuizBtn.addEventListener("click", () => {
mostrarSeccao("cadastro");
});
// Envio do cadastro pelo usuário
cadastroForm.addEventListener("submit", (e) => {
e.preventDefault();
nomeUsuario = document.getElementById("nome").value;
emailUsuario = document.getElementById("email").value;
mostrarSeccao("quiz");
exibirQuestao();
});
function exibirQuestao() {
const questao = perguntas[indiceQuestaoAtual];
const opcoesEmbaralhadas = embaralharArray([...questao.opcoes]);
questoesContainer.innerHTML = `
<div class="questao">
<div class="pergunta-header">
<span class="questao-nivel">Nível: ${questao.nivel}</span>
<span class="questao-categoria">Tema: ${questao.categoria}</span>
</div>
<h3>${indiceQuestaoAtual + 1}. ${questao.pergunta}</h3>
<div class="opcoes">
${opcoesEmbaralhadas
.map(
(opcao) => `
<label>
<input type="radio" name="opcao" value="${opcao.texto}" data-correta="${opcao.correta}">
<span>${opcao.texto}</span>
</label>
`
)
.join("")}
</div>
</div>
<div id="feedback-questao"></div>
`;
document.querySelectorAll('input[name="opcao"]').forEach((input) => {
input.addEventListener(
"click",
() => {
handleResposta(input);
},
{ once: true }
);
});
}
// Função que trata a resposta
function handleResposta(inputSelecionado) {
const opcaoSelecionada = inputSelecionado.value;
const questao = perguntas[indiceQuestaoAtual];
const opcao = questao.opcoes.find((o) => o.texto === opcaoSelecionada);
const feedbackQuestaoDiv = document.getElementById("feedback-questao");
const respostaCorreta = opcao.correta;
if (respostaCorreta) pontuacao++;
respostasUsuario.push({
pergunta: questao.pergunta,
categoria: questao.categoria,
nivel: questao.nivel,
correta: respostaCorreta,
explicacao: opcao.explicacao,
});
feedbackQuestaoDiv.className = `feedback-questao ${
respostaCorreta ? "correta" : "incorreta"
}`;
feedbackQuestaoDiv.innerHTML = `
<p><strong>Resposta ${
respostaCorreta ? "Correta!" : "Incorreta."
}</strong></p>
<p>${opcao.explicacao}</p>
`;
const labelSelecionada = inputSelecionado.parentElement;
labelSelecionada.classList.add(respostaCorreta ? "correta" : "incorreta");
if (!respostaCorreta) {
const opcaoCorretaLabel = document.querySelector(
`input[data-correta="true"]`
).parentElement;
opcaoCorretaLabel.classList.add("correta");
}
document.querySelectorAll('input[name="opcao"]').forEach((input) => {
input.disabled = true;
});
proximaQuestaoBtn.style.display = "block";
}
proximaQuestaoBtn.addEventListener("click", () => {
indiceQuestaoAtual++;
proximaQuestaoBtn.style.display = "none";
if (indiceQuestaoAtual < perguntas.length) {
exibirQuestao();
} else {
const resultadoFinal = {
pontuacao,
nivel: "",
respostas: respostasUsuario,
};
exibirResultado(resultadoFinal);
}
});
// Resultado do quiz
function exibirResultado(resultadoData) {
mostrarSeccao("resultado");
let nivel = "";
let feedbackNivel = "";
const acertosPorNivel = { Iniciante: 0, Intermediário: 0, Expert: 0 };
const totalPorNivel = {
Iniciante: perguntas.filter((q) => q.nivel === "Iniciante").length,
Intermediário: perguntas.filter((q) => q.nivel === "Intermediário").length,
Expert: perguntas.filter((q) => q.nivel === "Expert").length,
};
const acertosPorCategoria = {};
const totalPorCategoria = {};
perguntas.forEach((p) => {
if (!totalPorCategoria[p.categoria]) {
totalPorCategoria[p.categoria] = 0;
acertosPorCategoria[p.categoria] = 0;
}
totalPorCategoria[p.categoria]++;
});
resultadoData.respostas.forEach((res) => {
if (res.correta) {
acertosPorNivel[res.nivel]++;
acertosPorCategoria[res.categoria]++;
}
});
const totalAcertos = resultadoData.pontuacao;
if (totalAcertos <= 4) {
nivel = "Iniciante";
feedbackNivel =
"Você está no início da sua jornada. Foque em construir uma base sólida em lógica e fundamentos da computação. Continue praticando, pois isso é crucial para qualquer caminho na programação.";
} else if (totalAcertos <= 7) {
nivel = "Intermediário";
feedbackNivel =
"Você pode se considerar intermediário. Demonstrou familiaridade com conceitos-chave. O próximo passo é se aprofundar em temas mais complexos para chegar ao nível Expert.";
} else {
nivel = "Expert";
feedbackNivel =
"Excelente! Você demonstrou um conhecimento sólido e abrangente, especialmente em temas avançados. Está pronto para enfrentar desafios de alto nível e se destacar no mercado.";
}
let pontosFortes = [];
let pontosMelhorar = [];
for (const categoria in acertosPorCategoria) {
const percentual =
(acertosPorCategoria[categoria] / totalPorCategoria[categoria]) * 100;
if (percentual > 60) {
pontosFortes.push(categoria);
} else {
pontosMelhorar.push(categoria);
}
}
nivelResultadoFinal.innerHTML = `<h3>Seu Nível: ${nivel}</h3>`;
analiseFinal.innerHTML = `
<div class="feedback-final-card">
<p><strong>Pontuação:</strong> Você acertou ${
resultadoData.pontuacao
} de ${perguntas.length} perguntas.</p>
<p>${feedbackNivel}</p>
<p><strong>Seus pontos fortes:</strong> ${
pontosFortes.length > 0
? pontosFortes.join(", ")
: "Você sabe um pouco de tudo, então, não tem ainda um ponto forte."
}</p>
<p><strong>O que você pode fazer:</strong> ${
pontosMelhorar.length > 0
? `Reforce seus estudos em: <strong>${pontosMelhorar.join(
", "
)}</strong>.`
: "Continue praticando e explorando novos conceitos para manter seu conhecimento atualizado."
}</p>
</div>
<div class="botoes-resultado">
<button id="enviar-resultado-btn">Enviar Resultado Para o Seu Email</button>
<button id="refazer-teste-btn">Refazer Teste</button>
</div>
`;
// Define os dados a serem enviados
const resultadoParaEnviar = {
pontuacao: resultadoData.pontuacao,
nivel,
pontosFortes,
pontosMelhorar: pontosMelhorar,
};
// A chamada para a planilha deve vir aqui, DEPOIS que o HTML foi renderizado
enviarResultadoParaPlanilha(resultadoParaEnviar);
enviarResultadoBtn = document.getElementById("enviar-resultado-btn");
enviarResultadoBtn.addEventListener("click", () => {
// envia e-mail
enviarResultadoPorEmail(resultadoParaEnviar);
enviarResultadoBtn.disabled = true;
enviarResultadoBtn.textContent = "Enviado!";
});
refazerTesteBtn = document.getElementById("refazer-teste-btn");
refazerTesteBtn.addEventListener("click", () => {
pontuacao = 0;
indiceQuestaoAtual = 0;
respostasUsuario = [];
sessionStorage.clear();
window.location.reload();
});
sessionStorage.setItem("quizConcluido", "true");
sessionStorage.setItem(
"resultadoQuiz",
JSON.stringify({
pontuacao: resultadoData.pontuacao,
nivel,
respostas: resultadoData.respostas,
})
);
}
// Função que envia o resultado pro Google Forms
function enviarResultadoParaPlanilha(resultadoData) {
const FORM_URL =
"https://docs.google.com/forms/d/e/1FAIpQLSdlahHWiLMMTDBC5PP0mUwU3RTzcUHarPfbeR5AVdGrahcIig/formResponse";
const params = new URLSearchParams();
params.append("entry.697814456", nomeUsuario);
params.append("entry.1742734606", emailUsuario);
params.append("entry.82915780", resultadoData.pontuacao);
params.append("entry.302556256", resultadoData.nivel);
params.append("entry.988138350", resultadoData.pontosFortes);
params.append("entry.648974086", resultadoData.pontosMelhorar);
fetch(FORM_URL, {
method: "POST",
body: params,
mode: "no-cors",
})
.then(() => console.log("Dados enviados com sucesso para a planilha!"))
.catch((error) =>
console.error("Erro ao enviar dados para a planilha:", error)
);
}
// Função que envia os dados para o servidor.
async function enviarResultadoPorEmail(dados) {
await fetch("https://devcheck-housejs.vercel.app/api/send-email", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
nome: nomeUsuario,
email: emailUsuario,
pontuacao: dados.pontuacao,
nivel: dados.nivel,
pontosFortes: dados.pontosFortes,
pontosMelhorar: dados.pontosMelhorar,
}),
})
.then((res) => res.json())
.then((data) => {
if (data.ok) {
Swal.fire({
icon: "success",
title: "Sucesso!",
text: "Resultado enviado com sucesso para seu e-mail!",
confirmButtonText: "OK",
confirmButtonColor: "#1c5c1eef",
});
} else {
Swal.fire({
icon: "error",
title: "Erro!",
text: "Erro ao enviar resultado por e-mail. Tente novamente mais tarde.",
confirmButtonText: "Fechar",
confirmButtonColor: "rgba(122, 35, 35, 0.94)",
});
}
})
.catch((err) => {
console.error("Erro de rede:", err);
Swal.fire({
icon: "warning",
title: "Falha de conexão",
text: "Não foi possível conectar ao servidor de e-mail. Verifique sua conexão.",
confirmButtonText: "OK",
});
});
}