Beefy Boxes and Bandwidth Generously Provided by pair Networks
Just another Perl shrine
 
PerlMonks  

Summarize Orange phone bill

by fundflow (Chaplain)
on Apr 03, 2002 at 09:21 UTC ( [id://156270]=sourcecode: print w/replies, xml ) Need Help??
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
}

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: sourcecode [id://156270]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others taking refuge in the Monastery: (2)
As of 2024-04-19 20:27 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found