CGI/Perl Guide | Learning Center | Forums | Advertise | Login
Site Search: in

  Main Index MAIN
INDEX
Search Posts SEARCH
POSTS
Who's Online WHO'S
ONLINE
Log in LOG
IN

Home: Perl Programming Help: Intermediate: Re: [Zhris] Postage cost calculation: Edit Log



miller
User

Jun 20, 2011, 5:44 PM


Views: 4302
Re: [Zhris] Postage cost calculation

The following is meant to be a proof of concept, and not a finished product.

Basically, I would suggest that you remove the need for a special markup language from your script entirely. It needless complicates the code and makes it much harder to use in my opinion. Take advantage of the fact that you know perl and code your more complicated equations in perl as well.

I still left the below with the configuration info in the __DATA__ block, but that's not strictly necessary either. You could just as easily hardcode the config data directly in a hash that would remove the need for parsing.


Code
#! /usr/bin/perl 

use CGI::Carp qw(fatalsToBrowser warningsToBrowser);
use POSIX qw(ceil);

use strict;
use warnings;

print "Content-Type: text/plain\n\n";
warningsToBrowser(1);

###########################################################

my $weight = 800;

my %postage = Postage($weight);

while (my ($location, $cost_ref) = each %postage) {
print "$location\n";
print "\t@$_\n" for @$cost_ref;
}

###########################################################

our %POSTAGE;
INIT {
local $/ = "\n\n"; # Paragraph mode

while (<DATA>) {
chomp;

# Comments begin with #
my ($service, @rates) = grep {!/^#/} split "\n";

# Eval rates
for (@rates) {
$_ = [split "\t"];
$_->[1] = eval $_->[1];
die "$service - $@" if $@;
}

$POSTAGE{$service} = \@rates;
}
}

sub Postage {
my $weight = shift;
die "Invalid weight" unless $weight < 1_000_000_000;

my %postage;

for my $service (sort keys %POSTAGE) {
# The Last Max
my $max = $POSTAGE{$service}[-1][0];

# Subdivide Package according to max weight
my @weights = $weight;
while ($max && $weights[-1] > $max) {
unshift @weights, $max;
$weights[-1] -= $max;
}

for my $w (@weights) {
for my $rate (@{$POSTAGE{$service}}) {
next if $rate->[0] && $w > $rate->[0];
push @{$postage{$service}}, [$w, sprintf "%.2f", $rate->[1]($w)];
last;
}
}
}

return %postage;
}

###########################################################

# Each section is __DATA__ is labelled by a destination
# and then by max weight and the sub that determines the cost.
# If no max weight is specified, then treat as infinate.

__DATA__
UK & Europe
sub { 0.00 }

USA
200 sub { 2.00 }
sub { my $w = shift; 2.00 + 1.00 * ceil(($w-200)/100) }

Australia & New Zealand
200 sub { 2.00 }
2200 sub { my $w = shift; 2.00 * (1 + 1 / 1.1) ** ceil(($w - 200) / 200) }

Other
200 sub { 2.00 }
sub { my $w = shift; 2.00 + 1.00 * ceil(($w - 200) / 200) }

Test
100 sub { 1.00 }
200 sub { 1.00 + 0.99 }
300 sub { 1.00 + 0.99 + 0.80 }


- Miller


(This post was edited by miller on Jun 20, 2011, 5:45 PM)
Attachments: postage.pl (2.07 KB)


Edit Log:
Post edited by miller (User) on Jun 20, 2011, 5:45 PM


Search for (options) Powered by Gossamer Forum v.1.2.0

Web Applications & Managed Hosting Powered by Gossamer Threads
Visit our Mailing List Archives