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