Moved the Agents into their own repo. Kept the agent.pl just for reference
This commit is contained in:
parent
22381be29a
commit
8680a02b13
18132 changed files with 0 additions and 2569420 deletions
|
|
@ -1,259 +0,0 @@
|
|||
#!/usr/bin/env python3
|
||||
"""
|
||||
Server Admin Guide Validator
|
||||
|
||||
Validates generated server admin guides against quality gates and requirements.
|
||||
Ensures guides meet the "exhaustive" standard specified in the requirements.
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
import yaml
|
||||
import json
|
||||
from pathlib import Path
|
||||
import re
|
||||
|
||||
class GuideValidator:
|
||||
def __init__(self, docs_dir="docs/games", pdfs_dir="dist/pdfs", data_dir="data/games"):
|
||||
self.docs_dir = Path(docs_dir)
|
||||
self.pdfs_dir = Path(pdfs_dir)
|
||||
self.data_dir = Path(data_dir)
|
||||
self.errors = []
|
||||
self.warnings = []
|
||||
|
||||
def validate_all(self):
|
||||
"""Run all validation checks"""
|
||||
print("=== Server Admin Guide Validation ===\n")
|
||||
|
||||
self.validate_directory_structure()
|
||||
self.validate_yaml_data()
|
||||
self.validate_markdown_guides()
|
||||
self.validate_pdf_files()
|
||||
self.validate_manifest()
|
||||
self.validate_index_page()
|
||||
|
||||
return self.print_results()
|
||||
|
||||
def validate_directory_structure(self):
|
||||
"""Validate required directories exist"""
|
||||
print("Checking directory structure...")
|
||||
|
||||
required_dirs = [self.docs_dir, self.pdfs_dir, self.data_dir]
|
||||
for directory in required_dirs:
|
||||
if not directory.exists():
|
||||
self.errors.append(f"Required directory missing: {directory}")
|
||||
|
||||
required_files = [
|
||||
self.docs_dir / "_index.md",
|
||||
self.pdfs_dir / "manifest.json"
|
||||
]
|
||||
|
||||
for file_path in required_files:
|
||||
if not file_path.exists():
|
||||
self.errors.append(f"Required file missing: {file_path}")
|
||||
|
||||
print("✓ Directory structure validated\n")
|
||||
|
||||
def validate_yaml_data(self):
|
||||
"""Validate YAML game data meets exhaustive requirements"""
|
||||
print("Checking YAML game data...")
|
||||
|
||||
yaml_files = list(self.data_dir.glob("*.yml")) + list(self.data_dir.glob("*.yaml"))
|
||||
|
||||
for yaml_file in yaml_files:
|
||||
try:
|
||||
with open(yaml_file, 'r', encoding='utf-8') as f:
|
||||
game_data = yaml.safe_load(f)
|
||||
self.validate_single_game_yaml(game_data, yaml_file)
|
||||
except Exception as e:
|
||||
self.errors.append(f"Error reading {yaml_file}: {e}")
|
||||
|
||||
print("✓ YAML data validated\n")
|
||||
|
||||
def validate_single_game_yaml(self, game_data, filename):
|
||||
"""Validate individual game YAML meets requirements"""
|
||||
game_name = game_data.get('name', 'Unknown')
|
||||
|
||||
# Check required sections
|
||||
required_sections = ['name', 'supports_workshop', 'startup', 'configs', 'troubleshooting']
|
||||
for section in required_sections:
|
||||
if section not in game_data:
|
||||
self.errors.append(f"{filename}: Missing required section '{section}'")
|
||||
|
||||
# Validate startup parameters (minimum 10 flags)
|
||||
flags = game_data.get('startup', {}).get('flags', [])
|
||||
if len(flags) < 10:
|
||||
self.warnings.append(f"{game_name}: Only {len(flags)} startup flags (minimum 10 recommended)")
|
||||
|
||||
# Validate config files (minimum 8 entries)
|
||||
configs = game_data.get('configs', [])
|
||||
if len(configs) < 8:
|
||||
self.warnings.append(f"{game_name}: Only {len(configs)} config entries (minimum 8 recommended)")
|
||||
|
||||
# Validate port mapping
|
||||
ports = game_data.get('startup', {}).get('ports', [])
|
||||
if not ports:
|
||||
self.errors.append(f"{game_name}: No port mapping defined")
|
||||
else:
|
||||
for port in ports:
|
||||
required_port_fields = ['label', 'port', 'proto', 'relative']
|
||||
for field in required_port_fields:
|
||||
if field not in port:
|
||||
self.errors.append(f"{game_name}: Port entry missing '{field}' field")
|
||||
|
||||
def validate_markdown_guides(self):
|
||||
"""Validate generated Markdown guides"""
|
||||
print("Checking Markdown guides...")
|
||||
|
||||
required_sections = [
|
||||
"Quick Start",
|
||||
"Full Port Map",
|
||||
"Startup Parameters \\(EXHAUSTIVE\\)",
|
||||
"Configuration Files & Paths \\(ALL\\)",
|
||||
"Steam Workshop",
|
||||
"Player & Server Management",
|
||||
"Troubleshooting \\(Deep\\)",
|
||||
"Appendices"
|
||||
]
|
||||
|
||||
game_dirs = [d for d in self.docs_dir.iterdir() if d.is_dir()]
|
||||
|
||||
for game_dir in game_dirs:
|
||||
md_file = game_dir / "index.md"
|
||||
if not md_file.exists():
|
||||
self.errors.append(f"Missing Markdown file: {md_file}")
|
||||
continue
|
||||
|
||||
with open(md_file, 'r', encoding='utf-8') as f:
|
||||
content = f.read()
|
||||
|
||||
# Check for all required sections
|
||||
for section in required_sections:
|
||||
pattern = f"## {section}"
|
||||
if not re.search(pattern, content):
|
||||
self.errors.append(f"{md_file}: Missing required section '{section}'")
|
||||
|
||||
# Check for startup parameters table
|
||||
if "| Flag/Param | Default | Type/Range | Description | Example |" not in content:
|
||||
self.errors.append(f"{md_file}: Missing startup parameters table")
|
||||
|
||||
# Check for port mapping table
|
||||
if "| Feature | Port | Protocol | Relation | Notes |" not in content:
|
||||
self.errors.append(f"{md_file}: Missing port mapping table")
|
||||
|
||||
# Check for no TBD or placeholder content
|
||||
placeholders = ["TBD", "TODO", "coming soon", "placeholder"]
|
||||
for placeholder in placeholders:
|
||||
if placeholder.lower() in content.lower():
|
||||
self.warnings.append(f"{md_file}: Contains placeholder text '{placeholder}'")
|
||||
|
||||
print("✓ Markdown guides validated\n")
|
||||
|
||||
def validate_pdf_files(self):
|
||||
"""Validate PDF files exist and have reasonable size"""
|
||||
print("Checking PDF files...")
|
||||
|
||||
game_dirs = [d for d in self.docs_dir.iterdir() if d.is_dir()]
|
||||
|
||||
for game_dir in game_dirs:
|
||||
slug = game_dir.name
|
||||
pdf_file = self.pdfs_dir / f"{slug}__Server_Admin_Guide_v1.pdf"
|
||||
|
||||
if not pdf_file.exists():
|
||||
self.errors.append(f"Missing PDF file: {pdf_file}")
|
||||
continue
|
||||
|
||||
# Check file size (should be at least 20KB for a comprehensive guide)
|
||||
file_size = pdf_file.stat().st_size
|
||||
if file_size < 20480: # 20KB
|
||||
self.warnings.append(f"{pdf_file}: Small file size ({file_size} bytes) - may indicate incomplete content")
|
||||
|
||||
print("✓ PDF files validated\n")
|
||||
|
||||
def validate_manifest(self):
|
||||
"""Validate manifest.json structure and content"""
|
||||
print("Checking manifest...")
|
||||
|
||||
manifest_file = self.pdfs_dir / "manifest.json"
|
||||
if not manifest_file.exists():
|
||||
self.errors.append("Missing manifest.json file")
|
||||
return
|
||||
|
||||
try:
|
||||
with open(manifest_file, 'r', encoding='utf-8') as f:
|
||||
manifest = json.load(f)
|
||||
|
||||
# Check required fields
|
||||
required_fields = ["generated", "total_games", "games"]
|
||||
for field in required_fields:
|
||||
if field not in manifest:
|
||||
self.errors.append(f"Manifest missing required field: {field}")
|
||||
|
||||
# Validate games entries
|
||||
if "games" in manifest:
|
||||
for game in manifest["games"]:
|
||||
required_game_fields = ["title", "slug", "appid", "engine", "workshop_support", "ports", "config_files", "last_updated", "markdown_path", "pdf_path"]
|
||||
for field in required_game_fields:
|
||||
if field not in game:
|
||||
self.errors.append(f"Manifest game entry missing field: {field}")
|
||||
|
||||
except json.JSONDecodeError as e:
|
||||
self.errors.append(f"Invalid JSON in manifest: {e}")
|
||||
|
||||
print("✓ Manifest validated\n")
|
||||
|
||||
def validate_index_page(self):
|
||||
"""Validate index page content"""
|
||||
print("Checking index page...")
|
||||
|
||||
index_file = self.docs_dir / "_index.md"
|
||||
if not index_file.exists():
|
||||
self.errors.append("Missing index page")
|
||||
return
|
||||
|
||||
with open(index_file, 'r', encoding='utf-8') as f:
|
||||
content = f.read()
|
||||
|
||||
# Check for required sections
|
||||
required_content = [
|
||||
"# Game Server Admin Guides",
|
||||
"## Available Guides",
|
||||
"| Game | Engine | Workshop | AppID | Documentation | PDF Guide |",
|
||||
"## Statistics"
|
||||
]
|
||||
|
||||
for required in required_content:
|
||||
if required not in content:
|
||||
self.errors.append(f"Index page missing required content: {required}")
|
||||
|
||||
print("✓ Index page validated\n")
|
||||
|
||||
def print_results(self):
|
||||
"""Print validation results"""
|
||||
print("=== Validation Results ===\n")
|
||||
|
||||
if self.errors:
|
||||
print(f"❌ ERRORS ({len(self.errors)}):")
|
||||
for error in self.errors:
|
||||
print(f" • {error}")
|
||||
print()
|
||||
|
||||
if self.warnings:
|
||||
print(f"⚠️ WARNINGS ({len(self.warnings)}):")
|
||||
for warning in self.warnings:
|
||||
print(f" • {warning}")
|
||||
print()
|
||||
|
||||
if not self.errors and not self.warnings:
|
||||
print("✅ All validation checks passed!")
|
||||
elif not self.errors:
|
||||
print("✅ No critical errors found (warnings can be addressed)")
|
||||
else:
|
||||
print(f"❌ Validation failed with {len(self.errors)} errors")
|
||||
|
||||
return len(self.errors) == 0
|
||||
|
||||
if __name__ == "__main__":
|
||||
validator = GuideValidator()
|
||||
success = validator.validate_all()
|
||||
sys.exit(0 if success else 1)
|
||||
Loading…
Add table
Add a link
Reference in a new issue