/*! 🔗 SimpleIntentBox - P2P通信Box * * ## 📝 概要 * ピア・ツー・ピア通信機能を提供する軽量実装Box。 * ノード間のメッセージ配信、イベント通知、 * 分散アプリケーション構築に使用。 * * ## 🛠️ 利用可能メソッド * - `send(target, message)` - メッセージ送信 * - `on(event, callback)` - イベントリスナー登録 * - `emit(event, data)` - イベント発火 * - `connect(nodeId)` - ノード接続 * - `disconnect(nodeId)` - ノード切断 * - `getConnectedNodes()` - 接続中ノード一覧 * - `setNodeId(id)` - 自ノードID設定 * - `broadcast(message)` - 全ノードにブロードキャスト * * ## 💡 使用例 * ```nyash * local intent * intent = new SimpleIntentBox() * * // ノード設定 * intent.setNodeId("node1") * * // リスナー登録 * intent.on("message", "handleMessage") * intent.on("join", "handleNodeJoin") * * // メッセージ送信 * intent.send("node2", "Hello from node1!") * * // ブロードキャスト * intent.broadcast("System announcement") * ``` * * ## 🎮 実用例 - チャットアプリ * ```nyash * static box ChatNode { * init { intent, username, messages } * * main() { * me.intent = new SimpleIntentBox() * me.username = "User1" * me.messages = [] * * // ノード初期化 * me.intent.setNodeId(me.username) * me.setupEventHandlers() * * // チャットルームに参加 * me.joinChatRoom() * } * * setupEventHandlers() { * // メッセージ受信 * me.intent.on("chat_message", "onChatMessage") * // ユーザー参加 * me.intent.on("user_joined", "onUserJoined") * // ユーザー退出 * me.intent.on("user_left", "onUserLeft") * } * * sendMessage(text) { * local msg * msg = new MapBox() * msg.set("from", me.username) * msg.set("text", text) * msg.set("timestamp", new TimeBox().now()) * * me.intent.broadcast("chat_message", msg) * } * * onChatMessage(sender, message) { * me.messages.push(message) * print("[" + message.get("from") + "] " + message.get("text")) * } * } * ``` * * ## 🌐 分散計算例 * ```nyash * static box DistributedWorker { * init { intent, node_id, tasks } * * main() { * me.intent = new SimpleIntentBox() * me.node_id = "worker_" + RandomBox.randInt(1000, 9999) * me.tasks = [] * * me.intent.setNodeId(me.node_id) * me.registerAsWorker() * } * * registerAsWorker() { * // タスク受信リスナー * me.intent.on("task_assign", "processTask") * // 結果送信完了リスナー * me.intent.on("result_received", "onResultReceived") * * // ワーカー登録通知 * me.intent.broadcast("worker_ready", me.node_id) * } * * processTask(coordinator, task) { * print("Processing task: " + task.get("id")) * * // 重い計算処理... * local result * result = heavyCalculation(task.get("data")) * * // 結果を送信 * me.intent.send(coordinator, result) * } * } * ``` * * ## 🎯 ゲーム用マルチプレイヤー * ```nyash * static box GameClient { * init { intent, player_id, game_state } * * main() { * me.intent = new SimpleIntentBox() * me.player_id = "player_" + me.generateId() * me.game_state = new MapBox() * * me.connectToGame() * } * * connectToGame() { * me.intent.setNodeId(me.player_id) * * // ゲームイベント * me.intent.on("player_move", "onPlayerMove") * me.intent.on("game_update", "onGameUpdate") * me.intent.on("player_joined", "onPlayerJoined") * * // ゲーム参加 * me.intent.broadcast("join_game", me.player_id) * } * * movePlayer(x, y) { * local move_data * move_data = new MapBox() * move_data.set("player", me.player_id) * move_data.set("x", x) * move_data.set("y", y) * * me.intent.broadcast("player_move", move_data) * } * } * ``` * * ## ⚠️ 注意 * - 現在は最小限実装(フル機能開発中) * - ネットワーク通信は未実装(ローカル通信のみ) * - メッセージ配信は同一プロセス内限定 * - 本格P2P実装は将来バージョンで提供予定 */ use crate::box_trait::{NyashBox, StringBox, BoolBox, BoxCore, BoxBase}; use std::any::Any; use std::sync::RwLock; use std::collections::HashMap; #[derive(Debug)] pub struct SimpleIntentBox { base: BoxBase, // ノードID -> コールバック関数のマップ listeners: RwLock>>, // 仮実装 } impl Clone for SimpleIntentBox { fn clone(&self) -> Self { let listeners_val = self.listeners.read().unwrap().clone(); Self { base: BoxBase::new(), // New unique ID for clone listeners: RwLock::new(listeners_val), } } } impl SimpleIntentBox { pub fn new() -> Self { SimpleIntentBox { base: BoxBase::new(), listeners: RwLock::new(HashMap::new()), } } } impl BoxCore for SimpleIntentBox { fn box_id(&self) -> u64 { self.base.id } fn parent_type_id(&self) -> Option { self.base.parent_type_id } fn fmt_box(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { write!(f, "SimpleIntentBox(id: {}))", self.base.id) } fn as_any(&self) -> &dyn Any { self } fn as_any_mut(&mut self) -> &mut dyn Any { self } } impl NyashBox for SimpleIntentBox { fn to_string_box(&self) -> StringBox { StringBox::new("IntentBox") } fn equals(&self, other: &dyn NyashBox) -> BoolBox { if let Some(other_intent) = other.as_any().downcast_ref::() { BoolBox::new(self.base.id == other_intent.base.id) } else { BoolBox::new(false) } } fn type_name(&self) -> &'static str { "IntentBox" } fn clone_box(&self) -> Box { Box::new(self.clone()) } /// 仮実装: clone_boxと同じ(後で修正) fn share_box(&self) -> Box { self.clone_box() } } impl std::fmt::Display for SimpleIntentBox { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { self.fmt_box(f) } }