
miller
User
Jun 20, 2011, 5:44 PM
Views: 3688
|
|
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.
#! /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)
|