From 98af8885a6cf2e616de03ae990af1d9663c6ba91 Mon Sep 17 00:00:00 2001 From: Arthur Roberts Date: Tue, 19 Aug 2025 22:02:18 +0100 Subject: [PATCH] Added searching by lower or card name Also added help strings --- scryfall_deser/src/db.rs | 36 ++++++++++++++++++++++-------------- scryfall_deser/src/lib.rs | 5 ++++- scryfall_deser/src/main.rs | 30 ++++++++++++++++++++++++------ 3 files changed, 50 insertions(+), 21 deletions(-) diff --git a/scryfall_deser/src/db.rs b/scryfall_deser/src/db.rs index 5e8b3c2..cc3ed72 100644 --- a/scryfall_deser/src/db.rs +++ b/scryfall_deser/src/db.rs @@ -1,4 +1,5 @@ use rusqlite; +use std::fmt; use std::fs; use std::path::PathBuf; use std::str::SplitWhitespace; @@ -88,18 +89,28 @@ pub struct DbCard { pub scryfall_uri: String, } -pub fn get_card_by_name(name: &str) -> DbCard { +pub enum GetNameType { + Name, + LowercaseName, +} + +pub fn get_card_by_name(name: &str, name_type: GetNameType) -> Option { let sqlite_file = get_local_data_sqlite_file(); let conn = rusqlite::Connection::open(sqlite_file).unwrap(); - let mut stmt = conn - .prepare( + let sql = match name_type { + GetNameType::Name => { "SELECT name, type_line, oracle_text, power_toughness, loyalty, mana_cost, scryfall_uri - FROM cards WHERE name = (?1)", - ) - .unwrap(); + FROM cards WHERE name = (?1)" + } + GetNameType::LowercaseName => { + "SELECT name, type_line, oracle_text, power_toughness, loyalty, mana_cost, scryfall_uri + FROM cards WHERE lowercase_name = (?1)" + } + }; + let mut stmt = conn.prepare(sql).unwrap(); let mut rows = stmt.query([name]).unwrap(); - let card = match rows.next().unwrap() { - Some(row) => DbCard { + match rows.next().unwrap() { + Some(row) => Some(DbCard { name: row.get(0).unwrap(), type_line: row.get(1).unwrap(), oracle_text: row.get(2).unwrap(), @@ -107,12 +118,9 @@ pub fn get_card_by_name(name: &str) -> DbCard { loyalty: row.get(4).unwrap(), mana_cost: row.get(5).unwrap(), scryfall_uri: row.get(6).unwrap(), - }, - None => { - panic!("{} isn't a card that exists", name); - } - }; - card + }), + None => None, + } } const CREATE_CARDS_TABLE_SQL: &str = " diff --git a/scryfall_deser/src/lib.rs b/scryfall_deser/src/lib.rs index 7665ce4..1cacae4 100644 --- a/scryfall_deser/src/lib.rs +++ b/scryfall_deser/src/lib.rs @@ -5,7 +5,10 @@ mod deser; pub use crate::deser::ScryfallCard; mod db; -pub use db::{get_all_lowercase_card_names, get_card_by_name, init_db, update_db_with_file}; +pub use db::{ + get_all_card_names, get_all_lowercase_card_names, get_card_by_name, init_db, + update_db_with_file, GetNameType, +}; mod utils; pub use utils::get_local_cache_folder; diff --git a/scryfall_deser/src/main.rs b/scryfall_deser/src/main.rs index 8a3541f..a36a45d 100644 --- a/scryfall_deser/src/main.rs +++ b/scryfall_deser/src/main.rs @@ -4,14 +4,17 @@ use scryfall_deser::get_card_by_name; use scryfall_deser::get_local_cache_folder; use scryfall_deser::init_db; use scryfall_deser::update_db_with_file; +use scryfall_deser::GetNameType; use textdistance::str::damerau_levenshtein; #[derive(Parser, Debug)] #[command(version, about, long_about = None)] struct Args { + /// Download the latest bulk from Scryfall and update local db #[arg(short, long)] update: bool, - remainder: Vec, + /// Text to search for card with + search_text: Vec, } fn main() { @@ -24,14 +27,14 @@ fn main() { update_db_with_file(path); return; } - let card_name = args.remainder; + let card_name = args.search_text; if card_name.is_empty() { panic!("You need to put some card text to search"); } let search_string = card_name.join(" "); - //dbg!(&search_string); + let cards = get_all_lowercase_card_names(); - //dbg!(&cards); + let mut matching_cards = Vec::new(); for card in cards { if card.contains(&search_string) { @@ -40,8 +43,23 @@ fn main() { } if matching_cards.is_empty() { // Do some distance checking stuff + } else if matching_cards.len() == 1 { + let card = get_card_by_name(&matching_cards[0], GetNameType::LowercaseName); + dbg!(card); + } else { + // This will be the harder part I think } - //dbg!(matching_cards); - let card = get_card_by_name("Black Lotus"); + + /* For testing - all seemed to work alright + let card = get_card_by_name("Black Lotus", GetNameType::Name); dbg!(card); + let cards = get_all_card_names(); + for card in cards { + let card = get_card_by_name(&card); + dbg!(&card); + if card.is_none() { + panic!("None card for {:?}", card); + } + } + */ }