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