1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
//! Structs and type definitions that describe the app state.

use std::sync::{Arc, Mutex, MutexGuard};

use graphics::types::Color;

/// A wrapper around [`State`] that can be [safely shared](std::sync) between
/// threads.
#[derive(Debug, Clone)]
pub struct SharedState(Arc<Mutex<State>>);

impl SharedState {
  pub fn new(state: State) -> Self {
    SharedState(Arc::new(Mutex::new(state)))
  }

  pub fn get(&self) -> MutexGuard<'_, State> {
    self.0.lock().unwrap()
  }
}

/// Contains the state of the whole [app](crate::app::App).
#[derive(Debug)]
pub struct State {
  /// Current time in seconds. [Updated](crate::app::App::update) if the
  /// animation is not [paused](State::paused).
  pub time: f64,
  /// Speed factor (e.g. 1.0 - normal, 2.0 - 2x faster, 0.5 - 2x slower, etc).
  /// Affects the animation [time](State::time) and
  /// [delays](crate::array::Array::wait) in
  /// [algorithms](crate::algorithms::Algorithm).
  pub speed: f64,
  /// Is the animation paused?
  pub paused: bool,
  /// An array which is being sorted.
  pub array: Vec<u32>,
  /// Colored **overlays** of each value. **Overlay** means that these colors
  /// are _not_ used to [draw](crate::app::App::render) the values, instead
  /// they're drawn **over** the values. These colors can be used by an
  /// [algorithm](crate::algorithms::Algorithm) to highlight important array
  /// elements.
  ///
  /// The length of this vector is equal to the [array](State::array)
  /// length, so every color in this vector corresponds to a value with the
  /// exact same index.
  pub colors: Vec<Color>,
  /// Contains timestamps of the most recent array accesses of every element,
  /// which are drawn like [colored overlays](State::colors). The length of this
  /// vector is equal to the [array](State::array) length, so for every element
  /// in the [array](State::array) _only the most recent_ timestamp is stored
  /// here (not a big deal), so we can avoid memory allocations while program is
  /// running, and this is a pretty simple optimization. To optimize things even
  /// further I've done this: if an element hasn't been accessed yet or it has
  /// been accessed [long ago](crate::app::ACCESSED_VALUE_TIMEOUT), then instead
  /// of using an `Option<f64>` type for every element, I use negative values
  /// because they don't make any sense in the context of time (this saves
  /// [8 bytes](https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=0e335d0d6109850c7df766fd131c8916)
  /// for every element). When an [algorithm](crate::algorithms::Algorithm)
  /// [reads](crate::array::Array::get) or [writes](crate::array::Array::set) a
  /// value at a certain index from/to the array, the current
  /// [time](State::time) is stored at exactly the same index in this vector.
  pub array_accesses: Vec<f64>,
}

/// A constant that means "there's no array access here". _See_ documentation of
/// [`State.array_accesses`](State::array_accesses) to understand why this
/// constant is a negative number.
pub const NO_ARRAY_ACCESS: f64 = -1.0;