File size: 4,864 Bytes
6f2b94e
37e94dc
6f2b94e
 
37e94dc
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6f2b94e
37e94dc
 
 
 
87e23e5
 
 
 
 
 
de9b6c1
37e94dc
 
 
 
 
 
 
 
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
import gradio as gr
import ast


def grade(student_code):
    feedback = []
    grade = 10  # Start with full points

    try:
        # Parse the student's code into an AST (Abstract Syntax Tree)
        tree = ast.parse(student_code)

        # Variables to track correctness
        pin_setup = False
        initial_delay = False
        loop_found = False
        blink_pattern = False
        sleep_times = []

        # Analyze the AST
        for node in ast.walk(tree):
            # Check pin setup
            if isinstance(node, ast.Assign):
                if isinstance(node.value, ast.Call) and isinstance(node.value.func, ast.Attribute):
                    if node.value.func.attr == "Pin":
                        args = node.value.args
                        if len(args) >= 2 and isinstance(args[0], ast.Constant):
                            if str(args[0].value) == "21":
                                pin_setup = True
            
            # Check for time.sleep() calls
            if isinstance(node, ast.Call) and isinstance(node.func, ast.Attribute):
                if node.func.attr == "sleep" and isinstance(node.args[0], ast.Constant):
                    sleep_times.append(node.args[0].value)

            # Check for while loop
            if isinstance(node, ast.While):
                loop_found = True

            # Check LED alternation
            if isinstance(node, ast.Expr) and isinstance(node.value, ast.Call):
                if isinstance(node.value.func, ast.Attribute):
                    if node.value.func.attr == "value" or node.value.func.attr == "on" or node.value.func.attr == "off":
                        blink_pattern = True

        # Validate pin setup
        if not pin_setup:
            feedback.append("⛔️ Pin 21 must be correctly set as an output (-2 pts).")
            grade -= 2
        else:
            feedback.append("✅ Correct pin setup detected (+2 pts).")

        # Validate initial delay
        if 3 in sleep_times:
            initial_delay = True
            feedback.append("✅ Initial delay of 3 seconds detected (+2 pts).")
        else:
            feedback.append("⛔️ The LED must stay ON for 3 seconds initially (-2 pts).")
            grade -= 2

        # Validate while loop
        if not loop_found:
            feedback.append("⛔️ No `while True:` loop found! The LED must blink continuously (-2 pts).")
            grade -= 2
        else:
            feedback.append("✅ Infinite loop detected (+2 pts).")

        # Validate blinking pattern
        if 1 in sleep_times:
            feedback.append("✅ Blinking delay of 1 second detected (+2 pts).")
        else:
            feedback.append("⛔️ The LED must blink every second after the initial delay (-2 pts).")
            grade -= 2

        # Validate LED alternation
        if not blink_pattern:
            feedback.append("⛔️ The LED should alternate states in the loop (-2 pts).")
            grade -= 2
        else:
            feedback.append("✅ LED alternation detected (+2 pts).")

    except Exception as e:
        feedback = f"Error parsing code: {e}"

    # Ensure the grade is not negative
    grade = max(0, grade)

    grade = f"{grade}/10"
    
    feedback = "\n".join(feedback)

    # Return feedback
    return grade, feedback

# Interface Gradio seulement si le script est exécuté directement
if __name__ == "__main__":
    with gr.Blocks(gr.themes.Default(primary_hue="cyan")) as demo:
        with gr.Row():
            instructions = gr.Markdown("""
                ## Instructions
                1. Based on the examples you've seen so far, write a MicroPython code that follows the instructions above.                
                2. You can use the [Vittascience simulator](https://fr.vittascience.com/esp32/?mode=code&console=bottom&toolbox=scratch&simu=1&board=basic-esp32) to test your code.
                2. Click the "Grade" button to get a grade and feedback.
                3. Make sure your code is well-structured and efficient.
                4. When you're happy with your code, please upload your solution below to get graded.
                6. Good luck!
            """, container=False)
            code = gr.Code(label="MicroPython code", language="python", value='import machine\n\n# Your code here', lines=24)
        with gr.Row():
            feedback_output = gr.Textbox(label="Feedback", value="Click on the 'Grade' button to get feedback", interactive=False, scale=4)
            grade_output = gr.Textbox(label="Grade", interactive=False, value="0/10", scale=1)
        grade_btn = gr.Button("Grade", variant="primary")
        grade_btn.click(fn=grade, inputs=code, outputs=[grade_output, feedback_output], api_name="grade")

    demo.launch(show_error=False, allowed_paths=["/assets", "assets"], show_api=False)