Compare commits
4 commits
Author | SHA1 | Date | |
---|---|---|---|
149fbbd3f7 | |||
e325cb57e7 | |||
82e27fa4b2 | |||
cd3cef1691 |
11 changed files with 2579 additions and 820 deletions
5
.vscode/settings.json
vendored
Normal file
5
.vscode/settings.json
vendored
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
"rust-analyzer.linkedProjects": [
|
||||||
|
"./Cargo.toml"
|
||||||
|
]
|
||||||
|
}
|
2641
Cargo.lock
generated
2641
Cargo.lock
generated
File diff suppressed because it is too large
Load diff
|
@ -6,8 +6,12 @@ edition = "2021"
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
macroquad = "0.3.25"
|
anyhow = "1.0.75"
|
||||||
async-trait = "0.1.64"
|
async-trait = "0.1.64"
|
||||||
|
futures-core = "0.3.29"
|
||||||
|
futures-util = "0.3.29"
|
||||||
|
notan = "0.11.0"
|
||||||
|
tokio = {version = "1.34.0", features = ["full"] }
|
||||||
tokio-test = "*"
|
tokio-test = "*"
|
||||||
|
|
||||||
[profile.release]
|
[profile.release]
|
||||||
|
|
|
@ -1,28 +1,10 @@
|
||||||
|
|
||||||
use macroquad::audio::PlaySoundParams;
|
|
||||||
use macroquad::audio::Sound;
|
|
||||||
use macroquad::audio::play_sound;
|
|
||||||
use macroquad::audio::play_sound_once;
|
|
||||||
use macroquad::color;
|
|
||||||
use macroquad::color_u8;
|
|
||||||
use macroquad::rand;
|
|
||||||
|
|
||||||
use crate::soundGenerator;
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
pub struct Bar {
|
pub struct Bar {
|
||||||
pub position:usize,
|
pub position: usize,
|
||||||
pub color:color::Color,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Bar {
|
||||||
|
pub fn new(position: usize, hsl_color: f32) -> Self {
|
||||||
impl Bar{
|
Bar { position }
|
||||||
pub fn new(position:usize, hsl_color:f32) -> Self{
|
|
||||||
Bar{
|
|
||||||
position,
|
|
||||||
color: color::hsl_to_rgb((hsl_color as f32) , 1.0, 0.5),
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,322 +0,0 @@
|
||||||
|
|
||||||
|
|
||||||
use async_trait::async_trait;
|
|
||||||
use macroquad::audio::{play_sound_once, Sound, play_sound, PlaySoundParams};
|
|
||||||
use macroquad::color::{BROWN, WHITE};
|
|
||||||
use macroquad::{hash, time};
|
|
||||||
use macroquad::prelude::{clear_background, Vec2, BLACK};
|
|
||||||
use macroquad::rand::ChooseRandom;
|
|
||||||
use macroquad::shapes::draw_rectangle;
|
|
||||||
use macroquad::text::draw_text;
|
|
||||||
use macroquad::time::{get_frame_time, get_fps};
|
|
||||||
use macroquad::ui::root_ui;
|
|
||||||
use macroquad::window::{next_frame, screen_height, screen_width};
|
|
||||||
use crate::BarPlugin::Bar;
|
|
||||||
use crate::soundGenerator;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
|
||||||
pub struct GuiVec{
|
|
||||||
pub list: Vec<Bar>,
|
|
||||||
initialSize:usize,
|
|
||||||
pub lastTime:f64,
|
|
||||||
pub reads:i32,
|
|
||||||
pub writes:i32,
|
|
||||||
pub comps:i32,
|
|
||||||
isPaused:bool,
|
|
||||||
delay:f32,
|
|
||||||
pub done:bool,
|
|
||||||
renderSkip:i32,
|
|
||||||
skipped:i32,
|
|
||||||
lastTouched:Vec<usize>,
|
|
||||||
lastPlayed:f64,
|
|
||||||
}
|
|
||||||
#[async_trait]
|
|
||||||
pub trait SortingList{
|
|
||||||
|
|
||||||
async fn new(length:usize, delay:f32) -> Self;
|
|
||||||
|
|
||||||
fn len(&self) -> usize;
|
|
||||||
|
|
||||||
async fn swap(&mut self, index1:usize, index2:usize) -> bool;
|
|
||||||
|
|
||||||
async fn draw(&mut self);
|
|
||||||
|
|
||||||
fn randomize(&mut self);
|
|
||||||
|
|
||||||
fn elements(&mut self) -> std::slice::Iter<'_, Bar>;
|
|
||||||
|
|
||||||
fn get(&mut self, i:usize)-> &Bar;
|
|
||||||
|
|
||||||
fn lessThan(&mut self, a:usize, b:usize) -> bool;
|
|
||||||
|
|
||||||
|
|
||||||
fn lessThanEqual(&mut self, a:usize, b:usize) -> bool;
|
|
||||||
|
|
||||||
fn isSorted(&mut self) -> bool;
|
|
||||||
|
|
||||||
async fn set(&mut self, i:usize, elem:Bar) -> bool;
|
|
||||||
|
|
||||||
async fn show(&mut self);
|
|
||||||
|
|
||||||
fn getListClone(&self) -> Vec<Bar>;
|
|
||||||
}
|
|
||||||
#[async_trait]
|
|
||||||
impl SortingList for GuiVec{
|
|
||||||
|
|
||||||
async fn new(length:usize, delay:f32) -> Self {
|
|
||||||
let colorStep = 360./length as f32;
|
|
||||||
let mut list:Vec<Bar> = vec!();
|
|
||||||
let freqStep = 50. + ((2000.-50.)/length as f32);
|
|
||||||
|
|
||||||
for i in 1..length+1 {
|
|
||||||
let frequency = i as f32 * freqStep;
|
|
||||||
list.push(Bar::new(i, (colorStep*i as f32)/360.));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
GuiVec{
|
|
||||||
list,
|
|
||||||
initialSize:length as usize,
|
|
||||||
lastTime: 0.0 ,
|
|
||||||
reads:0,
|
|
||||||
writes:0,
|
|
||||||
comps:0,
|
|
||||||
isPaused:false,
|
|
||||||
delay,
|
|
||||||
done:false,
|
|
||||||
renderSkip:1,
|
|
||||||
skipped:0,
|
|
||||||
lastTouched:Vec::with_capacity(2),
|
|
||||||
lastPlayed:0.,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn draw(&mut self){
|
|
||||||
let mut frames = 0.0;
|
|
||||||
let mut delayText = self.delay.to_string();
|
|
||||||
let mut renderSkipText = self.renderSkip.to_string();
|
|
||||||
|
|
||||||
loop {
|
|
||||||
|
|
||||||
|
|
||||||
if self.skipped >= self.renderSkip{
|
|
||||||
clear_background(WHITE);
|
|
||||||
|
|
||||||
for (count,bar) in self.list.iter().enumerate(){
|
|
||||||
let mut color = bar.color;
|
|
||||||
if self.lastTouched.contains(&count){
|
|
||||||
color = BLACK;
|
|
||||||
}
|
|
||||||
draw_rectangle(screen_width() * ((count as f32)/(self.initialSize as f32)),screen_height() - (screen_height()/((self.len()) as f32))*bar.position as f32 , screen_width()/((self.len()) as f32), (screen_height()/((self.len()) as f32))*bar.position as f32, color);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
root_ui().window(hash!(),Vec2::new(screen_width()*0.01, 5.), Vec2::new(800.0, 50.), |ui|{
|
|
||||||
ui.input_text(hash!(), "Delay (ms)", &mut delayText);
|
|
||||||
ui.input_text(hash!(), "StepsPrFrame (How many steps of the algorithm pr frame)", &mut renderSkipText);
|
|
||||||
draw_text(&format!("FPS: {}", get_fps()), screen_width()*0.01 + 40., 80.0, 20.0, BLACK);
|
|
||||||
draw_text(&format!("Array reads: {}", self.reads), screen_width()*0.01 + 40., 110.0, 20.0, BLACK);
|
|
||||||
draw_text(&format!("Array writes: {}", self.writes), screen_width()*0.01 + 40., 140.0, 20.0, BLACK);
|
|
||||||
draw_text(&format!("Comparisons: {}", self.comps), screen_width()*0.01 + 40., 170.0, 20.0, BLACK);
|
|
||||||
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
if root_ui().button(Vec2::new(screen_width()*0.01, 60.), "Exit"){
|
|
||||||
self.done = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if root_ui().button(Vec2::new(screen_width()*0.01, 90.), "Pause"){
|
|
||||||
self.isPaused = !self.isPaused;
|
|
||||||
|
|
||||||
}
|
|
||||||
self.renderSkip = match renderSkipText.parse::<i32>(){
|
|
||||||
Ok(a) => a,
|
|
||||||
Err(_) => 1
|
|
||||||
};
|
|
||||||
|
|
||||||
self.delay = match (delayText.parse::<f32>(), self.isPaused){
|
|
||||||
(_, true) => f32::MAX,
|
|
||||||
(Ok(a), false) => a,
|
|
||||||
(Err(_), _)=> {f32::MAX}
|
|
||||||
};
|
|
||||||
next_frame().await;
|
|
||||||
self.skipped = 0;
|
|
||||||
}else{
|
|
||||||
self.skipped += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if frames >= self.delay && !self.done{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
frames += get_frame_time()* 1000.;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
fn len(&self) -> usize{
|
|
||||||
self.list.len()
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn swap(&mut self, index1:usize, index2:usize) -> bool{
|
|
||||||
self.writes += 2;
|
|
||||||
self.reads += 2;
|
|
||||||
self.list.swap(index1, index2);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
self.lastTouched.clear();
|
|
||||||
self.lastTouched.push(index1);
|
|
||||||
self.lastTouched.push(index2);
|
|
||||||
self.draw().await;
|
|
||||||
|
|
||||||
self.done
|
|
||||||
}
|
|
||||||
fn randomize(&mut self){
|
|
||||||
self.list.shuffle();
|
|
||||||
}
|
|
||||||
|
|
||||||
fn elements(&mut self) -> std::slice::Iter<'_, Bar> {
|
|
||||||
self.list.iter()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get(&mut self, i:usize)-> &Bar{
|
|
||||||
self.reads += 1;
|
|
||||||
self.lastTouched.clear();
|
|
||||||
self.lastTouched.push(i);
|
|
||||||
self.list.get(i).unwrap()
|
|
||||||
|
|
||||||
}
|
|
||||||
fn lessThan(&mut self, a:usize, b:usize) -> bool{
|
|
||||||
self.comps += 1;
|
|
||||||
return self.get(a).position < self.get(b).position
|
|
||||||
}
|
|
||||||
fn lessThanEqual(&mut self, a:usize, b:usize) -> bool{
|
|
||||||
self.comps += 1;
|
|
||||||
return self.get(a).position <= b
|
|
||||||
}
|
|
||||||
fn isSorted(&mut self) -> bool{
|
|
||||||
self.reads += self.len() as i32;
|
|
||||||
let mut prev = 0;
|
|
||||||
for bar in self.list.iter() {
|
|
||||||
if bar.position < prev{
|
|
||||||
return false;
|
|
||||||
}else{
|
|
||||||
prev = bar.position;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
true
|
|
||||||
}
|
|
||||||
async fn set(&mut self, i:usize, elem:Bar) -> bool{
|
|
||||||
|
|
||||||
self.writes += 1;
|
|
||||||
self.reads += 1;
|
|
||||||
self.list[i] = elem;
|
|
||||||
self.draw().await;
|
|
||||||
if time::get_time() + 0.1 >= self.lastPlayed{
|
|
||||||
|
|
||||||
self.lastPlayed = time::get_time()+0.1;
|
|
||||||
}
|
|
||||||
self.lastTouched.clear();
|
|
||||||
self.lastTouched.push(i);
|
|
||||||
self.done
|
|
||||||
|
|
||||||
}
|
|
||||||
async fn show(&mut self){
|
|
||||||
loop{
|
|
||||||
if !self.done{
|
|
||||||
self.draw().await
|
|
||||||
}else{
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn getListClone(&self) -> Vec<Bar>{
|
|
||||||
self.list.clone()
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct NonGuiVec{
|
|
||||||
pub list: Vec<Bar>,
|
|
||||||
|
|
||||||
}
|
|
||||||
#[async_trait]
|
|
||||||
impl SortingList for NonGuiVec{
|
|
||||||
async fn new(length:usize, delay:f32) -> Self{
|
|
||||||
let mut list = Vec::new();
|
|
||||||
for i in 0..(length as usize){
|
|
||||||
list.push(Bar::new(i, i as f32))
|
|
||||||
}
|
|
||||||
NonGuiVec { list: list }
|
|
||||||
}
|
|
||||||
|
|
||||||
fn len(&self) -> usize{
|
|
||||||
self.list.len()
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn swap(&mut self, index1:usize, index2:usize) -> bool{
|
|
||||||
self.list.swap(index1, index2);
|
|
||||||
false
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn draw(&mut self){
|
|
||||||
self.swap(0, 0).await;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn randomize(&mut self){
|
|
||||||
self.list.shuffle();
|
|
||||||
}
|
|
||||||
|
|
||||||
fn elements(&mut self) -> std::slice::Iter<'_, Bar> {
|
|
||||||
self.list.iter()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get(&mut self, i:usize)-> &Bar{
|
|
||||||
|
|
||||||
self.list.get(i).unwrap()
|
|
||||||
}
|
|
||||||
fn lessThan(&mut self, a:usize, b:usize) -> bool{
|
|
||||||
|
|
||||||
return self.get(a).position < self.get(b).position
|
|
||||||
}
|
|
||||||
fn lessThanEqual(&mut self, a:usize, b:usize) -> bool{
|
|
||||||
return self.get(a).position <= b
|
|
||||||
}
|
|
||||||
fn isSorted(&mut self) -> bool{
|
|
||||||
let mut prev = 0;
|
|
||||||
for bar in self.list.iter() {
|
|
||||||
if bar.position < prev{
|
|
||||||
return false;
|
|
||||||
}else{
|
|
||||||
prev = bar.position;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
true
|
|
||||||
}
|
|
||||||
async fn set(&mut self, i:usize, elem:Bar) -> bool{
|
|
||||||
|
|
||||||
self.list[i] = elem;
|
|
||||||
self.draw().await;
|
|
||||||
|
|
||||||
false
|
|
||||||
|
|
||||||
}
|
|
||||||
async fn show(&mut self){
|
|
||||||
|
|
||||||
}
|
|
||||||
fn getListClone(&self) -> Vec<Bar>{
|
|
||||||
self.list.clone()
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,64 +0,0 @@
|
||||||
mod radixSort;
|
|
||||||
mod insertSort;
|
|
||||||
mod bubbleSort;
|
|
||||||
mod binaryHeap;
|
|
||||||
mod coctailShaker;
|
|
||||||
mod quickSort;
|
|
||||||
mod bogoSort;
|
|
||||||
mod radixSortLSD;
|
|
||||||
|
|
||||||
|
|
||||||
use crate::GuiHookVec::GuiVec;
|
|
||||||
use crate::GuiHookVec::SortingList;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub struct Algorithm{
|
|
||||||
algorithms:Vec<String>
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Algorithm{
|
|
||||||
pub fn new() -> Self{
|
|
||||||
Algorithm { algorithms: vec![
|
|
||||||
"insertSort".to_string(),
|
|
||||||
"bubbleSort".to_string(),
|
|
||||||
"bogoSort".to_string(),
|
|
||||||
"cocktailShaker".to_string(),
|
|
||||||
"binaryHeap".to_string(),
|
|
||||||
"quickSort".to_string(),
|
|
||||||
"radixSortMSD".to_string(),
|
|
||||||
"radixSortLSD".to_string()
|
|
||||||
] }
|
|
||||||
}
|
|
||||||
pub async fn run(length:usize, delay:f32, functionName:String){
|
|
||||||
let mut list:GuiVec = SortingList::new(length, delay).await;
|
|
||||||
list.randomize();
|
|
||||||
|
|
||||||
|
|
||||||
match functionName.as_str() {
|
|
||||||
"insertSort" => insertSort::insertSort(&mut list).await,
|
|
||||||
"bubbleSort" => bubbleSort::bubbleSort(&mut list).await,
|
|
||||||
"bogoSort" => bogoSort::bogoSort(&mut list).await,
|
|
||||||
"cocktailShaker" => coctailShaker::cocktailShaker(&mut list).await,
|
|
||||||
"binaryHeap" => binaryHeap::binaryHeap(&mut list).await,
|
|
||||||
"quickSort" => quickSort::quickSort(&mut list).await,
|
|
||||||
"radixSortMSD" => radixSort::radixSort(&mut list).await,
|
|
||||||
"radixSortLSD" => radixSortLSD::radixSort(&mut list).await,
|
|
||||||
_ => panic!("No algorithm with that name implemented!")
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if !list.done{
|
|
||||||
list.show().await
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn getAlgorithms(&self) -> &Vec<String>{
|
|
||||||
&self.algorithms
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
BIN
src/assets/LDF-ComicSans/LDFComicSans.ttf
Normal file
BIN
src/assets/LDF-ComicSans/LDFComicSans.ttf
Normal file
Binary file not shown.
|
@ -1,63 +1,24 @@
|
||||||
use macroquad::hash;
|
enum Status {
|
||||||
|
|
||||||
use macroquad::{ui::root_ui, window::screen_width, prelude::Vec2};
|
|
||||||
|
|
||||||
|
|
||||||
enum Status{
|
|
||||||
Open,
|
Open,
|
||||||
Closed
|
Closed,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct ButtonDropDown{
|
pub struct ButtonDropDown {
|
||||||
selected:String,
|
selected: String,
|
||||||
elements:Vec<String>,
|
elements: Vec<String>,
|
||||||
status:Status
|
status: Status,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ButtonDropDown{
|
impl ButtonDropDown {
|
||||||
pub fn new(elements:&Vec<String>) -> Self{
|
pub fn new(elements: &Vec<String>) -> Self {
|
||||||
ButtonDropDown{
|
ButtonDropDown {
|
||||||
selected:elements.get(0).unwrap().clone(),
|
selected: elements.get(0).unwrap().clone(),
|
||||||
elements:elements.clone(),
|
elements: elements.clone(),
|
||||||
status:Status::Closed
|
status: Status::Closed,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn render(&mut self) -> String{
|
pub fn render(&mut self) -> String {
|
||||||
let mut algo = "";
|
"LOL".to_string()
|
||||||
let location = Vec2::new((screen_width() / 2.) - 150., 200.);
|
|
||||||
match self.status{
|
|
||||||
|
|
||||||
Status::Open => {
|
|
||||||
let size = Vec2::new(300., (self.elements.len() as f32*25.0) + 20.0);
|
|
||||||
root_ui().window(hash!(), location, size, |ui|{
|
|
||||||
let mut position = Vec2::new(10.0, 10.);
|
|
||||||
|
|
||||||
for i in self.elements.iter(){
|
|
||||||
let label = format!("{}{}", i[0..1].to_string().to_uppercase(), i[1..i.len()].to_string());
|
|
||||||
if ui.button(position, label.as_str()){
|
|
||||||
self.selected = i.clone();
|
|
||||||
self.status = Status::Closed;
|
|
||||||
}
|
|
||||||
position.y += 25.0;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
Status::Closed => {
|
|
||||||
root_ui().window(hash!(), location, Vec2::new(300., 50.), |ui|{
|
|
||||||
let uppercasedSelected = format!("{}{}", self.selected[0..1].to_string().to_uppercase(), self.selected[1..self.selected.len()].to_string());
|
|
||||||
ui.label(Vec2::new(10.0, 0.0), format!("Curent chosen algorithm: {}", uppercasedSelected).as_str());
|
|
||||||
if ui.button(Vec2::new(10.0, 20.0), "Open Menu!"){
|
|
||||||
self.status = Status::Open;
|
|
||||||
}
|
|
||||||
if ui.button(Vec2::new(200.0, 20.0), "RUN!"){
|
|
||||||
algo = self.selected.as_str();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
algo.to_string()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
37
src/insertSortGenerator.rs
Normal file
37
src/insertSortGenerator.rs
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
use std::cell::RefCell;
|
||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
|
use futures_core::stream::Stream;
|
||||||
|
use futures_util::pin_mut;
|
||||||
|
use futures_util::stream::StreamExt;
|
||||||
|
|
||||||
|
pub fn insert_sort(
|
||||||
|
mut list: Vec<u32>,
|
||||||
|
) -> impl std::ops::Generator<Yield = Rc<RefCell<Vec<u32>>>, Return = ()> {
|
||||||
|
let list2 = Rc::new(RefCell::new(list));
|
||||||
|
let len = list2.borrow().len() - 1;
|
||||||
|
move || {
|
||||||
|
for index in 0..len {
|
||||||
|
let mut j = index;
|
||||||
|
while j > 0 && list2.borrow()[j] < list2.borrow()[j+1] {
|
||||||
|
{
|
||||||
|
list2.borrow_mut().swap(j, j-1);
|
||||||
|
}
|
||||||
|
yield list2.clone();
|
||||||
|
j -= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn test(
|
||||||
|
mut list: Vec<u32>,
|
||||||
|
) -> impl std::ops::Generator<Yield = Rc<RefCell<Vec<u32>>>, Return = ()> {
|
||||||
|
let list2 = Rc::new(RefCell::new(list));
|
||||||
|
let len = list2.borrow().len();
|
||||||
|
move || {
|
||||||
|
for index in 0..len {
|
||||||
|
yield list2.clone();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
132
src/main.rs
132
src/main.rs
|
@ -1,67 +1,81 @@
|
||||||
|
#![feature(generators, generator_trait)]
|
||||||
mod BarPlugin;
|
mod BarPlugin;
|
||||||
mod GuiHookVec;
|
|
||||||
mod algorithm;
|
|
||||||
mod dropdown;
|
mod dropdown;
|
||||||
mod soundGenerator;
|
|
||||||
use std::f32::consts::PI;
|
|
||||||
use std::fs::File;
|
|
||||||
use std::path::Path;
|
|
||||||
|
|
||||||
use dropdown::ButtonDropDown;
|
|
||||||
|
|
||||||
|
|
||||||
use macroquad::prelude::*;
|
|
||||||
|
|
||||||
use macroquad::hash;
|
|
||||||
use macroquad::ui::root_ui;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#[macroquad::main("BeepSort")]
|
|
||||||
async fn main() {
|
|
||||||
let mut length = 1_usize;
|
|
||||||
let mut lengthString = "100".to_owned();
|
|
||||||
|
|
||||||
let mut delayText = "1".to_owned();
|
|
||||||
|
|
||||||
let mut algorithm = algorithm::Algorithm::new();
|
|
||||||
let mut buttonDropDown = ButtonDropDown::new(&algorithm.getAlgorithms());
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
loop{
|
|
||||||
clear_background(WHITE);
|
|
||||||
|
|
||||||
length = match lengthString.parse::<usize>(){
|
|
||||||
Ok(a) => a,
|
|
||||||
Err(_)=> {100}
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut centerX = screen_width()/2.0;
|
|
||||||
|
|
||||||
|
|
||||||
draw_text("Sorting! Made by Polsevev", centerX-170.0, screen_height()*0.1, 100.0, BLACK);
|
|
||||||
draw_text(&get_fps().to_string(), centerX + 300., 30.0, 20.0, BLACK);
|
|
||||||
root_ui().window(hash!(), Vec2::new(centerX - 150.0, 150.), Vec2::new(300., 45.), |ui|{
|
|
||||||
ui.input_text(hash!(), "Delay (ms)", &mut delayText);
|
|
||||||
ui.input_text(hash!(), "Length Of Array!", &mut lengthString);
|
|
||||||
});
|
|
||||||
|
|
||||||
let mut algo = buttonDropDown.render();
|
|
||||||
|
|
||||||
if algo != ""{
|
|
||||||
algorithm::Algorithm::run(length, 1.0, algo.to_string()).await;
|
|
||||||
}
|
|
||||||
next_frame().await
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
use std::cell::RefCell;
|
||||||
|
use std::ops::{Generator, GeneratorState};
|
||||||
|
use std::pin::Pin;
|
||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
|
use anyhow::Result;
|
||||||
|
use insertSortGenerator::{insert_sort, test};
|
||||||
|
use notan::draw::*;
|
||||||
|
use notan::draw::{CreateDraw, CreateFont, DrawConfig, Font};
|
||||||
|
use notan::prelude::*;
|
||||||
|
mod insertSortGenerator;
|
||||||
|
#[derive(AppState)]
|
||||||
|
struct State {
|
||||||
|
gen: Box<dyn Unpin + Generator<Yield = Rc<RefCell<Vec<u32>>>, Return = ()>>,
|
||||||
|
delay: f32,
|
||||||
|
lastStepTime: f32,
|
||||||
|
font: Font,
|
||||||
|
next: Option<String>,
|
||||||
|
finished: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn setup(gfx: &mut Graphics) -> State {
|
||||||
|
let mut arr = (1..=100).collect::<Vec<u32>>();
|
||||||
|
let gen = insert_sort(arr);
|
||||||
|
State {
|
||||||
|
gen: Box::new(gen),
|
||||||
|
delay: 1.,
|
||||||
|
lastStepTime: 1.,
|
||||||
|
font: gfx
|
||||||
|
.create_font(include_bytes!("./assets/LDF-ComicSans/LDFComicSans.ttf"))
|
||||||
|
.unwrap(),
|
||||||
|
next: None,
|
||||||
|
finished: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[notan_main]
|
||||||
|
fn main() -> Result<(), String> {
|
||||||
|
notan::init_with(setup)
|
||||||
|
.update(update)
|
||||||
|
.draw(draw)
|
||||||
|
.add_config(DrawConfig)
|
||||||
|
.build()
|
||||||
|
}
|
||||||
|
fn update(state: &mut State) {
|
||||||
|
if !state.finished {
|
||||||
|
match Pin::new(&mut state.gen).resume(()) {
|
||||||
|
GeneratorState::Yielded(a) => {
|
||||||
|
state.next = Some(format!("{:?}", a));
|
||||||
|
println!("We set something")
|
||||||
|
}
|
||||||
|
GeneratorState::Complete(_) => {
|
||||||
|
state.finished = true;
|
||||||
|
println!("Generator finished");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn draw(gfx: &mut Graphics, state: &mut State) {
|
||||||
|
let mut draw = gfx.create_draw();
|
||||||
|
|
||||||
|
draw.clear(Color::BLACK);
|
||||||
|
|
||||||
|
let text = if state.next.is_some() {
|
||||||
|
state.next.clone().unwrap()
|
||||||
|
} else {
|
||||||
|
String::new()
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
gfx.render(&draw);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn drawArr(draw: &mut Draw, screen_width: u32, screen_height: u32){
|
||||||
|
draw.rect(, size)
|
||||||
|
}
|
|
@ -1,99 +0,0 @@
|
||||||
use std::{f32::consts::PI};
|
|
||||||
|
|
||||||
use macroquad::{audio::{Sound, load_sound_from_bytes, play_sound_once}, window::{next_frame, screen_width, screen_height, clear_background}, text::draw_text, prelude::{BLACK, WHITE}};
|
|
||||||
|
|
||||||
|
|
||||||
const CHUNK_ID:&str = "RIFF";
|
|
||||||
const CHUNK_SIZE:&str = "----";
|
|
||||||
const FORMAT:&str = "WAVE";
|
|
||||||
|
|
||||||
//FMT sub-chunk
|
|
||||||
const SUBCHUNK_1_ID:&str = "fmt ";
|
|
||||||
const SUBCHUNK_1_SIZE:i32 = 16;
|
|
||||||
const AUDIO_FORMAT:i16 = 1;
|
|
||||||
const NUM_CHANNELS:i16 = 1;
|
|
||||||
const SAMPLE_RATE:i32 = 44100;
|
|
||||||
const BYTE_RATE:i32 = SAMPLE_RATE * NUM_CHANNELS as i32 * (SUBCHUNK_1_SIZE / 8);
|
|
||||||
const BLOACK_ALIGN:i16 = NUM_CHANNELS * (SUBCHUNK_1_SIZE / 8) as i16;
|
|
||||||
const BITS_PR_SAMPLE:i16 = 16;
|
|
||||||
|
|
||||||
//Data sub-chunk
|
|
||||||
const SUBCHUNK_2_ID:&str = "data";
|
|
||||||
const SUBCHUNK_2_SIZE:&str = "----";
|
|
||||||
|
|
||||||
|
|
||||||
const MAX_AMPLITUDE:usize = 32760;
|
|
||||||
|
|
||||||
pub async fn generateTone(frequency: f32, duration:f32) -> Sound{
|
|
||||||
|
|
||||||
// const CHUNK_ID:&str = "RIFF";
|
|
||||||
// const CHUNK_SIZE:&str = "----";
|
|
||||||
// const FORMAT:&str = "WAVE";
|
|
||||||
|
|
||||||
// //FMT sub-chunk
|
|
||||||
// const SUBCHUNK_1_ID:&str = "fmt ";
|
|
||||||
// const SUBCHUNK_1_SIZE:u32 = 16;
|
|
||||||
// const AUDIO_FORMAT:u16 = 1;
|
|
||||||
// const NUM_CHANNELS:u16 = 1;
|
|
||||||
// const SAMPLE_RATE:u32 = 44100;
|
|
||||||
// const BYTE_RATE:u32 = SAMPLE_RATE * NUM_CHANNELS as u32 * (SUBCHUNK_1_SIZE / 8);
|
|
||||||
// const BLOACK_ALIGN:u16 = NUM_CHANNELS * (SUBCHUNK_1_SIZE / 8) as u16;
|
|
||||||
// const BITS_PR_SAMPLE:u16 = 16;
|
|
||||||
|
|
||||||
// //Data sub-chunk
|
|
||||||
// const SUBCHUNK_2_ID:&str = "data";
|
|
||||||
// const SUBCHUNK_2_SIZE:&str = "----";
|
|
||||||
|
|
||||||
|
|
||||||
// const MAX_AMPLITUDE:usize = 32760;
|
|
||||||
|
|
||||||
|
|
||||||
let mut soundFileBytes = [
|
|
||||||
CHUNK_ID.as_bytes(),
|
|
||||||
CHUNK_SIZE.as_bytes(),
|
|
||||||
FORMAT.as_bytes(),
|
|
||||||
SUBCHUNK_1_ID.as_bytes(),
|
|
||||||
&SUBCHUNK_1_SIZE.to_le_bytes(),
|
|
||||||
&AUDIO_FORMAT.to_le_bytes(),
|
|
||||||
&NUM_CHANNELS.to_le_bytes(),
|
|
||||||
&SAMPLE_RATE.to_le_bytes(),
|
|
||||||
&BYTE_RATE.to_le_bytes(),
|
|
||||||
&BLOACK_ALIGN.to_le_bytes(),
|
|
||||||
&BITS_PR_SAMPLE.to_le_bytes(),
|
|
||||||
SUBCHUNK_2_ID.as_bytes(),
|
|
||||||
SUBCHUNK_2_SIZE.as_bytes()
|
|
||||||
].concat();
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
let startAudio = soundFileBytes.len();
|
|
||||||
|
|
||||||
|
|
||||||
let lim = ((SAMPLE_RATE as f32 * duration) as usize);
|
|
||||||
for i in 0..((SAMPLE_RATE as f32 * duration) as usize){
|
|
||||||
let amplitude = 500. * f32::sin((i as f32 - 300.) / 1200.);
|
|
||||||
let value = f32::sin((2. * PI * (i as f32) * (frequency as f32)) / SAMPLE_RATE as f32);
|
|
||||||
let channel = (amplitude * if i+100 > lim {0.} else {value});
|
|
||||||
|
|
||||||
soundFileBytes.append(&mut (channel as i16).to_le_bytes().to_vec());
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
let endAudio = soundFileBytes.len() as u32;
|
|
||||||
|
|
||||||
for (i, elem) in (endAudio-startAudio as u32).to_le_bytes().into_iter().enumerate(){
|
|
||||||
soundFileBytes[(startAudio-4)+i] = elem;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
for (i, elem) in (36+endAudio-startAudio as u32).to_be_bytes().into_iter().enumerate(){
|
|
||||||
soundFileBytes[4+i] = elem;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
load_sound_from_bytes(&soundFileBytes).await.expect("Failed to load")
|
|
||||||
|
|
||||||
}
|
|
Loading…
Reference in a new issue