#!/usr/bin/perl -w
# -*- perl -*-
use P4CGI ;
use strict ;
#
#################################################################
# CONFIGURATION INFORMATION
# All config info should be in P4CGI.pm
#
#################################################################
#
# P4 change browser
# Depot statistics
#
#################################################################
#######
# Parameters:
#
######
$| = 1 ;
#
# Get parameter(s)
#
my $FSPC = P4CGI::cgi()->param("FSPC") ;
$FSPC = "//..." unless defined $FSPC ;
my @FSPC = split(/\s*\+?\s*(?=\/\/)/,$FSPC) ;
$FSPC = "".join(" and ",@FSPC)."" ;
my $FSPCcmd = "\"" . join("\" \"",@FSPC) . "\"" ;
###
### subroutine findTime
### A (really) poor mans version of mktime(3).
### Parameters: year,month,day,hour,min
### Returns: time_t value that corresponds to above result (almost)
sub findTime($$$$$)
{
my ($iyear,$imon,$iday,$ihour,$imin) = @_ ;
$iyear -= 1900 ;
$imon-- ;
my $time = time() ;
my $delta = int($time/2)+1 ;
my $lastsgn = -1 ;
my $n = 300 ;
while($delta > 10) {
last if $n-- == 0 ;
my $sgn = 1 ;
my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($time) ;
my $i = ((((((((($iyear * 12) + $imon) * 32) + $iday) * 24) + $ihour) * 60) + $imin) * 60) + 30 ;
my $o = ((((((((($year * 12) + $mon) * 32) + $mday) * 24) + $hour) * 60) + $min) * 60) + $sec ;
last if $i == $o ;
$sgn = -1 if $i < $o ;
$time += ($sgn * $delta) ;
$delta = int(($delta+1)/2) ;
$lastsgn = $sgn ;
}
return $time ;
} ;
&P4CGI::SET_HELP_TARGET("DepotStats") ;
print &P4CGI::start_page("Depot Statistics for
".
join("
and
\n",@FSPC) . "" ,
&P4CGI::ul_list(&P4CGI::ahref(-url => &P4CGI::cgi()->self_url . "#weekly",
"Weekly Submit Statistics"),
&P4CGI::ahref(-url => &P4CGI::cgi()->self_url . "#byuser",
"Submit Statistics by user")
)) ;
sub printStat($$) {
my $prompt = shift @_ ;
my $data = shift @_ ;
print
&P4CGI::table_row({-type => "th",
-align => "right",
-valign => "top",
-width => "50%",
-text => "$prompt:"},
{-type => "td",
-align => "left",
-width => "50%",
-text => $data}) ;
};
print
"
Depot statistics
",
&P4CGI::start_table("") ;
{
my @counters ;
&P4CGI::p4call(\@counters,"counters") ;
# printStat("P4 counters","") ;
foreach (@counters) {
s/(\S+) = /P4 $1 counter = / ;
&printStat(split(" = ","$_")) ;
}
}
# Users
my @users ;
&P4CGI::p4call(\@users,"users") ;
printStat("Users",@users) ;
# Clients
my @clients ;
&P4CGI::p4call(\@clients,"clients") ;
printStat("Clients",@clients) ;
# Labels
my @labels ;
&P4CGI::p4call(\@labels,"labels") ;
printStat("Labels",@labels) ;
# branches
my @branches ;
&P4CGI::p4call(\@branches,"branches") ;
printStat("Branches",@branches) ;
# jobs
my @jobs ;
&P4CGI::p4call(\@jobs,"jobs") ;
printStat("Jobs",@jobs) ;
print &P4CGI::end_table(),"
" ;
# Get changes
my @changes ;
&P4CGI::p4call(\@changes,"changes -s submitted $FSPCcmd") ;
# Sort and remove duplicates
{
my @ch = sort { $a =~ /Change (\d+)/ ; my $ac = $1 ;
$b =~ /Change (\d+)/ ; my $bc = $1 ;
$bc <=> $ac } @changes ;
my $last="" ;
@changes = grep {my $l = $last ;
$last = $_ ;
$_ ne $l } @ch ;
}
## File list stats
print
"Statistics for \"$FSPC\"
",
&P4CGI::start_table("") ;
printStat("Submitted changes",scalar @changes) ;
# Data about first submit
my $first = pop @changes ;
push @changes,$first ;
$first =~ s/Change (\d+).*/$1/ ;
my %data ;
my $firstTime = 0;
my $firstDate = "";
my $daysSinceFirstSubmit = 0 ;
&P4CGI::p4readform("change -o $first",\%data) ;
if(exists $data{"Date"}) {
$firstDate = $data{"Date"} ;
if($data{"Date"} =~ /(\d+).(\d+).(\d+).(\d+).(\d+)/) {
$firstTime = findTime($1,$2,$3,$4,$5) ;
my $seconds = time() - $firstTime ;
$daysSinceFirstSubmit = int($seconds/(24*3600)) ;
}
}
# Last submit
my $last = shift @changes ;
unshift @changes,$last ;
$last =~ s/Change (\d+).*/$1/ ;
my $lastTime=0 ;
my $lastDate="" ;
my $daysSinceLastSubmit=0 ;
&P4CGI::p4readform("change -o $last",\%data) ;
if(exists $data{"Date"}) {
$lastDate = $data{"Date"} ;
if($data{"Date"} =~ /(\d+).(\d+).(\d+).(\d+).(\d+)/) {
$lastTime = findTime($1,$2,$3,$4,$5) ;
my $seconds = time() - $lastTime ;
$daysSinceLastSubmit = int($seconds/(24*3600)) ;
}
} ;
printStat("First submit","$first ($firstDate)") ;
printStat("Latest submit","$last ($lastDate)") ;
printStat("Days between first and latest submit",$daysSinceFirstSubmit-$daysSinceLastSubmit) ;
if(($daysSinceFirstSubmit-$daysSinceLastSubmit) > 0) {
printStat("Average submits per day",
sprintf("%.2f",@changes/($daysSinceFirstSubmit-$daysSinceLastSubmit))) ;
};
# Read and parse file list
my $files=0 ;
my $deletedFiles=0 ;
my %revlevels ;
my $maxrevlevel=0 ;
my $totrevs=0 ;
my $file ;
foreach $file (@FSPC) {
local *F ;
&P4CGI::p4call(*F,"files \"$file\"") ;
while() {
$files++ ;
/\#(\d+) - (\S+)/ ;
my ($r,$s) = ($1,$2) ;
$deletedFiles++ if $s eq "delete" ;
$totrevs += $r ;
$maxrevlevel = $r if $r > $maxrevlevel ;
$revlevels{$r} = 0 unless exists $revlevels{$r} ;
$revlevels{$r}++ ;
}
close F ;
}
printStat("Current number of files",$files) ;
printStat("Deleted files",$deletedFiles) ;
printStat("Average revision level for files ",sprintf("%.2f",$totrevs/$files)) ;
printStat("Max revision level",$maxrevlevel) ;
print &P4CGI::end_table(),"
" ;
# File revision statistics
# print
# "
",
# &P4CGI::start_table("width=90%"),
# &P4CGI::table_row(-type=>"th",
# undef,
# undef,
# "File Revision Statistics"),
# &P4CGI::table_row({-type=>"th",
# -text => "Revision Level",
# -width => "20%",
# -align => "right"},
# {-text => "No. of
files",
# -type=>"th",
# -width => "10%"},
# {-text => " ",
# -bgcolor=>&P4CGI::BGCOLOR()}),
# &P4CGI::end_table() ;
#
#my $max = 0 ;
#
#foreach (keys %revlevels) {
# $max = $revlevels{$_} if $max < $revlevels{$_} ;
#} ;
#
# my $rev=$maxrevlevel ;
# while($rev > 0) {
# my $n = 0 ;
# $n = $revlevels{$rev} if exists $revlevels{$rev} ;
# my $w = int((65.0 * $n)/$max) ;
# if($w == 0) { $w = 1 ; } ;
# print
# &P4CGI::start_table("colums=4 width=90% cellspacing=0"),
# &P4CGI::table_row({-text => "$rev",
# -width => "20%",
# -align => "right"},
# {-text => $n==0?"-":"$n",
# -align => "center",
# -width => "10%"},
# {-text => " ",
# -bgcolor => $n!=0?"blue":&P4CGI::BGCOLOR(),
# -width => "$w\%"},
# {-text => " ",
# -bgcolor=>&P4CGI::BGCOLOR()}) ;
# print &P4CGI::end_table() ;
# $rev-- ;
# }
my %dailySubStat ;
my %userSubStat ;
my $n ;
#my $time = time() ;
my $time = $lastTime ;
my $ONE_DAY=3600*24 ;
my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($time);
while($wday != 0) {
$time -= $ONE_DAY ;
($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($time);
}
sub getNextDate() {
my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($time);
$time -= $ONE_DAY * 7 ;
my $day = sprintf("%4d/%02.2d/%02.2d",$year + 1900, $mon + 1, $mday) ;
$dailySubStat{$day} = 0 ;
return $day ;
} ;
# Read and parse change list
my $day = getNextDate() ;
my $max = 0 ;
while(@changes > 0) {
$_ = shift @changes ;
if(/Change \d+ on (\S+) by (\S+)\@/) {
my $d = $1 ;
my $user = $2 ;
while($d lt $day) {
$day = getNextDate() ;
}
$dailySubStat{$day}++ ;
$max = $dailySubStat{$day} if $dailySubStat{$day} > $max ;
$userSubStat{$user} = 0 unless exists $userSubStat{$user} ;
$userSubStat{$user}++ ;
}
}
# Weekly Submit Statistics
print "Weekly Submit Rate for $FSPC
",
&P4CGI::start_table("width=90%"),
&P4CGI::table_row({-type=>"th",
-text => "Week starting",
-width => "20%",
-align => "right"},
{-text => "submits",
-type=>"th",
-width => "10%"},
{-text => " ",
-bgcolor=>&P4CGI::BGCOLOR()}),
&P4CGI::end_table() ;
my $d ;
foreach $d (sort { $b cmp $a } keys %dailySubStat) {
print &P4CGI::start_table("colums=4 width=90% cellspacing=0") ;
my $n = $dailySubStat{$d} ;
my $w = int((65.0 * $n)/$max) ;
if($w == 0) { $w = 1 ; } ;
print &P4CGI::table_row({-text => "$d",
-width => "20%",
-align => "right"},
{-text => $n==0?"-":"$n",
-align => "center",
-width => "10%"},
{-text => " ",
-bgcolor => $n!=0?"blue":&P4CGI::BGCOLOR(),
-width => "$w\%"},
{-text => " ",
-bgcolor=>&P4CGI::BGCOLOR()}) ;
print &P4CGI::end_table() ;
}
# Submits per user
print
"
Submits by user in $FSPC
",
&P4CGI::start_table("width=90%"),
&P4CGI::table_row({-type=>"th",
-text => "User",
-width => "20%",
-align => "right"},
{-text => "Submits",
-type=>"th",
-width => "10%"},
{-text => " ",
-bgcolor=>&P4CGI::BGCOLOR()}),
&P4CGI::end_table() ;
# Get users
my @listOfUsers = sort { uc($a) cmp uc ($b) } map { /^(\S+).*> \((.+)\) .*$/ ; $1 ; } @users ;
my %userCvt = map { /^(\S+).*> \((.+)\) .*$/ ; ($1,$2) ; } @users ;
my $u ;
$max = 0 ;
foreach $u (sort {$userSubStat{$b} <=> $userSubStat{$a} ; } keys %userSubStat) {
my $n = $userSubStat{$u} ;
$max = $n if $max == 0 ;
my $w = int((65.0 * $n)/$max) ;
if($w == 0) { $w = 1 ; } ;
if(exists $userCvt{$u}) {
my $fullUser = $userCvt{$u} ;
$u = &P4CGI::ahref(-url => "userView.cgi",
"USER=$u",
$fullUser) ;
}
else {
$u = "Old user: $u"
}
print
&P4CGI::start_table("colums=4 width=90% cellspacing=0"),
&P4CGI::table_row({-text => "$u",
-width => "20%",
-align => "right"},
{-text => $n==0?"-":"$n",
-align => "center",
-width => "10%"},
{-text => " ",
-bgcolor => $n!=0?"blue":&P4CGI::BGCOLOR(),
-width => "$w\%"},
{-text => " ",
-bgcolor=>&P4CGI::BGCOLOR()}) ;
print &P4CGI::end_table() ;
}
print &P4CGI::end_page() ;
#
# That's all folks
#