rewrote the list implementation to use traits for better mocking when testing

This commit is contained in:
Rolf Martin Glomsrud 2023-03-03 01:19:29 +01:00
parent c7b41c94c3
commit 70e2b4460c
4 changed files with 142 additions and 34 deletions

8
Cargo.lock generated
View file

@ -6,7 +6,7 @@ version = 3
name = "BeepSortMacroQuad" name = "BeepSortMacroQuad"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"async-recursion", "async-trait",
"macroquad", "macroquad",
] ]
@ -28,10 +28,10 @@ dependencies = [
] ]
[[package]] [[package]]
name = "async-recursion" name = "async-trait"
version = "1.0.2" version = "0.1.64"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3b015a331cc64ebd1774ba119538573603427eaace0a1950c423ab971f903796" checksum = "1cd7fce9ba8c3c042128ce72d8b2ddbf3a05747efb67ea0313c635e10bda47a2"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",

View file

@ -7,7 +7,7 @@ edition = "2021"
[dependencies] [dependencies]
macroquad = "0.3.25" macroquad = "0.3.25"
async-recursion = "1.0.2" async-trait = "0.1.64"
[toolchain] [toolchain]
channel = "nightly" channel = "nightly"
[profile.release] [profile.release]

View file

@ -1,11 +1,12 @@
use crate::BarPlugin::Bar; use crate::BarPlugin::Bar;
use crate::GuiHookVec;
use crate::GuiHookVec::GuiVec; 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::BinaryHeap;
use std::collections::HashMap; use std::collections::HashMap;
use std::collections::HashSet; use std::collections::HashSet;
@ -21,7 +22,7 @@ pub struct Algorithm{
impl Algorithm{ impl Algorithm{
pub async fn run(length:i32, delay:f32, functionName:String){ 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(); 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(){ for index in 0..list.len(){
let mut j = index; let mut j = index;
while j>0 && list.lessThan(j, j-1){ 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(); let n = list.len();
for i in 0..n { for i in 0..n {
for j in 0..(n - i - 1) { 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{ loop{
if list.swap(0,0).await {return}; 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 lowerBound = 0;
let mut upperBound = list.len()-1; let mut upperBound = list.len()-1;
let mut swapped = true; 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<i32, usize> = HashMap::new(); let mut indexMap:HashMap<i32, usize> = HashMap::new();
let mut binHeap:BinaryHeap<i32> = BinaryHeap::new(); let mut binHeap:BinaryHeap<i32> = 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; let mut pIndex = low;
for i in low..high{ 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 mut stack:Vec<(usize,usize)> = Vec::new();
let start = 0; let start = 0;
@ -177,7 +178,7 @@ impl Algorithm{
while stack.len() > 0{ while stack.len() > 0{
let (start,end) = stack.pop().unwrap(); 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 temp = Algorithm::partition(list, start, end, p).await;
let pivot = if temp >= 0 {temp} else {return}; 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; 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(){ if max < i.len(){
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]; let mut bucket = vec![vec![];10];
for (i, bar) in list.elements().enumerate(){ 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; let mut count = 0;
for i in sortedIndexes.clone(){ for i in sortedIndexes.clone(){
if list.set(count, listClone[i]).await {return true}; if list.set(count, listClone[i]).await {return true};

View file

@ -2,6 +2,7 @@
use std::borrow::{Borrow, BorrowMut}; use std::borrow::{Borrow, BorrowMut};
use std::ops::Add; use std::ops::Add;
use std::path::Iter; use std::path::Iter;
use async_trait::async_trait;
use macroquad::color::{BROWN, WHITE}; use macroquad::color::{BROWN, WHITE};
use macroquad::hash; use macroquad::hash;
use macroquad::prelude::{clear_background, Vec2, BLACK}; use macroquad::prelude::{clear_background, Vec2, BLACK};
@ -31,10 +32,40 @@ pub struct GuiVec{
skipped:i32 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<Bar>;
}
#[async_trait]
impl SortingList for GuiVec{
fn new(length:i32, delay:f32) -> Self {
let colorStep = 360./length as f32; let colorStep = 360./length as f32;
let mut list:Vec<Bar> = vec!(); let mut list:Vec<Bar> = vec!();
for i in 1..length+1 { 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 frames = 0.0;
let mut delayText = self.delay.to_string(); let mut delayText = self.delay.to_string();
let mut renderSkipText = self.renderSkip.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() 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.writes += 2;
self.reads += 2; self.reads += 2;
self.list.swap(index1, index2); self.list.swap(index1, index2);
self.draw().await; self.draw().await;
self.done self.done
} }
pub fn randomize(&mut self){ fn randomize(&mut self){
self.list.shuffle(); self.list.shuffle();
} }
pub fn elements(&mut self) -> std::slice::Iter<'_, Bar> { fn elements(&mut self) -> std::slice::Iter<'_, Bar> {
self.list.iter() self.list.iter()
} }
pub fn get(&mut self, i:usize)-> &Bar{ fn get(&mut self, i:usize)-> &Bar{
self.reads += 1; self.reads += 1;
self.list.get(i).unwrap() 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; self.comps += 1;
return self.get(a).position < self.get(b).position 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; self.comps += 1;
return self.get(a).position <= b return self.get(a).position <= b
} }
pub fn isSorted(&mut self) -> bool{ fn isSorted(&mut self) -> bool{
self.reads += self.len() as i32; self.reads += self.len() as i32;
let mut prev = 0; let mut prev = 0;
for bar in self.list.iter() { for bar in self.list.iter() {
@ -166,7 +197,7 @@ impl GuiVec{
} }
true 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.writes += 1;
self.reads += 1; self.reads += 1;
@ -175,7 +206,7 @@ impl GuiVec{
self.done self.done
} }
pub async fn show(&mut self){ async fn show(&mut self){
loop{ loop{
if !self.done{ if !self.done{
self.draw().await self.draw().await
@ -185,5 +216,81 @@ impl GuiVec{
} }
} }
fn getListClone(&self) -> Vec<Bar>{
self.list.clone()
}
} }
struct NonGuiVec{
pub list: Vec<Bar>,
}
#[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<Bar>{
self.list.clone()
}
}