#!/usr/bin/perl use warnings; use strict; use WWW::Mechanize; use XML::LibXML; use constant { PM_URL => 'http://www.perlmonks.org/bare/?node_id=', # Node ids: LOGIN => 109, XP => 32704, }; print "User? "; chomp(my $user = <>); print "Pass? "; chomp(my $pass = <>); my $mech = 'WWW::Mechanize'->new; $mech->get(PM_URL . LOGIN); $mech->submit_form( form_number => 1, fields => { user => $user, passwd => $pass, }, ); my %out; my $limit = 500; my $offset = 0; while (1) { $mech->get(PM_URL . XP . ";limit=$limit;offset=$offset"); my $xml = 'XML::LibXML'->load_xml(string => $mech->content); my @nodes = $xml->findnodes('/USERNODES/NODE'); last unless @nodes; for my $node (@nodes) { my ($date, $xp) = map $node->getAttribute($_), qw(createtime reputation); substr $date, 7, length($date), q{}; # Group by month. $out{$date}{count}++; $out{$date}{sum} += $xp; } $offset += $limit; } open my $OUT, '>', 'xp.out' or die $!; for my $date (sort keys %out) { print {$OUT} "$date\t", $out{$date}{sum} / $out{$date}{count}, "\n"; } close $OUT or die $!; =for gnuplot set xdata time set timefmt '%Y-%m' set xtics format '%Y-%m' plot 'xp.out' using 1:2:(2e6) with boxes fs solid =cut #### #!/usr/bin/perl use warnings; use strict; use 5.010; # // use Tk; use constant MESSAGE => 'Point a mouse over a bar to see the details'; my $width = 25; my $height = 200; my $space = 10; my $input = shift // 'xp.out'; open my $IN, '<', $input or die $!; my @rectangles; my ($oldest, $max, $min) = (0, 0, 0); while (my $line = <$IN>) { my ($date, $xp) = split ' ', $line; my ($year, $month) = split /-/, $date; my $x = $year * 12 + $month; $oldest ||= $x; $max = $xp if $xp > $max; $min = $xp if $xp < $min; push @rectangles, [ $x - $oldest, $xp, $date ]; } my $step = $height / $max; my $mw = 'MainWindow'->new(-title => 'Average XP per month'); my $info = MESSAGE; $mw->Label(-textvariable => \$info, -foreground => 'black', -background => 'white', -relief => 'ridge', )->pack(-pady => 5); my $canvas = $mw->Canvas(-background => 'white', -width => $width * (1 + $rectangles[-1][0]), -height => $height + 2 * $space + $step * abs $min, )->pack(-padx => 10, -pady => 10); for my $rect (@rectangles) { $canvas->createRectangle( $rect->[0] * $width, $space + $step * ($max - $rect->[1]), ++$rect->[0] * $width, $space + $height, -fill => (qw/blue cyan green yellow orange red/) [($rect->[1] + abs $min) / ($max + abs $min) * 5], -outline => 'black', -tag => "bar$rect->[0]", ); $canvas->bind("bar$rect->[0]", '' => sub { $info = "$rect->[2]: $rect->[1]" }); } $canvas->bind('all', '' => sub { $info = MESSAGE }); $mw->Button(-text => 'Quit', -command => sub { exit }, )->pack; MainLoop();