From f7fa4c20854ecdd06d80e5c13e4cb748657856bd Mon Sep 17 00:00:00 2001 From: Kiana Sheibani Date: Sun, 26 Nov 2023 23:17:49 -0500 Subject: [PATCH] Add searching for players by name or discriminator --- src/database.rs | 36 +++++++++++++++++++++++++++++ src/main.rs | 23 +++++++------------ src/util.rs | 60 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 104 insertions(+), 15 deletions(-) diff --git a/src/database.rs b/src/database.rs index d1dc96a..22c0f3f 100644 --- a/src/database.rs +++ b/src/database.rs @@ -327,6 +327,42 @@ pub fn get_player(connection: &Connection, player: PlayerId) -> sqlite::Result

sqlite::Result { + let query = "SELECT id, name, prefix FROM players WHERE discrim = ?"; + + let mut statement = connection.prepare(&query)?; + statement.bind((1, discrim))?; + statement.next()?; + Ok(PlayerData { + id: PlayerId(statement.read::("id")? as u64), + name: statement.read::("name")?, + prefix: statement.read::, _>("prefix")?, + discrim: discrim.to_owned(), + }) +} + +pub fn match_player_name(connection: &Connection, name: &str) -> sqlite::Result> { + let query = "SELECT * FROM players WHERE name LIKE ?"; + + connection + .prepare(&query)? + .into_iter() + .bind((1, &format!("%{}%", name)[..]))? + .map(|r| { + let r_ = r?; + Ok(PlayerData { + id: PlayerId(r_.read::("id") as u64), + name: r_.read::<&str, _>("name").to_owned(), + prefix: r_.read::, _>("prefix").map(|x| x.to_owned()), + discrim: r_.read::<&str, _>("discrim").to_owned(), + }) + }) + .try_collect() +} + pub fn get_player_rating_data( connection: &Connection, dataset: &str, diff --git a/src/main.rs b/src/main.rs index 4929dde..15c79bb 100644 --- a/src/main.rs +++ b/src/main.rs @@ -80,13 +80,7 @@ created if it does not already exist." Player { #[command(subcommand)] subcommand: PlayerSC, - #[arg( - short, - long, - value_name = "DATASET", - global = true, - help = "The dataset to access" - )] + #[arg(short, long, global = true, help = "The dataset to access")] dataset: Option, }, } @@ -465,17 +459,16 @@ fn player_info(dataset: Option, player: String) { let connection = open_datasets(&config_dir).unwrap_or_else(|_| error("Could not open datasets file", 2)); - let player_id = PlayerId(player.parse::().unwrap()); - let PlayerData { - id: _, + id, name, prefix, discrim, - } = get_player(&connection, player_id).unwrap(); + } = get_player_from_input(&connection, player) + .unwrap_or_else(|_| error("Could not find player", 1)); - let (deviation, volatility, last_played) = - get_player_rating_data(&connection, &dataset, player_id).unwrap(); + let (deviation, volatility, _) = get_player_rating_data(&connection, &dataset, id) + .unwrap_or_else(|_| error("Could not find player", 1)); println!(); if let Some(pre) = prefix { @@ -487,8 +480,8 @@ fn player_info(dataset: Option, player: String) { name, discrim ); - println!("\n\x1b[1mID:\x1b[0m {}", player_id.0); - println!("\x1b[1mDeviation:\x1b[0m {}", deviation); + println!("\x1b[1mID:\x1b[0m {}", id.0); + println!("\n\x1b[1mDeviation:\x1b[0m {}", deviation); println!("\x1b[1mVolatility:\x1b[0m {}", volatility); } diff --git a/src/util.rs b/src/util.rs index 5403663..9980b16 100644 --- a/src/util.rs +++ b/src/util.rs @@ -1,6 +1,10 @@ +use sqlite::*; use std::io::{self, Write}; use std::process::exit; +use crate::database::*; +use crate::queries::{PlayerData, PlayerId}; + pub const SECS_IN_HR: u64 = 3600; pub const SECS_IN_DAY: u64 = SECS_IN_HR * 24; pub const SECS_IN_WEEK: u64 = SECS_IN_DAY * 7; @@ -25,3 +29,59 @@ pub fn read_string() -> String { .unwrap_or_else(|_| error("Could not read from stdin", 2)); line.trim().to_owned() } + +pub enum PlayerInput { + Id(PlayerId), + Discrim(String), + Name(String), +} + +pub fn parse_player_input(input: String) -> PlayerInput { + if let Ok(id) = input.parse::() { + PlayerInput::Id(PlayerId(id)) + } else if input.chars().all(|c| c.is_ascii_hexdigit()) { + PlayerInput::Discrim(input) + } else { + PlayerInput::Name(input) + } +} + +pub fn get_player_from_input(connection: &Connection, input: String) -> sqlite::Result { + match parse_player_input(input) { + PlayerInput::Id(id) => get_player(connection, id), + PlayerInput::Discrim(discrim) => get_player_from_discrim(connection, &discrim), + PlayerInput::Name(name) => { + let players = match_player_name(connection, &name)?; + + if players.is_empty() { + error(&format!("Player {:?} not found", name), 1); + } else if players.len() == 1 { + Ok(players.into_iter().next().unwrap()) + } else { + println!("\nInput {:?} matches more than one player:\n", name); + + for (i, player) in players.iter().enumerate() { + print!("{} - ", i); + if let Some(pre) = player.prefix.clone() { + print!("\x1b[2m{}\x1b[22m ", pre); + } + println!( + "\x1b[4m\x1b]8;;https://www.start.gg/user/{1}\x1b\\\ +\x1b[1m{0}\x1b[22m\x1b]8;;\x1b\\\x1b[0m ({1})", + player.name, player.discrim + ) + } + + print!("\nPlayer (0-{}): ", players.len() - 1); + let index = read_string() + .parse::() + .unwrap_or_else(|_| error("Not an integer", 1)); + if index >= players.len() { + error("Out of range!", 1); + } + + Ok(players[index].clone()) + } + } + } +}