feat(video): 实现 FreeMode 状态随机游走
- 修改 select_next_state():FreeMode 无 next_state/next_states 时按权重随机选择 FreeMode 状态 - 新增 select_random_free_state() 方法实现权重随机算法 - InteractiveMode 保持原行为(停留当前状态) - 新增单元测试验证随机游走和 InteractiveMode 行为 - 所有测试通过(24/24) 旧版行为回补完成。
This commit is contained in:
47
TEAM_CHAT.md
47
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。
|
||||
|
||||
@@ -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::<HashMap<_, _>>();
|
||||
|
||||
let mut machine = StateMachine::new(StateMachineConfig {
|
||||
initial_state: "interactive".to_string(),
|
||||
states: states_map,
|
||||
});
|
||||
machine.start().expect("state machine should start");
|
||||
|
||||
assert!(!machine
|
||||
|
||||
Reference in New Issue
Block a user