Give move changelogs a few more relations. #78
[zzz-pokedex.git] / pokedex / db / tables.py
index 846fb19..e7bd48d 100644 (file)
@@ -53,6 +53,16 @@ class Ability(TableBase):
     short_effect = Column(markdown.MarkdownColumn(255), nullable=False,
         info=dict(description="Short summary of this ability's effect", format='markdown'))
 
+class AbilityChangelog(TableBase):
+    """History of changes to abilities across main game versions."""
+    __tablename__ = 'ability_changelog'
+    ability_id = Column(Integer, ForeignKey('abilities.id'), primary_key=True, nullable=False,
+        info=dict(description="The ID of the ability that changed"))
+    changed_in_version_group_id = Column(Integer, ForeignKey('version_groups.id'), primary_key=True, nullable=False,
+        info=dict(description="The ID of the version group in which the ability changed"))
+    effect = Column(markdown.MarkdownColumn(255), nullable=False,
+        info=dict(description="A description of the old behavior", format='markdown'))
+
 class AbilityFlavorText(TableBase):
     u"""In-game flavor text of an ability
     """
@@ -353,6 +363,8 @@ class Item(TableBase):
         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."))
+    short_effect = Column(Unicode(256), nullable=False,
+        info=dict(description="A short summary of the effect", format='plaintext'))
     effect = Column(markdown.MarkdownColumn(5120), nullable=False,
         info=dict(description=u"Detailed English description of the item's effect.", format='markdown'))
 
@@ -563,7 +575,7 @@ class MoveDamageClass(TableBase):
     __tablename__ = 'move_damage_classes'
     id = Column(Integer, primary_key=True, nullable=False,
         info=dict(description="A numeric ID"))
-    name = Column(Unicode(8), nullable=False,
+    name = Column(Unicode(16), nullable=False,
         info=dict(description="An English name of the class", format='plaintext'))
     description = Column(Unicode(64), nullable=False,
         info=dict(description="An English description of the class", format='plaintext'))
@@ -579,6 +591,16 @@ class MoveEffect(TableBase):
     effect = Column(Unicode(5120), nullable=False,
         info=dict(description="A detailed description of the effect", format='plaintext'))
 
+class MoveEffectChangelog(TableBase):
+    """History of changes to move effects across main game versions."""
+    __tablename__ = 'move_effect_changelog'
+    effect_id = Column(Integer, ForeignKey('move_effects.id'), primary_key=True, nullable=False,
+        info=dict(description="The ID of the effect that changed"))
+    changed_in_version_group_id = Column(Integer, ForeignKey('version_groups.id'), primary_key=True, nullable=False,
+        info=dict(description="The ID of the version group in which the effect changed"))
+    effect = Column(markdown.MarkdownColumn(255), nullable=False,
+        info=dict(description="A description of the old behavior", format='markdown'))
+
 class MoveFlag(TableBase):
     u"""Maps a move flag to a move
     """
@@ -663,7 +685,7 @@ class Move(TableBase):
         info=dict(description="ID of the damage class (physical/special) of the move"))
     effect_id = Column(Integer, ForeignKey('move_effects.id'), nullable=False,
         info=dict(description="ID of the move's effect"))
-    effect_chance = Column(Integer,
+    effect_chance = Column(Integer, nullable=True,
         info=dict(description="The chance for a secondary effect. What this is a chance of is specified by the move's effect."))
     contest_type_id = Column(Integer, ForeignKey('contest_types.id'), nullable=True,
         info=dict(description="ID of the move's Contest type (e.g. cool or smart)"))
@@ -672,6 +694,26 @@ class Move(TableBase):
     super_contest_effect_id = Column(Integer, ForeignKey('super_contest_effects.id'), nullable=True,
         info=dict(description="ID of the move's Super Contest effect"))
 
+class MoveChangelog(TableBase):
+    """History of changes to moves across main game versions."""
+    __tablename__ = 'move_changelog'
+    move_id = Column(Integer, ForeignKey('moves.id'), primary_key=True, nullable=False,
+        info=dict(description="ID of the move that changed"))
+    changed_in_version_group_id = Column(Integer, ForeignKey('version_groups.id'), primary_key=True, nullable=False,
+        info=dict(description="ID of the version group in which the move changed"))
+    type_id = Column(Integer, ForeignKey('types.id'), nullable=True,
+        info=dict(description="Prior type of the move, or NULL if unchanged"))
+    power = Column(SmallInteger, nullable=True,
+        info=dict(description="Prior base power of the move, or NULL if unchanged"))
+    pp = Column(SmallInteger, nullable=True,
+        info=dict(description="Prior base PP of the move, or NULL if unchanged"))
+    accuracy = Column(SmallInteger, nullable=True,
+        info=dict(description="Prior accuracy of the move, or NULL if unchanged"))
+    effect_id = Column(Integer, ForeignKey('move_effects.id'), nullable=True,
+        info=dict(description="Prior ID of the effect, or NULL if unchanged"))
+    effect_chance = Column(Integer, nullable=True,
+        info=dict(description="Prior effect chance, or NULL if unchanged"))
+
 class Nature(TableBase):
     u"""A nature a pokémon can have, such as Calm or Brave
     """
@@ -757,15 +799,6 @@ class Pokedex(TableBase):
     description = Column(Unicode(512),
         info=dict(description=u"A longer description of the pokédex", format='plaintext'))
 
-class PokedexVersionGroup(TableBase):
-    u"""Maps a pokédex to the version group that uses it
-    """
-    __tablename__ = 'pokedex_version_groups'
-    pokedex_id = Column(Integer, ForeignKey('pokedexes.id'), primary_key=True, nullable=False, autoincrement=False,
-        info=dict(description=u"ID of the pokédex"))
-    version_group_id = Column(Integer, ForeignKey('version_groups.id'), primary_key=True, nullable=False, autoincrement=False,
-        info=dict(description=u"ID of the version group"))
-
 class Pokemon(TableBase):
     u"""A species of Pokémon.  The core to this whole mess.
     """
@@ -1031,6 +1064,20 @@ class PokemonFormGroup(TableBase):
     description = Column(markdown.MarkdownColumn(1024), nullable=False,
         info=dict(description=u"English description of how the forms work", format='markdown'))
 
+class PokemonFormPokeathlonStat(TableBase):
+    u"""A Pokémon form's performance in one Pokéathlon stat."""
+    __tablename__ = 'pokemon_form_pokeathlon_stats'
+    pokemon_form_id = Column(Integer, ForeignKey('pokemon_forms.id'), primary_key=True, nullable=False, autoincrement=False,
+        info=dict(description=u'The ID of the Pokémon form.'))
+    pokeathlon_stat_id = Column(Integer, ForeignKey('pokeathlon_stats.id'), primary_key=True, nullable=False, autoincrement=False,
+        info=dict(description=u'The ID of the Pokéathlon stat.'))
+    minimum_stat = Column(Integer, nullable=False, autoincrement=False,
+        info=dict(description=u'The minimum value for this stat for this Pokémon form.'))
+    base_stat = Column(Integer, nullable=False, autoincrement=False,
+        info=dict(description=u'The default value for this stat for this Pokémon form.'))
+    maximum_stat = Column(Integer, nullable=False, autoincrement=False,
+        info=dict(description=u'The maximum value for this stat for this Pokémon form.'))
+
 class PokemonHabitat(TableBase):
     u"""The habitat of a pokémon, as given in the FireRed/LeafGreen version pokédex
     """
@@ -1229,6 +1276,8 @@ class VersionGroup(TableBase):
         info=dict(description=u"A numeric ID"))
     generation_id = Column(Integer, ForeignKey('generations.id'), nullable=False,
         info=dict(description=u"ID of the generation the games of this group belong to"))
+    pokedex_id = Column(Integer, ForeignKey('pokedexes.id'), nullable=False,
+        info=dict(description=u"ID of the regional Pokédex used in this version group."))
 
 class VersionGroupRegion(TableBase):
     u"""Maps a region to a game version group that features it
@@ -1240,25 +1289,48 @@ class VersionGroupRegion(TableBase):
         info=dict(description=u"ID of the region"))
 
 class Version(TableBase):
-    u"""A version of a mainline pokémon game
+    u"""An individual main-series Pokémon game
     """
     __tablename__ = 'versions'
     id = Column(Integer, primary_key=True, nullable=False,
-        info=dict(description=u"A numeric ID"))
+        info=dict(description=u"A unique ID for this version"))
     version_group_id = Column(Integer, ForeignKey('version_groups.id'), nullable=False,
-        info=dict(description=u"ID of the version group this game belongs to"))
+        info=dict(description=u"The ID of the version group this game belongs to"))
     name = Column(Unicode(32), nullable=False,
         info=dict(description=u'The English name of the game, without the "Pokémon" prefix', official=True, format='plaintext'))
 
 
 ### Relations down here, to avoid ordering problems
+Ability.changelog = relation(AbilityChangelog,
+    order_by=AbilityChangelog.changed_in_version_group_id.desc(),
+    backref='ability',
+)
 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')
+Ability.all_pokemon = relation(Pokemon,
+    secondary=PokemonAbility.__table__,
+    back_populates='all_abilities',
+)
 Ability.pokemon = relation(Pokemon,
     secondary=PokemonAbility.__table__,
+    primaryjoin=and_(
+        PokemonAbility.ability_id == Ability.id,
+        PokemonAbility.is_dream == False
+    ),
+    back_populates='abilities',
+)
+Ability.dream_pokemon = relation(Pokemon,
+    secondary=PokemonAbility.__table__,
+    primaryjoin=and_(
+        PokemonAbility.ability_id == Ability.id,
+        PokemonAbility.is_dream == True
+    ),
+    back_populates='dream_ability',
 )
 
+AbilityChangelog.changed_in = relation(VersionGroup, backref='ability_changelog')
+
 AbilityFlavorText.version_group = relation(VersionGroup)
 
 AbilityName.language = relation(Language)
@@ -1337,6 +1409,10 @@ LocationInternalID.generation = relation(Generation)
 Machine.item = relation(Item)
 Machine.version_group = relation(VersionGroup)
 
+Move.changelog = relation(MoveChangelog,
+    order_by=MoveChangelog.changed_in_version_group_id.desc(),
+    backref='move',
+)
 Move.contest_effect = relation(ContestEffect, backref='moves')
 Move.contest_combo_next = association_proxy('contest_combo_first', 'second')
 Move.contest_combo_prev = association_proxy('contest_combo_second', 'first')
@@ -1358,6 +1434,13 @@ Move.type = relation(Type, backref='moves')
 Move.effect = markdown.MoveEffectProperty('effect')
 Move.short_effect = markdown.MoveEffectProperty('short_effect')
 
+MoveChangelog.changed_in = relation(VersionGroup, backref='move_changelog')
+MoveChangelog.move_effect = relation(MoveEffect, backref='move_changelog')
+MoveChangelog.type = relation(Type, backref='move_changelog')
+
+MoveChangelog.effect = markdown.MoveEffectProperty('effect')
+MoveChangelog.short_effect = markdown.MoveEffectProperty('short_effect')
+
 MoveEffect.category_map = relation(MoveEffectCategoryMap)
 MoveEffect.categories = association_proxy('category_map', 'category')
 MoveEffectCategoryMap.category = relation(MoveEffectCategory)
@@ -1389,7 +1472,7 @@ NatureName.language = relation(Language)
 NaturePokeathlonStat.pokeathlon_stat = relation(PokeathlonStat, backref='nature_effects')
 
 Pokedex.region = relation(Region, backref='pokedexes')
-Pokedex.version_groups = relation(VersionGroup, secondary=PokedexVersionGroup.__table__, backref='pokedexes')
+Pokedex.version_groups = relation(VersionGroup, order_by=VersionGroup.id, back_populates='pokedex')
 
 Pokemon.all_abilities = relation(Ability,
     secondary=PokemonAbility.__table__,
@@ -1481,10 +1564,15 @@ PokemonForm.unique_pokemon = relation(Pokemon, backref=backref('unique_form', us
                                       primaryjoin=PokemonForm.unique_pokemon_id==Pokemon.id)
 PokemonForm.version_group = relation(VersionGroup)
 PokemonForm.form_group = association_proxy('form_base_pokemon', 'form_group')
+PokemonForm.pokeathlon_stats = relation(PokemonFormPokeathlonStat,
+                                        order_by=PokemonFormPokeathlonStat.pokeathlon_stat_id,
+                                        backref='pokemon_form')
 
 PokemonFormGroup.pokemon = relation(Pokemon, backref=backref('form_group',
                                                              uselist=False))
 
+PokemonFormPokeathlonStat.pokeathlon_stat = relation(PokeathlonStat)
+
 PokemonItem.item = relation(Item, backref='pokemon')
 PokemonItem.version = relation(Version)
 
@@ -1498,7 +1586,7 @@ PokemonMove.machine = relation(Machine, backref='pokemon_moves',
 PokemonMove.move = relation(Move, backref='pokemon_moves')
 PokemonMove.method = relation(PokemonMoveMethod)
 
-PokemonName.language = relation(Language)
+PokemonName.language = relation(Language, lazy='joined')
 
 PokemonStat.stat = relation(Stat)
 
@@ -1530,9 +1618,11 @@ Type.foreign_names = relation(TypeName, backref='type')
 
 TypeName.language = relation(Language)
 
-Version.version_group = relation(VersionGroup, backref='versions')
+Version.version_group = relation(VersionGroup, back_populates='versions')
 Version.generation = association_proxy('version_group', 'generation')
 
+VersionGroup.versions = relation(Version, order_by=Version.id, back_populates='version_group')
 VersionGroup.generation = relation(Generation, backref='version_groups')
 VersionGroup.version_group_regions = relation(VersionGroupRegion, backref='version_group')
 VersionGroup.regions = association_proxy('version_group_regions', 'region')
+VersionGroup.pokedex = relation(Pokedex, back_populates='version_groups')