namazu-dev(ring)


[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: (garbage) Development Power Graph



Satoru Takabayashi <satoru-t@xxxxxxxxxxxxxxxxxx> wrote:

>>GD & gifgraphモジュール があれば結構簡単にできそうです。
>
>changelog2graph を作りました。生成したグラフを 
><http://cl.aist-nara.ac.jp/~satoru-t/tmp/ChangeLog.png> に置
>きました。

累積のグラフにした方がおもしろいです。グラフを再描画して同じ
ところに置き直しました。むらがあると階段状になります。

# Ruby はむらがなくてきれいです。:-)
# <http://cl.aist-nara.ac.jp/~satoru-t/tmp/ruby-ChangeLog.png>

-- Satoru Takabayashi

#! /usr/local/bin/perl -w
#
# changelog2graph - a tool to graph ChangeLog file.
#
# Usage:
#
#   % changelog2graph ChangeLog > ChangeLog.png
#
# Copyright (C) 2000 Satoru Takabayashi <satoru-t@xxxxxxxxxxxxxxxxxx>
#     All rights reserved.
#     This is free software with ABSOLUTELY NO WARRANTY.
#
# You can redistribute it and/or modify it under the terms of 
# the GNU General Public License version 2.
#

use strict;
use PNGgraph::lines;
use Time::Local;
use constant Independent => 0;
use constant Cumulative  => 1;

my %month_names = ("Jan" => 0, "Feb" => 1, "Mar" => 2, "Apr" => 3, 
		   "May" => 4, "Jun" => 5, "Jul" => 6, "Aug" => 7, 
		   "Sep" => 8, "Oct" => 9, "Nov" => 10, "Dec" => 11);

main();
sub main () {
    my %freqs = analyze_changelog();
    my $first_time = get_first_time(\%freqs);
    my $last_time  = get_last_time(\%freqs);
    my @data = generate_data(\%freqs, $first_time, $last_time);

    my $my_graph = new PNGgraph::lines(600,400);
    $my_graph->set( 
		    transparent   => 0,
		    two_axes      => 1,
		    line_width    => 2,
		    x_label       => 'Date',
		    y_label       => 'Changes',
		    title         => 'ChangeLog Graph',
		    x_label_skip  => int(@{$data[0]} / 8) + 1,
		    y_label_skip  => 2,
		    r_margin      => 40,
		    textclr       => "black",
		    dclrs         => [ qw(red blue green pink cyan) ],
		    );

    print $my_graph->plot(\@data);
}

sub analyze_changelog () {
    my %freqs = ();
    my $date  = undef;
    my $freq  = 0;
    while (<>) {
	next if /^\s*$/;
	chomp;

	if (/^(?:Sun|Mon|Tue|Wed|Thu|Fri|Sat)\s+
	    (\w+)\s+(\d+)\s+(?:[\d:]+)\s+(\d+)(.*)/x) 
	{ 
	    # Old type format: 
	    # Wed Jun  2 17:55:44 1999  Foo Bar <foo@xxxxxx>
	    my $mon  = $month_names{$1} + 1;
	    my $mday = $2;
	    my $year = $3;
	    my $rest = $4;

	    # Convert it to ISO 8601 type.
	    $_ = sprintf "%4d-%02d-%02d%s", $year, $mon, $mday, $rest;
	}

	if (/^(\d{4}-\d{2}-\d{2})\s/) {  
	    # ISO 8601 format:
	    # 1999-06-02  Foo Bar <foo@xxxxxx>
	    if (defined $date) {
		$freqs{$date} = $freq;
	    }
	    $date = $1;
	    $freq = 0;
	} elsif (/^\s+\*/) {
	    $freq++;
	}
    }
    $freqs{$date} = $freq;

    return %freqs;
}

sub get_first_time ($) {
    my ($freqs_ref) = @_;

    my $first_date = (sort keys %{$freqs_ref})[0];
    return date_to_time($first_date);
}

sub get_last_time ($) {
    my ($freqs_ref) = @_;

    my $last_date = (reverse sort keys %{$freqs_ref})[0];
    return date_to_time($last_date);
}

sub date_to_time ($) {
    my ($date) = @_;

    if ($date =~ /^(\d+)-(\d+)-(\d+)/) {
	my $year = $1;
	my $mon  = $2 - 1;
	my $mday = $3;
	return timelocal(0, 0, 0, $mday, $mon, $year);
    } else {
	die "$date: invalid date format";
    }
}

sub generate_data ($$$) {
    my ($freqs_ref, $first_time, $last_time) = @_;

    my @dates = ();
    my @indps = (); # independent
    my @cumls = (); # cumulative
    my $sum = 0;
    for (my $time = $first_time; $time <= $last_time; $time += 60 * 60 * 24) {
	my ($sec, $min, $hour, $mday, $mon, $year,
	    $wday, $yday, $isdst) = localtime($time);
	$year += 1900;
	$mon++;
	my $date = sprintf "%4d-%02d-%02d", $year, $mon, $mday;
	
	push @dates, $date;
	if (defined $freqs_ref->{$date}) {
	    push @indps, $freqs_ref->{$date};
	    $sum += $freqs_ref->{$date}
	} else {
	    push @indps, 0;
	}
	push @cumls, $sum;
    }

    return ([ @dates ], [ @indps ], [ @cumls ]);
}