Link move flavour text to version groups. #169
[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, eagerload_all, relation
7 from sqlalchemy.orm.session import Session
8 from sqlalchemy.sql import and_
9 from sqlalchemy.types 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 generation_id = Column(Integer, ForeignKey('generations.id'), nullable=False)
22 effect = Column(rst.RstTextColumn(5120), nullable=False)
23 short_effect = Column(rst.RstTextColumn(255), nullable=False)
24
25 class AbilityFlavorText(TableBase):
26 __tablename__ = 'ability_flavor_text'
27 ability_id = Column(Integer, ForeignKey('abilities.id'), primary_key=True, nullable=False, autoincrement=False)
28 version_group_id = Column(Integer, ForeignKey('version_groups.id'), primary_key=True, nullable=False, autoincrement=False)
29 flavor_text = Column(Unicode(64), nullable=False)
30
31 class Berry(TableBase):
32 __tablename__ = 'berries'
33 id = Column(Integer, primary_key=True, nullable=False)
34 item_id = Column(Integer, ForeignKey('items.id'), nullable=False)
35 firmness_id = Column(Integer, ForeignKey('berry_firmness.id'), nullable=False)
36 natural_gift_power = Column(Integer, nullable=True)
37 natural_gift_type_id = Column(Integer, ForeignKey('types.id'), nullable=True)
38 size = Column(Integer, nullable=False)
39 max_harvest = Column(Integer, nullable=False)
40 growth_time = Column(Integer, nullable=False)
41 soil_dryness = Column(Integer, nullable=False)
42 smoothness = Column(Integer, nullable=False)
43
44 class BerryFirmness(TableBase):
45 __tablename__ = 'berry_firmness'
46 id = Column(Integer, primary_key=True, nullable=False)
47 name = Column(Unicode(10), nullable=False)
48
49 class BerryFlavor(TableBase):
50 __tablename__ = 'berry_flavors'
51 berry_id = Column(Integer, ForeignKey('berries.id'), primary_key=True, nullable=False, autoincrement=False)
52 contest_type_id = Column(Integer, ForeignKey('contest_types.id'), primary_key=True, nullable=False, autoincrement=False)
53 flavor = Column(Integer, nullable=False)
54
55 class ContestCombo(TableBase):
56 __tablename__ = 'contest_combos'
57 first_move_id = Column(Integer, ForeignKey('moves.id'), primary_key=True, nullable=False, autoincrement=False)
58 second_move_id = Column(Integer, ForeignKey('moves.id'), primary_key=True, nullable=False, autoincrement=False)
59
60 class ContestEffect(TableBase):
61 __tablename__ = 'contest_effects'
62 id = Column(Integer, primary_key=True, nullable=False)
63 appeal = Column(SmallInteger, nullable=False)
64 jam = Column(SmallInteger, nullable=False)
65 flavor_text = Column(Unicode(64), nullable=False)
66 effect = Column(Unicode(255), nullable=False)
67
68 class ContestType(TableBase):
69 __tablename__ = 'contest_types'
70 id = Column(Integer, primary_key=True, nullable=False)
71 name = Column(Unicode(6), nullable=False)
72 flavor = Column(Unicode(6), nullable=False)
73 color = Column(Unicode(6), nullable=False)
74
75 class EggGroup(TableBase):
76 __tablename__ = 'egg_groups'
77 id = Column(Integer, primary_key=True, nullable=False)
78 name = Column(Unicode(16), nullable=False)
79
80 class Encounter(TableBase):
81 """Rows in this table represent encounters with wild Pokémon. Bear with
82 me, here.
83
84 Within a given area in a given game, encounters are differentiated by the
85 "slot" they are in and the state of the game world.
86
87 What the player is doing to get an encounter, such as surfing or walking
88 through tall grass, is called terrain. Each terrain has its own set of
89 encounter slots.
90
91 Within a terrain, slots are defined primarily by rarity. Each slot can
92 also be affected by world conditions; for example, the 20% slot for walking
93 in tall grass is affected by whether a swarm is in effect in that area.
94 "Is there a swarm?" is a condition; "there is a swarm" and "there is not a
95 swarm" are the possible values of this condition.
96
97 A slot (20% walking in grass) and any appropriate world conditions (no
98 swarm) are thus enough to define a specific encounter.
99
100 Well, okay, almost: each slot actually appears twice.
101 """
102
103 __tablename__ = 'encounters'
104 id = Column(Integer, primary_key=True, nullable=False)
105 version_id = Column(Integer, ForeignKey('versions.id'), nullable=False, autoincrement=False)
106 location_area_id = Column(Integer, ForeignKey('location_areas.id'), nullable=False, autoincrement=False)
107 encounter_slot_id = Column(Integer, ForeignKey('encounter_slots.id'), nullable=False, autoincrement=False)
108 pokemon_id = Column(Integer, ForeignKey('pokemon.id'), nullable=False, autoincrement=False)
109 min_level = Column(Integer, nullable=False, autoincrement=False)
110 max_level = Column(Integer, nullable=False, autoincrement=False)
111
112 class EncounterCondition(TableBase):
113 """Rows in this table represent varying conditions in the game world, such
114 as time of day.
115 """
116
117 __tablename__ = 'encounter_conditions'
118 id = Column(Integer, primary_key=True, nullable=False)
119 name = Column(Unicode(64), nullable=False)
120
121 class EncounterConditionValue(TableBase):
122 """Rows in this table represent possible states for a condition; for
123 example, the state of 'swarm' could be 'swarm' or 'no swarm'.
124 """
125
126 __tablename__ = 'encounter_condition_values'
127 id = Column(Integer, primary_key=True, nullable=False)
128 encounter_condition_id = Column(Integer, ForeignKey('encounter_conditions.id'), primary_key=False, nullable=False, autoincrement=False)
129 name = Column(Unicode(64), nullable=False)
130 is_default = Column(Boolean, nullable=False)
131
132 class EncounterConditionValueMap(TableBase):
133 """Maps encounters to the specific conditions under which they occur."""
134
135 __tablename__ = 'encounter_condition_value_map'
136 encounter_id = Column(Integer, ForeignKey('encounters.id'), primary_key=True, nullable=False, autoincrement=False)
137 encounter_condition_value_id = Column(Integer, ForeignKey('encounter_condition_values.id'), primary_key=True, nullable=False, autoincrement=False)
138
139 class EncounterTerrain(TableBase):
140 """Rows in this table represent ways the player can enter a wild encounter,
141 e.g., surfing, fishing, or walking through tall grass.
142 """
143
144 __tablename__ = 'encounter_terrain'
145 id = Column(Integer, primary_key=True, nullable=False)
146 name = Column(Unicode(64), nullable=False)
147
148 class EncounterSlot(TableBase):
149 """Rows in this table represent an abstract "slot" within a terrain,
150 associated with both some set of conditions and a rarity.
151
152 Note that there are two encounters per slot, so the rarities will only add
153 up to 50.
154 """
155
156 __tablename__ = 'encounter_slots'
157 id = Column(Integer, primary_key=True, nullable=False)
158 version_group_id = Column(Integer, ForeignKey('version_groups.id'), nullable=False, autoincrement=False)
159 encounter_terrain_id = Column(Integer, ForeignKey('encounter_terrain.id'), primary_key=False, nullable=False, autoincrement=False)
160 slot = Column(Integer, nullable=True)
161 rarity = Column(Integer, nullable=False)
162
163 class EncounterSlotCondition(TableBase):
164 """Lists all conditions that affect each slot."""
165
166 __tablename__ = 'encounter_slot_conditions'
167 encounter_slot_id = Column(Integer, ForeignKey('encounter_slots.id'), primary_key=True, nullable=False, autoincrement=False)
168 encounter_condition_id = Column(Integer, ForeignKey('encounter_conditions.id'), primary_key=True, nullable=False, autoincrement=False)
169
170 class EvolutionChain(TableBase):
171 __tablename__ = 'evolution_chains'
172 id = Column(Integer, primary_key=True, nullable=False)
173 growth_rate_id = Column(Integer, ForeignKey('growth_rates.id'), nullable=False)
174 steps_to_hatch = Column(Integer, nullable=False)
175 baby_trigger_item = Column(Unicode(12))
176
177 class EvolutionMethod(TableBase):
178 __tablename__ = 'evolution_methods'
179 id = Column(Integer, primary_key=True, nullable=False)
180 name = Column(Unicode(64), nullable=False)
181 description = Column(Unicode(255), nullable=False)
182
183 class Experience(TableBase):
184 __tablename__ = 'experience'
185 growth_rate_id = Column(Integer, ForeignKey('growth_rates.id'), primary_key=True, nullable=False)
186 level = Column(Integer, primary_key=True, nullable=False, autoincrement=False)
187 experience = Column(Integer, nullable=False)
188
189 class Generation(TableBase):
190 __tablename__ = 'generations'
191 id = Column(Integer, primary_key=True, nullable=False)
192 main_region_id = Column(Integer, ForeignKey('regions.id'))
193 canonical_pokedex_id = Column(Integer, ForeignKey('pokedexes.id'))
194 name = Column(Unicode(16), nullable=False)
195
196 class GrowthRate(TableBase):
197 """`formula` is written in LaTeX math notation."""
198 __tablename__ = 'growth_rates'
199 id = Column(Integer, primary_key=True, nullable=False)
200 name = Column(Unicode(20), nullable=False)
201 formula = Column(Unicode(500), nullable=False)
202
203 class Item(TableBase):
204 __tablename__ = 'items'
205 __singlename__ = 'item'
206 id = Column(Integer, primary_key=True, nullable=False)
207 name = Column(Unicode(16), nullable=False)
208 category_id = Column(Integer, ForeignKey('item_categories.id'), nullable=False)
209 cost = Column(Integer, nullable=False)
210 fling_power = Column(Integer, nullable=True)
211 fling_effect_id = Column(Integer, ForeignKey('item_fling_effects.id'), nullable=True)
212 effect = Column(rst.RstTextColumn(5120), nullable=False)
213
214 @property
215 def appears_underground(self):
216 return any(flag.identifier == u'underground' for flag in self.flags)
217
218 class ItemCategory(TableBase):
219 __tablename__ = 'item_categories'
220 id = Column(Integer, primary_key=True, nullable=False)
221 pocket_id = Column(Integer, ForeignKey('item_pockets.id'), nullable=False)
222 name = Column(Unicode(16), nullable=False)
223
224 class ItemFlag(TableBase):
225 __tablename__ = 'item_flags'
226 id = Column(Integer, primary_key=True, nullable=False)
227 identifier = Column(Unicode(24), nullable=False)
228 name = Column(Unicode(64), nullable=False)
229
230 class ItemFlagMap(TableBase):
231 __tablename__ = 'item_flag_map'
232 item_id = Column(Integer, ForeignKey('items.id'), primary_key=True, autoincrement=False, nullable=False)
233 item_flag_id = Column(Integer, ForeignKey('item_flags.id'), primary_key=True, autoincrement=False, nullable=False)
234
235 class ItemFlavorText(TableBase):
236 __tablename__ = 'item_flavor_text'
237 item_id = Column(Integer, ForeignKey('items.id'), primary_key=True, autoincrement=False, nullable=False)
238 version_group_id = Column(Integer, ForeignKey('version_groups.id'), primary_key=True, autoincrement=False, nullable=False)
239 flavor_text = Column(Unicode(255), nullable=False)
240
241 class ItemFlingEffect(TableBase):
242 __tablename__ = 'item_fling_effects'
243 id = Column(Integer, primary_key=True, nullable=False)
244 effect = Column(Unicode(255), nullable=False)
245
246 class ItemInternalID(TableBase):
247 __tablename__ = 'item_internal_ids'
248 item_id = Column(Integer, ForeignKey('items.id'), primary_key=True, autoincrement=False, nullable=False)
249 generation_id = Column(Integer, ForeignKey('generations.id'), primary_key=True, autoincrement=False, nullable=False)
250 internal_id = Column(Integer, nullable=False)
251
252 class ItemPocket(TableBase):
253 __tablename__ = 'item_pockets'
254 id = Column(Integer, primary_key=True, nullable=False)
255 identifier = Column(Unicode(16), nullable=False)
256 name = Column(Unicode(16), nullable=False)
257
258 class Language(TableBase):
259 __tablename__ = 'languages'
260 id = Column(Integer, primary_key=True, nullable=False)
261 iso639 = Column(Unicode(2), nullable=False)
262 iso3166 = Column(Unicode(2), nullable=False)
263 name = Column(Unicode(16), nullable=False)
264
265 class Location(TableBase):
266 __tablename__ = 'locations'
267 __singlename__ = 'location'
268 id = Column(Integer, primary_key=True, nullable=False)
269 region_id = Column(Integer, ForeignKey('regions.id'))
270 name = Column(Unicode(64), nullable=False)
271
272 class LocationArea(TableBase):
273 __tablename__ = 'location_areas'
274 id = Column(Integer, primary_key=True, nullable=False)
275 location_id = Column(Integer, ForeignKey('locations.id'), nullable=False)
276 internal_id = Column(Integer, nullable=False)
277 name = Column(Unicode(64), nullable=True)
278
279 class LocationAreaEncounterRate(TableBase):
280 __tablename__ = 'location_area_encounter_rates'
281 location_area_id = Column(Integer, ForeignKey('location_areas.id'), primary_key=True, nullable=False, autoincrement=False)
282 encounter_terrain_id = Column(Integer, ForeignKey('encounter_terrain.id'), primary_key=True, nullable=False, autoincrement=False)
283 version_id = Column(Integer, ForeignKey('versions.id'), primary_key=True, autoincrement=False)
284 rate = Column(Integer, nullable=True)
285
286 class Machine(TableBase):
287 __tablename__ = 'machines'
288 machine_number = Column(Integer, primary_key=True, nullable=False, autoincrement=False)
289 version_group_id = Column(Integer, ForeignKey('version_groups.id'), primary_key=True, nullable=False, autoincrement=False)
290 item_id = Column(Integer, ForeignKey('items.id'), nullable=False)
291 move_id = Column(Integer, ForeignKey('moves.id'), nullable=False)
292
293 @property
294 def is_hm(self):
295 return self.machine_number >= 100
296
297 class MoveBattleStyle(TableBase):
298 __tablename__ = 'move_battle_styles'
299 id = Column(Integer, primary_key=True, nullable=False)
300 name = Column(Unicode(8), nullable=False)
301
302 class MoveEffectCategory(TableBase):
303 __tablename__ = 'move_effect_categories'
304 id = Column(Integer, primary_key=True, nullable=False)
305 name = Column(Unicode(64), nullable=False)
306 can_affect_user = Column(Boolean, nullable=False)
307
308 class MoveEffectCategoryMap(TableBase):
309 __tablename__ = 'move_effect_category_map'
310 move_effect_id = Column(Integer, ForeignKey('move_effects.id'), primary_key=True, nullable=False)
311 move_effect_category_id = Column(Integer, ForeignKey('move_effect_categories.id'), primary_key=True, nullable=False)
312 affects_user = Column(Boolean, primary_key=True, nullable=False)
313
314 class MoveDamageClass(TableBase):
315 __tablename__ = 'move_damage_classes'
316 id = Column(Integer, primary_key=True, nullable=False)
317 name = Column(Unicode(8), nullable=False)
318 description = Column(Unicode(64), nullable=False)
319
320 class MoveEffect(TableBase):
321 __tablename__ = 'move_effects'
322 id = Column(Integer, primary_key=True, nullable=False)
323 priority = Column(SmallInteger, nullable=False)
324 short_effect = Column(Unicode(256), nullable=False)
325 effect = Column(Unicode(5120), nullable=False)
326
327 class MoveFlag(TableBase):
328 __tablename__ = 'move_flags'
329 move_id = Column(Integer, ForeignKey('moves.id'), primary_key=True, nullable=False, autoincrement=False)
330 move_flag_type_id = Column(Integer, ForeignKey('move_flag_types.id'), primary_key=True, nullable=False, autoincrement=False)
331
332 class MoveFlagType(TableBase):
333 __tablename__ = 'move_flag_types'
334 id = Column(Integer, primary_key=True, nullable=False)
335 name = Column(Unicode(32), nullable=False)
336 description = Column(rst.RstTextColumn(128), nullable=False)
337
338 class MoveFlavorText(TableBase):
339 __tablename__ = 'move_flavor_text'
340 move_id = Column(Integer, ForeignKey('moves.id'), primary_key=True, nullable=False, autoincrement=False)
341 version_group_id = Column(Integer, ForeignKey('version_groups.id'), primary_key=True, nullable=False, autoincrement=False)
342 flavor_text = Column(Unicode(255), nullable=False)
343
344 class MoveName(TableBase):
345 __tablename__ = 'move_names'
346 move_id = Column(Integer, ForeignKey('moves.id'), primary_key=True, nullable=False, autoincrement=False)
347 language_id = Column(Integer, ForeignKey('languages.id'), primary_key=True, nullable=False, autoincrement=False)
348 name = Column(Unicode(16), nullable=False)
349
350 class MoveTarget(TableBase):
351 __tablename__ = 'move_targets'
352 id = Column(Integer, primary_key=True, nullable=False)
353 name = Column(Unicode(32), nullable=False)
354 description = Column(Unicode(128), nullable=False)
355
356 class Move(TableBase):
357 __tablename__ = 'moves'
358 __singlename__ = 'move'
359 id = Column(Integer, primary_key=True, nullable=False)
360 name = Column(Unicode(12), nullable=False)
361 generation_id = Column(Integer, ForeignKey('generations.id'), nullable=False)
362 type_id = Column(Integer, ForeignKey('types.id'), nullable=False)
363 power = Column(SmallInteger)
364 pp = Column(SmallInteger, nullable=False)
365 accuracy = Column(SmallInteger)
366 target_id = Column(Integer, ForeignKey('move_targets.id'), nullable=False)
367 damage_class_id = Column(Integer, ForeignKey('move_damage_classes.id'), nullable=False)
368 effect_id = Column(Integer, ForeignKey('move_effects.id'), nullable=False)
369 effect_chance = Column(Integer)
370 contest_type_id = Column(Integer, ForeignKey('contest_types.id'), nullable=True)
371 contest_effect_id = Column(Integer, ForeignKey('contest_effects.id'), nullable=True)
372 super_contest_effect_id = Column(Integer, ForeignKey('super_contest_effects.id'), nullable=False)
373
374 class Nature(TableBase):
375 __tablename__ = 'natures'
376 __singlename__ = 'nature'
377 id = Column(Integer, primary_key=True, nullable=False)
378 name = Column(Unicode(8), nullable=False)
379 decreased_stat_id = Column(Integer, ForeignKey('stats.id'), nullable=False)
380 increased_stat_id = Column(Integer, ForeignKey('stats.id'), nullable=False)
381 hates_flavor_id = Column(Integer, ForeignKey('contest_types.id'), nullable=False)
382 likes_flavor_id = Column(Integer, ForeignKey('contest_types.id'), nullable=False)
383
384 class NatureBattleStylePreference(TableBase):
385 __tablename__ = 'nature_battle_style_preferences'
386 nature_id = Column(Integer, ForeignKey('natures.id'), primary_key=True, nullable=False)
387 move_battle_style_id = Column(Integer, ForeignKey('move_battle_styles.id'), primary_key=True, nullable=False)
388 low_hp_preference = Column(Integer, nullable=False)
389 high_hp_preference = Column(Integer, nullable=False)
390
391 class NaturePokeathlonStat(TableBase):
392 __tablename__ = 'nature_pokeathlon_stats'
393 nature_id = Column(Integer, ForeignKey('natures.id'), primary_key=True, nullable=False)
394 pokeathlon_stat_id = Column(Integer, ForeignKey('pokeathlon_stats.id'), primary_key=True, nullable=False)
395 max_change = Column(Integer, nullable=False)
396
397 class PokeathlonStat(TableBase):
398 __tablename__ = 'pokeathlon_stats'
399 id = Column(Integer, primary_key=True, nullable=False)
400 name = Column(Unicode(8), nullable=False)
401
402 class Pokedex(TableBase):
403 __tablename__ = 'pokedexes'
404 id = Column(Integer, primary_key=True, nullable=False)
405 region_id = Column(Integer, ForeignKey('regions.id'), nullable=True)
406 name = Column(Unicode(16), nullable=False)
407 description = Column(Unicode(512))
408
409 class PokedexVersionGroup(TableBase):
410 __tablename__ = 'pokedex_version_groups'
411 pokedex_id = Column(Integer, ForeignKey('pokedexes.id'), primary_key=True, nullable=False, autoincrement=False)
412 version_group_id = Column(Integer, ForeignKey('version_groups.id'), primary_key=True, nullable=False, autoincrement=False)
413
414 class Pokemon(TableBase):
415 """The core to this whole mess.
416
417 Note that I use both 'forme' and 'form' in both code and the database. I
418 only use 'forme' when specifically referring to Pokémon that have multiple
419 distinct species as forms—i.e., different stats or movesets. 'Form' is a
420 more general term referring to any variation within a species, including
421 purely cosmetic forms like Unown.
422 """
423 __tablename__ = 'pokemon'
424 __singlename__ = 'pokemon'
425 id = Column(Integer, primary_key=True, nullable=False)
426 name = Column(Unicode(20), nullable=False)
427 forme_name = Column(Unicode(16))
428 forme_base_pokemon_id = Column(Integer, ForeignKey('pokemon.id'))
429 generation_id = Column(Integer, ForeignKey('generations.id'))
430 evolution_chain_id = Column(Integer, ForeignKey('evolution_chains.id'))
431 evolution_parent_pokemon_id = Column(Integer, ForeignKey('pokemon.id'))
432 evolution_method_id = Column(Integer, ForeignKey('evolution_methods.id'))
433 evolution_parameter = Column(Unicode(32))
434 height = Column(Integer, nullable=False)
435 weight = Column(Integer, nullable=False)
436 species = Column(Unicode(16), nullable=False)
437 color_id = Column(Integer, ForeignKey('pokemon_colors.id'), nullable=False)
438 pokemon_shape_id = Column(Integer, ForeignKey('pokemon_shapes.id'), nullable=False)
439 habitat_id = Column(Integer, ForeignKey('pokemon_habitats.id'), nullable=True)
440 gender_rate = Column(Integer, nullable=False)
441 capture_rate = Column(Integer, nullable=False)
442 base_experience = Column(Integer, nullable=False)
443 base_happiness = Column(Integer, nullable=False)
444 is_baby = Column(Boolean, nullable=False)
445 has_gen4_fem_sprite = Column(Boolean, nullable=False)
446 has_gen4_fem_back_sprite = Column(Boolean, nullable=False)
447
448 ### Stuff to handle alternate Pokémon forms
449
450 @property
451 def national_id(self):
452 """Returns the National Pokédex number for this Pokémon. Use this
453 instead of the id directly; alternate formes may make the id incorrect.
454 """
455
456 if self.forme_base_pokemon_id:
457 return self.forme_base_pokemon_id
458 return self.id
459
460 @property
461 def full_name(self):
462 """Returns the name of this Pokémon, including its Forme, if any."""
463
464 if self.forme_name:
465 return "%s %s" % (self.forme_name.title(), self.name)
466 return self.name
467
468 @property
469 def normal_form(self):
470 """Returns the normal form for this Pokémon; i.e., this will return
471 regular Deoxys when called on any Deoxys form.
472 """
473
474 if self.forme_base_pokemon:
475 return self.forme_base_pokemon
476
477 return self
478
479 ### Not forms!
480
481 def stat(self, stat_name):
482 """Returns a PokemonStat record for the given stat name (or Stat row
483 object). Uses the normal has-many machinery, so all the stats are
484 effectively cached.
485 """
486 if isinstance(stat_name, Stat):
487 stat_name = stat_name.name
488
489 for pokemon_stat in self.stats:
490 if pokemon_stat.stat.name == stat_name:
491 return pokemon_stat
492
493 return None
494
495 class PokemonAbility(TableBase):
496 __tablename__ = 'pokemon_abilities'
497 pokemon_id = Column(Integer, ForeignKey('pokemon.id'), primary_key=True, nullable=False, autoincrement=False)
498 ability_id = Column(Integer, ForeignKey('abilities.id'), nullable=False)
499 slot = Column(Integer, primary_key=True, nullable=False, autoincrement=False)
500
501 class PokemonColor(TableBase):
502 __tablename__ = 'pokemon_colors'
503 id = Column(Integer, primary_key=True, nullable=False, autoincrement=False)
504 name = Column(Unicode(6), nullable=False)
505
506 class PokemonDexNumber(TableBase):
507 __tablename__ = 'pokemon_dex_numbers'
508 pokemon_id = Column(Integer, ForeignKey('pokemon.id'), primary_key=True, nullable=False, autoincrement=False)
509 pokedex_id = Column(Integer, ForeignKey('pokedexes.id'), primary_key=True, nullable=False, autoincrement=False)
510 pokedex_number = Column(Integer, nullable=False)
511
512 class PokemonEggGroup(TableBase):
513 __tablename__ = 'pokemon_egg_groups'
514 pokemon_id = Column(Integer, ForeignKey('pokemon.id'), primary_key=True, nullable=False, autoincrement=False)
515 egg_group_id = Column(Integer, ForeignKey('egg_groups.id'), primary_key=True, nullable=False, autoincrement=False)
516
517 class PokemonFlavorText(TableBase):
518 __tablename__ = 'pokemon_flavor_text'
519 pokemon_id = Column(Integer, ForeignKey('pokemon.id'), primary_key=True, nullable=False, autoincrement=False)
520 version_id = Column(Integer, ForeignKey('versions.id'), primary_key=True, nullable=False, autoincrement=False)
521 flavor_text = Column(Unicode(255), nullable=False)
522
523 class PokemonFormGroup(TableBase):
524 __tablename__ = 'pokemon_form_groups'
525 pokemon_id = Column(Integer, ForeignKey('pokemon.id'), primary_key=True, nullable=False, autoincrement=False)
526 is_battle_only = Column(Boolean, nullable=False)
527 description = Column(Unicode(512), nullable=False)
528
529 class PokemonFormSprite(TableBase):
530 __tablename__ = 'pokemon_form_sprites'
531 id = Column(Integer, primary_key=True, nullable=False)
532 pokemon_id = Column(Integer, ForeignKey('pokemon.id'), primary_key=True, nullable=False, autoincrement=False)
533 introduced_in_version_group_id = Column(Integer, ForeignKey('version_groups.id'), primary_key=True, nullable=False, autoincrement=False)
534 name = Column(Unicode(16), nullable=True)
535 is_default = Column(Boolean, nullable=True)
536
537 class PokemonHabitat(TableBase):
538 __tablename__ = 'pokemon_habitats'
539 id = Column(Integer, primary_key=True, nullable=False, autoincrement=False)
540 name = Column(Unicode(16), nullable=False)
541
542 class PokemonItem(TableBase):
543 __tablename__ = 'pokemon_items'
544 pokemon_id = Column(Integer, ForeignKey('pokemon.id'), primary_key=True, nullable=False, autoincrement=False)
545 version_id = Column(Integer, ForeignKey('versions.id'), primary_key=True, nullable=False, autoincrement=False)
546 item_id = Column(Integer, ForeignKey('items.id'), primary_key=True, nullable=False, autoincrement=False)
547 rarity = Column(Integer, nullable=False)
548
549 class PokemonMove(TableBase):
550 __tablename__ = 'pokemon_moves'
551 pokemon_id = Column(Integer, ForeignKey('pokemon.id'), primary_key=True, nullable=False, autoincrement=False)
552 version_group_id = Column(Integer, ForeignKey('version_groups.id'), primary_key=True, nullable=False, autoincrement=False)
553 move_id = Column(Integer, ForeignKey('moves.id'), primary_key=True, nullable=False, autoincrement=False, index=True)
554 pokemon_move_method_id = Column(Integer, ForeignKey('pokemon_move_methods.id'), primary_key=True, nullable=False, autoincrement=False)
555 level = Column(Integer, primary_key=True, nullable=True, autoincrement=False)
556 order = Column(Integer, nullable=True)
557
558 class PokemonMoveMethod(TableBase):
559 __tablename__ = 'pokemon_move_methods'
560 id = Column(Integer, primary_key=True, nullable=False, autoincrement=False)
561 name = Column(Unicode(64), nullable=False)
562 description = Column(Unicode(255), nullable=False)
563
564 class PokemonName(TableBase):
565 __tablename__ = 'pokemon_names'
566 pokemon_id = Column(Integer, ForeignKey('pokemon.id'), primary_key=True, nullable=False, autoincrement=False)
567 language_id = Column(Integer, ForeignKey('languages.id'), primary_key=True, nullable=False, autoincrement=False)
568 name = Column(Unicode(16), nullable=False)
569
570 class PokemonShape(TableBase):
571 __tablename__ = 'pokemon_shapes'
572 id = Column(Integer, primary_key=True, nullable=False)
573 name = Column(Unicode(24), nullable=False)
574 awesome_name = Column(Unicode(16), nullable=False)
575
576 class PokemonStat(TableBase):
577 __tablename__ = 'pokemon_stats'
578 pokemon_id = Column(Integer, ForeignKey('pokemon.id'), primary_key=True, nullable=False, autoincrement=False)
579 stat_id = Column(Integer, ForeignKey('stats.id'), primary_key=True, nullable=False, autoincrement=False)
580 base_stat = Column(Integer, nullable=False)
581 effort = Column(Integer, nullable=False)
582
583 class PokemonType(TableBase):
584 __tablename__ = 'pokemon_types'
585 pokemon_id = Column(Integer, ForeignKey('pokemon.id'), primary_key=True, nullable=False, autoincrement=False)
586 type_id = Column(Integer, ForeignKey('types.id'), nullable=False)
587 slot = Column(Integer, primary_key=True, nullable=False, autoincrement=False)
588
589 class Region(TableBase):
590 """Major areas of the world: Kanto, Johto, etc."""
591 __tablename__ = 'regions'
592 id = Column(Integer, primary_key=True, nullable=False)
593 name = Column(Unicode(16), nullable=False)
594
595 class Stat(TableBase):
596 __tablename__ = 'stats'
597 id = Column(Integer, primary_key=True, nullable=False)
598 name = Column(Unicode(16), nullable=False)
599
600 class SuperContestCombo(TableBase):
601 __tablename__ = 'super_contest_combos'
602 first_move_id = Column(Integer, ForeignKey('moves.id'), primary_key=True, nullable=False, autoincrement=False)
603 second_move_id = Column(Integer, ForeignKey('moves.id'), primary_key=True, nullable=False, autoincrement=False)
604
605 class SuperContestEffect(TableBase):
606 __tablename__ = 'super_contest_effects'
607 id = Column(Integer, primary_key=True, nullable=False)
608 appeal = Column(SmallInteger, nullable=False)
609 flavor_text = Column(Unicode(64), nullable=False)
610
611 class TypeEfficacy(TableBase):
612 __tablename__ = 'type_efficacy'
613 damage_type_id = Column(Integer, ForeignKey('types.id'), primary_key=True, nullable=False, autoincrement=False)
614 target_type_id = Column(Integer, ForeignKey('types.id'), primary_key=True, nullable=False, autoincrement=False)
615 damage_factor = Column(Integer, nullable=False)
616
617 class Type(TableBase):
618 __tablename__ = 'types'
619 __singlename__ = 'type'
620 id = Column(Integer, primary_key=True, nullable=False)
621 name = Column(Unicode(8), nullable=False)
622 abbreviation = Column(Unicode(3), nullable=False)
623 generation_id = Column(Integer, ForeignKey('generations.id'), nullable=False)
624 damage_class_id = Column(Integer, ForeignKey('move_damage_classes.id'), nullable=False) ## ??? is none; everything else is physical or special
625
626 class VersionGroup(TableBase):
627 __tablename__ = 'version_groups'
628 id = Column(Integer, primary_key=True, nullable=False)
629 generation_id = Column(Integer, ForeignKey('generations.id'), nullable=False)
630
631 class VersionGroupRegion(TableBase):
632 __tablename__ = 'version_group_regions'
633 version_group_id = Column(Integer, ForeignKey('version_groups.id'), primary_key=True, nullable=False)
634 region_id = Column(Integer, ForeignKey('regions.id'), primary_key=True, nullable=False)
635
636 class Version(TableBase):
637 __tablename__ = 'versions'
638 id = Column(Integer, primary_key=True, nullable=False)
639 version_group_id = Column(Integer, ForeignKey('version_groups.id'), nullable=False)
640 name = Column(Unicode(32), nullable=False)
641
642
643 ### Relations down here, to avoid ordering problems
644 Ability.flavor_text = relation(AbilityFlavorText, order_by=AbilityFlavorText.version_group_id, backref='abilities')
645 Ability.generation = relation(Generation, backref='abilities')
646
647 AbilityFlavorText.version_group = relation(VersionGroup)
648
649 Berry.berry_firmness = relation(BerryFirmness, backref='berries')
650 Berry.firmness = association_proxy('berry_firmness', 'name')
651 Berry.flavors = relation(BerryFlavor, order_by=BerryFlavor.contest_type_id, backref='berry')
652 Berry.natural_gift_type = relation(Type)
653
654 BerryFlavor.contest_type = relation(ContestType)
655
656 ContestCombo.first = relation(Move, primaryjoin=ContestCombo.first_move_id==Move.id,
657 backref='contest_combo_first')
658 ContestCombo.second = relation(Move, primaryjoin=ContestCombo.second_move_id==Move.id,
659 backref='contest_combo_second')
660
661 Encounter.location_area = relation(LocationArea, backref='encounters')
662 Encounter.pokemon = relation(Pokemon, backref='encounters')
663 Encounter.version = relation(Version, backref='encounters')
664 Encounter.slot = relation(EncounterSlot, backref='encounters')
665
666 EncounterConditionValue.condition = relation(EncounterCondition, backref='values')
667
668 Encounter.condition_value_map = relation(EncounterConditionValueMap, backref='encounter')
669 Encounter.condition_values = association_proxy('condition_value_map', 'condition_value')
670 EncounterConditionValueMap.condition_value = relation(EncounterConditionValue,
671 backref='encounter_map')
672
673 EncounterSlot.terrain = relation(EncounterTerrain, backref='slots')
674
675 EncounterSlot.condition_map = relation(EncounterSlotCondition, backref='slot')
676 EncounterSlot.conditions = association_proxy('condition_map', 'condition')
677 EncounterSlotCondition.condition = relation(EncounterCondition,
678 backref='slot_map')
679
680 EvolutionChain.growth_rate = relation(GrowthRate, backref='evolution_chains')
681
682 Experience.growth_rate = relation(GrowthRate, backref='experience_table')
683
684 Generation.canonical_pokedex = relation(Pokedex, backref='canonical_for_generation')
685 Generation.versions = relation(Version, secondary=VersionGroup.__table__)
686 Generation.main_region = relation(Region)
687
688 GrowthRate.max_experience_obj = relation(Experience, primaryjoin=and_(Experience.growth_rate_id == GrowthRate.id, Experience.level == 100), uselist=False)
689 GrowthRate.max_experience = association_proxy('max_experience_obj', 'experience')
690
691 Item.berry = relation(Berry, uselist=False, backref='item')
692 Item.flags = relation(ItemFlag, secondary=ItemFlagMap.__table__)
693 Item.flavor_text = relation(ItemFlavorText, order_by=ItemFlavorText.version_group_id.asc(), backref='item')
694 Item.fling_effect = relation(ItemFlingEffect, backref='items')
695 Item.machines = relation(Machine, order_by=Machine.version_group_id.asc())
696 Item.category = relation(ItemCategory)
697 Item.pocket = association_proxy('category', 'pocket')
698
699 ItemCategory.items = relation(Item, order_by=Item.name)
700 ItemCategory.pocket = relation(ItemPocket)
701
702 ItemFlavorText.version_group = relation(VersionGroup)
703
704 ItemPocket.categories = relation(ItemCategory, order_by=ItemCategory.name)
705
706 Location.region = relation(Region, backref='locations')
707
708 LocationArea.location = relation(Location, backref='areas')
709
710 Machine.item = relation(Item)
711 Machine.version_group = relation(VersionGroup)
712
713 Move.contest_effect = relation(ContestEffect, backref='moves')
714 Move.contest_combo_next = association_proxy('contest_combo_first', 'second')
715 Move.contest_combo_prev = association_proxy('contest_combo_second', 'first')
716 Move.contest_type = relation(ContestType, backref='moves')
717 Move.damage_class = relation(MoveDamageClass, backref='moves')
718 Move.flags = association_proxy('move_flags', 'flag')
719 Move.flavor_text = relation(MoveFlavorText, order_by=MoveFlavorText.version_group_id, backref='move')
720 Move.foreign_names = relation(MoveName, backref='pokemon')
721 Move.generation = relation(Generation, backref='moves')
722 Move.machines = relation(Machine, backref='move')
723 Move.move_effect = relation(MoveEffect, backref='moves')
724 Move.move_flags = relation(MoveFlag, backref='move')
725 Move.super_contest_effect = relation(SuperContestEffect, backref='moves')
726 Move.super_contest_combo_next = association_proxy('super_contest_combo_first', 'second')
727 Move.super_contest_combo_prev = association_proxy('super_contest_combo_second', 'first')
728 Move.target = relation(MoveTarget, backref='moves')
729 Move.type = relation(Type, backref='moves')
730
731 Move.effect = rst.MoveEffectProperty('effect')
732 Move.priority = association_proxy('move_effect', 'priority')
733 Move.short_effect = rst.MoveEffectProperty('short_effect')
734
735 MoveEffect.category_map = relation(MoveEffectCategoryMap)
736 MoveEffect.categories = association_proxy('category_map', 'category')
737 MoveEffectCategoryMap.category = relation(MoveEffectCategory)
738
739 MoveFlag.flag = relation(MoveFlagType)
740
741 MoveFlavorText.version_group = relation(VersionGroup)
742
743 MoveName.language = relation(Language)
744
745 Nature.decreased_stat = relation(Stat, primaryjoin=Nature.decreased_stat_id==Stat.id,
746 backref='decreasing_natures')
747 Nature.increased_stat = relation(Stat, primaryjoin=Nature.increased_stat_id==Stat.id,
748 backref='increasing_natures')
749 Nature.hates_flavor = relation(ContestType, primaryjoin=Nature.hates_flavor_id==ContestType.id,
750 backref='hating_natures')
751 Nature.likes_flavor = relation(ContestType, primaryjoin=Nature.likes_flavor_id==ContestType.id,
752 backref='liking_natures')
753 Nature.battle_style_preferences = relation(NatureBattleStylePreference,
754 order_by=NatureBattleStylePreference.move_battle_style_id,
755 backref='nature')
756 Nature.pokeathlon_effects = relation(NaturePokeathlonStat, order_by=NaturePokeathlonStat.pokeathlon_stat_id)
757
758 NatureBattleStylePreference.battle_style = relation(MoveBattleStyle, backref='nature_preferences')
759
760 NaturePokeathlonStat.pokeathlon_stat = relation(PokeathlonStat, backref='nature_effects')
761
762 Pokedex.region = relation(Region, backref='pokedexes')
763 Pokedex.version_groups = relation(VersionGroup, secondary=PokedexVersionGroup.__table__, backref='pokedexes')
764
765 Pokemon.abilities = relation(Ability, secondary=PokemonAbility.__table__,
766 order_by=PokemonAbility.slot,
767 backref='pokemon')
768 Pokemon.formes = relation(Pokemon, primaryjoin=Pokemon.id==Pokemon.forme_base_pokemon_id,
769 backref=backref('forme_base_pokemon',
770 remote_side=[Pokemon.id]))
771 Pokemon.pokemon_color = relation(PokemonColor, backref='pokemon')
772 Pokemon.color = association_proxy('pokemon_color', 'name')
773 Pokemon.dex_numbers = relation(PokemonDexNumber, backref='pokemon')
774 Pokemon.default_form_sprite = relation(PokemonFormSprite,
775 primaryjoin=and_(
776 Pokemon.id==PokemonFormSprite.pokemon_id,
777 PokemonFormSprite.is_default==True,
778 ),
779 uselist=False)
780 Pokemon.egg_groups = relation(EggGroup, secondary=PokemonEggGroup.__table__,
781 order_by=PokemonEggGroup.egg_group_id,
782 backref='pokemon')
783 Pokemon.evolution_chain = relation(EvolutionChain, backref='pokemon')
784 Pokemon.evolution_method = relation(EvolutionMethod)
785 Pokemon.evolution_children = relation(Pokemon, primaryjoin=Pokemon.id==Pokemon.evolution_parent_pokemon_id,
786 backref=backref('evolution_parent',
787 remote_side=[Pokemon.id]))
788 Pokemon.flavor_text = relation(PokemonFlavorText, order_by=PokemonFlavorText.version_id.asc(), backref='pokemon')
789 Pokemon.foreign_names = relation(PokemonName, backref='pokemon')
790 Pokemon.pokemon_habitat = relation(PokemonHabitat, backref='pokemon')
791 Pokemon.habitat = association_proxy('pokemon_habitat', 'name')
792 Pokemon.items = relation(PokemonItem, backref='pokemon')
793 Pokemon.generation = relation(Generation, backref='pokemon')
794 Pokemon.shape = relation(PokemonShape, backref='pokemon')
795 Pokemon.stats = relation(PokemonStat, backref='pokemon')
796 Pokemon.types = relation(Type, secondary=PokemonType.__table__, order_by=PokemonType.slot.asc())
797
798 PokemonDexNumber.pokedex = relation(Pokedex)
799
800 PokemonFlavorText.version = relation(Version)
801
802 PokemonItem.item = relation(Item, backref='pokemon')
803 PokemonItem.version = relation(Version)
804
805 PokemonFormGroup.pokemon = relation(Pokemon, backref=backref('form_group',
806 uselist=False))
807 PokemonFormSprite.pokemon = relation(Pokemon, backref='form_sprites')
808 PokemonFormSprite.introduced_in = relation(VersionGroup)
809
810 PokemonMove.pokemon = relation(Pokemon, backref='pokemon_moves')
811 PokemonMove.version_group = relation(VersionGroup)
812 PokemonMove.machine = relation(Machine, backref='pokemon_moves',
813 primaryjoin=and_(Machine.version_group_id==PokemonMove.version_group_id,
814 Machine.move_id==PokemonMove.move_id),
815 foreign_keys=[Machine.version_group_id, Machine.move_id],
816 uselist=False)
817 PokemonMove.move = relation(Move, backref='pokemon_moves')
818 PokemonMove.method = relation(PokemonMoveMethod)
819
820 PokemonName.language = relation(Language)
821
822 PokemonStat.stat = relation(Stat)
823
824 # This is technically a has-many; Generation.main_region_id -> Region.id
825 Region.generation = relation(Generation, uselist=False)
826 Region.version_group_regions = relation(VersionGroupRegion, backref='region',
827 order_by='VersionGroupRegion.version_group_id')
828 Region.version_groups = association_proxy('version_group_regions', 'version_group')
829
830 SuperContestCombo.first = relation(Move, primaryjoin=SuperContestCombo.first_move_id==Move.id,
831 backref='super_contest_combo_first')
832 SuperContestCombo.second = relation(Move, primaryjoin=SuperContestCombo.second_move_id==Move.id,
833 backref='super_contest_combo_second')
834
835 Type.damage_efficacies = relation(TypeEfficacy,
836 primaryjoin=Type.id
837 ==TypeEfficacy.damage_type_id,
838 backref='damage_type')
839 Type.target_efficacies = relation(TypeEfficacy,
840 primaryjoin=Type.id
841 ==TypeEfficacy.target_type_id,
842 backref='target_type')
843
844 Type.generation = relation(Generation, backref='types')
845 Type.damage_class = relation(MoveDamageClass, backref='types')
846
847 Version.version_group = relation(VersionGroup, backref='versions')
848 Version.generation = association_proxy('version_group', 'generation')
849
850 VersionGroup.generation = relation(Generation, backref='version_groups')
851 VersionGroup.version_group_regions = relation(VersionGroupRegion, backref='version_group')
852 VersionGroup.regions = association_proxy('version_group_regions', 'region')