http://qs1969.pair.com?node_id=254849

Looking for ideas to not have a totally bare website, I recently wrote a program that gathers my XP and number of posts on perlmonks, and plots the information.

The program below is run nightly from cron.

Abigail

#!/usr/bin/perl use strict; use warnings; use POSIX 'strftime'; use Date::Calc qw /Today Delta_Days/; use LWP::Simple; sub plotme; my $outdir = "/home/abigail/WWW"; $outdir = "/tmp" unless -d $outdir; my $output = "$outdir/monks.html"; my $outfile = "$outdir/Images/monks.png"; my $data = "$outdir/Data/monks.dat"; sub logme { my ($xp, $arts) = @_; my $today = strftime "%Y-%m-%d" => localtime; open my $fh => "+<", $data or die "Failed to open $data: $!\n"; my $first_line = <$fh>; my $first_date = (split /:/ => $first_line, 2) [0]; while (<$fh>) { my ($date, $xp, $arts) = split; if ($date =~ /^$today/) { close $fh; return $first_date; } } printf $fh "%s: %6d %6d\n" => $today, $xp, $arts; close $fh or die "Failed to close $data: $!\n"; return $first_date; } my $url = "http://www.perlmonks.org/index.pl?node_id=169744"; my $content = get ($url) or die "Failed to fetch $url\n"; my ($since) = $content =~ m!<td>User \s+ since:</td> \s+ <td>([^<]+)</td>!x; my ($exp) = $content =~ m!<td>Experience:</td> \s+ <td><b>(\d+)</b></td>!x; my ($arts) = $content =~ m!<td>Writeups:</td> \s+ <td><b><a[^>]+>(\d+)</a></b></td>!x; die "Failed to find 'User since'.\n" unless defined $since; die "Failed to find 'Experience'.\n" unless defined $exp; die "Failed to find 'Write ups'.\n" unless defined $arts; unless ($since =~ /([A-Z][a-z]+)\s+(\d+),\s+(\d+)/) { die "Failed to parse $since.\n"; } my %M = qw /Jan 1 Feb 2 Mar 3 Apr 4 May 5 Jun 6 Jul 7 Aug 8 Sep 9 Oct 10 Nov 11 Dec 12/; my ($month, $day, $year) = ($M {$1}, $2, $3); my $start = "$2 $1 $3"; my $nr_of_days = Delta_Days $year, $month, $day, Today; my $exp_per_day = sprintf "%.1f" => $exp / $nr_of_days; my $arts_per_day = sprintf "%.1f" => $arts / $nr_of_days; my $exp_per_art = sprintf "%.1f" => $exp / $arts; my $first_log = logme $exp, $arts; my ($s_y, $s_m, $s_d) = split /-/ => $first_log; $first_log = strftime "%e %B %Y" => 0, 0, 0, $s_d, $s_m - 1, $s_y - 19 +00; plotme; # # HTML generating stuff. # my $now = strftime "%e %B %Y" => localtime; open my $of => ">", $output or die "Failed to open $output: $!\n"; select $of; print << "--"; <html> <head><title>Perl Monk Postings</title></head> <body> <a href = "/">Home</a> <hr> <h1>Perl Monk Postings</h1> <p> I'm a frequent poster on <a href = "http://www.perlmonks.org">Perlmonk +s</a>. My first post dates from $start. Since then, I gathered $exp experienc +e points, writing $arts posts. This comes to $arts_per_day articles per +day on average, and $exp_per_day experience points per day. <p> It doesn't account to $exp_per_art experience per article, because you can get heaps of experience for just connecting to the site, or voting on other people. <p> Below is a graph showing the experience progress since $first_log. <p align = "center"> <img src = "Images/monks.png" alt = "Perlmonks experience points"> <p> It should be noted that experience points don't mean anything. <p> <hr> <div align = "center"> <table><tr><td> Copyright 2003 by Abigail.<br> Page last modified: $now.<br> Comments to: \$web\$\@abigail.nl </td></tr></table> </div> </body></html> -- close $of or die "Failed to close $output: $!\n"; chmod 0644 => $output or die "Failed to chmod $output: $!\n"; sub plotme { open my $plot => "| gnuplot" or die "Failed to open pipe: $!\n"; print $plot <<"--"; set terminal png color set out "$outfile" set xdata time set timefmt "%Y-%m-%d:" set key left top Left reverse samplen 2 title "Legend" box set grid xtics ytics set xtics nomirror set ytics nomirror set y2tics nomirror set yrange [0:] set y2range [0:] set ylabel "XP" set y2label "Postings" plot "$data" using 1:2 smooth unique axis x1y1 title "Perlmonks +XP", \\ "$data" using 1:3 smooth unique axis x1y2 title "Nr of post +ings" -- close $plot or die "Failed to close pipe: $!\n"; chmod 0644 => $outfile or die "Failed to chmod $outfile: $!\n"; } __END__ This program is copyright 2003 by Abigail. Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the "Softwar +e"), to deal in the Software without restriction, including without limitat +ion the rights to use, copy, modify, merge, publish, distribute, sublicens +e, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be include +d in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRES +S OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILIT +Y, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHAL +L THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

Replies are listed 'Best First'.
Re: Plotting XP
by BrowserUk (Patriarch) on May 02, 2003 at 00:19 UTC

    Graphics?? COLOR??? XP???? Abigail-II???


    Examine what is said, not who speaks.
    1) When a distinguished but elderly scientist states that something is possible, he is almost certainly right. When he states that something is impossible, he is very probably wrong.
    2) The only way of discovering the limits of the possible is to venture a little way past them into the impossible
    3) Any sufficiently advanced technology is indistinguishable from magic.
    Arthur C. Clarke.
      Just what I thought. :-D

      Makeshifts last the longest.

      It says It should be noted that experience points don't mean anything on the website.

      Nice script, Abigail!

        It was the color graphics that suprised me most.

        I wonder what happened to humour


        Examine what is said, not who speaks.
        1) When a distinguished but elderly scientist states that something is possible, he is almost certainly right. When he states that something is impossible, he is very probably wrong.
        2) The only way of discovering the limits of the possible is to venture a little way past them into the impossible
        3) Any sufficiently advanced technology is indistinguishable from magic.
        Arthur C. Clarke.
      My feelings regarding form over content and the Tragedy of HTML are in agreement with Abigail's long-standing manifesto cited above. The CERN/TB-L view of the WWW was ruined by the introduction of Marketing-style graphic design. However, when the data is rich enough, graphics and even color graphics are appropriate. See Bertin and/or Tufte. 1 2 3 4
      (Note that conformant to dogma, these are em tags not i tags!) Abigail's manifesto is upheld perfectly, since not only was the data rich enough to grpah, the article showed the code but didn't link the graphic.

      system()ing out to gnuplot is fine for those who have it and are comfortable with it. I recall doing stereograms with Unix V7 plot and a daiseywheel terminal, it works, but I've not played much with gnuplot. The example is even readably self-documenting as an embedded here-doc, I like that. (I may be over-sensitized on that; Uri was sounding off on readability last night in his Boston.PM rehearsal of his YAPC talk.) Hiding the system() in a open("|gnuplot") that demos 5.6's autoviv FDs is even cooler.

      In spirit of TMTOWTDI and CUFP, I rather like Stein's GD.pm and Verbruggen's GD::Graph wrapper for Boutell's libgd. Latest revs support TrueColor as well as palettized, and both PNG and JPeG (GIF is gone). I see there's even now a Template::Plugin::GD::Graph in the Template-Toolkit, which could be interesting for on-the-fly graphics (which I try to avoid, but could be useful if the data xor users are dynamic).

      Cheers,
      -- Bill N1VUX
      If I post a few more times I should register, eh?

        My comment was very much tongue in cheek.

        I hate blinking text, text-in-gifs and 30 seconds flash introductions with a vengence.

        I like my code syntax highlighted, as it adds another dimension, and allows the computer to do much of the work of ensuring I close my quotes, don't misspell my keywords, highlights variables that have only been seen once (usually typos) etc. That's what computers are for.

        As you say, when the graphic incorporates information not style, it is a definite plus.

        Oh go on with you..... it doesn't hurt! Join already.


        Examine what is said, not who speaks.
        "Efficiency is intelligent laziness." -David Dunham
        "When I'm working on a problem, I never think about beauty. I think only how to solve the problem. But when I have finished, if the solution is not beautiful, I know it is wrong." -Richard Buckminster Fuller
Re: Plotting XP
by Anonymous Monk on May 02, 2003 at 09:10 UTC
    wow, that is bad code. How is +< supposed to create the data file?

      perldoc -f open

      [...] You can put a '+' in front of the '>' or '<' to indicate you want both read and write access to the file; thus  '+<' is almost always preferred for read/write updates--the '+>' mode would clobber the file first.

        OK, I read your message again. You said create.

        c:\> perl -e "open FH, '+<new_file.txt'; print FH '123'; close FH;" c:\> dir new_file.txt [..] File not Found

        Maybe Abigail-II's file already existed/was not created by this script? At least what open and close return is checked.

      It doesn't. I never claimed it will. The data file I use, I originally seeded by hand.

      If I have given the suggestion the code I posted is something you can just download and run everywhere, I've given the wrong impression. I just posted code that runs daily on my system, and that was developped purely to run on my system. It was posted mainly for educational and illustrational purposes. It should run on many systems, but some assembly will be required.

      Abigail

        Nice one Abigail-II :-) ++

        As for me this code it's a "pure good thing" - nice idea, short code and some place left for (programmer, not the program) evolution :-)
        - It works for me... but nobody said it would work for you :-P

        Greetz, Tom.
      Why should it?

      Makeshifts last the longest.