#!/usr/bin/perl -w use strict; use XML::Simple; use Data::Dumper; use Getopt::Std; # Figure out which ADSL connection is best. # Paul Fenwick # 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}} (keys %compare))[0..$top-1]) { print join("\t",$compare{$plan}{EFYC},$compare{$plan}{EYC},$plan),"\n"; print map { "\t\t$_\n"; } @{$compare{$plan}{features}}; } __END__