""" 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()