Changeset 388

Show
Ignore:
Timestamp:
12/16/07 22:39:00 (12 months ago)
Author:
eevee
Message:

Added a class to wrap around location/Pokemon pairs, and simplified location data on Pokemon pages. (#228)

Location:
veekun/trunk
Files:
2 added
4 modified

Legend:

Unmodified
Added
Removed
  • veekun/trunk/lib/Vee/Controller/Dex.pm

    r382 r388  
    553553    }; 
    554554 
    555     # This is all devoted to locations, the second-most complicated section! 
    556     # it is full of clever hackery that presents mostly-correct data as well 
    557     # as I can manage while still presenting users with what they expect. 
    558     # This is engineered to be as usable as possible, which means: 
    559     # 1. columns that are empty will not show up 
    560     # 2. replacements like day/night/swarm will show levels/rarity for when that 
    561     #    event is in effect, rather than a meaningless icon 
    562     my $encounters_rs = $row->encounters_rs(undef, { 
    563         prefetch  => 'location', 
    564         group_by  => [qw/ version location_id section method /], 
    565  
    566         # this minor hackery will essentially collapse multiple rows for a 
    567         # method into one short one we care about 
    568         '+select' => [ 
    569             \ 'GROUP_CONCAT(rarity SEPARATOR " ") AS rarity', 
    570             \ 'MIN(min_level) AS min_level', 
    571             \ 'MAX(max_level) AS max_level', 
    572         ], 
    573         '+as'     => [qw/ rarity min_level max_level /], 
    574  
    575         # grass needs to come first so we can do replacements correctly 
    576         order_by  => 'method = "grass" DESC, method IN ("daytime", "night") DESC', 
    577     } ); 
    578  
    579     my %locations; 
    580     my (%loc_seen_methods, $loc_any_sections, %loc_bases); 
    581     while (my $enc = $encounters_rs->next) { 
    582         $loc_any_sections = 1 if $enc->section; 
    583  
    584         # if this is a wacky replacement and we don't have grass, mark it as 
    585         # existing and then skip to the next thingy. 
    586         if (not grep { $enc->method eq $_ } 
    587             qw/ grass daytime night surfing old-rod good-rod super-rod / 
    588         ) { 
    589             unless (grep { defined $locations{ $enc->version }{ $enc->location->name }{ $enc->section }{$_} } qw/ grass daytime night /) { 
    590                 $locations{ $enc->version }{ $enc->location->name } 
    591                           { $enc->section }{ $enc->method } = 1; 
    592                 $loc_seen_methods{ $enc->method } = 1; 
    593             } 
    594             next; 
    595         } 
    596          
    597         my $sec_ref = $locations{ $enc->version }{ $enc->location->name } 
    598                                 { $enc->section } ||= {}; 
    599  
    600         my $is_replacement = grep { $enc->method eq $_ } qw/ daytime night /; 
    601  
    602         my ($min, $max) = ($enc->min_level, $enc->max_level); 
    603         my @rarities = split / /, $enc->rarity; 
    604  
    605         # this assumes that the levels are already in the database! 
    606         # sql: UPDATE location_encounters l INNER JOIN location_encounters l2 USING (location_id, section, rarity) SET l.min_level = l2.min_level, l.max_level = l2.max_level WHERE l.method IN ('daytime', 'night') AND l2.method = 'grass'; 
    607  
    608         if ($is_replacement and 
    609             my $base_ref = $loc_bases{ $enc->version }{ $enc->location->name }{ $enc->section }) 
    610         { 
    611             @rarities = uniq @rarities, split / /, $base_ref->rarity; 
    612              
    613             # TODO: lol this doesn't work all that well 
    614             $min = min $min, $base_ref->min_level; 
    615             $max = max $max, $base_ref->max_level; 
    616         } 
    617  
    618         # make levels intelligently readable 
    619         my $level; 
    620         if (not $min) { 
    621             $level = ''; 
    622         } elsif ($min == $max) { 
    623             $level = $min; 
    624         } else { 
    625             $level = $min . ' - ' . $max; 
    626         } 
    627  
    628         my $rarity = sum map { $Generations[3]{locpercents}[$_] } @rarities; 
    629  
    630         $sec_ref->{ $enc->method } = { 
    631             level  => $level, 
    632             rarity => $rarity, 
    633         }; 
    634         $loc_bases{ $enc->version }{ $enc->location->name }{ $enc->section } = $enc 
    635             if $enc->method eq 'grass'; 
    636  
    637         $loc_seen_methods{ $enc->method } = 1; 
    638     } 
    639  
    640     # for Pokemon that appear during the morning and aren't changed at other 
    641     # times, we have to fill in the default ourselves 
    642     for my $version (keys %locations) { 
    643         my $version_ref = $locations{$version}; 
    644         for my $location (keys %$version_ref) { 
    645             my $location_ref = $version_ref->{$location}; 
    646             for my $section (keys %$location_ref) { 
    647                 my $section_ref = $location_ref->{$section}; 
    648  
    649                 next if $section_ref->{daytime} and $section_ref->{night}; 
    650  
    651                 my $base_ref = $loc_bases{ $version }{ $location }{ $section }; 
    652                 next if not $base_ref; 
    653  
    654                 # TODO: don't hardcode 2/3 
    655                 my @rarities = grep { $_ != 2 and $_ != 3 } split / /, $base_ref->rarity; 
    656                 next if not @rarities; 
    657  
    658                 # TODO: levels suck down here, too 
    659                 my $copied_enc = { 
    660                     level  => $base_ref->level, 
    661                     rarity => sum map { $Generations[3]{locpercents}[$_] } @rarities 
    662                 }; 
    663  
    664                 $section_ref->{daytime} ||= $copied_enc; 
    665                 $section_ref->{night}   ||= $copied_enc; 
    666  
    667                 $loc_seen_methods{daytime} = $loc_seen_methods{night} = 1; 
    668             } 
    669         } 
    670     } 
    671  
    672     BARE: { 
    673         local $Data::Dumper::Sortkeys = 1; 
    674         if ( Dumper($locations{diamond}) eq Dumper($locations{pearl}) ) { 
    675             %locations = ( dp => $locations{diamond} ); 
    676         } 
    677     } 
    678  
    679     $s->{encounters} = \%locations; 
    680  
    681     my @location_columns = grep { $loc_seen_methods{$_} } qw/ 
    682         grass daytime night surfing 
    683         old-rod good-rod super-rod swarm poketore 
    684     /; 
    685     push @location_columns, 'dualslot' 
    686         if grep { /^ds-/ } keys %loc_seen_methods; 
    687     unshift @location_columns, 'section' if $loc_any_sections; 
    688     $s->{location_columns} = { map { $_ => 1 } @location_columns }; 
     555    my %new_encounters; 
     556    my @new_encounters = $row->sane_encounters; 
     557    warn $_->simplest_method for @new_encounters; 
     558    $s->{new_encounters} = \@new_encounters; 
    689559 
    690560    # moves from here down 
  • veekun/trunk/lib/Vee/Schema/Pokemon.pm

    r350 r388  
    44use warnings; 
    55use base 'DBIx::Class'; 
     6 
     7use Vee::Dex::EncounterSet; 
    68 
    79=head1 NAME 
     
    133135} 
    134136 
     137=head2 sane_encounters 
     138 
     139Returns the following data structure representing this Pokemon's wild 
     140encounters: 
     141 
     142    [ 
     143        { 
     144            location => $location_obj, 
     145            section  => $section, 
     146            methods  => { 
     147                grass => [ 
     148                    { 
     149                        levels => [ 5, 7 ], 
     150                        rarity => 100, 
     151                    }, ... 
     152                ], ... 
     153            } 
     154        }, ... 
     155    ] 
     156 
     157=cut 
     158 
     159sub sane_encounters { 
     160    my ($self) = @_; 
     161 
     162    my @encounter_sets; 
     163 
     164    my $sections_rs = $self->encounters_rs( undef, { 
     165        group_by => 'location_id, section', 
     166    } ); 
     167 
     168    while (my $section = $sections_rs->next) { 
     169        my $encounters_rs = $section->location->encounters_rs( { 
     170            version     => 'diamond', 
     171            section     => $section->section, 
     172        } ); 
     173 
     174        push @encounter_sets, Vee::Dex::EncounterSet->new($encounters_rs, $self); 
     175    } 
     176 
     177    return @encounter_sets; 
     178} 
     179 
    135180=head1 SEE ALSO 
    136181 
  • veekun/trunk/lib/Vee/View/TT.pm

    r359 r388  
    7272$Template::Stash::SCALAR_OPS->{tohex} = sub { sprintf "%02X", $_[0] }; 
    7373$Template::Stash::SCALAR_OPS->{hex} = sub { hex shift }; 
    74 $Template::Stash::LIST_OPS->{hash} = sub { return { @{$_[0]} } }; 
    7574 
    7675################################################################################ 
  • veekun/trunk/templates/dex/page/pokemon.tt

    r361 r388  
    281281<p>Numbers are levels.  Bars are relative rarity.  Hover for a percentage.</p> 
    282282<p>Swarms, the Pok&eacute;radar, and dual-slot icons are shown if [% this.name %] shows up during the event but <em>not</em> normally.  See the location page for gritty details.</p> 
    283 [% hacky_ds_map = { ruby => 'ru', sapphire => 'sa', emerald => 'e', firered => 'fr', leafgreen => 'lg' } %] 
    284 [% FOR version IN encounters.keys.sort %] 
    285 [%     IF version != 'dp' %] 
    286 <h2>[% Icons.${ version.substr(0, 1) } %] [% version | ucfirst %]</h2> 
    287 [%     END %] 
    288 [% IF location_columns.keys.size %] 
    289 <table cellspacing="0" cellpadding="3" class="dex-table dex-locations"> 
    290 [% grass_columns = (location_columns.grass   || 0) 
    291                  + (location_columns.daytime || 0) 
    292                  + (location_columns.night   || 0) %] 
    293 [% fish_columns = (location_columns.${'old-rod'}   || 0) 
    294                 + (location_columns.${'good-rod'}  || 0) 
    295                 + (location_columns.${'super-rod'} || 0) %] 
    296 [% rowspan = ' rowspan="2"' IF grass_columns OR fish_columns OR location_columns.dualslot %] 
     283 
     284<table cellspacing="0" cellpadding="3" class="dex-table dex-locations" style="display: inline-table;"> 
    297285<tr class="heading"> 
    298     <th[% rowspan %]>Area</th> 
    299 [% IF location_columns.section %] 
    300     <th[% rowspan %]>Section</th> 
    301 [% END %] 
    302 [% IF grass_columns %] 
    303     <th colspan="[% grass_columns %]">Grass</th> 
    304 [% END %] 
    305 [% IF location_columns.surfing %] 
    306     <th[% rowspan %]>Surfing</th> 
    307 [% END %] 
    308 [% IF fish_columns %] 
    309     <th colspan="[% fish_columns %]">Fishing</th> 
    310 [% END %] 
    311 [% IF location_columns.swarm %] 
    312     <th[% rowspan %]>Swarm</th> 
    313 [% END %] 
    314 [% IF location_columns.poketore %] 
    315     <th[% rowspan %]>Pok&eacute;radar</th> 
    316 [% END %] 
    317 [% IF location_columns.dualslot %] 
    318     <th colspan="5">Game in GBA slot</th> 
    319 [% END %] 
    320 </tr> 
    321 [% IF grass_columns OR fish_columns OR location_columns.dualslot %] 
    322 <tr class="heading"> 
    323 [% IF location_columns.grass %] 
    324     <th>Morn</th> 
    325 [% END %] 
    326 [% IF location_columns.daytime %] 
    327     <th>Day</th> 
    328 [% END %] 
    329 [% IF location_columns.night %] 
    330     <th>Night</th> 
    331 [% END %] 
    332 [% IF location_columns.${'old-rod'} %] 
    333     <th><img src="/dex-images/items/old-rod.png" alt=""/><br/>Old</th> 
    334 [% END %] 
    335 [% IF location_columns.${'good-rod'} %] 
    336     <th><img src="/dex-images/items/good-rod.png" alt=""/><br/>Good</th> 
    337 [% END %] 
    338 [% IF location_columns.${'super-rod'} %] 
    339     <th><img src="/dex-images/items/super-rod.png" alt=""/><br/>Super</th> 
    340 [% END %] 
    341 [% IF location_columns.dualslot %] 
    342 [%     FOR slot IN [ 'ru', 'sa', 'e', 'fr', 'lg' ] %] 
    343     <th>[% Icons.$slot %]</th> 
    344 [%     END %] 
    345 [% END %] 
    346 </tr> 
    347 [% END %] 
     286    <th> Area </th> 
     287    <th> Section </th> 
     288    <th> Level </th> 
     289    <th> Morn </th> 
     290    <th> Day </th> 
     291    <th> Night </th> 
     292</tr> 
    348293[% color = 1 %] 
    349 [% FOR location IN encounters.$version.keys.sort %] 
    350 [%     FOR section IN encounters.$version.$location.keys.sort %] 
    351 [%             methods = encounters.$version.$location.$section %] 
     294[% FOREACH enc IN new_encounters %] 
    352295<tr class="color[% color %]"> 
    353     <td class="dex-locations-zone"><a href="[% dex_uri('locations', location) %]">[% location %]</a></td> 
    354 [% IF location_columns.section %] 
    355     <td class="dex-locations-zone">[% section %]</td> 
    356 [% END %] 
    357 [% IF location_columns.grass %] 
    358 [%     rarity_cell(methods.grass) %] 
    359 [% END %] 
    360 [% IF location_columns.daytime %] 
    361 [%     rarity_cell(methods.daytime) %] 
    362 [% END %] 
    363 [% IF location_columns.night %] 
    364 [%     rarity_cell(methods.night) %] 
    365 [% END %] 
    366 [%         FOR m IN ['surfing', 'old-rod', 'good-rod', 'super-rod'] %] 
    367 [%             NEXT IF NOT location_columns.$m %] 
    368     <td>[% methods.$m.level %][% rarity_bar(methods.$m.rarity) %]</td> 
    369 [%         END %] 
    370 [% IF location_columns.swarm %] 
    371     <td>[% IF methods.swarm %]<img src="/dex-images/items/teachy-tv.png" alt="swarm"/>[% END %]</td> 
    372 [% END %] 
    373 [% IF location_columns.poketore %] 
    374     <td>[% IF methods.poketore %]<img src="/dex-images/items/poketore.png" alt="poketore"/>[% END %]</td> 
    375 [% END %] 
    376 [% IF location_columns.dualslot %] 
    377 [%     FOR slot IN [ 'ruby', 'sapphire', 'emerald', 'firered', 'leafgreen' ] %] 
    378 <td>[% IF methods.${"ds-$slot"} %][% Icons.${ hacky_ds_map.$slot } %][% END %]</td> 
    379 [%     END %] 
    380 [% END %] 
    381 </tr> 
    382 [%         color = 3 - color %] 
    383 [%     END %] 
     296    <td> [% enc.location.name %] </td> 
     297    <td> [% enc.section %] </td> 
     298[%     SET simple_method = enc.simplest_method.hash %] 
     299    <td> [% simple_method.level.0 %][% IF simple_method.level.0 != simple_method.level.1; ' - '; simple_method.level.1; END %] </td> 
     300[%     category = simple_method.category %] 
     301[%     SWITCH category %] 
     302[%     CASE 'time' %] 
     303    <td> [% simple_method.rarities.morning %]% </td> 
     304    <td> [% simple_method.rarities.daytime %]% </td> 
     305    <td> [% simple_method.rarities.night %]% </td> 
     306[%     CASE 'swarm' %] 
     307    <td colspan="3"><img src="/dex-images/items/teachy-tv.png" alt="Swarm" title="Swarm"/> [% simple_method.rarities.1 %]%</td> 
     308[%     CASE 'water' %] 
     309    <td colspan="3">[% FOR rod IN simple_method.rarities.keys %]<img src="/dex-images/items/[% rod == 'surfing' ? 'hm-water' : rod %].png" alt="[% rod %]" title="[% rod %]"/> [% simple_method.rarities.$rod %]%[% '; ' UNLESS loop.last %][% END %] </td> 
     310[%     CASE 'pokeradar' %] 
     311    <td colspan="3"><img src="/dex-images/items/poke-radar.png" alt="Radar" title="Radar"/> [% simple_method.rarities.1 %]%</td> 
     312[%     CASE 'dualslot' %] 
     313    <td colspan="3">[% FOR ver IN simple_method.rarities.keys %][% Icons.$ver %] [%+ simple_method.rarities.$ver %]%[% '; ' UNLESS loop.last %][% END %]</td> 
     314[%     CASE %] 
     315    <td colspan="3">unknown: [% category %]: [% simple_method.rarities.keys.sort.join %]</td> 
     316[%     END %] 
     317</tr> 
     318[%     color = 3 - color %] 
    384319[% END %] 
    385320</table> 
    386 [% ELSE %] 
    387 <p> This Pok&eacute;mon is not available in the wild. </p> 
    388 [% END %] 
    389 [% END %] 
    390321 
    391322<!-- ####################################################################### -->