mirror of
https://github.com/ricoriedel/wipe.git
synced 2024-11-26 09:46:37 +00:00
Choose values randomly
This commit is contained in:
parent
1dcc712983
commit
35ca4b2605
61
src/choose.rs
Normal file
61
src/choose.rs
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
use rand::prelude::IteratorRandom;
|
||||||
|
use rand::Rng;
|
||||||
|
|
||||||
|
pub trait Options {
|
||||||
|
fn all() -> Vec<Self> where Self: Sized;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Chooser<TRng> {
|
||||||
|
rng: TRng
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<TRng: Rng> Chooser<TRng> {
|
||||||
|
pub fn new(rng: TRng) -> Self {
|
||||||
|
Self { rng }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn choose<TValue: Options>(&mut self, selection: Vec<TValue>) -> TValue {
|
||||||
|
let options = if selection.is_empty() {
|
||||||
|
TValue::all()
|
||||||
|
} else {
|
||||||
|
selection
|
||||||
|
};
|
||||||
|
options.into_iter().choose_stable(&mut self.rng).unwrap()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
use rand::rngs::mock::StepRng;
|
||||||
|
use crate::{Chooser, Options};
|
||||||
|
|
||||||
|
enum MockOptions {
|
||||||
|
First,
|
||||||
|
Second,
|
||||||
|
Third
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Options for MockOptions {
|
||||||
|
fn all() -> Vec<Self> where Self: Sized {
|
||||||
|
use MockOptions::*;
|
||||||
|
|
||||||
|
vec![First, Second, Third]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn choose() {
|
||||||
|
let rng = StepRng::new(0, 1);
|
||||||
|
let mut chooser = Chooser::new(rng);
|
||||||
|
|
||||||
|
assert!(matches!(chooser.choose(vec![MockOptions::First, MockOptions::Second]), MockOptions::Second));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn choose_empty() {
|
||||||
|
let rng = StepRng::new(0, 1);
|
||||||
|
let mut chooser = Chooser::new(rng);
|
||||||
|
|
||||||
|
assert!(matches!(chooser.choose(Vec::new()), MockOptions::Third));
|
||||||
|
}
|
||||||
|
}
|
51
src/main.rs
51
src/main.rs
@ -3,10 +3,11 @@ use std::time::Duration;
|
|||||||
use anyhow::Error;
|
use anyhow::Error;
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
use clap::ArgEnum;
|
use clap::ArgEnum;
|
||||||
use crossterm::style::Color::*;
|
use rand::rngs::OsRng;
|
||||||
use crate::animation::Animation;
|
use crate::animation::Animation;
|
||||||
use crate::animation::circle::CircleAnimation;
|
use crate::animation::circle::CircleAnimation;
|
||||||
use crate::char::SimpleCharSampler;
|
use crate::char::SimpleCharSampler;
|
||||||
|
use crate::choose::{Chooser, Options};
|
||||||
use crate::color::{ColorSampler, SimpleColorSampler};
|
use crate::color::{ColorSampler, SimpleColorSampler};
|
||||||
use crate::fill::circle::CircleFillMode;
|
use crate::fill::circle::CircleFillMode;
|
||||||
use crate::fill::FillMode;
|
use crate::fill::FillMode;
|
||||||
@ -29,12 +30,21 @@ mod sampler;
|
|||||||
mod render;
|
mod render;
|
||||||
mod timer;
|
mod timer;
|
||||||
mod runner;
|
mod runner;
|
||||||
|
mod choose;
|
||||||
|
|
||||||
#[derive(Copy, Clone, ArgEnum)]
|
#[derive(Copy, Clone, ArgEnum)]
|
||||||
enum AnimationType {
|
enum AnimationType {
|
||||||
Circle
|
Circle
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Options for AnimationType {
|
||||||
|
fn all() -> Vec<Self> where Self: Sized {
|
||||||
|
use AnimationType::*;
|
||||||
|
|
||||||
|
vec![Circle]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, ArgEnum)]
|
#[derive(Copy, Clone, ArgEnum)]
|
||||||
enum ColorType {
|
enum ColorType {
|
||||||
Red,
|
Red,
|
||||||
@ -47,12 +57,28 @@ enum ColorType {
|
|||||||
Rainbow,
|
Rainbow,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Options for ColorType {
|
||||||
|
fn all() -> Vec<Self> where Self: Sized {
|
||||||
|
use ColorType::*;
|
||||||
|
|
||||||
|
vec![Red, Green, Blue, LightRed, LightGreen, LightBlue, Grey, Rainbow]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, ArgEnum)]
|
#[derive(Copy, Clone, ArgEnum)]
|
||||||
enum FillModeType {
|
enum FillModeType {
|
||||||
Circle,
|
Circle,
|
||||||
Level
|
Level
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Options for FillModeType {
|
||||||
|
fn all() -> Vec<Self> where Self: Sized {
|
||||||
|
use FillModeType::*;
|
||||||
|
|
||||||
|
vec![Circle, Level]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Parser)]
|
#[derive(Parser)]
|
||||||
#[clap(author = env!("CARGO_PKG_AUTHORS"), version = env!("CARGO_PKG_VERSION"), about = env!("CARGO_PKG_DESCRIPTION"))]
|
#[clap(author = env!("CARGO_PKG_AUTHORS"), version = env!("CARGO_PKG_VERSION"), about = env!("CARGO_PKG_DESCRIPTION"))]
|
||||||
struct Args {
|
struct Args {
|
||||||
@ -64,6 +90,10 @@ struct Args {
|
|||||||
color: Vec<ColorType>,
|
color: Vec<ColorType>,
|
||||||
#[clap(long, default_value = ".-+%#", help = "Set chars")]
|
#[clap(long, default_value = ".-+%#", help = "Set chars")]
|
||||||
chars: String,
|
chars: String,
|
||||||
|
#[clap(long, default_value = "30", help = "Set frames per second")]
|
||||||
|
fps: u64,
|
||||||
|
#[clap(long, default_value = "1000", help = "Set duration [milliseconds]")]
|
||||||
|
duration: u64,
|
||||||
#[clap(long, help = "Set width [default: terminal width]")]
|
#[clap(long, help = "Set width [default: terminal width]")]
|
||||||
width: Option<usize>,
|
width: Option<usize>,
|
||||||
#[clap(long, help = "Set height [default: terminal height]")]
|
#[clap(long, help = "Set height [default: terminal height]")]
|
||||||
@ -72,23 +102,26 @@ struct Args {
|
|||||||
|
|
||||||
fn main() -> Result<(), Error> {
|
fn main() -> Result<(), Error> {
|
||||||
let args = Args::parse();
|
let args = Args::parse();
|
||||||
|
let mut chooser = Chooser::new(OsRng::default());
|
||||||
|
|
||||||
let terminal = crossterm::terminal::size()?;
|
let terminal = crossterm::terminal::size()?;
|
||||||
let width = args.width.unwrap_or(terminal.0 as usize);
|
let width = args.width.unwrap_or(terminal.0 as usize);
|
||||||
let height = args.width.unwrap_or(terminal.1 as usize);
|
let height = args.height.unwrap_or(terminal.1 as usize);
|
||||||
let size = Vector::from_terminal(width, height);
|
let size = Vector::from_terminal(width, height);
|
||||||
|
let delay = Duration::from_micros(1_000_000 / args.fps);
|
||||||
|
let duration = Duration::from_millis(args.duration);
|
||||||
|
|
||||||
let animation = create_animation(args.animation[0], size);
|
let animation = create_animation(chooser.choose(args.animation), size);
|
||||||
let fill = create_fill(args.fill[0], size);
|
let fill = create_fill(chooser.choose(args.fill), size);
|
||||||
let color = create_color(args.color[0]);
|
let color = create_color(chooser.choose(args.color));
|
||||||
let char = Box::new(SimpleCharSampler::new(args.chars));
|
let char = Box::new(SimpleCharSampler::new(args.chars));
|
||||||
|
|
||||||
let sampler = ComposedSampler::new(animation, fill, color, char);
|
let sampler = ComposedSampler::new(animation, fill, color, char);
|
||||||
let surface =WriteSurface::new(stdout(), width, height);
|
let surface = WriteSurface::new(stdout(), width, height);
|
||||||
|
|
||||||
let renderer = SamplerRenderer::new(surface, sampler);
|
let renderer = SamplerRenderer::new(surface, sampler);
|
||||||
let timer = SimpleTimer::new(Duration::from_millis(1000 / 60));
|
let timer = SimpleTimer::new(delay);
|
||||||
let runner = Runner::new(Duration::from_secs(2), timer, renderer);
|
let runner = Runner::new(duration, timer, renderer);
|
||||||
|
|
||||||
runner.run()
|
runner.run()
|
||||||
}
|
}
|
||||||
@ -107,6 +140,8 @@ fn create_fill(fill: FillModeType, size: Vector) -> Box<dyn FillMode> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn create_color(color: ColorType) -> Box<dyn ColorSampler> {
|
fn create_color(color: ColorType) -> Box<dyn ColorSampler> {
|
||||||
|
use crossterm::style::Color::*;
|
||||||
|
|
||||||
match color {
|
match color {
|
||||||
ColorType::Red => Box::new(SimpleColorSampler::new(vec![Yellow, DarkYellow, Red])),
|
ColorType::Red => Box::new(SimpleColorSampler::new(vec![Yellow, DarkYellow, Red])),
|
||||||
ColorType::Green => Box::new(SimpleColorSampler::new(vec![Cyan, DarkGreen, Green])),
|
ColorType::Green => Box::new(SimpleColorSampler::new(vec![Cyan, DarkGreen, Green])),
|
||||||
|
Loading…
Reference in New Issue
Block a user