# encoding: utf8
-from sqlalchemy import Column, ForeignKey, MetaData, Table
+u"""The Pokédex schema
+
+Columns have a info dictionary with these keys:
+- description: The description of the column
+- official: True if the values appear in games or official material; False if
+ they are fan-created or fan-written. This flag is currently only set for
+ official text columns.
+- markup: The format of a text column. Can be one of:
+ - plaintext: Normal Unicode text (widely used in names)
+ - markdown: Veekun's Markdown flavor (generally used in effect descriptions)
+ - gametext: Transcription of in-game text that strives to be both
+ human-readable and represent the original text exactly.
+ - identifier: A fan-made identifier in the [-_a-z0-9]* format. Not intended
+ for translation.
+ - latex: A formula in LaTeX syntax.
+- foreign: If set, the column contains foreign (non-English) text.
+
+"""
+# XXX: Check if "gametext" is set correctly everywhere
+
+# XXX: Some columns paradoxically have official=True and markup='identifier'.
+# This is when one column is used as both the English name (lowercased) and
+# an identifier. This should be fixed.
+
+from sqlalchemy import Column, ForeignKey, MetaData, PrimaryKeyConstraint, Table
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.ext.associationproxy import association_proxy
from sqlalchemy.orm import backref, eagerload_all, relation
from sqlalchemy.sql import and_
from sqlalchemy.types import *
-from pokedex.db import rst
+from pokedex.db import markdown
metadata = MetaData()
TableBase = declarative_base(metadata=metadata)
class Ability(TableBase):
+ """An ability a pokémon can have, such as Static or Pressure.
+ """
__tablename__ = 'abilities'
__singlename__ = 'ability'
- id = Column(Integer, primary_key=True, nullable=False)
- name = Column(Unicode(24), nullable=False)
- generation_id = Column(Integer, ForeignKey('generations.id'), nullable=False)
- effect = Column(rst.RstTextColumn(5120), nullable=False)
- short_effect = Column(rst.RstTextColumn(255), nullable=False)
+ id = Column(Integer, primary_key=True, nullable=False,
+ info=dict(description="A numeric ID"))
+ name = Column(Unicode(24), nullable=False,
+ info=dict(description="The official English name of this ability", official=True, format='plaintext'))
+ generation_id = Column(Integer, ForeignKey('generations.id'), nullable=False,
+ info=dict(description="ID of the generation this ability was introduced in", detail=True))
+ effect = Column(markdown.MarkdownColumn(5120), nullable=False,
+ info=dict(description="Detailed description of this ability's effect", format='markdown'))
+ short_effect = Column(markdown.MarkdownColumn(255), nullable=False,
+ info=dict(description="Short summary of this ability's effect", format='markdown'))
class AbilityFlavorText(TableBase):
+ """In-game flavor text of an ability
+ """
__tablename__ = 'ability_flavor_text'
- ability_id = Column(Integer, ForeignKey('abilities.id'), primary_key=True, nullable=False, autoincrement=False)
- version_group_id = Column(Integer, ForeignKey('version_groups.id'), primary_key=True, nullable=False, autoincrement=False)
- flavor_text = Column(Unicode(64), nullable=False)
+ ability_id = Column(Integer, ForeignKey('abilities.id'), primary_key=True, nullable=False, autoincrement=False,
+ info=dict(description="A numeric ID"))
+ version_group_id = Column(Integer, ForeignKey('version_groups.id'), primary_key=True, nullable=False, autoincrement=False,
+ info=dict(description="The versions this flavor text is shown in"))
+ flavor_text = Column(Unicode(64), nullable=False,
+ info=dict(description="The actual flavor text", official=True, format='gametext'))
+
+class AbilityName(TableBase):
+ """Non-English official name of an ability
+ """
+ __tablename__ = 'ability_names'
+ ability_id = Column(Integer, ForeignKey('abilities.id'), primary_key=True, nullable=False, autoincrement=False,
+ info=dict(description="ID of the ability"))
+ language_id = Column(Integer, ForeignKey('languages.id'), primary_key=True, nullable=False, autoincrement=False,
+ info=dict(description="ID of the language"))
+ name = Column(Unicode(16), nullable=False,
+ info=dict(description="ID of the language", official=True, foreign=True, format='plaintext'))
class Berry(TableBase):
+ """A Berry, consumable item that grows on trees
+
+ For data common to all Items, such as the name, see the corresponding Item entry.
+ """
__tablename__ = 'berries'
- id = Column(Integer, primary_key=True, nullable=False)
- item_id = Column(Integer, ForeignKey('items.id'), nullable=False)
- firmness_id = Column(Integer, ForeignKey('berry_firmness.id'), nullable=False)
- natural_gift_power = Column(Integer, nullable=True)
- natural_gift_type_id = Column(Integer, ForeignKey('types.id'), nullable=True)
- size = Column(Integer, nullable=False)
- max_harvest = Column(Integer, nullable=False)
- growth_time = Column(Integer, nullable=False)
- soil_dryness = Column(Integer, nullable=False)
- smoothness = Column(Integer, nullable=False)
+ id = Column(Integer, primary_key=True, nullable=False,
+ info=dict(description="A numeric ID"))
+ item_id = Column(Integer, ForeignKey('items.id'), nullable=False,
+ info=dict(description="ID of the Item this Berry corresponds to"))
+ firmness_id = Column(Integer, ForeignKey('berry_firmness.id'), nullable=False,
+ info=dict(description="ID of this berry's firmness"))
+ natural_gift_power = Column(Integer, nullable=True,
+ info=dict(description="Power of Natural Gift when that move is used with this Berry"))
+ natural_gift_type_id = Column(Integer, ForeignKey('types.id'), nullable=True,
+ info=dict(description="ID of the Type that Natural Gift will have when used with this Berry"))
+ size = Column(Integer, nullable=False,
+ info=dict(description=u"Size of this Berry, in millimeters"))
+ max_harvest = Column(Integer, nullable=False,
+ info=dict(description="Maximum number of these berries that can grow on one tree"))
+ growth_time = Column(Integer, nullable=False,
+ info=dict(description="Time it takes the tree to grow one stage, in hours. Multiply by four to get overall time."))
+ soil_dryness = Column(Integer, nullable=False,
+ info=dict(description="The speed of soil drying the tree causes")) # XXX: What's this exactly? I'm not a good farmer
+ smoothness = Column(Integer, nullable=False,
+ info=dict(description="Smoothness of this Berry, a culinary attribute. Higher is better."))
class BerryFirmness(TableBase):
+ """A Berry firmness, such as "hard" or "very soft".
+ """
__tablename__ = 'berry_firmness'
- id = Column(Integer, primary_key=True, nullable=False)
- name = Column(Unicode(10), nullable=False)
+ id = Column(Integer, primary_key=True, nullable=False,
+ info=dict(description="A numeric ID"))
+ name = Column(Unicode(10), nullable=False,
+ info=dict(description="English name of the firmness level", official=True, format='plaintext'))
class BerryFlavor(TableBase):
+ """A Berry flavor level.
+ """
__tablename__ = 'berry_flavors'
- berry_id = Column(Integer, ForeignKey('berries.id'), primary_key=True, nullable=False, autoincrement=False)
- contest_type_id = Column(Integer, ForeignKey('contest_types.id'), primary_key=True, nullable=False, autoincrement=False)
- flavor = Column(Integer, nullable=False)
+ berry_id = Column(Integer, ForeignKey('berries.id'), primary_key=True, nullable=False, autoincrement=False,
+ info=dict(description="ID of the berry"))
+ contest_type_id = Column(Integer, ForeignKey('contest_types.id'), primary_key=True, nullable=False, autoincrement=False,
+ info=dict(description="ID of the flavor"))
+ flavor = Column(Integer, nullable=False,
+ info=dict(description="Level of the flavor in the berry"))
class ContestCombo(TableBase):
+ """Combo of two moves in a Contest.
+ """
__tablename__ = 'contest_combos'
- first_move_id = Column(Integer, ForeignKey('moves.id'), primary_key=True, nullable=False, autoincrement=False)
- second_move_id = Column(Integer, ForeignKey('moves.id'), primary_key=True, nullable=False, autoincrement=False)
+ first_move_id = Column(Integer, ForeignKey('moves.id'), primary_key=True, nullable=False, autoincrement=False,
+ info=dict(description="ID of the first move in the combo"))
+ second_move_id = Column(Integer, ForeignKey('moves.id'), primary_key=True, nullable=False, autoincrement=False,
+ info=dict(description="ID of the second and final move in the combo"))
class ContestEffect(TableBase):
+ """Effect of a move when used in a Contest.
+ """
__tablename__ = 'contest_effects'
- id = Column(Integer, primary_key=True, nullable=False)
- appeal = Column(SmallInteger, nullable=False)
- jam = Column(SmallInteger, nullable=False)
- flavor_text = Column(Unicode(64), nullable=False)
- effect = Column(Unicode(255), nullable=False)
+ id = Column(Integer, primary_key=True, nullable=False,
+ info=dict(description="A numeric ID"))
+ appeal = Column(SmallInteger, nullable=False,
+ info=dict(description="The base number of hearts the user of this move gets"))
+ jam = Column(SmallInteger, nullable=False,
+ info=dict(description="The base number of hearts the user's opponent loses"))
+ flavor_text = Column(Unicode(64), nullable=False,
+ info=dict(description="English in-game description of this effect", official=True, format='gametext'))
+ effect = Column(Unicode(255), nullable=False,
+ info=dict(description="Detailed description of the effect", format='markdown'))
class ContestType(TableBase):
+ u"""A Contest type, such as "cool" or "smart". Also functions as Berry flavor and Pokéblock color."""
__tablename__ = 'contest_types'
- id = Column(Integer, primary_key=True, nullable=False)
- name = Column(Unicode(6), nullable=False)
- flavor = Column(Unicode(6), nullable=False)
- color = Column(Unicode(6), nullable=False)
+ id = Column(Integer, primary_key=True, nullable=False,
+ info=dict(description="A numeric ID"))
+ name = Column(Unicode(6), nullable=False,
+ info=dict(description="The English name of the Contest type", official=True, format='identifier'))
+ flavor = Column(Unicode(6), nullable=False,
+ info=dict(description="The English name of the corresponding Berry flavor", official=True, format='identifier'))
+ color = Column(Unicode(6), nullable=False,
+ info=dict(description="The English name of the corresponding Pokéblock color", official=True, format='identifier'))
class EggGroup(TableBase):
+ """An Egg group. Usually, two Pokémon can breed if they share an Egg Group.
+
+ (exceptions are the Ditto and No Eggs groups)
+ """
__tablename__ = 'egg_groups'
- id = Column(Integer, primary_key=True, nullable=False)
- name = Column(Unicode(16), nullable=False)
+ id = Column(Integer, primary_key=True, nullable=False,
+ info=dict(description="A numeric ID"))
+ name = Column(Unicode(16), nullable=False,
+ info=dict(description="The English “official” name. One NPC in Stadium uses these names; they are pretty bad.", official=True, format='identifier'))
class Encounter(TableBase):
- """Rows in this table represent encounters with wild Pokémon. Bear with
- me, here.
+ """Encounters with wild Pokémon.
+
+ Bear with me, here.
Within a given area in a given game, encounters are differentiated by the
"slot" they are in and the state of the game world.
"""
__tablename__ = 'encounters'
- id = Column(Integer, primary_key=True, nullable=False)
- version_id = Column(Integer, ForeignKey('versions.id'), nullable=False, autoincrement=False)
- location_area_id = Column(Integer, ForeignKey('location_areas.id'), nullable=False, autoincrement=False)
- encounter_slot_id = Column(Integer, ForeignKey('encounter_slots.id'), nullable=False, autoincrement=False)
- pokemon_id = Column(Integer, ForeignKey('pokemon.id'), nullable=False, autoincrement=False)
- min_level = Column(Integer, nullable=False, autoincrement=False)
- max_level = Column(Integer, nullable=False, autoincrement=False)
+ id = Column(Integer, primary_key=True, nullable=False,
+ info=dict(description="A numeric ID"))
+ version_id = Column(Integer, ForeignKey('versions.id'), nullable=False, autoincrement=False,
+ info=dict(description="The ID of the Version this applies to"))
+ location_area_id = Column(Integer, ForeignKey('location_areas.id'), nullable=False, autoincrement=False,
+ info=dict(description="The ID of the Location of this encounter"))
+ encounter_slot_id = Column(Integer, ForeignKey('encounter_slots.id'), nullable=False, autoincrement=False,
+ info=dict(description="The ID of the encounter slot, which determines terrain and rarity"))
+ pokemon_id = Column(Integer, ForeignKey('pokemon.id'), nullable=False, autoincrement=False,
+ info=dict(description=u"The ID of the encountered Pokémon"))
+ min_level = Column(Integer, nullable=False, autoincrement=False,
+ info=dict(description=u"The minimum level of the encountered Pokémon"))
+ max_level = Column(Integer, nullable=False, autoincrement=False,
+ info=dict(description=u"The maxmum level of the encountered Pokémon"))
class EncounterCondition(TableBase):
- """Rows in this table represent varying conditions in the game world, such
- as time of day.
+ """A conditions in the game world that affects pokémon encounters, such as time of day.
"""
__tablename__ = 'encounter_conditions'
- id = Column(Integer, primary_key=True, nullable=False)
- name = Column(Unicode(64), nullable=False)
+ id = Column(Integer, primary_key=True, nullable=False,
+ info=dict(description="A numeric ID"))
+ name = Column(Unicode(64), nullable=False,
+ info=dict(description="An English name of the condition", format='plaintext'))
class EncounterConditionValue(TableBase):
- """Rows in this table represent possible states for a condition; for
- example, the state of 'swarm' could be 'swarm' or 'no swarm'.
+ """A possible state for a condition; for example, the state of 'swarm' could be 'swarm' or 'no swarm'.
"""
__tablename__ = 'encounter_condition_values'
- id = Column(Integer, primary_key=True, nullable=False)
- encounter_condition_id = Column(Integer, ForeignKey('encounter_conditions.id'), primary_key=False, nullable=False, autoincrement=False)
- name = Column(Unicode(64), nullable=False)
- is_default = Column(Boolean, nullable=False)
+ id = Column(Integer, primary_key=True, nullable=False,
+ info=dict(description="A numeric ID"))
+ encounter_condition_id = Column(Integer, ForeignKey('encounter_conditions.id'), primary_key=False, nullable=False, autoincrement=False,
+ info=dict(description="The ID of the encounter condition this is a value of"))
+ name = Column(Unicode(64), nullable=False,
+ info=dict(description="An english name of this value", format='plaintext'))
+ is_default = Column(Boolean, nullable=False,
+ info=dict(description='Set if this value is "default" or "normal" in some sense'))
class EncounterConditionValueMap(TableBase):
"""Maps encounters to the specific conditions under which they occur."""
__tablename__ = 'encounter_condition_value_map'
- encounter_id = Column(Integer, ForeignKey('encounters.id'), primary_key=True, nullable=False, autoincrement=False)
- encounter_condition_value_id = Column(Integer, ForeignKey('encounter_condition_values.id'), primary_key=True, nullable=False, autoincrement=False)
+ encounter_id = Column(Integer, ForeignKey('encounters.id'), primary_key=True, nullable=False, autoincrement=False,
+ info=dict(description="ID of the encounter"))
+ encounter_condition_value_id = Column(Integer, ForeignKey('encounter_condition_values.id'), primary_key=True, nullable=False, autoincrement=False,
+ info=dict(description="ID of the encounter condition value"))
class EncounterTerrain(TableBase):
- """Rows in this table represent ways the player can enter a wild encounter,
- e.g., surfing, fishing, or walking through tall grass.
+ """A way the player can enter a wild encounter, e.g., surfing, fishing, or walking through tall grass.
"""
__tablename__ = 'encounter_terrain'
- id = Column(Integer, primary_key=True, nullable=False)
- name = Column(Unicode(64), nullable=False)
+ id = Column(Integer, primary_key=True, nullable=False,
+ info=dict(description="A numeric ID"))
+ name = Column(Unicode(64), nullable=False,
+ info=dict(description="An english name of this terrain", format='plaintext'))
class EncounterSlot(TableBase):
- """Rows in this table represent an abstract "slot" within a terrain,
- associated with both some set of conditions and a rarity.
+ """Aan abstract "slot" within a terrain, associated with both some set of conditions and a rarity.
Note that there are two encounters per slot, so the rarities will only add
up to 50.
"""
__tablename__ = 'encounter_slots'
- id = Column(Integer, primary_key=True, nullable=False)
- version_group_id = Column(Integer, ForeignKey('version_groups.id'), nullable=False, autoincrement=False)
- encounter_terrain_id = Column(Integer, ForeignKey('encounter_terrain.id'), primary_key=False, nullable=False, autoincrement=False)
+ id = Column(Integer, primary_key=True, nullable=False,
+ info=dict(description="A numeric ID"))
+ version_group_id = Column(Integer, ForeignKey('version_groups.id'), nullable=False, autoincrement=False,
+ info=dict(description="The ID of the Version group this slot is in"))
+ encounter_terrain_id = Column(Integer, ForeignKey('encounter_terrain.id'), primary_key=False, nullable=False, autoincrement=False,
+ info=dict(description="The ID of the terrain"))
slot = Column(Integer, nullable=True)
- rarity = Column(Integer, nullable=False)
+ # XXX: What is this?
+ rarity = Column(Integer, nullable=False,
+ info=dict(description="The chance of the encounter, in percent")) # XXX: It is in percent, right? I'm confused.
class EncounterSlotCondition(TableBase):
- """Lists all conditions that affect each slot."""
+ """A condition that affects an encounter slot."""
__tablename__ = 'encounter_slot_conditions'
- encounter_slot_id = Column(Integer, ForeignKey('encounter_slots.id'), primary_key=True, nullable=False, autoincrement=False)
- encounter_condition_id = Column(Integer, ForeignKey('encounter_conditions.id'), primary_key=True, nullable=False, autoincrement=False)
+ encounter_slot_id = Column(Integer, ForeignKey('encounter_slots.id'), primary_key=True, nullable=False, autoincrement=False,
+ info=dict(description="The ID of the encounter slot"))
+ encounter_condition_id = Column(Integer, ForeignKey('encounter_conditions.id'), primary_key=True, nullable=False, autoincrement=False,
+ info=dict(description="The ID of the encounter condition"))
class EvolutionChain(TableBase):
+ """A family of pokémon that are linked by evolution"""
__tablename__ = 'evolution_chains'
- id = Column(Integer, primary_key=True, nullable=False)
- growth_rate_id = Column(Integer, ForeignKey('growth_rates.id'), nullable=False)
- steps_to_hatch = Column(Integer, nullable=False)
- baby_trigger_item = Column(Unicode(12))
+ id = Column(Integer, primary_key=True, nullable=False,
+ info=dict(description="A numeric ID"))
+ growth_rate_id = Column(Integer, ForeignKey('growth_rates.id'), nullable=False,
+ info=dict(description="ID of the growth rate for this family"))
+ baby_trigger_item_id = Column(Integer, ForeignKey('items.id'), nullable=True,
+ info=dict(description="Item that a parent must hold while breeding to produce a baby"))
class EvolutionTrigger(TableBase):
+ """An evolution type, such as "level" or "trade"."""
__tablename__ = 'evolution_triggers'
- id = Column(Integer, primary_key=True, nullable=False)
- identifier = Column(Unicode(16), nullable=False)
+ id = Column(Integer, primary_key=True, nullable=False,
+ info=dict(description="A numeric ID"))
+ identifier = Column(Unicode(16), nullable=False,
+ info=dict(description="An English identifier", format='identifier'))
class Experience(TableBase):
+ """EXP needed for a certain level with a certain growth rate"""
__tablename__ = 'experience'
- growth_rate_id = Column(Integer, ForeignKey('growth_rates.id'), primary_key=True, nullable=False)
- level = Column(Integer, primary_key=True, nullable=False, autoincrement=False)
- experience = Column(Integer, nullable=False)
+ growth_rate_id = Column(Integer, ForeignKey('growth_rates.id'), primary_key=True, nullable=False,
+ info=dict(description="ID of the growth rate"))
+ level = Column(Integer, primary_key=True, nullable=False, autoincrement=False,
+ info=dict(description="The level"))
+ experience = Column(Integer, nullable=False,
+ info=dict(description="The number of EXP points needed to get to that level"))
class Generation(TableBase):
+ u"""A Generation of the pokémon franchise"""
__tablename__ = 'generations'
- id = Column(Integer, primary_key=True, nullable=False)
- main_region_id = Column(Integer, ForeignKey('regions.id'))
- canonical_pokedex_id = Column(Integer, ForeignKey('pokedexes.id'))
- name = Column(Unicode(16), nullable=False)
+ id = Column(Integer, primary_key=True, nullable=False,
+ info=dict(description="A numeric ID"))
+ main_region_id = Column(Integer, ForeignKey('regions.id'),
+ info=dict(description="ID of the region this generation's main games take place in"))
+ canonical_pokedex_id = Column(Integer, ForeignKey('pokedexes.id'),
+ info=dict(description=u"ID of the pokédex this generation's main games use by default"))
+ name = Column(Unicode(16), nullable=False,
+ info=dict(description=u'An English name of this generation, such as "Generation IV"', format='plaintext'))
class GrowthRate(TableBase):
- """`formula` is written in LaTeX math notation."""
+ u"""Growth rate of a pokémon, i.e. the EXP → level function."""
__tablename__ = 'growth_rates'
- id = Column(Integer, primary_key=True, nullable=False)
- name = Column(Unicode(20), nullable=False)
- formula = Column(Unicode(500), nullable=False)
+ id = Column(Integer, primary_key=True, nullable=False,
+ info=dict(description="A numeric ID"))
+ name = Column(Unicode(20), nullable=False,
+ info=dict(description="A name for the", format='identifier'))
+ formula = Column(Unicode(500), nullable=False,
+ info=dict(description="The formula", format='latex'))
class Item(TableBase):
+ """An Item from the games, like "Poké Ball" or "Bicycle"."""
__tablename__ = 'items'
__singlename__ = 'item'
- id = Column(Integer, primary_key=True, nullable=False)
- name = Column(Unicode(16), nullable=False)
- category_id = Column(Integer, ForeignKey('item_categories.id'), nullable=False)
- cost = Column(Integer, nullable=False)
- fling_power = Column(Integer, nullable=True)
- fling_effect_id = Column(Integer, ForeignKey('item_fling_effects.id'), nullable=True)
- effect = Column(rst.RstTextColumn(5120), nullable=False)
+ id = Column(Integer, primary_key=True, nullable=False,
+ info=dict(description="A numeric ID"))
+ name = Column(Unicode(20), nullable=False,
+ info=dict(description="The English name of the item", official=True, format='plaintext'))
+ category_id = Column(Integer, ForeignKey('item_categories.id'), nullable=False,
+ info=dict(description="ID of a category this item belongs to"))
+ cost = Column(Integer, nullable=False,
+ info=dict(description=u"Cost of the item when bought. Items sell for half this price."))
+ fling_power = Column(Integer, nullable=True,
+ info=dict(description=u"Power of the move Fling when used with this item."))
+ fling_effect_id = Column(Integer, ForeignKey('item_fling_effects.id'), nullable=True,
+ 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."))
+ effect = Column(markdown.MarkdownColumn(5120), nullable=False,
+ info=dict(description=u"Detailed English description of the item's effect.", format='markdown'))
@property
def appears_underground(self):
+ """True if the item appears underground, as specified by the appropriate flag"""
return any(flag.identifier == u'underground' for flag in self.flags)
class ItemCategory(TableBase):
+ """An item category"""
+ # XXX: This is fanon, right?
__tablename__ = 'item_categories'
- id = Column(Integer, primary_key=True, nullable=False)
- pocket_id = Column(Integer, ForeignKey('item_pockets.id'), nullable=False)
- name = Column(Unicode(16), nullable=False)
+ id = Column(Integer, primary_key=True, nullable=False,
+ info=dict(description="A numeric ID"))
+ pocket_id = Column(Integer, ForeignKey('item_pockets.id'), nullable=False,
+ info=dict(description="ID of the pocket these items go to"))
+ name = Column(Unicode(16), nullable=False,
+ info=dict(description="English name of the category", format='plaintext'))
class ItemFlag(TableBase):
+ """An item attribute such as "consumable" or "holdable"."""
__tablename__ = 'item_flags'
- id = Column(Integer, primary_key=True, nullable=False)
- identifier = Column(Unicode(24), nullable=False)
- name = Column(Unicode(64), nullable=False)
+ id = Column(Integer, primary_key=True, nullable=False,
+ info=dict(description="A numeric ID"))
+ identifier = Column(Unicode(24), nullable=False,
+ info=dict(description="Identifier of the flag", format='identifier'))
+ name = Column(Unicode(64), nullable=False,
+ info=dict(description="Short English description of the flag", format='plaintext'))
class ItemFlagMap(TableBase):
+ """Maps an item flag to its item."""
__tablename__ = 'item_flag_map'
- item_id = Column(Integer, ForeignKey('items.id'), primary_key=True, autoincrement=False, nullable=False)
- item_flag_id = Column(Integer, ForeignKey('item_flags.id'), primary_key=True, autoincrement=False, nullable=False)
+ item_id = Column(Integer, ForeignKey('items.id'), primary_key=True, autoincrement=False, nullable=False,
+ info=dict(description="The ID of the item"))
+ item_flag_id = Column(Integer, ForeignKey('item_flags.id'), primary_key=True, autoincrement=False, nullable=False,
+ info=dict(description="The ID of the item flag"))
class ItemFlavorText(TableBase):
+ """An in-game description of an item"""
__tablename__ = 'item_flavor_text'
- item_id = Column(Integer, ForeignKey('items.id'), primary_key=True, autoincrement=False, nullable=False)
- version_group_id = Column(Integer, ForeignKey('version_groups.id'), primary_key=True, autoincrement=False, nullable=False)
- flavor_text = Column(Unicode(255), nullable=False)
+ item_id = Column(Integer, ForeignKey('items.id'), primary_key=True, autoincrement=False, nullable=False,
+ info=dict(description="The ID of the item"))
+ version_group_id = Column(Integer, ForeignKey('version_groups.id'), primary_key=True, autoincrement=False, nullable=False,
+ info=dict(description="ID of the version group that sports this text"))
+ flavor_text = Column(Unicode(255), nullable=False,
+ info=dict(description="The flavor text itself", official=True, format='gametext'))
class ItemFlingEffect(TableBase):
+ """An effect of the move Fling when used with a specific item"""
__tablename__ = 'item_fling_effects'
- id = Column(Integer, primary_key=True, nullable=False)
- effect = Column(Unicode(255), nullable=False)
+ id = Column(Integer, primary_key=True, nullable=False,
+ info=dict(description="A numeric ID"))
+ effect = Column(Unicode(255), nullable=False,
+ info=dict(description="English description of the effect", format='plaintext'))
class ItemInternalID(TableBase):
+ """The internal ID number a game uses for an item"""
__tablename__ = 'item_internal_ids'
- item_id = Column(Integer, ForeignKey('items.id'), primary_key=True, autoincrement=False, nullable=False)
- generation_id = Column(Integer, ForeignKey('generations.id'), primary_key=True, autoincrement=False, nullable=False)
- internal_id = Column(Integer, nullable=False)
+ item_id = Column(Integer, ForeignKey('items.id'), primary_key=True, autoincrement=False, nullable=False,
+ info=dict(description="The database ID of the item"))
+ generation_id = Column(Integer, ForeignKey('generations.id'), primary_key=True, autoincrement=False, nullable=False,
+ info=dict(description="ID of the generation of games"))
+ internal_id = Column(Integer, nullable=False,
+ info=dict(description="Internal ID of the item in the generation"))
+
+class ItemName(TableBase):
+ """A non-English name of an item"""
+ __tablename__ = 'item_names'
+ item_id = Column(Integer, ForeignKey('items.id'), primary_key=True, nullable=False, autoincrement=False,
+ info=dict(description="The ID of the item"))
+ language_id = Column(Integer, ForeignKey('languages.id'), primary_key=True, nullable=False, autoincrement=False,
+ info=dict(description="The ID of the language"))
+ name = Column(Unicode(16), nullable=False,
+ info=dict(description="The name of the item in this language", foreign=True, format='plaintext'))
class ItemPocket(TableBase):
+ """A pocket that categorizes items"""
__tablename__ = 'item_pockets'
- id = Column(Integer, primary_key=True, nullable=False)
- identifier = Column(Unicode(16), nullable=False)
- name = Column(Unicode(16), nullable=False)
+ id = Column(Integer, primary_key=True, nullable=False,
+ info=dict(description="A numeric ID"))
+ identifier = Column(Unicode(16), nullable=False,
+ info=dict(description="An identifier of this pocket", format='identifier'))
+ name = Column(Unicode(16), nullable=False,
+ info=dict(description="A numeric ID", format='plaintext'))
class Language(TableBase):
+ u"""A language the Pokémon games have been transleted into; except English"""
__tablename__ = 'languages'
- id = Column(Integer, primary_key=True, nullable=False)
- iso639 = Column(Unicode(2), nullable=False)
- iso3166 = Column(Unicode(2), nullable=False)
- name = Column(Unicode(16), nullable=False)
+ id = Column(Integer, primary_key=True, nullable=False,
+ info=dict(description="A numeric ID"))
+ iso639 = Column(Unicode(2), nullable=False,
+ info=dict(description="The two-letter code of the country where this language is spoken. Note that it is not unique."))
+ iso3166 = Column(Unicode(2), nullable=False,
+ info=dict(description="The two-letter code of the language. Note that it is not unique."))
+ name = Column(Unicode(16), nullable=False,
+ info=dict(description="The English name of the language", format='plaintext'))
class Location(TableBase):
__tablename__ = 'locations'
version_id = Column(Integer, ForeignKey('versions.id'), primary_key=True, autoincrement=False)
rate = Column(Integer, nullable=True)
+class LocationInternalID(TableBase):
+ __tablename__ = 'location_internal_ids'
+ location_id = Column(Integer, ForeignKey('locations.id'), nullable=False, primary_key=True)
+ generation_id = Column(Integer, ForeignKey('generations.id'), nullable=False, primary_key=True)
+ internal_id = Column(Integer, nullable=False)
+
class Machine(TableBase):
__tablename__ = 'machines'
machine_number = Column(Integer, primary_key=True, nullable=False, autoincrement=False)
class MoveEffect(TableBase):
__tablename__ = 'move_effects'
id = Column(Integer, primary_key=True, nullable=False)
- priority = Column(SmallInteger, nullable=False)
short_effect = Column(Unicode(256), nullable=False)
effect = Column(Unicode(5120), nullable=False)
class MoveFlagType(TableBase):
__tablename__ = 'move_flag_types'
id = Column(Integer, primary_key=True, nullable=False)
+ identifier = Column(Unicode(16), nullable=False)
name = Column(Unicode(32), nullable=False)
- description = Column(rst.RstTextColumn(128), nullable=False)
+ description = Column(markdown.MarkdownColumn(128), nullable=False)
class MoveFlavorText(TableBase):
__tablename__ = 'move_flavor_text'
__tablename__ = 'moves'
__singlename__ = 'move'
id = Column(Integer, primary_key=True, nullable=False)
- name = Column(Unicode(12), nullable=False)
+ name = Column(Unicode(24), nullable=False)
generation_id = Column(Integer, ForeignKey('generations.id'), nullable=False)
type_id = Column(Integer, ForeignKey('types.id'), nullable=False)
- power = Column(SmallInteger)
+ power = Column(SmallInteger, nullable=False)
pp = Column(SmallInteger, nullable=False)
- accuracy = Column(SmallInteger)
+ accuracy = Column(SmallInteger, nullable=True)
+ priority = Column(SmallInteger, nullable=False)
target_id = Column(Integer, ForeignKey('move_targets.id'), nullable=False)
damage_class_id = Column(Integer, ForeignKey('move_damage_classes.id'), nullable=False)
effect_id = Column(Integer, ForeignKey('move_effects.id'), nullable=False)
effect_chance = Column(Integer)
contest_type_id = Column(Integer, ForeignKey('contest_types.id'), nullable=True)
contest_effect_id = Column(Integer, ForeignKey('contest_effects.id'), nullable=True)
- super_contest_effect_id = Column(Integer, ForeignKey('super_contest_effects.id'), nullable=False)
+ super_contest_effect_id = Column(Integer, ForeignKey('super_contest_effects.id'), nullable=True)
class Nature(TableBase):
__tablename__ = 'natures'
hates_flavor_id = Column(Integer, ForeignKey('contest_types.id'), nullable=False)
likes_flavor_id = Column(Integer, ForeignKey('contest_types.id'), nullable=False)
+ @property
+ def is_neutral(self):
+ u"""Returns True iff this nature doesn't alter a Pokémon's stats,
+ bestow taste preferences, etc.
+ """
+ return self.increased_stat_id == self.decreased_stat_id
+
class NatureBattleStylePreference(TableBase):
__tablename__ = 'nature_battle_style_preferences'
nature_id = Column(Integer, ForeignKey('natures.id'), primary_key=True, nullable=False)
low_hp_preference = Column(Integer, nullable=False)
high_hp_preference = Column(Integer, nullable=False)
+class NatureName(TableBase):
+ __tablename__ = 'nature_names'
+ nature_id = Column(Integer, ForeignKey('natures.id'), primary_key=True, nullable=False, autoincrement=False)
+ language_id = Column(Integer, ForeignKey('languages.id'), primary_key=True, nullable=False, autoincrement=False)
+ name = Column(Unicode(8), nullable=False)
+
class NaturePokeathlonStat(TableBase):
__tablename__ = 'nature_pokeathlon_stats'
nature_id = Column(Integer, ForeignKey('natures.id'), primary_key=True, nullable=False)
weight = Column(Integer, nullable=False)
species = Column(Unicode(16), nullable=False)
color_id = Column(Integer, ForeignKey('pokemon_colors.id'), nullable=False)
- pokemon_shape_id = Column(Integer, ForeignKey('pokemon_shapes.id'), nullable=False)
+ pokemon_shape_id = Column(Integer, ForeignKey('pokemon_shapes.id'), nullable=True)
habitat_id = Column(Integer, ForeignKey('pokemon_habitats.id'), nullable=True)
gender_rate = Column(Integer, nullable=False)
capture_rate = Column(Integer, nullable=False)
base_experience = Column(Integer, nullable=False)
base_happiness = Column(Integer, nullable=False)
is_baby = Column(Boolean, nullable=False)
+ hatch_counter = Column(Integer, nullable=False)
has_gen4_fem_sprite = Column(Boolean, nullable=False)
has_gen4_fem_back_sprite = Column(Boolean, nullable=False)
if pokemon_stat.stat.name == stat_name:
return pokemon_stat
- return None
+ raise KeyError(u'No stat named %s' % stat_name)
+
+ @property
+ def better_damage_class(self):
+ u"""Returns the MoveDamageClass that this Pokémon is best suited for,
+ based on its attack stats.
+
+ If the attack stats are about equal (within 5), returns None. The
+ value None, not the damage class called 'None'.
+ """
+ phys = self.stat(u'Attack')
+ spec = self.stat(u'Special Attack')
+
+ diff = phys.base_stat - spec.base_stat
+
+ if diff > 5:
+ return phys.stat.damage_class
+ elif diff < -5:
+ return spec.stat.damage_class
+ else:
+ return None
class PokemonAbility(TableBase):
__tablename__ = 'pokemon_abilities'
__tablename__ = 'pokemon_form_groups'
pokemon_id = Column(Integer, ForeignKey('pokemon.id'), primary_key=True, nullable=False, autoincrement=False)
is_battle_only = Column(Boolean, nullable=False)
- description = Column(Unicode(512), nullable=False)
+ description = Column(markdown.MarkdownColumn(1024), nullable=False)
class PokemonFormSprite(TableBase):
__tablename__ = 'pokemon_form_sprites'
id = Column(Integer, primary_key=True, nullable=False, autoincrement=False)
name = Column(Unicode(16), nullable=False)
+class PokemonInternalID(TableBase):
+ __tablename__ = 'pokemon_internal_ids'
+ pokemon_id = Column(Integer, ForeignKey('pokemon.id'), primary_key=True, autoincrement=False, nullable=False)
+ generation_id = Column(Integer, ForeignKey('generations.id'), primary_key=True, autoincrement=False, nullable=False)
+ internal_id = Column(Integer, nullable=False)
+
class PokemonItem(TableBase):
__tablename__ = 'pokemon_items'
pokemon_id = Column(Integer, ForeignKey('pokemon.id'), primary_key=True, nullable=False, autoincrement=False)
class PokemonMove(TableBase):
__tablename__ = 'pokemon_moves'
- pokemon_id = Column(Integer, ForeignKey('pokemon.id'), primary_key=True, nullable=False, autoincrement=False)
- version_group_id = Column(Integer, ForeignKey('version_groups.id'), primary_key=True, nullable=False, autoincrement=False)
- move_id = Column(Integer, ForeignKey('moves.id'), primary_key=True, nullable=False, autoincrement=False, index=True)
- pokemon_move_method_id = Column(Integer, ForeignKey('pokemon_move_methods.id'), primary_key=True, nullable=False, autoincrement=False)
- level = Column(Integer, primary_key=True, nullable=True, autoincrement=False)
+ pokemon_id = Column(Integer, ForeignKey('pokemon.id'), nullable=False, index=True)
+ version_group_id = Column(Integer, ForeignKey('version_groups.id'), nullable=False, index=True)
+ move_id = Column(Integer, ForeignKey('moves.id'), nullable=False, index=True)
+ pokemon_move_method_id = Column(Integer, ForeignKey('pokemon_move_methods.id'), nullable=False, index=True)
+ level = Column(Integer, nullable=True, index=True)
order = Column(Integer, nullable=True)
+ __table_args__ = (
+ PrimaryKeyConstraint('pokemon_id', 'version_group_id', 'move_id', 'pokemon_move_method_id', 'level'),
+ {},
+ )
+
class PokemonMoveMethod(TableBase):
__tablename__ = 'pokemon_move_methods'
id = Column(Integer, primary_key=True, nullable=False, autoincrement=False)
class Stat(TableBase):
__tablename__ = 'stats'
id = Column(Integer, primary_key=True, nullable=False)
+ damage_class_id = Column(Integer, ForeignKey('move_damage_classes.id'), nullable=True)
name = Column(Unicode(16), nullable=False)
class SuperContestCombo(TableBase):
generation_id = Column(Integer, ForeignKey('generations.id'), nullable=False)
damage_class_id = Column(Integer, ForeignKey('move_damage_classes.id'), nullable=False) ## ??? is none; everything else is physical or special
+class TypeName(TableBase):
+ __tablename__ = 'type_names'
+ type_id = Column(Integer, ForeignKey('types.id'), primary_key=True, nullable=False, autoincrement=False)
+ language_id = Column(Integer, ForeignKey('languages.id'), primary_key=True, nullable=False, autoincrement=False)
+ name = Column(Unicode(16), nullable=False)
+
class VersionGroup(TableBase):
__tablename__ = 'version_groups'
id = Column(Integer, primary_key=True, nullable=False)
### Relations down here, to avoid ordering problems
-Ability.flavor_text = relation(AbilityFlavorText, order_by=AbilityFlavorText.version_group_id, backref='abilities')
+Ability.flavor_text = relation(AbilityFlavorText, order_by=AbilityFlavorText.version_group_id, backref='ability')
+Ability.foreign_names = relation(AbilityName, backref='ability')
Ability.generation = relation(Generation, backref='abilities')
AbilityFlavorText.version_group = relation(VersionGroup)
+AbilityName.language = relation(Language)
+
Berry.berry_firmness = relation(BerryFirmness, backref='berries')
Berry.firmness = association_proxy('berry_firmness', 'name')
Berry.flavors = relation(BerryFlavor, order_by=BerryFlavor.contest_type_id, backref='berry')
backref='slot_map')
EvolutionChain.growth_rate = relation(GrowthRate, backref='evolution_chains')
+EvolutionChain.baby_trigger_item = relation(Item, backref='evolution_chains')
Experience.growth_rate = relation(GrowthRate, backref='experience_table')
Item.flags = relation(ItemFlag, secondary=ItemFlagMap.__table__)
Item.flavor_text = relation(ItemFlavorText, order_by=ItemFlavorText.version_group_id.asc(), backref='item')
Item.fling_effect = relation(ItemFlingEffect, backref='items')
+Item.foreign_names = relation(ItemName, backref='item')
Item.machines = relation(Machine, order_by=Machine.version_group_id.asc())
Item.category = relation(ItemCategory)
Item.pocket = association_proxy('category', 'pocket')
ItemFlavorText.version_group = relation(VersionGroup)
+ItemInternalID.item = relation(Item, backref='internal_ids')
+ItemInternalID.generation = relation(Generation)
+
+ItemName.language = relation(Language)
+
ItemPocket.categories = relation(ItemCategory, order_by=ItemCategory.name)
Location.region = relation(Region, backref='locations')
LocationArea.location = relation(Location, backref='areas')
+LocationInternalID.location = relation(Location, backref='internal_ids')
+LocationInternalID.generation = relation(Generation)
+
Machine.item = relation(Item)
Machine.version_group = relation(VersionGroup)
Move.damage_class = relation(MoveDamageClass, backref='moves')
Move.flags = association_proxy('move_flags', 'flag')
Move.flavor_text = relation(MoveFlavorText, order_by=MoveFlavorText.version_group_id, backref='move')
-Move.foreign_names = relation(MoveName, backref='pokemon')
+Move.foreign_names = relation(MoveName, backref='move')
Move.generation = relation(Generation, backref='moves')
Move.machines = relation(Machine, backref='move')
Move.move_effect = relation(MoveEffect, backref='moves')
Move.target = relation(MoveTarget, backref='moves')
Move.type = relation(Type, backref='moves')
-Move.effect = rst.MoveEffectProperty('effect')
-Move.priority = association_proxy('move_effect', 'priority')
-Move.short_effect = rst.MoveEffectProperty('short_effect')
+Move.effect = markdown.MoveEffectProperty('effect')
+Move.short_effect = markdown.MoveEffectProperty('short_effect')
MoveEffect.category_map = relation(MoveEffectCategoryMap)
MoveEffect.categories = association_proxy('category_map', 'category')
MoveName.language = relation(Language)
+Nature.foreign_names = relation(NatureName, backref='nature')
Nature.decreased_stat = relation(Stat, primaryjoin=Nature.decreased_stat_id==Stat.id,
backref='decreasing_natures')
Nature.increased_stat = relation(Stat, primaryjoin=Nature.increased_stat_id==Stat.id,
NatureBattleStylePreference.battle_style = relation(MoveBattleStyle, backref='nature_preferences')
+NatureName.language = relation(Language)
+
NaturePokeathlonStat.pokeathlon_stat = relation(PokeathlonStat, backref='nature_effects')
Pokedex.region = relation(Region, backref='pokedexes')
remote_side=[Pokemon.id]))
Pokemon.pokemon_color = relation(PokemonColor, backref='pokemon')
Pokemon.color = association_proxy('pokemon_color', 'name')
-Pokemon.dex_numbers = relation(PokemonDexNumber, backref='pokemon')
+Pokemon.dex_numbers = relation(PokemonDexNumber, order_by=PokemonDexNumber.pokedex_id.asc(), backref='pokemon')
Pokemon.default_form_sprite = relation(PokemonFormSprite,
primaryjoin=and_(
Pokemon.id==PokemonFormSprite.pokemon_id,
order_by=PokemonEggGroup.egg_group_id,
backref='pokemon')
Pokemon.evolution_chain = relation(EvolutionChain, backref='pokemon')
-Pokemon.evolution_children = relation(Pokemon,
- secondary=PokemonEvolution.__table__,
+Pokemon.child_pokemon = relation(Pokemon,
primaryjoin=Pokemon.id==PokemonEvolution.from_pokemon_id,
+ secondary=PokemonEvolution.__table__,
secondaryjoin=PokemonEvolution.to_pokemon_id==Pokemon.id,
- backref=backref('evolution_parent',
- remote_side=[Pokemon.id],
- uselist=False,
- ),
+ backref=backref('parent_pokemon', uselist=False),
)
Pokemon.flavor_text = relation(PokemonFlavorText, order_by=PokemonFlavorText.version_id.asc(), backref='pokemon')
Pokemon.foreign_names = relation(PokemonName, backref='pokemon')
Pokemon.items = relation(PokemonItem, backref='pokemon')
Pokemon.generation = relation(Generation, backref='pokemon')
Pokemon.shape = relation(PokemonShape, backref='pokemon')
-Pokemon.stats = relation(PokemonStat, backref='pokemon')
+Pokemon.stats = relation(PokemonStat, backref='pokemon', order_by=PokemonStat.stat_id.asc())
Pokemon.types = relation(Type, secondary=PokemonType.__table__, order_by=PokemonType.slot.asc())
PokemonDexNumber.pokedex = relation(Pokedex)
order_by='VersionGroupRegion.version_group_id')
Region.version_groups = association_proxy('version_group_regions', 'version_group')
+Stat.damage_class = relation(MoveDamageClass, backref='stats')
+
SuperContestCombo.first = relation(Move, primaryjoin=SuperContestCombo.first_move_id==Move.id,
backref='super_contest_combo_first')
SuperContestCombo.second = relation(Move, primaryjoin=SuperContestCombo.second_move_id==Move.id,
Type.generation = relation(Generation, backref='types')
Type.damage_class = relation(MoveDamageClass, backref='types')
+Type.foreign_names = relation(TypeName, backref='type')
+
+TypeName.language = relation(Language)
Version.version_group = relation(VersionGroup, backref='versions')
Version.generation = association_proxy('version_group', 'generation')