Add experience tables.
[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 flavor_text = Column(Unicode(255), nullable=False)
205 effect = Column(Unicode(5120), nullable=False)
206 is_underground = Column(Boolean, nullable=False)
207 can_hold = Column(Boolean, nullable=False)
208 is_battle_item = Column(Boolean, nullable=False)
209 can_use_automatically = Column(Boolean, nullable=False)
210 can_reuse = Column(Boolean, nullable=False)
211
212 class ItemCategory(TableBase):
213 __tablename__ = 'item_categories'
214 id = Column(Integer, primary_key=True, nullable=False)
215 pocket_id = Column(Integer, ForeignKey('item_pockets.id'), nullable=False)
216 name = Column(Unicode(16), nullable=False)
217
218 class ItemFlingEffect(TableBase):
219 __tablename__ = 'item_fling_effects'
220 id = Column(Integer, primary_key=True, nullable=False)
221 effect = Column(Unicode(255), nullable=False)
222
223 class ItemPocket(TableBase):
224 __tablename__ = 'item_pockets'
225 id = Column(Integer, primary_key=True, nullable=False)
226 identifier = Column(Unicode(16), nullable=False)
227 name = Column(Unicode(16), nullable=False)
228
229 class Language(TableBase):
230 __tablename__ = 'languages'
231 id = Column(Integer, primary_key=True, nullable=False)
232 iso639 = Column(Unicode(2), nullable=False)
233 iso3166 = Column(Unicode(2), nullable=False)
234 name = Column(Unicode(16), nullable=False)
235
236 class Location(TableBase):
237 __tablename__ = 'locations'
238 __singlename__ = 'location'
239 id = Column(Integer, primary_key=True, nullable=False)
240 region_id = Column(Integer, ForeignKey('regions.id'))
241 name = Column(Unicode(64), nullable=False)
242
243 class LocationArea(TableBase):
244 __tablename__ = 'location_areas'
245 id = Column(Integer, primary_key=True, nullable=False)
246 location_id = Column(Integer, ForeignKey('locations.id'), nullable=False)
247 internal_id = Column(Integer, nullable=False)
248 name = Column(Unicode(64), nullable=True)
249
250 class LocationAreaEncounterRate(TableBase):
251 __tablename__ = 'location_area_encounter_rates'
252 location_area_id = Column(Integer, ForeignKey('location_areas.id'), primary_key=True, nullable=False, autoincrement=False)
253 encounter_terrain_id = Column(Integer, ForeignKey('encounter_terrain.id'), primary_key=True, nullable=False, autoincrement=False)
254 version_id = Column(Integer, ForeignKey('versions.id'), primary_key=True, autoincrement=False)
255 rate = Column(Integer, nullable=True)
256
257 class Machine(TableBase):
258 __tablename__ = 'machines'
259 machine_number = Column(Integer, primary_key=True, nullable=False, autoincrement=False)
260 version_group_id = Column(Integer, ForeignKey('version_groups.id'), primary_key=True, nullable=False, autoincrement=False)
261 move_id = Column(Integer, ForeignKey('moves.id'), nullable=False)
262
263 class MoveBattleStyle(TableBase):
264 __tablename__ = 'move_battle_styles'
265 id = Column(Integer, primary_key=True, nullable=False)
266 name = Column(Unicode(8), nullable=False)
267
268 class MoveEffectCategory(TableBase):
269 __tablename__ = 'move_effect_categories'
270 id = Column(Integer, primary_key=True, nullable=False)
271 name = Column(Unicode(64), nullable=False)
272 can_affect_user = Column(Boolean, nullable=False)
273
274 class MoveEffectCategoryMap(TableBase):
275 __tablename__ = 'move_effect_category_map'
276 move_effect_id = Column(Integer, ForeignKey('move_effects.id'), primary_key=True, nullable=False)
277 move_effect_category_id = Column(Integer, ForeignKey('move_effect_categories.id'), primary_key=True, nullable=False)
278 affects_user = Column(Boolean, primary_key=True, nullable=False)
279
280 class MoveDamageClass(TableBase):
281 __tablename__ = 'move_damage_classes'
282 id = Column(Integer, primary_key=True, nullable=False)
283 name = Column(Unicode(8), nullable=False)
284 description = Column(Unicode(64), nullable=False)
285
286 class MoveEffect(TableBase):
287 __tablename__ = 'move_effects'
288 id = Column(Integer, primary_key=True, nullable=False)
289 priority = Column(SmallInteger, nullable=False)
290 short_effect = Column(Unicode(256), nullable=False)
291 effect = Column(Unicode(5120), nullable=False)
292
293 class MoveFlag(TableBase):
294 __tablename__ = 'move_flags'
295 move_id = Column(Integer, ForeignKey('moves.id'), primary_key=True, nullable=False, autoincrement=False)
296 move_flag_type_id = Column(Integer, ForeignKey('move_flag_types.id'), primary_key=True, nullable=False, autoincrement=False)
297
298 class MoveFlagType(TableBase):
299 __tablename__ = 'move_flag_types'
300 id = Column(Integer, primary_key=True, nullable=False)
301 name = Column(Unicode(32), nullable=False)
302 description = Column(rst.RstTextColumn(128), nullable=False)
303
304 class MoveFlavorText(TableBase):
305 __tablename__ = 'move_flavor_text'
306 move_id = Column(Integer, ForeignKey('moves.id'), primary_key=True, nullable=False, autoincrement=False)
307 generation_id = Column(Integer, ForeignKey('generations.id'), primary_key=True, nullable=False, autoincrement=False)
308 flavor_text = Column(Unicode(255), nullable=False)
309
310 class MoveName(TableBase):
311 __tablename__ = 'move_names'
312 move_id = Column(Integer, ForeignKey('moves.id'), primary_key=True, nullable=False, autoincrement=False)
313 language_id = Column(Integer, ForeignKey('languages.id'), primary_key=True, nullable=False, autoincrement=False)
314 name = Column(Unicode(16), nullable=False)
315
316 class MoveTarget(TableBase):
317 __tablename__ = 'move_targets'
318 id = Column(Integer, primary_key=True, nullable=False)
319 name = Column(Unicode(32), nullable=False)
320 description = Column(Unicode(128), nullable=False)
321
322 class Move(TableBase):
323 __tablename__ = 'moves'
324 __singlename__ = 'move'
325 id = Column(Integer, primary_key=True, nullable=False)
326 name = Column(Unicode(12), nullable=False)
327 generation_id = Column(Integer, ForeignKey('generations.id'), nullable=False)
328 type_id = Column(Integer, ForeignKey('types.id'), nullable=False)
329 power = Column(SmallInteger)
330 pp = Column(SmallInteger, nullable=False)
331 accuracy = Column(SmallInteger)
332 target_id = Column(Integer, ForeignKey('move_targets.id'), nullable=False)
333 damage_class_id = Column(Integer, ForeignKey('move_damage_classes.id'), nullable=False)
334 effect_id = Column(Integer, ForeignKey('move_effects.id'), nullable=False)
335 effect_chance = Column(Integer)
336 contest_type_id = Column(Integer, ForeignKey('contest_types.id'), nullable=True)
337 contest_effect_id = Column(Integer, ForeignKey('contest_effects.id'), nullable=True)
338 super_contest_effect_id = Column(Integer, ForeignKey('super_contest_effects.id'), nullable=False)
339
340 class Nature(TableBase):
341 __tablename__ = 'natures'
342 __singlename__ = 'nature'
343 id = Column(Integer, primary_key=True, nullable=False)
344 name = Column(Unicode(8), nullable=False)
345 decreased_stat_id = Column(Integer, ForeignKey('stats.id'), nullable=False)
346 increased_stat_id = Column(Integer, ForeignKey('stats.id'), nullable=False)
347 hates_flavor_id = Column(Integer, ForeignKey('contest_types.id'), nullable=False)
348 likes_flavor_id = Column(Integer, ForeignKey('contest_types.id'), nullable=False)
349
350 class NatureBattleStylePreference(TableBase):
351 __tablename__ = 'nature_battle_style_preferences'
352 nature_id = Column(Integer, ForeignKey('natures.id'), primary_key=True, nullable=False)
353 move_battle_style_id = Column(Integer, ForeignKey('move_battle_styles.id'), primary_key=True, nullable=False)
354 low_hp_preference = Column(Integer, nullable=False)
355 high_hp_preference = Column(Integer, nullable=False)
356
357 class NaturePokeathlonStat(TableBase):
358 __tablename__ = 'nature_pokeathlon_stats'
359 nature_id = Column(Integer, ForeignKey('natures.id'), primary_key=True, nullable=False)
360 pokeathlon_stat_id = Column(Integer, ForeignKey('pokeathlon_stats.id'), primary_key=True, nullable=False)
361 max_change = Column(Integer, nullable=False)
362
363 class PokeathlonStat(TableBase):
364 __tablename__ = 'pokeathlon_stats'
365 id = Column(Integer, primary_key=True, nullable=False)
366 name = Column(Unicode(8), nullable=False)
367
368 class Pokedex(TableBase):
369 __tablename__ = 'pokedexes'
370 id = Column(Integer, primary_key=True, nullable=False)
371 region_id = Column(Integer, ForeignKey('regions.id'), nullable=True)
372 name = Column(Unicode(16), nullable=False)
373 description = Column(Unicode(512))
374
375 class PokedexVersionGroup(TableBase):
376 __tablename__ = 'pokedex_version_groups'
377 pokedex_id = Column(Integer, ForeignKey('pokedexes.id'), primary_key=True, nullable=False, autoincrement=False)
378 version_group_id = Column(Integer, ForeignKey('version_groups.id'), primary_key=True, nullable=False, autoincrement=False)
379
380 class Pokemon(TableBase):
381 """The core to this whole mess.
382
383 Note that I use both 'forme' and 'form' in both code and the database. I
384 only use 'forme' when specifically referring to Pokémon that have multiple
385 distinct species as forms—i.e., different stats or movesets. 'Form' is a
386 more general term referring to any variation within a species, including
387 purely cosmetic forms like Unown.
388 """
389 __tablename__ = 'pokemon'
390 __singlename__ = 'pokemon'
391 id = Column(Integer, primary_key=True, nullable=False)
392 name = Column(Unicode(20), nullable=False)
393 forme_name = Column(Unicode(16))
394 forme_base_pokemon_id = Column(Integer, ForeignKey('pokemon.id'))
395 generation_id = Column(Integer, ForeignKey('generations.id'))
396 evolution_chain_id = Column(Integer, ForeignKey('evolution_chains.id'))
397 evolution_parent_pokemon_id = Column(Integer, ForeignKey('pokemon.id'))
398 evolution_method_id = Column(Integer, ForeignKey('evolution_methods.id'))
399 evolution_parameter = Column(Unicode(32))
400 height = Column(Integer, nullable=False)
401 weight = Column(Integer, nullable=False)
402 species = Column(Unicode(16), nullable=False)
403 color_id = Column(Integer, ForeignKey('pokemon_colors.id'), nullable=False)
404 pokemon_shape_id = Column(Integer, ForeignKey('pokemon_shapes.id'), nullable=False)
405 habitat_id = Column(Integer, ForeignKey('pokemon_habitats.id'), nullable=True)
406 gender_rate = Column(Integer, nullable=False)
407 capture_rate = Column(Integer, nullable=False)
408 base_experience = Column(Integer, nullable=False)
409 base_happiness = Column(Integer, nullable=False)
410 is_baby = Column(Boolean, nullable=False)
411 has_gen4_fem_sprite = Column(Boolean, nullable=False)
412 has_gen4_fem_back_sprite = Column(Boolean, nullable=False)
413
414 ### Stuff to handle alternate Pokémon forms
415
416 @property
417 def national_id(self):
418 """Returns the National Pokédex number for this Pokémon. Use this
419 instead of the id directly; alternate formes may make the id incorrect.
420 """
421
422 if self.forme_base_pokemon_id:
423 return self.forme_base_pokemon_id
424 return self.id
425
426 @property
427 def full_name(self):
428 """Returns the name of this Pokémon, including its Forme, if any."""
429
430 if self.forme_name:
431 return "%s %s" % (self.forme_name.title(), self.name)
432 return self.name
433
434 @property
435 def normal_form(self):
436 """Returns the normal form for this Pokémon; i.e., this will return
437 regular Deoxys when called on any Deoxys form.
438 """
439
440 if self.forme_base_pokemon:
441 return self.forme_base_pokemon
442
443 return self
444
445 ### Not forms!
446
447 def stat(self, stat_name):
448 """Returns a PokemonStat record for the given stat name (or Stat row
449 object). Uses the normal has-many machinery, so all the stats are
450 effectively cached.
451 """
452 if isinstance(stat_name, Stat):
453 stat_name = stat_name.name
454
455 for pokemon_stat in self.stats:
456 if pokemon_stat.stat.name == stat_name:
457 return pokemon_stat
458
459 return None
460
461 class PokemonAbility(TableBase):
462 __tablename__ = 'pokemon_abilities'
463 pokemon_id = Column(Integer, ForeignKey('pokemon.id'), primary_key=True, nullable=False, autoincrement=False)
464 ability_id = Column(Integer, ForeignKey('abilities.id'), nullable=False)
465 slot = Column(Integer, primary_key=True, nullable=False, autoincrement=False)
466
467 class PokemonColor(TableBase):
468 __tablename__ = 'pokemon_colors'
469 id = Column(Integer, primary_key=True, nullable=False, autoincrement=False)
470 name = Column(Unicode(6), nullable=False)
471
472 class PokemonDexNumber(TableBase):
473 __tablename__ = 'pokemon_dex_numbers'
474 pokemon_id = Column(Integer, ForeignKey('pokemon.id'), primary_key=True, nullable=False, autoincrement=False)
475 pokedex_id = Column(Integer, ForeignKey('pokedexes.id'), primary_key=True, nullable=False, autoincrement=False)
476 pokedex_number = Column(Integer, nullable=False)
477
478 class PokemonEggGroup(TableBase):
479 __tablename__ = 'pokemon_egg_groups'
480 pokemon_id = Column(Integer, ForeignKey('pokemon.id'), primary_key=True, nullable=False, autoincrement=False)
481 egg_group_id = Column(Integer, ForeignKey('egg_groups.id'), primary_key=True, nullable=False, autoincrement=False)
482
483 class PokemonFlavorText(TableBase):
484 __tablename__ = 'pokemon_flavor_text'
485 pokemon_id = Column(Integer, ForeignKey('pokemon.id'), primary_key=True, nullable=False, autoincrement=False)
486 version_id = Column(Integer, ForeignKey('versions.id'), primary_key=True, nullable=False, autoincrement=False)
487 flavor_text = Column(Unicode(255), nullable=False)
488
489 class PokemonFormGroup(TableBase):
490 __tablename__ = 'pokemon_form_groups'
491 pokemon_id = Column(Integer, ForeignKey('pokemon.id'), primary_key=True, nullable=False, autoincrement=False)
492 is_battle_only = Column(Boolean, nullable=False)
493 description = Column(Unicode(512), nullable=False)
494
495 class PokemonFormSprite(TableBase):
496 __tablename__ = 'pokemon_form_sprites'
497 id = Column(Integer, primary_key=True, nullable=False)
498 pokemon_id = Column(Integer, ForeignKey('pokemon.id'), primary_key=True, nullable=False, autoincrement=False)
499 introduced_in_version_group_id = Column(Integer, ForeignKey('version_groups.id'), primary_key=True, nullable=False, autoincrement=False)
500 name = Column(Unicode(16), nullable=True)
501 is_default = Column(Boolean, nullable=True)
502
503 class PokemonHabitat(TableBase):
504 __tablename__ = 'pokemon_habitats'
505 id = Column(Integer, primary_key=True, nullable=False, autoincrement=False)
506 name = Column(Unicode(16), nullable=False)
507
508 class PokemonItem(TableBase):
509 __tablename__ = 'pokemon_items'
510 pokemon_id = Column(Integer, ForeignKey('pokemon.id'), primary_key=True, nullable=False, autoincrement=False)
511 version_id = Column(Integer, ForeignKey('versions.id'), primary_key=True, nullable=False, autoincrement=False)
512 item_id = Column(Integer, ForeignKey('items.id'), primary_key=True, nullable=False, autoincrement=False)
513 rarity = Column(Integer, nullable=False)
514
515 class PokemonMove(TableBase):
516 __tablename__ = 'pokemon_moves'
517 pokemon_id = Column(Integer, ForeignKey('pokemon.id'), primary_key=True, nullable=False, autoincrement=False)
518 version_group_id = Column(Integer, ForeignKey('version_groups.id'), primary_key=True, nullable=False, autoincrement=False)
519 move_id = Column(Integer, ForeignKey('moves.id'), primary_key=True, nullable=False, autoincrement=False, index=True)
520 pokemon_move_method_id = Column(Integer, ForeignKey('pokemon_move_methods.id'), primary_key=True, nullable=False, autoincrement=False)
521 level = Column(Integer, primary_key=True, nullable=True, autoincrement=False)
522 order = Column(Integer, nullable=True)
523
524 class PokemonMoveMethod(TableBase):
525 __tablename__ = 'pokemon_move_methods'
526 id = Column(Integer, primary_key=True, nullable=False, autoincrement=False)
527 name = Column(Unicode(64), nullable=False)
528 description = Column(Unicode(255), nullable=False)
529
530 class PokemonName(TableBase):
531 __tablename__ = 'pokemon_names'
532 pokemon_id = Column(Integer, ForeignKey('pokemon.id'), primary_key=True, nullable=False, autoincrement=False)
533 language_id = Column(Integer, ForeignKey('languages.id'), primary_key=True, nullable=False, autoincrement=False)
534 name = Column(Unicode(16), nullable=False)
535
536 class PokemonShape(TableBase):
537 __tablename__ = 'pokemon_shapes'
538 id = Column(Integer, primary_key=True, nullable=False)
539 name = Column(Unicode(24), nullable=False)
540 awesome_name = Column(Unicode(16), nullable=False)
541
542 class PokemonStat(TableBase):
543 __tablename__ = 'pokemon_stats'
544 pokemon_id = Column(Integer, ForeignKey('pokemon.id'), primary_key=True, nullable=False, autoincrement=False)
545 stat_id = Column(Integer, ForeignKey('stats.id'), primary_key=True, nullable=False, autoincrement=False)
546 base_stat = Column(Integer, nullable=False)
547 effort = Column(Integer, nullable=False)
548
549 class PokemonType(TableBase):
550 __tablename__ = 'pokemon_types'
551 pokemon_id = Column(Integer, ForeignKey('pokemon.id'), primary_key=True, nullable=False, autoincrement=False)
552 type_id = Column(Integer, ForeignKey('types.id'), nullable=False)
553 slot = Column(Integer, primary_key=True, nullable=False, autoincrement=False)
554
555 class Region(TableBase):
556 """Major areas of the world: Kanto, Johto, etc."""
557 __tablename__ = 'regions'
558 id = Column(Integer, primary_key=True, nullable=False)
559 name = Column(Unicode(16), nullable=False)
560
561 class Stat(TableBase):
562 __tablename__ = 'stats'
563 id = Column(Integer, primary_key=True, nullable=False)
564 name = Column(Unicode(16), nullable=False)
565
566 class SuperContestCombo(TableBase):
567 __tablename__ = 'super_contest_combos'
568 first_move_id = Column(Integer, ForeignKey('moves.id'), primary_key=True, nullable=False, autoincrement=False)
569 second_move_id = Column(Integer, ForeignKey('moves.id'), primary_key=True, nullable=False, autoincrement=False)
570
571 class SuperContestEffect(TableBase):
572 __tablename__ = 'super_contest_effects'
573 id = Column(Integer, primary_key=True, nullable=False)
574 appeal = Column(SmallInteger, nullable=False)
575 flavor_text = Column(Unicode(64), nullable=False)
576
577 class TypeEfficacy(TableBase):
578 __tablename__ = 'type_efficacy'
579 damage_type_id = Column(Integer, ForeignKey('types.id'), primary_key=True, nullable=False, autoincrement=False)
580 target_type_id = Column(Integer, ForeignKey('types.id'), primary_key=True, nullable=False, autoincrement=False)
581 damage_factor = Column(Integer, nullable=False)
582
583 class Type(TableBase):
584 __tablename__ = 'types'
585 __singlename__ = 'type'
586 id = Column(Integer, primary_key=True, nullable=False)
587 name = Column(Unicode(8), nullable=False)
588 abbreviation = Column(Unicode(3), nullable=False)
589 generation_id = Column(Integer, ForeignKey('generations.id'), nullable=False)
590 damage_class_id = Column(Integer, ForeignKey('move_damage_classes.id'), nullable=False) ## ??? is none; everything else is physical or special
591
592 class VersionGroup(TableBase):
593 __tablename__ = 'version_groups'
594 id = Column(Integer, primary_key=True, nullable=False)
595 generation_id = Column(Integer, ForeignKey('generations.id'), nullable=False)
596
597 class VersionGroupRegion(TableBase):
598 __tablename__ = 'version_group_regions'
599 version_group_id = Column(Integer, ForeignKey('version_groups.id'), primary_key=True, nullable=False)
600 region_id = Column(Integer, ForeignKey('regions.id'), primary_key=True, nullable=False)
601
602 class Version(TableBase):
603 __tablename__ = 'versions'
604 id = Column(Integer, primary_key=True, nullable=False)
605 version_group_id = Column(Integer, ForeignKey('version_groups.id'), nullable=False)
606 name = Column(Unicode(32), nullable=False)
607
608
609 ### Relations down here, to avoid ordering problems
610 Berry.berry_firmness = relation(BerryFirmness, backref='berries')
611 Berry.firmness = association_proxy('berry_firmness', 'name')
612 Berry.flavors = relation(BerryFlavor, order_by=BerryFlavor.contest_type_id, backref='berry')
613 Berry.natural_gift_type = relation(Type)
614
615 BerryFlavor.contest_type = relation(ContestType)
616
617 ContestCombo.first = relation(Move, primaryjoin=ContestCombo.first_move_id==Move.id,
618 backref='contest_combo_first')
619 ContestCombo.second = relation(Move, primaryjoin=ContestCombo.second_move_id==Move.id,
620 backref='contest_combo_second')
621
622 Encounter.location_area = relation(LocationArea, backref='encounters')
623 Encounter.pokemon = relation(Pokemon, backref='encounters')
624 Encounter.version = relation(Version, backref='encounters')
625 Encounter.slot = relation(EncounterSlot, backref='encounters')
626
627 EncounterConditionValue.condition = relation(EncounterCondition, backref='values')
628
629 Encounter.condition_value_map = relation(EncounterConditionValueMap, backref='encounter')
630 Encounter.condition_values = association_proxy('condition_value_map', 'condition_value')
631 EncounterConditionValueMap.condition_value = relation(EncounterConditionValue,
632 backref='encounter_map')
633
634 EncounterSlot.terrain = relation(EncounterTerrain, backref='slots')
635
636 EncounterSlot.condition_map = relation(EncounterSlotCondition, backref='slot')
637 EncounterSlot.conditions = association_proxy('condition_map', 'condition')
638 EncounterSlotCondition.condition = relation(EncounterCondition,
639 backref='slot_map')
640
641 EvolutionChain.growth_rate = relation(GrowthRate, backref='evolution_chains')
642
643 Experience.growth_rate = relation(GrowthRate, backref='experience_table')
644
645 Generation.canonical_pokedex = relation(Pokedex, backref='canonical_for_generation')
646 Generation.versions = relation(Version, secondary=VersionGroup.__table__)
647 Generation.main_region = relation(Region)
648
649 Item.berry = relation(Berry, uselist=False, backref='item')
650 Item.fling_effect = relation(ItemFlingEffect, backref='items')
651 Item.category = relation(ItemCategory)
652 Item.pocket = association_proxy('category', 'pocket')
653
654 ItemCategory.items = relation(Item, order_by=Item.name)
655 ItemCategory.pocket = relation(ItemPocket)
656
657 ItemPocket.categories = relation(ItemCategory, order_by=ItemCategory.name)
658
659 Location.region = relation(Region, backref='locations')
660
661 LocationArea.location = relation(Location, backref='areas')
662
663 Machine.version_group = relation(VersionGroup)
664
665 Move.contest_effect = relation(ContestEffect, backref='moves')
666 Move.contest_combo_next = association_proxy('contest_combo_first', 'second')
667 Move.contest_combo_prev = association_proxy('contest_combo_second', 'first')
668 Move.contest_type = relation(ContestType, backref='moves')
669 Move.damage_class = relation(MoveDamageClass, backref='moves')
670 Move.flags = association_proxy('move_flags', 'flag')
671 Move.flavor_text = relation(MoveFlavorText, order_by=MoveFlavorText.generation_id, backref='move')
672 Move.foreign_names = relation(MoveName, backref='pokemon')
673 Move.generation = relation(Generation, backref='moves')
674 Move.machines = relation(Machine, backref='move')
675 Move.move_effect = relation(MoveEffect, backref='moves')
676 Move.move_flags = relation(MoveFlag, backref='move')
677 Move.super_contest_effect = relation(SuperContestEffect, backref='moves')
678 Move.super_contest_combo_next = association_proxy('super_contest_combo_first', 'second')
679 Move.super_contest_combo_prev = association_proxy('super_contest_combo_second', 'first')
680 Move.target = relation(MoveTarget, backref='moves')
681 Move.type = relation(Type, backref='moves')
682
683 Move.effect = rst.MoveEffectProperty('effect')
684 Move.priority = association_proxy('move_effect', 'priority')
685 Move.short_effect = rst.MoveEffectProperty('short_effect')
686
687 MoveEffect.category_map = relation(MoveEffectCategoryMap)
688 MoveEffect.categories = association_proxy('category_map', 'category')
689 MoveEffectCategoryMap.category = relation(MoveEffectCategory)
690
691 MoveFlag.flag = relation(MoveFlagType)
692
693 MoveFlavorText.generation = relation(Generation)
694
695 MoveName.language = relation(Language)
696
697 Nature.decreased_stat = relation(Stat, primaryjoin=Nature.decreased_stat_id==Stat.id,
698 backref='decreasing_natures')
699 Nature.increased_stat = relation(Stat, primaryjoin=Nature.increased_stat_id==Stat.id,
700 backref='increasing_natures')
701 Nature.hates_flavor = relation(ContestType, primaryjoin=Nature.hates_flavor_id==ContestType.id,
702 backref='hating_natures')
703 Nature.likes_flavor = relation(ContestType, primaryjoin=Nature.likes_flavor_id==ContestType.id,
704 backref='liking_natures')
705 Nature.battle_style_preferences = relation(NatureBattleStylePreference,
706 order_by=NatureBattleStylePreference.move_battle_style_id,
707 backref='nature')
708 Nature.pokeathlon_effects = relation(NaturePokeathlonStat, order_by=NaturePokeathlonStat.pokeathlon_stat_id)
709
710 NatureBattleStylePreference.battle_style = relation(MoveBattleStyle, backref='nature_preferences')
711
712 NaturePokeathlonStat.pokeathlon_stat = relation(PokeathlonStat, backref='nature_effects')
713
714 Pokedex.region = relation(Region, backref='pokedexes')
715 Pokedex.version_groups = relation(VersionGroup, secondary=PokedexVersionGroup.__table__, backref='pokedexes')
716
717 Pokemon.abilities = relation(Ability, secondary=PokemonAbility.__table__,
718 order_by=PokemonAbility.slot,
719 backref='pokemon')
720 Pokemon.formes = relation(Pokemon, primaryjoin=Pokemon.id==Pokemon.forme_base_pokemon_id,
721 backref=backref('forme_base_pokemon',
722 remote_side=[Pokemon.id]))
723 Pokemon.pokemon_color = relation(PokemonColor, backref='pokemon')
724 Pokemon.color = association_proxy('pokemon_color', 'name')
725 Pokemon.dex_numbers = relation(PokemonDexNumber, backref='pokemon')
726 Pokemon.default_form_sprite = relation(PokemonFormSprite,
727 primaryjoin=and_(
728 Pokemon.id==PokemonFormSprite.pokemon_id,
729 PokemonFormSprite.is_default==True,
730 ),
731 uselist=False)
732 Pokemon.egg_groups = relation(EggGroup, secondary=PokemonEggGroup.__table__,
733 order_by=PokemonEggGroup.egg_group_id,
734 backref='pokemon')
735 Pokemon.evolution_chain = relation(EvolutionChain, backref='pokemon')
736 Pokemon.evolution_method = relation(EvolutionMethod)
737 Pokemon.evolution_children = relation(Pokemon, primaryjoin=Pokemon.id==Pokemon.evolution_parent_pokemon_id,
738 backref=backref('evolution_parent',
739 remote_side=[Pokemon.id]))
740 Pokemon.flavor_text = relation(PokemonFlavorText, order_by=PokemonFlavorText.pokemon_id, backref='pokemon')
741 Pokemon.foreign_names = relation(PokemonName, backref='pokemon')
742 Pokemon.pokemon_habitat = relation(PokemonHabitat, backref='pokemon')
743 Pokemon.habitat = association_proxy('pokemon_habitat', 'name')
744 Pokemon.items = relation(PokemonItem, backref='pokemon')
745 Pokemon.generation = relation(Generation, backref='pokemon')
746 Pokemon.shape = relation(PokemonShape, backref='pokemon')
747 Pokemon.stats = relation(PokemonStat, backref='pokemon')
748 Pokemon.types = relation(Type, secondary=PokemonType.__table__)
749
750 PokemonDexNumber.pokedex = relation(Pokedex)
751
752 PokemonFlavorText.version = relation(Version)
753
754 PokemonItem.item = relation(Item, backref='pokemon')
755 PokemonItem.version = relation(Version)
756
757 PokemonFormGroup.pokemon = relation(Pokemon, backref=backref('form_group',
758 uselist=False))
759 PokemonFormSprite.pokemon = relation(Pokemon, backref='form_sprites')
760 PokemonFormSprite.introduced_in = relation(VersionGroup)
761
762 PokemonMove.pokemon = relation(Pokemon, backref='pokemon_moves')
763 PokemonMove.version_group = relation(VersionGroup)
764 PokemonMove.machine = relation(Machine, backref='pokemon_moves',
765 primaryjoin=and_(Machine.version_group_id==PokemonMove.version_group_id,
766 Machine.move_id==PokemonMove.move_id),
767 foreign_keys=[Machine.version_group_id, Machine.move_id],
768 uselist=False)
769 PokemonMove.move = relation(Move, backref='pokemon_moves')
770 PokemonMove.method = relation(PokemonMoveMethod)
771
772 PokemonName.language = relation(Language)
773
774 PokemonStat.stat = relation(Stat)
775
776 # This is technically a has-many; Generation.main_region_id -> Region.id
777 Region.generation = relation(Generation, uselist=False)
778 Region.version_group_regions = relation(VersionGroupRegion, backref='region',
779 order_by='VersionGroupRegion.version_group_id')
780 Region.version_groups = association_proxy('version_group_regions', 'version_group')
781
782 SuperContestCombo.first = relation(Move, primaryjoin=SuperContestCombo.first_move_id==Move.id,
783 backref='super_contest_combo_first')
784 SuperContestCombo.second = relation(Move, primaryjoin=SuperContestCombo.second_move_id==Move.id,
785 backref='super_contest_combo_second')
786
787 Type.damage_efficacies = relation(TypeEfficacy,
788 primaryjoin=Type.id
789 ==TypeEfficacy.damage_type_id,
790 backref='damage_type')
791 Type.target_efficacies = relation(TypeEfficacy,
792 primaryjoin=Type.id
793 ==TypeEfficacy.target_type_id,
794 backref='target_type')
795
796 Type.generation = relation(Generation, backref='types')
797 Type.damage_class = relation(MoveDamageClass, backref='types')
798
799 Version.version_group = relation(VersionGroup, backref='versions')
800 Version.generation = association_proxy('version_group', 'generation')
801
802 VersionGroup.generation = relation(Generation, backref='version_groups')
803 VersionGroup.version_group_regions = relation(VersionGroupRegion, backref='version_group')
804 VersionGroup.regions = association_proxy('version_group_regions', 'region')