swarm-engine-core 0.1.6

Core types and orchestration for SwarmEngine
Documentation
//! WorkResult を MutationInput に変換するアダプター

use crate::exploration::mutation::ExplorationResult;
use crate::exploration::{MapNodeId, MutationInput};

/// WorkResult を MutationInput に変換するアダプター
///
/// Orchestrator 内で WorkResult::Acted を処理する際に使用。
/// ExplorationSpaceV2 への入力として渡せる。
pub struct WorkResultAdapter {
    /// 対象ノード ID
    pub node_id: MapNodeId,
    /// アクション名
    pub action_name: String,
    /// ターゲット(Optional)
    pub target: Option<String>,
    /// アクション実行結果
    pub result: ExplorationResult,
}

impl WorkResultAdapter {
    /// 成功/失敗と discovery から ExplorationResult を構築
    pub fn new(
        node_id: MapNodeId,
        action_name: &str,
        target: Option<&str>,
        success: bool,
        discovery: Option<&serde_json::Value>,
    ) -> Self {
        let result = if success {
            // discovery があれば Discover、なければ Success
            if let Some(disc) = discovery {
                // discovery が配列なら children として扱う
                if let Some(arr) = disc.as_array() {
                    let children: Vec<String> = arr
                        .iter()
                        .filter_map(|v| v.as_str().map(|s| s.to_string()))
                        .collect();
                    if !children.is_empty() {
                        ExplorationResult::Discover(children)
                    } else {
                        ExplorationResult::Success
                    }
                } else {
                    ExplorationResult::Success
                }
            } else {
                ExplorationResult::Success
            }
        } else {
            ExplorationResult::Fail(None)
        };

        Self {
            node_id,
            action_name: action_name.to_string(),
            target: target.map(|s| s.to_string()),
            result,
        }
    }
}

impl MutationInput for WorkResultAdapter {
    fn node_id(&self) -> MapNodeId {
        self.node_id
    }

    fn action_name(&self) -> &str {
        &self.action_name
    }

    fn target(&self) -> Option<&str> {
        self.target.as_deref()
    }

    fn result(&self) -> &ExplorationResult {
        &self.result
    }
}