635b967c169c3425d2736a08f92bd1439d298c50
[zzz-pokedex.git] / pokedex / db / tables.py
1 # encoding: utf8
2
3 u"""The Pokédex schema
4
5 Columns have a info dictionary with these keys:
6 - description: The description of the column
7 - official: True if the values appear in games or official material; False if
8 they are fan-created or fan-written. This flag is currently only set for
9 official text columns.
10 - markup: The format of a text column. Can be one of:
11 - plaintext: Normal Unicode text (widely used in names)
12 - markdown: Veekun's Markdown flavor (generally used in effect descriptions)
13 - gametext: Transcription of in-game text that strives to be both
14 human-readable and represent the original text exactly.
15 - identifier: A fan-made identifier in the [-_a-z0-9]* format. Not intended
16 for translation.
17 - latex: A formula in LaTeX syntax.
18 - foreign: If set, the column contains foreign (non-English) text.
19
20 """
21 # XXX: Check if "gametext" is set correctly everywhere
22
23 # XXX: Some columns paradoxically have official=True and markup='identifier'.
24 # This is when one column is used as both the English name (lowercased) and
25 # an identifier. This should be fixed.
26
27 from sqlalchemy import Column, ForeignKey, MetaData, PrimaryKeyConstraint, Table
28 from sqlalchemy.ext.declarative import declarative_base
29 from sqlalchemy.ext.associationproxy import association_proxy
30 from sqlalchemy.orm import backref, eagerload_all, relation
31 from sqlalchemy.orm.session import Session
32 from sqlalchemy.sql import and_
33 from sqlalchemy.types import *
34
35 from pokedex.db import markdown
36
37 metadata = MetaData()
38 TableBase = declarative_base(metadata=metadata)
39
40 class Ability(TableBase):
41 u"""An ability a Pokémon can have, such as Static or Pressure.
42 """
43 __tablename__ = 'abilities'
44 __singlename__ = 'ability'
45 id = Column(Integer, primary_key=True, nullable=False,
46 info=dict(description="This ability's unique ID; matches the games' internal ID"))
47 name = Column(Unicode(24), nullable=False,
48 info=dict(description="The official English name of this ability", official=True, format='plaintext'))
49 generation_id = Column(Integer, ForeignKey('generations.id'), nullable=False,
50 info=dict(description="The ID of the generation this ability was introduced in", detail=True))
51 effect = Column(markdown.MarkdownColumn(5120), nullable=False,
52 info=dict(description="A detailed description of this ability's effect", format='markdown'))
53 short_effect = Column(markdown.MarkdownColumn(255), nullable=False,
54 info=dict(description="A short summary of this ability's effect", format='markdown'))
55
56 class AbilityChangelog(TableBase):
57 """History of changes to abilities across main game versions."""
58 __tablename__ = 'ability_changelog'
59 ability_id = Column(Integer, ForeignKey('abilities.id'), primary_key=True, nullable=False,
60 info=dict(description="The ID of the ability that changed"))
61 changed_in_version_group_id = Column(Integer, ForeignKey('version_groups.id'), primary_key=True, nullable=False,
62 info=dict(description="The ID of the version group in which the ability changed"))
63 effect = Column(markdown.MarkdownColumn(255), nullable=False,
64 info=dict(description="A description of the old behavior", format='markdown'))
65
66 class AbilityFlavorText(TableBase):
67 u"""In-game flavor text of an ability
68 """
69 __tablename__ = 'ability_flavor_text'
70 ability_id = Column(Integer, ForeignKey('abilities.id'), primary_key=True, nullable=False, autoincrement=False,
71 info=dict(description="The ID of the ability"))
72 version_group_id = Column(Integer, ForeignKey('version_groups.id'), primary_key=True, nullable=False, autoincrement=False,
73 info=dict(description="The ID of the version group this flavor text is taken from"))
74 flavor_text = Column(Unicode(64), nullable=False,
75 info=dict(description="The actual flavor text", official=True, format='gametext'))
76
77 class AbilityName(TableBase):
78 u"""Non-English official name of an ability
79 """
80 __tablename__ = 'ability_names'
81 ability_id = Column(Integer, ForeignKey('abilities.id'), primary_key=True, nullable=False, autoincrement=False,
82 info=dict(description="The ID of the ability"))
83 language_id = Column(Integer, ForeignKey('languages.id'), primary_key=True, nullable=False, autoincrement=False,
84 info=dict(description="The ID of the language"))
85 name = Column(Unicode(16), nullable=False,
86 info=dict(description="The ID of the language", official=True, foreign=True, format='plaintext'))
87
88 class Berry(TableBase):
89 u"""A Berry, consumable item that grows on trees
90
91 For data common to all items, such as the name, see the corresponding item entry.
92 """
93 __tablename__ = 'berries'
94 id = Column(Integer, primary_key=True, nullable=False,
95 info=dict(description="This Berry's in-game number"))
96 item_id = Column(Integer, ForeignKey('items.id'), nullable=False,
97 info=dict(description="The ID of the item that represents this Berry"))
98 firmness_id = Column(Integer, ForeignKey('berry_firmness.id'), nullable=False,
99 info=dict(description="The ID of this Berry's firmness category"))
100 natural_gift_power = Column(Integer, nullable=True,
101 info=dict(description="Natural Gift's power when used with this Berry"))
102 natural_gift_type_id = Column(Integer, ForeignKey('types.id'), nullable=True,
103 info=dict(description="The ID of the Type that Natural Gift has when used with this Berry"))
104 size = Column(Integer, nullable=False,
105 info=dict(description=u"The size of this Berry, in millimeters"))
106 max_harvest = Column(Integer, nullable=False,
107 info=dict(description="The maximum number of these berries that can grow on one tree in Generation IV"))
108 growth_time = Column(Integer, nullable=False,
109 info=dict(description="Time it takes the tree to grow one stage, in hours. Berry trees go through four of these growth stages before they can be picked."))
110 soil_dryness = Column(Integer, nullable=False,
111 info=dict(description="The speed at which this Berry dries out the soil as it grows. A higher rate means the soil dries more quickly."))
112 smoothness = Column(Integer, nullable=False,
113 info=dict(description="The smoothness of this Berry, used in making Pokéblocks or Poffins"))
114
115 class BerryFirmness(TableBase):
116 u"""A Berry firmness, such as "hard" or "very soft".
117 """
118 __tablename__ = 'berry_firmness'
119 id = Column(Integer, primary_key=True, nullable=False,
120 info=dict(description="A unique ID for this firmness"))
121 name = Column(Unicode(10), nullable=False,
122 info=dict(description="The games' English label for this firmness level", official=True, format='plaintext'))
123
124 class BerryFlavor(TableBase):
125 u"""A Berry flavor level.
126 """
127 __tablename__ = 'berry_flavors'
128 berry_id = Column(Integer, ForeignKey('berries.id'), primary_key=True, nullable=False, autoincrement=False,
129 info=dict(description="The ID of the berry"))
130 contest_type_id = Column(Integer, ForeignKey('contest_types.id'), primary_key=True, nullable=False, autoincrement=False,
131 info=dict(description="The ID of the flavor"))
132 flavor = Column(Integer, nullable=False,
133 info=dict(description="The level of the flavor in the berry"))
134
135 class ContestCombo(TableBase):
136 u"""Combo of two moves in a Contest.
137 """
138 __tablename__ = 'contest_combos'
139 first_move_id = Column(Integer, ForeignKey('moves.id'), primary_key=True, nullable=False, autoincrement=False,
140 info=dict(description="The ID of the first move in the combo"))
141 second_move_id = Column(Integer, ForeignKey('moves.id'), primary_key=True, nullable=False, autoincrement=False,
142 info=dict(description="The ID of the second and final move in the combo"))
143
144 class ContestEffect(TableBase):
145 u"""Effect of a move when used in a Contest.
146 """
147 __tablename__ = 'contest_effects'
148 id = Column(Integer, primary_key=True, nullable=False,
149 info=dict(description="A unique ID for this effect"))
150 appeal = Column(SmallInteger, nullable=False,
151 info=dict(description="The base number of hearts the user of this move gets"))
152 jam = Column(SmallInteger, nullable=False,
153 info=dict(description="The base number of hearts the user's opponent loses"))
154 flavor_text = Column(Unicode(64), nullable=False,
155 info=dict(description="The English in-game description of this effect", official=True, format='gametext'))
156 effect = Column(Unicode(255), nullable=False,
157 info=dict(description="A detailed description of the effect", format='markdown'))
158
159 class ContestType(TableBase):
160 u"""A Contest type, such as "cool" or "smart", and their associated Berry flavors and Pokéblock colors.
161 """
162 __tablename__ = 'contest_types'
163 id = Column(Integer, primary_key=True, nullable=False,
164 info=dict(description="A unique ID for this Contest type"))
165 name = Column(Unicode(6), nullable=False,
166 info=dict(description="The English name of the Contest type", official=True, format='identifier'))
167 flavor = Column(Unicode(6), nullable=False,
168 info=dict(description="The English name of the corresponding Berry flavor", official=True, format='identifier'))
169 color = Column(Unicode(6), nullable=False,
170 info=dict(description=u"The English name of the corresponding Pokéblock color", official=True, format='identifier'))
171
172 class EggGroup(TableBase):
173 u"""An Egg group. Usually, two Pokémon can breed if they share an Egg Group.
174
175 (exceptions are the Ditto and No Eggs groups)
176 """
177 __tablename__ = 'egg_groups'
178 id = Column(Integer, primary_key=True, nullable=False,
179 info=dict(description="A unique ID for this group"))
180 name = Column(Unicode(16), nullable=False,
181 info=dict(description=u"The English name of this egg group, from Earl's Pokémon Academy in Pokémon Stadium 2. "
182 u"And no, these haven't officially been used anywhere else.", official=True, format='identifier'))
183
184 class Encounter(TableBase):
185 u"""Encounters with wild Pokémon.
186
187 Bear with me, here.
188
189 Within a given area in a given game, encounters are differentiated by the
190 "slot" they are in and the state of the game world.
191
192 What the player is doing to get an encounter, such as surfing or walking
193 through tall grass, is called terrain. Each terrain has its own set of
194 encounter slots.
195
196 Within a terrain, slots are defined primarily by rarity. Each slot can
197 also be affected by world conditions; for example, the 20% slot for walking
198 in tall grass is affected by whether a swarm is in effect in that area.
199 "Is there a swarm?" is a condition; "there is a swarm" and "there is not a
200 swarm" are the possible values of this condition.
201
202 A slot (20% walking in grass) and any appropriate world conditions (no
203 swarm) are thus enough to define a specific encounter.
204
205 Well, okay, almost: each slot actually appears twice.
206 """
207
208 __tablename__ = 'encounters'
209 id = Column(Integer, primary_key=True, nullable=False,
210 info=dict(description="A unique ID for this encounter"))
211 version_id = Column(Integer, ForeignKey('versions.id'), nullable=False, autoincrement=False,
212 info=dict(description="The ID of the version this applies to"))
213 location_area_id = Column(Integer, ForeignKey('location_areas.id'), nullable=False, autoincrement=False,
214 info=dict(description="The ID of the location of this encounter"))
215 encounter_slot_id = Column(Integer, ForeignKey('encounter_slots.id'), nullable=False, autoincrement=False,
216 info=dict(description="The ID of the encounter slot, which determines terrain and rarity"))
217 pokemon_id = Column(Integer, ForeignKey('pokemon.id'), nullable=False, autoincrement=False,
218 info=dict(description=u"The ID of the encountered Pokémon"))
219 min_level = Column(Integer, nullable=False, autoincrement=False,
220 info=dict(description=u"The minimum level of the encountered Pokémon"))
221 max_level = Column(Integer, nullable=False, autoincrement=False,
222 info=dict(description=u"The maxmum level of the encountered Pokémon"))
223
224 class EncounterCondition(TableBase):
225 u"""A conditions in the game world that affects Pokémon encounters, such as time of day.
226 """
227
228 __tablename__ = 'encounter_conditions'
229 id = Column(Integer, primary_key=True, nullable=False,
230 info=dict(description="A unique ID for this condition"))
231 name = Column(Unicode(64), nullable=False,
232 info=dict(description="An English label for the condition", format='plaintext'))
233
234 class EncounterConditionValue(TableBase):
235 u"""A possible state for a condition; for example, the state of 'swarm' could be 'swarm' or 'no swarm'.
236 """
237
238 __tablename__ = 'encounter_condition_values'
239 id = Column(Integer, primary_key=True, nullable=False,
240 info=dict(description="A numeric ID"))
241 encounter_condition_id = Column(Integer, ForeignKey('encounter_conditions.id'), primary_key=False, nullable=False, autoincrement=False,
242 info=dict(description="The ID of the encounter condition this is a value of"))
243 name = Column(Unicode(64), nullable=False,
244 info=dict(description="An English label for this value", format='plaintext'))
245 is_default = Column(Boolean, nullable=False,
246 info=dict(description='Set if this value is the default state for the condition'))
247
248 class EncounterConditionValueMap(TableBase):
249 u"""Maps encounters to the specific conditions under which they occur.
250 """
251 __tablename__ = 'encounter_condition_value_map'
252 encounter_id = Column(Integer, ForeignKey('encounters.id'), primary_key=True, nullable=False, autoincrement=False,
253 info=dict(description="The ID of the encounter"))
254 encounter_condition_value_id = Column(Integer, ForeignKey('encounter_condition_values.id'), primary_key=True, nullable=False, autoincrement=False,
255 info=dict(description="The ID of the encounter condition value"))
256
257 class EncounterTerrain(TableBase):
258 u"""A way the player can enter a wild encounter, e.g., surfing, fishing, or walking through tall grass.
259 """
260
261 __tablename__ = 'encounter_terrain'
262 id = Column(Integer, primary_key=True, nullable=False,
263 info=dict(description="A unique ID for the terrain"))
264 name = Column(Unicode(64), nullable=False,
265 info=dict(description="An English label for this terrain", format='plaintext'))
266
267 class EncounterSlot(TableBase):
268 u"""An abstract "slot" within a terrain, associated with both some set of conditions and a rarity.
269
270 Note that there are two encounters per slot, so the rarities will only add
271 up to 50.
272 """
273
274 __tablename__ = 'encounter_slots'
275 id = Column(Integer, primary_key=True, nullable=False,
276 info=dict(description="A unique ID for this slot"))
277 version_group_id = Column(Integer, ForeignKey('version_groups.id'), nullable=False, autoincrement=False,
278 info=dict(description="The ID of the version group this slot is in"))
279 encounter_terrain_id = Column(Integer, ForeignKey('encounter_terrain.id'), primary_key=False, nullable=False, autoincrement=False,
280 info=dict(description="The ID of the terrain"))
281 slot = Column(Integer, nullable=True,
282 info=dict(description="This slot's order for the location and terrain"))
283 rarity = Column(Integer, nullable=False,
284 info=dict(description="The chance of the encounter as a percentage"))
285
286 class EncounterSlotCondition(TableBase):
287 u"""A condition that affects an encounter slot.
288 """
289 __tablename__ = 'encounter_slot_conditions'
290 encounter_slot_id = Column(Integer, ForeignKey('encounter_slots.id'), primary_key=True, nullable=False, autoincrement=False,
291 info=dict(description="The ID of the encounter slot"))
292 encounter_condition_id = Column(Integer, ForeignKey('encounter_conditions.id'), primary_key=True, nullable=False, autoincrement=False,
293 info=dict(description="The ID of the encounter condition"))
294
295 class EvolutionChain(TableBase):
296 u"""A family of Pokémon that are linked by evolution
297 """
298 __tablename__ = 'evolution_chains'
299 id = Column(Integer, primary_key=True, nullable=False,
300 info=dict(description="A numeric ID"))
301 growth_rate_id = Column(Integer, ForeignKey('growth_rates.id'), nullable=False,
302 info=dict(description="ID of the growth rate for this family"))
303 baby_trigger_item_id = Column(Integer, ForeignKey('items.id'), nullable=True,
304 info=dict(description="Item that a parent must hold while breeding to produce a baby"))
305
306 class EvolutionTrigger(TableBase):
307 u"""An evolution type, such as "level" or "trade".
308 """
309 __tablename__ = 'evolution_triggers'
310 id = Column(Integer, primary_key=True, nullable=False,
311 info=dict(description="A numeric ID"))
312 identifier = Column(Unicode(16), nullable=False,
313 info=dict(description="An English identifier", format='identifier'))
314
315 class Experience(TableBase):
316 u"""EXP needed for a certain level with a certain growth rate
317 """
318 __tablename__ = 'experience'
319 growth_rate_id = Column(Integer, ForeignKey('growth_rates.id'), primary_key=True, nullable=False,
320 info=dict(description="ID of the growth rate"))
321 level = Column(Integer, primary_key=True, nullable=False, autoincrement=False,
322 info=dict(description="The level"))
323 experience = Column(Integer, nullable=False,
324 info=dict(description="The number of EXP points needed to get to that level"))
325
326 class Generation(TableBase):
327 u"""A Generation of the Pokémon franchise
328 """
329 __tablename__ = 'generations'
330 id = Column(Integer, primary_key=True, nullable=False,
331 info=dict(description="A numeric ID"))
332 main_region_id = Column(Integer, ForeignKey('regions.id'),
333 info=dict(description="ID of the region this generation's main games take place in"))
334 canonical_pokedex_id = Column(Integer, ForeignKey('pokedexes.id'),
335 info=dict(description=u"ID of the Pokédex this generation's main games use by default"))
336 name = Column(Unicode(16), nullable=False,
337 info=dict(description=u'An English name of this generation, such as "Generation IV"', format='plaintext'))
338
339 class GrowthRate(TableBase):
340 u"""Growth rate of a Pokémon, i.e. the EXP → level function.
341 """
342 __tablename__ = 'growth_rates'
343 id = Column(Integer, primary_key=True, nullable=False,
344 info=dict(description="A numeric ID"))
345 name = Column(Unicode(20), nullable=False,
346 info=dict(description="A name for the", format='identifier'))
347 formula = Column(Unicode(500), nullable=False,
348 info=dict(description="The formula", format='latex'))
349
350 class Item(TableBase):
351 u"""An Item from the games, like "Poké Ball" or "Bicycle".
352 """
353 __tablename__ = 'items'
354 __singlename__ = 'item'
355 id = Column(Integer, primary_key=True, nullable=False,
356 info=dict(description="A numeric ID"))
357 name = Column(Unicode(20), nullable=False,
358 info=dict(description="The English name of the item", official=True, format='plaintext'))
359 category_id = Column(Integer, ForeignKey('item_categories.id'), nullable=False,
360 info=dict(description="ID of a category this item belongs to"))
361 cost = Column(Integer, nullable=False,
362 info=dict(description=u"Cost of the item when bought. Items sell for half this price."))
363 fling_power = Column(Integer, nullable=True,
364 info=dict(description=u"Power of the move Fling when used with this item."))
365 fling_effect_id = Column(Integer, ForeignKey('item_fling_effects.id'), nullable=True,
366 info=dict(description=u"ID of the fling-effect of the move Fling when used with this item. Note that these are different from move effects."))
367 short_effect = Column(Unicode(256), nullable=False,
368 info=dict(description="A short summary of the effect", format='plaintext'))
369 effect = Column(markdown.MarkdownColumn(5120), nullable=False,
370 info=dict(description=u"Detailed English description of the item's effect.", format='markdown'))
371
372 @property
373 def appears_underground(self):
374 u"""True if the item appears underground, as specified by the appropriate flag
375 """
376 return any(flag.identifier == u'underground' for flag in self.flags)
377
378 class ItemCategory(TableBase):
379 u"""An item category
380 """
381 # XXX: This is fanon, right?
382 __tablename__ = 'item_categories'
383 id = Column(Integer, primary_key=True, nullable=False,
384 info=dict(description="A numeric ID"))
385 pocket_id = Column(Integer, ForeignKey('item_pockets.id'), nullable=False,
386 info=dict(description="ID of the pocket these items go to"))
387 name = Column(Unicode(16), nullable=False,
388 info=dict(description="English name of the category", format='plaintext'))
389
390 class ItemFlag(TableBase):
391 u"""An item attribute such as "consumable" or "holdable".
392 """
393 __tablename__ = 'item_flags'
394 id = Column(Integer, primary_key=True, nullable=False,
395 info=dict(description="A numeric ID"))
396 identifier = Column(Unicode(24), nullable=False,
397 info=dict(description="Identifier of the flag", format='identifier'))
398 name = Column(Unicode(64), nullable=False,
399 info=dict(description="Short English description of the flag", format='plaintext'))
400
401 class ItemFlagMap(TableBase):
402 u"""Maps an item flag to its item.
403 """
404 __tablename__ = 'item_flag_map'
405 item_id = Column(Integer, ForeignKey('items.id'), primary_key=True, autoincrement=False, nullable=False,
406 info=dict(description="The ID of the item"))
407 item_flag_id = Column(Integer, ForeignKey('item_flags.id'), primary_key=True, autoincrement=False, nullable=False,
408 info=dict(description="The ID of the item flag"))
409
410 class ItemFlavorText(TableBase):
411 u"""An in-game description of an item
412 """
413 __tablename__ = 'item_flavor_text'
414 item_id = Column(Integer, ForeignKey('items.id'), primary_key=True, autoincrement=False, nullable=False,
415 info=dict(description="The ID of the item"))
416 version_group_id = Column(Integer, ForeignKey('version_groups.id'), primary_key=True, autoincrement=False, nullable=False,
417 info=dict(description="ID of the version group that sports this text"))
418 flavor_text = Column(Unicode(255), nullable=False,
419 info=dict(description="The flavor text itself", official=True, format='gametext'))
420
421 class ItemFlingEffect(TableBase):
422 u"""An effect of the move Fling when used with a specific item
423 """
424 __tablename__ = 'item_fling_effects'
425 id = Column(Integer, primary_key=True, nullable=False,
426 info=dict(description="A numeric ID"))
427 effect = Column(Unicode(255), nullable=False,
428 info=dict(description="English description of the effect", format='plaintext'))
429
430 class ItemInternalID(TableBase):
431 u"""The internal ID number a game uses for an item
432 """
433 __tablename__ = 'item_internal_ids'
434 item_id = Column(Integer, ForeignKey('items.id'), primary_key=True, autoincrement=False, nullable=False,
435 info=dict(description="The database ID of the item"))
436 generation_id = Column(Integer, ForeignKey('generations.id'), primary_key=True, autoincrement=False, nullable=False,
437 info=dict(description="ID of the generation of games"))
438 internal_id = Column(Integer, nullable=False,
439 info=dict(description="Internal ID of the item in the generation"))
440
441 class ItemName(TableBase):
442 u"""A non-English name of an item
443 """
444 __tablename__ = 'item_names'
445 item_id = Column(Integer, ForeignKey('items.id'), primary_key=True, nullable=False, autoincrement=False,
446 info=dict(description="The ID of the item"))
447 language_id = Column(Integer, ForeignKey('languages.id'), primary_key=True, nullable=False, autoincrement=False,
448 info=dict(description="The ID of the language"))
449 name = Column(Unicode(16), nullable=False,
450 info=dict(description="The name of the item in this language", foreign=True, format='plaintext'))
451
452 class ItemPocket(TableBase):
453 u"""A pocket that categorizes items
454 """
455 __tablename__ = 'item_pockets'
456 id = Column(Integer, primary_key=True, nullable=False,
457 info=dict(description="A numeric ID"))
458 identifier = Column(Unicode(16), nullable=False,
459 info=dict(description="An identifier of this pocket", format='identifier'))
460 name = Column(Unicode(16), nullable=False,
461 info=dict(description="A numeric ID", format='plaintext'))
462
463 class Language(TableBase):
464 u"""A language the Pokémon games have been transleted into; except English
465 """
466 __tablename__ = 'languages'
467 id = Column(Integer, primary_key=True, nullable=False,
468 info=dict(description="A numeric ID"))
469 iso639 = Column(Unicode(2), nullable=False,
470 info=dict(description="The two-letter code of the country where this language is spoken. Note that it is not unique."))
471 iso3166 = Column(Unicode(2), nullable=False,
472 info=dict(description="The two-letter code of the language. Note that it is not unique."))
473 name = Column(Unicode(16), nullable=False,
474 info=dict(description="The English name of the language", format='plaintext'))
475
476 class Location(TableBase):
477 u"""A place in the Pokémon world
478 """
479 __tablename__ = 'locations'
480 __singlename__ = 'location'
481 id = Column(Integer, primary_key=True, nullable=False,
482 info=dict(description="A numeric ID"))
483 region_id = Column(Integer, ForeignKey('regions.id'),
484 info=dict(description="ID of the region this location is in"))
485 name = Column(Unicode(64), nullable=False,
486 info=dict(description="English name of the location", official=True, format='plaintext'))
487
488 class LocationArea(TableBase):
489 u"""A sub-area of a location
490 """
491 __tablename__ = 'location_areas'
492 id = Column(Integer, primary_key=True, nullable=False,
493 info=dict(description="A numeric ID"))
494 location_id = Column(Integer, ForeignKey('locations.id'), nullable=False,
495 info=dict(description="ID of the location this area is part of"))
496 internal_id = Column(Integer, nullable=False,
497 info=dict(description="ID the games ude for this area"))
498 name = Column(Unicode(64), nullable=True,
499 info=dict(description="An English name of the area, if applicable", format='plaintext'))
500
501 class LocationAreaEncounterRate(TableBase):
502 # XXX: What's this exactly? Someone add the docstring & revise the descriptions
503 __tablename__ = 'location_area_encounter_rates'
504 location_area_id = Column(Integer, ForeignKey('location_areas.id'), primary_key=True, nullable=False, autoincrement=False,
505 info=dict(description="ID of the area"))
506 encounter_terrain_id = Column(Integer, ForeignKey('encounter_terrain.id'), primary_key=True, nullable=False, autoincrement=False,
507 info=dict(description="ID of the terrain"))
508 version_id = Column(Integer, ForeignKey('versions.id'), primary_key=True, autoincrement=False,
509 info=dict(description="ID of the version"))
510 rate = Column(Integer, nullable=True,
511 info=dict(description="The encounter rate")) # units?
512
513 class LocationInternalID(TableBase):
514 u"""IDs the games use internally for locations
515 """
516 __tablename__ = 'location_internal_ids'
517 location_id = Column(Integer, ForeignKey('locations.id'), nullable=False, primary_key=True,
518 info=dict(description="Database ID of the locaion"))
519 generation_id = Column(Integer, ForeignKey('generations.id'), nullable=False, primary_key=True,
520 info=dict(description="ID of the generation this entry to"))
521 internal_id = Column(Integer, nullable=False,
522 info=dict(description="Internal game ID of the location"))
523
524 class Machine(TableBase):
525 u"""A TM or HM; numbered item that can teach a move to a Pokémon
526 """
527 __tablename__ = 'machines'
528 machine_number = Column(Integer, primary_key=True, nullable=False, autoincrement=False,
529 info=dict(description="Number of the machine for TMs, or 100 + the munber for HMs"))
530 version_group_id = Column(Integer, ForeignKey('version_groups.id'), primary_key=True, nullable=False, autoincrement=False,
531 info=dict(description="Versions this entry applies to"))
532 item_id = Column(Integer, ForeignKey('items.id'), nullable=False,
533 info=dict(description="ID of the corresponding Item"))
534 move_id = Column(Integer, ForeignKey('moves.id'), nullable=False,
535 info=dict(description="ID of the taught move"))
536
537 @property
538 def is_hm(self):
539 u"""True if this machine is a HM, False if it's a TM
540 """
541 return self.machine_number >= 100
542
543 class MoveBattleStyle(TableBase):
544 u"""A battle style of a move""" # XXX: Explain better
545 __tablename__ = 'move_battle_styles'
546 id = Column(Integer, primary_key=True, nullable=False,
547 info=dict(description="A numeric ID"))
548 name = Column(Unicode(8), nullable=False,
549 info=dict(description="An English name for this battle style", format='plaintext'))
550
551 class MoveEffectCategory(TableBase):
552 u"""Category of a move effect
553 """
554 __tablename__ = 'move_effect_categories'
555 id = Column(Integer, primary_key=True, nullable=False,
556 info=dict(description="A numeric ID"))
557 name = Column(Unicode(64), nullable=False,
558 info=dict(description="English name of the category", format='plaintext'))
559 can_affect_user = Column(Boolean, nullable=False,
560 info=dict(description="Set if the user can be affected"))
561
562 class MoveEffectCategoryMap(TableBase):
563 u"""Maps a move effect category to a move effect
564 """
565 __tablename__ = 'move_effect_category_map'
566 move_effect_id = Column(Integer, ForeignKey('move_effects.id'), primary_key=True, nullable=False,
567 info=dict(description="ID of the move effect"))
568 move_effect_category_id = Column(Integer, ForeignKey('move_effect_categories.id'), primary_key=True, nullable=False,
569 info=dict(description="ID of the category"))
570 affects_user = Column(Boolean, primary_key=True, nullable=False,
571 info=dict(description="Set if the user is affected"))
572
573 class MoveDamageClass(TableBase):
574 u"""Any of the damage classes moves can have, i.e. physical, special, or non-damaging.
575 """
576 __tablename__ = 'move_damage_classes'
577 id = Column(Integer, primary_key=True, nullable=False,
578 info=dict(description="A numeric ID"))
579 name = Column(Unicode(16), nullable=False,
580 info=dict(description="An English name of the class", format='plaintext'))
581 description = Column(Unicode(64), nullable=False,
582 info=dict(description="An English description of the class", format='plaintext'))
583
584 class MoveEffect(TableBase):
585 u"""An effect of a move
586 """
587 __tablename__ = 'move_effects'
588 id = Column(Integer, primary_key=True, nullable=False,
589 info=dict(description="A numeric ID"))
590 short_effect = Column(Unicode(256), nullable=False,
591 info=dict(description="A short summary of the effect", format='plaintext'))
592 effect = Column(Unicode(5120), nullable=False,
593 info=dict(description="A detailed description of the effect", format='plaintext'))
594
595 class MoveEffectChangelog(TableBase):
596 """History of changes to move effects across main game versions."""
597 __tablename__ = 'move_effect_changelog'
598 effect_id = Column(Integer, ForeignKey('move_effects.id'), primary_key=True, nullable=False,
599 info=dict(description="The ID of the effect that changed"))
600 changed_in_version_group_id = Column(Integer, ForeignKey('version_groups.id'), primary_key=True, nullable=False,
601 info=dict(description="The ID of the version group in which the effect changed"))
602 effect = Column(markdown.MarkdownColumn(255), nullable=False,
603 info=dict(description="A description of the old behavior", format='markdown'))
604
605 class MoveFlag(TableBase):
606 u"""Maps a move flag to a move
607 """
608 # XXX: Other flags have a ___Flag class for the actual flag and ___FlagMap for the map,
609 # these, somewhat confusingly, have MoveFlagType and MoveFlag
610 __tablename__ = 'move_flags'
611 move_id = Column(Integer, ForeignKey('moves.id'), primary_key=True, nullable=False, autoincrement=False,
612 info=dict(description="ID of the move"))
613 move_flag_type_id = Column(Integer, ForeignKey('move_flag_types.id'), primary_key=True, nullable=False, autoincrement=False,
614 info=dict(description="ID of the flag"))
615
616 class MoveFlagType(TableBase):
617 u"""A Move attribute such as "snatchable" or "contact".
618 """
619 __tablename__ = 'move_flag_types'
620 id = Column(Integer, primary_key=True, nullable=False,
621 info=dict(description="A numeric ID"))
622 identifier = Column(Unicode(16), nullable=False,
623 info=dict(description="A short identifier for the flag", format='identifier'))
624 name = Column(Unicode(32), nullable=False,
625 info=dict(description="An English name for the flag", format='plaintext'))
626 description = Column(markdown.MarkdownColumn(128), nullable=False,
627 info=dict(description="A short English description of the flag", format='markdown'))
628
629 class MoveFlavorText(TableBase):
630 u"""In-game description of a move
631 """
632 __tablename__ = 'move_flavor_text'
633 move_id = Column(Integer, ForeignKey('moves.id'), primary_key=True, nullable=False, autoincrement=False,
634 info=dict(description="ID of the move"))
635 version_group_id = Column(Integer, ForeignKey('version_groups.id'), primary_key=True, nullable=False, autoincrement=False,
636 info=dict(description="ID of the version group this text appears in"))
637 flavor_text = Column(Unicode(255), nullable=False,
638 info=dict(description="The English flavor text", official=True, format='gametext'))
639
640 class MoveName(TableBase):
641 u"""Non-English name of a move
642 """
643 __tablename__ = 'move_names'
644 move_id = Column(Integer, ForeignKey('moves.id'), primary_key=True, nullable=False, autoincrement=False,
645 info=dict(description="ID of the move"))
646 language_id = Column(Integer, ForeignKey('languages.id'), primary_key=True, nullable=False, autoincrement=False,
647 info=dict(description="ID of the language"))
648 name = Column(Unicode(16), nullable=False,
649 info=dict(description="ID of the language", foreign=True, format='plaintext'))
650
651 class MoveTarget(TableBase):
652 u"""Targetting or "range" of a move, e.g. "Affects all opponents" or "Affects user".
653 """
654 __tablename__ = 'move_targets'
655 id = Column(Integer, primary_key=True, nullable=False,
656 info=dict(description="A numeric ID"))
657 name = Column(Unicode(32), nullable=False,
658 info=dict(description="An English name", format='plaintext'))
659 description = Column(Unicode(128), nullable=False,
660 info=dict(description="An English description", format='plaintext'))
661
662 class Move(TableBase):
663 u"""A Move: technique or attack a Pokémon can learn to use
664 """
665 __tablename__ = 'moves'
666 __singlename__ = 'move'
667 id = Column(Integer, primary_key=True, nullable=False,
668 info=dict(description="A numeric ID"))
669 name = Column(Unicode(24), nullable=False,
670 info=dict(description="The English name of the move", official=True, format='plaintext'))
671 generation_id = Column(Integer, ForeignKey('generations.id'), nullable=False,
672 info=dict(description="ID of the generation this move first appeared in"))
673 type_id = Column(Integer, ForeignKey('types.id'), nullable=False,
674 info=dict(description="ID of the move's elemental type"))
675 power = Column(SmallInteger, nullable=False,
676 info=dict(description="Base power of the move"))
677 pp = Column(SmallInteger, nullable=False,
678 info=dict(description="Base PP (Power Points) of the move"))
679 accuracy = Column(SmallInteger, nullable=True,
680 info=dict(description="Accuracy of the move; NULL means it never misses"))
681 priority = Column(SmallInteger, nullable=False,
682 info=dict(description="The move's priority bracket"))
683 target_id = Column(Integer, ForeignKey('move_targets.id'), nullable=False,
684 info=dict(description="ID of the target (range) of the move"))
685 damage_class_id = Column(Integer, ForeignKey('move_damage_classes.id'), nullable=False,
686 info=dict(description="ID of the damage class (physical/special) of the move"))
687 effect_id = Column(Integer, ForeignKey('move_effects.id'), nullable=False,
688 info=dict(description="ID of the move's effect"))
689 effect_chance = Column(Integer, nullable=True,
690 info=dict(description="The chance for a secondary effect. What this is a chance of is specified by the move's effect."))
691 contest_type_id = Column(Integer, ForeignKey('contest_types.id'), nullable=True,
692 info=dict(description="ID of the move's Contest type (e.g. cool or smart)"))
693 contest_effect_id = Column(Integer, ForeignKey('contest_effects.id'), nullable=True,
694 info=dict(description="ID of the move's Contest effect"))
695 super_contest_effect_id = Column(Integer, ForeignKey('super_contest_effects.id'), nullable=True,
696 info=dict(description="ID of the move's Super Contest effect"))
697
698 class MoveChangelog(TableBase):
699 """History of changes to moves across main game versions."""
700 __tablename__ = 'move_changelog'
701 move_id = Column(Integer, ForeignKey('moves.id'), primary_key=True, nullable=False,
702 info=dict(description="ID of the move that changed"))
703 changed_in_version_group_id = Column(Integer, ForeignKey('version_groups.id'), primary_key=True, nullable=False,
704 info=dict(description="ID of the version group in which the move changed"))
705 type_id = Column(Integer, ForeignKey('types.id'), nullable=True,
706 info=dict(description="Prior type of the move, or NULL if unchanged"))
707 power = Column(SmallInteger, nullable=True,
708 info=dict(description="Prior base power of the move, or NULL if unchanged"))
709 pp = Column(SmallInteger, nullable=True,
710 info=dict(description="Prior base PP of the move, or NULL if unchanged"))
711 accuracy = Column(SmallInteger, nullable=True,
712 info=dict(description="Prior accuracy of the move, or NULL if unchanged"))
713 effect_id = Column(Integer, ForeignKey('move_effects.id'), nullable=True,
714 info=dict(description="Prior ID of the effect, or NULL if unchanged"))
715 effect_chance = Column(Integer, nullable=True,
716 info=dict(description="Prior effect chance, or NULL if unchanged"))
717
718 class Nature(TableBase):
719 u"""A nature a Pokémon can have, such as Calm or Brave
720 """
721 __tablename__ = 'natures'
722 __singlename__ = 'nature'
723 id = Column(Integer, primary_key=True, nullable=False,
724 info=dict(description="A numeric ID"))
725 name = Column(Unicode(8), nullable=False,
726 info=dict(description="An English name of the nature", official=True, format='plaintext'))
727 decreased_stat_id = Column(Integer, ForeignKey('stats.id'), nullable=False,
728 info=dict(description="ID of the stat that this nature decreases by 10% (if decreased_stat_id is the same, the effects cancel out)"))
729 increased_stat_id = Column(Integer, ForeignKey('stats.id'), nullable=False,
730 info=dict(description="ID of the stat that this nature increases by 10% (if decreased_stat_id is the same, the effects cancel out)"))
731 hates_flavor_id = Column(Integer, ForeignKey('contest_types.id'), nullable=False,
732 info=dict(description=u"ID of the Berry flavor the Pokémon hates (if likes_flavor_id is the same, the effects cancel out)"))
733 likes_flavor_id = Column(Integer, ForeignKey('contest_types.id'), nullable=False,
734 info=dict(description=u"ID of the Berry flavor the Pokémon likes (if hates_flavor_id is the same, the effects cancel out)"))
735
736 @property
737 def is_neutral(self):
738 u"""Returns True iff this nature doesn't alter a Pokémon's stats,
739 bestow taste preferences, etc.
740 """
741 return self.increased_stat_id == self.decreased_stat_id
742
743 class NatureBattleStylePreference(TableBase):
744 u"""Battle Palace move preference
745
746 Specifies how likely a Pokémon with a specific Nature is to use a move of
747 a particular battl style in Battle Palace or Battle Tent
748 """
749 __tablename__ = 'nature_battle_style_preferences'
750 nature_id = Column(Integer, ForeignKey('natures.id'), primary_key=True, nullable=False,
751 info=dict(description=u"ID of the Pokémon's nature"))
752 move_battle_style_id = Column(Integer, ForeignKey('move_battle_styles.id'), primary_key=True, nullable=False,
753 info=dict(description="ID of the battle style"))
754 low_hp_preference = Column(Integer, nullable=False,
755 info=dict(description=u"Chance of using the move, in percent, if HP is under ½"))
756 high_hp_preference = Column(Integer, nullable=False,
757 info=dict(description=u"Chance of using the move, in percent, if HP is over ½"))
758
759 class NatureName(TableBase):
760 u"""Non-english name of a Nature
761 """
762 __tablename__ = 'nature_names'
763 nature_id = Column(Integer, ForeignKey('natures.id'), primary_key=True, nullable=False, autoincrement=False,
764 info=dict(description="ID of the nature"))
765 language_id = Column(Integer, ForeignKey('languages.id'), primary_key=True, nullable=False, autoincrement=False,
766 info=dict(description="ID of the language"))
767 name = Column(Unicode(8), nullable=False,
768 info=dict(description="The nature's foreign name", foreign=True, format='plaintext'))
769
770 class NaturePokeathlonStat(TableBase):
771 u"""Specifies how a Nature affects a Pokéathlon stat
772 """
773 __tablename__ = 'nature_pokeathlon_stats'
774 nature_id = Column(Integer, ForeignKey('natures.id'), primary_key=True, nullable=False,
775 info=dict(description="ID of the nature"))
776 pokeathlon_stat_id = Column(Integer, ForeignKey('pokeathlon_stats.id'), primary_key=True, nullable=False,
777 info=dict(description="ID of the stat"))
778 max_change = Column(Integer, nullable=False,
779 info=dict(description="Maximum change"))
780
781 class PokeathlonStat(TableBase):
782 u"""A Pokéathlon stat, such as "Stamina" or "Jump".
783 """
784 __tablename__ = 'pokeathlon_stats'
785 id = Column(Integer, primary_key=True, nullable=False,
786 info=dict(description="A numeric ID"))
787 name = Column(Unicode(8), nullable=False,
788 info=dict(description="The English name of the stat", official=True, format='plaintext'))
789
790 class Pokedex(TableBase):
791 u"""A collection of Pokémon species ordered in a particular way
792 """
793 __tablename__ = 'pokedexes'
794 id = Column(Integer, primary_key=True, nullable=False,
795 info=dict(description="A numeric ID"))
796 region_id = Column(Integer, ForeignKey('regions.id'), nullable=True,
797 info=dict(description=u"ID of the region this Pokédex is used in, or None if it's global"))
798 name = Column(Unicode(16), nullable=False,
799 info=dict(description=u"An English name of the Pokédex", format='plaintext'))
800 description = Column(Unicode(512),
801 info=dict(description=u"A longer description of the Pokédex", format='plaintext'))
802
803 class Pokemon(TableBase):
804 u"""A species of Pokémon. The core to this whole mess.
805 """
806 __tablename__ = 'pokemon'
807 __singlename__ = 'pokemon'
808 id = Column(Integer, primary_key=True, nullable=False,
809 info=dict(description=u"A numeric ID"))
810 name = Column(Unicode(20), nullable=False,
811 info=dict(description=u"The English name of the Pokémon", official=True, format='plaintext'))
812 generation_id = Column(Integer, ForeignKey('generations.id'),
813 info=dict(description=u"ID of the generation this species first appeared in"))
814 evolution_chain_id = Column(Integer, ForeignKey('evolution_chains.id'),
815 info=dict(description=u"ID of the species' evolution chain (a.k.a. family)"))
816 height = Column(Integer, nullable=False,
817 info=dict(description=u"The height of the Pokémon, in decimeters (tenths of a meter)"))
818 weight = Column(Integer, nullable=False,
819 info=dict(description=u"The weight of the Pokémon, in tenths of a kilogram (decigrams)"))
820 species = Column(Unicode(16), nullable=False,
821 info=dict(description=u'The short English flavor text, such as "Seed" or "Lizard"; usually affixed with the word "Pokémon"',
822 official=True, format='plaintext'))
823 color_id = Column(Integer, ForeignKey('pokemon_colors.id'), nullable=False,
824 info=dict(description=u"ID of this Pokémon's Pokédex color, as used for a gimmick search function in the games."))
825 pokemon_shape_id = Column(Integer, ForeignKey('pokemon_shapes.id'), nullable=True,
826 info=dict(description=u"ID of this Pokémon's body shape, as used for a gimmick search function in the games."))
827 habitat_id = Column(Integer, ForeignKey('pokemon_habitats.id'), nullable=True,
828 info=dict(description=u"ID of this Pokémon's habitat, as used for a gimmick search function in the games."))
829 gender_rate = Column(Integer, nullable=False,
830 info=dict(description=u"The chance of this Pokémon being female, in eighths; or -1 for genderless"))
831 capture_rate = Column(Integer, nullable=False,
832 info=dict(description=u"The base capture rate; up to 255"))
833 base_experience = Column(Integer, nullable=False,
834 info=dict(description=u"The base EXP gained when defeating this Pokémon")) # XXX: Is this correct?
835 base_happiness = Column(Integer, nullable=False,
836 info=dict(description=u"The tameness when caught by a normal ball"))
837 is_baby = Column(Boolean, nullable=False,
838 info=dict(description=u"True iff the Pokémon is a baby, i.e. a lowest-stage Pokémon that cannot breed but whose evolved form can."))
839 hatch_counter = Column(Integer, nullable=False,
840 info=dict(description=u"Initial hatch counter: one must walk 255 × (hatch_counter + 1) steps before this Pokémon's egg hatches, unless utilizing bonuses like Flame Body's"))
841 has_gender_differences = Column(Boolean, nullable=False,
842 info=dict(description=u"Set iff the species exhibits enough sexual dimorphism to have separate sets of sprites in Gen IV and beyond."))
843 order = Column(Integer, nullable=False, index=True,
844 info=dict(description=u"Order for sorting. Almost national order, except families and forms are grouped together."))
845
846 ### Stuff to handle alternate Pokémon forms
847
848 @property
849 def form(self):
850 u"""Returns the Pokémon's form, using its default form as fallback."""
851
852 return self.unique_form or self.default_form
853
854 @property
855 def is_base_form(self):
856 u"""Returns True iff the Pokémon is the base form for its species,
857 e.g. Land Shaymin.
858 """
859
860 return self.unique_form is None or self.unique_form.is_default
861
862 @property
863 def form_name(self):
864 u"""Returns the Pokémon's form name if it represents a particular form
865 and that form has a name, or None otherwise.
866 """
867
868 # If self.unique_form is None, the short-circuit "and" will go ahead
869 # and return that. Otherwise, it'll return the form's name, which may
870 # also be None.
871 return self.unique_form and self.unique_form.name
872
873 @property
874 def full_name(self):
875 u"""Returns the Pokémon's name, including its form if applicable."""
876
877 if self.form_name:
878 return '{0} {1}'.format(self.form_name, self.name)
879 else:
880 return self.name
881
882 @property
883 def normal_form(self):
884 u"""Returns the normal form for this Pokémon; i.e., this will return
885 regular Deoxys when called on any Deoxys form.
886 """
887
888 if self.unique_form:
889 return self.unique_form.form_base_pokemon
890 return self
891
892 ### Not forms!
893
894 def stat(self, stat_name):
895 u"""Returns a PokemonStat record for the given stat name (or Stat row
896 object). Uses the normal has-many machinery, so all the stats are
897 effectively cached.
898 """
899 if isinstance(stat_name, Stat):
900 stat_name = stat_name.name
901
902 for pokemon_stat in self.stats:
903 if pokemon_stat.stat.name == stat_name:
904 return pokemon_stat
905
906 raise KeyError(u'No stat named %s' % stat_name)
907
908 @property
909 def better_damage_class(self):
910 u"""Returns the MoveDamageClass that this Pokémon is best suited for,
911 based on its attack stats.
912
913 If the attack stats are about equal (within 5), returns None. The
914 value None, not the damage class called 'None'.
915 """
916 phys = self.stat(u'Attack')
917 spec = self.stat(u'Special Attack')
918
919 diff = phys.base_stat - spec.base_stat
920
921 if diff > 5:
922 return phys.stat.damage_class
923 elif diff < -5:
924 return spec.stat.damage_class
925 else:
926 return None
927
928 class PokemonAbility(TableBase):
929 u"""Maps an ability to a Pokémon that can have it
930 """
931 __tablename__ = 'pokemon_abilities'
932 pokemon_id = Column(Integer, ForeignKey('pokemon.id'), primary_key=True, nullable=False, autoincrement=False,
933 info=dict(description=u"ID of the Pokémon"))
934 ability_id = Column(Integer, ForeignKey('abilities.id'), nullable=False,
935 info=dict(description=u"ID of the ability"))
936 # XXX having both a method and a slot is kind of gross. "slot" is a
937 # misnomer, anyway: duplicate abilities don't appear in slot 2.
938 # Probably should replace that with "order".
939 is_dream = Column(Boolean, nullable=False, index=True,
940 info=dict(description=u"Whether this is a Dream World ability"))
941 slot = Column(Integer, primary_key=True, nullable=False, autoincrement=False,
942 info=dict(description=u"The ability slot, i.e. 1 or 2 for gen. IV"))
943
944 class PokemonColor(TableBase):
945 u"""The "Pokédex color" of a Pokémon species. Usually based on the Pokémon's color.
946 """
947 __tablename__ = 'pokemon_colors'
948 id = Column(Integer, primary_key=True, nullable=False, autoincrement=False,
949 info=dict(description=u"ID of the Pokémon"))
950 name = Column(Unicode(6), nullable=False,
951 info=dict(description=u"The English name of the color", official=True, format='identifier'))
952
953 class PokemonDexNumber(TableBase):
954 u"""The number of a Pokémon in a particular Pokédex (e.g. Jigglypuff is #138 in Hoenn's 'dex)
955 """
956 __tablename__ = 'pokemon_dex_numbers'
957 pokemon_id = Column(Integer, ForeignKey('pokemon.id'), primary_key=True, nullable=False, autoincrement=False,
958 info=dict(description=u"ID of the Pokémon"))
959 pokedex_id = Column(Integer, ForeignKey('pokedexes.id'), primary_key=True, nullable=False, autoincrement=False,
960 info=dict(description=u"ID of the Pokédex"))
961 pokedex_number = Column(Integer, nullable=False,
962 info=dict(description=u"Number of the Pokémon in that the Pokédex"))
963
964 class PokemonEggGroup(TableBase):
965 u"""Maps an Egg group to a Pokémon; each Pokémon belongs to one or two egg groups
966 """
967 __tablename__ = 'pokemon_egg_groups'
968 pokemon_id = Column(Integer, ForeignKey('pokemon.id'), primary_key=True, nullable=False, autoincrement=False,
969 info=dict(description=u"ID of the Pokémon"))
970 egg_group_id = Column(Integer, ForeignKey('egg_groups.id'), primary_key=True, nullable=False, autoincrement=False,
971 info=dict(description=u"ID of the egg group"))
972
973 class PokemonEvolution(TableBase):
974 u"""A required action ("trigger") and the conditions under which the trigger
975 must occur to cause a Pokémon to evolve.
976
977 Any condition may be null if it does not apply for a particular Pokémon.
978 """
979 __tablename__ = 'pokemon_evolution'
980 from_pokemon_id = Column(Integer, ForeignKey('pokemon.id'), nullable=False,
981 info=dict(description=u"The ID of the pre-evolution Pokémon."))
982 to_pokemon_id = Column(Integer, ForeignKey('pokemon.id'), primary_key=True, nullable=False, autoincrement=False,
983 info=dict(description=u"The ID of the post-evolution Pokémon."))
984 evolution_trigger_id = Column(Integer, ForeignKey('evolution_triggers.id'), nullable=False,
985 info=dict(description=u"The ID of the evolution trigger."))
986 trigger_item_id = Column(Integer, ForeignKey('items.id'), nullable=True,
987 info=dict(description=u"The ID of the item that must be used on the Pokémon."))
988 minimum_level = Column(Integer, nullable=True,
989 info=dict(description=u"The minimum level for the Pokémon."))
990 gender = Column(Enum('male', 'female', name='pokemon_evolution_gender'), nullable=True,
991 info=dict(description=u"The Pokémon's required gender, or None if gender doesn't matter"))
992 location_id = Column(Integer, ForeignKey('locations.id'), nullable=True,
993 info=dict(description=u"The ID of the location the evolution must be triggered at."))
994 held_item_id = Column(Integer, ForeignKey('items.id'), nullable=True,
995 info=dict(description=u"The ID of the item the Pokémon must hold."))
996 time_of_day = Column(Enum('morning', 'day', 'night', name='pokemon_evolution_time_of_day'), nullable=True,
997 info=dict(description=u"The required time of day."))
998 known_move_id = Column(Integer, ForeignKey('moves.id'), nullable=True,
999 info=dict(description=u"The ID of the move the Pokémon must know."))
1000 minimum_happiness = Column(Integer, nullable=True,
1001 info=dict(description=u"The minimum happiness value the Pokémon must have."))
1002 minimum_beauty = Column(Integer, nullable=True,
1003 info=dict(description=u"The minimum Beauty value the Pokémon must have."))
1004 relative_physical_stats = Column(Integer, nullable=True,
1005 info=dict(description=u"The required relation between the Pokémon's Attack and Defense stats, as sgn(atk-def)."))
1006 party_pokemon_id = Column(Integer, ForeignKey('pokemon.id'), nullable=True,
1007 info=dict(description=u"The ID of the Pokémon that must be present in the party."))
1008 trade_pokemon_id = Column(Integer, ForeignKey('pokemon.id'), nullable=True,
1009 info=dict(description=u"The ID of the Pokémon for which this Pokémon must be traded."))
1010
1011 class PokemonFlavorText(TableBase):
1012 u"""In-game Pokédex descrption of a Pokémon.
1013 """
1014 __tablename__ = 'pokemon_flavor_text'
1015 pokemon_id = Column(Integer, ForeignKey('pokemon.id'), primary_key=True, nullable=False, autoincrement=False,
1016 info=dict(description=u"ID of the Pokémon"))
1017 version_id = Column(Integer, ForeignKey('versions.id'), primary_key=True, nullable=False, autoincrement=False,
1018 info=dict(description=u"ID of the version that has this flavor text"))
1019 flavor_text = Column(Unicode(255), nullable=False,
1020 info=dict(description=u"ID of the version that has this flavor text", official=True, format='gametext'))
1021
1022 class PokemonForm(TableBase):
1023 u"""An individual form of a Pokémon.
1024
1025 Pokémon that do not have separate forms are still given a single row to
1026 represent their single form.
1027 """
1028 __tablename__ = 'pokemon_forms'
1029 __singlename__ = 'pokemon_form'
1030 id = Column(Integer, primary_key=True, nullable=False,
1031 info=dict(description=u'A unique ID for this form.'))
1032 name = Column(Unicode(16), nullable=True,
1033 info=dict(description=u"This form's name, e.g. \"Plant\" for Plant Cloak Burmy.", official=True, format='plaintext'))
1034 form_base_pokemon_id = Column(Integer, ForeignKey('pokemon.id'), nullable=False, autoincrement=False,
1035 info=dict(description=u'The ID of the base Pokémon for this form.'))
1036 unique_pokemon_id = Column(Integer, ForeignKey('pokemon.id'), autoincrement=False,
1037 info=dict(description=u'The ID of a Pokémon that represents specifically this form, for Pokémon with functionally-different forms like Wormadam.'))
1038 introduced_in_version_group_id = Column(Integer, ForeignKey('version_groups.id'), autoincrement=False,
1039 info=dict(description=u'The ID of the version group in which this form first appeared.'))
1040 is_default = Column(Boolean, nullable=False,
1041 info=dict(description=u'Set for exactly one form used as the default for each species.'))
1042 order = Column(Integer, nullable=False, autoincrement=False,
1043 info=dict(description=u'The order in which forms should be sorted. Multiple forms may have equal order, in which case they should fall back on sorting by name.'))
1044
1045 @property
1046 def pokemon(self):
1047 u"""Returns the Pokémon for this form, using the form base as fallback.
1048 """
1049
1050 return self.unique_pokemon or self.form_base_pokemon
1051
1052 @property
1053 def full_name(self):
1054 u"""Returns the full name of this form, e.g. "Plant Cloak"."""
1055
1056 if not self.name:
1057 return None
1058 elif self.form_group and self.form_group.term:
1059 return '{0} {1}'.format(self.name, self.form_group.term)
1060 else:
1061 return self.name
1062
1063 @property
1064 def pokemon_name(self):
1065 u"""Returns the name of this Pokémon with this form, e.g. "Plant
1066 Burmy".
1067 """
1068
1069 if self.name:
1070 return '{0} {1}'.format(self.name, self.form_base_pokemon.name)
1071 else:
1072 return self.form_base_pokemon.name
1073
1074 class PokemonFormGroup(TableBase):
1075 u"""Information about a Pokémon's forms as a group."""
1076 __tablename__ = 'pokemon_form_groups'
1077 pokemon_id = Column(Integer, ForeignKey('pokemon.id'), primary_key=True, nullable=False, autoincrement=False,
1078 info=dict(description=u"ID of the base form Pokémon"))
1079 term = Column(Unicode(16), nullable=True,
1080 info=dict(description=u"The term for this Pokémon's forms, e.g. \"Cloak\" for Burmy or \"Forme\" for Deoxys.", official=True, format='plaintext'))
1081 is_battle_only = Column(Boolean, nullable=False,
1082 info=dict(description=u"Set iff the forms only change in battle"))
1083 description = Column(markdown.MarkdownColumn(1024), nullable=False,
1084 info=dict(description=u"English description of how the forms work", format='markdown'))
1085
1086 class PokemonFormPokeathlonStat(TableBase):
1087 u"""A Pokémon form's performance in one Pokéathlon stat."""
1088 __tablename__ = 'pokemon_form_pokeathlon_stats'
1089 pokemon_form_id = Column(Integer, ForeignKey('pokemon_forms.id'), primary_key=True, nullable=False, autoincrement=False,
1090 info=dict(description=u'The ID of the Pokémon form.'))
1091 pokeathlon_stat_id = Column(Integer, ForeignKey('pokeathlon_stats.id'), primary_key=True, nullable=False, autoincrement=False,
1092 info=dict(description=u'The ID of the Pokéathlon stat.'))
1093 minimum_stat = Column(Integer, nullable=False, autoincrement=False,
1094 info=dict(description=u'The minimum value for this stat for this Pokémon form.'))
1095 base_stat = Column(Integer, nullable=False, autoincrement=False,
1096 info=dict(description=u'The default value for this stat for this Pokémon form.'))
1097 maximum_stat = Column(Integer, nullable=False, autoincrement=False,
1098 info=dict(description=u'The maximum value for this stat for this Pokémon form.'))
1099
1100 class PokemonHabitat(TableBase):
1101 u"""The habitat of a Pokémon, as given in the FireRed/LeafGreen version Pokédex
1102 """
1103 __tablename__ = 'pokemon_habitats'
1104 id = Column(Integer, primary_key=True, nullable=False, autoincrement=False,
1105 info=dict(description=u"A numeric ID"))
1106 name = Column(Unicode(16), nullable=False,
1107 info=dict(description=u"The English name of the habitat", official=True, format='plaintext'))
1108
1109 class PokemonInternalID(TableBase):
1110 u"""The number of a Pokémon a game uses internally
1111 """
1112 __tablename__ = 'pokemon_internal_ids'
1113 pokemon_id = Column(Integer, ForeignKey('pokemon.id'), primary_key=True, autoincrement=False, nullable=False,
1114 info=dict(description=u"Database ID of the Pokémon"))
1115 generation_id = Column(Integer, ForeignKey('generations.id'), primary_key=True, autoincrement=False, nullable=False,
1116 info=dict(description=u"Database ID of the generation"))
1117 internal_id = Column(Integer, nullable=False,
1118 info=dict(description=u"Internal ID the generation's games use for the Pokémon"))
1119
1120 class PokemonItem(TableBase):
1121 u"""Record of an item a Pokémon can hold in the wild
1122 """
1123 __tablename__ = 'pokemon_items'
1124 pokemon_id = Column(Integer, ForeignKey('pokemon.id'), primary_key=True, nullable=False, autoincrement=False,
1125 info=dict(description=u"ID of the Pokémon"))
1126 version_id = Column(Integer, ForeignKey('versions.id'), primary_key=True, nullable=False, autoincrement=False,
1127 info=dict(description=u"ID of the version this applies to"))
1128 item_id = Column(Integer, ForeignKey('items.id'), primary_key=True, nullable=False, autoincrement=False,
1129 info=dict(description=u"ID of the item"))
1130 rarity = Column(Integer, nullable=False,
1131 info=dict(description=u"Chance of the Pokémon holding the item, in percent"))
1132
1133 class PokemonMove(TableBase):
1134 u"""Record of a move a Pokémon can learn
1135 """
1136 __tablename__ = 'pokemon_moves'
1137 pokemon_id = Column(Integer, ForeignKey('pokemon.id'), nullable=False, index=True,
1138 info=dict(description=u"ID of the Pokémon"))
1139 version_group_id = Column(Integer, ForeignKey('version_groups.id'), nullable=False, index=True,
1140 info=dict(description=u"ID of the version group this applies to"))
1141 move_id = Column(Integer, ForeignKey('moves.id'), nullable=False, index=True,
1142 info=dict(description=u"ID of the move"))
1143 pokemon_move_method_id = Column(Integer, ForeignKey('pokemon_move_methods.id'), nullable=False, index=True,
1144 info=dict(description=u"ID of the method this move is learned by"))
1145 level = Column(Integer, nullable=True, index=True,
1146 info=dict(description=u"Level the move is learned at, if applicable"))
1147 order = Column(Integer, nullable=True,
1148 info=dict(description=u"A sort key to produce the correct ordering when all else is equal")) # XXX: This needs a better description
1149
1150 __table_args__ = (
1151 PrimaryKeyConstraint('pokemon_id', 'version_group_id', 'move_id', 'pokemon_move_method_id', 'level'),
1152 {},
1153 )
1154
1155 class PokemonMoveMethod(TableBase):
1156 u"""A method a move can be learned by, such as "Level up" or "Tutor".
1157 """
1158 __tablename__ = 'pokemon_move_methods'
1159 id = Column(Integer, primary_key=True, nullable=False, autoincrement=False,
1160 info=dict(description=u"A numeric ID"))
1161 name = Column(Unicode(64), nullable=False,
1162 info=dict(description=u"An English name of the method", format='plaintext'))
1163 description = Column(Unicode(255), nullable=False,
1164 info=dict(description=u"A detailed description of how the method works", format='plaintext'))
1165
1166 class PokemonName(TableBase):
1167 u"""A non-English name of a Pokémon.
1168 """
1169 __tablename__ = 'pokemon_names'
1170 pokemon_id = Column(Integer, ForeignKey('pokemon.id'), primary_key=True, nullable=False, autoincrement=False,
1171 info=dict(description=u"ID of the Pokémon"))
1172 language_id = Column(Integer, ForeignKey('languages.id'), primary_key=True, nullable=False, autoincrement=False,
1173 info=dict(description=u"ID of the language"))
1174 name = Column(Unicode(16), nullable=False,
1175 info=dict(description=u"Name of the Pokémon in the language", foreign=True, format='plaintext'))
1176
1177 class PokemonShape(TableBase):
1178 u"""The shape of a Pokémon's body, as used in generation IV Pokédexes.
1179 """
1180 __tablename__ = 'pokemon_shapes'
1181 id = Column(Integer, primary_key=True, nullable=False,
1182 info=dict(description=u"A numeric ID"))
1183 name = Column(Unicode(24), nullable=False,
1184 info=dict(description=u"A boring English name of the body shape", format='plaintext'))
1185 awesome_name = Column(Unicode(16), nullable=False,
1186 info=dict(description=u"A splendiferous, technically English, name of the body shape", format='plaintext'))
1187
1188 class PokemonStat(TableBase):
1189 u"""A stat value of a Pokémon
1190 """
1191 __tablename__ = 'pokemon_stats'
1192 pokemon_id = Column(Integer, ForeignKey('pokemon.id'), primary_key=True, nullable=False, autoincrement=False,
1193 info=dict(description=u"ID of the Pokémon"))
1194 stat_id = Column(Integer, ForeignKey('stats.id'), primary_key=True, nullable=False, autoincrement=False,
1195 info=dict(description=u"ID of the stat"))
1196 base_stat = Column(Integer, nullable=False,
1197 info=dict(description=u"The base stat"))
1198 effort = Column(Integer, nullable=False,
1199 info=dict(description=u"The effort increase in this stat gained when this Pokémon is defeated"))
1200
1201 class PokemonType(TableBase):
1202 u"""Maps a type to a Pokémon. Each Pokémon has 1 or 2 types.
1203 """
1204 __tablename__ = 'pokemon_types'
1205 pokemon_id = Column(Integer, ForeignKey('pokemon.id'), primary_key=True, nullable=False, autoincrement=False,
1206 info=dict(description=u"ID of the Pokémon"))
1207 type_id = Column(Integer, ForeignKey('types.id'), nullable=False,
1208 info=dict(description=u"ID of the type"))
1209 slot = Column(Integer, primary_key=True, nullable=False, autoincrement=False,
1210 info=dict(description=u"The type's slot, 1 or 2, used to sort types if there are two of them"))
1211
1212 class Region(TableBase):
1213 u"""Major areas of the world: Kanto, Johto, etc.
1214 """
1215 __tablename__ = 'regions'
1216 id = Column(Integer, primary_key=True, nullable=False,
1217 info=dict(description=u"A numeric ID"))
1218 name = Column(Unicode(16), nullable=False,
1219 info=dict(description=u"The English name of the region", official=True, format='plaintext'))
1220
1221 class Stat(TableBase):
1222 u"""A Stat, such as Attack or Speed
1223 """
1224 __tablename__ = 'stats'
1225 id = Column(Integer, primary_key=True, nullable=False,
1226 info=dict(description=u"A numeric ID"))
1227 damage_class_id = Column(Integer, ForeignKey('move_damage_classes.id'), nullable=True,
1228 info=dict(description=u"For offensive and defensive stats, the damage this stat relates to; otherwise None (the NULL value)"))
1229 name = Column(Unicode(16), nullable=False,
1230 info=dict(description=u"The English name of the stat", official=True, format='plaintext'))
1231
1232 class SuperContestCombo(TableBase):
1233 u"""Combo of two moves in a Super Contest.
1234 """
1235 __tablename__ = 'super_contest_combos'
1236 first_move_id = Column(Integer, ForeignKey('moves.id'), primary_key=True, nullable=False, autoincrement=False,
1237 info=dict(description=u"The ID of the first move in the combo."))
1238 second_move_id = Column(Integer, ForeignKey('moves.id'), primary_key=True, nullable=False, autoincrement=False,
1239 info=dict(description=u"The ID of the second and last move."))
1240
1241 class SuperContestEffect(TableBase):
1242 u"""An effect a move can have when used in the Super Contest
1243 """
1244 __tablename__ = 'super_contest_effects'
1245 id = Column(Integer, primary_key=True, nullable=False,
1246 info=dict(description=u"This effect's unique ID."))
1247 appeal = Column(SmallInteger, nullable=False,
1248 info=dict(description=u"The number of hearts the user gains."))
1249 flavor_text = Column(Unicode(64), nullable=False,
1250 info=dict(description=u"An English description of the effect.", format='plaintext'))
1251
1252 class TypeEfficacy(TableBase):
1253 u"""The damage multiplier used when a move of a particular type damages a
1254 Pokémon of a particular other type.
1255 """
1256 __tablename__ = 'type_efficacy'
1257 damage_type_id = Column(Integer, ForeignKey('types.id'), primary_key=True, nullable=False, autoincrement=False,
1258 info=dict(description=u"The ID of the damaging type."))
1259 target_type_id = Column(Integer, ForeignKey('types.id'), primary_key=True, nullable=False, autoincrement=False,
1260 info=dict(description=u"The ID of the defending Pokémon's type."))
1261 damage_factor = Column(Integer, nullable=False,
1262 info=dict(description=u"The multiplier, as a percentage of damage inflicted."))
1263
1264 class Type(TableBase):
1265 u"""Any of the elemental types Pokémon and moves can have."""
1266 __tablename__ = 'types'
1267 __singlename__ = 'type'
1268 id = Column(Integer, primary_key=True, nullable=False,
1269 info=dict(description=u"A unique ID for this type."))
1270 name = Column(Unicode(8), nullable=False,
1271 info=dict(description=u"This type's English name.", format='plaintext'))
1272 abbreviation = Column(Unicode(3), nullable=False,
1273 info=dict(description=u"An arbitrary 3-letter abbreviation of this type.", format='plaintext')) # XXX: Or is it not arbitrary?
1274 generation_id = Column(Integer, ForeignKey('generations.id'), nullable=False,
1275 info=dict(description=u"The ID of the generation this type first appeared in."))
1276 damage_class_id = Column(Integer, ForeignKey('move_damage_classes.id'), nullable=False,
1277 info=dict(description=u"The ID of the damage class this type's moves had before Generation IV."))
1278
1279 class TypeName(TableBase):
1280 u"""An official non-English name of an elemental type."""
1281 __tablename__ = 'type_names'
1282 type_id = Column(Integer, ForeignKey('types.id'), primary_key=True, nullable=False, autoincrement=False,
1283 info=dict(description=u"The ID of the type."))
1284 language_id = Column(Integer, ForeignKey('languages.id'), primary_key=True, nullable=False, autoincrement=False,
1285 info=dict(description=u"The ID of the language."))
1286 name = Column(Unicode(16), nullable=False,
1287 info=dict(description=u"The name of the type in this language.", foreign=True, format='plaintext'))
1288
1289 class VersionGroup(TableBase):
1290 u"""A group of versions, containing either two paired versions (such as Red
1291 and Blue) or a single game (such as Yellow.)
1292 """
1293 __tablename__ = 'version_groups'
1294 id = Column(Integer, primary_key=True, nullable=False,
1295 info=dict(description=u"This version group's unique ID."))
1296 generation_id = Column(Integer, ForeignKey('generations.id'), nullable=False,
1297 info=dict(description=u"The ID of the generation the games in this group belong to."))
1298 pokedex_id = Column(Integer, ForeignKey('pokedexes.id'), nullable=False,
1299 info=dict(description=u"The ID of the regional Pokédex used in this version group."))
1300
1301 class VersionGroupRegion(TableBase):
1302 u"""Maps a version group to a region that appears in it."""
1303 __tablename__ = 'version_group_regions'
1304 version_group_id = Column(Integer, ForeignKey('version_groups.id'), primary_key=True, nullable=False,
1305 info=dict(description=u"The ID of the version group."))
1306 region_id = Column(Integer, ForeignKey('regions.id'), primary_key=True, nullable=False,
1307 info=dict(description=u"The ID of the region."))
1308
1309 class Version(TableBase):
1310 u"""An individual main-series Pokémon game."""
1311 __tablename__ = 'versions'
1312 id = Column(Integer, primary_key=True, nullable=False,
1313 info=dict(description=u"A unique ID for this version."))
1314 version_group_id = Column(Integer, ForeignKey('version_groups.id'), nullable=False,
1315 info=dict(description=u"The ID of the version group this game belongs to."))
1316 name = Column(Unicode(32), nullable=False,
1317 info=dict(description=u'The English "version" name for this game, e.g. "Red", without the rest of the title.', official=True, format='plaintext'))
1318
1319
1320 ### Relations down here, to avoid ordering problems
1321 Ability.changelog = relation(AbilityChangelog,
1322 order_by=AbilityChangelog.changed_in_version_group_id.desc(),
1323 backref='ability',
1324 )
1325 Ability.flavor_text = relation(AbilityFlavorText, order_by=AbilityFlavorText.version_group_id, backref='ability')
1326 Ability.foreign_names = relation(AbilityName, backref='ability')
1327 Ability.generation = relation(Generation, backref='abilities')
1328 Ability.all_pokemon = relation(Pokemon,
1329 secondary=PokemonAbility.__table__,
1330 back_populates='all_abilities',
1331 )
1332 Ability.pokemon = relation(Pokemon,
1333 secondary=PokemonAbility.__table__,
1334 primaryjoin=and_(
1335 PokemonAbility.ability_id == Ability.id,
1336 PokemonAbility.is_dream == False
1337 ),
1338 back_populates='abilities',
1339 )
1340 Ability.dream_pokemon = relation(Pokemon,
1341 secondary=PokemonAbility.__table__,
1342 primaryjoin=and_(
1343 PokemonAbility.ability_id == Ability.id,
1344 PokemonAbility.is_dream == True
1345 ),
1346 back_populates='dream_ability',
1347 )
1348
1349 AbilityChangelog.changed_in = relation(VersionGroup, backref='ability_changelog')
1350
1351 AbilityFlavorText.version_group = relation(VersionGroup)
1352
1353 AbilityName.language = relation(Language)
1354
1355 Berry.berry_firmness = relation(BerryFirmness, backref='berries')
1356 Berry.firmness = association_proxy('berry_firmness', 'name')
1357 Berry.flavors = relation(BerryFlavor, order_by=BerryFlavor.contest_type_id, backref='berry')
1358 Berry.natural_gift_type = relation(Type)
1359
1360 BerryFlavor.contest_type = relation(ContestType)
1361
1362 ContestCombo.first = relation(Move, primaryjoin=ContestCombo.first_move_id==Move.id,
1363 backref='contest_combo_first')
1364 ContestCombo.second = relation(Move, primaryjoin=ContestCombo.second_move_id==Move.id,
1365 backref='contest_combo_second')
1366
1367 Encounter.location_area = relation(LocationArea, backref='encounters')
1368 Encounter.pokemon = relation(Pokemon, backref='encounters')
1369 Encounter.version = relation(Version, backref='encounters')
1370 Encounter.slot = relation(EncounterSlot, backref='encounters')
1371
1372 EncounterConditionValue.condition = relation(EncounterCondition, backref='values')
1373
1374 Encounter.condition_value_map = relation(EncounterConditionValueMap, backref='encounter')
1375 Encounter.condition_values = association_proxy('condition_value_map', 'condition_value')
1376 EncounterConditionValueMap.condition_value = relation(EncounterConditionValue,
1377 backref='encounter_map')
1378
1379 EncounterSlot.terrain = relation(EncounterTerrain, backref='slots')
1380 EncounterSlot.version_group = relation(VersionGroup)
1381
1382 EncounterSlot.condition_map = relation(EncounterSlotCondition, backref='slot')
1383 EncounterSlot.conditions = association_proxy('condition_map', 'condition')
1384 EncounterSlotCondition.condition = relation(EncounterCondition,
1385 backref='slot_map')
1386
1387 EvolutionChain.growth_rate = relation(GrowthRate, backref='evolution_chains')
1388 EvolutionChain.baby_trigger_item = relation(Item, backref='evolution_chains')
1389 EvolutionChain.pokemon = relation(Pokemon, order_by=Pokemon.order, back_populates='evolution_chain')
1390
1391 Experience.growth_rate = relation(GrowthRate, backref='experience_table')
1392
1393 Generation.canonical_pokedex = relation(Pokedex, backref='canonical_for_generation')
1394 Generation.versions = relation(Version, secondary=VersionGroup.__table__)
1395 Generation.main_region = relation(Region)
1396
1397 GrowthRate.max_experience_obj = relation(Experience, primaryjoin=and_(Experience.growth_rate_id == GrowthRate.id, Experience.level == 100), uselist=False)
1398 GrowthRate.max_experience = association_proxy('max_experience_obj', 'experience')
1399
1400 Item.berry = relation(Berry, uselist=False, backref='item')
1401 Item.flags = relation(ItemFlag, secondary=ItemFlagMap.__table__)
1402 Item.flavor_text = relation(ItemFlavorText, order_by=ItemFlavorText.version_group_id.asc(), backref='item')
1403 Item.fling_effect = relation(ItemFlingEffect, backref='items')
1404 Item.foreign_names = relation(ItemName, backref='item')
1405 Item.machines = relation(Machine, order_by=Machine.version_group_id.asc())
1406 Item.category = relation(ItemCategory)
1407 Item.pocket = association_proxy('category', 'pocket')
1408
1409 ItemCategory.items = relation(Item, order_by=Item.name)
1410 ItemCategory.pocket = relation(ItemPocket)
1411
1412 ItemFlavorText.version_group = relation(VersionGroup)
1413
1414 ItemInternalID.item = relation(Item, backref='internal_ids')
1415 ItemInternalID.generation = relation(Generation)
1416
1417 ItemName.language = relation(Language)
1418
1419 ItemPocket.categories = relation(ItemCategory, order_by=ItemCategory.name)
1420
1421 Location.region = relation(Region, backref='locations')
1422
1423 LocationArea.location = relation(Location, backref='areas')
1424
1425 LocationInternalID.location = relation(Location, backref='internal_ids')
1426 LocationInternalID.generation = relation(Generation)
1427
1428 Machine.item = relation(Item)
1429 Machine.version_group = relation(VersionGroup)
1430
1431 Move.changelog = relation(MoveChangelog,
1432 order_by=MoveChangelog.changed_in_version_group_id.desc(),
1433 backref='move',
1434 )
1435 Move.contest_effect = relation(ContestEffect, backref='moves')
1436 Move.contest_combo_next = association_proxy('contest_combo_first', 'second')
1437 Move.contest_combo_prev = association_proxy('contest_combo_second', 'first')
1438 Move.contest_type = relation(ContestType, backref='moves')
1439 Move.damage_class = relation(MoveDamageClass, backref='moves')
1440 Move.flags = association_proxy('move_flags', 'flag')
1441 Move.flavor_text = relation(MoveFlavorText, order_by=MoveFlavorText.version_group_id, backref='move')
1442 Move.foreign_names = relation(MoveName, backref='move')
1443 Move.generation = relation(Generation, backref='moves')
1444 Move.machines = relation(Machine, backref='move')
1445 Move.move_effect = relation(MoveEffect, backref='moves')
1446 Move.move_flags = relation(MoveFlag, backref='move')
1447 Move.super_contest_effect = relation(SuperContestEffect, backref='moves')
1448 Move.super_contest_combo_next = association_proxy('super_contest_combo_first', 'second')
1449 Move.super_contest_combo_prev = association_proxy('super_contest_combo_second', 'first')
1450 Move.target = relation(MoveTarget, backref='moves')
1451 Move.type = relation(Type, backref='moves')
1452
1453 Move.effect = markdown.MoveEffectProperty('effect')
1454 Move.short_effect = markdown.MoveEffectProperty('short_effect')
1455
1456 MoveChangelog.changed_in = relation(VersionGroup, backref='move_changelog')
1457 MoveChangelog.move_effect = relation(MoveEffect, backref='move_changelog')
1458 MoveChangelog.type = relation(Type, backref='move_changelog')
1459
1460 MoveChangelog.effect = markdown.MoveEffectProperty('effect')
1461 MoveChangelog.short_effect = markdown.MoveEffectProperty('short_effect')
1462
1463 MoveEffect.category_map = relation(MoveEffectCategoryMap)
1464 MoveEffect.categories = association_proxy('category_map', 'category')
1465 MoveEffectCategoryMap.category = relation(MoveEffectCategory)
1466
1467 MoveFlag.flag = relation(MoveFlagType)
1468
1469 MoveFlavorText.version_group = relation(VersionGroup)
1470
1471 MoveName.language = relation(Language)
1472
1473 Nature.foreign_names = relation(NatureName, backref='nature')
1474 Nature.decreased_stat = relation(Stat, primaryjoin=Nature.decreased_stat_id==Stat.id,
1475 backref='decreasing_natures')
1476 Nature.increased_stat = relation(Stat, primaryjoin=Nature.increased_stat_id==Stat.id,
1477 backref='increasing_natures')
1478 Nature.hates_flavor = relation(ContestType, primaryjoin=Nature.hates_flavor_id==ContestType.id,
1479 backref='hating_natures')
1480 Nature.likes_flavor = relation(ContestType, primaryjoin=Nature.likes_flavor_id==ContestType.id,
1481 backref='liking_natures')
1482 Nature.battle_style_preferences = relation(NatureBattleStylePreference,
1483 order_by=NatureBattleStylePreference.move_battle_style_id,
1484 backref='nature')
1485 Nature.pokeathlon_effects = relation(NaturePokeathlonStat, order_by=NaturePokeathlonStat.pokeathlon_stat_id)
1486
1487 NatureBattleStylePreference.battle_style = relation(MoveBattleStyle, backref='nature_preferences')
1488
1489 NatureName.language = relation(Language)
1490
1491 NaturePokeathlonStat.pokeathlon_stat = relation(PokeathlonStat, backref='nature_effects')
1492
1493 Pokedex.region = relation(Region, backref='pokedexes')
1494 Pokedex.version_groups = relation(VersionGroup, order_by=VersionGroup.id, back_populates='pokedex')
1495
1496 Pokemon.all_abilities = relation(Ability,
1497 secondary=PokemonAbility.__table__,
1498 order_by=PokemonAbility.slot,
1499 )
1500 Pokemon.abilities = relation(Ability,
1501 secondary=PokemonAbility.__table__,
1502 primaryjoin=and_(
1503 Pokemon.id == PokemonAbility.pokemon_id,
1504 PokemonAbility.is_dream == False,
1505 ),
1506 order_by=PokemonAbility.slot,
1507 )
1508 Pokemon.dream_ability = relation(Ability,
1509 secondary=PokemonAbility.__table__,
1510 primaryjoin=and_(
1511 Pokemon.id == PokemonAbility.pokemon_id,
1512 PokemonAbility.is_dream == True,
1513 ),
1514 uselist=False,
1515 )
1516 Pokemon.pokemon_color = relation(PokemonColor, backref='pokemon')
1517 Pokemon.color = association_proxy('pokemon_color', 'name')
1518 Pokemon.dex_numbers = relation(PokemonDexNumber, order_by=PokemonDexNumber.pokedex_id.asc(), backref='pokemon')
1519 Pokemon.egg_groups = relation(EggGroup, secondary=PokemonEggGroup.__table__,
1520 order_by=PokemonEggGroup.egg_group_id,
1521 backref=backref('pokemon', order_by=Pokemon.order))
1522 Pokemon.evolution_chain = relation(EvolutionChain, back_populates='pokemon')
1523 Pokemon.child_pokemon = relation(Pokemon,
1524 primaryjoin=Pokemon.id==PokemonEvolution.from_pokemon_id,
1525 secondary=PokemonEvolution.__table__,
1526 secondaryjoin=PokemonEvolution.to_pokemon_id==Pokemon.id,
1527 backref=backref('parent_pokemon', uselist=False),
1528 )
1529 Pokemon.flavor_text = relation(PokemonFlavorText, order_by=PokemonFlavorText.version_id.asc(), backref='pokemon')
1530 Pokemon.foreign_names = relation(PokemonName, backref='pokemon')
1531 Pokemon.forms = relation(PokemonForm, primaryjoin=Pokemon.id==PokemonForm.form_base_pokemon_id,
1532 order_by=(PokemonForm.order.asc(), PokemonForm.name.asc()))
1533 Pokemon.default_form = relation(PokemonForm,
1534 primaryjoin=and_(Pokemon.id==PokemonForm.form_base_pokemon_id, PokemonForm.is_default==True),
1535 uselist=False,
1536 )
1537 Pokemon.pokemon_habitat = relation(PokemonHabitat, backref='pokemon')
1538 Pokemon.habitat = association_proxy('pokemon_habitat', 'name')
1539 Pokemon.items = relation(PokemonItem, backref='pokemon')
1540 Pokemon.generation = relation(Generation, backref='pokemon')
1541 Pokemon.shape = relation(PokemonShape, backref='pokemon')
1542 Pokemon.stats = relation(PokemonStat, backref='pokemon', order_by=PokemonStat.stat_id.asc())
1543 Pokemon.types = relation(Type, secondary=PokemonType.__table__,
1544 order_by=PokemonType.slot.asc(),
1545 back_populates='pokemon')
1546
1547 PokemonDexNumber.pokedex = relation(Pokedex)
1548
1549 PokemonEvolution.from_pokemon = relation(Pokemon,
1550 primaryjoin=PokemonEvolution.from_pokemon_id==Pokemon.id,
1551 backref='child_evolutions',
1552 )
1553 PokemonEvolution.to_pokemon = relation(Pokemon,
1554 primaryjoin=PokemonEvolution.to_pokemon_id==Pokemon.id,
1555 backref=backref('parent_evolution', uselist=False),
1556 )
1557 PokemonEvolution.child_evolutions = relation(PokemonEvolution,
1558 primaryjoin=PokemonEvolution.from_pokemon_id==PokemonEvolution.to_pokemon_id,
1559 foreign_keys=[PokemonEvolution.to_pokemon_id],
1560 backref=backref('parent_evolution',
1561 remote_side=[PokemonEvolution.from_pokemon_id],
1562 uselist=False,
1563 ),
1564 )
1565 PokemonEvolution.trigger = relation(EvolutionTrigger, backref='evolutions')
1566 PokemonEvolution.trigger_item = relation(Item,
1567 primaryjoin=PokemonEvolution.trigger_item_id==Item.id,
1568 backref='triggered_evolutions',
1569 )
1570 PokemonEvolution.held_item = relation(Item,
1571 primaryjoin=PokemonEvolution.held_item_id==Item.id,
1572 backref='required_for_evolutions',
1573 )
1574 PokemonEvolution.location = relation(Location, backref='triggered_evolutions')
1575 PokemonEvolution.known_move = relation(Move, backref='triggered_evolutions')
1576 PokemonEvolution.party_pokemon = relation(Pokemon,
1577 primaryjoin=PokemonEvolution.party_pokemon_id==Pokemon.id,
1578 backref='triggered_evolutions',
1579 )
1580 PokemonEvolution.trade_pokemon = relation(Pokemon,
1581 primaryjoin=PokemonEvolution.trade_pokemon_id==Pokemon.id,
1582 )
1583
1584 PokemonFlavorText.version = relation(Version)
1585
1586 PokemonForm.form_base_pokemon = relation(Pokemon, primaryjoin=PokemonForm.form_base_pokemon_id==Pokemon.id)
1587 PokemonForm.unique_pokemon = relation(Pokemon, backref=backref('unique_form', uselist=False),
1588 primaryjoin=PokemonForm.unique_pokemon_id==Pokemon.id)
1589 PokemonForm.version_group = relation(VersionGroup)
1590 PokemonForm.form_group = association_proxy('form_base_pokemon', 'form_group')
1591 PokemonForm.pokeathlon_stats = relation(PokemonFormPokeathlonStat,
1592 order_by=PokemonFormPokeathlonStat.pokeathlon_stat_id,
1593 backref='pokemon_form')
1594
1595 PokemonFormGroup.pokemon = relation(Pokemon, backref=backref('form_group',
1596 uselist=False))
1597
1598 PokemonFormPokeathlonStat.pokeathlon_stat = relation(PokeathlonStat)
1599
1600 PokemonItem.item = relation(Item, backref='pokemon')
1601 PokemonItem.version = relation(Version)
1602
1603 PokemonMove.pokemon = relation(Pokemon, backref='pokemon_moves')
1604 PokemonMove.version_group = relation(VersionGroup)
1605 PokemonMove.machine = relation(Machine, backref='pokemon_moves',
1606 primaryjoin=and_(Machine.version_group_id==PokemonMove.version_group_id,
1607 Machine.move_id==PokemonMove.move_id),
1608 foreign_keys=[Machine.version_group_id, Machine.move_id],
1609 uselist=False)
1610 PokemonMove.move = relation(Move, backref='pokemon_moves')
1611 PokemonMove.method = relation(PokemonMoveMethod)
1612
1613 PokemonName.language = relation(Language, lazy='joined')
1614
1615 PokemonStat.stat = relation(Stat)
1616
1617 # This is technically a has-many; Generation.main_region_id -> Region.id
1618 Region.generation = relation(Generation, uselist=False)
1619 Region.version_group_regions = relation(VersionGroupRegion, backref='region',
1620 order_by='VersionGroupRegion.version_group_id')
1621 Region.version_groups = association_proxy('version_group_regions', 'version_group')
1622
1623 Stat.damage_class = relation(MoveDamageClass, backref='stats')
1624
1625 SuperContestCombo.first = relation(Move, primaryjoin=SuperContestCombo.first_move_id==Move.id,
1626 backref='super_contest_combo_first')
1627 SuperContestCombo.second = relation(Move, primaryjoin=SuperContestCombo.second_move_id==Move.id,
1628 backref='super_contest_combo_second')
1629
1630 Type.damage_efficacies = relation(TypeEfficacy,
1631 primaryjoin=Type.id
1632 ==TypeEfficacy.damage_type_id,
1633 backref='damage_type')
1634 Type.target_efficacies = relation(TypeEfficacy,
1635 primaryjoin=Type.id
1636 ==TypeEfficacy.target_type_id,
1637 backref='target_type')
1638
1639 Type.generation = relation(Generation, backref='types')
1640 Type.damage_class = relation(MoveDamageClass, backref='types')
1641 Type.foreign_names = relation(TypeName, backref='type')
1642 Type.pokemon = relation(Pokemon, secondary=PokemonType.__table__,
1643 order_by=Pokemon.order,
1644 back_populates='types')
1645
1646 TypeName.language = relation(Language)
1647
1648 Version.version_group = relation(VersionGroup, back_populates='versions')
1649 Version.generation = association_proxy('version_group', 'generation')
1650
1651 VersionGroup.versions = relation(Version, order_by=Version.id, back_populates='version_group')
1652 VersionGroup.generation = relation(Generation, backref='version_groups')
1653 VersionGroup.version_group_regions = relation(VersionGroupRegion, backref='version_group')
1654 VersionGroup.regions = association_proxy('version_group_regions', 'region')
1655 VersionGroup.pokedex = relation(Pokedex, back_populates='version_groups')