1use super::{DemoConfig, DemoEvent};
6use crate::tui::animation::{
7 agent_avatar::{ActivityLevel, AgentAvatar, AgentRole},
8 message_flow::{MessageFlow, MessageFlowManager, MessageType},
9 particles::ParticleSystem,
10 progress::AnimatedProgressBar,
11 token_stream::TokenStream,
12 Animation, AnimationManager,
13};
14use std::collections::HashMap;
15use std::time::{Duration, Instant};
16
17#[derive(Debug, Clone, PartialEq, Eq)]
19pub enum DemoState {
20 Idle,
22 Running,
24 Paused,
26 Completed,
28 Error(String),
30}
31
32pub trait DemoScenario: Send + Sync {
34 fn name(&self) -> &str;
36
37 fn description(&self) -> &str;
39
40 fn total_stages(&self) -> usize;
42
43 fn initialize(&mut self, runner: &mut DemoRunner);
45
46 fn execute_stage(&mut self, stage: usize, runner: &mut DemoRunner) -> bool;
48
49 fn cleanup(&mut self, runner: &mut DemoRunner);
51}
52
53pub struct DemoRunner {
55 config: DemoConfig,
57 state: DemoState,
59 scenario_name: Option<String>,
61 current_stage: usize,
63 total_stages: usize,
65 start_time: Option<Instant>,
67 events: Vec<DemoEvent>,
69 animation_manager: AnimationManager,
71 particle_system: ParticleSystem,
73 message_flow_manager: MessageFlowManager,
75 token_stream: TokenStream,
77 progress_bar: AnimatedProgressBar,
79 agents: HashMap<String, AgentAvatar>,
81}
82
83impl DemoRunner {
84 pub fn new(config: DemoConfig) -> Self {
86 Self {
87 config: config.clone(),
88 state: DemoState::Idle,
89 scenario_name: None,
90 current_stage: 0,
91 total_stages: 0,
92 start_time: None,
93 events: Vec::new(),
94 animation_manager: AnimationManager::new(),
95 particle_system: ParticleSystem::new(config.max_particles),
96 message_flow_manager: MessageFlowManager::new(),
97 token_stream: TokenStream::new(50),
98 progress_bar: AnimatedProgressBar::new(0.0),
99 agents: HashMap::new(),
100 }
101 }
102
103 pub fn start(&mut self, scenario: &mut dyn DemoScenario) {
105 self.scenario_name = Some(scenario.name().to_string());
106 self.total_stages = scenario.total_stages();
107 self.current_stage = 0;
108 self.start_time = Some(Instant::now());
109 self.state = DemoState::Running;
110 self.events.clear();
111
112 self.emit_event(DemoEvent::ScenarioStarted {
113 name: scenario.name().to_string(),
114 });
115
116 scenario.initialize(self);
117 }
118
119 pub fn next_stage(&mut self, scenario: &mut dyn DemoScenario) -> bool {
121 if self.state != DemoState::Running {
122 return false;
123 }
124
125 if self.current_stage >= self.total_stages {
126 self.complete(scenario);
127 return false;
128 }
129
130 let success = scenario.execute_stage(self.current_stage, self);
131
132 if success {
133 self.emit_event(DemoEvent::StageCompleted {
134 stage: self.current_stage,
135 total: self.total_stages,
136 });
137
138 self.current_stage += 1;
139 self.progress_bar
140 .set_progress(self.current_stage as f32 / self.total_stages as f32);
141 }
142
143 success
144 }
145
146 fn complete(&mut self, scenario: &mut dyn DemoScenario) {
148 let duration = self
149 .start_time
150 .map(|t| t.elapsed().as_secs_f32())
151 .unwrap_or(0.0);
152
153 self.emit_event(DemoEvent::ScenarioCompleted {
154 duration_secs: duration,
155 });
156
157 scenario.cleanup(self);
158 self.state = DemoState::Completed;
159 }
160
161 pub fn pause(&mut self) {
163 if self.state == DemoState::Running {
164 self.state = DemoState::Paused;
165 self.animation_manager.toggle_pause();
166 }
167 }
168
169 pub fn resume(&mut self) {
171 if self.state == DemoState::Paused {
172 self.state = DemoState::Running;
173 self.animation_manager.toggle_pause();
174 }
175 }
176
177 pub fn reset(&mut self) {
179 self.state = DemoState::Idle;
180 self.scenario_name = None;
181 self.current_stage = 0;
182 self.total_stages = 0;
183 self.start_time = None;
184 self.events.clear();
185 self.agents.clear();
186 self.particle_system.clear();
187 self.progress_bar.set_progress(0.0);
188 }
189
190 pub fn update(&mut self, delta_time: f32) {
192 let adjusted_delta = delta_time * self.config.speed_multiplier;
193
194 self.animation_manager.update(adjusted_delta);
195 self.particle_system.update(adjusted_delta);
196 self.message_flow_manager.update(adjusted_delta);
197 self.token_stream.update(adjusted_delta);
198 self.progress_bar.update(adjusted_delta);
199
200 for avatar in self.agents.values_mut() {
201 avatar.update(adjusted_delta);
202 }
203 }
204
205 pub fn add_agent(&mut self, id: &str, role: AgentRole) {
209 let avatar = AgentAvatar::new(role).with_name(id);
210 self.agents.insert(id.to_string(), avatar);
211 }
212
213 pub fn set_agent_activity(&mut self, id: &str, level: ActivityLevel) {
215 if let Some(avatar) = self.agents.get_mut(id) {
216 avatar.set_activity(level);
217 }
218 }
219
220 pub fn add_agent_tokens(&mut self, id: &str, tokens: u64) {
222 if let Some(avatar) = self.agents.get_mut(id) {
223 avatar.add_tokens(tokens);
224 }
225
226 self.emit_event(DemoEvent::TokensProcessed {
227 count: tokens,
228 rate: tokens as f64 / 0.016, });
230 }
231
232 pub fn agent(&self, id: &str) -> Option<&AgentAvatar> {
234 self.agents.get(id)
235 }
236
237 pub fn send_message(
241 &mut self,
242 from: &str,
243 to: &str,
244 msg_type: MessageType,
245 from_pos: (f32, f32),
246 to_pos: (f32, f32),
247 ) {
248 let flow = MessageFlow::new(from_pos, to_pos, msg_type);
249 self.message_flow_manager.add(flow);
250
251 self.emit_event(DemoEvent::MessageSent {
252 from: from.to_string(),
253 to: to.to_string(),
254 msg_type: format!("{:?}", msg_type),
255 });
256 }
257
258 pub fn sparkle(&mut self, x: f32, y: f32, count: usize) {
262 if self.config.particles_enabled {
263 self.particle_system.sparkle(x, y, count);
264 self.emit_event(DemoEvent::EffectTriggered {
265 effect_type: "sparkle".to_string(),
266 x,
267 y,
268 });
269 }
270 }
271
272 pub fn explode(&mut self, x: f32, y: f32, count: usize) {
274 if self.config.particles_enabled {
275 self.particle_system.explode(x, y, count);
276 self.emit_event(DemoEvent::EffectTriggered {
277 effect_type: "explode".to_string(),
278 x,
279 y,
280 });
281 }
282 }
283
284 pub fn celebrate(&mut self, x: f32, y: f32) {
286 if self.config.particles_enabled {
287 self.particle_system.celebrate(x, y);
288 self.emit_event(DemoEvent::EffectTriggered {
289 effect_type: "celebrate".to_string(),
290 x,
291 y,
292 });
293 }
294 }
295
296 pub fn set_token_rate(&mut self, rate: f64) {
300 self.token_stream.set_rate(rate);
301 }
302
303 pub fn set_total_tokens(&mut self, total: u64) {
305 self.token_stream.set_total(total);
306 }
307
308 pub fn emit_event(&mut self, event: DemoEvent) {
312 self.events.push(event);
313 }
314
315 pub fn events(&self) -> &[DemoEvent] {
317 &self.events
318 }
319
320 pub fn state(&self) -> &DemoState {
323 &self.state
324 }
325
326 pub fn current_stage(&self) -> usize {
327 self.current_stage
328 }
329
330 pub fn total_stages(&self) -> usize {
331 self.total_stages
332 }
333
334 pub fn progress(&self) -> f32 {
335 if self.total_stages == 0 {
336 0.0
337 } else {
338 self.current_stage as f32 / self.total_stages as f32
339 }
340 }
341
342 pub fn elapsed(&self) -> Duration {
343 self.start_time.map(|t| t.elapsed()).unwrap_or_default()
344 }
345
346 pub fn particle_system(&self) -> &ParticleSystem {
347 &self.particle_system
348 }
349
350 pub fn message_flow_manager(&self) -> &MessageFlowManager {
351 &self.message_flow_manager
352 }
353
354 pub fn token_stream(&self) -> &TokenStream {
355 &self.token_stream
356 }
357
358 pub fn progress_bar(&self) -> &AnimatedProgressBar {
359 &self.progress_bar
360 }
361
362 pub fn agents(&self) -> &HashMap<String, AgentAvatar> {
363 &self.agents
364 }
365
366 pub fn config(&self) -> &DemoConfig {
367 &self.config
368 }
369}
370
371impl Default for DemoRunner {
372 fn default() -> Self {
373 Self::new(DemoConfig::default())
374 }
375}
376
377#[cfg(test)]
378mod tests {
379 use super::*;
380
381 struct TestScenario {
382 name: String,
383 stages: usize,
384 initialized: bool,
385 executed_stages: Vec<usize>,
386 cleaned_up: bool,
387 }
388
389 impl TestScenario {
390 fn new(stages: usize) -> Self {
391 Self {
392 name: "Test Scenario".to_string(),
393 stages,
394 initialized: false,
395 executed_stages: Vec::new(),
396 cleaned_up: false,
397 }
398 }
399 }
400
401 impl DemoScenario for TestScenario {
402 fn name(&self) -> &str {
403 &self.name
404 }
405
406 fn description(&self) -> &str {
407 "A test scenario"
408 }
409
410 fn total_stages(&self) -> usize {
411 self.stages
412 }
413
414 fn initialize(&mut self, _runner: &mut DemoRunner) {
415 self.initialized = true;
416 }
417
418 fn execute_stage(&mut self, stage: usize, _runner: &mut DemoRunner) -> bool {
419 self.executed_stages.push(stage);
420 true
421 }
422
423 fn cleanup(&mut self, _runner: &mut DemoRunner) {
424 self.cleaned_up = true;
425 }
426 }
427
428 #[test]
429 fn test_demo_runner_new() {
430 let runner = DemoRunner::new(DemoConfig::default());
431 assert_eq!(*runner.state(), DemoState::Idle);
432 assert_eq!(runner.current_stage(), 0);
433 }
434
435 #[test]
436 fn test_demo_runner_start() {
437 let mut runner = DemoRunner::new(DemoConfig::default());
438 let mut scenario = TestScenario::new(5);
439
440 runner.start(&mut scenario);
441
442 assert!(scenario.initialized);
443 assert_eq!(*runner.state(), DemoState::Running);
444 assert_eq!(runner.total_stages(), 5);
445 }
446
447 #[test]
448 fn test_demo_runner_stages() {
449 let mut runner = DemoRunner::new(DemoConfig::default());
450 let mut scenario = TestScenario::new(3);
451
452 runner.start(&mut scenario);
453
454 assert!(runner.next_stage(&mut scenario));
455 assert_eq!(runner.current_stage(), 1);
456
457 assert!(runner.next_stage(&mut scenario));
458 assert_eq!(runner.current_stage(), 2);
459
460 assert!(runner.next_stage(&mut scenario));
461 assert_eq!(runner.current_stage(), 3);
462
463 assert!(!runner.next_stage(&mut scenario));
465 assert_eq!(*runner.state(), DemoState::Completed);
466 assert!(scenario.cleaned_up);
467 }
468
469 #[test]
470 fn test_demo_runner_pause_resume() {
471 let mut runner = DemoRunner::new(DemoConfig::default());
472 let mut scenario = TestScenario::new(3);
473
474 runner.start(&mut scenario);
475 assert_eq!(*runner.state(), DemoState::Running);
476
477 runner.pause();
478 assert_eq!(*runner.state(), DemoState::Paused);
479
480 runner.resume();
481 assert_eq!(*runner.state(), DemoState::Running);
482 }
483
484 #[test]
485 fn test_demo_runner_agents() {
486 let mut runner = DemoRunner::new(DemoConfig::default());
487
488 runner.add_agent("coder-1", AgentRole::Coder);
489 runner.add_agent("tester-1", AgentRole::Tester);
490
491 assert_eq!(runner.agents().len(), 2);
492 assert!(runner.agent("coder-1").is_some());
493 assert!(runner.agent("unknown").is_none());
494 }
495
496 #[test]
497 fn test_demo_runner_effects() {
498 let mut runner = DemoRunner::new(DemoConfig::default());
499
500 runner.sparkle(10.0, 10.0, 5);
501 runner.explode(20.0, 20.0, 10);
502 runner.celebrate(30.0, 30.0);
503
504 assert_eq!(runner.events().len(), 3);
505 }
506}