Changeset 388
- Timestamp:
- 12/16/07 22:39:00 (12 months ago)
- Location:
- veekun/trunk
- Files:
-
- 2 added
- 4 modified
-
lib/Vee/Controller/Dex.pm (modified) (1 diff)
-
lib/Vee/Dex (added)
-
lib/Vee/Dex/EncounterSet.pm (added)
-
lib/Vee/Schema/Pokemon.pm (modified) (2 diffs)
-
lib/Vee/View/TT.pm (modified) (1 diff)
-
templates/dex/page/pokemon.tt (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
veekun/trunk/lib/Vee/Controller/Dex.pm
r382 r388 553 553 }; 554 554 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; 689 559 690 560 # moves from here down -
veekun/trunk/lib/Vee/Schema/Pokemon.pm
r350 r388 4 4 use warnings; 5 5 use base 'DBIx::Class'; 6 7 use Vee::Dex::EncounterSet; 6 8 7 9 =head1 NAME … … 133 135 } 134 136 137 =head2 sane_encounters 138 139 Returns the following data structure representing this Pokemon's wild 140 encounters: 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 159 sub 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 135 180 =head1 SEE ALSO 136 181 -
veekun/trunk/lib/Vee/View/TT.pm
r359 r388 72 72 $Template::Stash::SCALAR_OPS->{tohex} = sub { sprintf "%02X", $_[0] }; 73 73 $Template::Stash::SCALAR_OPS->{hex} = sub { hex shift }; 74 $Template::Stash::LIST_OPS->{hash} = sub { return { @{$_[0]} } };75 74 76 75 ################################################################################ -
veekun/trunk/templates/dex/page/pokemon.tt
r361 r388 281 281 <p>Numbers are levels. Bars are relative rarity. Hover for a percentage.</p> 282 282 <p>Swarms, the Poké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;"> 297 285 <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é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> 348 293 [% 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 %] 352 295 <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 %] 384 319 [% END %] 385 320 </table> 386 [% ELSE %]387 <p> This Pokémon is not available in the wild. </p>388 [% END %]389 [% END %]390 321 391 322 <!-- ####################################################################### -->
