mirror of
https://github.com/PokeAPI/pokeapi
synced 2025-02-16 12:38:25 +00:00
Merge pull request #634 from phrasmotica/feature/past-type-efficacy
Add past type damage relations data
This commit is contained in:
commit
2be93d816c
7 changed files with 548 additions and 117 deletions
|
@ -594,6 +594,16 @@ def _build_types():
|
|||
|
||||
build_generic((TypeEfficacy,), "type_efficacy.csv", csv_record_to_objects)
|
||||
|
||||
def csv_record_to_objects(info):
|
||||
yield TypeEfficacyPast(
|
||||
damage_type_id=int(info[0]),
|
||||
target_type_id=int(info[1]),
|
||||
damage_factor=int(info[2]),
|
||||
generation_id=int(info[3]),
|
||||
)
|
||||
|
||||
build_generic((TypeEfficacyPast,), "type_efficacy_past.csv", csv_record_to_objects)
|
||||
|
||||
|
||||
#############
|
||||
# CONTEST #
|
||||
|
|
7
data/v2/csv/type_efficacy_past.csv
Normal file
7
data/v2/csv/type_efficacy_past.csv
Normal file
|
@ -0,0 +1,7 @@
|
|||
damage_type_id,target_type_id,damage_factor,generation_id
|
||||
4,7,200,1
|
||||
7,4,200,1
|
||||
8,14,0,1
|
||||
15,10,100,1
|
||||
8,9,50,5
|
||||
17,9,50,5
|
|
|
@ -2864,67 +2864,133 @@ Types are properties for Pokémon and their moves. Each type has three propertie
|
|||
|
||||
```json
|
||||
{
|
||||
"id": 5,
|
||||
"name": "ground",
|
||||
"damage_relations": {
|
||||
"no_damage_to": [{
|
||||
"name": "flying",
|
||||
"url": "http://pokeapi.co/api/v2/type/3/"
|
||||
}],
|
||||
"half_damage_to": [{
|
||||
"name": "bug",
|
||||
"url": "http://pokeapi.co/api/v2/type/7/"
|
||||
}],
|
||||
"double_damage_to": [{
|
||||
"name": "poison",
|
||||
"url": "http://pokeapi.co/api/v2/type/4/"
|
||||
}],
|
||||
"no_damage_from": [{
|
||||
"name": "electric",
|
||||
"url": "http://pokeapi.co/api/v2/type/13/"
|
||||
}],
|
||||
"half_damage_from": [{
|
||||
"name": "poison",
|
||||
"url": "http://pokeapi.co/api/v2/type/4/"
|
||||
}],
|
||||
"double_damage_from": [{
|
||||
"name": "water",
|
||||
"url": "http://pokeapi.co/api/v2/type/11/"
|
||||
}]
|
||||
},
|
||||
"game_indices": [{
|
||||
"game_index": 4,
|
||||
"generation": {
|
||||
"name": "generation-i",
|
||||
"url": "http://pokeapi.co/api/v2/generation/1/"
|
||||
}
|
||||
}],
|
||||
"generation": {
|
||||
"name": "generation-i",
|
||||
"url": "http://pokeapi.co/api/v2/generation/1/"
|
||||
},
|
||||
"move_damage_class": {
|
||||
"name": "physical",
|
||||
"url": "http://pokeapi.co/api/v2/move-damage-class/2/"
|
||||
},
|
||||
"names": [{
|
||||
"name": "ã˜ã‚ã‚“",
|
||||
"language": {
|
||||
"name": "ja",
|
||||
"url": "http://pokeapi.co/api/v2/language/1/"
|
||||
}
|
||||
}],
|
||||
"pokemon": [{
|
||||
"slot": 1,
|
||||
"pokemon": {
|
||||
"name": "sandshrew",
|
||||
"url": "http://pokeapi.co/api/v2/pokemon/27/"
|
||||
}
|
||||
}],
|
||||
"moves": [{
|
||||
"name": "sand-attack",
|
||||
"url": "http://pokeapi.co/api/v2/move/28/"
|
||||
}]
|
||||
"id": 8,
|
||||
"name": "ghost",
|
||||
"damage_relations": {
|
||||
"no_damage_to": [
|
||||
{
|
||||
"name": "normal",
|
||||
"url": "https://pokeapi.co/api/v2/type/1/"
|
||||
}
|
||||
],
|
||||
"half_damage_to": [
|
||||
{
|
||||
"name": "dark",
|
||||
"url": "https://pokeapi.co/api/v2/type/17/"
|
||||
}
|
||||
],
|
||||
"double_damage_to": [
|
||||
{
|
||||
"name": "ghost",
|
||||
"url": "https://pokeapi.co/api/v2/type/8/"
|
||||
}
|
||||
],
|
||||
"no_damage_from": [
|
||||
{
|
||||
"name": "normal",
|
||||
"url": "https://pokeapi.co/api/v2/type/1/"
|
||||
}
|
||||
],
|
||||
"half_damage_from": [
|
||||
{
|
||||
"name": "poison",
|
||||
"url": "https://pokeapi.co/api/v2/type/4/"
|
||||
}
|
||||
],
|
||||
"double_damage_from": [
|
||||
{
|
||||
"name": "ghost",
|
||||
"url": "https://pokeapi.co/api/v2/type/8/"
|
||||
}
|
||||
]
|
||||
},
|
||||
"past_damage_relations": [
|
||||
{
|
||||
"generation": {
|
||||
"name": "generation-v",
|
||||
"url": "https://pokeapi.co/api/v2/generation/5/"
|
||||
},
|
||||
"damage_relations": {
|
||||
"no_damage_to": [
|
||||
{
|
||||
"name": "normal",
|
||||
"url": "https://pokeapi.co/api/v2/type/1/"
|
||||
}
|
||||
],
|
||||
"half_damage_to": [
|
||||
{
|
||||
"name": "steel",
|
||||
"url": "https://pokeapi.co/api/v2/type/9/"
|
||||
}
|
||||
],
|
||||
"double_damage_to": [
|
||||
{
|
||||
"name": "ghost",
|
||||
"url": "https://pokeapi.co/api/v2/type/8/"
|
||||
}
|
||||
],
|
||||
"no_damage_from": [
|
||||
{
|
||||
"name": "normal",
|
||||
"url": "https://pokeapi.co/api/v2/type/1/"
|
||||
}
|
||||
],
|
||||
"half_damage_from": [
|
||||
{
|
||||
"name": "poison",
|
||||
"url": "https://pokeapi.co/api/v2/type/4/"
|
||||
}
|
||||
],
|
||||
"double_damage_from": [
|
||||
{
|
||||
"name": "ghost",
|
||||
"url": "https://pokeapi.co/api/v2/type/8/"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
"game_indices": [
|
||||
{
|
||||
"game_index": 8,
|
||||
"generation": {
|
||||
"name": "generation-i",
|
||||
"url": "https://pokeapi.co/api/v2/generation/1/"
|
||||
}
|
||||
}
|
||||
],
|
||||
"generation": {
|
||||
"name": "generation-i",
|
||||
"url": "https://pokeapi.co/api/v2/generation/1/"
|
||||
},
|
||||
"move_damage_class": {
|
||||
"name": "physical",
|
||||
"url": "https://pokeapi.co/api/v2/move-damage-class/2/"
|
||||
},
|
||||
"names": [
|
||||
{
|
||||
"name": "ゴースト",
|
||||
"language": {
|
||||
"name": "ja-Hrkt",
|
||||
"url": "https://pokeapi.co/api/v2/language/1/"
|
||||
}
|
||||
}
|
||||
],
|
||||
"pokemon": [
|
||||
{
|
||||
"slot": 1,
|
||||
"pokemon": {
|
||||
"name": "gastly",
|
||||
"url": "https://pokeapi.co/api/v2/pokemon/92/"
|
||||
}
|
||||
}
|
||||
],
|
||||
"moves": [
|
||||
{
|
||||
"name": "night-shade",
|
||||
"url": "https://pokeapi.co/api/v2/move/101/"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -2934,15 +3000,16 @@ Types are properties for Pokémon and their moves. Each type has three propertie
|
|||
|
||||
| Name | Description | Data Type |
|
||||
| ---- | ----------- | --------- |
|
||||
| id | The identifier for this type resource | integer |
|
||||
| name | The name for this type resource | string |
|
||||
| damage_relations | A detail of how effective this type is toward others and vice versa | [TypeRelations](#typerelations) |
|
||||
| game_indices | A list of game indices relevent to this item by generation | list [GenerationGameIndex](#generationgameindex) |
|
||||
| generation | The generation this type was introduced in | [NamedAPIResource](#namedapiresource) ([Generation](#generations)) |
|
||||
| move_damage_class | The class of damage inflicted by this type | [NamedAPIResource](#namedapiresource) ([MoveDamageClass](#move-damage-classes)) |
|
||||
| names | The name of this type listed in different languages | list [Name](#resourcename) |
|
||||
| pokemon | A list of details of pokemon that have this type | [TypePokemon](#typepokemon) |
|
||||
| moves | A list of moves that have this type | list [NamedAPIResource](#namedapiresource) ([Move](#moves)) |
|
||||
| id | The identifier for this type resource | integer |
|
||||
| name | The name for this type resource | string |
|
||||
| damage_relations | A detail of how effective this type is toward others and vice versa | [TypeRelations](#typerelations) |
|
||||
| past_damage_relations | A list of details of how effective this type was toward others and vice versa in previous generations | list [TypeRelationsPast](#typerelationspast) |
|
||||
| game_indices | A list of game indices relevent to this item by generation | list [GenerationGameIndex](#generationgameindex) |
|
||||
| generation | The generation this type was introduced in | [NamedAPIResource](#namedapiresource) ([Generation](#generations)) |
|
||||
| move_damage_class | The class of damage inflicted by this type | [NamedAPIResource](#namedapiresource) ([MoveDamageClass](#move-damage-classes)) |
|
||||
| names | The name of this type listed in different languages | list [Name](#resourcename) |
|
||||
| pokemon | A list of details of pokemon that have this type | [TypePokemon](#typepokemon) |
|
||||
| moves | A list of moves that have this type | list [NamedAPIResource](#namedapiresource) ([Move](#moves)) |
|
||||
|
||||
#### TypePokemon
|
||||
|
||||
|
@ -2962,6 +3029,13 @@ Types are properties for Pokémon and their moves. Each type has three propertie
|
|||
| half_damage_from | A list of types that are not very effective against this type | list [NamedAPIResource](#namedapiresource) ([Type](#types)) |
|
||||
| double_damage_from | A list of types that are very effective against this type | list [NamedAPIResource](#namedapiresource) ([Type](#types)) |
|
||||
|
||||
#### TypeRelationsPast
|
||||
|
||||
| Name | Description | Data Type |
|
||||
| ---- | ----------- | --------- |
|
||||
| generation | The last generation in which the referenced type had the listed damage relations | [NamedAPIResource](#namedapiresource) ([Generation](#generations)) |
|
||||
| damage_relations | The damage relations the referenced type had up to and including the listed generation | list [TypeRelations](#typerelations) |
|
||||
|
||||
|
||||
<h1 id="utility-section">Utility</h1>
|
||||
|
||||
|
|
84
pokemon_v2/migrations/0011_typeefficacypast.py
Normal file
84
pokemon_v2/migrations/0011_typeefficacypast.py
Normal file
|
@ -0,0 +1,84 @@
|
|||
# Generated by Django 2.1.11 on 2021-02-24 13:42
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("pokemon_v2", "0010_pokemonformtype"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name="TypeEfficacyPast",
|
||||
fields=[
|
||||
(
|
||||
"id",
|
||||
models.AutoField(
|
||||
auto_created=True,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
verbose_name="ID",
|
||||
),
|
||||
),
|
||||
("damage_factor", models.IntegerField()),
|
||||
(
|
||||
"damage_type",
|
||||
models.ForeignKey(
|
||||
blank=True,
|
||||
null=True,
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
related_name="typeefficacypast_damage_type",
|
||||
to="pokemon_v2.Type",
|
||||
),
|
||||
),
|
||||
(
|
||||
"generation",
|
||||
models.ForeignKey(
|
||||
blank=True,
|
||||
null=True,
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
related_name="typeefficacypast",
|
||||
to="pokemon_v2.Generation",
|
||||
),
|
||||
),
|
||||
(
|
||||
"target_type",
|
||||
models.ForeignKey(
|
||||
blank=True,
|
||||
null=True,
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
related_name="typeefficacypast_target_type",
|
||||
to="pokemon_v2.Type",
|
||||
),
|
||||
),
|
||||
],
|
||||
options={
|
||||
"abstract": False,
|
||||
},
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="typeefficacy",
|
||||
name="damage_type",
|
||||
field=models.ForeignKey(
|
||||
blank=True,
|
||||
null=True,
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
related_name="typeefficacy_damage_type",
|
||||
to="pokemon_v2.Type",
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="typeefficacy",
|
||||
name="target_type",
|
||||
field=models.ForeignKey(
|
||||
blank=True,
|
||||
null=True,
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
related_name="typeefficacy_target_type",
|
||||
to="pokemon_v2.Type",
|
||||
),
|
||||
),
|
||||
]
|
|
@ -614,6 +614,30 @@ class HasType(models.Model):
|
|||
abstract = True
|
||||
|
||||
|
||||
class HasTypeEfficacy(models.Model):
|
||||
|
||||
damage_type = models.ForeignKey(
|
||||
"Type",
|
||||
blank=True,
|
||||
null=True,
|
||||
related_name="%(class)s_damage_type",
|
||||
on_delete=models.CASCADE,
|
||||
)
|
||||
|
||||
target_type = models.ForeignKey(
|
||||
"Type",
|
||||
blank=True,
|
||||
null=True,
|
||||
related_name="%(class)s_target_type",
|
||||
on_delete=models.CASCADE,
|
||||
)
|
||||
|
||||
damage_factor = models.IntegerField()
|
||||
|
||||
class Meta:
|
||||
abstract = True
|
||||
|
||||
|
||||
class HasVersion(models.Model):
|
||||
|
||||
version = models.ForeignKey(
|
||||
|
@ -795,25 +819,13 @@ class TypeGameIndex(HasType, HasGeneration, HasGameIndex):
|
|||
pass
|
||||
|
||||
|
||||
class TypeEfficacy(models.Model):
|
||||
class TypeEfficacy(HasTypeEfficacy):
|
||||
pass
|
||||
|
||||
damage_type = models.ForeignKey(
|
||||
"Type",
|
||||
blank=True,
|
||||
null=True,
|
||||
related_name="damage_type",
|
||||
on_delete=models.CASCADE,
|
||||
)
|
||||
|
||||
target_type = models.ForeignKey(
|
||||
"Type",
|
||||
blank=True,
|
||||
null=True,
|
||||
related_name="target_type",
|
||||
on_delete=models.CASCADE,
|
||||
)
|
||||
|
||||
damage_factor = models.IntegerField()
|
||||
# model for a type's efficacy that was used until a given generation
|
||||
class TypeEfficacyPast(HasTypeEfficacy, HasGeneration):
|
||||
pass
|
||||
|
||||
|
||||
#################
|
||||
|
|
|
@ -1793,6 +1793,15 @@ class TypeEfficacySerializer(serializers.ModelSerializer):
|
|||
fields = "__all__"
|
||||
|
||||
|
||||
class TypeEfficacyPastSerializer(serializers.ModelSerializer):
|
||||
|
||||
generation = GenerationSummarySerializer()
|
||||
|
||||
class Meta:
|
||||
model = TypeEfficacyPast
|
||||
fields = ("target_type", "damage_type", "damage_factor", "generation")
|
||||
|
||||
|
||||
class TypeGameIndexSerializer(serializers.ModelSerializer):
|
||||
|
||||
generation = GenerationSummarySerializer()
|
||||
|
@ -1823,6 +1832,9 @@ class TypeDetailSerializer(serializers.ModelSerializer):
|
|||
)
|
||||
move_damage_class = MoveDamageClassSummarySerializer()
|
||||
damage_relations = serializers.SerializerMethodField("get_type_relationships")
|
||||
past_damage_relations = serializers.SerializerMethodField(
|
||||
"get_type_past_relationships"
|
||||
)
|
||||
pokemon = serializers.SerializerMethodField("get_type_pokemon")
|
||||
moves = MoveSummarySerializer(many=True, read_only=True, source="move")
|
||||
|
||||
|
@ -1832,6 +1844,7 @@ class TypeDetailSerializer(serializers.ModelSerializer):
|
|||
"id",
|
||||
"name",
|
||||
"damage_relations",
|
||||
"past_damage_relations",
|
||||
"game_indices",
|
||||
"generation",
|
||||
"move_damage_class",
|
||||
|
@ -1840,6 +1853,22 @@ class TypeDetailSerializer(serializers.ModelSerializer):
|
|||
"moves",
|
||||
)
|
||||
|
||||
# adds an entry for the given type with the given damage
|
||||
# factor in the given direction to the set of relations
|
||||
def add_type_entry(self, relations, type, damage_factor, direction="_damage_to"):
|
||||
if damage_factor == 200:
|
||||
relations["double" + direction].append(
|
||||
TypeSummarySerializer(type, context=self.context).data
|
||||
)
|
||||
elif damage_factor == 50:
|
||||
relations["half" + direction].append(
|
||||
TypeSummarySerializer(type, context=self.context).data
|
||||
)
|
||||
elif damage_factor == 0:
|
||||
relations["no" + direction].append(
|
||||
TypeSummarySerializer(type, context=self.context).data
|
||||
)
|
||||
|
||||
def get_type_relationships(self, obj):
|
||||
|
||||
relations = OrderedDict()
|
||||
|
@ -1857,18 +1886,8 @@ class TypeDetailSerializer(serializers.ModelSerializer):
|
|||
|
||||
for relation in serializer.data:
|
||||
type = Type.objects.get(pk=relation["target_type"])
|
||||
if relation["damage_factor"] == 200:
|
||||
relations["double_damage_to"].append(
|
||||
TypeSummarySerializer(type, context=self.context).data
|
||||
)
|
||||
elif relation["damage_factor"] == 50:
|
||||
relations["half_damage_to"].append(
|
||||
TypeSummarySerializer(type, context=self.context).data
|
||||
)
|
||||
elif relation["damage_factor"] == 0:
|
||||
relations["no_damage_to"].append(
|
||||
TypeSummarySerializer(type, context=self.context).data
|
||||
)
|
||||
damage_factor = relation["damage_factor"]
|
||||
self.add_type_entry(relations, type, damage_factor, direction="_damage_to")
|
||||
|
||||
# Damage From
|
||||
results = TypeEfficacy.objects.filter(target_type=obj)
|
||||
|
@ -1876,21 +1895,143 @@ class TypeDetailSerializer(serializers.ModelSerializer):
|
|||
|
||||
for relation in serializer.data:
|
||||
type = Type.objects.get(pk=relation["damage_type"])
|
||||
if relation["damage_factor"] == 200:
|
||||
relations["double_damage_from"].append(
|
||||
TypeSummarySerializer(type, context=self.context).data
|
||||
)
|
||||
elif relation["damage_factor"] == 50:
|
||||
relations["half_damage_from"].append(
|
||||
TypeSummarySerializer(type, context=self.context).data
|
||||
)
|
||||
elif relation["damage_factor"] == 0:
|
||||
relations["no_damage_from"].append(
|
||||
TypeSummarySerializer(type, context=self.context).data
|
||||
)
|
||||
damage_factor = relation["damage_factor"]
|
||||
self.add_type_entry(
|
||||
relations, type, damage_factor, direction="_damage_from"
|
||||
)
|
||||
|
||||
return relations
|
||||
|
||||
# takes a list of past type relations by generation and
|
||||
# returns a list of lists where each list has the entries
|
||||
# for a single generation
|
||||
def group_relations_by_generation(self, serializer_data):
|
||||
data_by_gen = []
|
||||
|
||||
current_generation = ""
|
||||
generation_data = []
|
||||
for relation in serializer_data:
|
||||
|
||||
gen_name = relation["generation"]["name"]
|
||||
if gen_name != current_generation:
|
||||
# first item for this generation so create its list
|
||||
current_generation = gen_name
|
||||
generation_data = [relation]
|
||||
data_by_gen.append(generation_data)
|
||||
else:
|
||||
# add to this generation's list
|
||||
generation_data.append(relation)
|
||||
|
||||
return data_by_gen
|
||||
|
||||
# removes the entry for the given type in
|
||||
# the given direction from the set of relations
|
||||
def remove_type_entry(self, relations, type, direction="_damage_to"):
|
||||
for k in ["double", "half", "no"]:
|
||||
rel_list = relations[k + direction]
|
||||
for i, o in enumerate(rel_list):
|
||||
if o["name"] == type.name:
|
||||
del rel_list[i]
|
||||
return
|
||||
|
||||
# returns past type relationships for the given type object
|
||||
def get_type_past_relationships(self, obj):
|
||||
|
||||
# collect data from DB
|
||||
damage_type_results = list(TypeEfficacyPast.objects.filter(damage_type=obj))
|
||||
target_type_results = list(TypeEfficacyPast.objects.filter(target_type=obj))
|
||||
serializer = TypeEfficacyPastSerializer(
|
||||
damage_type_results + target_type_results, many=True, context=self.context
|
||||
)
|
||||
|
||||
# group data by generation
|
||||
data_by_gen = self.group_relations_by_generation(serializer.data)
|
||||
|
||||
# process each generation's data in turn
|
||||
final_data = []
|
||||
past_relations = {}
|
||||
for gen_data in data_by_gen:
|
||||
# create past relations object for this generation
|
||||
past_relations = OrderedDict()
|
||||
|
||||
# set generation
|
||||
past_relations["generation"] = gen_data[0]["generation"]
|
||||
|
||||
# use current damage relations object
|
||||
past_relations["damage_relations"] = self.get_type_relationships(obj)
|
||||
relations = past_relations["damage_relations"]
|
||||
|
||||
current_gen = Generation.objects.get(name=gen_data[0]["generation"]["name"])
|
||||
|
||||
# remove types not yet introduced
|
||||
# e.g. Poison has no effect on Steel, but Steel was not present in generation I
|
||||
# so it should be absent from the list
|
||||
relations["no_damage_to"] = self.remove_newer_types(
|
||||
relations["no_damage_to"], current_gen
|
||||
)
|
||||
relations["half_damage_to"] = self.remove_newer_types(
|
||||
relations["half_damage_to"], current_gen
|
||||
)
|
||||
relations["double_damage_to"] = self.remove_newer_types(
|
||||
relations["double_damage_to"], current_gen
|
||||
)
|
||||
relations["no_damage_from"] = self.remove_newer_types(
|
||||
relations["no_damage_from"], current_gen
|
||||
)
|
||||
relations["half_damage_from"] = self.remove_newer_types(
|
||||
relations["half_damage_from"], current_gen
|
||||
)
|
||||
relations["double_damage_from"] = self.remove_newer_types(
|
||||
relations["double_damage_from"], current_gen
|
||||
)
|
||||
|
||||
# populate offensive relations
|
||||
results = list(filter(lambda x: x["damage_type"] == obj.id, gen_data))
|
||||
for relation in results:
|
||||
|
||||
type = Type.objects.get(pk=relation["target_type"])
|
||||
|
||||
# remove conflicting entry if it exists
|
||||
self.remove_type_entry(relations, type, direction="_damage_to")
|
||||
|
||||
# add entry
|
||||
damage_factor = relation["damage_factor"]
|
||||
self.add_type_entry(
|
||||
relations, type, damage_factor, direction="_damage_to"
|
||||
)
|
||||
|
||||
del relation["generation"]
|
||||
|
||||
# populate defensive relations
|
||||
results = list(filter(lambda x: x["target_type"] == obj.id, gen_data))
|
||||
for relation in results:
|
||||
|
||||
type = Type.objects.get(pk=relation["damage_type"])
|
||||
|
||||
# remove conflicting entry if it exists
|
||||
self.remove_type_entry(relations, type, direction="_damage_from")
|
||||
|
||||
# add entry
|
||||
damage_factor = relation["damage_factor"]
|
||||
self.add_type_entry(
|
||||
relations, type, damage_factor, direction="_damage_from"
|
||||
)
|
||||
|
||||
del relation["generation"]
|
||||
|
||||
# add to final list
|
||||
final_data.append(past_relations)
|
||||
|
||||
return final_data
|
||||
|
||||
def remove_newer_types(self, relations, current_gen):
|
||||
return list(filter(lambda x: self.type_is_present(x, current_gen), relations))
|
||||
|
||||
def type_is_present(self, type, current_gen):
|
||||
type_obj = Type.objects.get(name=type["name"])
|
||||
gen_introduced = Generation.objects.get(pk=type_obj.generation.id)
|
||||
return gen_introduced.id <= current_gen.id
|
||||
|
||||
def get_type_pokemon(self, obj):
|
||||
|
||||
poke_type_objects = PokemonType.objects.filter(type=obj)
|
||||
|
|
|
@ -3420,12 +3420,30 @@ class APITests(APIData, APITestCase):
|
|||
pokemon = self.setup_pokemon_data(name="pkmn for base tp")
|
||||
pokemon_type = self.setup_pokemon_type_data(pokemon=pokemon, type=type)
|
||||
|
||||
no_damage_to = self.setup_type_data(name="no damage to tp")
|
||||
half_damage_to = self.setup_type_data(name="half damage to tp")
|
||||
double_damage_to = self.setup_type_data(name="double damage to tp")
|
||||
no_damage_from = self.setup_type_data(name="no damage from tp")
|
||||
half_damage_from = self.setup_type_data(name="half damage from tp")
|
||||
double_damage_from = self.setup_type_data(name="double damage from tp")
|
||||
generation = self.setup_generation_data(name="past gen")
|
||||
|
||||
no_damage_to = self.setup_type_data(
|
||||
name="no damage to tp", generation=generation
|
||||
)
|
||||
half_damage_to = self.setup_type_data(
|
||||
name="half damage to tp", generation=generation
|
||||
)
|
||||
double_damage_to = self.setup_type_data(
|
||||
name="double damage to tp", generation=generation
|
||||
)
|
||||
no_damage_from = self.setup_type_data(
|
||||
name="no damage from tp", generation=generation
|
||||
)
|
||||
half_damage_from = self.setup_type_data(
|
||||
name="half damage from tp", generation=generation
|
||||
)
|
||||
double_damage_from = self.setup_type_data(
|
||||
name="double damage from tp", generation=generation
|
||||
)
|
||||
|
||||
newer_generation = self.setup_generation_data(name="newer_generation")
|
||||
|
||||
newer_type = self.setup_type_data(name="newer tp", generation=newer_generation)
|
||||
|
||||
# type relations
|
||||
no_damage_to_relation = TypeEfficacy(
|
||||
|
@ -3458,6 +3476,22 @@ class APITests(APIData, APITestCase):
|
|||
)
|
||||
double_damage_from_type_relation.save()
|
||||
|
||||
double_damage_from_newer_type_relation = TypeEfficacy(
|
||||
damage_type=newer_type, target_type=type, damage_factor=200
|
||||
)
|
||||
double_damage_from_newer_type_relation.save()
|
||||
|
||||
# past type relations
|
||||
|
||||
# type used to deal half damage rather than no damage
|
||||
past_no_damage_to_relation = TypeEfficacyPast(
|
||||
damage_type=type,
|
||||
target_type=no_damage_to,
|
||||
damage_factor=50,
|
||||
generation=generation,
|
||||
)
|
||||
past_no_damage_to_relation.save()
|
||||
|
||||
response = self.client.get("{}/type/{}/".format(API_V2, type.pk))
|
||||
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
|
@ -3552,6 +3586,75 @@ class APITests(APIData, APITestCase):
|
|||
response.data["damage_relations"]["double_damage_from"][0]["url"],
|
||||
"{}{}/type/{}/".format(TEST_HOST, API_V2, double_damage_from.pk),
|
||||
)
|
||||
|
||||
# past damage relations params
|
||||
|
||||
# generation
|
||||
past_damage_relations = response.data["past_damage_relations"]
|
||||
gen_data = past_damage_relations[0]["generation"]
|
||||
self.assertEqual(gen_data["name"], generation.name)
|
||||
self.assertEqual(
|
||||
gen_data["url"],
|
||||
"{}{}/generation/{}/".format(
|
||||
TEST_HOST, API_V2, past_no_damage_to_relation.generation.pk
|
||||
),
|
||||
)
|
||||
|
||||
# relations
|
||||
gen_relations = past_damage_relations[0]["damage_relations"]
|
||||
|
||||
# type that currently receives no damage used to receive half damage, so is no longer in
|
||||
# this list...
|
||||
self.assertEqual(len(gen_relations["no_damage_to"]), 0)
|
||||
|
||||
self.assertEqual(
|
||||
gen_relations["half_damage_to"][0]["name"], half_damage_to.name
|
||||
)
|
||||
self.assertEqual(
|
||||
gen_relations["half_damage_to"][0]["url"],
|
||||
"{}{}/type/{}/".format(TEST_HOST, API_V2, half_damage_to.pk),
|
||||
)
|
||||
|
||||
# ...it's in this list instead
|
||||
self.assertEqual(gen_relations["half_damage_to"][1]["name"], no_damage_to.name)
|
||||
self.assertEqual(
|
||||
gen_relations["half_damage_to"][1]["url"],
|
||||
"{}{}/type/{}/".format(TEST_HOST, API_V2, no_damage_to.pk),
|
||||
)
|
||||
|
||||
self.assertEqual(
|
||||
gen_relations["double_damage_to"][0]["name"], double_damage_to.name
|
||||
)
|
||||
self.assertEqual(
|
||||
gen_relations["double_damage_to"][0]["url"],
|
||||
"{}{}/type/{}/".format(TEST_HOST, API_V2, double_damage_to.pk),
|
||||
)
|
||||
self.assertEqual(
|
||||
gen_relations["no_damage_from"][0]["name"], no_damage_from.name
|
||||
)
|
||||
self.assertEqual(
|
||||
gen_relations["no_damage_from"][0]["url"],
|
||||
"{}{}/type/{}/".format(TEST_HOST, API_V2, no_damage_from.pk),
|
||||
)
|
||||
self.assertEqual(
|
||||
gen_relations["half_damage_from"][0]["name"], half_damage_from.name
|
||||
)
|
||||
self.assertEqual(
|
||||
gen_relations["half_damage_from"][0]["url"],
|
||||
"{}{}/type/{}/".format(TEST_HOST, API_V2, half_damage_from.pk),
|
||||
)
|
||||
self.assertEqual(
|
||||
gen_relations["double_damage_from"][0]["name"], double_damage_from.name
|
||||
)
|
||||
self.assertEqual(
|
||||
gen_relations["double_damage_from"][0]["url"],
|
||||
"{}{}/type/{}/".format(TEST_HOST, API_V2, double_damage_from.pk),
|
||||
)
|
||||
|
||||
# second double-damage-from type is absent because it's from a newer generation than the
|
||||
# generation of this set of relations
|
||||
self.assertEqual(len(gen_relations["double_damage_from"]), 1)
|
||||
|
||||
# game indices params
|
||||
self.assertEqual(
|
||||
response.data["game_indices"][0]["game_index"], type_game_index.game_index
|
||||
|
|
Loading…
Add table
Reference in a new issue