Marked sprite forms with what version group introduced them.
[zzz-pokedex.git] / pokedex / db / tables.py
1 # encoding: utf8
2
3 from sqlalchemy import Column, ForeignKey, MetaData, Table
4 from sqlalchemy.ext.declarative import declarative_base
5 from sqlalchemy.ext.associationproxy import association_proxy
6 from sqlalchemy.orm import backref, relation
7 from sqlalchemy.types import *
8 from sqlalchemy.databases.mysql import *
9
10 from pokedex.db import rst
11
12 metadata = MetaData()
13 TableBase = declarative_base(metadata=metadata)
14
15 class Ability(TableBase):
16 __tablename__ = 'abilities'
17 __singlename__ = 'ability'
18 id = Column(Integer, primary_key=True, nullable=False)
19 name = Column(Unicode(24), nullable=False)
20 flavor_text = Column(Unicode(64), nullable=False)
21 effect = Column(Unicode(255), nullable=False)
22
23 class ContestEffect(TableBase):
24 __tablename__ = 'contest_effects'
25 id = Column(Integer, primary_key=True, nullable=False)
26 appeal = Column(SmallInteger, nullable=False)
27 jam = Column(SmallInteger, nullable=False)
28 flavor_text = Column(Unicode(64), nullable=False)
29 effect = Column(Unicode(255), nullable=False)
30
31 class EggGroup(TableBase):
32 __tablename__ = 'egg_groups'
33 id = Column(Integer, primary_key=True, nullable=False)
34 name = Column(Unicode(16), nullable=False)
35
36 class Encounter(TableBase):
37 """Rows in this table represent encounters with wild Pokémon.
38
39 Within a given area in a given game, encounters are differentiated by the
40 slot they are in and a world condition.
41
42 Groups of slots belong to encounter types; these are what the player is
43 doing to get an encounter, such as surfing or walking through tall grass.
44
45 Within an encounter type, slots are defined primarily by rarity. Each slot
46 can also be affected by a world condition; for example, the 20% slot for
47 walking in tall grass is affected by whether a swarm is in effect in the
48 areas. "There is a swarm" and "there is not a swarm" are conditions, and
49 together they make a condition group. However, since "not a swarm" is a
50 base state rather than any sort of new state, it is omitted and instead
51 referred to by a NULL.
52
53 A slot (20% walking in grass) and single world condition (NULL, i.e. no
54 swarm) are thus enough to define a specific encounter.
55
56 Well, okay, almost: each slot actually appears twice.
57 """
58
59 __tablename__ = 'encounters'
60 id = Column(Integer, primary_key=True, nullable=False)
61 version_id = Column(Integer, ForeignKey('versions.id'), nullable=False, autoincrement=False)
62 location_area_id = Column(Integer, ForeignKey('location_areas.id'), nullable=False, autoincrement=False)
63 encounter_type_slot_id = Column(Integer, ForeignKey('encounter_type_slots.id'), nullable=False, autoincrement=False)
64 encounter_condition_id = Column(Integer, ForeignKey('encounter_conditions.id'), nullable=True, autoincrement=False)
65 pokemon_id = Column(Integer, ForeignKey('pokemon.id'), nullable=False, autoincrement=False)
66 min_level = Column(Integer, nullable=False, autoincrement=False)
67 max_level = Column(Integer, nullable=False, autoincrement=False)
68
69 class EncounterCondition(TableBase):
70 """Rows in this table represent something different about the world that
71 can affect what Pokémon are encountered.
72 """
73
74 __tablename__ = 'encounter_conditions'
75 id = Column(Integer, primary_key=True, nullable=False)
76 encounter_condition_group_id = Column(Integer, ForeignKey('encounter_condition_groups.id'), primary_key=False, nullable=False, autoincrement=False)
77 name = Column(Unicode(64), nullable=False)
78
79 class EncounterConditionGroup(TableBase):
80 """Rows in this table represent a group of mutually exclusive conditions,
81 such as morning/day/night. "Conditions" that are part of the default state
82 of the world, such as "not during a swarm" or "not using the PokéRadar",
83 are not included in this table and are referred to by NULLs in other
84 tables.
85 """
86
87 __tablename__ = 'encounter_condition_groups'
88 id = Column(Integer, primary_key=True, nullable=False)
89 name = Column(Unicode(64), nullable=False)
90
91 class EncounterType(TableBase):
92 """Rows in this table represent ways the player can enter a wild encounter;
93 i.e. surfing, fishing, or walking through tall grass.
94 """
95
96 __tablename__ = 'encounter_types'
97 id = Column(Integer, primary_key=True, nullable=False)
98 name = Column(Unicode(64), nullable=False)
99
100 class EncounterTypeSlot(TableBase):
101 """Rows in this table represent an abstract "slot" within an encounter
102 type, associated with both a condition group and a rarity.
103
104 Note that there are two encounters per slot, so the rarities will only add
105 up to 50.
106 """
107
108 __tablename__ = 'encounter_type_slots'
109 id = Column(Integer, primary_key=True, nullable=False)
110 encounter_type_id = Column(Integer, ForeignKey('encounter_types.id'), primary_key=False, nullable=False, autoincrement=False)
111 encounter_condition_group_id = Column(Integer, ForeignKey('encounter_condition_groups.id'), primary_key=False, nullable=True, autoincrement=False)
112 rarity = Column(Integer, nullable=False, autoincrement=False)
113
114 class EvolutionChain(TableBase):
115 __tablename__ = 'evolution_chains'
116 id = Column(Integer, primary_key=True, nullable=False)
117 growth_rate_id = Column(Integer, ForeignKey('growth_rates.id'), nullable=False)
118 steps_to_hatch = Column(Integer, nullable=False)
119 baby_trigger_item = Column(Unicode(12))
120
121 class EvolutionMethod(TableBase):
122 __tablename__ = 'evolution_methods'
123 id = Column(Integer, primary_key=True, nullable=False)
124 name = Column(Unicode(64), nullable=False)
125 description = Column(Unicode(255), nullable=False)
126
127 class Generation(TableBase):
128 __tablename__ = 'generations'
129 id = Column(Integer, primary_key=True, nullable=False)
130 name = Column(Unicode(16), nullable=False)
131 main_region = Column(Unicode(16), nullable=False)
132
133 class GrowthRate(TableBase):
134 """`formula` is written in LaTeX math notation."""
135 __tablename__ = 'growth_rates'
136 id = Column(Integer, primary_key=True, nullable=False)
137 name = Column(Unicode(20), nullable=False)
138 formula = Column(Unicode(500), nullable=False)
139
140 class Item(TableBase):
141 __tablename__ = 'items'
142 __singlename__ = 'item'
143 id = Column(Integer, primary_key=True, nullable=False)
144 name = Column(Unicode(16), nullable=False)
145
146 class Language(TableBase):
147 __tablename__ = 'languages'
148 id = Column(Integer, primary_key=True, nullable=False)
149 name = Column(Unicode(16), nullable=False)
150
151 class Location(TableBase):
152 __tablename__ = 'locations'
153 __singlename__ = 'location'
154 id = Column(Integer, primary_key=True, nullable=False)
155 generation_id = Column(Integer, ForeignKey('generations.id'), nullable=False)
156 name = Column(Unicode(64), nullable=False)
157
158 class LocationArea(TableBase):
159 __tablename__ = 'location_areas'
160 id = Column(Integer, primary_key=True, nullable=False)
161 location_id = Column(Integer, ForeignKey('locations.id'), nullable=False)
162 internal_id = Column(Integer, nullable=False)
163 name = Column(Unicode(64), nullable=True)
164
165 class LocationAreaEncounterRate(TableBase):
166 __tablename__ = 'location_area_encounter_rates'
167 location_area_id = Column(Integer, ForeignKey('location_areas.id'), primary_key=True, nullable=False, autoincrement=False)
168 encounter_type_id = Column(Integer, ForeignKey('encounter_types.id'), primary_key=True, nullable=False, autoincrement=False)
169 rate = Column(Integer, nullable=True)
170
171 class Machine(TableBase):
172 __tablename__ = 'machines'
173 machine_number = Column(Integer, primary_key=True, nullable=False, autoincrement=False)
174 generation_id = Column(Integer, ForeignKey('generations.id'), primary_key=True, nullable=False, autoincrement=False)
175 move_id = Column(Integer, ForeignKey('moves.id'), nullable=False)
176
177 class MoveDamageClass(TableBase):
178 __tablename__ = 'move_damage_classes'
179 id = Column(Integer, primary_key=True, nullable=False)
180 name = Column(Unicode(8), nullable=False)
181 description = Column(Unicode(64), nullable=False)
182
183 class MoveEffect(TableBase):
184 __tablename__ = 'move_effects'
185 id = Column(Integer, primary_key=True, nullable=False)
186 priority = Column(SmallInteger, nullable=False)
187 short_effect = Column(Unicode(256), nullable=False)
188 effect = Column(Unicode(5120), nullable=False)
189
190 class MoveFlag(TableBase):
191 __tablename__ = 'move_flags'
192 move_id = Column(Integer, ForeignKey('moves.id'), primary_key=True, nullable=False, autoincrement=False)
193 move_flag_type_id = Column(Integer, ForeignKey('move_flag_types.id'), primary_key=True, nullable=False, autoincrement=False)
194
195 class MoveFlagType(TableBase):
196 __tablename__ = 'move_flag_types'
197 id = Column(Integer, primary_key=True, nullable=False)
198 name = Column(Unicode(32), nullable=False)
199 description = Column(rst.RstTextColumn(128), nullable=False)
200
201 class MoveFlavorText(TableBase):
202 __tablename__ = 'move_flavor_text'
203 move_id = Column(Integer, ForeignKey('moves.id'), primary_key=True, nullable=False, autoincrement=False)
204 generation_id = Column(Integer, ForeignKey('generations.id'), primary_key=True, nullable=False, autoincrement=False)
205 flavor_text = Column(Unicode(255), nullable=False)
206
207 class MoveName(TableBase):
208 __tablename__ = 'move_names'
209 move_id = Column(Integer, ForeignKey('moves.id'), primary_key=True, nullable=False, autoincrement=False)
210 language_id = Column(Integer, ForeignKey('languages.id'), primary_key=True, nullable=False, autoincrement=False)
211 name = Column(Unicode(16), nullable=False)
212
213 class MoveTarget(TableBase):
214 __tablename__ = 'move_targets'
215 id = Column(Integer, primary_key=True, nullable=False)
216 name = Column(Unicode(32), nullable=False)
217 description = Column(Unicode(128), nullable=False)
218
219 class Move(TableBase):
220 __tablename__ = 'moves'
221 __singlename__ = 'move'
222 id = Column(Integer, primary_key=True, nullable=False)
223 name = Column(Unicode(12), nullable=False)
224 generation_id = Column(Integer, ForeignKey('generations.id'), nullable=False)
225 type_id = Column(Integer, ForeignKey('types.id'), nullable=False)
226 power = Column(SmallInteger)
227 pp = Column(SmallInteger, nullable=False)
228 accuracy = Column(SmallInteger)
229 target_id = Column(Integer, ForeignKey('move_targets.id'), nullable=False)
230 damage_class_id = Column(Integer, ForeignKey('move_damage_classes.id'), nullable=False)
231 effect_id = Column(Integer, ForeignKey('move_effects.id'), nullable=False)
232 effect_chance = Column(Integer)
233 contest_type = Column(Unicode(8), nullable=False)
234 contest_effect_id = Column(Integer, ForeignKey('contest_effects.id'), nullable=True)
235 super_contest_effect_id = Column(Integer, ForeignKey('super_contest_effects.id'), nullable=False)
236
237 class Pokemon(TableBase):
238 """The core to this whole mess.
239
240 Note that I use both 'forme' and 'form' in both code and the database. I
241 only use 'forme' when specifically referring to Pokémon that have multiple
242 distinct species as forms—i.e., different stats or movesets. 'Form' is a
243 more general term referring to any variation within a species, including
244 purely cosmetic forms like Unown.
245 """
246 __tablename__ = 'pokemon'
247 __singlename__ = 'pokemon'
248 id = Column(Integer, primary_key=True, nullable=False)
249 name = Column(Unicode(20), nullable=False)
250 forme_name = Column(Unicode(16))
251 forme_base_pokemon_id = Column(Integer, ForeignKey('pokemon.id'))
252 generation_id = Column(Integer, ForeignKey('generations.id'))
253 evolution_chain_id = Column(Integer, ForeignKey('evolution_chains.id'))
254 evolution_parent_pokemon_id = Column(Integer, ForeignKey('pokemon.id'))
255 evolution_method_id = Column(Integer, ForeignKey('evolution_methods.id'))
256 evolution_parameter = Column(Unicode(32))
257 height = Column(Integer, nullable=False)
258 weight = Column(Integer, nullable=False)
259 species = Column(Unicode(16), nullable=False)
260 color = Column(Unicode(6), nullable=False)
261 pokemon_shape_id = Column(Integer, ForeignKey('pokemon_shapes.id'), nullable=False)
262 habitat = Column(Unicode(16), nullable=False)
263 gender_rate = Column(Integer, nullable=False)
264 capture_rate = Column(Integer, nullable=False)
265 base_experience = Column(Integer, nullable=False)
266 base_happiness = Column(Integer, nullable=False)
267 gen1_internal_id = Column(Integer)
268 is_baby = Column(Boolean, nullable=False)
269 has_gen4_fem_sprite = Column(Boolean, nullable=False)
270 has_gen4_fem_back_sprite = Column(Boolean, nullable=False)
271
272 ### Stuff to handle alternate Pokémon forms
273
274 @property
275 def national_id(self):
276 """Returns the National Pokédex number for this Pokémon. Use this
277 instead of the id directly; alternate formes may make the id incorrect.
278 """
279
280 if self.forme_base_pokemon_id:
281 return self.forme_base_pokemon_id
282 return self.id
283
284 @property
285 def full_name(self):
286 """Returns the name of this Pokémon, including its Forme, if any."""
287
288 if self.forme_name:
289 return "%s %s" % (self.forme_name.capitalize(), self.name)
290 return self.name
291
292 @property
293 def normal_form(self):
294 """Returns the normal form for this Pokémon; i.e., this will return
295 regular Deoxys when called on any Deoxys form.
296 """
297
298 if self.forme_base_pokemon:
299 return self.forme_base_pokemon
300
301 return self
302
303 class PokemonAbility(TableBase):
304 __tablename__ = 'pokemon_abilities'
305 pokemon_id = Column(Integer, ForeignKey('pokemon.id'), primary_key=True, nullable=False, autoincrement=False)
306 ability_id = Column(Integer, ForeignKey('abilities.id'), nullable=False)
307 slot = Column(Integer, primary_key=True, nullable=False, autoincrement=False)
308
309 class PokemonDexNumber(TableBase):
310 __tablename__ = 'pokemon_dex_numbers'
311 pokemon_id = Column(Integer, ForeignKey('pokemon.id'), primary_key=True, nullable=False, autoincrement=False)
312 generation_id = Column(Integer, ForeignKey('generations.id'), primary_key=True, nullable=False, autoincrement=False)
313 pokedex_number = Column(Integer, nullable=False)
314
315 class PokemonEggGroup(TableBase):
316 __tablename__ = 'pokemon_egg_groups'
317 pokemon_id = Column(Integer, ForeignKey('pokemon.id'), primary_key=True, nullable=False, autoincrement=False)
318 egg_group_id = Column(Integer, ForeignKey('egg_groups.id'), primary_key=True, nullable=False, autoincrement=False)
319
320 class PokemonFlavorText(TableBase):
321 __tablename__ = 'pokemon_flavor_text'
322 pokemon_id = Column(Integer, ForeignKey('pokemon.id'), primary_key=True, nullable=False, autoincrement=False)
323 version_id = Column(Integer, ForeignKey('versions.id'), primary_key=True, nullable=False, autoincrement=False)
324 flavor_text = Column(Unicode(255), nullable=False)
325
326 class PokemonFormGroup(TableBase):
327 __tablename__ = 'pokemon_form_groups'
328 pokemon_id = Column(Integer, ForeignKey('pokemon.id'), primary_key=True, nullable=False, autoincrement=False)
329 description = Column(Unicode(512), nullable=False)
330
331 class PokemonFormSprite(TableBase):
332 __tablename__ = 'pokemon_form_sprites'
333 id = Column(Integer, primary_key=True, nullable=False)
334 pokemon_id = Column(Integer, ForeignKey('pokemon.id'), primary_key=True, nullable=False, autoincrement=False)
335 introduced_in_version_group_id = Column(Integer, ForeignKey('version_groups.id'), primary_key=True, nullable=False, autoincrement=False)
336 name = Column(Unicode(16), nullable=True)
337
338 class PokemonItem(TableBase):
339 __tablename__ = 'pokemon_items'
340 pokemon_id = Column(Integer, ForeignKey('pokemon.id'), primary_key=True, nullable=False, autoincrement=False)
341 version_id = Column(Integer, ForeignKey('versions.id'), primary_key=True, nullable=False, autoincrement=False)
342 item_id = Column(Integer, ForeignKey('items.id'), primary_key=True, nullable=False, autoincrement=False)
343 rarity = Column(Integer, nullable=False)
344
345 class PokemonMove(TableBase):
346 __tablename__ = 'pokemon_moves'
347 pokemon_id = Column(Integer, ForeignKey('pokemon.id'), primary_key=True, nullable=False, autoincrement=False)
348 version_group_id = Column(Integer, ForeignKey('version_groups.id'), primary_key=True, nullable=False, autoincrement=False)
349 move_id = Column(Integer, ForeignKey('moves.id'), primary_key=True, nullable=False, autoincrement=False, index=True)
350 pokemon_move_method_id = Column(Integer, ForeignKey('pokemon_move_methods.id'), primary_key=True, nullable=False, autoincrement=False)
351 level = Column(Integer, primary_key=True, nullable=True, autoincrement=False)
352 order = Column(Integer, nullable=True)
353
354 class PokemonMoveMethod(TableBase):
355 __tablename__ = 'pokemon_move_methods'
356 id = Column(Integer, primary_key=True, nullable=False, autoincrement=False)
357 name = Column(Unicode(64), nullable=False)
358 description = Column(Unicode(255), nullable=False)
359
360 class PokemonName(TableBase):
361 __tablename__ = 'pokemon_names'
362 pokemon_id = Column(Integer, ForeignKey('pokemon.id'), primary_key=True, nullable=False, autoincrement=False)
363 language_id = Column(Integer, ForeignKey('languages.id'), primary_key=True, nullable=False, autoincrement=False)
364 name = Column(Unicode(16), nullable=False)
365
366 class PokemonShape(TableBase):
367 __tablename__ = 'pokemon_shapes'
368 id = Column(Integer, primary_key=True, nullable=False)
369 name = Column(Unicode(24), nullable=False)
370 awesome_name = Column(Unicode(16), nullable=False)
371
372 class PokemonStat(TableBase):
373 __tablename__ = 'pokemon_stats'
374 pokemon_id = Column(Integer, ForeignKey('pokemon.id'), primary_key=True, nullable=False, autoincrement=False)
375 stat_id = Column(Integer, ForeignKey('stats.id'), primary_key=True, nullable=False, autoincrement=False)
376 base_stat = Column(Integer, nullable=False)
377 effort = Column(Integer, nullable=False)
378
379 class PokemonType(TableBase):
380 __tablename__ = 'pokemon_types'
381 pokemon_id = Column(Integer, ForeignKey('pokemon.id'), primary_key=True, nullable=False, autoincrement=False)
382 type_id = Column(Integer, ForeignKey('types.id'), nullable=False)
383 slot = Column(Integer, primary_key=True, nullable=False, autoincrement=False)
384
385 class Stat(TableBase):
386 __tablename__ = 'stats'
387 id = Column(Integer, primary_key=True, nullable=False)
388 name = Column(Unicode(16), nullable=False)
389
390 class SuperContestEffect(TableBase):
391 __tablename__ = 'super_contest_effects'
392 id = Column(Integer, primary_key=True, nullable=False)
393 appeal = Column(SmallInteger, nullable=False)
394 flavor_text = Column(Unicode(64), nullable=False)
395
396 class TypeEfficacy(TableBase):
397 __tablename__ = 'type_efficacy'
398 damage_type_id = Column(Integer, ForeignKey('types.id'), primary_key=True, nullable=False, autoincrement=False)
399 target_type_id = Column(Integer, ForeignKey('types.id'), primary_key=True, nullable=False, autoincrement=False)
400 damage_factor = Column(Integer, nullable=False)
401
402 class Type(TableBase):
403 __tablename__ = 'types'
404 __singlename__ = 'type'
405 id = Column(Integer, primary_key=True, nullable=False)
406 name = Column(Unicode(8), nullable=False)
407 abbreviation = Column(Unicode(3), nullable=False)
408
409 class VersionGroup(TableBase):
410 __tablename__ = 'version_groups'
411 id = Column(Integer, primary_key=True, nullable=False)
412 generation_id = Column(Integer, ForeignKey('generations.id'), nullable=False)
413
414 class Version(TableBase):
415 __tablename__ = 'versions'
416 id = Column(Integer, primary_key=True, nullable=False)
417 version_group_id = Column(Integer, ForeignKey('version_groups.id'), nullable=False)
418 name = Column(Unicode(32), nullable=False)
419
420
421 ### Relations down here, to avoid ordering problems
422 Encounter.pokemon = relation(Pokemon, backref='encounters')
423 Encounter.version = relation(Version, backref='encounters')
424 Encounter.location_area = relation(LocationArea, backref='encounters')
425 Encounter.slot = relation(EncounterTypeSlot, backref='encounters')
426 Encounter.condition = relation(EncounterCondition, backref='encounters')
427
428 EncounterCondition.group = relation(EncounterConditionGroup,
429 backref='conditions')
430
431 EncounterTypeSlot.type = relation(EncounterType, backref='slots')
432
433 EvolutionChain.growth_rate = relation(GrowthRate, backref='evolution_chains')
434
435 Generation.versions = relation(Version, secondary=VersionGroup.__table__)
436
437 LocationArea.location = relation(Location, backref='areas')
438
439 Machine.generation = relation(Generation)
440
441 Move.contest_effect = relation(ContestEffect, backref='moves')
442 Move.damage_class = relation(MoveDamageClass, backref='moves')
443 Move.flags = association_proxy('move_flags', 'flag')
444 Move.flavor_text = relation(MoveFlavorText, order_by=MoveFlavorText.generation_id, backref='move')
445 Move.foreign_names = relation(MoveName, backref='pokemon')
446 Move.generation = relation(Generation, backref='moves')
447 Move.machines = relation(Machine, backref='move')
448 Move.move_effect = relation(MoveEffect, backref='moves')
449 Move.move_flags = relation(MoveFlag, backref='move')
450 Move.super_contest_effect = relation(SuperContestEffect, backref='moves')
451 Move.target = relation(MoveTarget, backref='moves')
452 Move.type = relation(Type, backref='moves')
453
454 Move.effect = rst.MoveEffectProperty('effect')
455 Move.priority = association_proxy('move_effect', 'priority')
456 Move.short_effect = rst.MoveEffectProperty('short_effect')
457
458 MoveFlag.flag = relation(MoveFlagType)
459
460 MoveFlavorText.generation = relation(Generation)
461
462 MoveName.language = relation(Language)
463
464 Pokemon.abilities = relation(Ability, secondary=PokemonAbility.__table__,
465 order_by=PokemonAbility.slot,
466 backref='pokemon')
467 Pokemon.formes = relation(Pokemon, primaryjoin=Pokemon.id==Pokemon.forme_base_pokemon_id,
468 backref=backref('forme_base_pokemon',
469 remote_side=[Pokemon.id]))
470 Pokemon.dex_numbers = relation(PokemonDexNumber, backref='pokemon')
471 Pokemon.egg_groups = relation(EggGroup, secondary=PokemonEggGroup.__table__,
472 order_by=PokemonEggGroup.egg_group_id,
473 backref='pokemon')
474 Pokemon.evolution_chain = relation(EvolutionChain, backref='pokemon')
475 Pokemon.evolution_method = relation(EvolutionMethod)
476 Pokemon.evolution_children = relation(Pokemon, primaryjoin=Pokemon.id==Pokemon.evolution_parent_pokemon_id,
477 backref=backref('evolution_parent',
478 remote_side=[Pokemon.id]))
479 Pokemon.flavor_text = relation(PokemonFlavorText, order_by=PokemonFlavorText.pokemon_id, backref='pokemon')
480 Pokemon.foreign_names = relation(PokemonName, backref='pokemon')
481 Pokemon.items = relation(PokemonItem)
482 Pokemon.generation = relation(Generation, backref='pokemon')
483 Pokemon.shape = relation(PokemonShape, backref='pokemon')
484 Pokemon.stats = relation(PokemonStat, backref='pokemon')
485 Pokemon.types = relation(Type, secondary=PokemonType.__table__)
486
487 PokemonDexNumber.generation = relation(Generation)
488
489 PokemonFlavorText.version = relation(Version)
490
491 PokemonItem.item = relation(Item, backref='pokemon')
492 PokemonItem.version = relation(Version)
493
494 PokemonFormGroup.pokemon = relation(Pokemon, backref=backref('form_group',
495 uselist=False))
496 PokemonFormSprite.pokemon = relation(Pokemon, backref='form_sprites')
497 PokemonFormSprite.introduced_in = relation(VersionGroup)
498
499 PokemonMove.pokemon = relation(Pokemon, backref='pokemon_moves')
500 PokemonMove.version_group = relation(VersionGroup)
501 PokemonMove.move = relation(Move, backref='pokemon_moves')
502 PokemonMove.method = relation(PokemonMoveMethod)
503
504 PokemonName.language = relation(Language)
505
506 PokemonStat.stat = relation(Stat)
507
508 Type.damage_efficacies = relation(TypeEfficacy,
509 primaryjoin=Type.id
510 ==TypeEfficacy.damage_type_id,
511 backref='damage_type')
512 Type.target_efficacies = relation(TypeEfficacy,
513 primaryjoin=Type.id
514 ==TypeEfficacy.target_type_id,
515 backref='target_type')
516
517 Version.version_group = relation(VersionGroup, backref='versions')
518 Version.generation = association_proxy('version_group', 'generation')
519
520 VersionGroup.generation = relation(Generation, backref='version_groups')