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