def explore_pokemon(context, request): # TODO should this be part of the api? it knows if there was "really" a # search did_search = bool(request.GET) if not did_search: return dict( did_search=did_search, results=None, all_pokemon=None, all_types=None, all_generations=None, ) q = api.Query(api.PokemonLocus, session) q.parse_multidict(request.GET) return dict( did_search=did_search, results=q.execute(), # XXX these really oughta come from the locus, or something. fix this # up yo all_types=session.query(t.Type), all_generations=session.query(t.Generation), )
def explore_pokemon(context, request): # TODO should this be part of the api? it knows if there was "really" a # search did_search = bool(request.GET) if not did_search: return dict( did_search=did_search, results=None, all_pokemon=None, all_types=None, all_generations=None, ) q = api.Query(api.PokemonLocus, session) q.parse_multidict(request.GET) return dict( did_search=did_search, results=q.execute(), # XXX these really oughta come from the locus, or something. fix this # up yo all_types=session.query(t.Type), all_generations=session.query(t.Generation), )
def nature_browse(context, request): natures = session.query(t.Nature) \ .join(t.Nature.names_local) \ .options( contains_eager(t.Nature.names_local), joinedload(t.Nature.increased_stat), joinedload(t.Nature.decreased_stat), joinedload(t.Nature.likes_flavor), joinedload(t.Nature.hates_flavor), ) \ .order_by(t.Nature.names_table.name.asc()) # TODO table is kinda fugly still # TODO not sure this page is titled correctly given gene hints # TODO old page has sort-by-stat stat_hint_table = dict() stat_hints = session.query(t.StatHint).options(joinedload(t.StatHint.names_local)) for stat_hint in stat_hints: subdict = stat_hint_table.setdefault(stat_hint.stat, {}) subdict[stat_hint.gene_mod_5] = stat_hint.message return dict( natures=natures, stat_hints=stat_hint_table, )
def move_search(context, request): # XXX request._LOCALE_ = 'en' # TODO should this be part of the api? it knows if there was "really" a # search did_search = bool(request.GET) q = api.Query(api.MoveLocus, session) q.parse_multidict(request.GET) move_groups, moves, move_previews = q.results() return dict( did_search=did_search, move_groups=move_groups, moves=moves, move_previews=move_previews, # XXX these really oughta come from the locus, or something. fix this # up yo all_types=session.query(t.Type), all_generations=session.query(t.Generation), )
def nature_browse(context, request): natures = session.query(t.Nature) \ .join(t.Nature.names_local) \ .options( contains_eager(t.Nature.names_local), joinedload(t.Nature.increased_stat), joinedload(t.Nature.decreased_stat), joinedload(t.Nature.likes_flavor), joinedload(t.Nature.hates_flavor), ) \ .order_by(t.Nature.names_table.name.asc()) # TODO table is kinda fugly still # TODO not sure this page is titled correctly given gene hints # TODO old page has sort-by-stat stat_hint_table = dict() stat_hints = session.query(t.StatHint).options( joinedload(t.StatHint.names_local)) for stat_hint in stat_hints: subdict = stat_hint_table.setdefault(stat_hint.stat, {}) subdict[stat_hint.gene_mod_5] = stat_hint.message return dict( natures=natures, stat_hints=stat_hint_table, )
def api_test(context, request): print context pokemon = session.query(t.Pokemon).join(t.Pokemon.species).filter(t.PokemonSpecies.identifier == 'rhydon').one() hardcoded = { # TODO specify output language 'name': dict(en=pokemon.name), 'base-stats': dict((pokemon_stat.stat.identifier, pokemon_stat.base_stat) for pokemon_stat in pokemon.stats), # TODO sprite urls # TODO link these? optionally expand them? something?? 'types': [type_.identifier for type_ in pokemon.types], # TODO what to show here, either? short effect in output language? 'abilities': [ability.identifier for ability in pokemon.abilities], # TODO damage? } data = dict() locus = a.PokemonLocus(pokemon) data['identifier'] = locus.identifier data.update(hardcoded) return data
def iter_options(self): # XXX from veekun_pokedex.model import session # TODO need to filter this # TODO need to order this? for row in session.query(self.target_locus): yield self.identified_by.__get__(row, type(row)), row
def place(context, request): location = context template_ns = dict() template_ns['location'] = location # Eagerload (session.query(t.Location) .filter_by(id=location.id) .options( joinedload('areas'), subqueryload('areas.encounters'), joinedload('areas.encounters.condition_values'), joinedload('areas.encounters.condition_values.condition'), ) .all() ) encounters = EncounterCollection([ encounter for area in location.areas for encounter in area.encounters ]) template_ns['fudged_encounters'] = encounters return template_ns
def type_browse(context, request): types = ( session.query(t.Type) .join(t.Type.names_local) # Force inner join here to strip out e.g. Shadow, which has no # efficacy .join(t.Type.damage_efficacies) .order_by(t.Type.names_table.name) .options( contains_eager(t.Type.names_local), contains_eager(t.Type.damage_efficacies), ) .all() ) efficacy_map = {} for attacking_type in types: submap = efficacy_map[attacking_type] = {} for efficacy in attacking_type.damage_efficacies: submap[efficacy.target_type] = efficacy.damage_factor template_ns = dict( types=types, efficacy_map=efficacy_map, ) return template_ns
def pokemon_search_landing_test(context, request): did_search = bool(request.GET) if did_search: all_pokemon = (session.query(t.Pokemon).filter( t.Pokemon.is_default).order_by(t.Pokemon.species_id.asc()).options( joinedload(t.Pokemon.species)).all())
def api_test(context, request): print context pokemon = session.query(t.Pokemon).join(t.Pokemon.species).filter( t.PokemonSpecies.identifier == 'rhydon').one() hardcoded = { # TODO specify output language 'name': dict(en=pokemon.name), 'base-stats': dict((pokemon_stat.stat.identifier, pokemon_stat.base_stat) for pokemon_stat in pokemon.stats), # TODO sprite urls # TODO link these? optionally expand them? something?? 'types': [type_.identifier for type_ in pokemon.types], # TODO what to show here, either? short effect in output language? 'abilities': [ability.identifier for ability in pokemon.abilities], # TODO damage? } data = dict() locus = a.PokemonLocus(pokemon) data['identifier'] = locus.identifier data.update(hardcoded) return data
def item_browse(context, request): items = session.query(t.Item) template_ns = dict( items=items, ) return template_ns
def iter_options(self): # XXX from veekun_pokedex.model import session # TODO need to filter this # TODO need to order this? for row in session.query(self.target_locus): yield self.identified_by.__get__(row, type(row)), row
def region_browse(context, request): regions = ( session.query(t.Region) .all() ) template_ns = dict( regions=regions, ) return template_ns
def pokemon_search_landing_test(context, request): did_search = bool(request.GET) if did_search: all_pokemon = ( session.query(t.Pokemon) .filter(t.Pokemon.is_default) .order_by(t.Pokemon.species_id.asc()) .options(joinedload(t.Pokemon.species)) .all() )
def render_markdown(context, row, relation, inline=False): """Renders a block of Markdown from the database. Call with a row and column name SEPARATELY -- then I can handle language fallback if we don't have this particular text translated yet. """ # XXX with the way this is set up, pokedex lib will do the markdowning for # us, which makes it hard for the linkifier to find the request. local = getattr(row, relation, None) if local: markdown = local else: # XXX uhm how do i get the original default language from veekun_pokedex.model import session import pokedex.db.tables as t english = session.query(t.Language).get(9) english_prose = getattr(row, relation + '_map').get(english) if english_prose: _ = context['_'] context.write(u"""<p class="missing-translation">{0}</p>""".format( _(u"Sorry, we haven't translated this into your language yet! " u"Here's the original English. (If you can help translate, let us know!)" ))) markdown = english_prose else: import warnings warnings.warn(u"""Can't find {0!r} prose for row {1!r}""".format( relation, row)) context.write(u'<em>(?)</em>') return u'' rendered = markdown.as_html() # Remove the <p> wrapper, if requested if inline: if not rendered.startswith(u'<p>') or not rendered.endswith(u'</p>'): raise ValueError( u"""Can't make {0!r} inline for row {1!r}""".format( relation, row)) rendered = rendered[3:-4] if u'<p>' in rendered or u'</p>' in rendered: raise ValueError( u"""Can't make {0!r} inline for row {1!r}""".format( relation, row)) context.write(rendered) return u''
def region(context, request): region = context.parent_row template_ns = dict() template_ns['region'] = region locations = (session.query(t.Location).with_parent(region).join( t.Location.names_local).order_by(t.Location.names_table.name).options( contains_eager(t.Location.names_local))) template_ns['locations'] = locations return template_ns
def __getitem__(self, key): if key not in LANGUAGES: raise KeyError # TODO could cache these in-process... language = session.query(t.Language).filter_by(identifier=key).one() session.default_language_id = language.id # TODO this leaves a request out to dry if it doesn't happen to come # through here self.request._LOCALE_ = key self.request._veekun_language = language return localized_resource_root[key]
def __getitem__(self, key): if key not in LANGUAGES: raise KeyError # TODO could cache these in-process... language = session.query(t.Language).filter_by(identifier=key).one() session.default_language_id = language.id # TODO this leaves a request out to dry if it doesn't happen to come # through here self.request._LOCALE_ = key self.request._veekun_language = language return localized_resource_root[key]
def __init__(self, locus_cls, session): self.locus_cls = locus_cls self.session = session self.query = ( session.query(self.locus_cls.__table__) # TODO would be nice to raise an exception on read, but that's not # what `noload` does .options(lazyload('*')) ) self.fetches = set() # TODO this is crap self.grouper = None
def __init__(self, locus_cls, session): self.locus_cls = locus_cls self.session = session self.query = ( session.query(self.locus_cls.__table__) # TODO would be nice to raise an exception on read, but that's not # what `noload` does .options(lazyload("*")) ) self.fetches = set() # TODO this is crap self.grouper = None
def move_search(context, request): # XXX request._LOCALE_ = 'en' # TODO should this be part of the api? it knows if there was "really" a # search did_search = bool(request.GET) q = api.Query(api.MoveLocus, session) q.parse_multidict(request.GET) move_groups, moves, move_previews = q.results() return dict( did_search=did_search, move_groups=move_groups, moves=moves, move_previews=move_previews, # XXX these really oughta come from the locus, or something. fix this # up yo all_types=session.query(t.Type), all_generations=session.query(t.Generation), )
def render_markdown(context, row, relation, inline=False): """Renders a block of Markdown from the database. Call with a row and column name SEPARATELY -- then I can handle language fallback if we don't have this particular text translated yet. """ # XXX with the way this is set up, pokedex lib will do the markdowning for # us, which makes it hard for the linkifier to find the request. local = getattr(row, relation, None) if local: markdown = local else: # XXX uhm how do i get the original default language from veekun_pokedex.model import session import pokedex.db.tables as t english = session.query(t.Language).get(9) english_prose = getattr(row, relation + '_map').get(english) if english_prose: _ = context['_'] context.write(u"""<p class="missing-translation">{0}</p>""".format( _(u"Sorry, we haven't translated this into your language yet! " u"Here's the original English. (If you can help translate, let us know!)") )) markdown = english_prose else: import warnings warnings.warn(u"""Can't find {0!r} prose for row {1!r}""".format(relation, row)) context.write(u'<em>(?)</em>') return u'' rendered = markdown.as_html() # Remove the <p> wrapper, if requested if inline: if not rendered.startswith(u'<p>') or not rendered.endswith(u'</p>'): raise ValueError(u"""Can't make {0!r} inline for row {1!r}""".format(relation, row)) rendered = rendered[3:-4] if u'<p>' in rendered or u'</p>' in rendered: raise ValueError(u"""Can't make {0!r} inline for row {1!r}""".format(relation, row)) context.write(rendered) return u''
def ability_browse(context, request): abilities = ( session.query(t.Ability) .filter_by(is_main_series=True) .join(t.Ability.names_local) .order_by(t.Ability.names_table.name.asc()) .options( eagerload(t.Ability.prose_local), contains_eager(t.Ability.names_local), ) ) template_ns = dict( abilities=abilities, ) return template_ns
def api_search_test(context, request): q = session.query(t.Pokemon) q = q.join(t.Pokemon.species) name_crit = request.GET.getall('name') name_crit = filter(lambda x: x, name_crit) if name_crit: # TODO ... q = q.filter(t.PokemonSpecies.identifier.in_(name_crit)) q = q.order_by(t.Pokemon.id.asc()) results = [] for row in q: results.append(dict(identifier=row.species.identifier)) return results
def region(context, request): region = context.parent_row template_ns = dict() template_ns['region'] = region locations = ( session.query(t.Location) .with_parent(region) .join(t.Location.names_local) .order_by(t.Location.names_table.name) .options( contains_eager(t.Location.names_local) ) ) template_ns['locations'] = locations return template_ns
def api_search_test(context, request): q = session.query(t.Pokemon) q = q.join(t.Pokemon.species) name_crit = request.GET.getall('name') name_crit = filter(lambda x: x, name_crit) if name_crit: # TODO ... q = q.filter(t.PokemonSpecies.identifier.in_(name_crit)) q = q.order_by(t.Pokemon.id.asc()) results = [] for row in q: results.append(dict(identifier=row.species.identifier)) return results
def __getitem__(self, key): # `key` should be a whatever name q = session.query(self.table) \ .join(self.table.names_local) \ .filter(func.lower(self.table.names_table.name) == key) if self.parent_row is not None: q = q.with_parent(self.parent_row) try: row = q.one() except NoResultFound: # TODO ought to do a 404 with lookup raise KeyError else: if self.parent_class: return self.parent_class(row) else: return row
def __getitem__(self, key): # `key` should be a whatever name q = session.query(self.table) \ .join(self.table.names_local) \ .filter(func.lower(self.table.names_table.name) == key) if self.parent_row is not None: q = q.with_parent(self.parent_row) try: row = q.one() except NoResultFound: # TODO ought to do a 404 with lookup raise KeyError else: if self.parent_class: return self.parent_class(row) else: return row
def place(context, request): location = context template_ns = dict() template_ns['location'] = location # Eagerload (session.query(t.Location).filter_by(id=location.id).options( joinedload('areas'), subqueryload('areas.encounters'), joinedload('areas.encounters.condition_values'), joinedload('areas.encounters.condition_values.condition'), ).all()) encounters = EncounterCollection([ encounter for area in location.areas for encounter in area.encounters ]) template_ns['fudged_encounters'] = encounters return template_ns
def item_browse(context, request): items = session.query(t.Item) template_ns = dict(items=items, ) return template_ns
def _build_evolution_table(evolution_chain_id): """Convert an evolution chain into a format more amenable to the HTML table model. Returns a nested list like: [ [empty, Eevee, Vaporeon, None] [None, None, Jolton, None] [None, None, Flareon, None] ... ] Each sublist is a physical row in the resulting table, containing one element per evolution stage: baby, basic, stage 1, and stage 2. The individual items are simple `EvolutionTableCell` objects: None is a cell that should be skipped entirely (due to rowspans) and "empty" is a cell object whose `is_empty` is true. """ # Prefetch the evolution details q = session.query(t.PokemonSpecies) \ .filter_by(evolution_chain_id=evolution_chain_id) \ .order_by(t.PokemonSpecies.id.asc()) \ .options( subqueryload('evolutions'), joinedload('evolutions.trigger'), joinedload('evolutions.trigger_item'), joinedload('evolutions.held_item'), joinedload('evolutions.location'), joinedload('evolutions.known_move'), joinedload('evolutions.party_species'), joinedload('parent_species'), joinedload('default_form'), ) family = q.all() # Strategy: Build a row for each final-form Pokémon. Intermediate species # will naturally get included. # We need to replace repeated cells in the same column with None and fix # rowspans. Cute trick: build the table backwards, and propagate rowspans # upwards through the table as it's built. evolution_table = [] all_parent_species = set(species.parent_species for species in family) final_species = [ species for species in family if species not in all_parent_species ] final_species.reverse() for species in final_species: row = [] while species: row.insert(0, EvolutionTableCell(species)) species = species.parent_species # The last cell in the row is now either a basic or baby. Insert a # blank cell (with species of None) for baby if necessary if not row[0].species.is_baby: row.insert(0, EvolutionTableCell(None)) # Pad to four columns while len(row) < 4: row.append(EvolutionTableCell(None)) # Compare to the previous row (which is actually the next row). If # anything's repeated, absorb its rowspan and replace it with None. if evolution_table: for i, (cell, next_cell) in enumerate(zip(row, evolution_table[-1])): if cell.species == next_cell.species: cell.rowspan += next_cell.rowspan evolution_table[-1][i] = None evolution_table.append(row) evolution_table.reverse() return evolution_table
def pokemon(context, request): species = context default_pokemon = species.default_pokemon # TODO this pokemon is actually a species!! deal with forms!!! template_ns = dict( species=species, pokemon=default_pokemon, ) # Preload a bunch of stuff we'll always need # TODO share this? for preload_enum_table in (t.Generation, t.VersionGroup, t.Version): session.query(preload_enum_table).all() ## Type efficacy type_efficacies = defaultdict(lambda: 100) for target_type in default_pokemon.types: # We start at 100, and every damage factor is a percentage. Dividing # by 100 with every iteration turns the damage factor into a decimal # percentage, without any float nonsense for type_efficacy in target_type.target_efficacies: type_efficacies[type_efficacy.damage_type] = ( type_efficacies[type_efficacy.damage_type] * type_efficacy.damage_factor // 100) # Turn that dict of type => efficacy into a dict of efficacy => types. efficacy_types = {} for type_, efficacy in type_efficacies.items(): efficacy_types.setdefault(efficacy, []).append(type_) template_ns['efficacy_types'] = efficacy_types ### Stats # This takes a lot of queries :( stat_total = 0 stat_percentiles = {} for pokemon_stat in default_pokemon.stats: stat_total += pokemon_stat.base_stat less = _countif(t.PokemonStat.base_stat < pokemon_stat.base_stat) equal = _countif(t.PokemonStat.base_stat == pokemon_stat.base_stat) total = func.count(t.PokemonStat.base_stat) q = session.query((less + equal / 2.) / total) \ .filter_by(stat=pokemon_stat.stat) percentile, = q.one() # pg gives us fixed-point, which sqla turns into Decimal stat_percentiles[pokemon_stat.stat] = float(percentile) # Percentile for the total # Need to make a derived table that maps pokemon_id to total_stats stat_total_subq = session.query( t.PokemonStat.pokemon_id, func.sum(t.PokemonStat.base_stat).label('stat_total'), ) \ .group_by(t.PokemonStat.pokemon_id) \ .subquery() less = _countif(stat_total_subq.c.stat_total < stat_total) equal = _countif(stat_total_subq.c.stat_total == stat_total) total = func.count(stat_total_subq.c.stat_total) q = session.query((less + equal / 2.) / total) percentile, = q.one() stat_percentiles['total'] = float(percentile) template_ns['stat_percentiles'] = stat_percentiles template_ns['stat_total'] = stat_total ## Wild held items # To date (as of B/W 2), no Pokémon has ever held more than three different # items in its history. So it makes sense to show wild items as a little # table like the move table. item_table = CollapsibleVersionTable() for pokemon_item in default_pokemon.items: item_table.add_version_datum(pokemon_item.version, pokemon_item.item, pokemon_item.rarity) template_ns['wild_held_items'] = item_table ## Evolution template_ns['evolution_table'] = _build_evolution_table( species.evolution_chain_id) ## Moves # XXX yeah this is bad q = session.query(t.PokemonMove) \ .with_parent(default_pokemon) \ .order_by( t.PokemonMove.level.asc(), # t.Machine.machine_number.asc(), t.PokemonMove.order.asc(), t.PokemonMove.version_group_id.asc(), ) moves_table = SectionedCollapsibleVersionTable() for pokemove in q: moves_table.add_group_datum(pokemove.method, pokemove.version_group, pokemove.move, pokemove.level) _method_order = [ u'level-up', 'egg', u'tutor', u'stadium-surfing-pikachu', u'machine' ] moves_table.sort_sections( lambda method: _method_order.index(method.identifier)) template_ns['moves'] = moves_table return template_ns
def _build_evolution_table(evolution_chain_id): """Convert an evolution chain into a format more amenable to the HTML table model. Returns a nested list like: [ [empty, Eevee, Vaporeon, None] [None, None, Jolton, None] [None, None, Flareon, None] ... ] Each sublist is a physical row in the resulting table, containing one element per evolution stage: baby, basic, stage 1, and stage 2. The individual items are simple `EvolutionTableCell` objects: None is a cell that should be skipped entirely (due to rowspans) and "empty" is a cell object whose `is_empty` is true. """ # Prefetch the evolution details q = session.query(t.PokemonSpecies) \ .filter_by(evolution_chain_id=evolution_chain_id) \ .order_by(t.PokemonSpecies.id.asc()) \ .options( subqueryload('evolutions'), joinedload('evolutions.trigger'), joinedload('evolutions.trigger_item'), joinedload('evolutions.held_item'), joinedload('evolutions.location'), joinedload('evolutions.known_move'), joinedload('evolutions.party_species'), joinedload('parent_species'), joinedload('default_form'), ) family = q.all() # Strategy: Build a row for each final-form Pokémon. Intermediate species # will naturally get included. # We need to replace repeated cells in the same column with None and fix # rowspans. Cute trick: build the table backwards, and propagate rowspans # upwards through the table as it's built. evolution_table = [] all_parent_species = set(species.parent_species for species in family) final_species = [ species for species in family if species not in all_parent_species ] final_species.reverse() for species in final_species: row = [] while species: row.insert(0, EvolutionTableCell(species)) species = species.parent_species # The last cell in the row is now either a basic or baby. Insert a # blank cell (with species of None) for baby if necessary if not row[0].species.is_baby: row.insert(0, EvolutionTableCell(None)) # Pad to four columns while len(row) < 4: row.append(EvolutionTableCell(None)) # Compare to the previous row (which is actually the next row). If # anything's repeated, absorb its rowspan and replace it with None. if evolution_table: for i, (cell, next_cell) in enumerate(zip(row, evolution_table[-1])): if cell.species == next_cell.species: cell.rowspan += next_cell.rowspan evolution_table[-1][i] = None evolution_table.append(row) evolution_table.reverse() return evolution_table
def pokemon(context, request): species = context default_pokemon = species.default_pokemon # TODO this pokemon is actually a species!! deal with forms!!! template_ns = dict( species=species, pokemon=default_pokemon, ) # Preload a bunch of stuff we'll always need # TODO share this? for preload_enum_table in (t.Generation, t.VersionGroup, t.Version): session.query(preload_enum_table).all() ## Type efficacy type_efficacies = defaultdict(lambda: 100) for target_type in default_pokemon.types: # We start at 100, and every damage factor is a percentage. Dividing # by 100 with every iteration turns the damage factor into a decimal # percentage, without any float nonsense for type_efficacy in target_type.target_efficacies: type_efficacies[type_efficacy.damage_type] = ( type_efficacies[type_efficacy.damage_type] * type_efficacy.damage_factor // 100) # Turn that dict of type => efficacy into a dict of efficacy => types. efficacy_types = {} for type_, efficacy in type_efficacies.items(): efficacy_types.setdefault(efficacy, []).append(type_) template_ns['efficacy_types'] = efficacy_types ### Stats # This takes a lot of queries :( stat_total = 0 stat_percentiles = {} for pokemon_stat in default_pokemon.stats: stat_total += pokemon_stat.base_stat less = _countif(t.PokemonStat.base_stat < pokemon_stat.base_stat) equal = _countif(t.PokemonStat.base_stat == pokemon_stat.base_stat) total = func.count(t.PokemonStat.base_stat) q = session.query((less + equal / 2.) / total) \ .filter_by(stat=pokemon_stat.stat) percentile, = q.one() # pg gives us fixed-point, which sqla turns into Decimal stat_percentiles[pokemon_stat.stat] = float(percentile) # Percentile for the total # Need to make a derived table that maps pokemon_id to total_stats stat_total_subq = session.query( t.PokemonStat.pokemon_id, func.sum(t.PokemonStat.base_stat).label('stat_total'), ) \ .group_by(t.PokemonStat.pokemon_id) \ .subquery() less = _countif(stat_total_subq.c.stat_total < stat_total) equal = _countif(stat_total_subq.c.stat_total == stat_total) total = func.count(stat_total_subq.c.stat_total) q = session.query((less + equal / 2.) / total) percentile, = q.one() stat_percentiles['total'] = float(percentile) template_ns['stat_percentiles'] = stat_percentiles template_ns['stat_total'] = stat_total ## Wild held items # To date (as of B/W 2), no Pokémon has ever held more than three different # items in its history. So it makes sense to show wild items as a little # table like the move table. item_table = CollapsibleVersionTable() for pokemon_item in default_pokemon.items: item_table.add_version_datum(pokemon_item.version, pokemon_item.item, pokemon_item.rarity) template_ns['wild_held_items'] = item_table ## Evolution template_ns['evolution_table'] = _build_evolution_table( species.evolution_chain_id) ## Moves # XXX yeah this is bad q = session.query(t.PokemonMove) \ .with_parent(default_pokemon) \ .order_by( t.PokemonMove.level.asc(), # t.Machine.machine_number.asc(), t.PokemonMove.order.asc(), t.PokemonMove.version_group_id.asc(), ) moves_table = SectionedCollapsibleVersionTable() for pokemove in q: moves_table.add_group_datum( pokemove.method, pokemove.version_group, pokemove.move, pokemove.level) _method_order = [u'level-up', 'egg', u'tutor', u'stadium-surfing-pikachu', u'machine'] moves_table.sort_sections(lambda method: _method_order.index(method.identifier)) template_ns['moves'] = moves_table return template_ns
def region_browse(context, request): regions = (session.query(t.Region).all()) template_ns = dict(regions=regions, ) return template_ns