49d9c1761429f777f385fbc400f73798677a73fa
[zzz-pokedex.git] / pokedex / db / tables.py
1 # encoding: utf8
2
3 from sqlalchemy import Column, ForeignKey, MetaData, Table
4 from sqlalchemy.ext.declarative import declarative_base
5 from sqlalchemy.orm import backref, relation
6 from sqlalchemy.types import *
7 from sqlalchemy.databases.mysql import *
8
9 metadata = MetaData()
10 TableBase = declarative_base(metadata=metadata)
11
12 class Ability(TableBase):
13 __tablename__ = 'abilities'
14 id = Column(Integer, primary_key=True, nullable=False)
15 name = Column(Unicode(24), nullable=False)
16 flavor_text = Column(Unicode(64), nullable=False)
17 effect = Column(Unicode(255), nullable=False)
18
19 class ContestEffect(TableBase):
20 __tablename__ = 'contest_effects'
21 id = Column(Integer, primary_key=True, nullable=False)
22 appeal = Column(SmallInteger, nullable=False)
23 jam = Column(SmallInteger, nullable=False)
24 flavor = Column(Unicode(255), nullable=False)
25 effect = Column(Unicode(255), nullable=False)
26
27 class EggGroup(TableBase):
28 __tablename__ = 'egg_groups'
29 id = Column(Integer, primary_key=True, nullable=False)
30 name = Column(Unicode(16), nullable=False)
31
32 class Encounter(TableBase):
33 """Rows in this table represent encounters with wild Pokémon.
34
35 Within a given area in a given game, encounters are differentiated by the
36 slot they are in and a world condition.
37
38 Groups of slots belong to encounter types; these are what the player is
39 doing to get an encounter, such as surfing or walking through tall grass.
40
41 Within an encounter type, slots are defined primarily by rarity. Each slot
42 can also be affected by a world condition; for example, the 20% slot for
43 walking in tall grass is affected by whether a swarm is in effect in the
44 areas. "There is a swarm" and "there is not a swarm" are conditions, and
45 together they make a condition group. However, since "not a swarm" is a
46 base state rather than any sort of new state, it is omitted and instead
47 referred to by a NULL.
48
49 A slot (20% walking in grass) and single world condition (NULL, i.e. no
50 swarm) are thus enough to define a specific encounter.
51
52 Well, okay, almost: each slot actually appears twice.
53 """
54
55 __tablename__ = 'encounters'
56 id = Column(Integer, primary_key=True, nullable=False)
57 version_id = Column(Integer, ForeignKey('versions.id'), nullable=False, autoincrement=False)
58 location_area_id = Column(Integer, ForeignKey('location_areas.id'), nullable=False, autoincrement=False)
59 encounter_type_slot_id = Column(Integer, ForeignKey('encounter_type_slots.id'), nullable=False, autoincrement=False)
60 encounter_condition_id = Column(Integer, ForeignKey('encounter_conditions.id'), nullable=True, autoincrement=False)
61 pokemon_id = Column(Integer, ForeignKey('pokemon.id'), nullable=False, autoincrement=False)
62 min_level = Column(Integer, nullable=False, autoincrement=False)
63 max_level = Column(Integer, nullable=False, autoincrement=False)
64
65 class EncounterCondition(TableBase):
66 """Rows in this table represent something different about the world that
67 can affect what Pokémon are encountered.
68 """
69
70 __tablename__ = 'encounter_conditions'
71 id = Column(Integer, primary_key=True, nullable=False)
72 encounter_condition_group_id = Column(Integer, ForeignKey('encounter_condition_groups.id'), primary_key=False, nullable=False, autoincrement=False)
73 name = Column(Unicode(64), nullable=False)
74
75 class EncounterConditionGroup(TableBase):
76 """Rows in this table represent a group of mutually exclusive conditions,
77 such as morning/day/night. "Conditions" that are part of the default state
78 of the world, such as "not during a swarm" or "not using the PokéRadar",
79 are not included in this table and are referred to by NULLs in other
80 tables.
81 """
82
83 __tablename__ = 'encounter_condition_groups'
84 id = Column(Integer, primary_key=True, nullable=False)
85 name = Column(Unicode(64), nullable=False)
86
87 class EncounterType(TableBase):
88 """Rows in this table represent ways the player can enter a wild encounter;
89 i.e. surfing, fishing, or walking through tall grass.
90 """
91
92 __tablename__ = 'encounter_types'
93 id = Column(Integer, primary_key=True, nullable=False)
94 name = Column(Unicode(64), nullable=False)
95
96 class EncounterTypeSlot(TableBase):
97 """Rows in this table represent an abstract "slot" within an encounter
98 type, associated with both a condition group and a rarity.
99
100 Note that there are two encounters per slot, so the rarities will only add
101 up to 50.
102 """
103
104 __tablename__ = 'encounter_type_slots'
105 id = Column(Integer, primary_key=True, nullable=False)
106 encounter_type_id = Column(Integer, ForeignKey('encounter_types.id'), primary_key=False, nullable=False, autoincrement=False)
107 encounter_condition_group_id = Column(Integer, ForeignKey('encounter_condition_groups.id'), primary_key=False, nullable=True, autoincrement=False)
108 rarity = Column(Integer, nullable=False, autoincrement=False)
109
110 class EvolutionChain(TableBase):
111 __tablename__ = 'evolution_chains'
112 id = Column(Integer, primary_key=True, nullable=False)
113 growth_rate_id = Column(Integer, ForeignKey('growth_rates.id'), nullable=False)
114 steps_to_hatch = Column(Integer, nullable=False)
115 baby_trigger_item = Column(Unicode(12))
116
117 class EvolutionMethod(TableBase):
118 __tablename__ = 'evolution_methods'
119 id = Column(Integer, primary_key=True, nullable=False)
120 name = Column(Unicode(64), nullable=False)
121 description = Column(Unicode(255), nullable=False)
122
123 class Generation(TableBase):
124 __tablename__ = 'generations'
125 id = Column(Integer, primary_key=True, nullable=False)
126 name = Column(Unicode(16), nullable=False)
127 main_region = Column(Unicode(16), nullable=False)
128
129 class GrowthRate(TableBase):
130 __tablename__ = 'growth_rates'
131 id = Column(Integer, primary_key=True, nullable=False)
132 name = Column(Unicode(16), nullable=False)
133 formula = Column(Unicode(255), nullable=False)
134
135 class Language(TableBase):
136 __tablename__ = 'languages'
137 id = Column(Integer, primary_key=True, nullable=False)
138 name = Column(Unicode(16), nullable=False)
139
140 class Location(TableBase):
141 __tablename__ = 'locations'
142 id = Column(Integer, primary_key=True, nullable=False)
143 generation_id = Column(Integer, ForeignKey('generations.id'), nullable=False)
144 name = Column(Unicode(64), nullable=False)
145
146 class LocationArea(TableBase):
147 __tablename__ = 'location_areas'
148 id = Column(Integer, primary_key=True, nullable=False)
149 location_id = Column(Integer, ForeignKey('locations.id'), nullable=False)
150 internal_id = Column(Integer, nullable=False)
151 name = Column(Unicode(64), nullable=True)
152
153 class MoveEffect(TableBase):
154 __tablename__ = 'move_effects'
155 id = Column(Integer, primary_key=True, nullable=False)
156 priority = Column(SmallInteger, nullable=False)
157 short_effect = Column(Unicode(128), nullable=False)
158 effect = Column(Unicode(255), nullable=False)
159
160 class MoveTarget(TableBase):
161 __tablename__ = 'move_targets'
162 id = Column(Integer, primary_key=True, nullable=False)
163 name = Column(Unicode(32), nullable=False)
164 description = Column(Unicode(128), nullable=False)
165
166 class Move(TableBase):
167 __tablename__ = 'moves'
168 id = Column(Integer, primary_key=True, nullable=False)
169 name = Column(Unicode(12), nullable=False)
170 type_id = Column(Integer, ForeignKey('types.id'), nullable=False)
171 power = Column(SmallInteger)
172 pp = Column(SmallInteger, nullable=False)
173 accuracy = Column(SmallInteger)
174 target_id = Column(Integer, ForeignKey('move_targets.id'), nullable=False)
175 category = Column(Unicode(8), nullable=False)
176 effect_id = Column(Integer, ForeignKey('move_effects.id'), nullable=False)
177 effect_chance = Column(Integer)
178 contest_type = Column(Unicode(8), nullable=False)
179 contest_effect_id = Column(Integer, ForeignKey('contest_effects.id'), nullable=False)
180 super_contest_effect_id = Column(Integer, nullable=False)
181
182 class Pokemon(TableBase):
183 __tablename__ = 'pokemon'
184 id = Column(Integer, primary_key=True, nullable=False)
185 name = Column(Unicode(20), nullable=False)
186 forme_name = Column(Unicode(16))
187 forme_base_pokemon_id = Column(Integer, ForeignKey('pokemon.id'))
188 generation_id = Column(Integer, ForeignKey('generations.id'))
189 evolution_chain_id = Column(Integer, ForeignKey('evolution_chains.id'))
190 evolution_parent_pokemon_id = Column(Integer, ForeignKey('pokemon.id'))
191 evolution_method_id = Column(Integer, ForeignKey('evolution_methods.id'))
192 evolution_parameter = Column(Unicode(32))
193 height = Column(Integer, nullable=False)
194 weight = Column(Integer, nullable=False)
195 species = Column(Unicode(16), nullable=False)
196 color = Column(Unicode(6), nullable=False)
197 pokemon_shape_id = Column(Integer, ForeignKey('pokemon_shapes.id'), nullable=False)
198 habitat = Column(Unicode(16), nullable=False)
199 gender_rate = Column(Integer, nullable=False)
200 capture_rate = Column(Integer, nullable=False)
201 base_experience = Column(Integer, nullable=False)
202 base_happiness = Column(Integer, nullable=False)
203 gen1_internal_id = Column(Integer)
204 is_baby = Column(Boolean, nullable=False)
205 has_gen4_fem_sprite = Column(Boolean, nullable=False)
206 has_gen4_fem_back_sprite = Column(Boolean, nullable=False)
207
208 ### Stuff to handle alternate Pokémon forms
209
210 @property
211 def national_id(self):
212 """Returns the National Pokédex number for this Pokémon. Use this
213 instead of the id directly; alternate formes may make the id incorrect.
214 """
215
216 if self.forme_base_pokemon_id:
217 return self.forme_base_pokemon_id
218 return self.id
219
220 @property
221 def full_name(self):
222 """Returns the name of this Pokémon, including its Forme, if any."""
223
224 if self.forme_name:
225 return "%s %s" % (self.forme_name.capitalize(), self.name)
226 return self.name
227
228 class PokemonAbility(TableBase):
229 __tablename__ = 'pokemon_abilities'
230 pokemon_id = Column(Integer, ForeignKey('pokemon.id'), primary_key=True, nullable=False, autoincrement=False)
231 ability_id = Column(Integer, ForeignKey('abilities.id'), nullable=False)
232 slot = Column(Integer, primary_key=True, nullable=False, autoincrement=False)
233
234 class PokemonDexNumber(TableBase):
235 __tablename__ = 'pokemon_dex_numbers'
236 pokemon_id = Column(Integer, ForeignKey('pokemon.id'), primary_key=True, nullable=False, autoincrement=False)
237 generation_id = Column(Integer, ForeignKey('generations.id'), primary_key=True, nullable=False, autoincrement=False)
238 pokedex_number = Column(Integer, nullable=False)
239
240 class PokemonEggGroup(TableBase):
241 __tablename__ = 'pokemon_egg_groups'
242 pokemon_id = Column(Integer, ForeignKey('pokemon.id'), primary_key=True, nullable=False, autoincrement=False)
243 egg_group_id = Column(Integer, ForeignKey('egg_groups.id'), primary_key=True, nullable=False, autoincrement=False)
244
245 class PokemonFlavorText(TableBase):
246 __tablename__ = 'pokemon_flavor_text'
247 pokemon_id = Column(Integer, ForeignKey('pokemon.id'), primary_key=True, nullable=False, autoincrement=False)
248 version_id = Column(Integer, ForeignKey('versions.id'), primary_key=True, nullable=False, autoincrement=False)
249 flavor_text = Column(Unicode(255), nullable=False)
250
251 class PokemonFormGroup(TableBase):
252 __tablename__ = 'pokemon_form_groups'
253 pokemon_id = Column(Integer, ForeignKey('pokemon.id'), primary_key=True, nullable=False, autoincrement=False)
254 description = Column(Unicode(255), nullable=False)
255
256 class PokemonFormSprite(TableBase):
257 __tablename__ = 'pokemon_form_sprites'
258 id = Column(Integer, primary_key=True, nullable=False)
259 pokemon_id = Column(Integer, ForeignKey('pokemon.id'), primary_key=True, nullable=False, autoincrement=False)
260 name = Column(Unicode(16), nullable=True)
261
262 class PokemonName(TableBase):
263 __tablename__ = 'pokemon_names'
264 pokemon_id = Column(Integer, ForeignKey('pokemon.id'), primary_key=True, nullable=False, autoincrement=False)
265 language_id = Column(Integer, ForeignKey('languages.id'), primary_key=True, nullable=False, autoincrement=False)
266 name = Column(Unicode(16), nullable=False)
267
268 class PokemonShape(TableBase):
269 __tablename__ = 'pokemon_shapes'
270 id = Column(Integer, primary_key=True, nullable=False)
271 name = Column(Unicode(24), nullable=False)
272 awesome_name = Column(Unicode(16), nullable=False)
273
274 class PokemonStat(TableBase):
275 __tablename__ = 'pokemon_stats'
276 pokemon_id = Column(Integer, ForeignKey('pokemon.id'), primary_key=True, nullable=False, autoincrement=False)
277 stat_id = Column(Integer, ForeignKey('stats.id'), primary_key=True, nullable=False, autoincrement=False)
278 base_stat = Column(Integer, nullable=False)
279 effort = Column(Integer, nullable=False)
280
281 class PokemonType(TableBase):
282 __tablename__ = 'pokemon_types'
283 pokemon_id = Column(Integer, ForeignKey('pokemon.id'), primary_key=True, nullable=False, autoincrement=False)
284 type_id = Column(Integer, ForeignKey('types.id'), nullable=False)
285 slot = Column(Integer, primary_key=True, nullable=False, autoincrement=False)
286
287 class Stat(TableBase):
288 __tablename__ = 'stats'
289 id = Column(Integer, primary_key=True, nullable=False)
290 name = Column(Unicode(16), nullable=False)
291
292 class TypeEfficacy(TableBase):
293 __tablename__ = 'type_efficacy'
294 damage_type_id = Column(Integer, ForeignKey('types.id'), primary_key=True, nullable=False, autoincrement=False)
295 target_type_id = Column(Integer, ForeignKey('types.id'), primary_key=True, nullable=False, autoincrement=False)
296 damage_factor = Column(Integer, nullable=False)
297
298 class Type(TableBase):
299 __tablename__ = 'types'
300 id = Column(Integer, primary_key=True, nullable=False)
301 name = Column(Unicode(8), nullable=False)
302 abbreviation = Column(Unicode(3), nullable=False)
303
304 class VersionGroup(TableBase):
305 __tablename__ = 'version_groups'
306 id = Column(Integer, primary_key=True, nullable=False)
307 generation_id = Column(Integer, ForeignKey('generations.id'), nullable=False)
308
309 class Version(TableBase):
310 __tablename__ = 'versions'
311 id = Column(Integer, primary_key=True, nullable=False)
312 version_group_id = Column(Integer, ForeignKey('version_groups.id'), nullable=False)
313 name = Column(Unicode(32), nullable=False)
314
315
316 ### Relations down here, to avoid ordering problems
317 Encounter.pokemon = relation(Pokemon, backref='encounters')
318 Encounter.version = relation(Version, backref='encounters')
319 Encounter.location_area = relation(LocationArea, backref='encounters')
320 Encounter.slot = relation(EncounterTypeSlot, backref='encounters')
321 Encounter.condition = relation(EncounterCondition, backref='encounters')
322
323 EncounterCondition.group = relation(EncounterConditionGroup,
324 backref='conditions')
325
326 EncounterTypeSlot.type = relation(EncounterType, backref='slots')
327
328 EvolutionChain.growth_rate = relation(GrowthRate, backref='evolution_chains')
329
330 LocationArea.location = relation(Location, backref='areas')
331
332 Pokemon.abilities = relation(Ability, secondary=PokemonAbility.__table__,
333 order_by=PokemonAbility.slot,
334 backref='pokemon')
335 Pokemon.dex_numbers = relation(PokemonDexNumber, backref='pokemon')
336 Pokemon.egg_groups = relation(EggGroup, secondary=PokemonEggGroup.__table__,
337 order_by=PokemonEggGroup.egg_group_id,
338 backref='pokemon')
339 Pokemon.evolution_chain = relation(EvolutionChain, backref='pokemon')
340 Pokemon.evolution_method = relation(EvolutionMethod)
341 Pokemon.evolution_children = relation(Pokemon, primaryjoin=Pokemon.id==Pokemon.evolution_parent_pokemon_id,
342 backref=backref('evolution_parent',
343 remote_side=[Pokemon.id]))
344 Pokemon.flavor_text = relation(PokemonFlavorText, backref='pokemon')
345 Pokemon.foreign_names = relation(PokemonName, backref='pokemon')
346 Pokemon.generation = relation(Generation, backref='pokemon')
347 Pokemon.shape = relation(PokemonShape, backref='pokemon')
348 Pokemon.stats = relation(PokemonStat, backref='pokemon')
349 Pokemon.types = relation(Type, secondary=PokemonType.__table__)
350
351 PokemonDexNumber.generation = relation(Generation)
352
353 PokemonFlavorText.version = relation(Version)
354
355 PokemonFormGroup.pokemon = relation(Pokemon, backref=backref('form_group',
356 uselist=False))
357 PokemonFormSprite.pokemon = relation(Pokemon, backref='form_sprites')
358
359 PokemonName.language = relation(Language)
360
361 PokemonStat.stat = relation(Stat)
362
363 Type.damage_efficacies = relation(TypeEfficacy,
364 primaryjoin=Type.id
365 ==TypeEfficacy.damage_type_id,
366 backref='damage_type')
367 Type.target_efficacies = relation(TypeEfficacy,
368 primaryjoin=Type.id
369 ==TypeEfficacy.target_type_id,
370 backref='target_type')
371
372 Version.generation = relation(Generation, secondary=VersionGroup.__table__,
373 backref='versions')