File size: 3,988 Bytes
ec4da21
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
from typing import Any, Dict, Tuple

METRIC_KEYS = [
    "hierarchy_strength",
    "focal_clarity",
    "typography_control",
    "font_conflict",
    "palette_control",
    "color_conflict",
    "visual_clutter",
    "template_genericity",
    "originality",
    "technical_quality",
    "visual_impact",
]

REQUIRED_KEYS = {
    "content_present": bool,
    "hierarchy_strength": int,
    "focal_clarity": int,
    "typography_control": int,
    "font_conflict": int,
    "palette_control": int,
    "color_conflict": int,
    "visual_clutter": int,
    "template_genericity": int,
    "originality": int,
    "technical_quality": int,
    "visual_impact": int,
    "confidence": (float, int),
    "comment": str,
}


PRESENCE_SCHEMA = {
    "type": "object",
    "properties": {
        "content_present": {"type": "boolean"},
    },
    "required": ["content_present"],
    "additionalProperties": False,
}


def metric_schema(metric_name: str) -> Dict[str, Any]:
    return {
        "type": "object",
        "properties": {
            metric_name: {"type": "integer", "minimum": 1, "maximum": 5},
        },
        "required": [metric_name],
        "additionalProperties": False,
    }


FINAL_JUDGE_SCHEMA = {
    "type": "object",
    "properties": {
        "label": {"type": "string", "enum": ["bad", "medium", "good"]},
        "confidence": {"type": "number", "minimum": 0.0, "maximum": 1.0},
        "rationale": {"type": "string"},
    },
    "required": ["label", "confidence", "rationale"],
    "additionalProperties": False,
}


OUTPUT_SCHEMA = {
    "type": "object",
    "properties": {
        "content_present": {"type": "boolean"},
        "hierarchy_strength": {"type": "integer", "minimum": 1, "maximum": 5},
        "focal_clarity": {"type": "integer", "minimum": 1, "maximum": 5},
        "typography_control": {"type": "integer", "minimum": 1, "maximum": 5},
        "font_conflict": {"type": "integer", "minimum": 1, "maximum": 5},
        "palette_control": {"type": "integer", "minimum": 1, "maximum": 5},
        "color_conflict": {"type": "integer", "minimum": 1, "maximum": 5},
        "visual_clutter": {"type": "integer", "minimum": 1, "maximum": 5},
        "template_genericity": {"type": "integer", "minimum": 1, "maximum": 5},
        "originality": {"type": "integer", "minimum": 1, "maximum": 5},
        "technical_quality": {"type": "integer", "minimum": 1, "maximum": 5},
        "visual_impact": {"type": "integer", "minimum": 1, "maximum": 5},
        "confidence": {"type": "number", "minimum": 0.0, "maximum": 1.0},
        "comment": {"type": "string"},
    },
    "required": [
        "content_present",
        "hierarchy_strength",
        "focal_clarity",
        "typography_control",
        "font_conflict",
        "palette_control",
        "color_conflict",
        "visual_clutter",
        "template_genericity",
        "originality",
        "technical_quality",
        "visual_impact",
        "confidence",
        "comment",
    ],
    "additionalProperties": False,
}


def validate_scores(data: Dict[str, Any]) -> Tuple[bool, str]:
    for key, expected_type in REQUIRED_KEYS.items():
        if key not in data:
            return False, f"Missing key: {key}"

        if not isinstance(data[key], expected_type):
            return False, f"Invalid type for key: {key}"

    for key in METRIC_KEYS:
        value = data[key]
        if not isinstance(value, int):
            return False, f"{key} must be int"
        if value < 1 or value > 5:
            return False, f"{key} must be in range 1..5"

    confidence = float(data["confidence"])
    if confidence < 0.0 or confidence > 1.0:
        return False, "confidence must be in range 0.0..1.0"

    comment = data["comment"].strip()
    if not comment:
        return False, "comment must not be empty"

    return True, "ok"