Category: | Utility Scripts |
Author/Contact Info | /msg fundflow |
Description: | Parse the phone bill given by Orange cellphone company (www.orange.net)
It shows the information per phone number (number of calls and text messages, and the cost/minute). I use it to check which of my friends costs me the most :) I'm now in the UK and this is the bill they give here, but this might work in other countries. In case there's a problem with other countries, let me know. |
#!/usr/bin/perl -w # # Summarize Orange's phone bill. # use strict; # This optional file holds known phone numbers. Each line contains a # "name: phone" pair (i.e. separated by a colon) my $phonefile = "../phones"; # The international phone country prefix: my $country_prefix = "44"; my %numbers; if (-f $phonefile) { print "Reading the phone list from $phonefile\n"; open(F, "<$phonefile") or die "Can't read phone file"; while(<F>) { next if /^$/; my ($name, $number) = split(/:/); #m/([^:]+):(.+)/; die ("Parse error in $phonefile line $.") unless defined($name) an +d defined($number); next unless defined($name); $number =~ s/\s//g; $numbers{$number} = $name; } } $numbers{''} = "Unknown"; # Add variations on the numbers: foreach (sort keys %numbers) { my ($k)=$_; s/ //g; $numbers{$_} = $numbers{$k}; s/^0(?=[1-9])/$country_prefix/; $numbers{$_} = $numbers{$k}; } my %costs; my %calls; my %texts; my %totals; my %durations; my $count =0; my $tot=0; my $thedate; # File format: # Date Day Time Number Place called Call Service plan Duration Cost # 19/01/02 Sat 00:07 07957543534 Other Mobile Network talk 0:00:06 0.0 +10 # 08:02 02076345454 Inner London talk talk 0:13:28 0.000 while (<>) { next unless /^Date\s* Day\s* Time\s* Number/ .. eof(); # Skip the +header my ($date,$day,$time,$number,$place,$class,$service,$duration,$cos +t) = m<((?:\d\d\/\d\d\/\d\d)*) # Possible date \s*(\w*) # Possible day of week \s*(\d\d:\d\d) # Time of call \s*([\d+]*) # Number #\s*((?:(?:\w+\s)+|\(\w+\))+) # Place called \s*(.*(?=talk|text|data)) # Place called \s*(talk|text|data) # Call class \s*(\w*) # Possible Service Plan \s*(\d+:\d\d:\d\d) # Duration \s*([\d.]+) # Cost >x; if (defined($cost)) { #print "$count : $time $number $place\n"; $count++; $tot += $cost; if (defined($numbers{$number})) { $number = $numbers{$number} }; $costs{$number}+= $cost; if($class eq 'talk') { $calls{$number}++; } elsif ($class eq 'text' || $class eq 'data') { $texts{$number}++; } else { print "Unknown class '$class' for number '$number'\n"; } my ($h,$m,$s) = $duration=~m/(\d+):(\d+):(\d+)/; $durations{$number} += $s + 60*($m + 60*$h); } if(/^\s*(Sub total|Total)\s+£(.*)/ ) { # (correctness check) if (abs($2 - $tot)>0.01 and $#ARGV==1) { print "$#ARGV\n"; print join "\n", @ARGV; printf("\nERROR: Line $., %5.2f != %5.2f by %f\n", $2, $tot, abs($2-$tot)); exit; } } } my $bill = 0; my $airtime = 0; for (sort keys %costs) { $calls{$_}=0 unless defined($calls{$_}); $texts{$_}=0 unless defined($texts{$_}); my $per = $durations{$_}>0 ? 100*$costs{$_}/$durations{$_} : 0; printf("%-20s : %10s %3dt %3dc £%5.2f %5.2f ¢/s\n", $_, &timeprint($durations{$_}), $texts{$_}, $calls{$_}, $costs{$_}, $per); $bill += $costs{$_}; $airtime += $durations{$_}; } printf("Total $count calls (%s), %d numbers, $bill pounds\n", timepri +nt($airtime), scalar keys(%costs)); sub timeprint { my $t = shift; my $o; if ($t < 60) { $o = "$t"."s"; } elsif ($t<60*60) { $o = sprintf "%2dm%2ds", int($t/60), $t%60; } else { my $r = $t%3600; $o = sprintf "%2dh%2dm%2ds", ($t-$r)/3600, int($r/60), $r%60; } $o } |
Back to
Code Catacombs