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
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
//! The [`Array`](crate::array::Array) struct.

use graphics::color::TRANSPARENT;
use graphics::types::Color;

use crate::state::SharedState;

/// A convenient wrapper around [`SharedState`] for
/// [algorithms](crate::algorithms) that handles concurrency and all that stuff.
/// **All methods in this struct lock the [state](crate::state::State) for as
/// short as possible** so that the rendering thread can lock it when it wants.
#[derive(Debug, Clone)]
pub struct Array(SharedState);

impl Array {
  /// Creates a new array from a copy of [`SharedState`].
  pub fn new(state: SharedState) -> Self {
    Array(state)
  }

  /// Puts the current thread to sleep for the specified amount of time and
  /// blocks it if the animation is [paused](crate::state::State::paused).
  pub fn wait(&self, ms: u64) {
    use std::thread;
    use std::time::Duration;

    // state must be locked for as short as possible so we shouldn't keep it
    // locked while sleeping (`thread::sleep` and `thread::park`)

    thread::sleep(Duration::from_micros({
      let state = self.0.get();
      (ms as f64 * 1000.0 / state.speed) as u64
    }));

    let paused = {
      let state = self.0.get();
      state.paused
    };

    if paused {
      thread::park();
    }
  }

  /// Returns the length of the underlying [vector](crate::state::State::array).
  pub fn len(&self) -> usize {
    let state = self.0.get();
    state.array.len()
  }

  /// Returns a value at a given index.
  pub fn get(&self, index: usize) -> u32 {
    let mut state = self.0.get();
    let value = state.array[index];

    state.array_accesses[index] = state.time;

    value
  }

  /// Sets a value of the at a given index.
  pub fn set(&self, index: usize, value: u32) {
    let mut state = self.0.get();
    state.array[index] = value;

    state.array_accesses[index] = state.time;
  }

  /// Swaps two values at given indices.
  pub fn swap(&self, a: usize, b: usize) {
    let mut state = self.0.get();
    state.array.swap(a, b);
  }

  //  /// Reverses the Array.
  //  pub fn reverse(&self) {
  //    let mut state = self.0.get();
  //    state.array.reverse();
  //  }

  /// Shuffles the Array.
  pub fn shuffle(&self) {
    use rand::{thread_rng, Rng};
    let mut state = self.0.get();
    thread_rng().shuffle(&mut state.array);
  }

  /// Resets color of the value at a given index (sets it to the transparent
  /// color).
  ///
  /// _See_ [`State.colors`](crate::state::State::colors)
  pub fn reset_color(&self, index: usize) {
    self.set_color(index, TRANSPARENT);
  }

  /// Sets color of the value at a given index.
  ///
  /// _See_ [`State.colors`](crate::state::State::colors)
  pub fn set_color(&self, index: usize, color: Color) {
    let mut state = self.0.get();
    state.colors[index] = color;
  }
}