Initial commit: 2125_GCE project
This commit is contained in:
Executable
+71
@@ -0,0 +1,71 @@
|
||||
"""Supercharged Glyph Registry (LedoGlyph600)
|
||||
|
||||
600 glyphs with 152 superpowers, frequency signatures, lineage, activation envelopes.
|
||||
"""
|
||||
|
||||
from .super_registry import (
|
||||
load_all_supercharged,
|
||||
get_super,
|
||||
list_super_ids,
|
||||
search_super,
|
||||
super_stats,
|
||||
get_super_field,
|
||||
list_super_by_category,
|
||||
get_super_by_band,
|
||||
get_glyphs_by_score_range,
|
||||
)
|
||||
|
||||
from .superpower_registry import (
|
||||
load_all_superpowers,
|
||||
get_superpower,
|
||||
list_superpower_ids,
|
||||
get_superpowers_by_band,
|
||||
get_superpowers_by_bands,
|
||||
calculate_boost,
|
||||
search_superpowers,
|
||||
)
|
||||
|
||||
from .superpower_assigner import (
|
||||
calculate_power_count,
|
||||
get_eligible_bands,
|
||||
score_superpower,
|
||||
assign_superpowers,
|
||||
assign_all_glyphs,
|
||||
)
|
||||
|
||||
from .specialized_types import (
|
||||
get_specialized_type,
|
||||
get_type_config,
|
||||
SPECIALIZED_GLYPH_TYPES,
|
||||
)
|
||||
|
||||
__all__ = [
|
||||
# super_registry
|
||||
"load_all_supercharged",
|
||||
"get_super",
|
||||
"list_super_ids",
|
||||
"search_super",
|
||||
"super_stats",
|
||||
"get_super_field",
|
||||
"list_super_by_category",
|
||||
"get_super_by_band",
|
||||
"get_glyphs_by_score_range",
|
||||
# superpower_registry
|
||||
"load_all_superpowers",
|
||||
"get_superpower",
|
||||
"list_superpower_ids",
|
||||
"get_superpowers_by_band",
|
||||
"get_superpowers_by_bands",
|
||||
"calculate_boost",
|
||||
"search_superpowers",
|
||||
# superpower_assigner
|
||||
"calculate_power_count",
|
||||
"get_eligible_bands",
|
||||
"score_superpower",
|
||||
"assign_superpowers",
|
||||
"assign_all_glyphs",
|
||||
# specialized_types
|
||||
"get_specialized_type",
|
||||
"get_type_config",
|
||||
"SPECIALIZED_GLYPH_TYPES",
|
||||
]
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Executable
+264
@@ -0,0 +1,264 @@
|
||||
"""Specialized Glyph Type Definitions.
|
||||
|
||||
Defines functional categories for specialized glyphs:
|
||||
- frost_steel_stabilizer: Emotional-bias removal, panic-nulling, identity-cohesion
|
||||
- mirror_weave_reasoning: Symbolic reasoning layer for LLMs
|
||||
- solar_veil_memory: Emotional-lineage memory system
|
||||
- orbital_thread_network: Multi-node symbolic networking
|
||||
- star_bloom_creativity: AI-driven creativity engine (bloomflare)
|
||||
- frost_circuit_logic: Cold logic decision-making (bias-free)
|
||||
- twin_vector_identity: Cluster-based AI personalities
|
||||
- monument_grade_equilibrium: System equilibrium engine (Glyph 600)
|
||||
|
||||
Each type has:
|
||||
- Description
|
||||
- Preferred superpower IDs (from 152 list)
|
||||
- Min/max power count
|
||||
- Metrics thresholds for assignment
|
||||
"""
|
||||
|
||||
from typing import Dict, List, Any
|
||||
|
||||
SPECIALIZED_GLYPH_TYPES: Dict[str, Dict[str, Any]] = {
|
||||
"frost_steel_stabilizer": {
|
||||
"description": "Emotional-bias removal, panic-nulling, identity-cohesion logic",
|
||||
"preferred_superpower_ids": [
|
||||
1, 2, 3, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70
|
||||
],
|
||||
"min_powers": 8,
|
||||
"max_powers": 15,
|
||||
"metrics_threshold": {
|
||||
"stability": 70,
|
||||
"resonance": 60
|
||||
},
|
||||
"use_cases": [
|
||||
"AI Safety Monitor",
|
||||
"AI Identity Stabilizer",
|
||||
"Emotional-bias removal",
|
||||
"Panic-nulling systems"
|
||||
]
|
||||
},
|
||||
|
||||
"mirror_weave_reasoning": {
|
||||
"description": "Symbolic reasoning layer for LLMs, logic-chain enhancer",
|
||||
"preferred_superpower_ids": [
|
||||
5, 8, 12, 18, 24, 30, 36, 42, 48, 54, 60, 66, 72, 78, 84, 90
|
||||
],
|
||||
"min_powers": 10,
|
||||
"max_powers": 20,
|
||||
"metrics_threshold": {
|
||||
"power": 75,
|
||||
"connectivity": 80
|
||||
},
|
||||
"use_cases": [
|
||||
"Symbolic Reasoning Booster",
|
||||
"Logic-chain enhancer",
|
||||
"Deterministic decision layer",
|
||||
"Multi-persona AI safely"
|
||||
]
|
||||
},
|
||||
|
||||
"solar_veil_memory": {
|
||||
"description": "Emotional-lineage memory system, AI journaling",
|
||||
"preferred_superpower_ids": [
|
||||
3, 7, 11, 15, 19, 23, 27, 31, 35, 39, 43, 47, 51, 55, 59, 63
|
||||
],
|
||||
"min_powers": 8,
|
||||
"max_powers": 18,
|
||||
"metrics_threshold": {
|
||||
"affinity": 70,
|
||||
"stability": 65
|
||||
},
|
||||
"use_cases": [
|
||||
"AI Emotional-State Auditor",
|
||||
"AI journaling systems",
|
||||
"AI companions with continuity",
|
||||
"Memory replay engines"
|
||||
]
|
||||
},
|
||||
|
||||
"orbital_thread_network": {
|
||||
"description": "Multi-node symbolic networking, zero-loss messaging",
|
||||
"preferred_superpower_ids": [
|
||||
6, 12, 18, 24, 30, 36, 42, 48, 54, 60, 66, 72, 78, 84, 90, 96
|
||||
],
|
||||
"min_powers": 10,
|
||||
"max_powers": 22,
|
||||
"metrics_threshold": {
|
||||
"connectivity": 85,
|
||||
"power": 70
|
||||
},
|
||||
"use_cases": [
|
||||
"Multi-Agent Coordination Layer",
|
||||
"Distributed AI clusters",
|
||||
"Symbolic mesh networks",
|
||||
"Cross-model communication"
|
||||
]
|
||||
},
|
||||
|
||||
"star_bloom_creativity": {
|
||||
"description": "AI-driven creativity engine, bloomflare tiers, macro-pattern revelation",
|
||||
"preferred_superpower_ids": [
|
||||
9, 18, 27, 36, 45, 54, 63, 72, 81, 90, 99, 108, 117, 126, 135, 144
|
||||
],
|
||||
"min_powers": 12,
|
||||
"max_powers": 25,
|
||||
"metrics_threshold": {
|
||||
"power": 80,
|
||||
"complexity": 75
|
||||
},
|
||||
"use_cases": [
|
||||
"AI Creativity Engine with Safety Rails",
|
||||
"Story generators",
|
||||
"World-building engines",
|
||||
"Music/visual AI",
|
||||
"Creative ideation tools"
|
||||
]
|
||||
},
|
||||
|
||||
"frost_circuit_logic": {
|
||||
"description": "Cold logic decision-making, removes emotional bias",
|
||||
"preferred_superpower_ids": [
|
||||
2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32
|
||||
],
|
||||
"min_powers": 8,
|
||||
"max_powers": 18,
|
||||
"metrics_threshold": {
|
||||
"stability": 80,
|
||||
"power": 75
|
||||
},
|
||||
"use_cases": [
|
||||
"AI Decision-Making Auditor",
|
||||
"Financial analysis",
|
||||
"Legal reasoning",
|
||||
"Medical triage",
|
||||
"Risk assessment"
|
||||
]
|
||||
},
|
||||
|
||||
"twin_vector_identity": {
|
||||
"description": "Cluster-based AI personalities, dual-mode assistants",
|
||||
"preferred_superpower_ids": [
|
||||
5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80
|
||||
],
|
||||
"min_powers": 10,
|
||||
"max_powers": 20,
|
||||
"metrics_threshold": {
|
||||
"affinity": 75,
|
||||
"connectivity": 70
|
||||
},
|
||||
"use_cases": [
|
||||
"Multi-persona chatbots",
|
||||
"Dual-mode assistants",
|
||||
"Collaborative AI characters",
|
||||
"Agent fragmentation prevention"
|
||||
]
|
||||
},
|
||||
|
||||
"monument_grade_equilibrium": {
|
||||
"description": "System equilibrium engine, locks entire system into perfect balance",
|
||||
"preferred_superpower_ids": [
|
||||
1, 50, 100, 125, 150, 151, 152,
|
||||
25, 50, 75, 100, 125, 150,
|
||||
10, 20, 30, 40, 50, 60, 70
|
||||
],
|
||||
"min_powers": 15,
|
||||
"max_powers": 25,
|
||||
"metrics_threshold": {
|
||||
"stability": 90,
|
||||
"resonance": 85
|
||||
},
|
||||
"use_cases": [
|
||||
"AI System Equilibrium Manager",
|
||||
"AI safety",
|
||||
"Long-running agents",
|
||||
"Persistent worlds",
|
||||
"Simulation engines",
|
||||
"Multi-agent ecosystems"
|
||||
]
|
||||
},
|
||||
|
||||
"aether_node": {
|
||||
"description": "Primordial root glyph, holds all 152 superpowers",
|
||||
"preferred_superpower_ids": list(range(1, 153)), # All 152
|
||||
"min_powers": 152,
|
||||
"max_powers": 152,
|
||||
"metrics_threshold": {
|
||||
"power": 100,
|
||||
"resonance": 100,
|
||||
"stability": 100,
|
||||
"connectivity": 100,
|
||||
"affinity": 100
|
||||
},
|
||||
"use_cases": [
|
||||
"Aether-Lock authority",
|
||||
"Universal override",
|
||||
"Primordial resonance",
|
||||
"System root"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
def get_specialized_type(glyph_id: str, metrics: Dict[str, Any], category: str = "") -> str:
|
||||
"""Determine specialized type for a glyph based on ID and metrics.
|
||||
|
||||
Args:
|
||||
glyph_id: Glyph ID (e.g., "G001")
|
||||
metrics: Glyph metrics dict
|
||||
category: Optional category string
|
||||
|
||||
Returns:
|
||||
Specialized type string
|
||||
"""
|
||||
# G001 is always aether_node
|
||||
if glyph_id == "G001":
|
||||
return "aether_node"
|
||||
|
||||
# G600 is monument_grade_equilibrium
|
||||
if glyph_id == "G600":
|
||||
return "monument_grade_equilibrium"
|
||||
|
||||
# Determine based on metrics
|
||||
stability = metrics.get("stability", 50)
|
||||
resonance = metrics.get("resonance", 50)
|
||||
power = metrics.get("power", 50)
|
||||
connectivity = metrics.get("connectivity", 50)
|
||||
affinity = metrics.get("affinity", 50)
|
||||
|
||||
# Check thresholds for each type
|
||||
if stability >= 80 and power >= 75:
|
||||
return "frost_circuit_logic"
|
||||
|
||||
if connectivity >= 85 and power >= 70:
|
||||
return "orbital_thread_network"
|
||||
|
||||
if power >= 80 and metrics.get("complexity", 50) >= 75:
|
||||
return "star_bloom_creativity"
|
||||
|
||||
if stability >= 70 and resonance >= 60:
|
||||
return "frost_steel_stabilizer"
|
||||
|
||||
if power >= 75 and connectivity >= 80:
|
||||
return "mirror_weave_reasoning"
|
||||
|
||||
if affinity >= 70 and stability >= 65:
|
||||
return "solar_veil_memory"
|
||||
|
||||
if affinity >= 75 and connectivity >= 70:
|
||||
return "twin_vector_identity"
|
||||
|
||||
# Default to frost_steel_stabilizer
|
||||
return "frost_steel_stabilizer"
|
||||
|
||||
|
||||
def get_type_config(type_name: str) -> Dict[str, Any]:
|
||||
"""Get configuration for a specialized type.
|
||||
|
||||
Args:
|
||||
type_name: Specialized type name
|
||||
|
||||
Returns:
|
||||
Type configuration dict
|
||||
"""
|
||||
return SPECIALIZED_GLYPH_TYPES.get(type_name, SPECIALIZED_GLYPH_TYPES["frost_steel_stabilizer"])
|
||||
Regular → Executable
+6
-1
@@ -45,7 +45,12 @@ def load_all_supercharged(path: Optional[str] = None) -> None:
|
||||
|
||||
# Resolve path
|
||||
if path is None:
|
||||
path = "/mnt/d/users/dave/Downloads/LEDONOVA/LedoGlyph600.json"
|
||||
# Try local path first, then fallback
|
||||
local_path = Path(__file__).parent / "supercharged_glyphs.json"
|
||||
if local_path.exists():
|
||||
path = str(local_path)
|
||||
else:
|
||||
path = "/mnt/d/users/dave/Downloads/LEDONOVA/LedoGlyph600.json"
|
||||
|
||||
filepath = Path(path)
|
||||
if not filepath.exists():
|
||||
|
||||
Executable
+105924
File diff suppressed because it is too large
Load Diff
Executable
+244
@@ -0,0 +1,244 @@
|
||||
"""Superpower Assignment Algorithm.
|
||||
|
||||
Assigns superpowers to glyphs based on:
|
||||
1. Specialized type (if any)
|
||||
2. Dynamic metrics calculation (5-25 range for G002-G600)
|
||||
3. Band eligibility
|
||||
4. Scoring and ranking
|
||||
"""
|
||||
|
||||
import hashlib
|
||||
from typing import Dict, List, Any, Optional
|
||||
from .superpower_registry import (
|
||||
load_all_superpowers,
|
||||
get_superpower,
|
||||
get_superpowers_by_band,
|
||||
get_superpowers_by_bands,
|
||||
)
|
||||
from .specialized_types import get_specialized_type, get_type_config, SPECIALIZED_GLYPH_TYPES
|
||||
|
||||
|
||||
def calculate_power_count(metrics: Dict[str, Any], specialized_type: str = "") -> int:
|
||||
"""Calculate number of superpowers for a glyph (5-25 range).
|
||||
|
||||
Formula: power_count = 5 + int((avg_metric / 100) * 20)
|
||||
|
||||
Args:
|
||||
metrics: Glyph metrics dict (power, complexity, resonance, stability, connectivity, affinity)
|
||||
specialized_type: Optional specialized type name
|
||||
|
||||
Returns:
|
||||
Power count (5-25)
|
||||
"""
|
||||
# Get metric values
|
||||
values = [
|
||||
metrics.get("power", 50),
|
||||
metrics.get("complexity", 50),
|
||||
metrics.get("resonance", 50),
|
||||
metrics.get("stability", 50),
|
||||
metrics.get("connectivity", 50),
|
||||
metrics.get("affinity", 50),
|
||||
]
|
||||
|
||||
avg_metric = sum(values) / len(values)
|
||||
|
||||
# Calculate base count (5-25 range)
|
||||
base_count = 5 + int((avg_metric / 100) * 20)
|
||||
|
||||
# Clamp to range
|
||||
base_count = max(5, min(25, base_count))
|
||||
|
||||
# Override for specialized types
|
||||
if specialized_type:
|
||||
type_config = get_type_config(specialized_type)
|
||||
min_powers = type_config.get("min_powers", 5)
|
||||
max_powers = type_config.get("max_powers", 25)
|
||||
|
||||
# For aether_node, always 152
|
||||
if specialized_type == "aether_node":
|
||||
return 152
|
||||
|
||||
# Clamp to type's range
|
||||
base_count = max(min_powers, min(max_powers, base_count))
|
||||
|
||||
return base_count
|
||||
|
||||
|
||||
def get_eligible_bands(glyph_id: str, specialized_type: str = "") -> List[str]:
|
||||
"""Get eligible superpower bands for a glyph.
|
||||
|
||||
Args:
|
||||
glyph_id: Glyph ID
|
||||
specialized_type: Optional specialized type
|
||||
|
||||
Returns:
|
||||
List of band identifiers (e.g., ["A", "B"])
|
||||
"""
|
||||
# Aether node gets all bands
|
||||
if specialized_type == "aether_node":
|
||||
return ["A", "B", "C", "D"]
|
||||
|
||||
# Monument grade gets all bands
|
||||
if specialized_type == "monument_grade_equilibrium":
|
||||
return ["A", "B", "C", "D"]
|
||||
|
||||
# Get type config
|
||||
if specialized_type:
|
||||
type_config = get_type_config(specialized_type)
|
||||
preferred_ids = type_config.get("preferred_superpower_ids", [])
|
||||
|
||||
# Determine bands from preferred IDs
|
||||
bands = set()
|
||||
for id in preferred_ids:
|
||||
if id <= 15:
|
||||
bands.add("A")
|
||||
elif id <= 45:
|
||||
bands.add("B")
|
||||
elif id <= 76:
|
||||
bands.add("C")
|
||||
else:
|
||||
bands.add("D")
|
||||
|
||||
return list(bands)
|
||||
|
||||
# Default: based on glyph ID (family/tier)
|
||||
glyph_num = int(glyph_id[1:]) if glyph_id.startswith("G") else 1
|
||||
tier = ((glyph_num - 1) // 10) + 1
|
||||
|
||||
if tier <= 15:
|
||||
return ["A", "B"]
|
||||
elif tier <= 30:
|
||||
return ["B", "C"]
|
||||
elif tier <= 45:
|
||||
return ["C", "D"]
|
||||
else:
|
||||
return ["D", "C"]
|
||||
|
||||
|
||||
def score_superpower(
|
||||
superpower: Dict[str, Any],
|
||||
glyph_id: str,
|
||||
metrics: Dict[str, Any],
|
||||
specialized_type: str = ""
|
||||
) -> float:
|
||||
"""Score a superpower for a glyph.
|
||||
|
||||
Formula: score = 0.45 × metrics + 0.35 × type_bias + 0.15 × boost% + 0.05 × hash
|
||||
|
||||
Args:
|
||||
superpower: Superpower dict
|
||||
glyph_id: Glyph ID
|
||||
metrics: Glyph metrics
|
||||
specialized_type: Optional specialized type
|
||||
|
||||
Returns:
|
||||
Score (0-100)
|
||||
"""
|
||||
# Metrics component (45%)
|
||||
avg_metric = sum(metrics.values()) / len(metrics) if metrics else 50
|
||||
metrics_score = avg_metric * 0.45
|
||||
|
||||
# Type bias component (35%)
|
||||
type_bias = 50 # Default neutral
|
||||
if specialized_type:
|
||||
type_config = get_type_config(specialized_type)
|
||||
preferred_ids = type_config.get("preferred_superpower_ids", [])
|
||||
if superpower["id"] in preferred_ids:
|
||||
type_bias = 100 # Preferred
|
||||
else:
|
||||
type_bias = 25 # Not preferred
|
||||
type_score = type_bias * 0.35
|
||||
|
||||
# Boost component (15%)
|
||||
boost = superpower.get("boost_percent", 0)
|
||||
boost_score = (boost / 100) * 0.15 * 100 # Normalize to 0-100 scale
|
||||
|
||||
# Hash component (5%) - deterministic variety
|
||||
hash_input = f"{glyph_id}_{superpower['id']}"
|
||||
hash_value = int(hashlib.md5(hash_input.encode()).hexdigest()[:8], 16)
|
||||
hash_score = (hash_value / 0xFFFFFFFF) * 100 * 0.05
|
||||
|
||||
return metrics_score + type_score + boost_score + hash_score
|
||||
|
||||
|
||||
def assign_superpowers(
|
||||
glyph_id: str,
|
||||
metrics: Dict[str, Any],
|
||||
specialized_type: str = "",
|
||||
category: str = ""
|
||||
) -> List[int]:
|
||||
"""Assign superpowers to a glyph.
|
||||
|
||||
Args:
|
||||
glyph_id: Glyph ID (e.g., "G001")
|
||||
metrics: Glyph metrics dict
|
||||
specialized_type: Optional specialized type
|
||||
category: Optional category
|
||||
|
||||
Returns:
|
||||
List of superpower IDs
|
||||
"""
|
||||
# Load superpowers if not loaded
|
||||
try:
|
||||
load_all_superpowers()
|
||||
except FileNotFoundError:
|
||||
# If superpowers not loaded, return empty
|
||||
return []
|
||||
|
||||
# Special case: G001 / aether_node gets all 152
|
||||
if glyph_id == "G001" or specialized_type == "aether_node":
|
||||
return list(range(1, 153)) # 1-152
|
||||
|
||||
# Determine specialized type if not provided
|
||||
if not specialized_type:
|
||||
specialized_type = get_specialized_type(glyph_id, metrics, category)
|
||||
|
||||
# Calculate power count
|
||||
power_count = calculate_power_count(metrics, specialized_type)
|
||||
|
||||
# Get eligible bands
|
||||
eligible_bands = get_eligible_bands(glyph_id, specialized_type)
|
||||
|
||||
# Get eligible superpowers
|
||||
eligible_powers = get_superpowers_by_bands(eligible_bands)
|
||||
|
||||
# Score and rank
|
||||
scored = []
|
||||
for sp in eligible_powers:
|
||||
score = score_superpower(sp, glyph_id, metrics, specialized_type)
|
||||
scored.append((score, sp))
|
||||
|
||||
# Sort by score descending
|
||||
scored.sort(key=lambda x: x[0], reverse=True)
|
||||
|
||||
# Take top N
|
||||
result = [sp["id"] for score, sp in scored[:power_count]]
|
||||
|
||||
return result
|
||||
|
||||
|
||||
def assign_all_glyphs(glyphs: List[Dict[str, Any]]) -> Dict[str, List[int]]:
|
||||
"""Assign superpowers to all glyphs.
|
||||
|
||||
Args:
|
||||
glyphs: List of glyph dicts
|
||||
|
||||
Returns:
|
||||
Dict mapping glyph_id to superpower IDs
|
||||
"""
|
||||
result = {}
|
||||
|
||||
for glyph in glyphs:
|
||||
glyph_id = glyph.get("id", "")
|
||||
metrics = glyph.get("originalMetrics", {})
|
||||
category = glyph.get("category", "")
|
||||
|
||||
# Get specialized type
|
||||
specialized_type = get_specialized_type(glyph_id, metrics, category)
|
||||
|
||||
# Assign superpowers
|
||||
superpower_ids = assign_superpowers(glyph_id, metrics, specialized_type, category)
|
||||
|
||||
result[glyph_id] = superpower_ids
|
||||
|
||||
return result
|
||||
Executable
+235
@@ -0,0 +1,235 @@
|
||||
"""Superpower Registry for 152 Superpowers.
|
||||
|
||||
Provides:
|
||||
- load_all_superpowers() - Load all 152 superpowers
|
||||
- get_superpower(id) - Get single superpower by ID
|
||||
- get_superpowers_by_band(band) - Get all superpowers in band
|
||||
- calculate_boost(superpower_ids) - Calculate aggregate boost
|
||||
- search_superpowers(query) - Search superpowers by name/description
|
||||
"""
|
||||
|
||||
import json
|
||||
from pathlib import Path
|
||||
from typing import Optional, List, Dict, Any
|
||||
|
||||
# Module-level cache
|
||||
_superpowers: Optional[Dict[int, dict]] = None
|
||||
_superpowers_list: Optional[List[dict]] = None
|
||||
_loaded = False
|
||||
_load_path: Optional[Path] = None
|
||||
|
||||
|
||||
def load_all_superpowers(path: Optional[str] = None) -> None:
|
||||
"""Load all 152 superpowers from JSON file.
|
||||
|
||||
Args:
|
||||
path: Optional path to superpowers.json file.
|
||||
Defaults to /home/dave/superdave/glyphs/superpowers.json
|
||||
"""
|
||||
global _superpowers, _superpowers_list, _loaded, _load_path
|
||||
|
||||
if _loaded:
|
||||
return
|
||||
|
||||
if path is None:
|
||||
path = "/home/dave/superdave/glyphs/superpowers.json"
|
||||
|
||||
filepath = Path(path)
|
||||
if not filepath.exists():
|
||||
raise FileNotFoundError(f"Superpowers file not found: {filepath}")
|
||||
|
||||
_load_path = filepath
|
||||
|
||||
with open(filepath) as f:
|
||||
data = json.load(f)
|
||||
|
||||
# Validate count
|
||||
if data.get("total") != 152:
|
||||
raise ValueError(f"Expected 152 superpowers, got {data.get('total')}")
|
||||
|
||||
# Build cache by ID
|
||||
_superpowers = {}
|
||||
for sp in data.get("superpowers", []):
|
||||
_superpowers[sp["id"]] = sp
|
||||
|
||||
# Build sorted list
|
||||
_superpowers_list = sorted(_superpowers.values(), key=lambda x: x["id"])
|
||||
|
||||
_loaded = True
|
||||
|
||||
|
||||
def get_superpower(id: int) -> Optional[dict]:
|
||||
"""Get a single superpower by ID.
|
||||
|
||||
Args:
|
||||
id: Superpower ID (1-152)
|
||||
|
||||
Returns:
|
||||
Superpower dict with id, name, boost_percent, description, band
|
||||
"""
|
||||
if not _loaded:
|
||||
load_all_superpowers()
|
||||
|
||||
return _superpowers.get(id) if _superpowers else None
|
||||
|
||||
|
||||
def list_superpower_ids() -> List[int]:
|
||||
"""List all superpower IDs (sorted).
|
||||
|
||||
Returns:
|
||||
List of 152 superpower IDs [1, 2, ..., 152]
|
||||
"""
|
||||
if not _loaded:
|
||||
load_all_superpowers()
|
||||
|
||||
return [sp["id"] for sp in _superpowers_list] if _superpowers_list else []
|
||||
|
||||
|
||||
def get_superpowers_by_band(band: str) -> List[dict]:
|
||||
"""Get all superpowers in a band.
|
||||
|
||||
Args:
|
||||
band: Band identifier ("A", "B", "C", "D")
|
||||
|
||||
Returns:
|
||||
List of superpower dicts in that band
|
||||
"""
|
||||
if not _loaded:
|
||||
load_all_superpowers()
|
||||
|
||||
if not _superpowers_list:
|
||||
return []
|
||||
|
||||
return [sp for sp in _superpowers_list if sp.get("band") == band]
|
||||
|
||||
|
||||
def get_superpowers_by_bands(bands: List[str]) -> List[dict]:
|
||||
"""Get all superpowers in multiple bands.
|
||||
|
||||
Args:
|
||||
bands: List of band identifiers
|
||||
|
||||
Returns:
|
||||
List of superpower dicts in those bands
|
||||
"""
|
||||
if not _loaded:
|
||||
load_all_superpowers()
|
||||
|
||||
if not _superpowers_list:
|
||||
return []
|
||||
|
||||
return [sp for sp in _superpowers_list if sp.get("band") in bands]
|
||||
|
||||
|
||||
def calculate_boost(superpower_ids: List[int]) -> float:
|
||||
"""Calculate aggregate boost from superpower IDs.
|
||||
|
||||
Formula: power_boost = 1.0 + Σ(boost_percent) / 100.0
|
||||
|
||||
Args:
|
||||
superpower_ids: List of superpower IDs
|
||||
|
||||
Returns:
|
||||
Aggregate boost multiplier (e.g., 2.0 = 200% effectiveness)
|
||||
"""
|
||||
if not _loaded:
|
||||
load_all_superpowers()
|
||||
|
||||
total_boost = 0.0
|
||||
for id in superpower_ids:
|
||||
sp = _superpowers.get(id)
|
||||
if sp:
|
||||
total_boost += sp.get("boost_percent", 0) / 100.0
|
||||
|
||||
return 1.0 + total_boost
|
||||
|
||||
|
||||
def search_superpowers(query: str, fields: Optional[List[str]] = None, limit: int = 20) -> List[dict]:
|
||||
"""Search superpowers by query.
|
||||
|
||||
Args:
|
||||
query: Search string (case-insensitive substring)
|
||||
fields: Fields to search (default: ["name", "description"])
|
||||
limit: Maximum results
|
||||
|
||||
Returns:
|
||||
List of matching superpower dicts
|
||||
"""
|
||||
if not _loaded:
|
||||
load_all_superpowers()
|
||||
|
||||
if not _superpowers_list:
|
||||
return []
|
||||
|
||||
if fields is None:
|
||||
fields = ["name", "description"]
|
||||
|
||||
query_lower = query.lower()
|
||||
results = []
|
||||
|
||||
for sp in _superpowers_list:
|
||||
for field in fields:
|
||||
value = sp.get(field, "")
|
||||
if isinstance(value, str) and query_lower in value.lower():
|
||||
results.append(sp)
|
||||
break
|
||||
|
||||
if len(results) >= limit:
|
||||
break
|
||||
|
||||
return results
|
||||
|
||||
|
||||
def super_stats() -> dict:
|
||||
"""Get statistics about the superpower registry.
|
||||
|
||||
Returns:
|
||||
Dict with total, bands, loaded status, etc.
|
||||
"""
|
||||
if not _loaded:
|
||||
load_all_superpowers()
|
||||
|
||||
if not _superpowers_list:
|
||||
return {
|
||||
"total": 0,
|
||||
"bands": {},
|
||||
"loaded": False,
|
||||
}
|
||||
|
||||
# Count by band
|
||||
band_counts = {}
|
||||
for sp in _superpowers_list:
|
||||
band = sp.get("band")
|
||||
band_counts[band] = band_counts.get(band, 0) + 1
|
||||
|
||||
return {
|
||||
"total": len(_superpowers_list),
|
||||
"band_counts": band_counts,
|
||||
"loaded": _loaded,
|
||||
"load_path": str(_load_path) if _load_path else None,
|
||||
}
|
||||
|
||||
|
||||
# Global singleton instance
|
||||
_adapter_instance: Optional[Any] = None
|
||||
|
||||
|
||||
def get_superpower_names(superpower_ids: List[int]) -> List[str]:
|
||||
"""Get names for a list of superpower IDs.
|
||||
|
||||
Args:
|
||||
superpower_ids: List of IDs
|
||||
|
||||
Returns:
|
||||
List of superpower names
|
||||
"""
|
||||
if not _loaded:
|
||||
load_all_superpowers()
|
||||
|
||||
names = []
|
||||
for id in superpower_ids:
|
||||
sp = _superpowers.get(id)
|
||||
if sp:
|
||||
names.append(sp.get("name", f"SP{id}"))
|
||||
|
||||
return names
|
||||
Executable
+1100
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user