rmayormartins's picture
JAVA-judge33
d9000eb
raw
history blame
19.8 kB
# Instalação das dependências
!pip install -q javalang gradio
import gradio as gr
import javalang
from typing import Dict, List, Tuple
import re
class JavaStructuralEvaluator:
"""Avaliador baseado em estruturas usadas"""
def __init__(self):
self.rubric = {
"declaracoes": 25, # Declarações e tipos
"estruturas_controle": 25, # if, switch, loops
"operadores": 25, # Operadores e expressões
"io_strings": 25 # System.out, concatenação, etc
}
def analyze_declarations(self, code: str) -> Tuple[float, List[str]]:
"""Analisa declarações e tipos"""
score = 0
feedback = []
try:
tree = javalang.parse.parse(code)
# Verificar tipos primitivos
primitives = {
'int': 'números inteiros',
'double': 'números decimais',
'boolean': 'valores lógicos',
'char': 'caracteres',
'float': 'números decimais (float)',
'long': 'números longos',
'byte': 'valores byte',
'short': 'números curtos'
}
used_types = set()
for _, node in tree.filter(javalang.tree.LocalVariableDeclaration):
type_name = node.type.name
used_types.add(type_name)
for type_name, description in primitives.items():
if type_name in used_types:
score += 3
feedback.append(f"✓ Uso correto de {type_name} para {description}")
# Verificar declarações de variáveis
total_vars = len(list(tree.filter(javalang.tree.LocalVariableDeclaration)))
if total_vars > 0:
score += 5
feedback.append(f"✓ {total_vars} variáveis declaradas corretamente")
# Verificar constantes
constants = list(tree.filter(javalang.tree.FieldDeclaration))
if any('final' in node.modifiers for _, node in tree.filter(javalang.tree.FieldDeclaration)):
score += 4
feedback.append("✓ Uso adequado de constantes (final)")
except Exception as e:
feedback.append("⚠ Erro na análise de declarações")
return score, feedback
def analyze_control_structures(self, code: str) -> Tuple[float, List[str]]:
"""Analisa estruturas de controle"""
score = 0
feedback = []
try:
tree = javalang.parse.parse(code)
# If/Else
if_count = len(list(tree.filter(javalang.tree.IfStatement)))
if if_count > 0:
score += 5
feedback.append(f"✓ Uso correto de {if_count} estrutura(s) if/else")
# Switch
switch_count = len(list(tree.filter(javalang.tree.SwitchStatement)))
if switch_count > 0:
score += 5
feedback.append(f"✓ Uso correto de {switch_count} switch/case")
# For loops
for_count = len(list(tree.filter(javalang.tree.ForStatement)))
if for_count > 0:
score += 5
feedback.append(f"✓ Uso correto de {for_count} loop(s) for")
# While loops
while_count = len(list(tree.filter(javalang.tree.WhileStatement)))
if while_count > 0:
score += 5
feedback.append(f"✓ Uso correto de {while_count} loop(s) while")
# Do-While loops
do_while_count = len(list(tree.filter(javalang.tree.DoStatement)))
if do_while_count > 0:
score += 5
feedback.append(f"✓ Uso correto de {do_while_count} loop(s) do-while")
except Exception as e:
feedback.append("⚠ Erro na análise de estruturas de controle")
return score, feedback
def analyze_operators(self, code: str) -> Tuple[float, List[str]]:
"""Analisa operadores e expressões"""
score = 0
feedback = []
try:
# Operadores aritméticos
arithmetic = ['+', '-', '*', '/', '%']
for op in arithmetic:
if op in code:
score += 2
feedback.append(f"✓ Uso do operador aritmético {op}")
# Operadores de comparação
comparison = ['==', '!=', '>', '<', '>=', '<=']
for op in comparison:
if op in code:
score += 2
feedback.append(f"✓ Uso do operador de comparação {op}")
# Operadores lógicos
logical = ['&&', '||', '!']
for op in logical:
if op in code:
score += 2
feedback.append(f"✓ Uso do operador lógico {op}")
# Operadores de atribuição
assignment = ['+=', '-=', '*=', '/=']
for op in assignment:
if op in code:
score += 2
feedback.append(f"✓ Uso do operador de atribuição {op}")
except Exception as e:
feedback.append("⚠ Erro na análise de operadores")
return score, feedback
def analyze_io_strings(self, code: str) -> Tuple[float, List[str]]:
"""Analisa entrada/saída e manipulação de strings"""
score = 0
feedback = []
try:
# System.out
if 'System.out.print' in code:
score += 5
feedback.append("✓ Uso correto de System.out.print")
# Scanner
if 'Scanner' in code:
score += 5
feedback.append("✓ Uso correto da classe Scanner para entrada")
# Concatenação de strings
if '+' in code and '"' in code:
score += 5
feedback.append("✓ Concatenação de strings com operador +")
# Métodos de String
string_methods = ['concat', 'substring', 'length', 'equals', 'compareTo']
for method in string_methods:
if f'.{method}(' in code:
score += 2
feedback.append(f"✓ Uso do método String.{method}")
except Exception as e:
feedback.append("⚠ Erro na análise de I/O e strings")
return score, feedback
def evaluate_code(self, code: str) -> Dict:
"""Avalia o código Java"""
# Análises individuais
decl_score, decl_feedback = self.analyze_declarations(code)
ctrl_score, ctrl_feedback = self.analyze_control_structures(code)
op_score, op_feedback = self.analyze_operators(code)
io_score, io_feedback = self.analyze_io_strings(code)
# Calcular pontuação total
total_score = sum([
decl_score,
ctrl_score,
op_score,
io_score
])
# Normalizar para 100
total_score = min(100, total_score)
# Determinar nível
proficiency = "Necessita Melhorias"
if total_score >= 90:
proficiency = "Excelente"
elif total_score >= 75:
proficiency = "Bom"
elif total_score >= 60:
proficiency = "Satisfatório"
return {
"total_score": total_score,
"proficiency": proficiency,
"feedback": {
"declaracoes": decl_feedback,
"estruturas_controle": ctrl_feedback,
"operadores": op_feedback,
"io_strings": io_feedback
}
}
class CompetencyEvaluator:
"""Avaliador baseado em competências"""
def __init__(self):
self.rubric = {
"syntax_correctness": 50, # Corretude sintática
"competencies": 50 # Competências demonstradas
}
def analyze_syntax_correctness(self, code: str) -> Tuple[float, List[str]]:
"""Analisa corretude sintática (50 pontos)"""
score = 0
feedback = []
try:
tree = javalang.parse.parse(code)
# 1. Estrutura básica do programa (10 pontos)
if 'class' in code:
score += 5
feedback.append("✓ Estrutura de classe correta")
if 'public static void main' in code:
score += 5
feedback.append("✓ Método main corretamente declarado")
# 2. Declarações e Tipos (10 pontos)
declarations = list(tree.filter(javalang.tree.LocalVariableDeclaration))
if declarations:
score += 5
feedback.append("✓ Declarações de variáveis sintáticamente corretas")
if any(d.type.name in ['int', 'double', 'String', 'boolean'] for d in declarations):
score += 5
feedback.append("✓ Tipos de dados usados corretamente")
# 3. Expressões e Operadores (10 pontos)
if list(tree.filter(javalang.tree.BinaryOperation)):
score += 10
feedback.append("✓ Expressões e operadores usados corretamente")
# 4. Blocos e Estruturas (10 pontos)
open_braces = code.count('{')
close_braces = code.count('}')
if open_braces == close_braces and open_braces > 0:
score += 5
feedback.append("✓ Blocos corretamente delimitados")
semicolons = len(re.findall(';[^;]*$', code, re.MULTILINE))
if semicolons > 0:
score += 5
feedback.append("✓ Instruções corretamente terminadas")
# 5. Entrada/Saída (10 pontos)
if 'System.out' in code:
score += 5
feedback.append("✓ Sintaxe de saída correta")
if 'Scanner' in code:
score += 5
feedback.append("✓ Sintaxe de entrada correta")
except Exception as e:
feedback.append(f"⚠ Erro de sintaxe: {str(e)}")
return score, feedback
def analyze_competencies(self, code: str) -> Tuple[float, List[str]]:
"""Analisa competências demonstradas (50 pontos)"""
score = 0
feedback = []
try:
tree = javalang.parse.parse(code)
# 1. Seleção de Estruturas (15 pontos)
structures = {
'if': list(tree.filter(javalang.tree.IfStatement)),
'for': list(tree.filter(javalang.tree.ForStatement)),
'while': list(tree.filter(javalang.tree.WhileStatement))
}
appropriate_use = True
for struct_type, instances in structures.items():
if instances:
if struct_type == 'for' and any('length' in str(inst) for inst in instances):
score += 5
feedback.append("✓ Uso adequado de for para iteração em arrays")
elif struct_type == 'while' and any('hasNext' in str(inst) for inst in instances):
score += 5
feedback.append("✓ Uso adequado de while para leitura de dados")
else:
score += 5
feedback.append(f"✓ Uso apropriado de {struct_type}")
# 2. Manipulação de Dados (15 pontos)
operations = list(tree.filter(javalang.tree.BinaryOperation))
if operations:
if any(op.operator in ['*', '/', '+', '-'] for op in operations):
score += 5
feedback.append("✓ Cálculos implementados corretamente")
if any(op.operator in ['>', '<', '>=', '<=', '=='] for op in operations):
score += 5
feedback.append("✓ Comparações implementadas corretamente")
if any('=' in str(op) for op in operations):
score += 5
feedback.append("✓ Atribuições implementadas corretamente")
# 3. Clareza e Organização (10 pontos)
# Verificar nomes significativos
if all(len(decl.declarators[0].name) > 1 for _, decl in tree.filter(javalang.tree.LocalVariableDeclaration)):
score += 5
feedback.append("✓ Nomes de variáveis significativos")
# Verificar indentação e comentários
lines = code.split('\n')
if any('//' in line or '/*' in line for line in lines):
score += 5
feedback.append("✓ Código bem documentado")
# 4. Resolução do Problema (10 pontos)
# Verificar se tem entrada, processamento e saída
has_input = 'Scanner' in code
has_processing = bool(operations)
has_output = 'System.out' in code
if has_input and has_output:
score += 5
feedback.append("✓ Programa com entrada e saída")
if has_processing:
score += 5
feedback.append("✓ Lógica de processamento implementada")
except Exception as e:
feedback.append(f"⚠ Erro na análise de competências: {str(e)}")
return score, feedback
def evaluate_code(self, code: str) -> Dict:
# Análises individuais
syntax_score, syntax_feedback = self.analyze_syntax_correctness(code)
comp_score, comp_feedback = self.analyze_competencies(code)
# Calcular pontuação total
total_score = syntax_score + comp_score
# Determinar nível
proficiency = "Necessita Melhorias"
if total_score >= 90:
proficiency = "Excelente"
elif total_score >= 75:
proficiency = "Bom"
elif total_score >= 60:
proficiency = "Satisfatório"
return {
"total_score": total_score,
"proficiency": proficiency,
"feedback": {
"corretude_sintatica": syntax_feedback,
"competencias": comp_feedback
}
}
def process_java_files(files) -> str:
"""Avalia código usando a rubrica estrutural"""
evaluator = JavaStructuralEvaluator()
return evaluate_files(files, evaluator, "Estrutural")
def evaluate_competency(files) -> str:
"""Avalia código usando a rubrica de competências"""
evaluator = CompetencyEvaluator()
return evaluate_files(files, evaluator, "Competências")
def evaluate_files(files, evaluator, evaluation_type: str) -> str:
"""Função auxiliar para avaliar arquivos com qualquer avaliador"""
results = []
project_files = {}
try:
if not isinstance(files, list):
files = [files]
# Primeiro, vamos ler todos os arquivos
for file in files:
with open(file.name, 'r', encoding='utf-8') as f:
content = f.read()
project_files[file.name] = content
# Identificar arquivo principal
main_file = None
other_files = {}
for filename, content in project_files.items():
if "public static void main" in content:
main_file = (filename, content)
else:
other_files[filename] = content
# Resumo do projeto
results.append(f"""
{'='*50}
AVALIAÇÃO {evaluation_type.upper()}
{'='*50}
Total de arquivos: {len(project_files)}
Arquivo principal: {main_file[0] if main_file else 'Não encontrado'}
Arquivos complementares: {len(other_files)}
{'='*50}
""")
# Avaliar arquivo principal
if main_file:
result = f"\nARQUIVO PRINCIPAL: {main_file[0]}\n{'-'*30}\n"
evaluation = evaluator.evaluate_code(main_file[1])
result += f"Pontuação Total: {evaluation['total_score']:.1f}/100\n"
result += f"Nível: {evaluation['proficiency']}\n\n"
result += "Feedback Detalhado:\n"
for category, comments in evaluation['feedback'].items():
if comments:
result += f"\n{category.title()}:\n"
for comment in comments:
result += f" {comment}\n"
results.append(result)
# Avaliar outros arquivos
if other_files:
results.append(f"\nARQUIVOS COMPLEMENTARES\n{'-'*30}")
for filename, content in other_files.items():
result = f"\nAvaliando: {filename}\n"
evaluation = evaluator.evaluate_code(content)
result += f"Pontuação: {evaluation['total_score']:.1f}/100\n"
result += f"Nível: {evaluation['proficiency']}\n\n"
result += "Feedback:\n"
for category, comments in evaluation['feedback'].items():
if comments:
result += f"\n{category.title()}:\n"
for comment in comments:
result += f" {comment}\n"
results.append(result)
return "\n".join(results)
except Exception as e:
return f"Erro ao processar arquivos: {str(e)}\nTipo do erro: {type(e)}"
# Interface Gradio com abas
with gr.Blocks(title="Java-Judge-Syntax-Competencies") as demo:
gr.Markdown("""
# Java-Judge-Syntax-Competencies
### [Visualizar Rubrica em PDF](rubric.pdf)
### [Visualizar Rubrica em PNG](rubric_table.png)
Este avaliador analisa código Java usando duas rubricas diferentes:
1. **Avaliação Estrutural**: Foca no uso correto de elementos da linguagem
2. **Avaliação por Competências**: Analisa qualidade e eficiência do código
""")
with gr.Tabs():
with gr.Tab("Avaliação Estrutural"):
upload_structural = gr.File(
file_count="multiple",
label="Upload dos arquivos Java"
)
evaluate_btn_structural = gr.Button("Avaliar Estruturas")
output_structural = gr.Textbox(
label="Resultado da Avaliação",
lines=25
)
evaluate_btn_structural.click(
fn=process_java_files,
inputs=upload_structural,
outputs=output_structural
)
with gr.Tab("Avaliação por Competências"):
upload_competency = gr.File(
file_count="multiple",
label="Upload dos arquivos Java"
)
evaluate_btn_competency = gr.Button("Avaliar Competências")
output_competency = gr.Textbox(
label="Resultado da Avaliação",
lines=25
)
evaluate_btn_competency.click(
fn=evaluate_competency,
inputs=upload_competency,
outputs=output_competency
)
if __name__ == "__main__":
demo.launch(share=True)