File size: 8,926 Bytes
11aa4b5
 
 
 
 
27c3ca2
11aa4b5
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3f4b0f0
11aa4b5
 
 
6803b94
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11aa4b5
3f4b0f0
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7f98838
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3f4b0f0
7f98838
 
 
3f4b0f0
 
7f98838
 
 
 
 
3f4b0f0
 
 
 
 
 
 
 
 
7f98838
3f4b0f0
 
 
 
 
 
 
 
 
 
 
 
 
7f98838
3f4b0f0
 
 
 
 
 
 
7f98838
3f4b0f0
7f98838
3f4b0f0
7f98838
 
 
11aa4b5
 
 
 
7f98838
 
3f4b0f0
 
 
 
 
 
 
11aa4b5
 
 
 
 
 
 
 
 
 
 
3f4b0f0
 
11aa4b5
 
 
 
7f98838
 
3f4b0f0
 
11aa4b5
 
 
 
27c3ca2
11aa4b5
27c3ca2
 
 
11aa4b5
 
 
27c3ca2
 
 
11aa4b5
 
 
 
 
 
3f4b0f0
 
 
 
 
 
 
 
 
 
 
 
 
 
11aa4b5
 
 
 
 
 
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
import gradio as gr
import javalang
from typing import Dict, List, Tuple

class JavaPOOEvaluator:
    """Java-Judge: OO Paradigm"""
    def __init__(self):
        self.rubric = {
            "classes": 20,
            "objetos": 20,
            "metodos": 20,
            "atributos": 20,
            "encapsulamento": 10,
            "heranca": 10,
            "polimorfismo": 10,
            "abstracao": 10,
        }

    def analyze_classes_and_objects(self, code: str) -> Tuple[float, List[str]]:
        """Avalia a definição e o uso de classes e objetos"""
        score = 0
        feedback = []

        try:
            tree = javalang.parse.parse(code)
            classes = list(tree.filter(javalang.tree.ClassDeclaration))
            
            if classes:
                score += 15
                feedback.append(f"✓ {len(classes)} classe(s) declarada(s) corretamente.")
            else:
                feedback.append("⚠ Nenhuma classe declarada encontrada.")

            objects = [node for _, node in tree.filter(javalang.tree.VariableDeclarator) if 'new' in str(node.initializer)]
            if objects:
                score += 5
                feedback.append(f"✓ {len(objects)} objeto(s) criado(s) corretamente.")
            else:
                feedback.append("⚠ Nenhuma instância de objeto criada.")
        except Exception as e:
            feedback.append("⚠ Erro ao analisar classes e objetos.")

        return score, feedback

    def analyze_methods(self, code: str) -> Tuple[float, List[str]]:
        """Avalia a definição e organização de métodos"""
        score = 0
        feedback = []

        try:
            tree = javalang.parse.parse(code)
            methods = list(tree.filter(javalang.tree.MethodDeclaration))
            
            if methods:
                score += 15
                feedback.append(f"✓ {len(methods)} método(s) declarado(s) corretamente.")
            else:
                feedback.append("⚠ Nenhum método declarado encontrado.")
        except Exception as e:
            feedback.append(f"⚠ Erro ao analisar métodos: {e}")

        return score, feedback

    def analyze_encapsulation(self, code: str) -> Tuple[float, List[str]]:
        """Avalia encapsulamento e uso de modificadores"""
        score = 0
        feedback = []

        try:
            tree = javalang.parse.parse(code)
            fields = list(tree.filter(javalang.tree.FieldDeclaration))

            private_count = sum(1 for _, node in fields if 'private' in node.modifiers)
            if private_count:
                score += 5
                feedback.append(f"✓ {private_count} atributo(s) encapsulado(s) com 'private'.")

            getters_setters = [method for _, method in tree.filter(javalang.tree.MethodDeclaration) if method.name.startswith('get') or method.name.startswith('set')]
            if getters_setters:
                score += 5
                feedback.append(f"✓ {len(getters_setters)} getter(s) ou setter(s) implementado(s).")
            else:
                feedback.append("⚠ Nenhum getter ou setter encontrado.")
        except Exception as e:
            feedback.append("⚠ Erro ao analisar encapsulamento.")

        return score, feedback

    def analyze_inheritance(self, code: str) -> Tuple[float, List[str]]:
        """Avalia o uso de herança"""
        score = 0
        feedback = []

        try:
            tree = javalang.parse.parse(code)
            subclasses = [node for _, node in tree.filter(javalang.tree.ClassDeclaration) if node.extends]
            
            if subclasses:
                score += 10
                feedback.append(f"✓ {len(subclasses)} classe(s) estendendo outra(s).")
            else:
                feedback.append("⚠ Nenhum uso de herança encontrado.")
        except Exception as e:
            feedback.append("⚠ Erro ao analisar herança.")

        return score, feedback

    def analyze_polymorphism(self, code: str) -> Tuple[float, List[str]]:
        """Avalia o uso de polimorfismo"""
        score = 0
        feedback = []

        try:
            tree = javalang.parse.parse(code)
            overridden_methods = [node for _, node in tree.filter(javalang.tree.MethodDeclaration) if 'Override' in (node.annotations or [])]
            
            if overridden_methods:
                score += 10
                feedback.append(f"✓ {len(overridden_methods)} método(s) sobrescrito(s) corretamente.")
            else:
                feedback.append("⚠ Nenhum uso de polimorfismo encontrado.")
        except Exception as e:
            feedback.append("⚠ Erro ao analisar polimorfismo.")

        return score, feedback

    def analyze_abstraction(self, code: str) -> Tuple[float, List[str]]:
        """Avalia o uso de abstração"""
        score = 0
        feedback = []

        try:
            tree = javalang.parse.parse(code)
            abstract_classes = [node for _, node in tree.filter(javalang.tree.ClassDeclaration) if 'abstract' in node.modifiers]
            interfaces = list(tree.filter(javalang.tree.InterfaceDeclaration))

            if abstract_classes:
                score += 5
                feedback.append(f"✓ {len(abstract_classes)} classe(s) abstrata(s) declarada(s).")
            else:
                feedback.append("⚠ Nenhuma classe abstrata encontrada.")

            if interfaces:
                score += 5
                feedback.append(f"✓ {len(interfaces)} interface(s) declarada(s).")
            else:
                feedback.append("⚠ Nenhuma interface encontrada.")
        except Exception as e:
            feedback.append("⚠ Erro ao analisar abstração.")

        return score, feedback

    def evaluate_code(self, code: str) -> Dict:
        """Avalia o código Java"""
        cls_score, cls_feedback = self.analyze_classes_and_objects(code)
        meth_score, meth_feedback = self.analyze_methods(code)
        enc_score, enc_feedback = self.analyze_encapsulation(code)
        inh_score, inh_feedback = self.analyze_inheritance(code)
        poly_score, poly_feedback = self.analyze_polymorphism(code)
        abs_score, abs_feedback = self.analyze_abstraction(code)

        essential_score = cls_score + meth_score
        bonus_score = enc_score + inh_score + poly_score + abs_score
        total_score = essential_score + bonus_score
        total_score = min(100, total_score)

        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,
            "essential_score": essential_score,
            "bonus_score": bonus_score,
            "proficiency": proficiency,
            "feedback": {
                "classes_objetos": cls_feedback,
                "metodos": meth_feedback,
                "encapsulamento": enc_feedback,
                "heranca": inh_feedback,
                "polimorfismo": poly_feedback,
                "abstracao": abs_feedback,
            }
        }

# Interface Gradio
with gr.Blocks(title="Java-Judge: OO Paradigm", css="#rubric_image img {max-width: 50%; height: auto; margin: 0 auto;}") as demo:
    gr.Markdown("# Avaliador de POO em Java")
    gr.Markdown("### [Visualizar a Rubrica em PDF](rubric.pdf)")
    gr.Markdown("#### Avalie seu código Java com base em critérios de POO")
    
    upload = gr.File(label="Carregue arquivos Java para avaliação", file_types=[".java"], file_count="multiple")
    evaluate_button = gr.Button("Avaliar Código")
    output = gr.Textbox(label="Resultado da Avaliação", lines=25)
    
    gr.Markdown("### Rubrica de Avaliação")
    rubric_image = gr.Image("rubric_table.png", label="Tabela Resumida da Rubrica", elem_id="rubric_image")

    def evaluate_code_files(files) -> str:
        evaluator = JavaPOOEvaluator()
        results = []

        for file in files:
            with open(file.name, 'r', encoding='utf-8') as f:
                code = f.read()
            evaluation = evaluator.evaluate_code(code)

            result = f"\nArquivo: {file.name}\n"
            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():
                result += f"\n{category.replace('_', ' ').title()}:\n"
                for comment in comments:
                    result += f"  {comment}\n"
            results.append(result)

        return "\n".join(results)

    evaluate_button.click(fn=evaluate_code_files, inputs=upload, outputs=output)

if __name__ == "__main__":
    demo.launch(share=True)