Add searching for players by name or discriminator

This commit is contained in:
Kiana Sheibani 2023-11-26 23:17:49 -05:00
parent 0c9d85666c
commit f7fa4c2085
Signed by: toki
GPG key ID: 6CB106C25E86A9F7
3 changed files with 104 additions and 15 deletions

View file

@ -327,6 +327,42 @@ pub fn get_player(connection: &Connection, player: PlayerId) -> sqlite::Result<P
}) })
} }
pub fn get_player_from_discrim(
connection: &Connection,
discrim: &str,
) -> sqlite::Result<PlayerData> {
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::<i64, _>("id")? as u64),
name: statement.read::<String, _>("name")?,
prefix: statement.read::<Option<String>, _>("prefix")?,
discrim: discrim.to_owned(),
})
}
pub fn match_player_name(connection: &Connection, name: &str) -> sqlite::Result<Vec<PlayerData>> {
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::<i64, _>("id") as u64),
name: r_.read::<&str, _>("name").to_owned(),
prefix: r_.read::<Option<&str>, _>("prefix").map(|x| x.to_owned()),
discrim: r_.read::<&str, _>("discrim").to_owned(),
})
})
.try_collect()
}
pub fn get_player_rating_data( pub fn get_player_rating_data(
connection: &Connection, connection: &Connection,
dataset: &str, dataset: &str,

View file

@ -80,13 +80,7 @@ created if it does not already exist."
Player { Player {
#[command(subcommand)] #[command(subcommand)]
subcommand: PlayerSC, subcommand: PlayerSC,
#[arg( #[arg(short, long, global = true, help = "The dataset to access")]
short,
long,
value_name = "DATASET",
global = true,
help = "The dataset to access"
)]
dataset: Option<String>, dataset: Option<String>,
}, },
} }
@ -465,17 +459,16 @@ fn player_info(dataset: Option<String>, player: String) {
let connection = let connection =
open_datasets(&config_dir).unwrap_or_else(|_| error("Could not open datasets file", 2)); open_datasets(&config_dir).unwrap_or_else(|_| error("Could not open datasets file", 2));
let player_id = PlayerId(player.parse::<u64>().unwrap());
let PlayerData { let PlayerData {
id: _, id,
name, name,
prefix, prefix,
discrim, 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) = let (deviation, volatility, _) = get_player_rating_data(&connection, &dataset, id)
get_player_rating_data(&connection, &dataset, player_id).unwrap(); .unwrap_or_else(|_| error("Could not find player", 1));
println!(); println!();
if let Some(pre) = prefix { if let Some(pre) = prefix {
@ -487,8 +480,8 @@ fn player_info(dataset: Option<String>, player: String) {
name, discrim name, discrim
); );
println!("\n\x1b[1mID:\x1b[0m {}", player_id.0); println!("\x1b[1mID:\x1b[0m {}", id.0);
println!("\x1b[1mDeviation:\x1b[0m {}", deviation); println!("\n\x1b[1mDeviation:\x1b[0m {}", deviation);
println!("\x1b[1mVolatility:\x1b[0m {}", volatility); println!("\x1b[1mVolatility:\x1b[0m {}", volatility);
} }

View file

@ -1,6 +1,10 @@
use sqlite::*;
use std::io::{self, Write}; use std::io::{self, Write};
use std::process::exit; use std::process::exit;
use crate::database::*;
use crate::queries::{PlayerData, PlayerId};
pub const SECS_IN_HR: u64 = 3600; pub const SECS_IN_HR: u64 = 3600;
pub const SECS_IN_DAY: u64 = SECS_IN_HR * 24; pub const SECS_IN_DAY: u64 = SECS_IN_HR * 24;
pub const SECS_IN_WEEK: u64 = SECS_IN_DAY * 7; 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)); .unwrap_or_else(|_| error("Could not read from stdin", 2));
line.trim().to_owned() 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::<u64>() {
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<PlayerData> {
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::<usize>()
.unwrap_or_else(|_| error("Not an integer", 1));
if index >= players.len() {
error("Out of range!", 1);
}
Ok(players[index].clone())
}
}
}
}