diff --git a/Cargo.lock b/Cargo.lock index b1480da..b2c75f6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3286,7 +3286,7 @@ dependencies = [ ] [[package]] -name = "smart-iv-calculator" +name = "smart_iv_calculator" version = "0.1.0" dependencies = [ "bevy", diff --git a/Cargo.toml b/Cargo.toml index fe96292..014f25e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "smart-iv-calculator" +name = "smart_iv_calculator" version = "0.1.0" edition = "2021" diff --git a/data/natures.json b/data/natures.json index 857ee51..c9998ed 100644 --- a/data/natures.json +++ b/data/natures.json @@ -2,6 +2,7 @@ "name": "Hardy", "alias": "hardy", "id": 1, + "pid": 0, "increased": null, "decreased": null }, @@ -9,6 +10,7 @@ "name": "Bold", "alias": "bold", "id": 2, + "pid": 5, "increased": "defense", "decreased": "attack" }, @@ -16,6 +18,7 @@ "name": "Modest", "alias": "modest", "id": 3, + "pid": 15, "increased": "special_attack", "decreased": "attack" }, @@ -23,6 +26,7 @@ "name": "Calm", "alias": "calm", "id": 4, + "pid": 20, "increased": "special_defense", "decreased": "attack" }, @@ -30,6 +34,7 @@ "name": "Timid", "alias": "timid", "id": 5, + "pid": 10, "increased": "speed", "decreased": "attack" }, @@ -37,6 +42,7 @@ "name": "Lonely", "alias": "lonely", "id": 6, + "pid": 1, "increased": "attack", "decreased": "defense" }, @@ -44,6 +50,7 @@ "name": "Docile", "alias": "docile", "id": 7, + "pid": 6, "increased": null, "decreased": null }, @@ -51,6 +58,7 @@ "name": "Mild", "alias": "mild", "id": 8, + "pid": 16, "increased": "special_attack", "decreased": "defense" }, @@ -58,6 +66,7 @@ "name": "Gentle", "alias": "gentle", "id": 9, + "pid": 21, "increased": "special_defense", "decreased": "defense" }, @@ -65,6 +74,7 @@ "name": "Hasty", "alias": "hasty", "id": 10, + "pid": 11, "increased": "speed", "decreased": "defense" }, @@ -72,6 +82,7 @@ "name": "Adamant", "alias": "adamant", "id": 11, + "pid": 3, "increased": "attack", "decreased": "special_attack" }, @@ -79,6 +90,7 @@ "name": "Impish", "alias": "impish", "id": 12, + "pid": 8, "increased": "defense", "decreased": "special_attack" }, @@ -86,6 +98,7 @@ "name": "Bashful", "alias": "bashful", "id": 13, + "pid": 18, "increased": null, "decreased": null }, @@ -93,6 +106,7 @@ "name": "Careful", "alias": "careful", "id": 14, + "pid": 23, "increased": "special_defense", "decreased": "special_attack" }, @@ -100,6 +114,7 @@ "name": "Rash", "alias": "rash", "id": 15, + "pid": 19, "increased": "special_attack", "decreased": "special_defense" }, @@ -107,6 +122,7 @@ "name": "Jolly", "alias": "jolly", "id": 16, + "pid": 13, "increased": "speed", "decreased": "special_attack" }, @@ -114,6 +130,7 @@ "name": "Naughty", "alias": "naughty", "id": 17, + "pid": 4, "increased": "attack", "decreased": "special_defense" }, @@ -121,6 +138,7 @@ "name": "Lax", "alias": "lax", "id": 18, + "pid": 9, "increased": "defense", "decreased": "special_defense" }, @@ -128,6 +146,7 @@ "name": "Quirky", "alias": "quirky", "id": 19, + "pid": 24, "increased": null, "decreased": null }, @@ -135,6 +154,7 @@ "name": "Naive", "alias": "naive", "id": 20, + "pid": 14, "increased": "speed", "decreased": "special_defense" }, @@ -142,6 +162,7 @@ "name": "Brave", "alias": "brave", "id": 21, + "pid": 2, "increased": "attack", "decreased": "speed" }, @@ -149,6 +170,7 @@ "name": "Relaxed", "alias": "relaxed", "id": 22, + "pid": 7, "increased": "defense", "decreased": "speed" }, @@ -156,6 +178,7 @@ "name": "Quiet", "alias": "quiet", "id": 23, + "pid": 17, "increased": "special_attack", "decreased": "speed" }, @@ -163,6 +186,7 @@ "name": "Sassy", "alias": "sassy", "id": 24, + "pid": 22, "increased": "special_defense", "decreased": "speed" }, @@ -170,6 +194,7 @@ "name": "Serious", "alias": "serious", "id": 25, + "pid": 12, "increased": null, "decreased": null } diff --git a/src/bin/ivcalc.rs b/src/bin/ivcalc.rs new file mode 100644 index 0000000..e119bfa --- /dev/null +++ b/src/bin/ivcalc.rs @@ -0,0 +1,5 @@ +use smart_iv_calculator::ivcalc; + +fn main() { + ivcalc::run() +} diff --git a/src/bin/ivpeek.rs b/src/bin/ivpeek.rs new file mode 100644 index 0000000..d9e0960 --- /dev/null +++ b/src/bin/ivpeek.rs @@ -0,0 +1,5 @@ +use smart_iv_calculator::ivpeek; + +fn main() { + ivpeek::run() +} diff --git a/src/database.rs b/src/database.rs index 2e7c4e1..4e1f816 100644 --- a/src/database.rs +++ b/src/database.rs @@ -1,28 +1,13 @@ +use std::collections::HashMap; + use bevy::prelude::*; use json::JsonValue; -use lazy_static::lazy_static; -use std::{ - collections::HashMap, - fs, - path::{Path, PathBuf}, + +use crate::{ + json::{read_characteristics, read_natures, read_pokedex}, + pokemon::*, }; -use crate::pokemon::*; - -lazy_static! { - static ref DATA_DIR: PathBuf = "./data".into(); - pub static ref TYPE_MAP: HashMap = { - let types = parse_json_file(DATA_DIR.join("types.json")); - let mut map = HashMap::new(); - for type_data in types.members() { - if let Some(type_data) = Type::from_json(type_data) { - map.insert(type_data.id, type_data); - } - } - map - }; -} - pub struct DatabasePlugin; impl Plugin for DatabasePlugin { @@ -60,28 +45,7 @@ fn database_setup( mut nature_database: ResMut>, mut characteristic_database: ResMut>, ) { - let natures = parse_json_file(DATA_DIR.join("natures.json")); - nature_database.populate_from_json(&natures); - let pokedex = parse_json_file(DATA_DIR.join("pokedex.json")); - pokemon_database.populate_from_json(&pokedex); - let characteristics = parse_json_file(DATA_DIR.join("characteristics.json")); - characteristic_database.populate_from_json(&characteristics); -} - -pub fn parse_json_file>(path: P) -> JsonValue { - json::parse(fs::read_to_string(path).unwrap().as_ref()).unwrap() -} - -pub fn load_url_asset( - url: String, - path: PathBuf, - assets: &Res, -) -> Result, Box> { - let system_path = Path::new("assets").join(&path); - if Path::exists(&path) { - return Ok(assets.load(path)); - } - let data = reqwest::blocking::get(&url)?.bytes()?; - fs::write(&system_path, data).unwrap(); - Ok(assets.load(path)) + nature_database.populate_from_json(&read_natures()); + pokemon_database.populate_from_json(&read_pokedex()); + characteristic_database.populate_from_json(&read_characteristics()); } diff --git a/src/main.rs b/src/ivcalc.rs similarity index 77% rename from src/main.rs rename to src/ivcalc.rs index 30ab91c..8d7ee70 100644 --- a/src/main.rs +++ b/src/ivcalc.rs @@ -1,12 +1,10 @@ use bevy::{prelude::*, window::WindowResolution}; -pub mod database; -pub mod inspector; -pub mod pokemon; -pub mod server; -pub mod ui; +mod calculator; +mod server; +mod ui; -fn main() { +pub fn run() { App::new() .add_plugins( DefaultPlugins @@ -21,8 +19,8 @@ fn main() { }) .set(ImagePlugin::default_nearest()), ) - .add_plugin(database::DatabasePlugin) - .add_plugin(inspector::InspectorPlugin) + .add_plugin(crate::database::DatabasePlugin) + .add_plugin(calculator::CalculatorPlugin) .add_plugin(ui::UiPlugin) .add_plugin(server::ServerPlugin) .run(); diff --git a/src/inspector.rs b/src/ivcalc/calculator.rs similarity index 66% rename from src/inspector.rs rename to src/ivcalc/calculator.rs index 172e72c..d0c0e40 100644 --- a/src/inspector.rs +++ b/src/ivcalc/calculator.rs @@ -1,19 +1,25 @@ +use std::{ + fs, + path::{Path, PathBuf}, +}; + use bevy::prelude::*; use bevy_egui::EguiContexts; -use crate::{ - database::{load_url_asset, Database}, - pokemon::*, +use crate::database::*; +use crate::pokemon::*; + +use super::{ server::Request, ui::{UiAssets, UiState}, }; -pub struct InspectorPlugin; +pub struct CalculatorPlugin; -impl Plugin for InspectorPlugin { +impl Plugin for CalculatorPlugin { fn build(&self, app: &mut App) { - app.register_type::() - .insert_resource(Inspector::default()) + app.register_type::() + .insert_resource(Calculator::default()) .add_system(state_changed) .add_system(request_handler.in_base_set(CoreSet::PreUpdate)); } @@ -21,7 +27,7 @@ impl Plugin for InspectorPlugin { #[derive(Reflect, Resource, Default, Debug, Clone)] #[reflect(Resource)] -pub struct Inspector { +pub struct Calculator { pub pokemon: Option, pub nature: Option, pub characteristic: Option, @@ -29,15 +35,15 @@ pub struct Inspector { } fn state_changed( - inspector: Res, + calculator: Res, assets: Res, mut ui_assets: ResMut, mut contexts: EguiContexts, ) { - if let (Some(pokemon), true) = (inspector.pokemon.as_ref(), inspector.is_changed()) { + if let (Some(pokemon), true) = (calculator.pokemon.as_ref(), calculator.is_changed()) { if !ui_assets.sprite_map.contains_key(&pokemon.key()) { let handle = load_url_asset( - pokemon.get_url(), + pokemon.sprite_url(), format!("cache/{name}.png", name = pokemon.key()).into(), &assets, ); @@ -53,7 +59,7 @@ fn state_changed( fn request_handler( mut request_events: EventReader, - mut inspector: ResMut, + mut calculator: ResMut, mut ui: ResMut, characteristics: Res>, natures: Res>, @@ -62,10 +68,10 @@ fn request_handler( info!("{:#}", request); match request.urn.as_str() { "clear" => { - inspector.pokemon = None; - inspector.nature = None; - inspector.characteristic = None; - inspector.derived_stats = DerivedStats::default(); + calculator.pokemon = None; + calculator.nature = None; + calculator.characteristic = None; + calculator.derived_stats = DerivedStats::default(); ui.name = String::from(""); ui.level = String::from(""); ui.derived_stats.clear(); @@ -77,11 +83,11 @@ fn request_handler( } if let Some(level) = data["level"].as_i32() { ui.level = level.to_string(); - inspector.derived_stats.level = Some(level); + calculator.derived_stats.level = Some(level); } if let Some(nature) = data["nature"].as_str() { if let Some(nature) = natures.map.get(&nature.to_lowercase()).cloned() { - inspector.nature = Some(nature); + calculator.nature = Some(nature); } } if let Some(characteristic) = data["characteristic"].as_str() { @@ -90,13 +96,13 @@ fn request_handler( .get(&characteristic.to_lowercase()) .cloned() { - inspector.characteristic = Some(characteristic); + calculator.characteristic = Some(characteristic); } } for stat in BaseStat::all() { if let Some(value) = data[stat.key()].as_i32() { ui.derived_stats.insert(stat, value.to_string()); - inspector.derived_stats.set_stat_value(stat, Some(value)); + calculator.derived_stats.set_stat_value(stat, Some(value)); } } } @@ -106,3 +112,17 @@ fn request_handler( } } } + +pub fn load_url_asset( + url: String, + path: PathBuf, + assets: &Res, +) -> Result, Box> { + let system_path = Path::new("assets").join(&path); + if Path::exists(&path) { + return Ok(assets.load(path)); + } + let data = reqwest::blocking::get(&url)?.bytes()?; + fs::write(&system_path, data).unwrap(); + Ok(assets.load(path)) +} diff --git a/src/server.rs b/src/ivcalc/server.rs similarity index 100% rename from src/server.rs rename to src/ivcalc/server.rs diff --git a/src/ui.rs b/src/ivcalc/ui.rs similarity index 93% rename from src/ui.rs rename to src/ivcalc/ui.rs index bd72855..bdadff8 100644 --- a/src/ui.rs +++ b/src/ivcalc/ui.rs @@ -3,7 +3,10 @@ use bevy_egui::{egui, EguiContexts, EguiPlugin}; use lazy_static::lazy_static; use std::collections::HashMap; -use crate::{database::Database, inspector::Inspector, pokemon::*}; +use crate::database::Database; +use crate::pokemon::*; + +use super::calculator::Calculator; const INPUT_LABEL_WIDTH: f32 = 100.0; const INPUT_TEXT_WIDTH: f32 = 150.0; @@ -69,18 +72,18 @@ fn load_assets(mut ui_assets: ResMut, assets: Res) { fn handle_state( ui_state: Res, pokemon: Res>, - mut inspector: ResMut, + mut calculator: ResMut, ) { if ui_state.is_changed() { if let Some(pokemon) = pokemon.map.get(ui_state.name.to_lowercase().as_str()) { - inspector.pokemon = Some(pokemon.clone()); + calculator.pokemon = Some(pokemon.clone()); } } } fn ui_system( mut contexts: EguiContexts, - mut inspector: ResMut, + mut calculator: ResMut, ui_assets: Res, mut ui_state: ResMut, mut rendered_texture_id: Local, @@ -96,11 +99,11 @@ fn ui_system( egui::CentralPanel::default().show(contexts.ctx_mut(), |ui| { let sprite_size = egui::Vec2::new(128., 128.); - let pokemon = inspector.pokemon.clone(); + let pokemon = calculator.pokemon.clone(); let pokemon = pokemon.as_ref(); - let nature = inspector.nature.clone(); + let nature = calculator.nature.clone(); let nature = nature.as_ref(); - let characteristic = inspector.characteristic.clone(); + let characteristic = calculator.characteristic.clone(); let characteristic = characteristic.as_ref(); // Pokemon @@ -128,11 +131,11 @@ fn ui_system( egui::ComboBox::new("nature", "") .selected_text(format!("{}", nature.map_or("-", |c| &c.name))) .show_ui(ui, |ui| { - ui.selectable_value(&mut inspector.nature, None, "-"); + ui.selectable_value(&mut calculator.nature, None, "-"); let mut chars: Vec<_> = natures.map.values().collect(); chars.sort_by_key(|c| c.name.clone()); for char in chars { - ui.selectable_value(&mut inspector.nature, Some(char.clone()), &char.name); + ui.selectable_value(&mut calculator.nature, Some(char.clone()), &char.name); } }); }); @@ -147,12 +150,12 @@ fn ui_system( egui::ComboBox::new("characteristic", "") .selected_text(format!("{}", characteristic.map_or("-", |c| &c.name))) .show_ui(ui, |ui| { - ui.selectable_value(&mut inspector.characteristic, None, "-"); + ui.selectable_value(&mut calculator.characteristic, None, "-"); let mut chars: Vec<_> = characteristics.map.values().collect(); chars.sort_by_key(|c| c.name.clone()); for char in chars { ui.selectable_value( - &mut inspector.characteristic, + &mut calculator.characteristic, Some(char.clone()), &char.name, ); @@ -212,7 +215,7 @@ fn ui_system( if input.changed() { *value = digit_filter(value); if let Ok(value) = value.parse::() { - inspector.derived_stats.level = Some(value); + calculator.derived_stats.level = Some(value); } } if input.gained_focus() { @@ -318,7 +321,7 @@ fn ui_system( *value = digit_filter(value); if let (Ok(value), derived) = ( value.parse::(), - inspector.derived_stats.value_mut(stat), + calculator.derived_stats.value_mut(stat), ) { *derived = Some(value); } @@ -330,8 +333,8 @@ fn ui_system( let possible_ivs = if let (Some(pokemon), Some(level), Some(derived_stat)) = ( pokemon, - inspector.derived_stats.level, - inspector.derived_stats.value(stat), + calculator.derived_stats.level, + calculator.derived_stats.value(stat), ) { calculate_possible_ivs( stat, diff --git a/src/ivpeek.rs b/src/ivpeek.rs new file mode 100644 index 0000000..75b3f1a --- /dev/null +++ b/src/ivpeek.rs @@ -0,0 +1,24 @@ +use bevy::{prelude::*, window::WindowResolution}; + +mod inspector; +mod ui; + +pub fn run() { + App::new() + .add_plugins( + DefaultPlugins + .set(WindowPlugin { + primary_window: Some(Window { + resolution: WindowResolution::new(720., 540.), + resizable: false, + title: "Smart IV peeker".to_string(), + ..default() + }), + ..default() + }) + .set(ImagePlugin::default_nearest()), + ) + .add_plugin(crate::database::DatabasePlugin) + .add_plugin(ui::UiPlugin) + .run() +} diff --git a/src/ivpeek/inspector.rs b/src/ivpeek/inspector.rs new file mode 100644 index 0000000..e040521 --- /dev/null +++ b/src/ivpeek/inspector.rs @@ -0,0 +1,34 @@ +use std::collections::HashMap; + +use bevy::prelude::*; + +use crate::pokemon::*; + +pub struct InspectorPlugin; + +impl Plugin for InspectorPlugin { + fn build(&self, app: &mut App) { + app.insert_resource(Inspector::default()); + } +} + +#[derive(Resource, Default)] +pub struct Inspector { + pub allies: Vec, + pub enemies: Vec, +} + +impl Inspector { + pub fn clear(&mut self) { + self.allies.clear(); + self.enemies.clear(); + } +} + +#[derive(Default)] +pub struct PokemonInstance { + pub pokemon: Pokemon, + pub nature: Option, + pub ivs: HashMap, + pub evs: HashMap, +} diff --git a/src/ivpeek/ui.rs b/src/ivpeek/ui.rs new file mode 100644 index 0000000..bb0c848 --- /dev/null +++ b/src/ivpeek/ui.rs @@ -0,0 +1,127 @@ +use bevy::prelude::*; +use bevy_egui::{egui, EguiContexts, EguiPlugin}; +use lazy_static::lazy_static; +use std::collections::HashMap; + +use crate::{database::Database, pokemon::*}; + +use super::inspector::{Inspector, PokemonInstance}; + +const BAR_HEIGHT: f32 = 12.0; +const BASE_STAT_WIDTH_MULT: f32 = 1.0; +const IV_WIDTH_MULT: f32 = 4.0; +const EV_WIDTH_MULT: f32 = 1.0; + +lazy_static! { + static ref BASE_STAT_COLOR_RANGES: Vec<(u8, egui::Color32)> = vec![ + (0, egui::Color32::from_rgb(255, 0, 0)), + (30, egui::Color32::from_rgb(255, 128, 0)), + (60, egui::Color32::from_rgb(255, 255, 0)), + (90, egui::Color32::from_rgb(128, 255, 0)), + (120, egui::Color32::from_rgb(0, 255, 0)), + (150, egui::Color32::from_rgb(0, 255, 128)), + (180, egui::Color32::from_rgb(0, 255, 255)), + ]; + static ref IV_COLOR_RANGES: Vec<(u8, egui::Color32)> = vec![ + (0, egui::Color32::from_rgb(255, 0, 0)), + (16, egui::Color32::from_rgb(255, 128, 0)), + (22, egui::Color32::from_rgb(255, 255, 0)), + (27, egui::Color32::from_rgb(128, 255, 0)), + (30, egui::Color32::from_rgb(0, 255, 0)), + ]; + static ref COLUMNS: Vec = vec![ + 25.0, // Base stat + 255.0 * BASE_STAT_WIDTH_MULT, // Base stat bar + 60.0, // Stat name + 40.0, // IV value + 32.0 * IV_WIDTH_MULT, // IV bar + 40.0, // EV value + 255.0 * EV_WIDTH_MULT, // EV bar + ]; +} + +pub struct UiPlugin; + +impl Plugin for UiPlugin { + fn build(&self, app: &mut App) { + app.add_plugin(EguiPlugin) + .insert_resource(Inspector::default()) + .insert_resource(UiAssets::default()) + .add_startup_system(load_assets) + .add_system(ui_system) + .add_startup_system(test_init); + } +} + +fn test_init(mut inspector: ResMut, pokemon_database: Res>) { + inspector.enemies.push(PokemonInstance { + pokemon: pokemon_database.map.get("baltoy").unwrap().clone(), + ..default() + }); +} + +#[derive(Resource, Default)] +pub struct UiAssets { + pub bar_handle: Handle, + pub sprite_map: HashMap, egui::TextureId)>, +} + +fn load_assets(mut ui_assets: ResMut, assets: Res) { + ui_assets.bar_handle = assets.load("ui/bar.png"); +} + +fn ui_system( + mut contexts: EguiContexts, + inspector: Res, + ui_assets: Res, + mut rendered_texture_id: Local, + mut is_initialized: Local, +) { + if !*is_initialized { + *is_initialized = true; + *rendered_texture_id = contexts.add_image(ui_assets.bar_handle.clone_weak()); + } + + egui::CentralPanel::default().show(contexts.ctx_mut(), |ui| { + let sprite_size = egui::Vec2::new(128., 128.); + for instance in inspector.enemies.iter().chain(inspector.allies.iter()) { + let pokemon = instance.pokemon.clone(); + + // Sprite + ui.horizontal(|ui| { + ui.horizontal(|ui| { + ui.set_min_size(sprite_size); + if let Some((_, rendered_texture_id)) = ui_assets.sprite_map.get(&pokemon.key()) + { + ui.add(egui::Image::new(*rendered_texture_id, sprite_size)); + } + }); + }); + } + }); +} + +fn nature_color(stat: BaseStat, nature: Option<&Nature>) -> egui::Color32 { + if let Some(nature) = nature { + if nature.increased == Some(stat) { + egui::Color32::from_rgb(255, 64, 192) + } else if nature.decreased == Some(stat) { + egui::Color32::from_rgb(64, 192, 255) + } else { + egui::Color32::LIGHT_GRAY + } + } else { + egui::Color32::LIGHT_GRAY + } +} + +fn iv_color(iv: u8) -> egui::Color32 { + for (treshold, color) in IV_COLOR_RANGES.iter().rev() { + if iv >= *treshold { + return color.clone(); + } + } + IV_COLOR_RANGES + .first() + .map_or(egui::Color32::LIGHT_GRAY, |(_, color)| color.clone()) +} diff --git a/src/json.rs b/src/json.rs new file mode 100644 index 0000000..cbde9f2 --- /dev/null +++ b/src/json.rs @@ -0,0 +1,43 @@ +use json::JsonValue; +use lazy_static::lazy_static; +use std::{ + collections::HashMap, + fs, + path::{Path, PathBuf}, +}; + +use crate::pokemon::*; + +lazy_static! { + static ref DATA_DIR: PathBuf = "./data".into(); + pub static ref TYPE_MAP: HashMap = { + let types = read_pokedex(); + let mut map = HashMap::new(); + for type_data in types.members() { + if let Some(type_data) = Type::from_json(type_data) { + map.insert(type_data.id, type_data); + } + } + map + }; +} + +pub fn parse_json_file>(path: P) -> JsonValue { + json::parse(fs::read_to_string(path).unwrap().as_ref()).unwrap() +} + +pub fn read_natures() -> JsonValue { + parse_json_file(DATA_DIR.join("natures.json")) +} + +pub fn read_pokedex() -> JsonValue { + parse_json_file(DATA_DIR.join("pokedex.json")) +} + +pub fn read_types() -> JsonValue { + parse_json_file(DATA_DIR.join("types.json")) +} + +pub fn read_characteristics() -> JsonValue { + parse_json_file(DATA_DIR.join("characteristics.json")) +} diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..c34afe1 --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,5 @@ +pub mod database; +pub mod ivcalc; +pub mod ivpeek; +pub mod json; +pub mod pokemon; diff --git a/src/pokemon.rs b/src/pokemon.rs index 26f8571..558faf4 100644 --- a/src/pokemon.rs +++ b/src/pokemon.rs @@ -2,7 +2,7 @@ use bevy::reflect::{FromReflect, Reflect}; use lazy_static::lazy_static; use std::{collections::HashMap, fmt}; -use crate::database::TYPE_MAP; +use crate::json::TYPE_MAP; pub type BaseValue = u8; pub type StatValue = i32; @@ -103,7 +103,7 @@ impl Pokemon { } } - pub fn get_url(&self) -> String { + pub fn sprite_url(&self) -> String { format!( "https://img.pokemondb.net/sprites/{gen}/normal/{name}.png", gen = self.get_sprite_gen(), @@ -183,6 +183,18 @@ impl BaseStat { BaseStat::Speed, ] } + + pub fn from_str(str: &str) -> Option { + match str { + "hp" => Some(BaseStat::Hp), + "attack" => Some(BaseStat::Attack), + "defense" => Some(BaseStat::Defense), + "special_attack" => Some(BaseStat::SpecialAttack), + "special_defense" => Some(BaseStat::SpecialDefense), + "speed" => Some(BaseStat::Speed), + _ => None, + } + } } impl GetKey for BaseStat { @@ -238,6 +250,7 @@ impl GetKey for Type { #[derive(Default, Debug, Clone, Reflect, FromReflect, PartialEq)] pub struct Nature { pub id: u8, + pub pid: u8, pub name: String, pub alias: String, pub increased: Option, @@ -260,6 +273,7 @@ impl FromJson for Nature { fn from_json(json: &json::JsonValue) -> Option { Some(Self { id: json["id"].as_u8()?, + pid: json["pid"].as_u8()?, name: json["name"].as_str()?.to_string(), alias: json["alias"].as_str()?.to_string(), increased: json["increased"]