use super::song::Song; use rand::seq::SliceRandom; use serenity::model::id::UserId; use std::collections::HashMap; use std::{cmp::min, collections::VecDeque}; #[derive(Clone)] pub struct SongQueue { queues: HashMap>, users: VecDeque, } impl SongQueue { pub fn new() -> SongQueue { SongQueue { queues: HashMap::new(), users: VecDeque::new(), } } fn new_user_queue(&mut self, user: UserId) { if self.queues.get(&user).is_none() { self.queues.insert(user, VecDeque::new()); } if !self.users.contains(&user) { self.users.push_back(user); } } pub fn push(&mut self, songs: Vec) { for song in songs.into_iter() { self.new_user_queue(song.queuer.id); let deque = self.queues.get_mut(&song.queuer.id).unwrap(); deque.push_back(song); } } pub fn peek(&self) -> Option { let user = match self.users.front() { Some(user) => user, None => return None, }; let deque = self.queues.get(&user).unwrap(); deque.front().cloned() } pub fn pop(&mut self) -> Option { let user = match self.users.pop_front() { Some(user) => user, None => return None, }; let deque = self.queues.get_mut(&user).unwrap(); let song = deque.pop_front(); if deque.len() > 0 { self.users.push_back(user); } song } pub fn shuffle(&mut self) -> Result<(), String> { if self.users.len() == 0 { return Err("queue is empty".to_string()); } for deque in self.queues.values_mut() { deque.make_contiguous().shuffle(&mut rand::thread_rng()); } Ok(()) } pub fn clear(&mut self) -> Result<(), String> { if self.users.len() == 0 { return Err("queue is empty".to_string()); }; self.queues.clear(); self.users.clear(); Ok(()) } pub fn get_string(&self) -> String { if self.users.len() == 0 { return "*empty*".to_string(); }; let mut s = String::new(); let queue = self.as_vec(); s.push_str(&format!( "*Showing {} of {} songs*\n", min(20, queue.len()), queue.len() )); for (i, song) in queue.iter().take(20).enumerate() { s += &format!( "{}: {} (queued by {})\n", i + 1, &song.get_string(), song.queuer.name ); } s } fn as_vec(&self) -> Vec { let mut clone = self.clone(); let mut queue = vec![]; while let Some(song) = clone.pop() { queue.push(song); } queue } }