localdex 0.2.40__py3-none-any.whl → 0.2.44__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
localdex/core.py CHANGED
@@ -6,10 +6,11 @@ Pokemon data with caching, search capabilities, and data loading.
6
6
  """
7
7
 
8
8
  import json
9
+ import math
9
10
  import os
10
11
  import glob
11
12
  from pathlib import Path
12
- from typing import Dict, List, Optional, Union, Any, Set
13
+ from typing import Dict, List, Optional, Union, Any, Set, Tuple
13
14
  from functools import lru_cache
14
15
 
15
16
  from .models import Pokemon, Move, Ability, Item, BaseStats
@@ -435,8 +436,8 @@ class LocalDex:
435
436
  hp=base_stats_data.get("hp", 0),
436
437
  attack=base_stats_data.get("attack", 0),
437
438
  defense=base_stats_data.get("defense", 0),
438
- special_attack=base_stats_data.get("special-attack", 0),
439
- special_defense=base_stats_data.get("special-defense", 0),
439
+ special_attack=base_stats_data.get("special_attack", 0),
440
+ special_defense=base_stats_data.get("special_defense", 0),
440
441
  speed=base_stats_data.get("speed", 0),
441
442
  )
442
443
  return Pokemon(
@@ -510,7 +511,7 @@ class LocalDex:
510
511
  """Create an Item object from raw data."""
511
512
  return Item(
512
513
  name=data.get("name", ""),
513
- description=data.get("desc"),
514
+ description=data.get("description", data.get("desc", "")),
514
515
  short_description=data.get("shortDesc"),
515
516
  generation=data.get("gen"),
516
517
  num=data.get("num"),
@@ -548,5 +549,597 @@ class LocalDex:
548
549
  "abilities": len(self._ability_cache),
549
550
  "items": len(self._item_cache)
550
551
  }
552
+ def get_base_stats_from_species(self, species: str):
553
+ """Get base stats from species name"""
554
+ return self.get_pokemon(name_or_id=species).base_stats
555
+
556
+ def get_hp_stat_from_species(self, species: str, iv: int, ev: int, level: int = 100) -> int:
557
+ """Calculate HP stat for a species with given IVs, EVs, and level"""
558
+ base_stats = self.get_base_stats_from_species(species)
559
+ return self.calculate_hp(base_stats.hp, iv, ev, level)
560
+
561
+ def get_attack_stat_from_species(self, species: str, iv: int, ev: int, level: int = 100, nature_modifier: float = 1.0) -> int:
562
+ """Calculate Attack stat for a species with given IVs, EVs, and level"""
563
+ base_stats = self.get_base_stats_from_species(species)
564
+ return self.calculate_other_stat(base_stats.attack, iv, ev, level, nature_modifier)
565
+
566
+ def get_defense_stat_from_species(self, species: str, iv: int, ev: int, level: int = 100, nature_modifier: float = 1.0) -> int:
567
+ """Calculate Defense stat for a species with given IVs, EVs, and level"""
568
+ base_stats = self.get_base_stats_from_species(species)
569
+ return self.calculate_other_stat(base_stats.defense, iv, ev, level, nature_modifier)
570
+
571
+ def get_special_attack_stat_from_species(self, species: str, iv: int, ev: int, level: int = 100, nature_modifier: float = 1.0) -> int:
572
+ """Calculate Special Attack stat for a species with given IVs, EVs, and level"""
573
+ base_stats = self.get_base_stats_from_species(species)
574
+ return self.calculate_other_stat(base_stats.special_attack, iv, ev, level, nature_modifier)
575
+
576
+ def get_special_defense_stat_from_species(self, species: str, iv: int, ev: int, level: int = 100, nature_modifier: float = 1.0) -> int:
577
+ """Calculate Special Defense stat for a species with given IVs, EVs, and level"""
578
+ base_stats = self.get_base_stats_from_species(species)
579
+ return self.calculate_other_stat(base_stats.special_defense, iv, ev, level, nature_modifier)
580
+
581
+ def get_speed_stat_from_species(self, species: str, iv: int, ev: int, level: int = 100, nature_modifier: float = 1.0) -> int:
582
+ """Calculate Speed stat for a species with given IVs, EVs, and level"""
583
+ base_stats = self.get_base_stats_from_species(species)
584
+ return self.calculate_other_stat(base_stats.speed, iv, ev, level, nature_modifier)
585
+
586
+ def get_substitute_health_from_species(self, species: str, iv: int, ev: int, level: int = 100) -> int:
587
+ """Calculate substitute health for a species (1/4 of max HP)"""
588
+ max_hp = self.get_hp_stat_from_species(species, iv, ev, level)
589
+ return int(max_hp / 4)
590
+
591
+ def calculate_hp(self, base: int, iv: int, ev: int, level: int = 100) -> int:
592
+ """
593
+ Calculate HP using the Pokemon HP formula.
594
+
595
+ Args:
596
+ base (int): Base HP stat
597
+ iv (int): Individual Value (0-31)
598
+ ev (int): Effort Value (0-252)
599
+ level (int): Pokemon level (1-100)
600
+
601
+ Returns:
602
+ int: Calculated HP value
603
+ """
604
+ hp = math.floor(((2 * base + iv + math.floor(ev / 4)) * level) / 100) + level + 10
605
+ return hp
606
+
607
+ def calculate_other_stat(self, base: int, iv: int, ev: int, level: int = 100, nature_modifier: float = 1.0) -> int:
608
+ """
609
+ Calculate other stats (Attack, Defense, Sp. Attack, Sp. Defense, Speed) using the Pokemon stat formula.
610
+
611
+ Args:
612
+ base (int): Base stat value
613
+ iv (int): Individual Value (0-31)
614
+ ev (int): Effort Value (0-252)
615
+ level (int): Pokemon level (1-100)
616
+ nature_modifier (float): Nature modifier (0.9 for hindering, 1.0 for neutral, 1.1 for beneficial)
617
+
618
+ Returns:
619
+ int: Calculated stat value
620
+ """
621
+ stat = math.floor((math.floor(((2 * base + iv + math.floor(ev / 4)) * level) / 100) + 5) * nature_modifier)
622
+ return stat
623
+
624
+ def calculate_hp_ev(self, total_hp: int, base_hp: int, iv: int, level: int = 100) -> int:
625
+ """
626
+ Calculate HP EV from total HP stat using the reverse of the Pokemon HP formula.
627
+
628
+ Args:
629
+ total_hp (int): Total HP stat value
630
+ base_hp (int): Base HP stat
631
+ iv (int): Individual Value (0-31)
632
+ level (int): Pokemon level (1-100)
633
+
634
+ Returns:
635
+ int: Required EV value (0-252)
636
+ """
637
+ if level <= 0:
638
+ raise ValueError("Level must be greater than 0")
639
+
640
+ # Instead of trying to reverse the formula exactly (which is complex due to floor operations),
641
+ # we'll find the EV that gives us the closest HP value
642
+ best_ev = 0
643
+ best_diff = float('inf')
644
+
645
+ for test_ev in range(0, 253, 4): # EVs are always multiples of 4
646
+ test_hp = self.calculate_hp(base_hp, iv, test_ev, level)
647
+ diff = abs(test_hp - total_hp)
648
+
649
+ if diff < best_diff:
650
+ best_diff = diff
651
+ best_ev = test_ev
652
+ elif diff == best_diff and test_ev < best_ev:
653
+ # If we have the same difference, prefer the lower EV
654
+ best_ev = test_ev
655
+
656
+ return best_ev
657
+
658
+ def calculate_other_stat_ev(self, total_stat: int, base_stat: int, iv: int, level: int = 100, nature_modifier: float = 1.0) -> int:
659
+ """
660
+ Calculate EV for other stats (Attack, Defense, Sp. Attack, Sp. Defense, Speed) using the reverse of the Pokemon stat formula.
661
+
662
+ Args:
663
+ total_stat (int): Total stat value
664
+ base_stat (int): Base stat value
665
+ iv (int): Individual Value (0-31)
666
+ level (int): Pokemon level (1-100)
667
+ nature_modifier (float): Nature modifier (0.9 for hindering, 1.0 for neutral, 1.1 for beneficial)
668
+
669
+ Returns:
670
+ int: Required EV value (0-252)
671
+ """
672
+ if level <= 0:
673
+ raise ValueError("Level must be greater than 0")
674
+ if nature_modifier <= 0:
675
+ raise ValueError("Nature modifier must be greater than 0")
676
+
677
+ # Instead of trying to reverse the formula exactly (which is complex due to floor operations),
678
+ # we'll find the EV that gives us the closest stat value
679
+ best_ev = 0
680
+ best_diff = float('inf')
681
+
682
+ for test_ev in range(0, 253, 4): # EVs are always multiples of 4
683
+ test_stat = self.calculate_other_stat(base_stat, iv, test_ev, level, nature_modifier)
684
+ diff = abs(test_stat - total_stat)
685
+
686
+ if diff < best_diff:
687
+ best_diff = diff
688
+ best_ev = test_ev
689
+ elif diff == best_diff and test_ev < best_ev:
690
+ # If we have the same difference, prefer the lower EV
691
+ best_ev = test_ev
692
+
693
+ return best_ev
694
+
695
+ def calculate_attack_ev(self, total_attack: int, base_attack: int, iv: int, level: int = 100, nature_modifier: float = 1.0) -> int:
696
+ """
697
+ Calculate Attack EV from total Attack stat.
698
+
699
+ Args:
700
+ total_attack (int): Total Attack stat value
701
+ base_attack (int): Base Attack stat
702
+ iv (int): Individual Value (0-31)
703
+ level (int): Pokemon level (1-100)
704
+ nature_modifier (float): Nature modifier (0.9 for hindering, 1.0 for neutral, 1.1 for beneficial)
705
+
706
+ Returns:
707
+ int: Required EV value (0-252)
708
+ """
709
+ return self.calculate_other_stat_ev(total_attack, base_attack, iv, level, nature_modifier)
710
+
711
+ def calculate_defense_ev(self, total_defense: int, base_defense: int, iv: int, level: int = 100, nature_modifier: float = 1.0) -> int:
712
+ """
713
+ Calculate Defense EV from total Defense stat.
714
+
715
+ Args:
716
+ total_defense (int): Total Defense stat value
717
+ base_defense (int): Base Defense stat
718
+ iv (int): Individual Value (0-31)
719
+ level (int): Pokemon level (1-100)
720
+ nature_modifier (float): Nature modifier (0.9 for hindering, 1.0 for neutral, 1.1 for beneficial)
721
+
722
+ Returns:
723
+ int: Required EV value (0-252)
724
+ """
725
+ return self.calculate_other_stat_ev(total_defense, base_defense, iv, level, nature_modifier)
726
+
727
+ def calculate_special_attack_ev(self, total_special_attack: int, base_special_attack: int, iv: int, level: int = 100, nature_modifier: float = 1.0) -> int:
728
+ """
729
+ Calculate Special Attack EV from total Special Attack stat.
730
+
731
+ Args:
732
+ total_special_attack (int): Total Special Attack stat value
733
+ base_special_attack (int): Base Special Attack stat
734
+ iv (int): Individual Value (0-31)
735
+ level (int): Pokemon level (1-100)
736
+ nature_modifier (float): Nature modifier (0.9 for hindering, 1.0 for neutral, 1.1 for beneficial)
737
+
738
+ Returns:
739
+ int: Required EV value (0-252)
740
+ """
741
+ return self.calculate_other_stat_ev(total_special_attack, base_special_attack, iv, level, nature_modifier)
742
+
743
+ def calculate_special_defense_ev(self, total_special_defense: int, base_special_defense: int, iv: int, level: int = 100, nature_modifier: float = 1.0) -> int:
744
+ """
745
+ Calculate Special Defense EV from total Special Defense stat.
746
+
747
+ Args:
748
+ total_special_defense (int): Total Special Defense stat value
749
+ base_special_defense (int): Base Special Defense stat
750
+ iv (int): Individual Value (0-31)
751
+ level (int): Pokemon level (1-100)
752
+ nature_modifier (float): Nature modifier (0.9 for hindering, 1.0 for neutral, 1.1 for beneficial)
753
+
754
+ Returns:
755
+ int: Required EV value (0-252)
756
+ """
757
+ return self.calculate_other_stat_ev(total_special_defense, base_special_defense, iv, level, nature_modifier)
758
+
759
+ def calculate_speed_ev(self, total_speed: int, base_speed: int, iv: int, level: int = 100, nature_modifier: float = 1.0) -> int:
760
+ """
761
+ Calculate Speed EV from total Speed stat.
762
+
763
+ Args:
764
+ total_speed (int): Total Speed stat value
765
+ base_speed (int): Base Speed stat
766
+ iv (int): Individual Value (0-31)
767
+ level (int): Pokemon level (1-100)
768
+ nature_modifier (float): Nature modifier (0.9 for hindering, 1.0 for neutral, 1.1 for beneficial)
769
+
770
+ Returns:
771
+ int: Required EV value (0-252)
772
+ """
773
+ return self.calculate_other_stat_ev(total_speed, base_speed, iv, level, nature_modifier)
774
+
775
+ def calculate_hp_ev_from_species(self, species: str, total_hp: int, iv: int, level: int = 100) -> int:
776
+ """
777
+ Calculate HP EV from total HP stat using species name.
778
+
779
+ Args:
780
+ species (str): Pokemon species name
781
+ total_hp (int): Total HP stat value
782
+ iv (int): Individual Value (0-31)
783
+ level (int): Pokemon level (1-100)
784
+
785
+ Returns:
786
+ int: Required EV value (0-252)
787
+ """
788
+ base_stats = self.get_base_stats_from_species(species)
789
+ return self.calculate_hp_ev(total_hp, base_stats.hp, iv, level)
790
+
791
+ def calculate_attack_ev_from_species(self, species: str, total_attack: int, iv: int, level: int = 100, nature_modifier: float = 1.0) -> int:
792
+ """
793
+ Calculate Attack EV from total Attack stat using species name.
794
+
795
+ Args:
796
+ species (str): Pokemon species name
797
+ total_attack (int): Total Attack stat value
798
+ iv (int): Individual Value (0-31)
799
+ level (int): Pokemon level (1-100)
800
+ nature_modifier (float): Nature modifier (0.9 for hindering, 1.0 for neutral, 1.1 for beneficial)
801
+
802
+ Returns:
803
+ int: Required EV value (0-252)
804
+ """
805
+ base_stats = self.get_base_stats_from_species(species)
806
+ return self.calculate_attack_ev(total_attack, base_stats.attack, iv, level, nature_modifier)
807
+
808
+ def calculate_defense_ev_from_species(self, species: str, total_defense: int, iv: int, level: int = 100, nature_modifier: float = 1.0) -> int:
809
+ """
810
+ Calculate Defense EV from total Defense stat using species name.
811
+
812
+ Args:
813
+ species (str): Pokemon species name
814
+ total_defense (int): Total Defense stat value
815
+ iv (int): Individual Value (0-31)
816
+ level (int): Pokemon level (1-100)
817
+ nature_modifier (float): Nature modifier (0.9 for hindering, 1.0 for neutral, 1.1 for beneficial)
818
+
819
+ Returns:
820
+ int: Required EV value (0-252)
821
+ """
822
+ base_stats = self.get_base_stats_from_species(species)
823
+ return self.calculate_defense_ev(total_defense, base_stats.defense, iv, level, nature_modifier)
824
+
825
+ def calculate_special_attack_ev_from_species(self, species: str, total_special_attack: int, iv: int, level: int = 100, nature_modifier: float = 1.0) -> int:
826
+ """
827
+ Calculate Special Attack EV from total Special Attack stat using species name.
828
+
829
+ Args:
830
+ species (str): Pokemon species name
831
+ total_special_attack (int): Total Special Attack stat value
832
+ iv (int): Individual Value (0-31)
833
+ level (int): Pokemon level (1-100)
834
+ nature_modifier (float): Nature modifier (0.9 for hindering, 1.0 for neutral, 1.1 for beneficial)
835
+
836
+ Returns:
837
+ int: Required EV value (0-252)
838
+ """
839
+ base_stats = self.get_base_stats_from_species(species)
840
+ return self.calculate_special_attack_ev(total_special_attack, base_stats.special_attack, iv, level, nature_modifier)
841
+
842
+ def calculate_special_defense_ev_from_species(self, species: str, total_special_defense: int, iv: int, level: int = 100, nature_modifier: float = 1.0) -> int:
843
+ """
844
+ Calculate Special Defense EV from total Special Defense stat using species name.
845
+
846
+ Args:
847
+ species (str): Pokemon species name
848
+ total_special_defense (int): Total Special Defense stat value
849
+ iv (int): Individual Value (0-31)
850
+ level (int): Pokemon level (1-100)
851
+ nature_modifier (float): Nature modifier (0.9 for hindering, 1.0 for neutral, 1.1 for beneficial)
852
+
853
+ Returns:
854
+ int: Required EV value (0-252)
855
+ """
856
+ base_stats = self.get_base_stats_from_species(species)
857
+ return self.calculate_special_defense_ev(total_special_defense, base_stats.special_defense, iv, level, nature_modifier)
858
+
859
+ def calculate_speed_ev_from_species(self, species: str, total_speed: int, iv: int, level: int = 100, nature_modifier: float = 1.0) -> int:
860
+ """
861
+ Calculate Speed EV from total Speed stat using species name.
862
+
863
+ Args:
864
+ species (str): Pokemon species name
865
+ total_speed (int): Total Speed stat value
866
+ iv (int): Individual Value (0-31)
867
+ level (int): Pokemon level (1-100)
868
+ nature_modifier (float): Nature modifier (0.9 for hindering, 1.0 for neutral, 1.1 for beneficial)
869
+
870
+ Returns:
871
+ int: Required EV value (0-252)
872
+ """
873
+ base_stats = self.get_base_stats_from_species(species)
874
+ return self.calculate_speed_ev(total_speed, base_stats.speed, iv, level, nature_modifier)
875
+
876
+ def calculate_all_evs_from_species(self, species: str, stats: Dict[str, int], ivs: Dict[str, int], level: int = 100, nature_modifier: float = 1.0) -> Dict[str, int]:
877
+ """
878
+ Calculate all EV values for a Pokemon using species name and target stats.
879
+
880
+ Args:
881
+ species (str): Pokemon species name
882
+ stats (Dict[str, int]): Dictionary of target stat values with keys: 'hp', 'attack', 'defense', 'special_attack', 'special_defense', 'speed'
883
+ ivs (Dict[str, int]): Dictionary of IV values with keys: 'hp', 'attack', 'defense', 'special_attack', 'special_defense', 'speed'
884
+ level (int): Pokemon level (1-100)
885
+ nature_modifier (float): Nature modifier (0.9 for hindering, 1.0 for neutral, 1.1 for beneficial)
886
+
887
+ Returns:
888
+ Dict[str, int]: Dictionary of required EV values for each stat
889
+ """
890
+ base_stats = self.get_base_stats_from_species(species)
891
+
892
+ evs = {}
893
+
894
+ # Calculate HP EV (no nature modifier)
895
+ if 'hp' in stats:
896
+ evs['hp'] = self.calculate_hp_ev(stats['hp'], base_stats.hp, ivs.get('hp', 31), level)
897
+
898
+ # Calculate other stat EVs (with nature modifier)
899
+ if 'attack' in stats:
900
+ evs['attack'] = self.calculate_attack_ev(stats['attack'], base_stats.attack, ivs.get('attack', 31), level, nature_modifier)
901
+
902
+ if 'defense' in stats:
903
+ evs['defense'] = self.calculate_defense_ev(stats['defense'], base_stats.defense, ivs.get('defense', 31), level, nature_modifier)
904
+
905
+ if 'special_attack' in stats:
906
+ evs['special_attack'] = self.calculate_special_attack_ev(stats['special_attack'], base_stats.special_attack, ivs.get('special_attack', 31), level, nature_modifier)
907
+
908
+ if 'special_defense' in stats:
909
+ evs['special_defense'] = self.calculate_special_defense_ev(stats['special_defense'], base_stats.special_defense, ivs.get('special_defense', 31), level, nature_modifier)
910
+
911
+ if 'speed' in stats:
912
+ evs['speed'] = self.calculate_speed_ev(stats['speed'], base_stats.speed, ivs.get('speed', 31), level, nature_modifier)
913
+
914
+ return evs
915
+
916
+ def calculate_hp_ev_and_nature_combinations(self, total_hp: int, base_hp: int, iv: int, level: int = 100) -> List[Tuple[int, float]]:
917
+ """
918
+ Calculate all possible EV and nature modifier combinations for HP.
919
+ Note: HP is not affected by nature, so this returns only the EV value with nature_modifier=1.0.
920
+
921
+ Args:
922
+ total_hp (int): Total HP stat value
923
+ base_hp (int): Base HP stat
924
+ iv (int): Individual Value (0-31)
925
+ level (int): Pokemon level (1-100)
926
+
927
+ Returns:
928
+ List[Tuple[int, float]]: List of (EV, nature_modifier) combinations
929
+ """
930
+ # HP is not affected by nature, so there's only one combination
931
+ ev = self.calculate_hp_ev(total_hp, base_hp, iv, level)
932
+ return [(ev, 1.0)]
933
+
934
+ def calculate_other_stat_ev_and_nature_combinations(self, total_stat: int, base_stat: int, iv: int, level: int = 100) -> List[Tuple[int, float]]:
935
+ """
936
+ Calculate all possible EV and nature modifier combinations for other stats.
937
+
938
+ Args:
939
+ total_stat (int): Total stat value
940
+ base_stat (int): Base stat value
941
+ iv (int): Individual Value (0-31)
942
+ level (int): Pokemon level (1-100)
943
+
944
+ Returns:
945
+ List[Tuple[int, float]]: List of (EV, nature_modifier) combinations
946
+ """
947
+ if level <= 0:
948
+ raise ValueError("Level must be greater than 0")
949
+
950
+ combinations = []
951
+
952
+ # Try each nature modifier: hindering (0.9), neutral (1.0), beneficial (1.1)
953
+ nature_modifiers = [0.9, 1.0, 1.1]
954
+
955
+ for nature_modifier in nature_modifiers:
956
+ try:
957
+ ev = self.calculate_other_stat_ev(total_stat, base_stat, iv, level, nature_modifier)
958
+
959
+ # Verify this combination actually produces the target stat (or closest possible)
960
+ calculated_stat = self.calculate_other_stat(base_stat, iv, ev, level, nature_modifier)
961
+
962
+ # Accept the combination if it produces the target stat or the closest possible value
963
+ if calculated_stat == total_stat or abs(calculated_stat - total_stat) <= 1:
964
+ combinations.append((ev, nature_modifier))
965
+
966
+ except (ValueError, ZeroDivisionError):
967
+ # Skip invalid combinations
968
+ continue
969
+
970
+ # Remove duplicates and sort by EV (ascending)
971
+ unique_combinations = list(set(combinations))
972
+ unique_combinations.sort(key=lambda x: x[0])
973
+
974
+ return unique_combinations
975
+
976
+ def calculate_attack_ev_and_nature_combinations(self, total_attack: int, base_attack: int, iv: int, level: int = 100) -> List[Tuple[int, float]]:
977
+ """
978
+ Calculate all possible Attack EV and nature modifier combinations.
979
+
980
+ Args:
981
+ total_attack (int): Total Attack stat value
982
+ base_attack (int): Base Attack stat
983
+ iv (int): Individual Value (0-31)
984
+ level (int): Pokemon level (1-100)
985
+
986
+ Returns:
987
+ List[Tuple[int, float]]: List of (EV, nature_modifier) combinations
988
+ """
989
+ return self.calculate_other_stat_ev_and_nature_combinations(total_attack, base_attack, iv, level)
990
+
991
+ def calculate_defense_ev_and_nature_combinations(self, total_defense: int, base_defense: int, iv: int, level: int = 100) -> List[Tuple[int, float]]:
992
+ """
993
+ Calculate all possible Defense EV and nature modifier combinations.
994
+
995
+ Args:
996
+ total_defense (int): Total Defense stat value
997
+ base_defense (int): Base Defense stat
998
+ iv (int): Individual Value (0-31)
999
+ level (int): Pokemon level (1-100)
1000
+
1001
+ Returns:
1002
+ List[Tuple[int, float]]: List of (EV, nature_modifier) combinations
1003
+ """
1004
+ return self.calculate_other_stat_ev_and_nature_combinations(total_defense, base_defense, iv, level)
1005
+
1006
+ def calculate_special_attack_ev_and_nature_combinations(self, total_special_attack: int, base_special_attack: int, iv: int, level: int = 100) -> List[Tuple[int, float]]:
1007
+ """
1008
+ Calculate all possible Special Attack EV and nature modifier combinations.
1009
+
1010
+ Args:
1011
+ total_special_attack (int): Total Special Attack stat value
1012
+ base_special_attack (int): Base Special Attack stat
1013
+ iv (int): Individual Value (0-31)
1014
+ level (int): Pokemon level (1-100)
1015
+
1016
+ Returns:
1017
+ List[Tuple[int, float]]: List of (EV, nature_modifier) combinations
1018
+ """
1019
+ return self.calculate_other_stat_ev_and_nature_combinations(total_special_attack, base_special_attack, iv, level)
1020
+
1021
+ def calculate_special_defense_ev_and_nature_combinations(self, total_special_defense: int, base_special_defense: int, iv: int, level: int = 100) -> List[Tuple[int, float]]:
1022
+ """
1023
+ Calculate all possible Special Defense EV and nature modifier combinations.
1024
+
1025
+ Args:
1026
+ total_special_defense (int): Total Special Defense stat value
1027
+ base_special_defense (int): Base Special Defense stat
1028
+ iv (int): Individual Value (0-31)
1029
+ level (int): Pokemon level (1-100)
1030
+
1031
+ Returns:
1032
+ List[Tuple[int, float]]: List of (EV, nature_modifier) combinations
1033
+ """
1034
+ return self.calculate_other_stat_ev_and_nature_combinations(total_special_defense, base_special_defense, iv, level)
1035
+
1036
+ def calculate_speed_ev_and_nature_combinations(self, total_speed: int, base_speed: int, iv: int, level: int = 100) -> List[Tuple[int, float]]:
1037
+ """
1038
+ Calculate all possible Speed EV and nature modifier combinations.
1039
+
1040
+ Args:
1041
+ total_speed (int): Total Speed stat value
1042
+ base_speed (int): Base Speed stat
1043
+ iv (int): Individual Value (0-31)
1044
+ level (int): Pokemon level (1-100)
1045
+
1046
+ Returns:
1047
+ List[Tuple[int, float]]: List of (EV, nature_modifier) combinations
1048
+ """
1049
+ return self.calculate_other_stat_ev_and_nature_combinations(total_speed, base_speed, iv, level)
551
1050
 
552
-
1051
+ def calculate_hp_ev_and_nature_combinations_from_species(self, species: str, total_hp: int, iv: int, level: int = 100) -> List[Tuple[int, float]]:
1052
+ """
1053
+ Calculate all possible HP EV and nature modifier combinations using species name.
1054
+
1055
+ Args:
1056
+ species (str): Pokemon species name
1057
+ total_hp (int): Total HP stat value
1058
+ iv (int): Individual Value (0-31)
1059
+ level (int): Pokemon level (1-100)
1060
+
1061
+ Returns:
1062
+ List[Tuple[int, float]]: List of (EV, nature_modifier) combinations
1063
+ """
1064
+ base_stats = self.get_base_stats_from_species(species)
1065
+ return self.calculate_hp_ev_and_nature_combinations(total_hp, base_stats.hp, iv, level)
1066
+
1067
+ def calculate_attack_ev_and_nature_combinations_from_species(self, species: str, total_attack: int, iv: int, level: int = 100) -> List[Tuple[int, float]]:
1068
+ """
1069
+ Calculate all possible Attack EV and nature modifier combinations using species name.
1070
+
1071
+ Args:
1072
+ species (str): Pokemon species name
1073
+ total_attack (int): Total Attack stat value
1074
+ iv (int): Individual Value (0-31)
1075
+ level (int): Pokemon level (1-100)
1076
+
1077
+ Returns:
1078
+ List[Tuple[int, float]]: List of (EV, nature_modifier) combinations
1079
+ """
1080
+ base_stats = self.get_base_stats_from_species(species)
1081
+ return self.calculate_attack_ev_and_nature_combinations(total_attack, base_stats.attack, iv, level)
1082
+
1083
+ def calculate_defense_ev_and_nature_combinations_from_species(self, species: str, total_defense: int, iv: int, level: int = 100) -> List[Tuple[int, float]]:
1084
+ """
1085
+ Calculate all possible Defense EV and nature modifier combinations using species name.
1086
+
1087
+ Args:
1088
+ species (str): Pokemon species name
1089
+ total_defense (int): Total Defense stat value
1090
+ iv (int): Individual Value (0-31)
1091
+ level (int): Pokemon level (1-100)
1092
+
1093
+ Returns:
1094
+ List[Tuple[int, float]]: List of (EV, nature_modifier) combinations
1095
+ """
1096
+ base_stats = self.get_base_stats_from_species(species)
1097
+ return self.calculate_defense_ev_and_nature_combinations(total_defense, base_stats.defense, iv, level)
1098
+
1099
+ def calculate_special_attack_ev_and_nature_combinations_from_species(self, species: str, total_special_attack: int, iv: int, level: int = 100) -> List[Tuple[int, float]]:
1100
+ """
1101
+ Calculate all possible Special Attack EV and nature modifier combinations using species name.
1102
+
1103
+ Args:
1104
+ species (str): Pokemon species name
1105
+ total_special_attack (int): Total Special Attack stat value
1106
+ iv (int): Individual Value (0-31)
1107
+ level (int): Pokemon level (1-100)
1108
+
1109
+ Returns:
1110
+ List[Tuple[int, float]]: List of (EV, nature_modifier) combinations
1111
+ """
1112
+ base_stats = self.get_base_stats_from_species(species)
1113
+ return self.calculate_special_attack_ev_and_nature_combinations(total_special_attack, base_stats.special_attack, iv, level)
1114
+
1115
+ def calculate_special_defense_ev_and_nature_combinations_from_species(self, species: str, total_special_defense: int, iv: int, level: int = 100) -> List[Tuple[int, float]]:
1116
+ """
1117
+ Calculate all possible Special Defense EV and nature modifier combinations using species name.
1118
+
1119
+ Args:
1120
+ species (str): Pokemon species name
1121
+ total_special_defense (int): Total Special Defense stat value
1122
+ iv (int): Individual Value (0-31)
1123
+ level (int): Pokemon level (1-100)
1124
+
1125
+ Returns:
1126
+ List[Tuple[int, float]]: List of (EV, nature_modifier) combinations
1127
+ """
1128
+ base_stats = self.get_base_stats_from_species(species)
1129
+ return self.calculate_special_defense_ev_and_nature_combinations(total_special_defense, base_stats.special_defense, iv, level)
1130
+
1131
+ def calculate_speed_ev_and_nature_combinations_from_species(self, species: str, total_speed: int, iv: int, level: int = 100) -> List[Tuple[int, float]]:
1132
+ """
1133
+ Calculate all possible Speed EV and nature modifier combinations using species name.
1134
+
1135
+ Args:
1136
+ species (str): Pokemon species name
1137
+ total_speed (int): Total Speed stat value
1138
+ iv (int): Individual Value (0-31)
1139
+ level (int): Pokemon level (1-100)
1140
+
1141
+ Returns:
1142
+ List[Tuple[int, float]]: List of (EV, nature_modifier) combinations
1143
+ """
1144
+ base_stats = self.get_base_stats_from_species(species)
1145
+ return self.calculate_speed_ev_and_nature_combinations(total_speed, base_stats.speed, iv, level)
@@ -0,0 +1,196 @@
1
+ Metadata-Version: 2.4
2
+ Name: localdex
3
+ Version: 0.2.44
4
+ Summary: A local Pokemon data repository/Pokedex with fast offline access
5
+ Author-email: LocalDex Team <localdex@example.com>
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/colefoster/localdex
8
+ Project-URL: Documentation, https://localdex.readthedocs.io/
9
+ Project-URL: Repository, https://github.com/colefoster/localdex
10
+ Project-URL: Bug Tracker, https://github.com/colefoster/localdex/issues
11
+ Classifier: Development Status :: 3 - Alpha
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Programming Language :: Python :: 3.8
15
+ Classifier: Programming Language :: Python :: 3.9
16
+ Classifier: Programming Language :: Python :: 3.10
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Topic :: Games/Entertainment
20
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
21
+ Requires-Python: >=3.8
22
+ Description-Content-Type: text/markdown
23
+ License-File: LICENSE
24
+ Requires-Dist: requests
25
+ Requires-Dist: typing-extensions
26
+ Provides-Extra: core
27
+ Provides-Extra: gen1
28
+ Provides-Extra: gen2
29
+ Provides-Extra: gen3
30
+ Provides-Extra: gen4
31
+ Provides-Extra: gen5
32
+ Provides-Extra: gen6
33
+ Provides-Extra: gen7
34
+ Provides-Extra: gen8
35
+ Provides-Extra: gen9
36
+ Provides-Extra: learnsets
37
+ Provides-Extra: items
38
+ Provides-Extra: abilities
39
+ Provides-Extra: full
40
+ Requires-Dist: localdex[abilities,gen1,gen2,gen3,gen4,gen5,gen6,gen7,gen8,gen9,items,learnsets]; extra == "full"
41
+ Provides-Extra: dev
42
+ Requires-Dist: pytest>=7.0.0; extra == "dev"
43
+ Requires-Dist: pytest-cov>=4.0.0; extra == "dev"
44
+ Requires-Dist: black>=22.0.0; extra == "dev"
45
+ Requires-Dist: isort>=5.0.0; extra == "dev"
46
+ Requires-Dist: mypy>=1.0.0; extra == "dev"
47
+ Requires-Dist: flake8>=5.0.0; extra == "dev"
48
+ Dynamic: license-file
49
+
50
+ # LocalDex
51
+
52
+ A fast, offline-first Python library for Pokemon data access. LocalDex provides comprehensive Pokemon information without requiring network requests.
53
+
54
+ [![PyPI version](https://badge.fury.io/py/localdex.svg)](https://badge.fury.io/py/localdex)
55
+ [![Python versions](https://img.shields.io/pypi/pyversions/localdex.svg)](https://pypi.org/project/localdex/)
56
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
57
+
58
+ ## Features
59
+
60
+ - **Offline Access**: All data stored locally - no network requests required
61
+ - **Fast Lookups**: Optimized caching and search capabilities
62
+ - **Comprehensive Data**: Pokemon, moves, abilities, and items
63
+ - **CLI Interface**: Command-line access to all data
64
+ - **Type Hints**: Full type support for better development experience
65
+ - **Stat Calculations**: Built-in stat calculation methods
66
+
67
+ ## Installation
68
+
69
+ ```bash
70
+ pip install localdex
71
+ ```
72
+
73
+ ## Quick Start
74
+
75
+ ```python
76
+ from localdex import LocalDex
77
+
78
+ # Initialize the dex
79
+ dex = LocalDex()
80
+
81
+ # Get Pokemon by name or ID
82
+ pikachu = dex.get_pokemon("pikachu")
83
+ charizard = dex.get_pokemon_by_id(6)
84
+
85
+ # Get moves and abilities
86
+ thunderbolt = dex.get_move("thunderbolt")
87
+ lightning_rod = dex.get_ability("lightning-rod")
88
+
89
+ # Search Pokemon
90
+ fire_types = dex.search_pokemon(type="fire")
91
+ fast_pokemon = dex.search_pokemon(min_speed=120)
92
+ legendary_fire = dex.search_pokemon(type="fire", is_legendary=True)
93
+
94
+ # Get all data
95
+ all_pokemon = dex.get_all_pokemon()
96
+ all_moves = dex.get_all_moves()
97
+ ```
98
+
99
+ ## CLI Usage
100
+
101
+ ```bash
102
+ # Get Pokemon information
103
+ localdex pokemon pikachu
104
+ localdex pokemon 25
105
+
106
+ # Search Pokemon
107
+ localdex search --type Fire --generation 1
108
+ localdex search --legendary --min-attack 100
109
+
110
+ # Get move and ability info
111
+ localdex move thunderbolt
112
+ localdex ability lightningrod
113
+
114
+ # List data
115
+ localdex list-pokemon --generation 1
116
+ localdex list-moves --type Electric
117
+
118
+ # Export data
119
+ localdex export --format json --output pokemon_data.json
120
+
121
+ # Run demo
122
+ localdex demo
123
+ ```
124
+
125
+ ## API Reference
126
+
127
+ ### Core Methods
128
+
129
+ - `get_pokemon(name_or_id)` - Get Pokemon by name or ID
130
+ - `get_pokemon_by_id(id)` - Get Pokemon by ID
131
+ - `get_pokemon_by_name(name)` - Get Pokemon by name
132
+ - `get_move(name)` - Get move by name
133
+ - `get_ability(name)` - Get ability by name
134
+ - `get_item(name)` - Get item by name
135
+ - `search_pokemon(**filters)` - Search Pokemon with filters
136
+ - `get_all_pokemon()` - Get all Pokemon
137
+ - `get_all_moves()` - Get all moves
138
+ - `get_all_abilities()` - Get all abilities
139
+ - `get_all_items()` - Get all items
140
+
141
+ ### Search Filters
142
+
143
+ ```python
144
+ # Available filters for search_pokemon()
145
+ dex.search_pokemon(
146
+ type="Fire", # Pokemon type
147
+ generation=1, # Generation number
148
+ is_legendary=True, # Legendary Pokemon
149
+ is_mythical=True, # Mythical Pokemon
150
+ min_attack=100, # Minimum attack stat
151
+ max_speed=50, # Maximum speed stat
152
+ name_contains="char" # Name contains text
153
+ )
154
+ ```
155
+
156
+ ### Data Models
157
+
158
+ ```python
159
+ # Pokemon model
160
+ pokemon = dex.get_pokemon("pikachu")
161
+ print(f"{pokemon.name} - {pokemon.types}")
162
+ print(f"HP: {pokemon.base_stats.hp}")
163
+ print(f"Attack: {pokemon.base_stats.attack}")
164
+
165
+ # Move model
166
+ move = dex.get_move("thunderbolt")
167
+ print(f"{move.name} - Power: {move.base_power}, Type: {move.type}")
168
+
169
+ # Ability model
170
+ ability = dex.get_ability("lightning-rod")
171
+ print(f"{ability.name} - {ability.description}")
172
+ ```
173
+
174
+ ## Stat Calculations
175
+
176
+ LocalDex includes methods for calculating Pokemon stats:
177
+
178
+ ```python
179
+ # Calculate stats with IVs, EVs, and level
180
+ hp = dex.get_hp_stat_from_species("pikachu", iv=31, ev=252, level=100)
181
+ attack = dex.get_attack_stat_from_species("pikachu", iv=31, ev=252, level=100)
182
+
183
+ # Generic stat calculation
184
+ hp = dex.calculate_hp(base=35, iv=31, ev=252, level=100)
185
+ attack = dex.calculate_other_stat(base=55, iv=31, ev=252, level=100, nature_modifier=1.1)
186
+ ```
187
+
188
+ ## License
189
+
190
+ MIT License - see [LICENSE](LICENSE) file for details.
191
+
192
+ ## Data Sources
193
+
194
+ Data sourced from [Pokemon Showdown](https://github.com/smogon/pokemon-showdown) and [PokeAPI](https://pokeapi.co/).
195
+
196
+
@@ -1,6 +1,6 @@
1
1
  localdex/__init__.py,sha256=TTeh9Eys8nLtcw7Dg2equDqnouthIUyfsqvABtzR2vA,403
2
2
  localdex/cli.py,sha256=WqBCyA0akAFJNrYa8jCA3zoZgYEptDYDMGfAGkvKyZc,19317
3
- localdex/core.py,sha256=0kjuL388OniX7hRG6c5fT72nCC76LolpAB2UFrNXPns,20480
3
+ localdex/core.py,sha256=xjqXVjXcsyo1_FL-IM9e1YJPqCBRSbReKd_wwC2w8h8,49276
4
4
  localdex/data_loader.py,sha256=hi9aSTto5Ti-OBGOgrQ-XwD5hmivsUwS1uC4rulhwQI,11366
5
5
  localdex/download_data.py,sha256=T4A3OliGe2RsrRV1glyCqRcFhQIRt29KcY1K1-IqTuU,21597
6
6
  localdex/exceptions.py,sha256=Z02-8Kci6jFDk2nnGdVSHZJMDDWE9vuwuASs4VM3To8,2777
@@ -4826,8 +4826,9 @@ localdex/models/ability.py,sha256=AQzv3XUHHl4sustMJjPDDjJOjXu2GMLTfcM3-tqQ_1w,30
4826
4826
  localdex/models/item.py,sha256=zXao8F-jBPUGq_YLeGeYeK_dZVI7aZMXtWOPwR3qusY,4677
4827
4827
  localdex/models/move.py,sha256=hfgcWI4ziz5MMvc9ddmkotxzYYdrSUqZZQ72IU5tucs,7629
4828
4828
  localdex/models/pokemon.py,sha256=glnOiEhkFc25U54hJHwUkT-okUgtL2prg3269YXI3w0,5422
4829
- localdex-0.2.40.dist-info/METADATA,sha256=RKqrxFuWY0y4-TZzkMJcIja370hWETfwnzWM1w6TpAA,8016
4830
- localdex-0.2.40.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
4831
- localdex-0.2.40.dist-info/entry_points.txt,sha256=n5GxSeQo-MRuvrT2wVk7hOzEFFsWf6tkBjkzmGIYJe4,47
4832
- localdex-0.2.40.dist-info/top_level.txt,sha256=vtupDMH-IaxVCoEZrmE0QzdTwhaKzngVJbTA1NkR_MY,9
4833
- localdex-0.2.40.dist-info/RECORD,,
4829
+ localdex-0.2.44.dist-info/licenses/LICENSE,sha256=i6DyIs1YqXBAxAIiGBS6vp2iQP9tiMd47S8dvaeFmDQ,1065
4830
+ localdex-0.2.44.dist-info/METADATA,sha256=GhTRATcy1SVpiW8UvOk8eFK2NVpFb8_56B5HAEXReWE,5886
4831
+ localdex-0.2.44.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
4832
+ localdex-0.2.44.dist-info/entry_points.txt,sha256=n5GxSeQo-MRuvrT2wVk7hOzEFFsWf6tkBjkzmGIYJe4,47
4833
+ localdex-0.2.44.dist-info/top_level.txt,sha256=vtupDMH-IaxVCoEZrmE0QzdTwhaKzngVJbTA1NkR_MY,9
4834
+ localdex-0.2.44.dist-info/RECORD,,
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 LocalDex
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -1,270 +0,0 @@
1
- Metadata-Version: 2.4
2
- Name: localdex
3
- Version: 0.2.40
4
- Summary: A local Pokemon data repository/Pokedex with fast offline access
5
- Author-email: LocalDex Team <localdex@example.com>
6
- License: MIT
7
- Project-URL: Homepage, https://github.com/colefoster/localdex
8
- Project-URL: Documentation, https://localdex.readthedocs.io/
9
- Project-URL: Repository, https://github.com/colefoster/localdex
10
- Project-URL: Bug Tracker, https://github.com/colefoster/localdex/issues
11
- Classifier: Development Status :: 3 - Alpha
12
- Classifier: Intended Audience :: Developers
13
- Classifier: Programming Language :: Python :: 3
14
- Classifier: Programming Language :: Python :: 3.8
15
- Classifier: Programming Language :: Python :: 3.9
16
- Classifier: Programming Language :: Python :: 3.10
17
- Classifier: Programming Language :: Python :: 3.11
18
- Classifier: Programming Language :: Python :: 3.12
19
- Classifier: Topic :: Games/Entertainment
20
- Classifier: Topic :: Software Development :: Libraries :: Python Modules
21
- Requires-Python: >=3.8
22
- Description-Content-Type: text/markdown
23
- Requires-Dist: requests
24
- Requires-Dist: typing-extensions
25
- Provides-Extra: core
26
- Provides-Extra: gen1
27
- Provides-Extra: gen2
28
- Provides-Extra: gen3
29
- Provides-Extra: gen4
30
- Provides-Extra: gen5
31
- Provides-Extra: gen6
32
- Provides-Extra: gen7
33
- Provides-Extra: gen8
34
- Provides-Extra: gen9
35
- Provides-Extra: learnsets
36
- Provides-Extra: items
37
- Provides-Extra: abilities
38
- Provides-Extra: full
39
- Requires-Dist: localdex[abilities,gen1,gen2,gen3,gen4,gen5,gen6,gen7,gen8,gen9,items,learnsets]; extra == "full"
40
- Provides-Extra: dev
41
- Requires-Dist: pytest>=7.0.0; extra == "dev"
42
- Requires-Dist: pytest-cov>=4.0.0; extra == "dev"
43
- Requires-Dist: black>=22.0.0; extra == "dev"
44
- Requires-Dist: isort>=5.0.0; extra == "dev"
45
- Requires-Dist: mypy>=1.0.0; extra == "dev"
46
- Requires-Dist: flake8>=5.0.0; extra == "dev"
47
-
48
- # LocalDex
49
-
50
- A fast, offline-first Python library for Pokemon data access. LocalDex provides comprehensive Pokemon information without requiring network requests, making it perfect for applications that need reliable, fast access to Pokemon data.
51
-
52
- [![PyPI version](https://badge.fury.io/py/localdex.svg)](https://badge.fury.io/py/localdex)
53
- [![Python versions](https://img.shields.io/pypi/pyversions/localdex.svg)](https://pypi.org/project/localdex/)
54
- [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
55
- [![Tests](https://github.com/colefoster/localdex/actions/workflows/release.yml/badge.svg)](https://github.com/colefoster/localdex/actions/workflows/release.yml)
56
-
57
- ## Features
58
-
59
- - **100% Offline**: All data is stored locally - no network requests required
60
- - **Fast Access**: Optimized for quick lookups and searches
61
- - **Comprehensive Data**: Pokemon, moves, abilities, items, and more
62
- - **Flexible Installation**: Choose which data sets to include
63
- - **Type Hints**: Full type support for better development experience
64
- - **Multiple Generations**: Support for all Pokemon generations
65
- - **Competitive Data**: Includes battle sets and competitive information
66
-
67
- ## Installation
68
-
69
- ### Basic Installation
70
-
71
- ```bash
72
- pip install localdex
73
- ```
74
-
75
- ### Selective Data Installation
76
-
77
- Install only the data you need to minimize package size:
78
-
79
- ```bash
80
- # Core Pokemon data only
81
- pip install localdex[core]
82
-
83
- # Specific generation
84
- pip install localdex[gen1] # Generation 1 only
85
- pip install localdex[gen9] # Generation 9 only
86
-
87
- # Additional data sets
88
- pip install localdex[competitive] # Competitive battle data
89
- pip install localdex[learnsets] # Detailed move learnsets
90
- pip install localdex[items] # Item data
91
- pip install localdex[abilities] # Ability data
92
-
93
- # Full installation with everything
94
- pip install localdex[full]
95
- ```
96
-
97
-
98
- ## Quick Start
99
-
100
- ```python
101
- from localdex import LocalDex
102
-
103
- # Initialize the dex
104
- dex = LocalDex()
105
-
106
- # Get Pokemon by name
107
- pikachu = dex.get_pokemon("pikachu")
108
- print(f"{pikachu.name} - {pikachu.types}")
109
-
110
- # Get Pokemon by ID
111
- charizard = dex.get_pokemon_by_id(6)
112
- print(f"{charizard.name} - HP: {charizard.base_stats.hp}")
113
-
114
- # Get Pokemon stats
115
- bulbasaur = dex.get_pokemon("bulbasaur")
116
- print(f"{bulbasaur.name} - Attack: {bulbasaur.base_stats.attack}, Speed: {bulbasaur.base_stats.speed}")
117
-
118
- # Get moves
119
- thunderbolt = dex.get_move("thunderbolt")
120
- print(f"{thunderbolt.name} - Power: {thunderbolt.base_power}, Type: {thunderbolt.type}")
121
-
122
- # Get abilities (note: use dashes in names like "lightning-rod")
123
- lightning_rod = dex.get_ability("lightning-rod")
124
- print(f"{lightning_rod.name} - {lightning_rod.description}")
125
-
126
- # Search Pokemon by type (case-insensitive)
127
- fire_types = dex.search_pokemon(type="fire")
128
- print(f"Fire type Pokemon: {[p.name for p in fire_types[:5]]}")
129
-
130
- # Search Pokemon by stat
131
- fast_pokemon = dex.search_pokemon(min_speed=120)
132
- print(f"Very fast Pokemon: {[p.name for p in fast_pokemon[:5]]}")
133
-
134
- # Get all moves of a specific type (case-insensitive)
135
- all_moves = dex.get_all_moves()
136
- electric_moves = [m for m in all_moves if m.type.lower() == "electric"]
137
- print(f"Electric moves count: {len(electric_moves)}")
138
- print(f"First 5 Electric moves: {[m.name for m in electric_moves[:5]]}")
139
-
140
- ## API Reference
141
-
142
- ### LocalDex Class
143
-
144
- The main class for accessing Pokemon data.
145
-
146
- #### Methods
147
-
148
- - `get_pokemon(name_or_id: Union[str, int]) -> Pokemon`: Get Pokemon by name or ID
149
- - `get_pokemon_by_id(id: int) -> Pokemon`: Get Pokemon by ID
150
- - `get_pokemon_by_name(name: str) -> Pokemon`: Get Pokemon by name
151
- - `search_pokemon(**filters) -> List[Pokemon]`: Search Pokemon with filters
152
- - `get_move(name: str) -> Move`: Get move by name
153
- - `get_ability(name: str) -> Ability`: Get ability by name
154
- - `get_item(name: str) -> Item`: Get item by name
155
- - `get_all_pokemon() -> List[Pokemon]`: Get all Pokemon
156
- - `get_all_moves() -> List[Move]`: Get all moves
157
- - `get_all_abilities() -> List[Ability]`: Get all abilities
158
- - `get_all_items() -> List[Item]`: Get all items
159
-
160
- #### Search Filters
161
-
162
- ```python
163
- # Search by type
164
- fire_pokemon = dex.search_pokemon(type="Fire")
165
-
166
- # Search by generation
167
- gen1_pokemon = dex.search_pokemon(generation=1)
168
-
169
- # Search by multiple criteria
170
- legendary_fire = dex.search_pokemon(type="Fire", is_legendary=True)
171
-
172
- # Search by base stat range
173
- strong_pokemon = dex.search_pokemon(min_attack=100)
174
- ```
175
-
176
- ### Data Models
177
-
178
- #### Pokemon
179
-
180
- ```python
181
- class Pokemon:
182
- id: int
183
- name: str
184
- types: List[str]
185
- base_stats: BaseStats
186
- abilities: Dict[str, Ability]
187
- moves: List[Move]
188
- height: float
189
- weight: float
190
- description: str
191
- # ... and more
192
- ```
193
-
194
- #### Move
195
-
196
- ```python
197
- class Move:
198
- name: str
199
- type: str
200
- category: str
201
- base_power: int
202
- accuracy: int
203
- pp: int
204
- description: str
205
- # ... and more
206
- ```
207
-
208
- #### Ability
209
-
210
- ```python
211
- class Ability:
212
- name: str
213
- description: str
214
- short_description: str
215
- # ... and more
216
- ```
217
-
218
- ## Data Sets
219
-
220
- LocalDex organizes data into logical sets that can be installed independently:
221
-
222
- ### Core Data (`core`)
223
- - Basic Pokemon information (name, types, base stats)
224
- - Essential for most applications
225
-
226
- ### Generation Data (`gen1`-`gen9`)
227
- - Pokemon data for specific generations
228
- - Useful for generation-specific applications
229
-
230
- ### Additional Data Sets
231
- - **Competitive** (`competitive`): Battle sets and competitive data
232
- - **Learnsets** (`learnsets`): Detailed move learning information
233
- - **Items** (`items`): Item data and effects
234
- - **Abilities** (`abilities`): Detailed ability information
235
-
236
- ## CLI Usage
237
-
238
- LocalDex includes a command-line interface for quick data access:
239
-
240
- ```bash
241
- # Get Pokemon information
242
- localdex pokemon pikachu
243
-
244
- # Search Pokemon
245
- localdex search --type Fire --generation 1
246
-
247
- # Get move information
248
- localdex move thunderbolt
249
-
250
- # Get ability information
251
- localdex ability lightningrod
252
-
253
- # List all Pokemon
254
- localdex list-pokemon
255
-
256
- # Export data to JSON
257
- localdex export --format json --output pokemon_data.json
258
- ```
259
-
260
- ## License
261
-
262
- This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
263
-
264
- ## Data Sources
265
-
266
- LocalDex uses data from:
267
- - [Pokemon Showdown](https://github.com/smogon/pokemon-showdown)
268
- - [PokeAPI](https://pokeapi.co/) (for initial data collection)
269
-
270
-