Schema documentation, up to Language
[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 """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="A numeric 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="ID of the generation this ability was introduced in", detail=True))
51 effect = Column(markdown.MarkdownColumn(5120), nullable=False,
52 info=dict(description="Detailed description of this ability's effect", format='markdown'))
53 short_effect = Column(markdown.MarkdownColumn(255), nullable=False,
54 info=dict(description="Short summary of this ability's effect", format='markdown'))
55
56 class AbilityFlavorText(TableBase):
57 """In-game flavor text of an ability
58 """
59 __tablename__ = 'ability_flavor_text'
60 ability_id = Column(Integer, ForeignKey('abilities.id'), primary_key=True, nullable=False, autoincrement=False,
61 info=dict(description="A numeric ID"))
62 version_group_id = Column(Integer, ForeignKey('version_groups.id'), primary_key=True, nullable=False, autoincrement=False,
63 info=dict(description="The versions this flavor text is shown in"))
64 flavor_text = Column(Unicode(64), nullable=False,
65 info=dict(description="The actual flavor text", official=True, format='gametext'))
66
67 class AbilityName(TableBase):
68 """Non-English official name of an ability
69 """
70 __tablename__ = 'ability_names'
71 ability_id = Column(Integer, ForeignKey('abilities.id'), primary_key=True, nullable=False, autoincrement=False,
72 info=dict(description="ID of the ability"))
73 language_id = Column(Integer, ForeignKey('languages.id'), primary_key=True, nullable=False, autoincrement=False,
74 info=dict(description="ID of the language"))
75 name = Column(Unicode(16), nullable=False,
76 info=dict(description="ID of the language", official=True, foreign=True, format='plaintext'))
77
78 class Berry(TableBase):
79 """A Berry, consumable item that grows on trees
80
81 For data common to all Items, such as the name, see the corresponding Item entry.
82 """
83 __tablename__ = 'berries'
84 id = Column(Integer, primary_key=True, nullable=False,
85 info=dict(description="A numeric ID"))
86 item_id = Column(Integer, ForeignKey('items.id'), nullable=False,
87 info=dict(description="ID of the Item this Berry corresponds to"))
88 firmness_id = Column(Integer, ForeignKey('berry_firmness.id'), nullable=False,
89 info=dict(description="ID of this berry's firmness"))
90 natural_gift_power = Column(Integer, nullable=True,
91 info=dict(description="Power of Natural Gift when that move is used with this Berry"))
92 natural_gift_type_id = Column(Integer, ForeignKey('types.id'), nullable=True,
93 info=dict(description="ID of the Type that Natural Gift will have when used with this Berry"))
94 size = Column(Integer, nullable=False,
95 info=dict(description=u"Size of this Berry, in millimeters"))
96 max_harvest = Column(Integer, nullable=False,
97 info=dict(description="Maximum number of these berries that can grow on one tree"))
98 growth_time = Column(Integer, nullable=False,
99 info=dict(description="Time it takes the tree to grow one stage, in hours. Multiply by four to get overall time."))
100 soil_dryness = Column(Integer, nullable=False,
101 info=dict(description="The speed of soil drying the tree causes")) # XXX: What's this exactly? I'm not a good farmer
102 smoothness = Column(Integer, nullable=False,
103 info=dict(description="Smoothness of this Berry, a culinary attribute. Higher is better."))
104
105 class BerryFirmness(TableBase):
106 """A Berry firmness, such as "hard" or "very soft".
107 """
108 __tablename__ = 'berry_firmness'
109 id = Column(Integer, primary_key=True, nullable=False,
110 info=dict(description="A numeric ID"))
111 name = Column(Unicode(10), nullable=False,
112 info=dict(description="English name of the firmness level", official=True, format='plaintext'))
113
114 class BerryFlavor(TableBase):
115 """A Berry flavor level.
116 """
117 __tablename__ = 'berry_flavors'
118 berry_id = Column(Integer, ForeignKey('berries.id'), primary_key=True, nullable=False, autoincrement=False,
119 info=dict(description="ID of the berry"))
120 contest_type_id = Column(Integer, ForeignKey('contest_types.id'), primary_key=True, nullable=False, autoincrement=False,
121 info=dict(description="ID of the flavor"))
122 flavor = Column(Integer, nullable=False,
123 info=dict(description="Level of the flavor in the berry"))
124
125 class ContestCombo(TableBase):
126 """Combo of two moves in a Contest.
127 """
128 __tablename__ = 'contest_combos'
129 first_move_id = Column(Integer, ForeignKey('moves.id'), primary_key=True, nullable=False, autoincrement=False,
130 info=dict(description="ID of the first move in the combo"))
131 second_move_id = Column(Integer, ForeignKey('moves.id'), primary_key=True, nullable=False, autoincrement=False,
132 info=dict(description="ID of the second and final move in the combo"))
133
134 class ContestEffect(TableBase):
135 """Effect of a move when used in a Contest.
136 """
137 __tablename__ = 'contest_effects'
138 id = Column(Integer, primary_key=True, nullable=False,
139 info=dict(description="A numeric ID"))
140 appeal = Column(SmallInteger, nullable=False,
141 info=dict(description="The base number of hearts the user of this move gets"))
142 jam = Column(SmallInteger, nullable=False,
143 info=dict(description="The base number of hearts the user's opponent loses"))
144 flavor_text = Column(Unicode(64), nullable=False,
145 info=dict(description="English in-game description of this effect", official=True, format='gametext'))
146 effect = Column(Unicode(255), nullable=False,
147 info=dict(description="Detailed description of the effect", format='markdown'))
148
149 class ContestType(TableBase):
150 u"""A Contest type, such as "cool" or "smart". Also functions as Berry flavor and Pokéblock color."""
151 __tablename__ = 'contest_types'
152 id = Column(Integer, primary_key=True, nullable=False,
153 info=dict(description="A numeric ID"))
154 name = Column(Unicode(6), nullable=False,
155 info=dict(description="The English name of the Contest type", official=True, format='identifier'))
156 flavor = Column(Unicode(6), nullable=False,
157 info=dict(description="The English name of the corresponding Berry flavor", official=True, format='identifier'))
158 color = Column(Unicode(6), nullable=False,
159 info=dict(description="The English name of the corresponding Pokéblock color", official=True, format='identifier'))
160
161 class EggGroup(TableBase):
162 """An Egg group. Usually, two Pokémon can breed if they share an Egg Group.
163
164 (exceptions are the Ditto and No Eggs groups)
165 """
166 __tablename__ = 'egg_groups'
167 id = Column(Integer, primary_key=True, nullable=False,
168 info=dict(description="A numeric ID"))
169 name = Column(Unicode(16), nullable=False,
170 info=dict(description="The English “official” name. One NPC in Stadium uses these names; they are pretty bad.", official=True, format='identifier'))
171
172 class Encounter(TableBase):
173 """Encounters with wild Pokémon.
174
175 Bear with me, here.
176
177 Within a given area in a given game, encounters are differentiated by the
178 "slot" they are in and the state of the game world.
179
180 What the player is doing to get an encounter, such as surfing or walking
181 through tall grass, is called terrain. Each terrain has its own set of
182 encounter slots.
183
184 Within a terrain, slots are defined primarily by rarity. Each slot can
185 also be affected by world conditions; for example, the 20% slot for walking
186 in tall grass is affected by whether a swarm is in effect in that area.
187 "Is there a swarm?" is a condition; "there is a swarm" and "there is not a
188 swarm" are the possible values of this condition.
189
190 A slot (20% walking in grass) and any appropriate world conditions (no
191 swarm) are thus enough to define a specific encounter.
192
193 Well, okay, almost: each slot actually appears twice.
194 """
195
196 __tablename__ = 'encounters'
197 id = Column(Integer, primary_key=True, nullable=False,
198 info=dict(description="A numeric ID"))
199 version_id = Column(Integer, ForeignKey('versions.id'), nullable=False, autoincrement=False,
200 info=dict(description="The ID of the Version this applies to"))
201 location_area_id = Column(Integer, ForeignKey('location_areas.id'), nullable=False, autoincrement=False,
202 info=dict(description="The ID of the Location of this encounter"))
203 encounter_slot_id = Column(Integer, ForeignKey('encounter_slots.id'), nullable=False, autoincrement=False,
204 info=dict(description="The ID of the encounter slot, which determines terrain and rarity"))
205 pokemon_id = Column(Integer, ForeignKey('pokemon.id'), nullable=False, autoincrement=False,
206 info=dict(description=u"The ID of the encountered Pokémon"))
207 min_level = Column(Integer, nullable=False, autoincrement=False,
208 info=dict(description=u"The minimum level of the encountered Pokémon"))
209 max_level = Column(Integer, nullable=False, autoincrement=False,
210 info=dict(description=u"The maxmum level of the encountered Pokémon"))
211
212 class EncounterCondition(TableBase):
213 """A conditions in the game world that affects pokémon encounters, such as time of day.
214 """
215
216 __tablename__ = 'encounter_conditions'
217 id = Column(Integer, primary_key=True, nullable=False,
218 info=dict(description="A numeric ID"))
219 name = Column(Unicode(64), nullable=False,
220 info=dict(description="An English name of the condition", format='plaintext'))
221
222 class EncounterConditionValue(TableBase):
223 """A possible state for a condition; for example, the state of 'swarm' could be 'swarm' or 'no swarm'.
224 """
225
226 __tablename__ = 'encounter_condition_values'
227 id = Column(Integer, primary_key=True, nullable=False,
228 info=dict(description="A numeric ID"))
229 encounter_condition_id = Column(Integer, ForeignKey('encounter_conditions.id'), primary_key=False, nullable=False, autoincrement=False,
230 info=dict(description="The ID of the encounter condition this is a value of"))
231 name = Column(Unicode(64), nullable=False,
232 info=dict(description="An english name of this value", format='plaintext'))
233 is_default = Column(Boolean, nullable=False,
234 info=dict(description='Set if this value is "default" or "normal" in some sense'))
235
236 class EncounterConditionValueMap(TableBase):
237 """Maps encounters to the specific conditions under which they occur."""
238
239 __tablename__ = 'encounter_condition_value_map'
240 encounter_id = Column(Integer, ForeignKey('encounters.id'), primary_key=True, nullable=False, autoincrement=False,
241 info=dict(description="ID of the encounter"))
242 encounter_condition_value_id = Column(Integer, ForeignKey('encounter_condition_values.id'), primary_key=True, nullable=False, autoincrement=False,
243 info=dict(description="ID of the encounter condition value"))
244
245 class EncounterTerrain(TableBase):
246 """A way the player can enter a wild encounter, e.g., surfing, fishing, or walking through tall grass.
247 """
248
249 __tablename__ = 'encounter_terrain'
250 id = Column(Integer, primary_key=True, nullable=False,
251 info=dict(description="A numeric ID"))
252 name = Column(Unicode(64), nullable=False,
253 info=dict(description="An english name of this terrain", format='plaintext'))
254
255 class EncounterSlot(TableBase):
256 """Aan abstract "slot" within a terrain, associated with both some set of conditions and a rarity.
257
258 Note that there are two encounters per slot, so the rarities will only add
259 up to 50.
260 """
261
262 __tablename__ = 'encounter_slots'
263 id = Column(Integer, primary_key=True, nullable=False,
264 info=dict(description="A numeric ID"))
265 version_group_id = Column(Integer, ForeignKey('version_groups.id'), nullable=False, autoincrement=False,
266 info=dict(description="The ID of the Version group this slot is in"))
267 encounter_terrain_id = Column(Integer, ForeignKey('encounter_terrain.id'), primary_key=False, nullable=False, autoincrement=False,
268 info=dict(description="The ID of the terrain"))
269 slot = Column(Integer, nullable=True)
270 # XXX: What is this?
271 rarity = Column(Integer, nullable=False,
272 info=dict(description="The chance of the encounter, in percent")) # XXX: It is in percent, right? I'm confused.
273
274 class EncounterSlotCondition(TableBase):
275 """A condition that affects an encounter slot."""
276
277 __tablename__ = 'encounter_slot_conditions'
278 encounter_slot_id = Column(Integer, ForeignKey('encounter_slots.id'), primary_key=True, nullable=False, autoincrement=False,
279 info=dict(description="The ID of the encounter slot"))
280 encounter_condition_id = Column(Integer, ForeignKey('encounter_conditions.id'), primary_key=True, nullable=False, autoincrement=False,
281 info=dict(description="The ID of the encounter condition"))
282
283 class EvolutionChain(TableBase):
284 """A family of pokémon that are linked by evolution"""
285 __tablename__ = 'evolution_chains'
286 id = Column(Integer, primary_key=True, nullable=False,
287 info=dict(description="A numeric ID"))
288 growth_rate_id = Column(Integer, ForeignKey('growth_rates.id'), nullable=False,
289 info=dict(description="ID of the growth rate for this family"))
290 baby_trigger_item_id = Column(Integer, ForeignKey('items.id'), nullable=True,
291 info=dict(description="Item that a parent must hold while breeding to produce a baby"))
292
293 class EvolutionTrigger(TableBase):
294 """An evolution type, such as "level" or "trade"."""
295 __tablename__ = 'evolution_triggers'
296 id = Column(Integer, primary_key=True, nullable=False,
297 info=dict(description="A numeric ID"))
298 identifier = Column(Unicode(16), nullable=False,
299 info=dict(description="An English identifier", format='identifier'))
300
301 class Experience(TableBase):
302 """EXP needed for a certain level with a certain growth rate"""
303 __tablename__ = 'experience'
304 growth_rate_id = Column(Integer, ForeignKey('growth_rates.id'), primary_key=True, nullable=False,
305 info=dict(description="ID of the growth rate"))
306 level = Column(Integer, primary_key=True, nullable=False, autoincrement=False,
307 info=dict(description="The level"))
308 experience = Column(Integer, nullable=False,
309 info=dict(description="The number of EXP points needed to get to that level"))
310
311 class Generation(TableBase):
312 u"""A Generation of the pokémon franchise"""
313 __tablename__ = 'generations'
314 id = Column(Integer, primary_key=True, nullable=False,
315 info=dict(description="A numeric ID"))
316 main_region_id = Column(Integer, ForeignKey('regions.id'),
317 info=dict(description="ID of the region this generation's main games take place in"))
318 canonical_pokedex_id = Column(Integer, ForeignKey('pokedexes.id'),
319 info=dict(description=u"ID of the pokédex this generation's main games use by default"))
320 name = Column(Unicode(16), nullable=False,
321 info=dict(description=u'An English name of this generation, such as "Generation IV"', format='plaintext'))
322
323 class GrowthRate(TableBase):
324 u"""Growth rate of a pokémon, i.e. the EXP → level function."""
325 __tablename__ = 'growth_rates'
326 id = Column(Integer, primary_key=True, nullable=False,
327 info=dict(description="A numeric ID"))
328 name = Column(Unicode(20), nullable=False,
329 info=dict(description="A name for the", format='identifier'))
330 formula = Column(Unicode(500), nullable=False,
331 info=dict(description="The formula", format='latex'))
332
333 class Item(TableBase):
334 """An Item from the games, like "Poké Ball" or "Bicycle"."""
335 __tablename__ = 'items'
336 __singlename__ = 'item'
337 id = Column(Integer, primary_key=True, nullable=False,
338 info=dict(description="A numeric ID"))
339 name = Column(Unicode(20), nullable=False,
340 info=dict(description="The English name of the item", official=True, format='plaintext'))
341 category_id = Column(Integer, ForeignKey('item_categories.id'), nullable=False,
342 info=dict(description="ID of a category this item belongs to"))
343 cost = Column(Integer, nullable=False,
344 info=dict(description=u"Cost of the item when bought. Items sell for half this price."))
345 fling_power = Column(Integer, nullable=True,
346 info=dict(description=u"Power of the move Fling when used with this item."))
347 fling_effect_id = Column(Integer, ForeignKey('item_fling_effects.id'), nullable=True,
348 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."))
349 effect = Column(markdown.MarkdownColumn(5120), nullable=False,
350 info=dict(description=u"Detailed English description of the item's effect.", format='markdown'))
351
352 @property
353 def appears_underground(self):
354 """True if the item appears underground, as specified by the appropriate flag"""
355 return any(flag.identifier == u'underground' for flag in self.flags)
356
357 class ItemCategory(TableBase):
358 """An item category"""
359 # XXX: This is fanon, right?
360 __tablename__ = 'item_categories'
361 id = Column(Integer, primary_key=True, nullable=False,
362 info=dict(description="A numeric ID"))
363 pocket_id = Column(Integer, ForeignKey('item_pockets.id'), nullable=False,
364 info=dict(description="ID of the pocket these items go to"))
365 name = Column(Unicode(16), nullable=False,
366 info=dict(description="English name of the category", format='plaintext'))
367
368 class ItemFlag(TableBase):
369 """An item attribute such as "consumable" or "holdable"."""
370 __tablename__ = 'item_flags'
371 id = Column(Integer, primary_key=True, nullable=False,
372 info=dict(description="A numeric ID"))
373 identifier = Column(Unicode(24), nullable=False,
374 info=dict(description="Identifier of the flag", format='identifier'))
375 name = Column(Unicode(64), nullable=False,
376 info=dict(description="Short English description of the flag", format='plaintext'))
377
378 class ItemFlagMap(TableBase):
379 """Maps an item flag to its item."""
380 __tablename__ = 'item_flag_map'
381 item_id = Column(Integer, ForeignKey('items.id'), primary_key=True, autoincrement=False, nullable=False,
382 info=dict(description="The ID of the item"))
383 item_flag_id = Column(Integer, ForeignKey('item_flags.id'), primary_key=True, autoincrement=False, nullable=False,
384 info=dict(description="The ID of the item flag"))
385
386 class ItemFlavorText(TableBase):
387 """An in-game description of an item"""
388 __tablename__ = 'item_flavor_text'
389 item_id = Column(Integer, ForeignKey('items.id'), primary_key=True, autoincrement=False, nullable=False,
390 info=dict(description="The ID of the item"))
391 version_group_id = Column(Integer, ForeignKey('version_groups.id'), primary_key=True, autoincrement=False, nullable=False,
392 info=dict(description="ID of the version group that sports this text"))
393 flavor_text = Column(Unicode(255), nullable=False,
394 info=dict(description="The flavor text itself", official=True, format='gametext'))
395
396 class ItemFlingEffect(TableBase):
397 """An effect of the move Fling when used with a specific item"""
398 __tablename__ = 'item_fling_effects'
399 id = Column(Integer, primary_key=True, nullable=False,
400 info=dict(description="A numeric ID"))
401 effect = Column(Unicode(255), nullable=False,
402 info=dict(description="English description of the effect", format='plaintext'))
403
404 class ItemInternalID(TableBase):
405 """The internal ID number a game uses for an item"""
406 __tablename__ = 'item_internal_ids'
407 item_id = Column(Integer, ForeignKey('items.id'), primary_key=True, autoincrement=False, nullable=False,
408 info=dict(description="The database ID of the item"))
409 generation_id = Column(Integer, ForeignKey('generations.id'), primary_key=True, autoincrement=False, nullable=False,
410 info=dict(description="ID of the generation of games"))
411 internal_id = Column(Integer, nullable=False,
412 info=dict(description="Internal ID of the item in the generation"))
413
414 class ItemName(TableBase):
415 """A non-English name of an item"""
416 __tablename__ = 'item_names'
417 item_id = Column(Integer, ForeignKey('items.id'), primary_key=True, nullable=False, autoincrement=False,
418 info=dict(description="The ID of the item"))
419 language_id = Column(Integer, ForeignKey('languages.id'), primary_key=True, nullable=False, autoincrement=False,
420 info=dict(description="The ID of the language"))
421 name = Column(Unicode(16), nullable=False,
422 info=dict(description="The name of the item in this language", foreign=True, format='plaintext'))
423
424 class ItemPocket(TableBase):
425 """A pocket that categorizes items"""
426 __tablename__ = 'item_pockets'
427 id = Column(Integer, primary_key=True, nullable=False,
428 info=dict(description="A numeric ID"))
429 identifier = Column(Unicode(16), nullable=False,
430 info=dict(description="An identifier of this pocket", format='identifier'))
431 name = Column(Unicode(16), nullable=False,
432 info=dict(description="A numeric ID", format='plaintext'))
433
434 class Language(TableBase):
435 u"""A language the Pokémon games have been transleted into; except English"""
436 __tablename__ = 'languages'
437 id = Column(Integer, primary_key=True, nullable=False,
438 info=dict(description="A numeric ID"))
439 iso639 = Column(Unicode(2), nullable=False,
440 info=dict(description="The two-letter code of the country where this language is spoken. Note that it is not unique."))
441 iso3166 = Column(Unicode(2), nullable=False,
442 info=dict(description="The two-letter code of the language. Note that it is not unique."))
443 name = Column(Unicode(16), nullable=False,
444 info=dict(description="The English name of the language", format='plaintext'))
445
446 class Location(TableBase):
447 __tablename__ = 'locations'
448 __singlename__ = 'location'
449 id = Column(Integer, primary_key=True, nullable=False)
450 region_id = Column(Integer, ForeignKey('regions.id'))
451 name = Column(Unicode(64), nullable=False)
452
453 class LocationArea(TableBase):
454 __tablename__ = 'location_areas'
455 id = Column(Integer, primary_key=True, nullable=False)
456 location_id = Column(Integer, ForeignKey('locations.id'), nullable=False)
457 internal_id = Column(Integer, nullable=False)
458 name = Column(Unicode(64), nullable=True)
459
460 class LocationAreaEncounterRate(TableBase):
461 __tablename__ = 'location_area_encounter_rates'
462 location_area_id = Column(Integer, ForeignKey('location_areas.id'), primary_key=True, nullable=False, autoincrement=False)
463 encounter_terrain_id = Column(Integer, ForeignKey('encounter_terrain.id'), primary_key=True, nullable=False, autoincrement=False)
464 version_id = Column(Integer, ForeignKey('versions.id'), primary_key=True, autoincrement=False)
465 rate = Column(Integer, nullable=True)
466
467 class LocationInternalID(TableBase):
468 __tablename__ = 'location_internal_ids'
469 location_id = Column(Integer, ForeignKey('locations.id'), nullable=False, primary_key=True)
470 generation_id = Column(Integer, ForeignKey('generations.id'), nullable=False, primary_key=True)
471 internal_id = Column(Integer, nullable=False)
472
473 class Machine(TableBase):
474 __tablename__ = 'machines'
475 machine_number = Column(Integer, primary_key=True, nullable=False, autoincrement=False)
476 version_group_id = Column(Integer, ForeignKey('version_groups.id'), primary_key=True, nullable=False, autoincrement=False)
477 item_id = Column(Integer, ForeignKey('items.id'), nullable=False)
478 move_id = Column(Integer, ForeignKey('moves.id'), nullable=False)
479
480 @property
481 def is_hm(self):
482 return self.machine_number >= 100
483
484 class MoveBattleStyle(TableBase):
485 __tablename__ = 'move_battle_styles'
486 id = Column(Integer, primary_key=True, nullable=False)
487 name = Column(Unicode(8), nullable=False)
488
489 class MoveEffectCategory(TableBase):
490 __tablename__ = 'move_effect_categories'
491 id = Column(Integer, primary_key=True, nullable=False)
492 name = Column(Unicode(64), nullable=False)
493 can_affect_user = Column(Boolean, nullable=False)
494
495 class MoveEffectCategoryMap(TableBase):
496 __tablename__ = 'move_effect_category_map'
497 move_effect_id = Column(Integer, ForeignKey('move_effects.id'), primary_key=True, nullable=False)
498 move_effect_category_id = Column(Integer, ForeignKey('move_effect_categories.id'), primary_key=True, nullable=False)
499 affects_user = Column(Boolean, primary_key=True, nullable=False)
500
501 class MoveDamageClass(TableBase):
502 __tablename__ = 'move_damage_classes'
503 id = Column(Integer, primary_key=True, nullable=False)
504 name = Column(Unicode(8), nullable=False)
505 description = Column(Unicode(64), nullable=False)
506
507 class MoveEffect(TableBase):
508 __tablename__ = 'move_effects'
509 id = Column(Integer, primary_key=True, nullable=False)
510 short_effect = Column(Unicode(256), nullable=False)
511 effect = Column(Unicode(5120), nullable=False)
512
513 class MoveFlag(TableBase):
514 __tablename__ = 'move_flags'
515 move_id = Column(Integer, ForeignKey('moves.id'), primary_key=True, nullable=False, autoincrement=False)
516 move_flag_type_id = Column(Integer, ForeignKey('move_flag_types.id'), primary_key=True, nullable=False, autoincrement=False)
517
518 class MoveFlagType(TableBase):
519 __tablename__ = 'move_flag_types'
520 id = Column(Integer, primary_key=True, nullable=False)
521 identifier = Column(Unicode(16), nullable=False)
522 name = Column(Unicode(32), nullable=False)
523 description = Column(markdown.MarkdownColumn(128), nullable=False)
524
525 class MoveFlavorText(TableBase):
526 __tablename__ = 'move_flavor_text'
527 move_id = Column(Integer, ForeignKey('moves.id'), primary_key=True, nullable=False, autoincrement=False)
528 version_group_id = Column(Integer, ForeignKey('version_groups.id'), primary_key=True, nullable=False, autoincrement=False)
529 flavor_text = Column(Unicode(255), nullable=False)
530
531 class MoveName(TableBase):
532 __tablename__ = 'move_names'
533 move_id = Column(Integer, ForeignKey('moves.id'), primary_key=True, nullable=False, autoincrement=False)
534 language_id = Column(Integer, ForeignKey('languages.id'), primary_key=True, nullable=False, autoincrement=False)
535 name = Column(Unicode(16), nullable=False)
536
537 class MoveTarget(TableBase):
538 __tablename__ = 'move_targets'
539 id = Column(Integer, primary_key=True, nullable=False)
540 name = Column(Unicode(32), nullable=False)
541 description = Column(Unicode(128), nullable=False)
542
543 class Move(TableBase):
544 __tablename__ = 'moves'
545 __singlename__ = 'move'
546 id = Column(Integer, primary_key=True, nullable=False)
547 name = Column(Unicode(24), nullable=False)
548 generation_id = Column(Integer, ForeignKey('generations.id'), nullable=False)
549 type_id = Column(Integer, ForeignKey('types.id'), nullable=False)
550 power = Column(SmallInteger, nullable=False)
551 pp = Column(SmallInteger, nullable=False)
552 accuracy = Column(SmallInteger, nullable=True)
553 priority = Column(SmallInteger, nullable=False)
554 target_id = Column(Integer, ForeignKey('move_targets.id'), nullable=False)
555 damage_class_id = Column(Integer, ForeignKey('move_damage_classes.id'), nullable=False)
556 effect_id = Column(Integer, ForeignKey('move_effects.id'), nullable=False)
557 effect_chance = Column(Integer)
558 contest_type_id = Column(Integer, ForeignKey('contest_types.id'), nullable=True)
559 contest_effect_id = Column(Integer, ForeignKey('contest_effects.id'), nullable=True)
560 super_contest_effect_id = Column(Integer, ForeignKey('super_contest_effects.id'), nullable=True)
561
562 class Nature(TableBase):
563 __tablename__ = 'natures'
564 __singlename__ = 'nature'
565 id = Column(Integer, primary_key=True, nullable=False)
566 name = Column(Unicode(8), nullable=False)
567 decreased_stat_id = Column(Integer, ForeignKey('stats.id'), nullable=False)
568 increased_stat_id = Column(Integer, ForeignKey('stats.id'), nullable=False)
569 hates_flavor_id = Column(Integer, ForeignKey('contest_types.id'), nullable=False)
570 likes_flavor_id = Column(Integer, ForeignKey('contest_types.id'), nullable=False)
571
572 @property
573 def is_neutral(self):
574 u"""Returns True iff this nature doesn't alter a Pokémon's stats,
575 bestow taste preferences, etc.
576 """
577 return self.increased_stat_id == self.decreased_stat_id
578
579 class NatureBattleStylePreference(TableBase):
580 __tablename__ = 'nature_battle_style_preferences'
581 nature_id = Column(Integer, ForeignKey('natures.id'), primary_key=True, nullable=False)
582 move_battle_style_id = Column(Integer, ForeignKey('move_battle_styles.id'), primary_key=True, nullable=False)
583 low_hp_preference = Column(Integer, nullable=False)
584 high_hp_preference = Column(Integer, nullable=False)
585
586 class NatureName(TableBase):
587 __tablename__ = 'nature_names'
588 nature_id = Column(Integer, ForeignKey('natures.id'), primary_key=True, nullable=False, autoincrement=False)
589 language_id = Column(Integer, ForeignKey('languages.id'), primary_key=True, nullable=False, autoincrement=False)
590 name = Column(Unicode(8), nullable=False)
591
592 class NaturePokeathlonStat(TableBase):
593 __tablename__ = 'nature_pokeathlon_stats'
594 nature_id = Column(Integer, ForeignKey('natures.id'), primary_key=True, nullable=False)
595 pokeathlon_stat_id = Column(Integer, ForeignKey('pokeathlon_stats.id'), primary_key=True, nullable=False)
596 max_change = Column(Integer, nullable=False)
597
598 class PokeathlonStat(TableBase):
599 __tablename__ = 'pokeathlon_stats'
600 id = Column(Integer, primary_key=True, nullable=False)
601 name = Column(Unicode(8), nullable=False)
602
603 class Pokedex(TableBase):
604 __tablename__ = 'pokedexes'
605 id = Column(Integer, primary_key=True, nullable=False)
606 region_id = Column(Integer, ForeignKey('regions.id'), nullable=True)
607 name = Column(Unicode(16), nullable=False)
608 description = Column(Unicode(512))
609
610 class PokedexVersionGroup(TableBase):
611 __tablename__ = 'pokedex_version_groups'
612 pokedex_id = Column(Integer, ForeignKey('pokedexes.id'), primary_key=True, nullable=False, autoincrement=False)
613 version_group_id = Column(Integer, ForeignKey('version_groups.id'), primary_key=True, nullable=False, autoincrement=False)
614
615 class Pokemon(TableBase):
616 """The core to this whole mess.
617
618 Note that I use both 'forme' and 'form' in both code and the database. I
619 only use 'forme' when specifically referring to Pokémon that have multiple
620 distinct species as forms—i.e., different stats or movesets. 'Form' is a
621 more general term referring to any variation within a species, including
622 purely cosmetic forms like Unown.
623 """
624 __tablename__ = 'pokemon'
625 __singlename__ = 'pokemon'
626 id = Column(Integer, primary_key=True, nullable=False)
627 name = Column(Unicode(20), nullable=False)
628 forme_name = Column(Unicode(16))
629 forme_base_pokemon_id = Column(Integer, ForeignKey('pokemon.id'))
630 generation_id = Column(Integer, ForeignKey('generations.id'))
631 evolution_chain_id = Column(Integer, ForeignKey('evolution_chains.id'))
632 height = Column(Integer, nullable=False)
633 weight = Column(Integer, nullable=False)
634 species = Column(Unicode(16), nullable=False)
635 color_id = Column(Integer, ForeignKey('pokemon_colors.id'), nullable=False)
636 pokemon_shape_id = Column(Integer, ForeignKey('pokemon_shapes.id'), nullable=True)
637 habitat_id = Column(Integer, ForeignKey('pokemon_habitats.id'), nullable=True)
638 gender_rate = Column(Integer, nullable=False)
639 capture_rate = Column(Integer, nullable=False)
640 base_experience = Column(Integer, nullable=False)
641 base_happiness = Column(Integer, nullable=False)
642 is_baby = Column(Boolean, nullable=False)
643 hatch_counter = Column(Integer, nullable=False)
644 has_gen4_fem_sprite = Column(Boolean, nullable=False)
645 has_gen4_fem_back_sprite = Column(Boolean, nullable=False)
646
647 ### Stuff to handle alternate Pokémon forms
648
649 @property
650 def national_id(self):
651 """Returns the National Pokédex number for this Pokémon. Use this
652 instead of the id directly; alternate formes may make the id incorrect.
653 """
654
655 if self.forme_base_pokemon_id:
656 return self.forme_base_pokemon_id
657 return self.id
658
659 @property
660 def full_name(self):
661 """Returns the name of this Pokémon, including its Forme, if any."""
662
663 if self.forme_name:
664 return "%s %s" % (self.forme_name.title(), self.name)
665 return self.name
666
667 @property
668 def normal_form(self):
669 """Returns the normal form for this Pokémon; i.e., this will return
670 regular Deoxys when called on any Deoxys form.
671 """
672
673 if self.forme_base_pokemon:
674 return self.forme_base_pokemon
675
676 return self
677
678 ### Not forms!
679
680 def stat(self, stat_name):
681 """Returns a PokemonStat record for the given stat name (or Stat row
682 object). Uses the normal has-many machinery, so all the stats are
683 effectively cached.
684 """
685 if isinstance(stat_name, Stat):
686 stat_name = stat_name.name
687
688 for pokemon_stat in self.stats:
689 if pokemon_stat.stat.name == stat_name:
690 return pokemon_stat
691
692 raise KeyError(u'No stat named %s' % stat_name)
693
694 @property
695 def better_damage_class(self):
696 u"""Returns the MoveDamageClass that this Pokémon is best suited for,
697 based on its attack stats.
698
699 If the attack stats are about equal (within 5), returns None. The
700 value None, not the damage class called 'None'.
701 """
702 phys = self.stat(u'Attack')
703 spec = self.stat(u'Special Attack')
704
705 diff = phys.base_stat - spec.base_stat
706
707 if diff > 5:
708 return phys.stat.damage_class
709 elif diff < -5:
710 return spec.stat.damage_class
711 else:
712 return None
713
714 class PokemonAbility(TableBase):
715 __tablename__ = 'pokemon_abilities'
716 pokemon_id = Column(Integer, ForeignKey('pokemon.id'), primary_key=True, nullable=False, autoincrement=False)
717 ability_id = Column(Integer, ForeignKey('abilities.id'), nullable=False)
718 slot = Column(Integer, primary_key=True, nullable=False, autoincrement=False)
719
720 class PokemonColor(TableBase):
721 __tablename__ = 'pokemon_colors'
722 id = Column(Integer, primary_key=True, nullable=False, autoincrement=False)
723 name = Column(Unicode(6), nullable=False)
724
725 class PokemonDexNumber(TableBase):
726 __tablename__ = 'pokemon_dex_numbers'
727 pokemon_id = Column(Integer, ForeignKey('pokemon.id'), primary_key=True, nullable=False, autoincrement=False)
728 pokedex_id = Column(Integer, ForeignKey('pokedexes.id'), primary_key=True, nullable=False, autoincrement=False)
729 pokedex_number = Column(Integer, nullable=False)
730
731 class PokemonEggGroup(TableBase):
732 __tablename__ = 'pokemon_egg_groups'
733 pokemon_id = Column(Integer, ForeignKey('pokemon.id'), primary_key=True, nullable=False, autoincrement=False)
734 egg_group_id = Column(Integer, ForeignKey('egg_groups.id'), primary_key=True, nullable=False, autoincrement=False)
735
736 class PokemonEvolution(TableBase):
737 __tablename__ = 'pokemon_evolution'
738 from_pokemon_id = Column(Integer, ForeignKey('pokemon.id'), nullable=False)
739 to_pokemon_id = Column(Integer, ForeignKey('pokemon.id'), primary_key=True, nullable=False, autoincrement=False)
740 evolution_trigger_id = Column(Integer, ForeignKey('evolution_triggers.id'), nullable=False)
741 trigger_item_id = Column(Integer, ForeignKey('items.id'), nullable=True)
742 minimum_level = Column(Integer, nullable=True)
743 gender = Column(Enum('male', 'female', name='pokemon_evolution_gender'), nullable=True)
744 location_id = Column(Integer, ForeignKey('locations.id'), nullable=True)
745 held_item_id = Column(Integer, ForeignKey('items.id'), nullable=True)
746 time_of_day = Column(Enum('morning', 'day', 'night', name='pokemon_evolution_time_of_day'), nullable=True)
747 known_move_id = Column(Integer, ForeignKey('moves.id'), nullable=True)
748 minimum_happiness = Column(Integer, nullable=True)
749 minimum_beauty = Column(Integer, nullable=True)
750 relative_physical_stats = Column(Integer, nullable=True)
751 party_pokemon_id = Column(Integer, ForeignKey('pokemon.id'), nullable=True)
752
753 class PokemonFlavorText(TableBase):
754 __tablename__ = 'pokemon_flavor_text'
755 pokemon_id = Column(Integer, ForeignKey('pokemon.id'), primary_key=True, nullable=False, autoincrement=False)
756 version_id = Column(Integer, ForeignKey('versions.id'), primary_key=True, nullable=False, autoincrement=False)
757 flavor_text = Column(Unicode(255), nullable=False)
758
759 class PokemonFormGroup(TableBase):
760 __tablename__ = 'pokemon_form_groups'
761 pokemon_id = Column(Integer, ForeignKey('pokemon.id'), primary_key=True, nullable=False, autoincrement=False)
762 is_battle_only = Column(Boolean, nullable=False)
763 description = Column(markdown.MarkdownColumn(1024), nullable=False)
764
765 class PokemonFormSprite(TableBase):
766 __tablename__ = 'pokemon_form_sprites'
767 id = Column(Integer, primary_key=True, nullable=False)
768 pokemon_id = Column(Integer, ForeignKey('pokemon.id'), primary_key=True, nullable=False, autoincrement=False)
769 introduced_in_version_group_id = Column(Integer, ForeignKey('version_groups.id'), primary_key=True, nullable=False, autoincrement=False)
770 name = Column(Unicode(16), nullable=True)
771 is_default = Column(Boolean, nullable=True)
772
773 class PokemonHabitat(TableBase):
774 __tablename__ = 'pokemon_habitats'
775 id = Column(Integer, primary_key=True, nullable=False, autoincrement=False)
776 name = Column(Unicode(16), nullable=False)
777
778 class PokemonInternalID(TableBase):
779 __tablename__ = 'pokemon_internal_ids'
780 pokemon_id = Column(Integer, ForeignKey('pokemon.id'), primary_key=True, autoincrement=False, nullable=False)
781 generation_id = Column(Integer, ForeignKey('generations.id'), primary_key=True, autoincrement=False, nullable=False)
782 internal_id = Column(Integer, nullable=False)
783
784 class PokemonItem(TableBase):
785 __tablename__ = 'pokemon_items'
786 pokemon_id = Column(Integer, ForeignKey('pokemon.id'), primary_key=True, nullable=False, autoincrement=False)
787 version_id = Column(Integer, ForeignKey('versions.id'), primary_key=True, nullable=False, autoincrement=False)
788 item_id = Column(Integer, ForeignKey('items.id'), primary_key=True, nullable=False, autoincrement=False)
789 rarity = Column(Integer, nullable=False)
790
791 class PokemonMove(TableBase):
792 __tablename__ = 'pokemon_moves'
793 pokemon_id = Column(Integer, ForeignKey('pokemon.id'), nullable=False, index=True)
794 version_group_id = Column(Integer, ForeignKey('version_groups.id'), nullable=False, index=True)
795 move_id = Column(Integer, ForeignKey('moves.id'), nullable=False, index=True)
796 pokemon_move_method_id = Column(Integer, ForeignKey('pokemon_move_methods.id'), nullable=False, index=True)
797 level = Column(Integer, nullable=True, index=True)
798 order = Column(Integer, nullable=True)
799
800 __table_args__ = (
801 PrimaryKeyConstraint('pokemon_id', 'version_group_id', 'move_id', 'pokemon_move_method_id', 'level'),
802 {},
803 )
804
805 class PokemonMoveMethod(TableBase):
806 __tablename__ = 'pokemon_move_methods'
807 id = Column(Integer, primary_key=True, nullable=False, autoincrement=False)
808 name = Column(Unicode(64), nullable=False)
809 description = Column(Unicode(255), nullable=False)
810
811 class PokemonName(TableBase):
812 __tablename__ = 'pokemon_names'
813 pokemon_id = Column(Integer, ForeignKey('pokemon.id'), primary_key=True, nullable=False, autoincrement=False)
814 language_id = Column(Integer, ForeignKey('languages.id'), primary_key=True, nullable=False, autoincrement=False)
815 name = Column(Unicode(16), nullable=False)
816
817 class PokemonShape(TableBase):
818 __tablename__ = 'pokemon_shapes'
819 id = Column(Integer, primary_key=True, nullable=False)
820 name = Column(Unicode(24), nullable=False)
821 awesome_name = Column(Unicode(16), nullable=False)
822
823 class PokemonStat(TableBase):
824 __tablename__ = 'pokemon_stats'
825 pokemon_id = Column(Integer, ForeignKey('pokemon.id'), primary_key=True, nullable=False, autoincrement=False)
826 stat_id = Column(Integer, ForeignKey('stats.id'), primary_key=True, nullable=False, autoincrement=False)
827 base_stat = Column(Integer, nullable=False)
828 effort = Column(Integer, nullable=False)
829
830 class PokemonType(TableBase):
831 __tablename__ = 'pokemon_types'
832 pokemon_id = Column(Integer, ForeignKey('pokemon.id'), primary_key=True, nullable=False, autoincrement=False)
833 type_id = Column(Integer, ForeignKey('types.id'), nullable=False)
834 slot = Column(Integer, primary_key=True, nullable=False, autoincrement=False)
835
836 class Region(TableBase):
837 """Major areas of the world: Kanto, Johto, etc."""
838 __tablename__ = 'regions'
839 id = Column(Integer, primary_key=True, nullable=False)
840 name = Column(Unicode(16), nullable=False)
841
842 class Stat(TableBase):
843 __tablename__ = 'stats'
844 id = Column(Integer, primary_key=True, nullable=False)
845 damage_class_id = Column(Integer, ForeignKey('move_damage_classes.id'), nullable=True)
846 name = Column(Unicode(16), nullable=False)
847
848 class SuperContestCombo(TableBase):
849 __tablename__ = 'super_contest_combos'
850 first_move_id = Column(Integer, ForeignKey('moves.id'), primary_key=True, nullable=False, autoincrement=False)
851 second_move_id = Column(Integer, ForeignKey('moves.id'), primary_key=True, nullable=False, autoincrement=False)
852
853 class SuperContestEffect(TableBase):
854 __tablename__ = 'super_contest_effects'
855 id = Column(Integer, primary_key=True, nullable=False)
856 appeal = Column(SmallInteger, nullable=False)
857 flavor_text = Column(Unicode(64), nullable=False)
858
859 class TypeEfficacy(TableBase):
860 __tablename__ = 'type_efficacy'
861 damage_type_id = Column(Integer, ForeignKey('types.id'), primary_key=True, nullable=False, autoincrement=False)
862 target_type_id = Column(Integer, ForeignKey('types.id'), primary_key=True, nullable=False, autoincrement=False)
863 damage_factor = Column(Integer, nullable=False)
864
865 class Type(TableBase):
866 __tablename__ = 'types'
867 __singlename__ = 'type'
868 id = Column(Integer, primary_key=True, nullable=False)
869 name = Column(Unicode(8), nullable=False)
870 abbreviation = Column(Unicode(3), nullable=False)
871 generation_id = Column(Integer, ForeignKey('generations.id'), nullable=False)
872 damage_class_id = Column(Integer, ForeignKey('move_damage_classes.id'), nullable=False) ## ??? is none; everything else is physical or special
873
874 class TypeName(TableBase):
875 __tablename__ = 'type_names'
876 type_id = Column(Integer, ForeignKey('types.id'), primary_key=True, nullable=False, autoincrement=False)
877 language_id = Column(Integer, ForeignKey('languages.id'), primary_key=True, nullable=False, autoincrement=False)
878 name = Column(Unicode(16), nullable=False)
879
880 class VersionGroup(TableBase):
881 __tablename__ = 'version_groups'
882 id = Column(Integer, primary_key=True, nullable=False)
883 generation_id = Column(Integer, ForeignKey('generations.id'), nullable=False)
884
885 class VersionGroupRegion(TableBase):
886 __tablename__ = 'version_group_regions'
887 version_group_id = Column(Integer, ForeignKey('version_groups.id'), primary_key=True, nullable=False)
888 region_id = Column(Integer, ForeignKey('regions.id'), primary_key=True, nullable=False)
889
890 class Version(TableBase):
891 __tablename__ = 'versions'
892 id = Column(Integer, primary_key=True, nullable=False)
893 version_group_id = Column(Integer, ForeignKey('version_groups.id'), nullable=False)
894 name = Column(Unicode(32), nullable=False)
895
896
897 ### Relations down here, to avoid ordering problems
898 Ability.flavor_text = relation(AbilityFlavorText, order_by=AbilityFlavorText.version_group_id, backref='ability')
899 Ability.foreign_names = relation(AbilityName, backref='ability')
900 Ability.generation = relation(Generation, backref='abilities')
901
902 AbilityFlavorText.version_group = relation(VersionGroup)
903
904 AbilityName.language = relation(Language)
905
906 Berry.berry_firmness = relation(BerryFirmness, backref='berries')
907 Berry.firmness = association_proxy('berry_firmness', 'name')
908 Berry.flavors = relation(BerryFlavor, order_by=BerryFlavor.contest_type_id, backref='berry')
909 Berry.natural_gift_type = relation(Type)
910
911 BerryFlavor.contest_type = relation(ContestType)
912
913 ContestCombo.first = relation(Move, primaryjoin=ContestCombo.first_move_id==Move.id,
914 backref='contest_combo_first')
915 ContestCombo.second = relation(Move, primaryjoin=ContestCombo.second_move_id==Move.id,
916 backref='contest_combo_second')
917
918 Encounter.location_area = relation(LocationArea, backref='encounters')
919 Encounter.pokemon = relation(Pokemon, backref='encounters')
920 Encounter.version = relation(Version, backref='encounters')
921 Encounter.slot = relation(EncounterSlot, backref='encounters')
922
923 EncounterConditionValue.condition = relation(EncounterCondition, backref='values')
924
925 Encounter.condition_value_map = relation(EncounterConditionValueMap, backref='encounter')
926 Encounter.condition_values = association_proxy('condition_value_map', 'condition_value')
927 EncounterConditionValueMap.condition_value = relation(EncounterConditionValue,
928 backref='encounter_map')
929
930 EncounterSlot.terrain = relation(EncounterTerrain, backref='slots')
931
932 EncounterSlot.condition_map = relation(EncounterSlotCondition, backref='slot')
933 EncounterSlot.conditions = association_proxy('condition_map', 'condition')
934 EncounterSlotCondition.condition = relation(EncounterCondition,
935 backref='slot_map')
936
937 EvolutionChain.growth_rate = relation(GrowthRate, backref='evolution_chains')
938 EvolutionChain.baby_trigger_item = relation(Item, backref='evolution_chains')
939
940 Experience.growth_rate = relation(GrowthRate, backref='experience_table')
941
942 Generation.canonical_pokedex = relation(Pokedex, backref='canonical_for_generation')
943 Generation.versions = relation(Version, secondary=VersionGroup.__table__)
944 Generation.main_region = relation(Region)
945
946 GrowthRate.max_experience_obj = relation(Experience, primaryjoin=and_(Experience.growth_rate_id == GrowthRate.id, Experience.level == 100), uselist=False)
947 GrowthRate.max_experience = association_proxy('max_experience_obj', 'experience')
948
949 Item.berry = relation(Berry, uselist=False, backref='item')
950 Item.flags = relation(ItemFlag, secondary=ItemFlagMap.__table__)
951 Item.flavor_text = relation(ItemFlavorText, order_by=ItemFlavorText.version_group_id.asc(), backref='item')
952 Item.fling_effect = relation(ItemFlingEffect, backref='items')
953 Item.foreign_names = relation(ItemName, backref='item')
954 Item.machines = relation(Machine, order_by=Machine.version_group_id.asc())
955 Item.category = relation(ItemCategory)
956 Item.pocket = association_proxy('category', 'pocket')
957
958 ItemCategory.items = relation(Item, order_by=Item.name)
959 ItemCategory.pocket = relation(ItemPocket)
960
961 ItemFlavorText.version_group = relation(VersionGroup)
962
963 ItemInternalID.item = relation(Item, backref='internal_ids')
964 ItemInternalID.generation = relation(Generation)
965
966 ItemName.language = relation(Language)
967
968 ItemPocket.categories = relation(ItemCategory, order_by=ItemCategory.name)
969
970 Location.region = relation(Region, backref='locations')
971
972 LocationArea.location = relation(Location, backref='areas')
973
974 LocationInternalID.location = relation(Location, backref='internal_ids')
975 LocationInternalID.generation = relation(Generation)
976
977 Machine.item = relation(Item)
978 Machine.version_group = relation(VersionGroup)
979
980 Move.contest_effect = relation(ContestEffect, backref='moves')
981 Move.contest_combo_next = association_proxy('contest_combo_first', 'second')
982 Move.contest_combo_prev = association_proxy('contest_combo_second', 'first')
983 Move.contest_type = relation(ContestType, backref='moves')
984 Move.damage_class = relation(MoveDamageClass, backref='moves')
985 Move.flags = association_proxy('move_flags', 'flag')
986 Move.flavor_text = relation(MoveFlavorText, order_by=MoveFlavorText.version_group_id, backref='move')
987 Move.foreign_names = relation(MoveName, backref='move')
988 Move.generation = relation(Generation, backref='moves')
989 Move.machines = relation(Machine, backref='move')
990 Move.move_effect = relation(MoveEffect, backref='moves')
991 Move.move_flags = relation(MoveFlag, backref='move')
992 Move.super_contest_effect = relation(SuperContestEffect, backref='moves')
993 Move.super_contest_combo_next = association_proxy('super_contest_combo_first', 'second')
994 Move.super_contest_combo_prev = association_proxy('super_contest_combo_second', 'first')
995 Move.target = relation(MoveTarget, backref='moves')
996 Move.type = relation(Type, backref='moves')
997
998 Move.effect = markdown.MoveEffectProperty('effect')
999 Move.short_effect = markdown.MoveEffectProperty('short_effect')
1000
1001 MoveEffect.category_map = relation(MoveEffectCategoryMap)
1002 MoveEffect.categories = association_proxy('category_map', 'category')
1003 MoveEffectCategoryMap.category = relation(MoveEffectCategory)
1004
1005 MoveFlag.flag = relation(MoveFlagType)
1006
1007 MoveFlavorText.version_group = relation(VersionGroup)
1008
1009 MoveName.language = relation(Language)
1010
1011 Nature.foreign_names = relation(NatureName, backref='nature')
1012 Nature.decreased_stat = relation(Stat, primaryjoin=Nature.decreased_stat_id==Stat.id,
1013 backref='decreasing_natures')
1014 Nature.increased_stat = relation(Stat, primaryjoin=Nature.increased_stat_id==Stat.id,
1015 backref='increasing_natures')
1016 Nature.hates_flavor = relation(ContestType, primaryjoin=Nature.hates_flavor_id==ContestType.id,
1017 backref='hating_natures')
1018 Nature.likes_flavor = relation(ContestType, primaryjoin=Nature.likes_flavor_id==ContestType.id,
1019 backref='liking_natures')
1020 Nature.battle_style_preferences = relation(NatureBattleStylePreference,
1021 order_by=NatureBattleStylePreference.move_battle_style_id,
1022 backref='nature')
1023 Nature.pokeathlon_effects = relation(NaturePokeathlonStat, order_by=NaturePokeathlonStat.pokeathlon_stat_id)
1024
1025 NatureBattleStylePreference.battle_style = relation(MoveBattleStyle, backref='nature_preferences')
1026
1027 NatureName.language = relation(Language)
1028
1029 NaturePokeathlonStat.pokeathlon_stat = relation(PokeathlonStat, backref='nature_effects')
1030
1031 Pokedex.region = relation(Region, backref='pokedexes')
1032 Pokedex.version_groups = relation(VersionGroup, secondary=PokedexVersionGroup.__table__, backref='pokedexes')
1033
1034 Pokemon.abilities = relation(Ability, secondary=PokemonAbility.__table__,
1035 order_by=PokemonAbility.slot,
1036 backref='pokemon')
1037 Pokemon.formes = relation(Pokemon, primaryjoin=Pokemon.id==Pokemon.forme_base_pokemon_id,
1038 backref=backref('forme_base_pokemon',
1039 remote_side=[Pokemon.id]))
1040 Pokemon.pokemon_color = relation(PokemonColor, backref='pokemon')
1041 Pokemon.color = association_proxy('pokemon_color', 'name')
1042 Pokemon.dex_numbers = relation(PokemonDexNumber, order_by=PokemonDexNumber.pokedex_id.asc(), backref='pokemon')
1043 Pokemon.default_form_sprite = relation(PokemonFormSprite,
1044 primaryjoin=and_(
1045 Pokemon.id==PokemonFormSprite.pokemon_id,
1046 PokemonFormSprite.is_default==True,
1047 ),
1048 uselist=False)
1049 Pokemon.egg_groups = relation(EggGroup, secondary=PokemonEggGroup.__table__,
1050 order_by=PokemonEggGroup.egg_group_id,
1051 backref='pokemon')
1052 Pokemon.evolution_chain = relation(EvolutionChain, backref='pokemon')
1053 Pokemon.child_pokemon = relation(Pokemon,
1054 primaryjoin=Pokemon.id==PokemonEvolution.from_pokemon_id,
1055 secondary=PokemonEvolution.__table__,
1056 secondaryjoin=PokemonEvolution.to_pokemon_id==Pokemon.id,
1057 backref=backref('parent_pokemon', uselist=False),
1058 )
1059 Pokemon.flavor_text = relation(PokemonFlavorText, order_by=PokemonFlavorText.version_id.asc(), backref='pokemon')
1060 Pokemon.foreign_names = relation(PokemonName, backref='pokemon')
1061 Pokemon.pokemon_habitat = relation(PokemonHabitat, backref='pokemon')
1062 Pokemon.habitat = association_proxy('pokemon_habitat', 'name')
1063 Pokemon.items = relation(PokemonItem, backref='pokemon')
1064 Pokemon.generation = relation(Generation, backref='pokemon')
1065 Pokemon.shape = relation(PokemonShape, backref='pokemon')
1066 Pokemon.stats = relation(PokemonStat, backref='pokemon', order_by=PokemonStat.stat_id.asc())
1067 Pokemon.types = relation(Type, secondary=PokemonType.__table__, order_by=PokemonType.slot.asc())
1068
1069 PokemonDexNumber.pokedex = relation(Pokedex)
1070
1071 PokemonEvolution.from_pokemon = relation(Pokemon,
1072 primaryjoin=PokemonEvolution.from_pokemon_id==Pokemon.id,
1073 backref='child_evolutions',
1074 )
1075 PokemonEvolution.to_pokemon = relation(Pokemon,
1076 primaryjoin=PokemonEvolution.to_pokemon_id==Pokemon.id,
1077 backref=backref('parent_evolution', uselist=False),
1078 )
1079 PokemonEvolution.child_evolutions = relation(PokemonEvolution,
1080 primaryjoin=PokemonEvolution.from_pokemon_id==PokemonEvolution.to_pokemon_id,
1081 foreign_keys=[PokemonEvolution.to_pokemon_id],
1082 backref=backref('parent_evolution',
1083 remote_side=[PokemonEvolution.from_pokemon_id],
1084 uselist=False,
1085 ),
1086 )
1087 PokemonEvolution.trigger = relation(EvolutionTrigger, backref='evolutions')
1088 PokemonEvolution.trigger_item = relation(Item,
1089 primaryjoin=PokemonEvolution.trigger_item_id==Item.id,
1090 backref='triggered_evolutions',
1091 )
1092 PokemonEvolution.held_item = relation(Item,
1093 primaryjoin=PokemonEvolution.held_item_id==Item.id,
1094 backref='required_for_evolutions',
1095 )
1096 PokemonEvolution.location = relation(Location, backref='triggered_evolutions')
1097 PokemonEvolution.known_move = relation(Move, backref='triggered_evolutions')
1098 PokemonEvolution.party_pokemon = relation(Pokemon,
1099 primaryjoin=PokemonEvolution.party_pokemon_id==Pokemon.id,
1100 backref='triggered_evolutions',
1101 )
1102
1103 PokemonFlavorText.version = relation(Version)
1104
1105 PokemonItem.item = relation(Item, backref='pokemon')
1106 PokemonItem.version = relation(Version)
1107
1108 PokemonFormGroup.pokemon = relation(Pokemon, backref=backref('form_group',
1109 uselist=False))
1110 PokemonFormSprite.pokemon = relation(Pokemon, backref='form_sprites')
1111 PokemonFormSprite.introduced_in = relation(VersionGroup)
1112
1113 PokemonMove.pokemon = relation(Pokemon, backref='pokemon_moves')
1114 PokemonMove.version_group = relation(VersionGroup)
1115 PokemonMove.machine = relation(Machine, backref='pokemon_moves',
1116 primaryjoin=and_(Machine.version_group_id==PokemonMove.version_group_id,
1117 Machine.move_id==PokemonMove.move_id),
1118 foreign_keys=[Machine.version_group_id, Machine.move_id],
1119 uselist=False)
1120 PokemonMove.move = relation(Move, backref='pokemon_moves')
1121 PokemonMove.method = relation(PokemonMoveMethod)
1122
1123 PokemonName.language = relation(Language)
1124
1125 PokemonStat.stat = relation(Stat)
1126
1127 # This is technically a has-many; Generation.main_region_id -> Region.id
1128 Region.generation = relation(Generation, uselist=False)
1129 Region.version_group_regions = relation(VersionGroupRegion, backref='region',
1130 order_by='VersionGroupRegion.version_group_id')
1131 Region.version_groups = association_proxy('version_group_regions', 'version_group')
1132
1133 Stat.damage_class = relation(MoveDamageClass, backref='stats')
1134
1135 SuperContestCombo.first = relation(Move, primaryjoin=SuperContestCombo.first_move_id==Move.id,
1136 backref='super_contest_combo_first')
1137 SuperContestCombo.second = relation(Move, primaryjoin=SuperContestCombo.second_move_id==Move.id,
1138 backref='super_contest_combo_second')
1139
1140 Type.damage_efficacies = relation(TypeEfficacy,
1141 primaryjoin=Type.id
1142 ==TypeEfficacy.damage_type_id,
1143 backref='damage_type')
1144 Type.target_efficacies = relation(TypeEfficacy,
1145 primaryjoin=Type.id
1146 ==TypeEfficacy.target_type_id,
1147 backref='target_type')
1148
1149 Type.generation = relation(Generation, backref='types')
1150 Type.damage_class = relation(MoveDamageClass, backref='types')
1151 Type.foreign_names = relation(TypeName, backref='type')
1152
1153 TypeName.language = relation(Language)
1154
1155 Version.version_group = relation(VersionGroup, backref='versions')
1156 Version.generation = association_proxy('version_group', 'generation')
1157
1158 VersionGroup.generation = relation(Generation, backref='version_groups')
1159 VersionGroup.version_group_regions = relation(VersionGroupRegion, backref='version_group')
1160 VersionGroup.regions = association_proxy('version_group_regions', 'region')