use serde::{Deserialize, Serialize};
use std::collections::HashMap;
pub type SessionId = String;
pub type TargetCoordinate = String;
pub type EntryId = String;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum GestaltType {
Manmade,
Natural,
Movement,
Energy,
Water,
Land,
}
impl GestaltType {
pub fn all() -> &'static [GestaltType] {
&[
GestaltType::Manmade,
GestaltType::Natural,
GestaltType::Movement,
GestaltType::Energy,
GestaltType::Water,
GestaltType::Land,
]
}
pub fn index(&self) -> usize {
match self {
GestaltType::Manmade => 0,
GestaltType::Natural => 1,
GestaltType::Movement => 2,
GestaltType::Energy => 3,
GestaltType::Water => 4,
GestaltType::Land => 5,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct StageIData {
pub stroke: Vec<(f32, f32)>,
pub spontaneous_descriptor: String,
pub classification: GestaltType,
pub confidence: f32,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum SensoryModality {
Texture,
Color,
Temperature,
Sound,
Smell,
Taste,
Dimension,
Luminosity,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct StageIIData {
pub impressions: Vec<(SensoryModality, String)>,
pub feature_vector: Option<Vec<f32>>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct StageIIIData {
pub sketch_elements: Vec<SketchElement>,
pub relationships: Vec<SpatialRelationship>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SketchElement {
pub label: String,
pub kind: GeometricKind,
pub position: (f32, f32),
pub scale: Option<f32>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum GeometricKind {
Point,
Line,
Curve,
Rectangle,
Circle,
Triangle,
Polygon,
Freeform,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SpatialRelationship {
pub from: String,
pub to: String,
pub relation: SpatialRelationType,
pub strength: f32,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum SpatialRelationType {
Adjacent,
Contains,
Above,
Below,
Inside,
Surrounding,
Connected,
Separated,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct StageIVData {
pub emotional_impact: Vec<(String, f32)>,
pub tangibles: Vec<String>,
pub intangibles: Vec<String>,
pub aol_detections: Vec<AOLDetection>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AOLDetection {
pub content: String,
pub timestamp_ms: u64,
pub flagged: bool,
pub anomaly_score: f32,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct StageVData {
pub probes: Vec<SignalLineProbe>,
pub cross_references: Vec<CrossReference>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SignalLineProbe {
pub query: String,
pub target_stage: u8,
pub attention_weights: Vec<f32>,
pub top_candidates: Vec<usize>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CrossReference {
pub from_stage: u8,
pub from_entry: usize,
pub to_stage: u8,
pub to_entry: usize,
pub score: f32,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct StageVIData {
pub partitions: Vec<TargetPartition>,
pub composite_description: String,
pub partition_confidence: Vec<f32>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TargetPartition {
pub label: String,
pub member_entries: Vec<(u8, usize)>,
pub centroid: Vec<f32>,
pub separation_strength: f32,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CrvSessionEntry {
pub session_id: SessionId,
pub coordinate: TargetCoordinate,
pub stage: u8,
pub embedding: Vec<f32>,
pub metadata: HashMap<String, serde_json::Value>,
pub timestamp_ms: u64,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CrvConfig {
pub dimensions: usize,
pub curvature: f32,
pub aol_threshold: f32,
pub refractory_period_ms: f64,
pub snn_dt: f64,
pub search_temperature: f32,
pub convergence_threshold: f32,
}
impl Default for CrvConfig {
fn default() -> Self {
Self {
dimensions: 384,
curvature: 1.0,
aol_threshold: 0.7,
refractory_period_ms: 50.0,
snn_dt: 1.0,
search_temperature: 1.0,
convergence_threshold: 0.75,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ConvergenceResult {
pub session_pairs: Vec<(SessionId, SessionId)>,
pub scores: Vec<f32>,
pub convergent_stages: Vec<u8>,
pub consensus_embedding: Option<Vec<f32>>,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_gestalt_type_all() {
let all = GestaltType::all();
assert_eq!(all.len(), 6);
}
#[test]
fn test_gestalt_type_index() {
assert_eq!(GestaltType::Manmade.index(), 0);
assert_eq!(GestaltType::Land.index(), 5);
}
#[test]
fn test_default_config() {
let config = CrvConfig::default();
assert_eq!(config.dimensions, 384);
assert_eq!(config.curvature, 1.0);
assert_eq!(config.aol_threshold, 0.7);
}
#[test]
fn test_session_entry_serialization() {
let entry = CrvSessionEntry {
session_id: "sess-001".to_string(),
coordinate: "1234-5678".to_string(),
stage: 1,
embedding: vec![0.1, 0.2, 0.3],
metadata: HashMap::new(),
timestamp_ms: 1000,
};
let json = serde_json::to_string(&entry).unwrap();
let deserialized: CrvSessionEntry = serde_json::from_str(&json).unwrap();
assert_eq!(deserialized.session_id, "sess-001");
assert_eq!(deserialized.stage, 1);
}
}