use crate::prelude::Beat; use ::rand::distributions; use core::future::Future; use once_cell::sync::Lazy; pub use bach::rand::*; pub fn rhythm(length: Beat, durations: impl IntoIterator) -> Vec { let durations: Vec<_> = durations.into_iter().collect(); let mut beats = vec![]; let mut total = Beat(0, 1); while total < length { let b = *one_of(&durations); let new_total = total + b; if new_total > length { let b = length - total; beats.push(b); break; } else { total = new_total; beats.push(b); } } beats } pub fn with_seed R, R>(seed: u64, f: F) -> R { scope::with(Scope::new(seed), f) } pub static SEED: Lazy = Lazy::new(|| { if let Ok(seed) = std::env::var("EUPHONY_SEED") { u64::from_str_radix(&seed, 16).unwrap() } else { 0 } }); pub trait OneOfExt<'a> { type Output; fn one_of(&'a self) -> Self::Output; fn pick(&'a self) -> Self::Output { self.one_of() } } impl<'a, T: 'a> OneOfExt<'a> for [T] { type Output = &'a T; fn one_of(&'a self) -> Self::Output { one_of(self) } } impl<'a> OneOfExt<'a> for usize { type Output = usize; fn one_of(&'a self) -> Self::Output { (0..*self).one_of() } } impl<'a> OneOfExt<'a> for u64 { type Output = u64; fn one_of(&'a self) -> Self::Output { (0..*self).one_of() } } macro_rules! one_of_range { ($range:ident) => { impl<'a, T> OneOfExt<'a> for core::ops::$range where core::ops::$range: distributions::uniform::SampleRange, T: Copy + distributions::uniform::SampleUniform + PartialOrd, { type Output = T; fn one_of(&'a self) -> Self::Output { gen_range(self.clone()) } } }; } one_of_range!(Range); one_of_range!(RangeTo); one_of_range!(RangeInclusive); one_of_range!(RangeToInclusive); pub trait TaskExt: Sized { fn seed(self, seed: u64) -> Task; fn inhert_seed(self) -> Task; } impl TaskExt for T where T: Future, { fn seed(self, seed: u64) -> Task { Task::new(self, Scope::new(seed)) } fn inhert_seed(self) -> Task { Task::new(self, scope::borrow_with(|v| v.clone())) } }