import math import os import random import string import sys import time ALFABETO = list(string.ascii_uppercase) # ============================================================================== # 1. EXCEÇÕES E GERENCIAMENTO DE NAVEGAÇÃO GLOBAL # ============================================================================== class VoltarException(Exception): """Sinaliza o comando 'voltar' para retornar à tela/etapa anterior.""" pass class ReiniciarException(Exception): """Sinaliza o comando 'reiniciar' para voltar ao menu principal.""" pass def checar_comando_global(entrada): """Verifica se o usuário digitou 'sair', 'reiniciar' ou 'voltar'.""" texto = str(entrada).lower().strip() if texto == "sair": print("\nDesligando o programa...") time.sleep(1) sys.exit() elif texto == "reiniciar": print("\nReiniciando a calculadora...") time.sleep(1) os.system("cls" if os.name == "nt" else "clear") raise ReiniciarException() elif texto == "voltar": raise VoltarException() # ============================================================================== # 2. FUNÇÕES DE ENTRADA, VALIDAÇÃO E FILTROS DE DADOS # ============================================================================== def pedir_inteiro(mensagem, min_val=None, max_val=None): """Valida entradas inteiras, limpa a tela e suporta comandos globais.""" while True: entrada = input(mensagem).strip() checar_comando_global(entrada) if not entrada.lstrip("-").isdigit(): print( f"\nA entrada '{entrada}' invalida! Digite um numero inteiro.\n" ) time.sleep(1.5) os.system("cls" if os.name == "nt" else "clear") continue valor = int(entrada) if min_val is not None and max_val is not None: if valor < min_val or valor > max_val: print( f"\nO numero {valor} e invalido! Escolha uma opcao entre {min_val} e {max_val}.\n" ) time.sleep(1.5) os.system("cls" if os.name == "nt" else "clear") continue os.system("cls" if os.name == "nt" else "clear") return valor def pedir_float(mensagem): """Valida números decimais, limpa a tela e suporta comandos globais.""" while True: entrada = input(mensagem).replace(",", ".").strip() checar_comando_global(entrada) try: valor = float(entrada) os.system("cls" if os.name == "nt" else "clear") return valor except ValueError: print( f"\nA entrada '{entrada}' e invalida! Digite um numero valido.\n" ) time.sleep(1.5) os.system("cls" if os.name == "nt" else "clear") def pedir_texto(mensagem): """Lê uma string, limpa a tela e suporta comandos globais.""" texto = input(mensagem) checar_comando_global(texto) os.system("cls" if os.name == "nt" else "clear") return texto def pedir_sim_nao(mensagem): """Filtra respostas Sim/Não.""" while True: resposta = input(mensagem).lower().strip() checar_comando_global(resposta) os.system("cls" if os.name == "nt" else "clear") if resposta in ["s", "sim"]: return True elif resposta in ["n", "nao", "não"]: return False else: print("Resposta invalida! Digite 's' ou 'n'.\n") time.sleep(1) os.system("cls" if os.name == "nt" else "clear") def pedir_correcao(item_nome, valor_item): """Avaliação de critérios de correção: Certo, Meio Certo ou Errado.""" valor_meio_certo = valor_item / 2.0 while True: print("---------------------------------------------------") print(f" Corrigindo: {item_nome} (Valor: {valor_item:.2f} pts)") print( f" [c] Certo ({valor_item:.2f} pts) | [mc] Meio Certo ({valor_meio_certo:.2f} pts) | [e] Errado (0.00 pts)" ) print("---------------------------------------------------") resposta = input("Qual o resultado do aluno?: ").lower().strip() checar_comando_global(resposta) os.system("cls" if os.name == "nt" else "clear") if resposta in ["c", "certo", "s", "sim"]: return valor_item elif resposta in ["mc", "meio", "meio certo"]: return valor_meio_certo elif resposta in ["e", "errado", "n", "nao", "não"]: return 0.0 else: print( "Opcao invalida! Digite 'c' (certo), 'mc' (meio certo) ou 'e' (errado).\n" ) time.sleep(1.5) os.system("cls" if os.name == "nt" else "clear") def gerador_valores_aleatorios_prova(num_questoes, valor_total_simulado=10.0): """Sorteia valores para as questões garantindo que a soma feche no valor total estipulado.""" if num_questoes <= 0: return [] pesos = [random.uniform(1.0, 5.0) for _ in range(num_questoes)] soma_pesos = sum(pesos) valores = [ round((p / soma_pesos) * valor_total_simulado, 2) for p in pesos ] soma_atual = sum(valores) diferenca = round(valor_total_simulado - soma_atual, 2) if diferenca != 0: valores[-1] = round(valores[-1] + diferenca, 2) return valores def pedir_alternativa_valida(mensagem, opcoes_letras): """Valida a alternativa correta escolhida.""" while True: resp = input(mensagem).upper().strip() checar_comando_global(resp) if resp in opcoes_letras: os.system("cls" if os.name == "nt" else "clear") return resp else: print( f"Opcao invalida! Escolha entre: {', '.join(opcoes_letras)}\n" ) time.sleep(1.5) os.system("cls" if os.name == "nt" else "clear") def exibir_manual(): """Painel descritivo de comandos globais.""" print("===================================================") print(" MANUAL MAKER - GUIA DE ABREVIACOES ") print("===================================================") print(" Comandos Globais (Funcionam em qualquer tela):") print(" [sair] -> Fecha o programa imediatamente") print(" [reiniciar] -> Voltar ao Menu Principal") print(" [voltar] -> Volta para a tela/etapa anterior") print("===================================================\n") # ============================================================================== # 3. IMPLEMENTAÇÃO DAS 10 OPÇÕES DO MENU # ============================================================================== def opcao_1_calcular_nota_aluno(): print("=== 1. CALCULADOR DE NOTA INDIVIDUAL DE ALUNO ===") nome = pedir_texto("Nome do aluno: ") qtd_questoes = pedir_inteiro("Quantidade de questoes da prova: ") valor_prova = pedir_float("Valor total da prova: ") valor_por_questao = valor_prova / qtd_questoes nota_final = 0.0 for i in range(1, qtd_questoes + 1): pontos = pedir_correcao(f"Questao {i}", valor_por_questao) nota_final += pontos print("===================================================") print(f" Aluno: {nome}") print(f" Nota Final: {nota_final:.2f} / {valor_prova:.2f}") print("===================================================") input("\nPressione ENTER para voltar ao menu...") os.system("cls" if os.name == "nt" else "clear") def opcao_2_porcentagem_nota(): print("=== 2. CALCULADORA DE PORCENTAGEM DE NOTA ===") nota_obtida = pedir_float("Nota obtida pelo aluno: ") nota_maxima = pedir_float("Nota maxima da prova: ") if nota_maxima == 0: print("A nota maxima nao pode ser zero!") else: porcentagem = (nota_obtida / nota_maxima) * 100 print("===================================================") print(f" Rendimento do aluno: {porcentagem:.2f}%") print("===================================================") input("\nPressione ENTER para voltar ao menu...") os.system("cls" if os.name == "nt" else "clear") def opcao_3_boletim_aluno(): print("=== 3. GERADOR DE BOLETIM DE UM ALUNO ===") nome = pedir_texto("Nome do aluno: ") qtd_materias = pedir_inteiro("Quantidade de materias: ") boletim = [] soma_notas = 0.0 for i in range(1, qtd_materias + 1): materia = pedir_texto(f"Nome da materia {i}: ") nota = pedir_float(f"Nota em {materia}: ") boletim.append((materia, nota)) soma_notas += nota media = soma_notas / qtd_materias if qtd_materias > 0 else 0 print("===================================================") print(f" BOLETIM ESCOLAR - ALUNO: {nome}") print("---------------------------------------------------") for mat, n in boletim: status = "Aprovado" if n >= 6.0 else "Recuperacao/Reprovado" print(f" {mat:<20} | Nota: {n:>5.2f} | Status: {status}") print("---------------------------------------------------") print(f" MEDIA GERAL: {media:.2f}") print("===================================================") input("\nPressione ENTER para voltar ao menu...") os.system("cls" if os.name == "nt" else "clear") def opcao_4_sair(): print("Desligando o programa...") time.sleep(1) sys.exit() def opcao_5_reiniciar(): print("Reiniciando a calculadora...") time.sleep(1) os.system("cls" if os.name == "nt" else "clear") raise ReiniciarException() def opcao_6_calculadora_integradat(): print("=== 6. CALCULADORA MULTIFUNCAO ===") print("1. Soma (+)") print("2. Subtracao (-)") print("3. Multiplicacao (*)") print("4. Divisao (/)") print("5. Raiz Quadrada (v)") print("6. Potenciacao (^)") op = pedir_inteiro("Escolha a operacao (1-6): ", min_val=1, max_val=6) if op in [1, 2, 3, 4, 6]: num1 = pedir_float("Digite o primeiro numero: ") num2 = pedir_float("Digite o segundo numero: ") if op == 1: res = num1 + num2 elif op == 2: res = num1 - num2 elif op == 3: res = num1 * num2 elif op == 4: if num2 == 0: print("\nErro: Divisao por zero!") input("\nPressione ENTER para continuar...") os.system("cls" if os.name == "nt" else "clear") return res = num1 / num2 elif op == 6: res = num1**num2 print(f"\nResultado: {res:.4f}") elif op == 5: num = pedir_float("Digite o numero para extrair a raiz quadrada: ") if num < 0: print("\nErro: Nao existe raiz de numero negativo nos reais!") else: print(f"\nResultado: {math.sqrt(num):.4f}") input("\nPressione ENTER para voltar ao menu...") os.system("cls" if os.name == "nt" else "clear") def opcao_7_boletim_multialuno(): print("=== 7. BOLETIM DE MULTIPLOS ALUNOS ===") qtd_alunos = pedir_inteiro("Quantidade de alunos: ") qtd_materias = pedir_inteiro("Quantidade de materias por aluno: ") materias = [] for m in range(1, qtd_materias + 1): materias.append(pedir_texto(f"Nome da materia {m}: ")) turma = [] for a in range(1, qtd_alunos + 1): nome_aluno = pedir_texto(f"Nome do aluno {a}: ") notas_aluno = {} soma = 0.0 for mat in materias: n = pedir_float(f"Nota de {nome_aluno} em {mat}: ") notas_aluno[mat] = n soma += n media = soma / qtd_materias if qtd_materias > 0 else 0 turma.append( {"nome": nome_aluno, "notas": notas_aluno, "media": media} ) print("===================================================================") print(" RESUMO DA TURMA - BOLETIM ") print("===================================================================") cabecalho = f"{'ALUNO':<15} | " + " | ".join( [f"{m[:8]:<8}" for m in materias] ) + " | MEDIA" print(cabecalho) print("-" * len(cabecalho)) for al in turma: linha_notas = " | ".join( [f"{al['notas'][m]:>8.2f}" for m in materias] ) print(f"{al['nome']:<15} | {linha_notas} | {al['media']:>5.2f}") print("===================================================================") input("\nPressione ENTER para voltar ao menu...") os.system("cls" if os.name == "nt" else "clear") def opcao_8_provas_multimaterias(): print("=== 8. GERADOR DE PROVA MULTIMATERIAS (SOMA = 10.0) ===") qtd_questoes = pedir_inteiro("Quantidade de questoes da prova: ") valor_total = 10.0 valores_q = gerador_valores_aleatorios_prova(qtd_questoes, valor_total) questoes = [] for i in range(qtd_questoes): num_q = i + 1 mat = pedir_texto(f"Materia da questao {num_q}: ") perg = pedir_texto(f"Enunciado da questao {num_q}: ") questoes.append( {"num": num_q, "materia": mat, "perg": perg, "valor": valores_q[i]} ) print("=================================================================") print(" TABELA DA PROVA MULTIMATERIAS ") print("=================================================================") print(f"{'QUESTÃO':<10} | {'MATERIA':<15} | {'ENUNCIADO':<30} | VALOR") print("-----------------------------------------------------------------") for q in questoes: p_corta = q["perg"][:27] + "..." if len(q["perg"]) > 30 else q["perg"] print( f"{q['num']:<10} | {q['materia']:<15} | {p_corta:<30} | {q['valor']:.2f} pts" ) print("=================================================================") input("\nPressione ENTER para voltar ao menu...") os.system("cls" if os.name == "nt" else "clear") def opcao_9_prova_simples(): print("=== 9. GERADOR DE PROVA SIMPLES (SOMA = 10.0) ===") qtd_questoes = pedir_inteiro("Quantidade de questoes: ") valor_total = 10.0 valores_q = gerador_valores_aleatorios_prova(qtd_questoes, valor_total) questoes = [] for i in range(qtd_questoes): num_q = i + 1 perg = pedir_texto(f"Pergunta da questao {num_q}: ") questoes.append({"num": num_q, "perg": perg, "valor": valores_q[i]}) print("=========================================================") print(" TABELA DE PROVA SIMPLES ") print("=========================================================") print(f"{'QUESTÃO':<10} | {'PERGUNTA':<35} | VALOR") print("---------------------------------------------------------") for q in questoes: p_corta = q["perg"][:32] + "..." if len(q["perg"]) > 35 else q["perg"] print(f"{q['num']:<10} | {p_corta:<35} | {q['valor']:.2f} pts") print("=========================================================") input("\nPressione ENTER para voltar ao menu...") os.system("cls" if os.name == "nt" else "clear") def opcao_10_gerar_simulado_completo(): """Gera o simulado completo com valores sorteados por questão, prova pronta e gabarito.""" print("=== 10. GERADOR DE SIMULADO COMPLETO ===") time.sleep(1) os.system("cls" if os.name == "nt" else "clear") valor_total_simulado = pedir_float( "Quanto vale o simulado inteiro (valor total): " ) qtd_questoes = pedir_inteiro("Quantas questoes tem o simulado: ") qtd_alternativas = pedir_inteiro( "Quantas alternativas por questao (ex: 4 para A,B,C,D / 5 para A,B,C,D,E): ", min_val=2, max_val=10, ) opcoes_letras = ALFABETO[:qtd_alternativas] # Sorteia valores aleatórios por questão que fecham exatamente no valor total do simulado valores_questoes = gerador_valores_aleatorios_prova( qtd_questoes, valor_total_simulado ) dados_simulado = [] q = 0 while q < qtd_questoes: num_q = q + 1 try: item_atual = ( dados_simulado[q] if q < len(dados_simulado) else { "num_q": num_q, "materia": "", "pergunta": "", "alternativas": {}, "valor_q": valores_questoes[q], "valor_alt": round( valores_questoes[q] / qtd_alternativas, 2 ), "resposta": "", } ) if not item_atual["materia"]: item_atual["materia"] = pedir_texto( f"Qual a materia da questao {num_q}: " ) if not item_atual["pergunta"]: item_atual["pergunta"] = pedir_texto( f"Qual a pergunta da questao {num_q}: " ) # Preenchimento das Alternativas (com painel de estado no topo) idx_alt = len(item_atual["alternativas"]) while idx_alt < len(opcoes_letras): letra = opcoes_letras[idx_alt] os.system("cls" if os.name == "nt" else "clear") print("=========================================================") print( f" QUESTAO {num_q} [{item_atual['materia']}] - Valor Sorteado: {item_atual['valor_q']:.2f} pts" ) print(f" Pergunta: {item_atual['pergunta']}") print("---------------------------------------------------------") if item_atual["alternativas"]: print(" Alternativas ja cadastradas:") for l_cad, txt_cad in item_atual["alternativas"].items(): print(f" ({l_cad}) {txt_cad}") print( "---------------------------------------------------------" ) print( "=========================================================\n" ) try: texto_alt = pedir_texto( f"Digite a alternativa {letra} da questao {num_q}: " ) item_atual["alternativas"][letra] = texto_alt idx_alt += 1 except VoltarException: if idx_alt > 0: letra_anterior = opcoes_letras[idx_alt - 1] del item_atual["alternativas"][letra_anterior] idx_alt -= 1 else: item_atual["pergunta"] = "" raise VoltarException() # Escolha da resposta correta os.system("cls" if os.name == "nt" else "clear") print("=========================================================") print( f" QUESTAO {num_q} [{item_atual['materia']}] - Valor Sorteado: {item_atual['valor_q']:.2f} pts" ) print(f" Pergunta: {item_atual['pergunta']}") print("---------------------------------------------------------") print(" Alternativas cadastradas:") for l_cad, txt_cad in item_atual["alternativas"].items(): print(f" ({l_cad}) {txt_cad}") print("=========================================================\n") letras_str = ", ".join(opcoes_letras) try: item_atual["resposta"] = pedir_alternativa_valida( f"Qual a resposta CORRETA da questao {num_q}? ({letras_str}): ", opcoes_letras, ) except VoltarException: letra_ultima = opcoes_letras[-1] del item_atual["alternativas"][letra_ultima] continue if q < len(dados_simulado): dados_simulado[q] = item_atual else: dados_simulado.append(item_atual) q += 1 except VoltarException: if item_atual["pergunta"] == "": item_atual["materia"] = "" elif item_atual["materia"] == "": if q > 0: q -= 1 else: raise VoltarException() # --- 1. TABELA COMPLETA COM VALORES SORTEADOS --- print( "==========================================================================================" ) print( " TABELA COMPLETA DO SIMULADO " ) print( "==========================================================================================" ) print( f"{'Nº QUESTÃO':<12} | {'MATERIA':<18} | {'PERGUNTA':<35} | {'VALOR Q.':<10} | {'VALOR ALT.':<10}" ) print( "------------------------------------------------------------------------------------------" ) for item in dados_simulado: p_corta = ( item["pergunta"][:32] + "..." if len(item["pergunta"]) > 35 else item["pergunta"] ) print( f"{item['num_q']:<12} | {item['materia']:<18} | {p_corta:<35} | {item['valor_q']:<10.2f} | {item['valor_alt']:<10.2f}" ) print( "------------------------------------------------------------------------------------------" ) print( f" VALOR TOTAL DO SIMULADO: {sum(item['valor_q'] for item in dados_simulado):.2f} pts" ) print( "==========================================================================================" ) print("\n") # --- 2. EXIBIÇÃO DA PROVA PRONTA --- print( "==========================================================================================" ) print( " PROVA DO SIMULADO " ) print( "==========================================================================================" ) for item in dados_simulado: print( f"Questao {item['num_q']} [{item['materia']}] - ({item['valor_q']:.2f} pts)" ) print(f"Pergunta: {item['pergunta']}") print("Alternativas:") for letra in opcoes_letras: conteudo = item["alternativas"][letra] print(f" ({letra}) {conteudo}") print( "\n------------------------------------------------------------------------------------------" ) print("\n") # --- 3. EXIBIÇÃO DO GABARITO OFICIAL --- print( "==========================================================================" ) print( " GABARITO OFICIAL " ) print( "==========================================================================" ) cabecalho_letras = " | ".join([f" {letra} " for letra in opcoes_letras]) print(f"{'QUESTÃO':<10} | {cabecalho_letras}") print( "--------------------------------------------------------------------------" ) for item in dados_simulado: linha_opcoes = [] for letra in opcoes_letras: if letra == item["resposta"]: linha_opcoes.append(" [X] ") else: linha_opcoes.append(" ( ) ") formato_linha = " | ".join(linha_opcoes) print(f" {item['num_q']:<8} | {formato_linha}") print( "==========================================================================" ) input("\nPressione ENTER para voltar ao menu principal...") os.system("cls" if os.name == "nt" else "clear") # ============================================================================== # 4. ESTRUTURA E LOOP PRINCIPAL DO PROGRAMA # ============================================================================== while True: try: exibir_manual() print("+++++++++++++++++++++++++++++++++++++++++++++++++++") print("+ BEM VINDO AO CALCULADOR DE NOTAS +") print("+ ALEM DE NOTAS VEM UMA CALCULADORA INTEGRADA +") print("+ E E TOTALMENTE EM PYTHON E GRATUITO +") print("+++++++++++++++++++++++++++++++++++++++++++++++++++") time.sleep(1) definicao = pedir_inteiro( "digite 1 para calcular a nota do aluno\n" "digite 2 para fazer a porcentagem da nota do aluno\n" "digite 3 para fazer um boletim\n" "digite 4 para sair\n" "digite 5 para reiniciar\n" "digite 6 para calcular numeros\n" "digite 7 para boletim multialuno\n" "digite 8 para gerar provas multimaterias com tabela (Soma = 10.0)\n" "digite 9 para gerar prova simples (sem materia) com tabela (Soma = 10.0)\n" "digite 10 para GERAR SIMULADO (Tabela + Prova Completa + Gabarito Personalizado)\n" "escolha uma opcao (1-10): ", min_val=1, max_val=10, ) if definicao == 1: opcao_1_calcular_nota_aluno() elif definicao == 2: opcao_2_porcentagem_nota() elif definicao == 3: opcao_3_boletim_aluno() elif definicao == 4: opcao_4_sair() elif definicao == 5: opcao_5_reiniciar() elif definicao == 6: opcao_6_calculadora_integradat() elif definicao == 7: opcao_7_boletim_multialuno() elif definicao == 8: opcao_8_provas_multimaterias() elif definicao == 9: opcao_9_prova_simples() elif definicao == 10: opcao_10_gerar_simulado_completo() except VoltarException: print("\nVoltando para a tela anterior...") time.sleep(1) os.system("cls" if os.name == "nt" else "clear") continue except ReiniciarException: continue except Exception as e: print(f"\nOcorreu um erro inesperado: {e}") time.sleep(2) os.system("cls" if os.name == "nt" else "clear")