File size: 8,945 Bytes
eaf7eca
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
"""
Test the game JSON schema and validation utilities.

Run this script to:
1. Test the schema against example games from the dataset
2. Validate schema structure
3. Test minimal game templates
4. Display validation results
"""

import json
from app.services.retrieval import load_games_dataset, normalize_game_record
from app.services.schema_validator import (
    load_schema,
    validate_game_schema,
    validate_task_structure,
    validate_safety_structure,
    create_minimal_game_template
)


def test_schema_structure():
    """Test that the schema itself is valid."""
    print("=" * 80)
    print("SCHEMA STRUCTURE TEST")
    print("=" * 80)
    
    try:
        schema = load_schema("game_schema.json")
        print("βœ“ Game schema loaded successfully")
        print(f"  Title: {schema.get('title')}")
        print(f"  Type: {schema.get('type')}")
        print(f"  Required fields: {', '.join(schema.get('required', []))}")
        return True
    except Exception as e:
        print(f"βœ— Failed to load schema: {e}")
        return False


def test_minimal_template():
    """Test validation of a minimal game template."""
    print("\n" + "=" * 80)
    print("MINIMAL GAME TEMPLATE TEST")
    print("=" * 80)
    
    template = create_minimal_game_template()
    is_valid, errors = validate_game_schema(template)
    
    if is_valid:
        print("βœ“ Minimal template is valid against schema")
        print(f"  Game ID: {template['game_id']}")
        print(f"  Title: {template['title']}")
        print(f"  Tasks: {len(template['tasks'])}")
        print(f"  Rules: {len(template['rules'])}")
        return True
    else:
        print(f"βœ— Minimal template validation failed:")
        for error in errors:
            print(f"  - {error}")
        return False


def test_dataset_games():
    """Test validation of example games from the dataset."""
    print("\n" + "=" * 80)
    print("DATASET GAMES VALIDATION TEST")
    print("=" * 80)
    
    # Load dataset
    raw_records = load_games_dataset("app/data/games_dataset.json")
    
    # Convert raw records to game schema format for testing
    tested_count = 0
    valid_count = 0
    invalid_games = []
    
    for raw in raw_records[:3]:  # Test first 3 as sample
        try:
            # Extract expected output as game structure
            output = raw.get('expected_output', {})
            input_data = raw.get('input', {})
            
            # Build game in schema format
            # Transform tasks to include required title field
            tasks_transformed = []
            for task in output.get('tasks', []):
                task_copy = task.copy()
                # Add title if missing
                if 'title' not in task_copy:
                    task_copy['title'] = task_copy.get('description', 'Task')[:50]
                # Ensure all required fields exist
                task_copy.setdefault('proof_type', 'observation')
                task_copy.setdefault('hint', 'See location hint above')
                task_copy.setdefault('safety_note', 'Follow general safety rules')
                tasks_transformed.append(task_copy)
            
            game = {
                "game_id": raw.get('id'),
                "title": f"Game {raw.get('id')}",
                "theme": "discovery",
                "setup": {
                    "city": input_data.get('location', {}).get('city', 'Paris'),
                    "area": input_data.get('location', {}).get('area', ''),
                    "meeting_point": "Central meeting point",
                    "duration_minutes": input_data.get('preferences', {}).get('duration_minutes', 45),
                    "num_players": input_data.get('preferences', {}).get('num_players', 4)
                },
                "rules": output.get('rules', []),
                "tasks": tasks_transformed,
                "global_hints": output.get('hints', [[]])[0] if output.get('hints') else [],
                "score_rules": ["Standard scoring"],
                "tie_breaker": "Most tasks completed",
                "safety": {
                    "allowed_zone": "Public area",
                    "forbidden_behaviors": [],
                    "adult_supervision": input_data.get('preferences', {}).get('age_group') == 'kids',
                    "stop_conditions": ["Emergency", "Weather"]
                },
                "story_seed": {
                    "tone": "playful",
                    "motifs": [],
                    "recap_style": "episode_recap"
                }
            }
            
            tested_count += 1
            is_valid, errors = validate_game_schema(game)
            
            if is_valid:
                valid_count += 1
                print(f"βœ“ {game['game_id']}: Valid")
            else:
                invalid_games.append({
                    'id': game['game_id'],
                    'errors': errors
                })
                print(f"βœ— {game['game_id']}: Invalid")
                for error in errors[:2]:  # Show first 2 errors
                    print(f"    {error}")
        
        except Exception as e:
            tested_count += 1
            print(f"βœ— {raw.get('id')}: Exception - {str(e)[:60]}")
    
    print(f"\nResults: {valid_count}/{tested_count} games valid")
    
    if invalid_games:
        print("\nInvalid games details:")
        for game_info in invalid_games:
            print(f"  {game_info['id']}: {game_info['errors']}")
    
    return valid_count == tested_count


def test_task_validation():
    """Test task-level validation."""
    print("\n" + "=" * 80)
    print("TASK VALIDATION TEST")
    print("=" * 80)
    
    test_cases = [
        {
            "name": "Valid task",
            "task": {
                "task_id": "t1",
                "title": "Find landmark",
                "description": "Locate and photograph the fountain",
                "location_hint": "Look in the central square",
                "points": 25,
                "time_limit_minutes": 15,
                "proof_type": "photo",
                "hint": "It's in the middle",
                "safety_note": "Stay on paths"
            },
            "expect_valid": True
        },
        {
            "name": "Invalid proof_type",
            "task": {
                "task_id": "t2",
                "title": "Task",
                "description": "Do something",
                "location_hint": "Somewhere",
                "points": 10,
                "time_limit_minutes": 5,
                "proof_type": "video",  # Invalid
                "hint": "Hint",
                "safety_note": "Safe"
            },
            "expect_valid": False
        },
        {
            "name": "Missing safety_note",
            "task": {
                "task_id": "t3",
                "title": "Task",
                "description": "Do something",
                "location_hint": "Somewhere",
                "points": 10,
                "time_limit_minutes": 5,
                "proof_type": "observation",
                "hint": "Hint"
                # Missing safety_note
            },
            "expect_valid": False
        }
    ]
    
    for test in test_cases:
        is_valid, errors = validate_task_structure(test['task'])
        status = "βœ“" if is_valid == test['expect_valid'] else "βœ—"
        print(f"{status} {test['name']}: {is_valid}")
        if errors:
            for error in errors[:1]:
                print(f"    {error}")


def test_safety_validation():
    """Test safety object validation."""
    print("\n" + "=" * 80)
    print("SAFETY VALIDATION TEST")
    print("=" * 80)
    
    valid_safety = {
        "allowed_zone": "Public park and streets",
        "forbidden_behaviors": [
            "Entering buildings",
            "Crossing roads unsafely"
        ],
        "adult_supervision": True,
        "stop_conditions": [
            "Injury",
            "Emergency"
        ]
    }
    
    is_valid, errors = validate_safety_structure(valid_safety)
    print(f"{'βœ“' if is_valid else 'βœ—'} Valid safety object: {is_valid}")
    if errors:
        for error in errors:
            print(f"    {error}")


def main():
    print("\nGAME SCHEMA AND VALIDATION TESTS\n")
    
    # Run all tests
    schema_ok = test_schema_structure()
    template_ok = test_minimal_template()
    dataset_ok = test_dataset_games()
    test_task_validation()
    test_safety_validation()
    
    # Summary
    print("\n" + "=" * 80)
    print("TEST SUMMARY")
    print("=" * 80)
    print(f"Schema structure: {'βœ“ PASS' if schema_ok else 'βœ— FAIL'}")
    print(f"Minimal template: {'βœ“ PASS' if template_ok else 'βœ— FAIL'}")
    print(f"Dataset games: {'βœ“ PASS' if dataset_ok else 'βœ— FAIL'}")
    print("\nSchema validation is ready for use in game generation and validation.")


if __name__ == "__main__":
    main()