cdddd30743dd8b7d7fef1fab43c631dc547374c3
[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_gen4_fem_sprite = Column(Boolean, nullable=False,
842 info=dict(description=u"Set iff the species' female front sprite is different from the male's in generation IV"))
843 has_gen4_fem_back_sprite = Column(Boolean, nullable=False,
844 info=dict(description=u"Set iff the species' female back sprite is different from the male's in generation IV"))
845 order = Column(Integer, nullable=False, index=True,
846 info=dict(description=u"Order for sorting. Almost national order, except families and forms are grouped together."))
847
848 ### Stuff to handle alternate Pokémon forms
849
850 @property
851 def is_base_form(self):
852 u"""Returns True iff the Pokémon is the base form for its species,
853 e.g. Land Shaymin.
854 """
855
856 return self.unique_form is None or self.unique_form.is_default
857
858 @property
859 def form_name(self):
860 u"""Returns the Pokémon's form name if it represents a particular form
861 and that form has a name, or None otherwise.
862 """
863
864 # If self.unique_form is None, the short-circuit "and" will go ahead
865 # and return that. Otherwise, it'll return the form's name, which may
866 # also be None.
867 return self.unique_form and self.unique_form.name
868
869 @property
870 def full_name(self):
871 u"""Returns the Pokémon's name, including its form if applicable."""
872
873 if self.form_name:
874 return '{0} {1}'.format(self.form_name, self.name)
875 else:
876 return self.name
877
878 @property
879 def normal_form(self):
880 u"""Returns the normal form for this Pokémon; i.e., this will return
881 regular Deoxys when called on any Deoxys form.
882 """
883
884 if self.unique_form:
885 return self.unique_form.form_base_pokemon
886 return self
887
888 ### Not forms!
889
890 def stat(self, stat_name):
891 u"""Returns a PokemonStat record for the given stat name (or Stat row
892 object). Uses the normal has-many machinery, so all the stats are
893 effectively cached.
894 """
895 if isinstance(stat_name, Stat):
896 stat_name = stat_name.name
897
898 for pokemon_stat in self.stats:
899 if pokemon_stat.stat.name == stat_name:
900 return pokemon_stat
901
902 raise KeyError(u'No stat named %s' % stat_name)
903
904 @property
905 def better_damage_class(self):
906 u"""Returns the MoveDamageClass that this Pokémon is best suited for,
907 based on its attack stats.
908
909 If the attack stats are about equal (within 5), returns None. The
910 value None, not the damage class called 'None'.
911 """
912 phys = self.stat(u'Attack')
913 spec = self.stat(u'Special Attack')
914
915 diff = phys.base_stat - spec.base_stat
916
917 if diff > 5:
918 return phys.stat.damage_class
919 elif diff < -5:
920 return spec.stat.damage_class
921 else:
922 return None
923
924 class PokemonAbility(TableBase):
925 u"""Maps an ability to a Pokémon that can have it
926 """
927 __tablename__ = 'pokemon_abilities'
928 pokemon_id = Column(Integer, ForeignKey('pokemon.id'), primary_key=True, nullable=False, autoincrement=False,
929 info=dict(description=u"ID of the Pokémon"))
930 ability_id = Column(Integer, ForeignKey('abilities.id'), nullable=False,
931 info=dict(description=u"ID of the ability"))
932 # XXX having both a method and a slot is kind of gross. "slot" is a
933 # misnomer, anyway: duplicate abilities don't appear in slot 2.
934 # Probably should replace that with "order".
935 is_dream = Column(Boolean, nullable=False, index=True,
936 info=dict(description=u"Whether this is a Dream World ability"))
937 slot = Column(Integer, primary_key=True, nullable=False, autoincrement=False,
938 info=dict(description=u"The ability slot, i.e. 1 or 2 for gen. IV"))
939
940 class PokemonColor(TableBase):
941 u"""The "Pokédex color" of a Pokémon species. Usually based on the Pokémon's color.
942 """
943 __tablename__ = 'pokemon_colors'
944 id = Column(Integer, primary_key=True, nullable=False, autoincrement=False,
945 info=dict(description=u"ID of the Pokémon"))
946 name = Column(Unicode(6), nullable=False,
947 info=dict(description=u"The English name of the color", official=True, format='identifier'))
948
949 class PokemonDexNumber(TableBase):
950 u"""The number of a Pokémon in a particular Pokédex (e.g. Jigglypuff is #138 in Hoenn's 'dex)
951 """
952 __tablename__ = 'pokemon_dex_numbers'
953 pokemon_id = Column(Integer, ForeignKey('pokemon.id'), primary_key=True, nullable=False, autoincrement=False,
954 info=dict(description=u"ID of the Pokémon"))
955 pokedex_id = Column(Integer, ForeignKey('pokedexes.id'), primary_key=True, nullable=False, autoincrement=False,
956 info=dict(description=u"ID of the Pokédex"))
957 pokedex_number = Column(Integer, nullable=False,
958 info=dict(description=u"Number of the Pokémon in that the Pokédex"))
959
960 class PokemonEggGroup(TableBase):
961 u"""Maps an Egg group to a Pokémon; each Pokémon belongs to one or two egg groups
962 """
963 __tablename__ = 'pokemon_egg_groups'
964 pokemon_id = Column(Integer, ForeignKey('pokemon.id'), primary_key=True, nullable=False, autoincrement=False,
965 info=dict(description=u"ID of the Pokémon"))
966 egg_group_id = Column(Integer, ForeignKey('egg_groups.id'), primary_key=True, nullable=False, autoincrement=False,
967 info=dict(description=u"ID of the egg group"))
968
969 class PokemonEvolution(TableBase):
970 u"""A required action ("trigger") and the conditions under which the trigger
971 must occur to cause a Pokémon to evolve.
972
973 Any condition may be null if it does not apply for a particular Pokémon.
974 """
975 __tablename__ = 'pokemon_evolution'
976 from_pokemon_id = Column(Integer, ForeignKey('pokemon.id'), nullable=False,
977 info=dict(description=u"The ID of the pre-evolution Pokémon."))
978 to_pokemon_id = Column(Integer, ForeignKey('pokemon.id'), primary_key=True, nullable=False, autoincrement=False,
979 info=dict(description=u"The ID of the post-evolution Pokémon."))
980 evolution_trigger_id = Column(Integer, ForeignKey('evolution_triggers.id'), nullable=False,
981 info=dict(description=u"The ID of the evolution trigger."))
982 trigger_item_id = Column(Integer, ForeignKey('items.id'), nullable=True,
983 info=dict(description=u"The ID of the item that must be used on the Pokémon."))
984 minimum_level = Column(Integer, nullable=True,
985 info=dict(description=u"The minimum level for the Pokémon."))
986 gender = Column(Enum('male', 'female', name='pokemon_evolution_gender'), nullable=True,
987 info=dict(description=u"The Pokémon's required gender, or None if gender doesn't matter"))
988 location_id = Column(Integer, ForeignKey('locations.id'), nullable=True,
989 info=dict(description=u"The ID of the location the evolution must be triggered at."))
990 held_item_id = Column(Integer, ForeignKey('items.id'), nullable=True,
991 info=dict(description=u"The ID of the item the Pokémon must hold."))
992 time_of_day = Column(Enum('morning', 'day', 'night', name='pokemon_evolution_time_of_day'), nullable=True,
993 info=dict(description=u"The required time of day."))
994 known_move_id = Column(Integer, ForeignKey('moves.id'), nullable=True,
995 info=dict(description=u"The ID of the move the Pokémon must know."))
996 minimum_happiness = Column(Integer, nullable=True,
997 info=dict(description=u"The minimum happiness value the Pokémon must have."))
998 minimum_beauty = Column(Integer, nullable=True,
999 info=dict(description=u"The minimum Beauty value the Pokémon must have."))
1000 relative_physical_stats = Column(Integer, nullable=True,
1001 info=dict(description=u"The required relation between the Pokémon's Attack and Defense stats, as sgn(atk-def)."))
1002 party_pokemon_id = Column(Integer, ForeignKey('pokemon.id'), nullable=True,
1003 info=dict(description=u"The ID of the Pokémon that must be present in the party."))
1004 trade_pokemon_id = Column(Integer, ForeignKey('pokemon.id'), nullable=True,
1005 info=dict(description=u"The ID of the Pokémon for which this Pokémon must be traded."))
1006
1007 class PokemonFlavorText(TableBase):
1008 u"""In-game Pokédex descrption of a Pokémon.
1009 """
1010 __tablename__ = 'pokemon_flavor_text'
1011 pokemon_id = Column(Integer, ForeignKey('pokemon.id'), primary_key=True, nullable=False, autoincrement=False,
1012 info=dict(description=u"ID of the Pokémon"))
1013 version_id = Column(Integer, ForeignKey('versions.id'), primary_key=True, nullable=False, autoincrement=False,
1014 info=dict(description=u"ID of the version that has this flavor text"))
1015 flavor_text = Column(Unicode(255), nullable=False,
1016 info=dict(description=u"ID of the version that has this flavor text", official=True, format='gametext'))
1017
1018 class PokemonForm(TableBase):
1019 u"""An individual form of a Pokémon.
1020
1021 Pokémon that do not have separate forms are still given a single row to
1022 represent their single form.
1023 """
1024 __tablename__ = 'pokemon_forms'
1025 __singlename__ = 'pokemon_form'
1026 id = Column(Integer, primary_key=True, nullable=False,
1027 info=dict(description=u'A unique ID for this form.'))
1028 name = Column(Unicode(16), nullable=True,
1029 info=dict(description=u"This form's name, e.g. \"Plant\" for Plant Cloak Burmy.", official=True, format='plaintext'))
1030 form_base_pokemon_id = Column(Integer, ForeignKey('pokemon.id'), nullable=False, autoincrement=False,
1031 info=dict(description=u'The ID of the base Pokémon for this form.'))
1032 unique_pokemon_id = Column(Integer, ForeignKey('pokemon.id'), autoincrement=False,
1033 info=dict(description=u'The ID of a Pokémon that represents specifically this form, for Pokémon with functionally-different forms like Wormadam.'))
1034 introduced_in_version_group_id = Column(Integer, ForeignKey('version_groups.id'), autoincrement=False,
1035 info=dict(description=u'The ID of the version group in which this form first appeared.'))
1036 is_default = Column(Boolean, nullable=False,
1037 info=dict(description=u'Set for exactly one form used as the default for each species.'))
1038 order = Column(Integer, nullable=False, autoincrement=False,
1039 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.'))
1040
1041 @property
1042 def full_name(self):
1043 u"""Returns the full name of this form, e.g. "Plant Cloak"."""
1044
1045 if not self.name:
1046 return None
1047 elif self.form_group and self.form_group.term:
1048 return '{0} {1}'.format(self.name, self.form_group.term)
1049 else:
1050 return self.name
1051
1052 @property
1053 def pokemon_name(self):
1054 u"""Returns the name of this Pokémon with this form, e.g. "Plant
1055 Burmy".
1056 """
1057
1058 if self.name:
1059 return '{0} {1}'.format(self.name, self.form_base_pokemon.name)
1060 else:
1061 return self.form_base_pokemon.name
1062
1063 class PokemonFormGroup(TableBase):
1064 u"""Information about a Pokémon's forms as a group."""
1065 __tablename__ = 'pokemon_form_groups'
1066 pokemon_id = Column(Integer, ForeignKey('pokemon.id'), primary_key=True, nullable=False, autoincrement=False,
1067 info=dict(description=u"ID of the base form Pokémon"))
1068 term = Column(Unicode(16), nullable=True,
1069 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'))
1070 is_battle_only = Column(Boolean, nullable=False,
1071 info=dict(description=u"Set iff the forms only change in battle"))
1072 description = Column(markdown.MarkdownColumn(1024), nullable=False,
1073 info=dict(description=u"English description of how the forms work", format='markdown'))
1074
1075 class PokemonFormPokeathlonStat(TableBase):
1076 u"""A Pokémon form's performance in one Pokéathlon stat."""
1077 __tablename__ = 'pokemon_form_pokeathlon_stats'
1078 pokemon_form_id = Column(Integer, ForeignKey('pokemon_forms.id'), primary_key=True, nullable=False, autoincrement=False,
1079 info=dict(description=u'The ID of the Pokémon form.'))
1080 pokeathlon_stat_id = Column(Integer, ForeignKey('pokeathlon_stats.id'), primary_key=True, nullable=False, autoincrement=False,
1081 info=dict(description=u'The ID of the Pokéathlon stat.'))
1082 minimum_stat = Column(Integer, nullable=False, autoincrement=False,
1083 info=dict(description=u'The minimum value for this stat for this Pokémon form.'))
1084 base_stat = Column(Integer, nullable=False, autoincrement=False,
1085 info=dict(description=u'The default value for this stat for this Pokémon form.'))
1086 maximum_stat = Column(Integer, nullable=False, autoincrement=False,
1087 info=dict(description=u'The maximum value for this stat for this Pokémon form.'))
1088
1089 class PokemonHabitat(TableBase):
1090 u"""The habitat of a Pokémon, as given in the FireRed/LeafGreen version Pokédex
1091 """
1092 __tablename__ = 'pokemon_habitats'
1093 id = Column(Integer, primary_key=True, nullable=False, autoincrement=False,
1094 info=dict(description=u"A numeric ID"))
1095 name = Column(Unicode(16), nullable=False,
1096 info=dict(description=u"The English name of the habitat", official=True, format='plaintext'))
1097
1098 class PokemonInternalID(TableBase):
1099 u"""The number of a Pokémon a game uses internally
1100 """
1101 __tablename__ = 'pokemon_internal_ids'
1102 pokemon_id = Column(Integer, ForeignKey('pokemon.id'), primary_key=True, autoincrement=False, nullable=False,
1103 info=dict(description=u"Database ID of the Pokémon"))
1104 generation_id = Column(Integer, ForeignKey('generations.id'), primary_key=True, autoincrement=False, nullable=False,
1105 info=dict(description=u"Database ID of the generation"))
1106 internal_id = Column(Integer, nullable=False,
1107 info=dict(description=u"Internal ID the generation's games use for the Pokémon"))
1108
1109 class PokemonItem(TableBase):
1110 u"""Record of an item a Pokémon can hold in the wild
1111 """
1112 __tablename__ = 'pokemon_items'
1113 pokemon_id = Column(Integer, ForeignKey('pokemon.id'), primary_key=True, nullable=False, autoincrement=False,
1114 info=dict(description=u"ID of the Pokémon"))
1115 version_id = Column(Integer, ForeignKey('versions.id'), primary_key=True, nullable=False, autoincrement=False,
1116 info=dict(description=u"ID of the version this applies to"))
1117 item_id = Column(Integer, ForeignKey('items.id'), primary_key=True, nullable=False, autoincrement=False,
1118 info=dict(description=u"ID of the item"))
1119 rarity = Column(Integer, nullable=False,
1120 info=dict(description=u"Chance of the Pokémon holding the item, in percent"))
1121
1122 class PokemonMove(TableBase):
1123 u"""Record of a move a Pokémon can learn
1124 """
1125 __tablename__ = 'pokemon_moves'
1126 pokemon_id = Column(Integer, ForeignKey('pokemon.id'), nullable=False, index=True,
1127 info=dict(description=u"ID of the Pokémon"))
1128 version_group_id = Column(Integer, ForeignKey('version_groups.id'), nullable=False, index=True,
1129 info=dict(description=u"ID of the version group this applies to"))
1130 move_id = Column(Integer, ForeignKey('moves.id'), nullable=False, index=True,
1131 info=dict(description=u"ID of the move"))
1132 pokemon_move_method_id = Column(Integer, ForeignKey('pokemon_move_methods.id'), nullable=False, index=True,
1133 info=dict(description=u"ID of the method this move is learned by"))
1134 level = Column(Integer, nullable=True, index=True,
1135 info=dict(description=u"Level the move is learned at, if applicable"))
1136 order = Column(Integer, nullable=True,
1137 info=dict(description=u"A sort key to produce the correct ordering when all else is equal")) # XXX: This needs a better description
1138
1139 __table_args__ = (
1140 PrimaryKeyConstraint('pokemon_id', 'version_group_id', 'move_id', 'pokemon_move_method_id', 'level'),
1141 {},
1142 )
1143
1144 class PokemonMoveMethod(TableBase):
1145 u"""A method a move can be learned by, such as "Level up" or "Tutor".
1146 """
1147 __tablename__ = 'pokemon_move_methods'
1148 id = Column(Integer, primary_key=True, nullable=False, autoincrement=False,
1149 info=dict(description=u"A numeric ID"))
1150 name = Column(Unicode(64), nullable=False,
1151 info=dict(description=u"An English name of the method", format='plaintext'))
1152 description = Column(Unicode(255), nullable=False,
1153 info=dict(description=u"A detailed description of how the method works", format='plaintext'))
1154
1155 class PokemonName(TableBase):
1156 u"""A non-English name of a Pokémon.
1157 """
1158 __tablename__ = 'pokemon_names'
1159 pokemon_id = Column(Integer, ForeignKey('pokemon.id'), primary_key=True, nullable=False, autoincrement=False,
1160 info=dict(description=u"ID of the Pokémon"))
1161 language_id = Column(Integer, ForeignKey('languages.id'), primary_key=True, nullable=False, autoincrement=False,
1162 info=dict(description=u"ID of the language"))
1163 name = Column(Unicode(16), nullable=False,
1164 info=dict(description=u"Name of the Pokémon in the language", foreign=True, format='plaintext'))
1165
1166 class PokemonShape(TableBase):
1167 u"""The shape of a Pokémon's body, as used in generation IV Pokédexes.
1168 """
1169 __tablename__ = 'pokemon_shapes'
1170 id = Column(Integer, primary_key=True, nullable=False,
1171 info=dict(description=u"A numeric ID"))
1172 name = Column(Unicode(24), nullable=False,
1173 info=dict(description=u"A boring English name of the body shape", format='plaintext'))
1174 awesome_name = Column(Unicode(16), nullable=False,
1175 info=dict(description=u"A splendiferous, technically English, name of the body shape", format='plaintext'))
1176
1177 class PokemonStat(TableBase):
1178 u"""A stat value of a Pokémon
1179 """
1180 __tablename__ = 'pokemon_stats'
1181 pokemon_id = Column(Integer, ForeignKey('pokemon.id'), primary_key=True, nullable=False, autoincrement=False,
1182 info=dict(description=u"ID of the Pokémon"))
1183 stat_id = Column(Integer, ForeignKey('stats.id'), primary_key=True, nullable=False, autoincrement=False,
1184 info=dict(description=u"ID of the stat"))
1185 base_stat = Column(Integer, nullable=False,
1186 info=dict(description=u"The base stat"))
1187 effort = Column(Integer, nullable=False,
1188 info=dict(description=u"The effort increase in this stat gained when this Pokémon is defeated"))
1189
1190 class PokemonType(TableBase):
1191 u"""Maps a type to a Pokémon. Each Pokémon has 1 or 2 types.
1192 """
1193 __tablename__ = 'pokemon_types'
1194 pokemon_id = Column(Integer, ForeignKey('pokemon.id'), primary_key=True, nullable=False, autoincrement=False,
1195 info=dict(description=u"ID of the Pokémon"))
1196 type_id = Column(Integer, ForeignKey('types.id'), nullable=False,
1197 info=dict(description=u"ID of the type"))
1198 slot = Column(Integer, primary_key=True, nullable=False, autoincrement=False,
1199 info=dict(description=u"The type's slot, 1 or 2, used to sort types if there are two of them"))
1200
1201 class Region(TableBase):
1202 u"""Major areas of the world: Kanto, Johto, etc.
1203 """
1204 __tablename__ = 'regions'
1205 id = Column(Integer, primary_key=True, nullable=False,
1206 info=dict(description=u"A numeric ID"))
1207 name = Column(Unicode(16), nullable=False,
1208 info=dict(description=u"The English name of the region", official=True, format='plaintext'))
1209
1210 class Stat(TableBase):
1211 u"""A Stat, such as Attack or Speed
1212 """
1213 __tablename__ = 'stats'
1214 id = Column(Integer, primary_key=True, nullable=False,
1215 info=dict(description=u"A numeric ID"))
1216 damage_class_id = Column(Integer, ForeignKey('move_damage_classes.id'), nullable=True,
1217 info=dict(description=u"For offensive and defensive stats, the damage this stat relates to; otherwise None (the NULL value)"))
1218 name = Column(Unicode(16), nullable=False,
1219 info=dict(description=u"The English name of the stat", official=True, format='plaintext'))
1220
1221 class SuperContestCombo(TableBase):
1222 u"""Combo of two moves in a Super Contest.
1223 """
1224 __tablename__ = 'super_contest_combos'
1225 first_move_id = Column(Integer, ForeignKey('moves.id'), primary_key=True, nullable=False, autoincrement=False,
1226 info=dict(description=u"The ID of the first move in the combo."))
1227 second_move_id = Column(Integer, ForeignKey('moves.id'), primary_key=True, nullable=False, autoincrement=False,
1228 info=dict(description=u"The ID of the second and last move."))
1229
1230 class SuperContestEffect(TableBase):
1231 u"""An effect a move can have when used in the Super Contest
1232 """
1233 __tablename__ = 'super_contest_effects'
1234 id = Column(Integer, primary_key=True, nullable=False,
1235 info=dict(description=u"This effect's unique ID."))
1236 appeal = Column(SmallInteger, nullable=False,
1237 info=dict(description=u"The number of hearts the user gains."))
1238 flavor_text = Column(Unicode(64), nullable=False,
1239 info=dict(description=u"An English description of the effect.", format='plaintext'))
1240
1241 class TypeEfficacy(TableBase):
1242 u"""The damage multiplier used when a move of a particular type damages a
1243 Pokémon of a particular other type.
1244 """
1245 __tablename__ = 'type_efficacy'
1246 damage_type_id = Column(Integer, ForeignKey('types.id'), primary_key=True, nullable=False, autoincrement=False,
1247 info=dict(description=u"The ID of the damaging type."))
1248 target_type_id = Column(Integer, ForeignKey('types.id'), primary_key=True, nullable=False, autoincrement=False,
1249 info=dict(description=u"The ID of the defending Pokémon's type."))
1250 damage_factor = Column(Integer, nullable=False,
1251 info=dict(description=u"The multiplier, as a percentage of damage inflicted."))
1252
1253 class Type(TableBase):
1254 u"""Any of the elemental types Pokémon and moves can have."""
1255 __tablename__ = 'types'
1256 __singlename__ = 'type'
1257 id = Column(Integer, primary_key=True, nullable=False,
1258 info=dict(description=u"A unique ID for this type."))
1259 name = Column(Unicode(8), nullable=False,
1260 info=dict(description=u"This type's English name.", format='plaintext'))
1261 abbreviation = Column(Unicode(3), nullable=False,
1262 info=dict(description=u"An arbitrary 3-letter abbreviation of this type.", format='plaintext')) # XXX: Or is it not arbitrary?
1263 generation_id = Column(Integer, ForeignKey('generations.id'), nullable=False,
1264 info=dict(description=u"The ID of the generation this type first appeared in."))
1265 damage_class_id = Column(Integer, ForeignKey('move_damage_classes.id'), nullable=False,
1266 info=dict(description=u"The ID of the damage class this type's moves had before Generation IV."))
1267
1268 class TypeName(TableBase):
1269 u"""An official non-English name of an elemental type."""
1270 __tablename__ = 'type_names'
1271 type_id = Column(Integer, ForeignKey('types.id'), primary_key=True, nullable=False, autoincrement=False,
1272 info=dict(description=u"The ID of the type."))
1273 language_id = Column(Integer, ForeignKey('languages.id'), primary_key=True, nullable=False, autoincrement=False,
1274 info=dict(description=u"The ID of the language."))
1275 name = Column(Unicode(16), nullable=False,
1276 info=dict(description=u"The name of the type in this language.", foreign=True, format='plaintext'))
1277
1278 class VersionGroup(TableBase):
1279 u"""A group of versions, containing either two paired versions (such as Red
1280 and Blue) or a single game (such as Yellow.)
1281 """
1282 __tablename__ = 'version_groups'
1283 id = Column(Integer, primary_key=True, nullable=False,
1284 info=dict(description=u"This version group's unique ID."))
1285 generation_id = Column(Integer, ForeignKey('generations.id'), nullable=False,
1286 info=dict(description=u"The ID of the generation the games in this group belong to."))
1287 pokedex_id = Column(Integer, ForeignKey('pokedexes.id'), nullable=False,
1288 info=dict(description=u"The ID of the regional Pokédex used in this version group."))
1289
1290 class VersionGroupRegion(TableBase):
1291 u"""Maps a version group to a region that appears in it."""
1292 __tablename__ = 'version_group_regions'
1293 version_group_id = Column(Integer, ForeignKey('version_groups.id'), primary_key=True, nullable=False,
1294 info=dict(description=u"The ID of the version group."))
1295 region_id = Column(Integer, ForeignKey('regions.id'), primary_key=True, nullable=False,
1296 info=dict(description=u"The ID of the region."))
1297
1298 class Version(TableBase):
1299 u"""An individual main-series Pokémon game."""
1300 __tablename__ = 'versions'
1301 id = Column(Integer, primary_key=True, nullable=False,
1302 info=dict(description=u"A unique ID for this version."))
1303 version_group_id = Column(Integer, ForeignKey('version_groups.id'), nullable=False,
1304 info=dict(description=u"The ID of the version group this game belongs to."))
1305 name = Column(Unicode(32), nullable=False,
1306 info=dict(description=u'The English "version" name for this game, e.g. "Red", without the rest of the title.', official=True, format='plaintext'))
1307
1308
1309 ### Relations down here, to avoid ordering problems
1310 Ability.changelog = relation(AbilityChangelog,
1311 order_by=AbilityChangelog.changed_in_version_group_id.desc(),
1312 backref='ability',
1313 )
1314 Ability.flavor_text = relation(AbilityFlavorText, order_by=AbilityFlavorText.version_group_id, backref='ability')
1315 Ability.foreign_names = relation(AbilityName, backref='ability')
1316 Ability.generation = relation(Generation, backref='abilities')
1317 Ability.all_pokemon = relation(Pokemon,
1318 secondary=PokemonAbility.__table__,
1319 back_populates='all_abilities',
1320 )
1321 Ability.pokemon = relation(Pokemon,
1322 secondary=PokemonAbility.__table__,
1323 primaryjoin=and_(
1324 PokemonAbility.ability_id == Ability.id,
1325 PokemonAbility.is_dream == False
1326 ),
1327 back_populates='abilities',
1328 )
1329 Ability.dream_pokemon = relation(Pokemon,
1330 secondary=PokemonAbility.__table__,
1331 primaryjoin=and_(
1332 PokemonAbility.ability_id == Ability.id,
1333 PokemonAbility.is_dream == True
1334 ),
1335 back_populates='dream_ability',
1336 )
1337
1338 AbilityChangelog.changed_in = relation(VersionGroup, backref='ability_changelog')
1339
1340 AbilityFlavorText.version_group = relation(VersionGroup)
1341
1342 AbilityName.language = relation(Language)
1343
1344 Berry.berry_firmness = relation(BerryFirmness, backref='berries')
1345 Berry.firmness = association_proxy('berry_firmness', 'name')
1346 Berry.flavors = relation(BerryFlavor, order_by=BerryFlavor.contest_type_id, backref='berry')
1347 Berry.natural_gift_type = relation(Type)
1348
1349 BerryFlavor.contest_type = relation(ContestType)
1350
1351 ContestCombo.first = relation(Move, primaryjoin=ContestCombo.first_move_id==Move.id,
1352 backref='contest_combo_first')
1353 ContestCombo.second = relation(Move, primaryjoin=ContestCombo.second_move_id==Move.id,
1354 backref='contest_combo_second')
1355
1356 Encounter.location_area = relation(LocationArea, backref='encounters')
1357 Encounter.pokemon = relation(Pokemon, backref='encounters')
1358 Encounter.version = relation(Version, backref='encounters')
1359 Encounter.slot = relation(EncounterSlot, backref='encounters')
1360
1361 EncounterConditionValue.condition = relation(EncounterCondition, backref='values')
1362
1363 Encounter.condition_value_map = relation(EncounterConditionValueMap, backref='encounter')
1364 Encounter.condition_values = association_proxy('condition_value_map', 'condition_value')
1365 EncounterConditionValueMap.condition_value = relation(EncounterConditionValue,
1366 backref='encounter_map')
1367
1368 EncounterSlot.terrain = relation(EncounterTerrain, backref='slots')
1369
1370 EncounterSlot.condition_map = relation(EncounterSlotCondition, backref='slot')
1371 EncounterSlot.conditions = association_proxy('condition_map', 'condition')
1372 EncounterSlotCondition.condition = relation(EncounterCondition,
1373 backref='slot_map')
1374
1375 EvolutionChain.growth_rate = relation(GrowthRate, backref='evolution_chains')
1376 EvolutionChain.baby_trigger_item = relation(Item, backref='evolution_chains')
1377 EvolutionChain.pokemon = relation(Pokemon, order_by=Pokemon.order, back_populates='evolution_chain')
1378
1379 Experience.growth_rate = relation(GrowthRate, backref='experience_table')
1380
1381 Generation.canonical_pokedex = relation(Pokedex, backref='canonical_for_generation')
1382 Generation.versions = relation(Version, secondary=VersionGroup.__table__)
1383 Generation.main_region = relation(Region)
1384
1385 GrowthRate.max_experience_obj = relation(Experience, primaryjoin=and_(Experience.growth_rate_id == GrowthRate.id, Experience.level == 100), uselist=False)
1386 GrowthRate.max_experience = association_proxy('max_experience_obj', 'experience')
1387
1388 Item.berry = relation(Berry, uselist=False, backref='item')
1389 Item.flags = relation(ItemFlag, secondary=ItemFlagMap.__table__)
1390 Item.flavor_text = relation(ItemFlavorText, order_by=ItemFlavorText.version_group_id.asc(), backref='item')
1391 Item.fling_effect = relation(ItemFlingEffect, backref='items')
1392 Item.foreign_names = relation(ItemName, backref='item')
1393 Item.machines = relation(Machine, order_by=Machine.version_group_id.asc())
1394 Item.category = relation(ItemCategory)
1395 Item.pocket = association_proxy('category', 'pocket')
1396
1397 ItemCategory.items = relation(Item, order_by=Item.name)
1398 ItemCategory.pocket = relation(ItemPocket)
1399
1400 ItemFlavorText.version_group = relation(VersionGroup)
1401
1402 ItemInternalID.item = relation(Item, backref='internal_ids')
1403 ItemInternalID.generation = relation(Generation)
1404
1405 ItemName.language = relation(Language)
1406
1407 ItemPocket.categories = relation(ItemCategory, order_by=ItemCategory.name)
1408
1409 Location.region = relation(Region, backref='locations')
1410
1411 LocationArea.location = relation(Location, backref='areas')
1412
1413 LocationInternalID.location = relation(Location, backref='internal_ids')
1414 LocationInternalID.generation = relation(Generation)
1415
1416 Machine.item = relation(Item)
1417 Machine.version_group = relation(VersionGroup)
1418
1419 Move.changelog = relation(MoveChangelog,
1420 order_by=MoveChangelog.changed_in_version_group_id.desc(),
1421 backref='move',
1422 )
1423 Move.contest_effect = relation(ContestEffect, backref='moves')
1424 Move.contest_combo_next = association_proxy('contest_combo_first', 'second')
1425 Move.contest_combo_prev = association_proxy('contest_combo_second', 'first')
1426 Move.contest_type = relation(ContestType, backref='moves')
1427 Move.damage_class = relation(MoveDamageClass, backref='moves')
1428 Move.flags = association_proxy('move_flags', 'flag')
1429 Move.flavor_text = relation(MoveFlavorText, order_by=MoveFlavorText.version_group_id, backref='move')
1430 Move.foreign_names = relation(MoveName, backref='move')
1431 Move.generation = relation(Generation, backref='moves')
1432 Move.machines = relation(Machine, backref='move')
1433 Move.move_effect = relation(MoveEffect, backref='moves')
1434 Move.move_flags = relation(MoveFlag, backref='move')
1435 Move.super_contest_effect = relation(SuperContestEffect, backref='moves')
1436 Move.super_contest_combo_next = association_proxy('super_contest_combo_first', 'second')
1437 Move.super_contest_combo_prev = association_proxy('super_contest_combo_second', 'first')
1438 Move.target = relation(MoveTarget, backref='moves')
1439 Move.type = relation(Type, backref='moves')
1440
1441 Move.effect = markdown.MoveEffectProperty('effect')
1442 Move.short_effect = markdown.MoveEffectProperty('short_effect')
1443
1444 MoveChangelog.changed_in = relation(VersionGroup, backref='move_changelog')
1445 MoveChangelog.move_effect = relation(MoveEffect, backref='move_changelog')
1446 MoveChangelog.type = relation(Type, backref='move_changelog')
1447
1448 MoveChangelog.effect = markdown.MoveEffectProperty('effect')
1449 MoveChangelog.short_effect = markdown.MoveEffectProperty('short_effect')
1450
1451 MoveEffect.category_map = relation(MoveEffectCategoryMap)
1452 MoveEffect.categories = association_proxy('category_map', 'category')
1453 MoveEffectCategoryMap.category = relation(MoveEffectCategory)
1454
1455 MoveFlag.flag = relation(MoveFlagType)
1456
1457 MoveFlavorText.version_group = relation(VersionGroup)
1458
1459 MoveName.language = relation(Language)
1460
1461 Nature.foreign_names = relation(NatureName, backref='nature')
1462 Nature.decreased_stat = relation(Stat, primaryjoin=Nature.decreased_stat_id==Stat.id,
1463 backref='decreasing_natures')
1464 Nature.increased_stat = relation(Stat, primaryjoin=Nature.increased_stat_id==Stat.id,
1465 backref='increasing_natures')
1466 Nature.hates_flavor = relation(ContestType, primaryjoin=Nature.hates_flavor_id==ContestType.id,
1467 backref='hating_natures')
1468 Nature.likes_flavor = relation(ContestType, primaryjoin=Nature.likes_flavor_id==ContestType.id,
1469 backref='liking_natures')
1470 Nature.battle_style_preferences = relation(NatureBattleStylePreference,
1471 order_by=NatureBattleStylePreference.move_battle_style_id,
1472 backref='nature')
1473 Nature.pokeathlon_effects = relation(NaturePokeathlonStat, order_by=NaturePokeathlonStat.pokeathlon_stat_id)
1474
1475 NatureBattleStylePreference.battle_style = relation(MoveBattleStyle, backref='nature_preferences')
1476
1477 NatureName.language = relation(Language)
1478
1479 NaturePokeathlonStat.pokeathlon_stat = relation(PokeathlonStat, backref='nature_effects')
1480
1481 Pokedex.region = relation(Region, backref='pokedexes')
1482 Pokedex.version_groups = relation(VersionGroup, order_by=VersionGroup.id, back_populates='pokedex')
1483
1484 Pokemon.all_abilities = relation(Ability,
1485 secondary=PokemonAbility.__table__,
1486 order_by=PokemonAbility.slot,
1487 )
1488 Pokemon.abilities = relation(Ability,
1489 secondary=PokemonAbility.__table__,
1490 primaryjoin=and_(
1491 Pokemon.id == PokemonAbility.pokemon_id,
1492 PokemonAbility.is_dream == False,
1493 ),
1494 order_by=PokemonAbility.slot,
1495 )
1496 Pokemon.dream_ability = relation(Ability,
1497 secondary=PokemonAbility.__table__,
1498 primaryjoin=and_(
1499 Pokemon.id == PokemonAbility.pokemon_id,
1500 PokemonAbility.is_dream == True,
1501 ),
1502 uselist=False,
1503 )
1504 Pokemon.pokemon_color = relation(PokemonColor, backref='pokemon')
1505 Pokemon.color = association_proxy('pokemon_color', 'name')
1506 Pokemon.dex_numbers = relation(PokemonDexNumber, order_by=PokemonDexNumber.pokedex_id.asc(), backref='pokemon')
1507 Pokemon.egg_groups = relation(EggGroup, secondary=PokemonEggGroup.__table__,
1508 order_by=PokemonEggGroup.egg_group_id,
1509 backref=backref('pokemon', order_by=Pokemon.order))
1510 Pokemon.evolution_chain = relation(EvolutionChain, back_populates='pokemon')
1511 Pokemon.child_pokemon = relation(Pokemon,
1512 primaryjoin=Pokemon.id==PokemonEvolution.from_pokemon_id,
1513 secondary=PokemonEvolution.__table__,
1514 secondaryjoin=PokemonEvolution.to_pokemon_id==Pokemon.id,
1515 backref=backref('parent_pokemon', uselist=False),
1516 )
1517 Pokemon.flavor_text = relation(PokemonFlavorText, order_by=PokemonFlavorText.version_id.asc(), backref='pokemon')
1518 Pokemon.foreign_names = relation(PokemonName, backref='pokemon')
1519 Pokemon.forms = relation(PokemonForm, primaryjoin=Pokemon.id==PokemonForm.form_base_pokemon_id,
1520 order_by=(PokemonForm.order.asc(), PokemonForm.name.asc()))
1521 Pokemon.default_form = relation(PokemonForm,
1522 primaryjoin=and_(Pokemon.id==PokemonForm.form_base_pokemon_id, PokemonForm.is_default==True),
1523 uselist=False,
1524 )
1525 Pokemon.pokemon_habitat = relation(PokemonHabitat, backref='pokemon')
1526 Pokemon.habitat = association_proxy('pokemon_habitat', 'name')
1527 Pokemon.items = relation(PokemonItem, backref='pokemon')
1528 Pokemon.generation = relation(Generation, backref='pokemon')
1529 Pokemon.shape = relation(PokemonShape, backref='pokemon')
1530 Pokemon.stats = relation(PokemonStat, backref='pokemon', order_by=PokemonStat.stat_id.asc())
1531 Pokemon.types = relation(Type, secondary=PokemonType.__table__,
1532 order_by=PokemonType.slot.asc(),
1533 back_populates='pokemon')
1534
1535 PokemonDexNumber.pokedex = relation(Pokedex)
1536
1537 PokemonEvolution.from_pokemon = relation(Pokemon,
1538 primaryjoin=PokemonEvolution.from_pokemon_id==Pokemon.id,
1539 backref='child_evolutions',
1540 )
1541 PokemonEvolution.to_pokemon = relation(Pokemon,
1542 primaryjoin=PokemonEvolution.to_pokemon_id==Pokemon.id,
1543 backref=backref('parent_evolution', uselist=False),
1544 )
1545 PokemonEvolution.child_evolutions = relation(PokemonEvolution,
1546 primaryjoin=PokemonEvolution.from_pokemon_id==PokemonEvolution.to_pokemon_id,
1547 foreign_keys=[PokemonEvolution.to_pokemon_id],
1548 backref=backref('parent_evolution',
1549 remote_side=[PokemonEvolution.from_pokemon_id],
1550 uselist=False,
1551 ),
1552 )
1553 PokemonEvolution.trigger = relation(EvolutionTrigger, backref='evolutions')
1554 PokemonEvolution.trigger_item = relation(Item,
1555 primaryjoin=PokemonEvolution.trigger_item_id==Item.id,
1556 backref='triggered_evolutions',
1557 )
1558 PokemonEvolution.held_item = relation(Item,
1559 primaryjoin=PokemonEvolution.held_item_id==Item.id,
1560 backref='required_for_evolutions',
1561 )
1562 PokemonEvolution.location = relation(Location, backref='triggered_evolutions')
1563 PokemonEvolution.known_move = relation(Move, backref='triggered_evolutions')
1564 PokemonEvolution.party_pokemon = relation(Pokemon,
1565 primaryjoin=PokemonEvolution.party_pokemon_id==Pokemon.id,
1566 backref='triggered_evolutions',
1567 )
1568 PokemonEvolution.trade_pokemon = relation(Pokemon,
1569 primaryjoin=PokemonEvolution.trade_pokemon_id==Pokemon.id,
1570 )
1571
1572 PokemonFlavorText.version = relation(Version)
1573
1574 PokemonForm.form_base_pokemon = relation(Pokemon, primaryjoin=PokemonForm.form_base_pokemon_id==Pokemon.id)
1575 PokemonForm.unique_pokemon = relation(Pokemon, backref=backref('unique_form', uselist=False),
1576 primaryjoin=PokemonForm.unique_pokemon_id==Pokemon.id)
1577 PokemonForm.version_group = relation(VersionGroup)
1578 PokemonForm.form_group = association_proxy('form_base_pokemon', 'form_group')
1579 PokemonForm.pokeathlon_stats = relation(PokemonFormPokeathlonStat,
1580 order_by=PokemonFormPokeathlonStat.pokeathlon_stat_id,
1581 backref='pokemon_form')
1582
1583 PokemonFormGroup.pokemon = relation(Pokemon, backref=backref('form_group',
1584 uselist=False))
1585
1586 PokemonFormPokeathlonStat.pokeathlon_stat = relation(PokeathlonStat)
1587
1588 PokemonItem.item = relation(Item, backref='pokemon')
1589 PokemonItem.version = relation(Version)
1590
1591 PokemonMove.pokemon = relation(Pokemon, backref='pokemon_moves')
1592 PokemonMove.version_group = relation(VersionGroup)
1593 PokemonMove.machine = relation(Machine, backref='pokemon_moves',
1594 primaryjoin=and_(Machine.version_group_id==PokemonMove.version_group_id,
1595 Machine.move_id==PokemonMove.move_id),
1596 foreign_keys=[Machine.version_group_id, Machine.move_id],
1597 uselist=False)
1598 PokemonMove.move = relation(Move, backref='pokemon_moves')
1599 PokemonMove.method = relation(PokemonMoveMethod)
1600
1601 PokemonName.language = relation(Language, lazy='joined')
1602
1603 PokemonStat.stat = relation(Stat)
1604
1605 # This is technically a has-many; Generation.main_region_id -> Region.id
1606 Region.generation = relation(Generation, uselist=False)
1607 Region.version_group_regions = relation(VersionGroupRegion, backref='region',
1608 order_by='VersionGroupRegion.version_group_id')
1609 Region.version_groups = association_proxy('version_group_regions', 'version_group')
1610
1611 Stat.damage_class = relation(MoveDamageClass, backref='stats')
1612
1613 SuperContestCombo.first = relation(Move, primaryjoin=SuperContestCombo.first_move_id==Move.id,
1614 backref='super_contest_combo_first')
1615 SuperContestCombo.second = relation(Move, primaryjoin=SuperContestCombo.second_move_id==Move.id,
1616 backref='super_contest_combo_second')
1617
1618 Type.damage_efficacies = relation(TypeEfficacy,
1619 primaryjoin=Type.id
1620 ==TypeEfficacy.damage_type_id,
1621 backref='damage_type')
1622 Type.target_efficacies = relation(TypeEfficacy,
1623 primaryjoin=Type.id
1624 ==TypeEfficacy.target_type_id,
1625 backref='target_type')
1626
1627 Type.generation = relation(Generation, backref='types')
1628 Type.damage_class = relation(MoveDamageClass, backref='types')
1629 Type.foreign_names = relation(TypeName, backref='type')
1630 Type.pokemon = relation(Pokemon, secondary=PokemonType.__table__,
1631 order_by=Pokemon.order,
1632 back_populates='types')
1633
1634 TypeName.language = relation(Language)
1635
1636 Version.version_group = relation(VersionGroup, back_populates='versions')
1637 Version.generation = association_proxy('version_group', 'generation')
1638
1639 VersionGroup.versions = relation(Version, order_by=Version.id, back_populates='version_group')
1640 VersionGroup.generation = relation(Generation, backref='version_groups')
1641 VersionGroup.version_group_regions = relation(VersionGroupRegion, backref='version_group')
1642 VersionGroup.regions = association_proxy('version_group_regions', 'region')
1643 VersionGroup.pokedex = relation(Pokedex, back_populates='version_groups')