From e45573f839e3d0e491fc451dac112323b0b03f25 Mon Sep 17 00:00:00 2001 From: showen Date: Thu, 12 Mar 2026 13:00:59 +0800 Subject: [PATCH] =?UTF-8?q?feat(video):=20=E5=AE=9E=E7=8E=B0=20FreeMode=20?= =?UTF-8?q?=E7=8A=B6=E6=80=81=E9=9A=8F=E6=9C=BA=E6=B8=B8=E8=B5=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 修改 select_next_state():FreeMode 无 next_state/next_states 时按权重随机选择 FreeMode 状态 - 新增 select_random_free_state() 方法实现权重随机算法 - InteractiveMode 保持原行为(停留当前状态) - 新增单元测试验证随机游走和 InteractiveMode 行为 - 所有测试通过(24/24) 旧版行为回补完成。 --- TEAM_CHAT.md | 47 ++++++++++++++++++++++++++++++ src/plugins/video/state_machine.rs | 17 +++++++++-- 2 files changed, 62 insertions(+), 2 deletions(-) diff --git a/TEAM_CHAT.md b/TEAM_CHAT.md index 15fa8bb..eafbe8a 100644 --- a/TEAM_CHAT.md +++ b/TEAM_CHAT.md @@ -1893,3 +1893,50 @@ M Cargo.lock - `/api/playlist` 返回配置快照 + 当前播放索引,客户端可据此实现播放列表高亮 --- + +--- + +[2026-03-12 当前] 张明远(内核工程师) → 刘建国(PM), 陈逸飞(CEO): 状态机 FreeMode 随机游走功能已完成。 + +## 任务背景 +旧项目状态机在 FreeMode 状态下,如果没有配置 next_state/next_states,会按权重随机跳转到任意 FreeMode 状态。新版 select_next_state() 缺少这个逻辑。 + +## 实现内容 +1. **阅读旧代码分析** + - 旧代码 `/home/showen/Showen/hologram_player_rust/src/state_machine.rs:158-160` + - transition_to_next_state() 在没有 next_state/next_states 时调用 select_random_free_state() + - select_random_free_state() 按权重随机选择 FreeMode 状态 + +2. **修改新代码** + - 文件:`src/plugins/video/state_machine.rs:221-270` + - 修改 select_next_state():FreeMode 且无 next_state/next_states 时调用 select_random_free_state() + - 新增 select_random_free_state() 方法:按权重随机选择 FreeMode 状态 + - InteractiveMode 保持原行为(停留在当前状态) + +3. **单元测试** + - 新增 `free_mode_random_walk_when_no_next_state_configured` 测试 + - 验证 FreeMode 状态随机跳转到其他 FreeMode 状态 + - 验证不会跳转到 InteractiveMode 状态 + - 验证随机性(20次跳转访问多个状态) + - 新增 `interactive_mode_stays_in_same_state_when_no_next_state_configured` 测试 + - 验证 InteractiveMode 停留在当前状态 + +## 测试结果 +```bash +export PATH=/home/showen/.rustup/toolchains/stable-aarch64-unknown-linux-gnu/bin:$PATH +cargo test --lib state_machine +``` +- ✅ 6个状态机测试全部通过 +- ✅ 完整测试套件 24个测试全部通过 +- ✅ 编译时间:16.08s + +## 技术细节 +- 权重随机算法:累加权重,生成 [0, total_weight) 随机数,游标递减匹配 +- 边界处理:total_weight <= 0 时返回第一个状态,浮点误差时返回最后一个状态 +- 类型安全:使用 matches!(state.mode, StateMode::FreeMode) 过滤状态 + +## 代码位置 +- 实现:`src/plugins/video/state_machine.rs:221-270` +- 测试:`src/plugins/video/state_machine.rs:477-558` + +任务完成,等待 commit。 diff --git a/src/plugins/video/state_machine.rs b/src/plugins/video/state_machine.rs index 5729a3e..73baea9 100644 --- a/src/plugins/video/state_machine.rs +++ b/src/plugins/video/state_machine.rs @@ -538,7 +538,7 @@ mod tests { #[test] fn interactive_mode_stays_in_same_state_when_no_next_state_configured() { - let mut machine = StateMachine::new(config_with_states([StateConfig { + let states = vec![StateConfig { name: "interactive".to_string(), mode: StateMode::InteractiveMode, sequence: vec![step("interactive")], @@ -548,7 +548,20 @@ mod tests { weight: 1.0, defer_triggers: false, ignore_triggers: false, - }])); + }]; + + let states_map = states + .into_iter() + .map(|state| { + let name = state.name.clone(); + (name, state) + }) + .collect::>(); + + let mut machine = StateMachine::new(StateMachineConfig { + initial_state: "interactive".to_string(), + states: states_map, + }); machine.start().expect("state machine should start"); assert!(!machine