use super::config::PerceptionConfig;
use super::hook::{DefaultPerceptionHook, PerceptionHook};
use super::state::KnowledgeBoardRegistry;
use super::system::PerceptionSystem;
use crate::Plugin;
use std::sync::Arc;
#[derive(Plugin)]
#[plugin(name = "issun:subjective_reality")]
pub struct SubjectiveRealityPlugin {
#[plugin(skip)]
hook: Arc<dyn PerceptionHook>,
#[plugin(resource)]
config: PerceptionConfig,
#[plugin(runtime_state)]
registry: KnowledgeBoardRegistry,
#[plugin(system)]
system: PerceptionSystem,
}
impl SubjectiveRealityPlugin {
pub fn new() -> Self {
let hook = Arc::new(DefaultPerceptionHook);
Self {
hook: hook.clone(),
config: PerceptionConfig::default(),
registry: KnowledgeBoardRegistry::new(),
system: PerceptionSystem::new(hook),
}
}
pub fn with_config(mut self, config: PerceptionConfig) -> Self {
self.config = config;
self
}
pub fn with_hook<H: PerceptionHook + 'static>(mut self, hook: H) -> Self {
let hook = Arc::new(hook);
self.hook = hook.clone();
self.system = PerceptionSystem::new(hook);
self
}
pub fn register_faction(mut self, faction_id: impl Into<String>) -> Self {
self.registry.register_faction(faction_id.into());
self
}
pub fn register_factions<I, S>(mut self, faction_ids: I) -> Self
where
I: IntoIterator<Item = S>,
S: Into<String>,
{
for faction_id in faction_ids {
self.registry.register_faction(faction_id.into());
}
self
}
}
impl Default for SubjectiveRealityPlugin {
fn default() -> Self {
Self::new()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_plugin_creation() {
let plugin = SubjectiveRealityPlugin::new();
assert_eq!(plugin.registry.faction_count(), 0);
}
#[test]
fn test_register_faction() {
let plugin = SubjectiveRealityPlugin::new().register_faction("faction_a");
assert_eq!(plugin.registry.faction_count(), 1);
assert!(plugin.registry.has_faction(&"faction_a".into()));
}
#[test]
fn test_register_multiple_factions() {
let plugin = SubjectiveRealityPlugin::new()
.register_faction("faction_a")
.register_faction("faction_b")
.register_faction("faction_c");
assert_eq!(plugin.registry.faction_count(), 3);
assert!(plugin.registry.has_faction(&"faction_a".into()));
assert!(plugin.registry.has_faction(&"faction_b".into()));
assert!(plugin.registry.has_faction(&"faction_c".into()));
}
#[test]
fn test_register_factions_vec() {
let plugin = SubjectiveRealityPlugin::new().register_factions(vec![
"faction_a",
"faction_b",
"faction_c",
]);
assert_eq!(plugin.registry.faction_count(), 3);
}
#[test]
fn test_with_config() {
let config = PerceptionConfig::default()
.with_default_accuracy(0.9)
.with_decay_rate(0.1);
let plugin = SubjectiveRealityPlugin::new().with_config(config.clone());
assert_eq!(plugin.config.default_accuracy, config.default_accuracy);
assert_eq!(plugin.config.decay_rate, config.decay_rate);
}
#[test]
fn test_with_custom_hook() {
use super::super::hook::PerceptionHook;
use async_trait::async_trait;
#[derive(Clone)]
struct TestHook;
#[async_trait]
impl PerceptionHook for TestHook {}
let plugin = SubjectiveRealityPlugin::new().with_hook(TestHook);
assert_eq!(plugin.registry.faction_count(), 0);
}
#[test]
fn test_builder_pattern() {
let plugin = SubjectiveRealityPlugin::new()
.with_config(
PerceptionConfig::default()
.with_default_accuracy(0.8)
.with_decay_rate(0.05),
)
.register_factions(vec!["player", "enemy_a", "enemy_b"]);
assert_eq!(plugin.config.default_accuracy, 0.8);
assert_eq!(plugin.config.decay_rate, 0.05);
assert_eq!(plugin.registry.faction_count(), 3);
}
}