diff --git a/Cargo.lock b/Cargo.lock index b52e8c5..b2b05e1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,59 +2,12 @@ # It is not intended for manual editing. version = 3 -[[package]] -name = "atty" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" -dependencies = [ - "hermit-abi", - "libc", - "winapi", -] - -[[package]] -name = "autocfg" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" - -[[package]] -name = "bitflags" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" - [[package]] name = "cfg-if" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" -[[package]] -name = "clap" -version = "3.2.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ea181bf566f71cb9a5d17a59e1871af638180a18fb0035c92ae62b705207123" -dependencies = [ - "atty", - "bitflags", - "clap_lex", - "indexmap", - "strsim", - "termcolor", - "textwrap", -] - -[[package]] -name = "clap_lex" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2850f2f5a82cbf437dd5af4d49848fbdfc27c157c3d010345776f952765261c5" -dependencies = [ - "os_str_bytes", -] - [[package]] name = "getrandom" version = "0.2.12" @@ -66,31 +19,6 @@ dependencies = [ "wasi", ] -[[package]] -name = "hashbrown" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" - -[[package]] -name = "hermit-abi" -version = "0.1.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" -dependencies = [ - "libc", -] - -[[package]] -name = "indexmap" -version = "1.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" -dependencies = [ - "autocfg", - "hashbrown", -] - [[package]] name = "itoa" version = "1.0.10" @@ -104,16 +32,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" [[package]] -name = "os_str_bytes" -version = "6.6.1" +name = "once_cell" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2355d85b9a3786f481747ced0e0ff2ba35213a1f9bd406ed906554d7af805a1" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" [[package]] name = "pokerust" version = "0.1.0" dependencies = [ - "clap", + "once_cell", "rand", "serde", "serde_json", @@ -210,38 +138,17 @@ dependencies = [ "serde", ] -[[package]] -name = "strsim" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" - [[package]] name = "syn" -version = "2.0.53" +version = "2.0.55" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7383cd0e49fff4b6b90ca5670bfd3e9d6a733b3f90c686605aa7eec8c4996032" +checksum = "002a1b3dbf967edfafc32655d0f377ab0bb7b994aa1d32c8cc7e9b8bf3ebb8f0" dependencies = [ "proc-macro2", "quote", "unicode-ident", ] -[[package]] -name = "termcolor" -version = "1.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" -dependencies = [ - "winapi-util", -] - -[[package]] -name = "textwrap" -version = "0.16.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23d434d3f8967a09480fb04132ebe0a3e088c173e6d0ee7897abbdf4eab0f8b9" - [[package]] name = "unicode-ident" version = "1.0.12" @@ -253,34 +160,3 @@ name = "wasi" version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" - -[[package]] -name = "winapi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" -dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", -] - -[[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" - -[[package]] -name = "winapi-util" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596" -dependencies = [ - "winapi", -] - -[[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" diff --git a/Cargo.toml b/Cargo.toml index 026d871..e394dee 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +rand = "0.8" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" -clap = "3.0" -rand = "0.8" +once_cell = "1.8.0" diff --git a/src/main.rs b/src/main.rs index ab24a94..0984506 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,139 +1,196 @@ -use clap::{App, Arg}; -use rand::{thread_rng, Rng}; -use serde::{Deserialize, Serialize}; -use std::fs; -use std::{fs::File, io::Read, path::Path}; +use rand::Rng; +use std::io::prelude::*; -fn main() { - let matches = App::new("pokemon-colorscripts") - .version("0.1.0") - .author("Your Name") - .about("Displays Pokemon in your terminal") - .arg( - Arg::with_name("list") - .short('l') - .long("list") - .help("Print list of all Pokemon"), - ) - .arg( - Arg::with_name("name") - .short('n') - .long("name") - .value_name("NAME") - .help("Select Pokémon by name.") - .takes_value(true), - ) - .arg( - Arg::with_name("form") - .short('f') - .long("form") - .value_name("FORM") - .help("Show an alternate form of a Pokémon") - .takes_value(true), - ) - .arg( - Arg::with_name("shiny") - .short('s') - .long("shiny") - .help("Show the shiny version of the Pokémon instead"), - ) - .arg( - Arg::with_name("big") - .short('b') - .long("big") - .help("Show a larger version of the sprite"), - ) - .arg( - Arg::with_name("random") - .short('r') - .long("random") - .value_name("GEN") - .help("Show a random Pokémon. Optionally specify a generation.") - .takes_value(true), - ) - // Add more arguments as per your Python script - .get_matches(); +// set global constants +const PROGRAM: once_cell::sync::Lazy = + once_cell::sync::Lazy::new(|| std::env::current_exe().unwrap()); - if matches.is_present("list") { - list_pokemon_names(); +const PROGRAM_DIR: once_cell::sync::Lazy = once_cell::sync::Lazy::new(|| { + std::path::PathBuf::from(std::env::current_exe().unwrap().parent().unwrap()) +}); + +const COLORSCRIPTS_DIR: once_cell::sync::Lazy = + once_cell::sync::Lazy::new(|| PROGRAM_DIR.join("colorscripts")); + +const REGULAR_SUBDIR: &str = "regular"; +const SHINY_SUBDIR: &str = "shiny"; + +const LARGE_SUBDIR: &str = "large"; +const SMALL_SUBDIR: &str = "small"; + +const SHINY_RATE: f64 = 1.0 / 128.0; + +const GENERATIONS: [(&str, (u32, u32)); 8] = [ + ("1", (1, 151)), + ("2", (152, 251)), + ("3", (252, 386)), + ("4", (387, 493)), + ("5", (494, 649)), + ("6", (650, 721)), + ("7", (722, 809)), + ("8", (810, 898)), +]; + +fn print_file(filepath: &std::path::Path) -> std::io::Result<()> { + let file = std::fs::File::open(filepath)?; + let reader = std::io::BufReader::new(file); + + for line in reader.lines() { + println!("{}", line?); } - if let Some(name) = matches.value_of("name") { - let shiny = matches.is_present("shiny"); - let is_large = matches.is_present("big"); - let form = matches.value_of("form"); - show_pokemon_by_name(name, shiny, is_large, form); - } else if matches.is_present("random") { - let generation = matches.value_of("random"); - let shiny = matches.is_present("shiny"); - let is_large = matches.is_present("big"); - show_random_pokemon(generation, shiny, is_large); - } - // Handle other commands similarly + Ok(()) } -#[derive(Serialize, Deserialize)] -struct Pokemon { - name: String, - // Define other fields as needed -} +fn list_pokemon_names(filepath: &std::path::Path) -> std::io::Result<()> { + let file = std::fs::File::open(filepath)?; + let reader = std::io::BufReader::new(file); + let pokemon_json: serde_json::Value = serde_json::from_reader(reader)?; -fn load_pokemon_data() -> Vec { - let path = Path::new("pokemon.json"); - let mut file = File::open(&path).expect("File not found"); - let mut contents = String::new(); - file.read_to_string(&mut contents) - .expect("Failed to read file"); + let mut count = 0; - serde_json::from_str(&contents).expect("Failed to parse JSON") -} - -fn list_pokemon_names() { - let pokemon_list = load_pokemon_data(); - for pokemon in pokemon_list { - println!("{}", pokemon.name); - } -} - -fn print_file(filepath: &str) { - match fs::read_to_string(filepath) { - Ok(contents) => println!("{}", contents), - Err(e) => eprintln!("Error reading file: {}", e), - } -} - -fn show_pokemon_by_name(name: &str, shiny: bool, is_large: bool, form: Option<&str>) { - let color_subdir = if shiny { "shiny" } else { "regular" }; - let size_subdir = if is_large { "large" } else { "small" }; - let mut pokemon_name = name.to_string(); - - if let Some(f) = form { - pokemon_name.push_str("-"); - pokemon_name.push_str(f); + if let serde_json::Value::Array(array) = pokemon_json { + for pokemon in array { + if let Some(name) = pokemon.get("name") { + if let serde_json::Value::String(name_str) = name { + println!("{}", name_str); + count += 1; + } + } + } } - let filepath = format!( - "{}/{}/{}/{}", - "path_to_colorscripts_dir", size_subdir, color_subdir, pokemon_name - ); + println!("Total: {} Pokémons", count); - println!("Showing: {}", pokemon_name); - print_file(&filepath); + Ok(()) } -fn show_random_pokemon(generation: Option<&str>, shiny: bool, is_large: bool) { - let pokemon_list = load_pokemon_data(); - // Simplified: Add logic to filter Pokémon based on the generation range - let mut rng = thread_rng(); - let pokemon_index = rng.gen_range(0..pokemon_list.len()); - let pokemon_name = &pokemon_list[pokemon_index].name; +fn show_pokemon_by_name( + name: &str, + show_title: bool, + shiny: bool, + is_large: bool, + form: Option<&str>, +) -> std::io::Result<()> { + // set variables + let base_path = COLORSCRIPTS_DIR; + let color_subdir = if shiny { SHINY_SUBDIR } else { REGULAR_SUBDIR }; + let size_subdir = if is_large { LARGE_SUBDIR } else { SMALL_SUBDIR }; - // Determine shininess based on a random chance or if explicitly requested - let is_shiny = if shiny { - true + let file = std::fs::File::open(PROGRAM_DIR.join("pokemon.json"))?; + let reader = std::io::BufReader::new(file); + let pokemon_json: serde_json::Value = serde_json::from_reader(reader)?; + + let pokemon_names: Vec<&str> = pokemon_json + .as_array() + .unwrap() + .iter() + .map(|pokemon| pokemon["name"].as_str().unwrap()) + .collect(); + + if !pokemon_names.contains(&name) { + println!("Invalid pokemon {}", name); + std::process::exit(1); + } + + let mut name = name.to_string(); + + if let Some(form) = form { + let forms: Vec<&str> = pokemon_json + .as_array() + .unwrap() + .iter() + .filter(|pokemon| pokemon["name"].as_str().unwrap() == name) + .flat_map(|pokemon| pokemon["forms"].as_array().unwrap().iter()) + .map(|form| form.as_str().unwrap()) + .collect(); + + let alternate_forms: Vec<&str> = + forms.iter().filter(|&f| *f != "regular").cloned().collect(); + + if alternate_forms.contains(&form) { + name.push_str(&format!("-{}", form)); + } else { + println!("Invalid form '{}' for pokemon {}", form, name); + if alternate_forms.is_empty() { + println!("No alternate forms available for {}", name); + } else { + println!("Available alternate forms are"); + for form in alternate_forms { + println!("- {}", form); + } + } + std::process::exit(1); + } + } + + let pokemon_file = base_path.join(size_subdir).join(color_subdir).join(&name); + + if show_title { + if shiny { + println!("{} (shiny)", name); + } else { + println!("{}", name); + } + } + + print_file(&pokemon_file) +} + +fn show_random_pokemon( + generations: &str, + show_title: bool, + shiny: bool, + is_large: bool, +) -> std::io::Result<()> { + let mut rng = rand::thread_rng(); + + let (start_gen, end_gen) = if generations.is_empty() { + ("1", "8") + } else if generations.contains(",") { + let gens: Vec<&str> = generations.split(",").collect(); + let gen = gens[rng.gen_range(0..gens.len())]; + (gen, gen) + } else if generations.contains("-") { + let gens: Vec<&str> = generations.split("-").collect(); + (gens[0], gens[1]) } else { - rng.gen_bool(1.0 / 128.0) + (generations, generations) }; - show_pokemon_by_name(pokemon_name, is_shiny, is_large, None); + let file = std::fs::File::open(PROGRAM_DIR.join("pokemon.json"))?; + let reader = std::io::BufReader::new(file); + let pokemon_json: serde_json::Value = serde_json::from_reader(reader)?; + let pokemon: Vec = pokemon_json + .as_array() + .unwrap() + .iter() + .map(|p| p["name"].as_str().unwrap().to_string()) + .collect(); + + let generations_map: std::collections::HashMap<_, _> = GENERATIONS.iter().cloned().collect(); + + if let Some((start_idx, end_idx)) = generations_map.get(start_gen) { + let random_idx = rng.gen_range(*start_idx..=*end_idx); + let random_pokemon = &pokemon[random_idx as usize - 1]; + let shiny = if !shiny { + rng.gen::() <= SHINY_RATE + } else { + shiny + }; + show_pokemon_by_name(random_pokemon, show_title, shiny, is_large, None)?; + } else { + println!("Invalid generation '{}'", generations); + std::process::exit(1); + } + + Ok(()) +} + +fn main() { + // println!("{}", PROGRAM.display()); + // println!("{}", PROGRAM_DIR.display()); + // println!("{}", COLORSCRIPTS_DIR.display()); + // show_pokemon_by_name("eevee", false, false, false, Some("gmax")).unwrap(); + show_random_pokemon("1-999", true, false, false); }