#!/usr/local/bin/perl -w # import away use strict; use warnings; use Template; use LWP::Simple; use Parse::CPAN::Packages; use File::Copy; use Data::Dumper; # fetch the list of names our %names; # the total number of modules on cpan my $total = 0; # the total lpm number my $lpmtotal = 0; # try and keep track of stuff my %seen; my %people; my %totalpeople; # are we going to rank everybody? my $everything = (@ARGV && $ARGV[0] eq '-e'); # everything i.e do the whole of CPAN my $names = (@ARGV && $ARGV[0] eq '-f') ? $ARGV[1] : '.cpanscorerc'; require $names; #die Dumper \%names; # gah, Parse::CPAN::Packages should really take a filehandle my $url = "http://ftp.funet.fi/pub/languages/perl/CPAN/modules/02packages.details.txt.gz"; my $rc = mirror( $url, "/tmp/packages.gz" ); # $rc == RC_NOT_MODIFIED and exit; !(is_success($rc) || $rc == RC_NOT_MODIFIED) and die "Could not fetch package\n"; system("gzip -dc /tmp/packages.gz > /tmp/packages"); my $p = Parse::CPAN::Packages->new("/tmp/packages"); # loop through all the modules foreach my $dist ($p->distributions) { my $dist_name; next unless $dist_name = $dist->dist; next unless $dist = $p->latest_distribution($dist_name); my $author = $dist->cpanid or next; # old version next if $seen{$dist_name}++; $total++; # increase the hash of the total number of people # this a hack and a bit redundant but cleaner # than using %people and then skipping anything # that doesn't have any modules $totalpeople{$author} = 1; # not london.pm next unless ($everything || (grep{/^$author$/} keys %names)); $lpmtotal++; $people{ $author }->{total}++; push @{$people{ $author }{modules}}, $dist_name; } # get the total number of people my $totalpeople = keys %totalpeople; my $lpmpeople = keys %names; # sort by number then name my @order = sort funky_sort keys %people; # to stop it getting ridiculously large if ($everything) { @order = grep { $people{$_}->{total}>1 } @order; } sub funky_sort () { my $diff = $people{$b}->{total} - $people{$a}->{total}; $diff = $names{$a} cmp $names{$b} if ($diff == 0 && !$everything); return $diff; } # now print it all out my $template = join "", ; my $tt = Template->new || die $Template::ERROR, "\n"; my $vars = { people => \%people, totalpeople => $totalpeople, total => $total, lpmtotal => $lpmtotal, time => scalar localtime(), order => \@order, names => \%names, lpmpeople => $lpmpeople, percent => $lpmtotal*100/$total, ppl_percent => $lpmpeople*100/$totalpeople, all => $everything, }; $tt->process(\$template, $vars) || die $tt->error(), "\n"; __DATA__ [%- IF !all -%]London.pm [%- END -%]CPAN Leaderboard

The [%- IF !all -%]London.pm [%- END -%]CPAN Leaderboard (generated from 02packages.details.txt.gz on [% time %])

Contributors are ranked by number of modules and then by name

The code that does it is here - it's ugly.

enjoy ...

simon

[%- SET lastscore = 0 -%] [%- SET rcounter = 0 -%] [%- SET pcounter = 0 -%] [% FOREACH person = order %] [%- rcounter=1+rcounter -%] [%- SET nmods = people.$person.total -%] [% END %]
 
[%- IF lastscore != nmods -%] [%- pcounter = rcounter -%] [%- pcounter -%] [%- ELSE -%] [%- pcounter -%]= [%- END -%] [%- lastscore = nmods -%] [%- IF pcounter<10 -%] [%- END -%]    [% names.$person %] ([% person %])   ([% nmods %]) [%- FOREACH module = people.$person.modules.sort -%] [%- module -%][%- IF module != people.$person.modules.sort.last -%], [%- END -%] [%- END -%]
 
[% IF !all %] London.pm contributed :

[% lpmtotal %] of [% total %] packages ([% percent | format("%.2f") %]%) on CPAN
and constitute [% lpmpeople %] of all [% totalpeople %] authors ([% ppl_percent | format("%.2f") %]%).

[% END %]