/** * AI Town — Relationship Graph Visualization * ============================================= * Shows connections between characters with sentiment colors. */ import React from "react"; import { View, Text, ScrollView } from "react-native"; import { Canvas, Circle, Line, vec } from "@shopify/react-native-skia"; interface Relationship { fromCharacterId: string; toCharacterId: string; sentiment: number; trust: number; interactionCount: number; relationshipType: string; } interface Character { _id: string; name: string; avatar: string; mood: string; } interface RelationshipGraphProps { characters: Character[]; relationships: Relationship[]; } export function RelationshipGraph({ characters, relationships }: RelationshipGraphProps) { if (characters.length === 0) { return ( No characters yet ); } // Arrange characters in a circle const centerX = 160; const centerY = 160; const radius = 120; const positions = characters.map((_, i) => { const angle = (i / characters.length) * Math.PI * 2 - Math.PI / 2; return { x: centerX + Math.cos(angle) * radius, y: centerY + Math.sin(angle) * radius, }; }); return ( 🕸️ Relationship Web {/* Draw relationship edges */} {relationships.map((rel, i) => { const fromIdx = characters.findIndex((c) => c._id === rel.fromCharacterId); const toIdx = characters.findIndex((c) => c._id === rel.toCharacterId); if (fromIdx === -1 || toIdx === -1) return null; const color = rel.sentiment > 0.5 ? "#22c55e" : rel.sentiment > 0 ? "#60a5fa" : rel.sentiment > -0.3 ? "#f59e0b" : "#ef4444"; const opacity = Math.min(1, Math.abs(rel.sentiment) + 0.3); return ( ); })} {/* Draw character nodes */} {positions.map((pos, i) => ( ))} {positions.map((pos, i) => ( ))} {/* Character labels */} {characters.map((char, i) => ( {char.avatar} {char.name} ))} {/* Legend */} Close Friendly Neutral Tense ); }