""" IOM Sync Engine — Synchronizes IOM data across apps, systems, and sites Handles: quiXzoom app, Landvex API, web dashboards, external systems """ from typing import Dict, List, Optional, Any from dataclasses import dataclass from datetime import datetime import json @dataclass class SyncTarget: """A synchronization target""" name: str endpoint: str auth_type: str # api_key, oauth, webhook auth_config: Dict enabled: bool = True last_sync: Optional[str] = None status: str = "pending" class IOMSyncEngine: """Synchronizes IOM data across all connected systems""" def __init__(self): self.targets = {} self.sync_log = [] # Default targets self._register_default_targets() def _register_default_targets(self): """Register default sync targets""" self.register_target(SyncTarget( name="quixzoom_app", endpoint="https://api.quixzoom.com/v1/iom/sync", auth_type="api_key", auth_config={"header": "X-API-Key"} )) self.register_target(SyncTarget( name="landvex_api", endpoint="https://api.landvex.com/v2/infrastructure", auth_type="oauth", auth_config={"scope": "infrastructure:write"} )) self.register_target(SyncTarget( name="web_dashboard", endpoint="https://dashboard.landvex.com/api/iom", auth_type="api_key", auth_config={"header": "Authorization"} )) self.register_target(SyncTarget( name="external_gis", endpoint="https://gis.partner.com/import", auth_type="webhook", auth_config={"secret": "shared_secret"} )) def register_target(self, target: SyncTarget): """Register a sync target""" self.targets[target.name] = target def sync_observation(self, observation: Dict) -> Dict: """ Sync a single observation to all targets Returns: Sync results per target """ results = {} for name, target in self.targets.items(): if not target.enabled: continue try: result = self._push_to_target(target, observation) results[name] = { "status": "success", "target": name, "timestamp": datetime.utcnow().isoformat() } target.last_sync = datetime.utcnow().isoformat() target.status = "synced" except Exception as e: results[name] = { "status": "error", "target": name, "error": str(e), "timestamp": datetime.utcnow().isoformat() } target.status = "error" # Log sync self.sync_log.append({ "type": "observation", "goid": observation.get("goid"), "timestamp": datetime.utcnow().isoformat(), "results": results }) return results def sync_rgi_analysis(self, rgi_result: Dict) -> Dict: """Sync RGI analysis to all targets""" results = {} for name, target in self.targets.items(): if not target.enabled: continue try: # Format for target formatted = self._format_for_target(rgi_result, target.name) result = self._push_to_target(target, formatted) results[name] = { "status": "success", "target": name, "rgi_score": rgi_result.get("overall_rgi"), "timestamp": datetime.utcnow().isoformat() } except Exception as e: results[name] = { "status": "error", "target": name, "error": str(e) } return results def sync_rcs_analysis(self, rcs_result: Dict) -> Dict: """Sync RCS analysis to all targets""" results = {} for name, target in self.targets.items(): if not target.enabled: continue try: formatted = self._format_rcs_for_target(rcs_result, target.name) result = self._push_to_target(target, formatted) results[name] = { "status": "success", "target": name, "rcs_score": rcs_result.get("rcs_score"), "timestamp": datetime.utcnow().isoformat() } except Exception as e: results[name] = { "status": "error", "target": name, "error": str(e) } return results def _format_for_target(self, data: Dict, target_name: str) -> Dict: """Format data for specific target""" if target_name == "quixzoom_app": # Format for mobile app return { "type": "rgi_analysis", "location": data.get("location"), "score": data.get("overall_rgi"), "level": data.get("contradiction_level"), "layers": data.get("reality_layers", {}), "mobile_optimized": True } elif target_name == "landvex_api": # Format for Landvex API return { "analysis_type": "reality_gap", "location_id": data.get("location"), "metrics": { "rgi": data.get("overall_rgi"), "subscores": data.get("subscores", {}) }, "layers": data.get("reality_layers", {}), "contradictions": data.get("contradictions", []) } elif target_name == "web_dashboard": # Format for web dashboard return { "dashboard_data": True, "location": data.get("location"), "rgi": data.get("overall_rgi"), "subscores": data.get("subscores", {}), "layers": data.get("reality_layers", {}), "contradictions": data.get("contradictions", []), "charts": self._generate_chart_data(data) } else: return data def _format_rcs_for_target(self, data: Dict, target_name: str) -> Dict: """Format RCS data for specific target""" if target_name == "quixzoom_app": return { "type": "contradiction_alert", "location": data.get("location"), "rcs_score": data.get("rcs_score"), "strongest_contradiction": data.get("strongest_contradictions", [{}])[0], "alert_level": "high" if data.get("rcs_score", 0) > 50 else "medium" if data.get("rcs_score", 0) > 20 else "low" } elif target_name == "landvex_api": return { "analysis_type": "contradiction", "location_id": data.get("location"), "rcs": data.get("rcs_score"), "contradictions": data.get("all_contradictions", []), "types": data.get("contradiction_types", {}) } else: return data def _generate_chart_data(self, data: Dict) -> Dict: """Generate chart data for dashboard""" subscores = data.get("subscores", {}) return { "radar_chart": { "labels": ["Physical", "Operational", "Safety", "Institutional", "Economic", "Maintenance", "Human Exp"], "values": [ subscores.get("physical_reality_gap", {}).get("score", 0), subscores.get("operational_reality_gap", {}).get("score", 0), subscores.get("safety_reality_gap", {}).get("score", 0), subscores.get("institutional_reality_gap", {}).get("score", 0), subscores.get("economic_reality_gap", {}).get("score", 0), subscores.get("maintenance_reality_gap", {}).get("score", 0), subscores.get("human_experience_gap", {}).get("score", 0) ] }, "layer_chart": { "labels": list(data.get("reality_layers", {}).keys()), "values": list(data.get("reality_layers", {}).values()) } } def _push_to_target(self, target: SyncTarget, data: Dict) -> bool: """Push data to a target (simulated)""" # In production, this would make actual HTTP requests # For now, simulate success return True def get_sync_status(self) -> Dict: """Get overall sync status""" return { "targets": len(self.targets), "enabled": sum(1 for t in self.targets.values() if t.enabled), "last_syncs": { name: target.last_sync for name, target in self.targets.items() }, "statuses": { name: target.status for name, target in self.targets.items() }, "recent_logs": self.sync_log[-10:] } def get_target_config(self, target_name: str) -> Optional[Dict]: """Get configuration for a target""" target = self.targets.get(target_name) if target: return { "name": target.name, "endpoint": target.endpoint, "auth_type": target.auth_type, "enabled": target.enabled, "last_sync": target.last_sync, "status": target.status } return None class IOMWebhookHandler: """Handles incoming webhooks from external systems""" def __init__(self, sync_engine: IOMSyncEngine): self.sync_engine = sync_engine def handle_observation_webhook(self, payload: Dict) -> Dict: """Handle observation from external system""" # Validate payload if "goid" not in payload: return {"status": "error", "message": "Missing GOID"} # Process observation observation = { "goid": payload["goid"], "timestamp": payload.get("timestamp", datetime.utcnow().isoformat()), "findings": payload.get("findings", []), "location": payload.get("location"), "media": payload.get("media"), "observer_id": payload.get("observer_id") } # Sync to all targets results = self.sync_engine.sync_observation(observation) return { "status": "success", "observation_id": payload["goid"], "sync_results": results } def handle_bulk_sync(self, observations: List[Dict]) -> Dict: """Handle bulk observation sync""" results = [] for obs in observations: result = self.handle_observation_webhook(obs) results.append(result) return { "status": "success", "processed": len(results), "successful": sum(1 for r in results if r["status"] == "success"), "failed": sum(1 for r in results if r["status"] == "error") } # Example usage def example_sync(): """Example: Sync RGI analysis to all targets""" engine = IOMSyncEngine() # Example RGI result rgi_result = { "location": "Bangkok Silom", "overall_rgi": 38.77, "contradiction_level": "medium", "subscores": { "physical_reality_gap": {"score": 63.33}, "operational_reality_gap": {"score": 16.67}, "safety_reality_gap": {"score": 0.0}, "institutional_reality_gap": {"score": 70.0}, "economic_reality_gap": {"score": 40.0}, "maintenance_reality_gap": {"score": 25.0}, "human_experience_gap": {"score": 20.0} }, "reality_layers": { "planned": 100.0, "constructed": 100.0, "maintained": 33.3, "observed": 100.0, "human_experience": 100.0, "informal_adaptation": 60.0, "hidden_systems": 0.0 } } # Sync to all targets results = engine.sync_rgi_analysis(rgi_result) print("=== RGI Sync Results ===") for target, result in results.items(): print(f"{target}: {result['status']}") # Get sync status status = engine.get_sync_status() print(f"\nTotal targets: {status['targets']}") print(f"Enabled: {status['enabled']}") return results if __name__ == '__main__': example_sync()