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: Postage cost calculation: Edit Log



Zhris
Enthusiast

Jun 2, 2011, 3:23 PM


Views: 4640
Postage cost calculation

Hi everyone,

I was trying to look for some kind of UK (Royal Mail) postage API with no success, then looked for some kind of server side script to handle postage for me (Perl, PHP, ASP etc) also with no success. Therefore I decided I would write my own script from scratch. This also had the benefit of being able to use my own custom rates.

- My main issue is regarding my data, which I have seemed to over complicate, so when it comes to creating 1) an admin feature to update it, 2) an overview, to display in a neatly formatted table the postage rates for each location - I may have difficulty (any idiot must be able to use it). I tried to create the data to be as compact as possible i.e. using a multiplier system where consecutive rates are part of a "pattern".

- Another issue is my use of infinity, whats the point in even entering a system of loops, when the postage cost never changes. Maybe I should try to recognize when it gets to a stage like this, for efficiency purposes.

- Finally, I also have the issue that I have to account for the possibility of a huge weight input, and since theres a size limit (20000g national, 2000g international) I would need to repeat i.e. so orders can be split up into seperate packages. I'm sure I won't have difficulties doing this (maybe use an inner subroutine, or even try out the redo command), but before doing so I wanted some advice in improving my script.

If anyone has done something like this before, or has any advice, could they please help me out a little. Maybe a pointer to a free quality pre-written script. Or just some feedback on my script. By the way, modules are out of the question, since i'm unable to install them onto my web server.

Here is what I have come up with so far, it still needs a little work in its current state (ignore my questionable cost operations, I was just playing around):


Code
#! /usr/bin/perl 
use strict;
use CGI::Carp qw/fatalsToBrowser warningsToBrowser/;
print "content-type: text/plain\n\n";
warningsToBrowser(1);

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

my $weight = "800";

my $postage = Postage($weight);

while (my ($location, $cost) = (each %{$postage})) {
print "$location => $cost\n";
}

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

sub Postage {
my $weight = shift;
die "Invalid weight" unless ($weight < "1000000000");

my $d = '(\d+(\.\d+)?|Inf)';
my %costoperations = (
'=' => sub { $_[1] },
'+' => sub { $_[0] + $_[1] },
'=*' => sub { $_[0] * $_[1] },
'+*' => sub { $_[0] + ($_[0] * $_[1]) },
'=' => sub { $_[0] / $_[1] },
'+' => sub { $_[0] + ($_[0] / $_[1]) }
);
my %postage;

while (<DATA>) {
next if ($_ =~ m/^(\!|\s)/);

my @row = split(/\|/, $_);
my $service = $row[1];
my @rates = split(/\//, $row[2]);

my $totalcost = "0.00";
my $flag = 0;

lastmarker:
foreach my $rate (@rates) {
die "Invalid rate" unless ($rate =~ m/^ $d [>] $d (\=|\+|\=\*|\+\*|\=\|\+\) $d ([*]$d)? $/x);
my ($minweight, $minweightdecimal, $uptoweight, $uptoweightdecimal, $costoperator, $cost, $costdecimal, $multiplierwithoperator, $multiplier, $multiplierdecimal) = ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10);
$multiplier = $multiplier || 1;

for (my $i = 1; $i <= $multiplier; $i++) {
$totalcost = $costoperations{$costoperator}->($totalcost, $cost);

if (($weight >= $minweight) && ($weight <= ($minweight + $uptoweight))) {
$flag = 1;
last lastmarker;
}

$minweight += $uptoweight + 1;
}
}

$postage{$service} = ($flag) ? sprintf("%.2f", $totalcost) : undef;
}

return \%postage;
}

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

__DATA__
|UK & Europe|1>Inf=0.00|
|USA|1>199=2.00/201>199+1.00*Inf|
|Australia & New Zealand|1>199=2.00/201>199+1.1*10|
|Other|1>199=2.00/201>199+1.00*Inf|
|Test|1>99=1.00/101>99+0.90/201>99+0.80|


Thank you,

Chris


(This post was edited by Zhris on Jun 2, 2011, 3:24 PM)


Edit Log:
Post edited by Zhris (Enthusiast) on Jun 2, 2011, 3:24 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