All pastes #42160 Raw Edit

Unnamed

public text v1 · immutable
#42160 ·published 2006-02-20 00:47 UTC
rendered paste body
#!/usr/bin/perl

use warnings;
use strict;

# constants for prices
our $GB_PRICE            = 3.95;
our $BRUSCHETTA_PRICE    = 4.95;
our $HUMMUS_PRICE        = 5.95;
our $SALAD_PRICE         = 1.00;
our $SPAGHETTI_PRICE     = 8.95;
our $LASAGNA_PRICE       = 9.95;
our $PIZZA_PRICE         = 10.95;
our $SOFT_DRINK_PRICE    = 2.00;
our $BEER_PRICE          = 3.00;
our $LIQUOR_PRICE        = 3.50;
our $WINE_PRICE          = 4.00;
our $GST                 = 0.07;
our $PST                 = 0.08;
our $LST                 = 0.10;

# the first argument of this function is a filename
# the second argument is a reference to a hash of variables
# all variables in that hash will be written out to a file
# the format of the file is as follows
# SCALARS: s:name:value
# ARRAYS : a:name:value1:value2:value3
# HASHES : h:name:key1:value1:key2:value2
# newlines are the seperators! there is no terminating character
sub write_hash {
    my $filename = shift @_;
    my $vars = shift @_;
   
    open(FILE, ">$filename");
    
    foreach my $key (keys %{$vars}) {
        # this one is just for convienence
        my $i = \( $vars->{$key} );

        # this is a switch statement
        # make a reference to $vars->{$key} and pass it to ref
        for (ref $i) {
            # if it is scalar, ref will return SCALAR...
            if (/SCALAR/) {
                print FILE "s:$key:" . $vars->{$key} . "\n";
            }
            # ...otherwise it returns an empty string
            # which means it is a hash or an array
            else {
                my $j = $vars->{$key};
                my $type = ref $j;
                # if it is an array, print out each element
                if ($type eq "ARRAY") {
                    print FILE "a:$key";
                    for my $element ( @{$j} ) {
                        print FILE ":$element";
                    }
                    print FILE "\n";
                }
                # likewise for a hash, print out the key/value pairs
                elsif ($type eq "HASH") {
                    print FILE "h:$key";
                    for my $k ( keys %{$j} ) {
                        print FILE ":$k:" . $j->{$k};
                    }
                    print FILE "\n";
                }
            }
        }
    }
   
    close(FILE);
        
    return;
}

# the first argument of this function is a filename
# function returns a hash
# see the above function for the format of the file
sub read_hash {
    my $filename = shift @_;
    my %vars;
    # these are used when extracting data from the fields
    my ($type, $name, $value, $key);

    open(FILE, "$filename");
    my @data = <FILE>;
    close(FILE);

    # iterate through the array 
    foreach my $line (@data) {
        # retrieve the type
        $type = substr($line, 0, 1);
        for ($type) {
            # if it's a scalar...
            if (/s/) {
                (undef,$name,$value) = split(/:/, $line, 3);
                chomp $value;
                $vars{$name} = $value;
            }
            # if it's an array...
            if (/a/) {
                # stores the elements of the array, temporarily
                my ($values, @elements);
                (undef,$name,$values) = split(/:/, $line, 3);
                chomp $values;
                @elements = split(/:/, $values);

                # now we've got the values split up
                # time to write things to the hash
                $vars{$name} = (\@elements);
            }
            # if it's a hash...
            if (/h/) {
                # $k and $v are for key and value
                my ($k, $v, $pairs, %hash);
                (undef,$name,$pairs) = split(/:/, $line, 3);
                chomp $pairs;

                # extract all the pairs and put them in the hash
                while (defined $pairs) {
                    ($k,$v,$pairs) = split(/:/, $pairs, 3);
                    $hash{$k} = $v;
                }

                # now shove a hash ref into our big hash!
                $vars{$name} = \%hash;
            }
        }
    }
    
    return %vars;
}

sub write_start {
    # get the error message, if there is one
    # undefined if there is no errmsg
    my $errmsg = shift(@_);

    print "Content-Type: text/html";
    print "\n\n";
    print '<?xml version="1.0" encoding="UTF-8"?>' . "\n";
    print '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" ';
    print '"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">' . "\n";
    print '<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">' . "\n";
    print '<head>' . "\n";
    print '<link rel="StyleSheet" href="css/assign1.css" type="text/css" ';
    print 'media="screen" title="mystyle" />' . "\n";
    print '<title>Restaurant Bill Calculator</title>' . "\n";
    print '</head>' . "\n";
    print '<body>' . "\n";
    print '<form action="assign1.cgi" method="get" name="patrons">' . "\n";
    if (defined $errmsg) {
        print '<div class="error">' . $errmsg . '</div>' . "\n";
        print '<br />' . "\n";
    }
    print '<table>' . "\n";
    print '<tr>' . "\n";
    print '<td class="label">Number of Patrons: </td>';
    print '<td class="value">' . "\n";
    print '<input type="text" name="patrons" size="6" maxlength="10" />' . "\n";
    print '</td>' . "\n";
    print '</tr><tr>' . "\n";
    print '<td align="center" colspan="2">' . "\n";
    print '<input type="submit" name="go" value="submit" />' . "\n";
    print '</td>' . "\n";
    print '</tr>' . "\n";
    print '</table>' . "\n";
    print '<input type="hidden" name="file" value="patron" />' . "\n";
    print '</form>' . "\n";
    print '</body>' . "\n";
    print '</html>' . "\n";
    
    return;
}

sub write_appetizer {
    # get the session id...
    my $session_id = shift @_;

    # this will have an error message if one was passed, and will be
    # undefined otherwise
    my $errmsg = shift @_;
    
    # ...and write the page
    print "Content-Type: text/html";
    print "\n\n";
    print '<?xml version="1.0" encoding="UTF-8"?>' . "\n";
    print '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" ';
    print '"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">' . "\n";
    print '<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">' . "\n";
    print '<head>' . "\n";
    print '<link rel="StyleSheet" href="css/assign1.css" type="text/css" ';
    print 'media="screen" title="mystyle" />' . "\n";
    print '<title>Restaurant Bill Calculator - Appetizers</title>' . "\n";
    print '</head>' . "\n";
    print '<body>' . "\n";
    print '<form action="assign1.cgi" method="get" name="appetizer">' . "\n";
    if (defined $errmsg) {
        print '<div class="error">' . $errmsg . '</div>' . "\n";
    }
    print '<table style="form">' . "\n";
    print '<tr>' . "\n";
    print '<td class="label">Appetizers: </td>' . "\n";
    print '<td class="value">' . "\n";
    print '<select name="appetizer">' . "\n";
    print '<option value="garlic bread">Garlic Bread ($3.95)</option>' . "\n";
    print '<option value="bruschetta">Brushetta ($4.95)</option>' . "\n";
    print '<option value="hummus">Humous & Tabouleh ($5.95)</option>' . "\n";
    print '</select>' . "\n";
    print '</tr><tr>' . "\n";
    print '<td class="label">Quantity: </td>' . "\n";
    print '<td class="value">';
    print '<input type="text" name="qty" size="6" maxlength="2" />' . "\n";
    print '</td>' . "\n";
    print '</tr><tr>' . "\n";
    print '<td class="label">Add more? </td>' . "\n";
    print '<td class="value"><input type="checkbox" name="more" /></td>' ."\n";
    print '</tr><tr>' . "\n";
    print '<td align="center" colspan="2">';
    print '<input type="submit" name="go" value="Submit" />';
    print '</td>' . "\n";
    print '</table>' . "\n";
    print '<input type="hidden" name="file" value="appetizer">' . "\n";
    print '<input type="hidden" name="session_id" value="' . $session_id
                                                           . '">' . "\n";
    print '</form>' . "\n";
    print '</body>' . "\n";
    print '</html>' . "\n";

    return;
}

sub write_entree {
    # retrieve the session id...
    my $session_id = shift @_;
    # and the error message
    my $errmsg = shift @_;

    # ...and write the page
    print "Content-Type: text/html";
    print "\n\n";
    print '<?xml version="1.0" encoding="UTF-8"?>' . "\n";
    print '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" ';
    print '"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">' . "\n";
    print '<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">' . "\n";
    print '<head>' . "\n";
    print '<link rel="StyleSheet" href="css/assign1.css" type="text/css" ';
    print 'media="screen" title="mystyle" />' . "\n";
    print '<title>Restaurant Bill Calculator - Entrees</title>' . "\n";
    print '</head>' . "\n";
    print '<body>' . "\n";
    print '<form action="assign1.cgi" method="get" name="entrees">' . "\n";
    if (defined $errmsg) {
        print '<div class="error">' . $errmsg . '</div>' . "\n";
    }
    print '<table style="form">' . "\n";
    print '<tr>' . "\n";
    print '<td class="label">Entrees: </td>' . "\n";
    print '<td class="value">' . "\n";
    print '<select name="entree">' . "\n";
    print '<option value="spaghetti">Spaghetti ($8.95)</option>' . "\n";
    print '<option value="lasagna">Lasanga ($9.95)</option>' . "\n";
    print '<option value="pizza">Pizza ($10.95)</option>' . "\n";
    print '</select>' . "\n";
    print '</tr><tr>' . "\n";
    print '<td class="label">Add a Salad? </td>' . "\n";
    print '<td class="value"><input type="checkbox" name="salad" /></td>'."\n";
    print '</tr><tr>' . "\n";
    print '<td class="label">Quantity: </td>' . "\n";
    print '<td class="value">';
    print '<input type="text" name="qty" size="6" maxlength="2" />' . "\n";
    print '</td>' . "\n";
    print '</tr><tr>' . "\n";
    print '<td class="label">Add more? </td>' . "\n";
    print '<td class="value"><input type="checkbox" name="more" /></td>' ."\n";
    print '</tr><tr>' . "\n";
    print '<td align="center" colspan="2">';
    print '<input type="submit" name="go" value="Submit" />';
    print '</td>' . "\n";
    print '</table>' . "\n";
    print '<input type="hidden" name="file" value="entree">' . "\n";
    print '<input type="hidden" name="session_id" value="' . $session_id
                                                           . '">' . "\n";
    print '</form>' . "\n";
    print '</body>' . "\n";
    print '</html>' . "\n";

    return;
}

sub write_drinks {
    # get the session id...
    my $session_id = shift @_;

    # this will have an error message if one was passed, and will be
    # undefined otherwise
    my $errmsg = shift @_;
    
    # ...and write the page
    print "Content-Type: text/html";
    print "\n\n";
    print '<?xml version="1.0" encoding="UTF-8"?>' . "\n";
    print '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" ';
    print '"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">' . "\n";
    print '<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">' . "\n";
    print '<head>' . "\n";
    print '<link rel="StyleSheet" href="css/assign1.css" type="text/css" ';
    print 'media="screen" title="mystyle" />' . "\n";
    print '<title>Restaurant Bill Calculator - Drinks</title>' . "\n";
    print '</head>' . "\n";
    print '<body>' . "\n";
    print '<form action="assign1.cgi" method="get" name="drinks">' . "\n";
    if (defined $errmsg) {
        print '<div class="error">' . $errmsg . '</div>' . "\n";
    }
    print '<table style="form">' . "\n";
    print '<tr>' . "\n";
    print '<td class="label">Drinks: </td>' . "\n";
    print '<td class="value">' . "\n";
    print '<select name="drink">' . "\n";
    print '<option value="soft drink">Soft Drink ($2)</option>' . "\n";
    print '<option value="beer">Beer ($3)</option>' . "\n";
    print '<option value="liquor">Liquor ($3.50)</option>' . "\n";
    print '<option value="wine">Wine ($4)</option>' . "\n";
    print '</select>' . "\n";
    print '</tr><tr>' . "\n";
    print '<td class="label">Quantity: </td>' . "\n";
    print '<td class="value">';
    print '<input type="text" name="qty" size="6" maxlength="2" />' . "\n";
    print '</td>' . "\n";
    print '</tr><tr>' . "\n";
    print '<td class="label">Add more? </td>' . "\n";
    print '<td class="value"><input type="checkbox" name="more" /></td>' ."\n";
    print '</tr><tr>' . "\n";
    print '<td align="center" colspan="2">';
    print '<input type="submit" name="go" value="Submit" />';
    print '</td>' . "\n";
    print '</table>' . "\n";
    print '<input type="hidden" name="file" value="drink">' . "\n";
    print '<input type="hidden" name="session_id" value="' . $session_id
                                                           . '">' . "\n";
    print '</form>' . "\n";
    print '</body>' . "\n";
    print '</html>' . "\n";

    return;
}

sub write_subtotal {
    # get the session id...
    my $session_id = shift @_;
    # and the variables we'll need
    my $vars = shift @_;
    my $appetizers  = $vars->{'appetizers'};
    my $entrees     = $vars->{'entrees'};
    my $drinks      = $vars->{'drinks'};

    # ...and write the page
    print "Content-Type: text/html";
    print "\n\n";
    print '<?xml version="1.0" encoding="UTF-8"?>' . "\n";
    print '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" ';
    print '"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">' . "\n";
    print '<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">' . "\n";
    print '<head>' . "\n";
    print '<link rel=StyleSheet" href="css/assign1.css" type="text/css" ';
    print 'media="screen" title="mystyle" />' . "\n";
    print '<title>Restaurant Bill Calculator - Subtotal</title>' . "\n";
    print '</head>' . "\n";
    print '<body>' . "\n";
    print '<form action="assign1.cgi" method="get" name="subtotal">' . "\n";
    print '<table class="form">' . "\n";
    print '<tr>' . "\n";
    print '<th>Item</th>' . "\n";
    print '<th>Total #</th>' . "\n";
    print '<th>Price Per</th>' . "\n";
    print '<th>Total Charge</th>' . "\n";
    print '</tr><tr>' . "\n";
    # now for the fun part
    print '<td>Garlic Bread</td>' . "\n";
    print '<td>' . $appetizers->{'garlic bread'} . '</td>' . "\n";
    print '<td>$';
    printf "%.2lf", $GB_PRICE;
    print '</td>' . "\n";
    print '<td>$';
    printf "%.2lf", $appetizers->{'garlic bread'} * $GB_PRICE;
    print '</td>' . "\n";
    print '</tr><tr>' . "\n";
    print '<td>Bruschetta</td>' . "\n";
    print '<td>' . $appetizers->{'bruschetta'} . '</td>' . "\n";
    print '<td>$';
    printf "%.2lf", $BRUSCHETTA_PRICE;
    print '</td>' . "\n";
    print '<td>$';
    printf "%.2lf", $appetizers->{'bruschetta'} * $BRUSCHETTA_PRICE;
    print '</td>' . "\n";
    print '</tr><tr>' . "\n";
    print '<td>Humous & Tabouleh</td>' . "\n";
    print '<td>' . $appetizers->{'hummus'} . '</td>' . "\n";
    print '<td>$';
    printf "%.2lf", $HUMMUS_PRICE;
    print '</td>' . "\n";
    print '<td>$';
    printf "%.2lf", $appetizers->{'hummus'} * $HUMMUS_PRICE;
    print '</td>' . "\n";
    print '</tr><tr>' . "\n";
    print '<td>Spaghetti</td>' . "\n";
    print '<td>' . $entrees->{'spaghetti'} . '</td>' . "\n";
    print '<td>$';
    printf "%.2lf", $SPAGHETTI_PRICE;
    print '</td>' . "\n";
    print '<td>$';
    printf "%.2lf", $entrees->{'spaghetti'} * $SPAGHETTI_PRICE;
    print '</td>' . "\n";
    print '</tr><tr>' . "\n";
    print '<td>Lasagna</td>' . "\n";
    print '<td>' . $entrees->{'lasagna'} . '</td>' . "\n";
    print '<td>$';
    printf "%.2lf", $LASAGNA_PRICE;
    print '</td>' . "\n";
    print '<td>$';
    printf "%.2lf", $entrees->{'lasagna'} * $LASAGNA_PRICE;
    print '</td>' . "\n";
    print '</tr><tr>' . "\n";
    print '<td>Pizza</td>' . "\n";
    print '<td>' . $entrees->{'pizza'} . '</td>' . "\n";
    print '<td>$';
    printf "%.2lf", $PIZZA_PRICE;
    print '</td>' . "\n";
    print '<td>$';
    printf "%.2lf", $entrees->{'pizza'} * $PIZZA_PRICE;
    print '</td>' . "\n";
    print '</tr><tr>' . "\n";
    print '<td>Salad</td>' . "\n";
    print '<td>' . $entrees->{'salad'} . '</td>' . "\n";
    print '<td>$';
    printf "%.2lf", $SALAD_PRICE;
    print '</td>' . "\n";
    print '<td>$';
    printf "%.2lf", $entrees->{'salad'} * $SALAD_PRICE;
    print '</td>' . "\n";
    print '</tr><tr>' . "\n";
    print '<td>Soft Drink</td>' . "\n";
    print '<td>' . $drinks->{'soft drink'} . '</td>' . "\n";
    print '<td>$';
    printf "%.2lf", $SOFT_DRINK_PRICE;
    print '</td>' . "\n";
    print '<td>$';
    printf "%.2lf", $drinks->{'soft drink'} * $SOFT_DRINK_PRICE;
    print '</td>' . "\n";
    print '</tr><tr>' . "\n";
    print '<td>Beer</td>' . "\n";
    print '<td>' . $drinks->{'beer'} . '</td>' . "\n";
    print '<td>$';
    printf "%.2lf", $BEER_PRICE;
    print '</td>' . "\n";
    print '<td>$';
    printf "%.2lf", $drinks->{'beer'} * $BEER_PRICE;
    print '</td>' . "\n";
    print '</tr><tr>' . "\n";
    print '<td>Liquor</td>' . "\n";
    print '<td>' . $drinks->{'liquor'} . '</td>' . "\n";
    print '<td>$';
    printf "%.2lf", $LIQUOR_PRICE;
    print '</td>' . "\n";
    print '<td>$';
    printf "%.2lf", $drinks->{'liquor'} * $LIQUOR_PRICE;
    print '</td>' . "\n";
    print '</tr><tr>' . "\n";
    print '<td>Wine</td>' . "\n";
    print '<td>' . $drinks->{'wine'} . '</td>' . "\n";
    print '<td>$';
    printf "%.2lf", $WINE_PRICE;
    print '</td>' . "\n";
    print '<td>$';
    printf "%.2lf", $drinks->{'wine'} * $WINE_PRICE;
    print '</td>' . "\n";
    print '</tr><tr>' . "\n";
    print '<td style="font-weight: bold">Sub-total</td>' . "\n";
    print '<td></td><td></td><td>$' . "\n";
    printf "%.2lf", $vars->{'subtotal'};
    print '</td>' . "\n";
    print '</tr><tr>' . "\n";
    print '<td style="font-weight: bold">GST (7%)</td>' . "\n";
    print '<td></td><td></td><td>$' . "\n";
    printf "%.2lf", $vars->{'subtotal'} * $GST;
    print '</td>' . "\n";
    print '</tr><tr>' . "\n";
    print '<td style="font-weight: bold">PST (8%)</td>' . "\n";
    print '<td></td><td></td><td>$' . "\n";
    printf "%.2lf", $vars->{'food_subtotal'} * $PST;
    print '</td>' . "\n";
    print '</tr><tr>' . "\n";
    print '<td style="font-weight: bold">Liquor Tax (10%)</td>' . "\n";
    print '<td></td><td></td><td>$' . "\n";
    printf "%.2lf", $vars->{'liquor_subtotal'} * $LST;
    print '</td>' . "\n";
    print '</tr><tr>' . "\n";
    print '<td><br /></td>' . "\n";
    print '</tr><tr>' . "\n";
    print '<td style="font-weight: bold">TOTAL BILL</td>' . "\n";
    print '<td></td><td></td><td>$' . "\n";
    printf "%.2lf", $vars->{'total'};
    print '</td>' . "\n";
    print '</tr>' . "\n";
    print '</table>' . "\n";
    print '<br />' . "\n";
    print '<form action="assign1.cgi" method="get" name="subtotal">' . "\n";
    print '<span>Please select a Gratuity: ' . "\n";
    print '<select name="tip">' . "\n";
    print '<option value="10">10%</option>' . "\n";
    print '<option value="15">15%</option>' . "\n";
    print '<option value="20">20%</option>' . "\n";
    print '</select>' . "\n";
    print '<input type="submit" name="go" value="Submit" />';
    print '<input type="hidden" name="file" value="subtotal">' . "\n";
    print '<input type="hidden" name="session_id" value="' . $session_id
                                                           . '">' . "\n";
    print '</form>' . "\n";
    print '</body>' . "\n";
    print '</html>' . "\n";
}

sub write_total {
    # get the data
    my $vars = shift @_;

    # get the amount of the tip
    my $tip_amt = ('.' . $vars->{'tip'}) * $vars->{'subtotal'};
    
    # write the page
    print "Content-Type: text/html";
    print "\n\n";
    print '<?xml version="1.0" encoding="UTF-8"?>' . "\n";
    print '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" ';
    print '"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">' . "\n";
    print '<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">' . "\n";
    print '<head>' . "\n";
    print '<link rel=StyleSheet" href="css/assign1.css" type="text/css" ';
    print 'media="screen" title="mystyle" />' . "\n";
    print '<title>Restaurant Bill Calculator - Grand Total</title>' . "\n";
    print '</head>' . "\n";
    print '<body>' . "\n";
    print '<h1>Grand Total:</h1>' . "\n";
    print '<p>The final total of the bill is $';
    printf "%.2lf", $vars->{'total'};
    print '</p><p>';
    print 'With a gratuity of ' . $vars->{'tip'} . '%';
    print ' of the sub-total ($';
    printf "%.2lf", $tip_amt;
    print ')';
    print ' the grand total is: $';
    printf "%.2lf", $vars->{'total'} + $tip_amt;
    print '.';
    print '</p><p>';
    print 'There are ' . $vars->{'patrons'} . ' patrons. Each person owes $';
    printf "%.2lf", ($vars->{'total'} + $tip_amt) / $vars->{'patrons'};
    print '.';
    print '</p>';
    print '</body>';
    print '</html>';
}
            
# returns the number of patrons, and the errorcode
sub process_patron {
    # put the query string into something we can work with
    my $qs = $_[0];
    my $err = 0;
    if (! $qs->{'patrons'} || length $qs->{'patrons'} > 2) {
        $err = 1;
    }
    
    return $qs->{'patrons'}, $err;
}

sub process_appetizer {
    # again with the query string
    my $qs = shift @_;
    # more contains 'on' if it was checked
    my $more = ($qs->{'more'}) ? 1 : 0;
    
    # fill %ret with the return values
    my %ret = (
       appetizer    => $qs->{'appetizer'},
       qty          => $qs->{'qty'},
       more         => $more,
    );
   
    return %ret;
}
   
sub process_entree {
    # get the QS
    my $qs = shift @_;

    # contains 'on' if it was checked
    my $more  = ($qs->{'more'})  ? 1 : 0;
    my $salad = ($qs->{'salad'}) ? 1 : 0;

    # fill ret with the appropriate values
    my %ret = (
       entree   => $qs->{'entree'},
       qty      => $qs->{'qty'},
       more     => $more,
       salad    => $salad
    );

    return %ret;
}
   
sub process_drinks {
    # get the query string
    my $qs = shift @_;

    # more contains 'on' if it was checked
    my $more = ($qs->{'more'}) ? 1 : 0;

    # fill %ret with the return values
    my %ret = (
       drink    => $qs->{'drink'},
       qty      => $qs->{'qty'},
       more     => $more
    );

    return %ret;
}
 
sub main {
    my %qs= split(/[;&=]/,$ENV{QUERY_STRING});
    foreach (values(%qs)) {
        s/(%[0-9a-f]{2}|\+)/$1 eq '+'?' ': chr(hex(substr($1,1)))/gei;
    }

    # initialize a few variables    
    my $page = $qs{'file'};
    my $err = 0;
    my $filename = "";
    my $errmsg = "";

    # if its the patron page, generate a new session id
    # otherwise, get the session id
    my $session_id;
    my %vars;
    if (! defined $qs{'session_id'} ) {
        $session_id = int(rand(100)) . time();
    }
    else {
        $session_id = $qs{'session_id'};
        $filename = ".meal-" . $session_id;
        %vars = read_hash($filename);
    }

    # this is the big important variable. it holds all the information
    # from the forms.

    # this is a switch statement
    for ($page) {
        if (/patron/) {
            ($vars{'patrons'}, $err) = process_patron(\%qs);
            if (! $err) {
                write_appetizer($session_id);
            }
            else {
                $errmsg = "Number of patrons must be between 1 and 99";
                # needs error message
                write_start($errmsg);
            }
        }
        elsif (/appetizer/) {
            # validate the appetizer page
            my %ret = process_appetizer(\%qs);
            my $amt = 0;

            # if this isn't the first time through the appetizers page
            # get the total number of appetizers ordered already...
            if (defined $vars{'appetizers'}) {
                foreach my $key (keys %{ $vars{'appetizers'} }) {
                    $amt += $vars{'appetizers'}->{$key};
                }
            }
            # ...and add the number of appetizers ordered on this iteration
            $amt += $ret{'qty'};

            # if there are more appetizers than people, give an error...
            if ($amt > $vars{'patrons'}) {
                $errmsg = "Total quantity of appetizers must be between"
                           . " 0 and " . $vars{'patrons'};
                write_appetizer($session_id, $errmsg);
            }
            # ...otherwise, save the data and display the appropriate page
            else {
                # these are just for syntactical simplicity
                my $key = $ret{'appetizer'};
                my $qty = $ret{'qty'};
                # if the appetizers reference isn't there...
                if (! defined $vars{'appetizers'}) {
                    # ...create it...
                    $vars{'appetizers'} = {};
                    # ...and initialize it
                    $vars{'appetizers'}->{'garlic bread'}   = 0;
                    $vars{'appetizers'}->{'bruschetta'}      = 0;
                    $vars{'appetizers'}->{'hummus'}         = 0;
                }

                # save the appetizer data
                $vars{'appetizers'}->{$key} += $qty;
                
                # if they want to add more appetizers...
                if ($ret{'more'} == 1) {
                    # ...write out the appetizer page
                    write_appetizer($session_id);
                }
                # otherwise...
                else {
                    # write out the entree page
                    write_entree($session_id);
                }
            }
        }
        elsif (/entree/) {
            # validate the entree data
            my %ret = process_entree(\%qs);
            my $amt = 0;
            
            # if this isn't the first time through the entree page
            # total up the amount of entrees ordered so far...
            if (defined $vars{'entrees'}) {
                foreach my $key (keys %{ $vars{'entrees'} }) {
                    $amt += $vars{'entrees'}->{$key};
                }
            }
            # take off the salads..we don't count them
            $amt -= $vars{'entrees'}->{'salad'};
            # ...and add the amount ordered in this iteration
            $amt += $ret{'qty'};
            print STDERR "amt: " . $amt . "\n";

            # if the amount of entrees is not the same as number of patrons
            # and they are not going to add more...
            if ($amt != $vars{'patrons'} && $ret{'more'} == 0) {
                # give 'em a nice error message and send 'em back.
                $errmsg = "Total number of entrees must be "
                          . $vars{'patrons'};
                write_entree($session_id, $errmsg);
            }
            else {
                # for simplicity
                my $key = $ret{'entree'};
                my $qty = $ret{'qty'};

                # if the entree hash in not defined,
                if (! defined $vars{'entrees'}) {
                    # declare it...
                    $vars{'entrees'} = {};
                    # and initialize it
                    $vars{'entrees'}->{'salad'}     = 0;
                    $vars{'entrees'}->{'spaghetti'} = 0;
                    $vars{'entrees'}->{'lasagna'}   = 0;
                    $vars{'entrees'}->{'pizza'}     = 0;
                }

                # save the data
                $vars{'entrees'}->{$key} += $qty;
                $vars{'entrees'}->{'salad'} += $qty * $ret{'salad'};
                
                # if they want to add more, write out the entree page
                if ($ret{'more'} == 1) {
                    write_entree($session_id);
                }
                # otherwise, write out the drinks page
                else {
                    write_drinks($session_id);
                }
            }
        }
        elsif (/drink/) {
            # validate the data
            my %ret = process_drinks(\%qs);
            my $amt = 0;

            # if this isn't the first time through the drinks page
            # get the total number of drinks ordered already....
            if (defined $vars{'drinks'}) {
                foreach my $key (keys %{ $vars{'drinks'} }) {
                    $amt += $vars{'drinks'}->{$key};
                }
            }
            # ...and add the number of drinks ordered on this iteration
            $amt += $ret{'qty'};

            # drinks must be between number of patrons and number of patrons*3
            # otherwise, give an error
            if (($amt < $vars{'patrons'} || $amt > ($vars{'patrons'} * 3))
               && $ret{'more'} == 0 ) {
                $errmsg = "Total quantity of drinks must be between "
                        . $vars{'patrons'} . " and " . $vars{'patrons'} * 3;
                write_drinks($session_id, $errmsg);
            }
            # otherwise, save the data and display the appropriate page
            else {
                # just for convienence
                my $key = $ret{'drink'};
                my $qty = $ret{'qty'};
                # if the drinks reference isn't there...
                if (! defined $vars{'drinks'}) {
                    # ...create it...
                    $vars{'drinks'} = {};
                    # ...and initialize it...
                    $vars{'drinks'}->{'soft drink'} = 0;
                    $vars{'drinks'}->{'beer'}       = 0;
                    $vars{'drinks'}->{'liquor'}     = 0;
                    $vars{'drinks'}->{'wine'}       = 0;
                }

                # save the drink data
                $vars{'drinks'}->{$key} += $qty;
                # we're nearing the end, so make up the total
                $vars{'subtotal'} 
                  = $vars{'appetizers'}->{'garlic bread'} * $GB_PRICE
                  + $vars{'appetizers'}->{'bruschetta'}   * $BRUSCHETTA_PRICE
                  + $vars{'appetizers'}->{'hummus'}       * $HUMMUS_PRICE
                  + $vars{'entrees'}->{'spaghetti'}       * $SPAGHETTI_PRICE
                  + $vars{'entrees'}->{'lasagna'}         * $LASAGNA_PRICE
                  + $vars{'entrees'}->{'pizza'}           * $PIZZA_PRICE
                  + $vars{'entrees'}->{'salad'}           * $SALAD_PRICE
                  + $vars{'drinks'}->{'soft drink'}       * $SOFT_DRINK_PRICE
                  + $vars{'drinks'}->{'beer'}             * $BEER_PRICE
                  + $vars{'drinks'}->{'liquor'}           * $LIQUOR_PRICE
                  + $vars{'drinks'}->{'wine'}             * $WINE_PRICE;
    
                $vars{'food_subtotal'} = $vars{'subtotal'}
                     - $vars{'drinks'}->{'beer'} * $BEER_PRICE
                     - $vars{'drinks'}->{'liquor'} * $LIQUOR_PRICE
                     - $vars{'drinks'}->{'wine'} * $WINE_PRICE;

                $vars{'liquor_subtotal'} = $vars{'drinks'}->{'beer'}
                     * $BEER_PRICE
                     + $vars{'drinks'}->{'liquor'} * $LIQUOR_PRICE
                     + $vars{'drinks'}->{'wine'} * $WINE_PRICE;

                $vars{'total'} = $vars{'subtotal'}
                     + $vars{'subtotal'} * $GST
                     + $vars{'food_subtotal'} * $PST
                     + $vars{'liquor_subtotal'} * $LST;

                # if they want to add more...
                if ($ret{'more'} == 1) {
                    write_drinks($session_id);
                }
                # otherwise..
                else {
                    write_subtotal($session_id, \%vars);
                }
            }
        }
        elsif (/subtotal/) {
            $vars{'tip'} = $qs{'tip'};
            write_total(\%vars);
        }
    }

    # write the vars out to the file, whee.
    $filename = ".meal-" . $session_id;
    write_hash($filename, \%vars);
}

main();