From 2f0af295cd75d64943edb4f1af0ebcd950297893 Mon Sep 17 00:00:00 2001 From: Nathan Perry Date: Mon, 18 Feb 2019 21:30:14 -0500 Subject: improve randomizer --- src/commands/meme.rs | 28 +++++----------------------- src/db/mod.rs | 44 ++++++++++++++++++++++++++------------------ 2 files changed, 31 insertions(+), 41 deletions(-) diff --git a/src/commands/meme.rs b/src/commands/meme.rs index 9cba630..0f9cda8 100644 --- a/src/commands/meme.rs +++ b/src/commands/meme.rs @@ -30,7 +30,10 @@ use crate::{ PlayQueue, }, commands::send, - db::*, + db::{ + *, + rand_meme as db_rand_meme, + }, Result, }; @@ -238,29 +241,8 @@ fn rand_meme(ctx: &Context, message: &Message) -> Result<()> { let conn = connection()?; let should_audio = ctx.currently_playing() && ctx.users_listening()?; - let modulus = if should_audio { 3 } else { 2 }; - let mem = match thread_rng().gen::() % modulus { - 0 => rand_text(&conn), - 1 => rand_image(&conn), - 2 => rand_audio(&conn), - _ => unreachable!(), - } - .or_else(|_| rand_text(&conn)) - .and_then(|mut mem| { - let mut ctr = 0; - while !should_audio && mem.audio_id.is_some() { - mem = rand_text(&conn)?; - - ctr += 1; - if ctr > 10 { - send(message.channel_id, "yer listenin to somethin else", message.tts)?; - bail!("looped too many times trying to find a non-audio meme"); - } - } - - Ok(mem) - }); + let mem = db_rand_meme(&conn, should_audio); match mem { Ok(mem) => { diff --git a/src/db/mod.rs b/src/db/mod.rs index 1ff05ce..1c2a032 100644 --- a/src/db/mod.rs +++ b/src/db/mod.rs @@ -102,26 +102,34 @@ pub fn delete_meme>(conn: &PgConnection, search: T, deleted_by: u6 }) } -pub fn rand_text(conn: &PgConnection) -> Result { - memes::table - .filter(memes::content.is_not_null()) - .order(random.desc()) - .first::(conn) - .map_err(Error::from) -} - -pub fn rand_image(conn: &PgConnection) -> Result { - memes::table - .filter(memes::image_id.is_not_null()) - .order(random.desc()) - .first::(conn) - .map_err(Error::from) -} +pub fn rand_meme(conn: &PgConnection, audio: bool) -> Result { + use rand::{thread_rng, seq::SliceRandom}; + use failure::err_msg; + use std::ops::Try; + + let ids: Vec = if audio { + memes::table + .select(memes::id) + .filter(memes::content.is_not_null() + .or(memes::image_id.is_not_null()) + .or(memes::audio_id.is_not_null())) + .load(conn) + .map_err(Error::from)? + } else { + memes::table + .select(memes::id) + .filter(memes::content.is_not_null() + .or(memes::image_id.is_not_null())) + .load(conn) + .map_err(Error::from)? + }; + + let id = ids.choose(&mut thread_rng()) + .into_result() + .map_err( |_| err_msg("couldn't load meme"))?; -pub fn rand_audio(conn: &PgConnection) -> Result { memes::table - .filter(memes::audio_id.is_not_null()) - .order(random.desc()) + .find(id) .first::(conn) .map_err(Error::from) } -- cgit v1.3.1