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