File size: 1,515 Bytes
a5c9fd4
 
 
 
50a0917
 
 
 
a5c9fd4
 
b56681c
 
a5c9fd4
b56681c
a5c9fd4
b56681c
4a63c86
a5c9fd4
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
50a0917
a5c9fd4
 
 
 
 
 
 
 
 
50a0917
 
 
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
from typing import Dict
import ast


MIN_TASK_SCORE = 0.01
MAX_TASK_SCORE = 0.99


def get_task() -> Dict:
    return {
        "id": "hard",
        "difficulty": "hard",
        "name": "refactor_types",
        "objective": "Preserve core structure and add meaningful type annotations.",
        "description": "Refactor code and add type hints.",
        "grader_name": "grade",
        "score_range": [MIN_TASK_SCORE, MAX_TASK_SCORE],
    }


def _count_type_hints(tree: ast.AST) -> int:
    count = 0
    for node in ast.walk(tree):
        if isinstance(node, ast.AnnAssign):
            count += 1
        elif isinstance(node, ast.FunctionDef):
            if node.returns is not None:
                count += 1
            for arg in node.args.args:
                if arg.annotation is not None:
                    count += 1
    return count


def _count_defs(tree: ast.AST) -> int:
    return sum(
        isinstance(node, (ast.FunctionDef, ast.ClassDef))
        for node in ast.walk(tree)
    )


def grade(candidate_code: str) -> float:
    """
    Score breakdown:
    - Structural preservation (defs exist) → +0.5
    - Type hints present → +0.5
    """
    try:
        tree = ast.parse(candidate_code)
    except SyntaxError:
        return MIN_TASK_SCORE

    score = 0.0

    if _count_defs(tree) > 0:
        score += 0.5

    if _count_type_hints(tree) > 0:
        score += 0.5

    score = round(score, 2)
    score = max(MIN_TASK_SCORE, min(MAX_TASK_SCORE, score))
    return score