http://www.perlmonks.org?node_id=127376

G'day everyone,

I'm in the process of changing bandwidth providers, and rather than figuring out the best people to go with by hand, I collected a bunch of data and dropped them into XML format. Being the geek I am, I then wrote an analysis tool to determine various cost estimates involved with the different providers and to do some comparisons.

The code isn't beautiful, it had features hacked into it as I required them, but even so others might find it useful. It certainly made the job of weeding through many many plans a lot nicer.

If you're in Australia, it comes with a free XML file containing all the ADSL providers I could find information for, and which serviced Victoria (most of them are national). You can find this file here. You'll probably want to look at this anyway if you wish to adapt this to suit providers in your own area.

The code is below and should be considered in the public domain. Feel free to use and modify as you see fit. :)

Cheers,
Paul

#!/usr/bin/perl -w use strict; use XML::Simple; use Data::Dumper; use Getopt::Std; # Figure out which ADSL connection is best. # Paul Fenwick <pjf@cpan.org> # November 2001 # # This program is in the public domain. # # Usage: analyse.pl [-b] [-v] [-s min_speed] [-f providerfile.xml] # [monthly_mb_usage] [top_n_plans] # # -b - Business plans only # -v - Verbose, show all calculated costs. # -s - Set minimum downlink speed. # # Abbreviations used: # # EMC - Estimated monthly cost # EYC - Estimated yearly cost # EFYC - Estimated first yearly cost my %opt = (v => 0, f => "./providers.xml", b => 0, s=>0); getopts('bvfs:',\%opt); # Bandwidth usage. my $usage = shift || 500; # Top N providers to show. my $top = shift || 5; my $xs = XML::Simple->new(); my $providers = $xs->XMLin($opt{f}, forcearray=>[qw/feature plan/]); my %compare = (); $providers = $providers->{provider}; foreach my $provider_name (sort keys %$providers) { my $provider = $providers->{$provider_name}; print "\n$provider_name\n" if $opt{v}; PLAN: foreach my $plan_name (keys %{$provider->{plan}}) { next if ($plan_name eq "null"); my $plan = $provider->{plan}{$plan_name}; # Skip any plan that doesn't meet out minimum speed. # A speed of 0 in the XML is considered to be uncapped, # and hence "fast enough". my $downlink = $plan->{speed}{downlink} || $provider->{speed}{downlink} || 0; next if ($downlink and $downlink < $opt{s}); # Skip any plan that mentions residential in the # name if we've been asked for business plans only. if ($opt{b}) { foreach (@{$plan->{feature}}) { next PLAN if /residential/i; } } # Figure out some basic costs. my $setup = $plan->{setup}{fee} || $provider->{setup}{fee}; my $excess = $usage - $plan->{monthly}{download}; ($excess < 0) and ($excess = 0); my $monthly = $plan->{monthly}{fee} + ($excess/100) * ($plan->{bandwidth}{fee}|| $provider->{bandwidth}{fee}||0); # Calculate various costs, record features, and insert into # our comparison hash for later sorting. my $ckey = "$provider_name/$plan_name"; $compare{$ckey}{EFYC} = $monthly*12+$setup; $compare{$ckey}{EYC} = $monthly*12; $compare{$ckey}{features} = [@{$provider->{feature}||[]}, @{$plan->{feature}||[]}]; # If we're in verbose mode, print out the calculated # costs. next unless $opt{v}; print "\t$plan_name\n"; print "\t\tSetup: $setup\n"; print "\t\tEMC: $monthly\n"; print "\t\tEYC: ",$compare{$ckey}{EYC},"\n"; print "\t\tEFYC: ",$compare{$ckey}{EFYC},"\n"; } } # Print the final summary of the top N providers with features, sorted # by estimated yearly cost. print "EFYC\tEYC\tProvider/Plan\n","-"x75,"\n"; $top = keys %compare if ($top > keys %compare); foreach my $plan ((sort {$compare{$a}{EYC} <=> $compare{$b}{EYC}} (key +s %compare))[0..$top-1]) { print join("\t",$compare{$plan}{EFYC},$compare{$plan}{EYC},$plan), +"\n"; print map { "\t\t$_\n"; } @{$compare{$plan}{features}}; } __END__