mirror of
https://github.com/PokeAPI/pokeapi
synced 2024-11-22 19:33:10 +00:00
Merge branch 'master' into circleci-hook
This commit is contained in:
commit
5b8e4e1964
2 changed files with 126 additions and 35 deletions
|
@ -3134,45 +3134,75 @@ class EvolutionChainDetailSerializer(serializers.ModelSerializer):
|
|||
pokemon_objects, many=True, context=self.context
|
||||
).data
|
||||
|
||||
chain = entry = OrderedDict()
|
||||
current_evolutions = None
|
||||
evolution_data = None
|
||||
previous_entry = None
|
||||
previous_species = None
|
||||
# convert evolution data list to tree
|
||||
evolution_tree = self.build_evolution_tree(ref_data)
|
||||
|
||||
for index, species in enumerate(ref_data):
|
||||
|
||||
# If evolves from something
|
||||
if species["evolves_from_species"]:
|
||||
|
||||
# In case this pokemon is one of multiple evolutions a pokemon can make
|
||||
if previous_species:
|
||||
if previous_species["id"] == species["evolves_from_species"]:
|
||||
current_evolutions = previous_entry["evolves_to"]
|
||||
|
||||
entry = OrderedDict()
|
||||
|
||||
evolution_object = PokemonEvolution.objects.filter(
|
||||
evolved_species=species["id"]
|
||||
)
|
||||
|
||||
evolution_data = PokemonEvolutionSerializer(
|
||||
evolution_object, many=True, context=self.context
|
||||
).data
|
||||
|
||||
current_evolutions.append(entry)
|
||||
|
||||
entry["is_baby"] = species["is_baby"]
|
||||
entry["species"] = summary_data[index]
|
||||
entry["evolution_details"] = evolution_data or []
|
||||
entry["evolves_to"] = []
|
||||
|
||||
# Keep track of previous entries for complex chaining
|
||||
previous_entry = entry
|
||||
previous_species = species
|
||||
# serialize chain recursively from tree
|
||||
chain = self.build_chain_link_entry(evolution_tree, summary_data)
|
||||
|
||||
return chain
|
||||
|
||||
# converts a list of Pokemon species evolution data into a tree representing the evolution chain
|
||||
def build_evolution_tree(self, species_evolution_data):
|
||||
evolution_tree = OrderedDict()
|
||||
evolution_tree["species"] = species_evolution_data[0]
|
||||
evolution_tree["children"] = []
|
||||
|
||||
for species in species_evolution_data[1:]:
|
||||
chain_link = OrderedDict()
|
||||
chain_link["species"] = species
|
||||
chain_link["children"] = []
|
||||
|
||||
evolves_from_species_id = chain_link["species"]["evolves_from_species"]
|
||||
|
||||
# find parent link by DFS
|
||||
parent_link = evolution_tree
|
||||
search_stack = [parent_link]
|
||||
|
||||
while len(search_stack) > 0:
|
||||
l = search_stack.pop()
|
||||
if l["species"]["id"] == evolves_from_species_id:
|
||||
parent_link = l
|
||||
break
|
||||
|
||||
# "left" to "right" requires reversing the list of children
|
||||
search_stack += reversed(l["children"])
|
||||
|
||||
parent_link["children"].append(chain_link)
|
||||
|
||||
return evolution_tree
|
||||
|
||||
# serializes an evolution chain link recursively
|
||||
# chain_link is a tree representing an evolution chain
|
||||
def build_chain_link_entry(self, chain_link, summary_data):
|
||||
entry = OrderedDict()
|
||||
evolution_data = None
|
||||
|
||||
species = chain_link["species"]
|
||||
if species["evolves_from_species"]:
|
||||
|
||||
evolution_object = PokemonEvolution.objects.filter(
|
||||
evolved_species=species["id"]
|
||||
)
|
||||
|
||||
evolution_data = PokemonEvolutionSerializer(
|
||||
evolution_object, many=True, context=self.context
|
||||
).data
|
||||
|
||||
entry["is_baby"] = species["is_baby"]
|
||||
|
||||
species_summary = next(x for x in summary_data if x["name"] == species["name"])
|
||||
entry["species"] = species_summary
|
||||
|
||||
entry["evolution_details"] = evolution_data or []
|
||||
|
||||
evolves_to = [
|
||||
self.build_chain_link_entry(c, summary_data) for c in chain_link["children"]
|
||||
]
|
||||
entry["evolves_to"] = evolves_to
|
||||
|
||||
return entry
|
||||
|
||||
|
||||
class PokemonDexNumberSerializer(serializers.ModelSerializer):
|
||||
|
||||
|
|
|
@ -5203,6 +5203,67 @@ class APITests(APIData, APITestCase):
|
|||
"{}{}/type/{}/".format(TEST_HOST, API_V2, stage_two_second_party_type.pk),
|
||||
)
|
||||
|
||||
# verifies that the wurmple evolution chain is serialized correctly
|
||||
def test_evolution_chain_api_wurmple_bugfix(self):
|
||||
|
||||
# set up wurmple-like evolution chain
|
||||
evolution_chain = self.setup_evolution_chain_data()
|
||||
|
||||
basic = self.setup_pokemon_species_data(
|
||||
name="wurmple", evolution_chain=evolution_chain,
|
||||
)
|
||||
|
||||
stage_one_first = self.setup_pokemon_species_data(
|
||||
name="silcoon", evolves_from_species=basic, evolution_chain=evolution_chain,
|
||||
)
|
||||
stage_one_first_evolution = self.setup_pokemon_evolution_data(
|
||||
evolved_species=stage_one_first, min_level=7
|
||||
)
|
||||
|
||||
stage_two_first = self.setup_pokemon_species_data(
|
||||
name="beautifly",
|
||||
evolves_from_species=stage_one_first,
|
||||
evolution_chain=evolution_chain,
|
||||
)
|
||||
stage_two_first_evolution = self.setup_pokemon_evolution_data(
|
||||
evolved_species=stage_two_first, min_level=10
|
||||
)
|
||||
|
||||
stage_one_second = self.setup_pokemon_species_data(
|
||||
name="cascoon", evolves_from_species=basic, evolution_chain=evolution_chain,
|
||||
)
|
||||
stage_one_second_evolution = self.setup_pokemon_evolution_data(
|
||||
evolved_species=stage_one_second, min_level=7
|
||||
)
|
||||
|
||||
stage_two_second = self.setup_pokemon_species_data(
|
||||
name="dustox",
|
||||
evolves_from_species=stage_one_second,
|
||||
evolution_chain=evolution_chain,
|
||||
)
|
||||
stage_two_second_evolution = self.setup_pokemon_evolution_data(
|
||||
evolved_species=stage_two_second, min_level=10
|
||||
)
|
||||
|
||||
response = self.client.get(
|
||||
"{}/evolution-chain/{}/".format(API_V2, evolution_chain.pk)
|
||||
)
|
||||
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
|
||||
# base params
|
||||
self.assertEqual(response.data["id"], evolution_chain.pk)
|
||||
|
||||
# assert tree has been serialized correctly
|
||||
basic_data = response.data["chain"]
|
||||
self.assertEqual(len(basic_data["evolves_to"]), 2)
|
||||
|
||||
stage_one_first_data = basic_data["evolves_to"][0]
|
||||
self.assertEqual(len(stage_one_first_data["evolves_to"]), 1)
|
||||
|
||||
stage_one_second_data = basic_data["evolves_to"][1]
|
||||
self.assertEqual(len(stage_one_second_data["evolves_to"]), 1)
|
||||
|
||||
# Encounter Tests
|
||||
def test_encounter_method_api(self):
|
||||
|
||||
|
|
Loading…
Reference in a new issue