From 70e2b4460c14d8727aa8960b9c4b1103fd467192 Mon Sep 17 00:00:00 2001 From: polsevev Date: Fri, 3 Mar 2023 01:19:29 +0100 Subject: [PATCH] rewrote the list implementation to use traits for better mocking when testing --- Cargo.lock | 8 +-- Cargo.toml | 2 +- src/Algorithm.rs | 33 ++++++------ src/GuiHookVec.rs | 133 +++++++++++++++++++++++++++++++++++++++++----- 4 files changed, 142 insertions(+), 34 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b4a9a38..328ae04 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6,7 +6,7 @@ version = 3 name = "BeepSortMacroQuad" version = "0.1.0" dependencies = [ - "async-recursion", + "async-trait", "macroquad", ] @@ -28,10 +28,10 @@ dependencies = [ ] [[package]] -name = "async-recursion" -version = "1.0.2" +name = "async-trait" +version = "0.1.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b015a331cc64ebd1774ba119538573603427eaace0a1950c423ab971f903796" +checksum = "1cd7fce9ba8c3c042128ce72d8b2ddbf3a05747efb67ea0313c635e10bda47a2" dependencies = [ "proc-macro2", "quote", diff --git a/Cargo.toml b/Cargo.toml index b126d86..344d22c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,7 +7,7 @@ edition = "2021" [dependencies] macroquad = "0.3.25" -async-recursion = "1.0.2" +async-trait = "0.1.64" [toolchain] channel = "nightly" [profile.release] diff --git a/src/Algorithm.rs b/src/Algorithm.rs index d5d96bb..9eb7d1a 100644 --- a/src/Algorithm.rs +++ b/src/Algorithm.rs @@ -1,11 +1,12 @@ use crate::BarPlugin::Bar; +use crate::GuiHookVec; use crate::GuiHookVec::GuiVec; +use crate::GuiHookVec::SortingList; + + -use async_recursion::async_recursion; -use macroquad::prelude::screen_width; -use macroquad::window::screen_height; use std::collections::BinaryHeap; use std::collections::HashMap; use std::collections::HashSet; @@ -21,7 +22,7 @@ pub struct Algorithm{ impl Algorithm{ pub async fn run(length:i32, delay:f32, functionName:String){ - let mut list = GuiVec::new(length, delay); + let mut list:GuiVec = SortingList::new(length, delay); list.randomize(); @@ -43,7 +44,7 @@ impl Algorithm{ } } - pub async fn insertSort(list:&mut GuiVec){ + pub async fn insertSort(list:&mut impl SortingList){ for index in 0..list.len(){ let mut j = index; while j>0 && list.lessThan(j, j-1){ @@ -73,7 +74,7 @@ impl Algorithm{ } */ - pub async fn bubbleSort(list:&mut GuiVec){ + pub async fn bubbleSort(list:&mut impl SortingList){ let n = list.len(); for i in 0..n { for j in 0..(n - i - 1) { @@ -85,7 +86,7 @@ impl Algorithm{ } - pub async fn bogoSort(list:&mut GuiVec){ + pub async fn bogoSort(list:&mut impl SortingList){ loop{ if list.swap(0,0).await {return}; @@ -96,7 +97,7 @@ impl Algorithm{ } } - pub async fn cocktailShaker(list:&mut GuiVec){ + pub async fn cocktailShaker(list:&mut impl SortingList){ let mut lowerBound = 0; let mut upperBound = list.len()-1; let mut swapped = true; @@ -127,7 +128,7 @@ impl Algorithm{ } - pub async fn binaryHeap(list:&mut GuiVec){ + pub async fn binaryHeap(list:&mut impl SortingList){ let mut indexMap:HashMap = HashMap::new(); let mut binHeap:BinaryHeap = BinaryHeap::new(); @@ -151,7 +152,7 @@ impl Algorithm{ - pub async fn partition(list:&mut GuiVec, mut low:usize, mut high:usize, p:i32) -> i32{ + pub async fn partition(list:&mut impl SortingList, mut low:usize, mut high:usize, p:i32) -> i32{ let mut pIndex = low; for i in low..high{ @@ -166,7 +167,7 @@ impl Algorithm{ } - pub async fn quickSort(list:&mut GuiVec) { + pub async fn quickSort(list:&mut impl SortingList) { let mut stack:Vec<(usize,usize)> = Vec::new(); let start = 0; @@ -177,7 +178,7 @@ impl Algorithm{ while stack.len() > 0{ let (start,end) = stack.pop().unwrap(); - let p = list.list[end].position; + let p = list.get(end).position; let temp = Algorithm::partition(list, start, end, p).await; let pivot = if temp >= 0 {temp} else {return}; @@ -193,10 +194,10 @@ impl Algorithm{ } - pub async fn radixSort(list:&mut GuiVec) { + pub async fn radixSort(list:&mut impl SortingList) { let mut max = usize::MAX; - for i in list.list.clone().into_iter().map(|x| x.position.to_string()){ + for i in list.getListClone().into_iter().map(|x| x.position.to_string()){ if max < i.len(){ max = i.len(); } @@ -207,7 +208,7 @@ impl Algorithm{ } } - pub async fn radix(list:&mut GuiVec, radix:usize) -> bool{ + pub async fn radix(list:&mut impl SortingList, radix:usize) -> bool{ let mut bucket = vec![vec![];10]; for (i, bar) in list.elements().enumerate(){ @@ -229,7 +230,7 @@ impl Algorithm{ } } - let mut listClone = list.list.clone(); + let mut listClone = list.getListClone(); let mut count = 0; for i in sortedIndexes.clone(){ if list.set(count, listClone[i]).await {return true}; diff --git a/src/GuiHookVec.rs b/src/GuiHookVec.rs index 7123b09..6031fa8 100644 --- a/src/GuiHookVec.rs +++ b/src/GuiHookVec.rs @@ -2,6 +2,7 @@ use std::borrow::{Borrow, BorrowMut}; use std::ops::Add; use std::path::Iter; +use async_trait::async_trait; use macroquad::color::{BROWN, WHITE}; use macroquad::hash; use macroquad::prelude::{clear_background, Vec2, BLACK}; @@ -31,10 +32,40 @@ pub struct GuiVec{ skipped:i32 } +#[async_trait] +pub trait SortingList{ -impl GuiVec{ + fn new(length:i32, delay:f32) -> Self; + + fn len(&self) -> usize; + + async fn swap(&mut self, index1:usize, index2:usize) -> bool; + + async fn draw(&mut self); - pub fn new(length:i32, delay:f32) -> 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:i32) -> 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; +} +#[async_trait] +impl SortingList for GuiVec{ + + fn new(length:i32, delay:f32) -> Self { let colorStep = 360./length as f32; let mut list:Vec = vec!(); for i in 1..length+1 { @@ -55,7 +86,7 @@ impl GuiVec{ } } - pub async fn draw(&mut self){ + async fn draw(&mut self){ let mut frames = 0.0; let mut delayText = self.delay.to_string(); let mut renderSkipText = self.renderSkip.to_string(); @@ -123,38 +154,38 @@ impl GuiVec{ } - pub fn len(&self) -> usize{ + fn len(&self) -> usize{ self.list.len() } - pub async fn swap(&mut self, index1:usize, index2:usize) -> bool{ + async fn swap(&mut self, index1:usize, index2:usize) -> bool{ self.writes += 2; self.reads += 2; self.list.swap(index1, index2); self.draw().await; self.done } - pub fn randomize(&mut self){ + fn randomize(&mut self){ self.list.shuffle(); } - pub fn elements(&mut self) -> std::slice::Iter<'_, Bar> { + fn elements(&mut self) -> std::slice::Iter<'_, Bar> { self.list.iter() } - pub fn get(&mut self, i:usize)-> &Bar{ + fn get(&mut self, i:usize)-> &Bar{ self.reads += 1; self.list.get(i).unwrap() } - pub fn lessThan(&mut self, a:usize, b:usize) -> bool{ + fn lessThan(&mut self, a:usize, b:usize) -> bool{ self.comps += 1; return self.get(a).position < self.get(b).position } - pub fn lessThanEqual(&mut self, a:usize, b:i32) -> bool{ + fn lessThanEqual(&mut self, a:usize, b:i32) -> bool{ self.comps += 1; return self.get(a).position <= b } - pub fn isSorted(&mut self) -> bool{ + fn isSorted(&mut self) -> bool{ self.reads += self.len() as i32; let mut prev = 0; for bar in self.list.iter() { @@ -166,7 +197,7 @@ impl GuiVec{ } true } - pub async fn set(&mut self, i:usize, elem:Bar) -> bool{ + async fn set(&mut self, i:usize, elem:Bar) -> bool{ self.writes += 1; self.reads += 1; @@ -175,7 +206,7 @@ impl GuiVec{ self.done } - pub async fn show(&mut self){ + async fn show(&mut self){ loop{ if !self.done{ self.draw().await @@ -185,5 +216,81 @@ impl GuiVec{ } } + fn getListClone(&self) -> Vec{ + self.list.clone() + } + } +struct NonGuiVec{ + pub list: Vec, + +} +#[async_trait] +impl SortingList for NonGuiVec{ + fn new(length:i32, delay:f32) -> Self{ + let mut list = Vec::new(); + for i in 0..(length as usize){ + list.push(Bar::new(i as i32, 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:i32) -> 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{ + self.list.clone() + } + +}