#!/usr/bin/perl 
#
# mcalc - mortgage calculator
#         script hacked together from various formulas I found on the net
#         to aid in calculating mortgage values.
#         pmt  - determine your minimum payment based on principal,
#                interest rate, and length of loan
#         intr - determine the total interest paid on a loan based on,
#                principal, interest rate, and your monthly payment
#         rate - determine the interest rate you require for a loan based
#                on principal, your monthly payment, and length of loan
#         amt  - determine the size of the loan you can afford based on 
#                your monthly payment, interest rate, and length of loan
#

my ($bal, $rate, $npmt, $intr, $toint, $bintr, $amt, $R, $years, $pmt, $p, $py, $mo, $yi);

if ( @ARGV < "4" ) {
    print "Usage:\n"
        . "\t$0 pmt  <amount>  <rate> <years> [terms-per-year]\n"
        . "\t$0 intr <amount>  <rate> <pmt>   [terms-per-year]\n"
        . "\t$0 rate <amount>  <pmt>  <years> [terms-per-year]\n"
        . "\t$0 amt  <payment> <rate> <years> [terms-per-year]\n";
    exit;
}

sub getpmt {
    my ($a, $r, $y, $p) = @_;
    return sprintf ("%.2f",($r + ($r / ((1 + $r)**($y * $p) - 1))) * $a);
}

sub getamt {
    my ($v, $r, $y, $p) = @_;
    $a  = $v / ($r + ($r / ((1 + $r)**($y * $p) - 1)));
    return sprintf ("%.2f",$a);
}

$py = 12;
$type = $ARGV[0];
shift @ARGV;
if ($type eq "pmt") {
    ($amt , $R, $years) = @ARGV;
    shift; shift; shift;
    $py = shift if (@ARGV);
    $rate = $R / ($py * 100);
    $pmt  = getpmt($amt, $rate, $years, $py);
} elsif ($type eq "amt") {
    ($pmt , $R, $years) = @ARGV;
    shift; shift; shift;
    $py = shift if (@ARGV);
    $rate = $R / ($py * 100);
    $amt = getamt($pmt, $rate, $years, $py);
    
} elsif ($type eq "rate")  {
    ($amt , $pmt, $years) = @ARGV;
    shift; shift; shift;
    $py = shift if (@ARGV);

    my ($dp, $c, $cpmt, $low, $high);

    $c;
    $R = 100;
    $rate = $R/($py * 100);
    $low  = 1/($py * 100);
    $high = $rate;

    $cpmt  = getpmt($amt, $rate, $years, $py);;
    $dp = abs($pmt - $cpmt);

    while(($dp > .01) && ($c < 1000)) {
        $c++;
        $rate  = ($low + $high) / 2;
        $cpmt  = sprintf("%.2f",getpmt($amt, $rate, $years, $py));
        $dp = abs($pmt - $cpmt);
        if ($cpmt > $pmt) {
            $high = $rate;
        } else {
            $low  = $rate;
        }
#        printf("(%.2f):(%s/%s):(%d):(%d)\n",$cpmt,$low*($py*100),$high*($py*100),$dp,$c);
    }

    $R = sprintf("%2.3f",$rate * ($py*100));
} else { # intr || tbl
    ($amt, $R, $pmt) = @ARGV;
    shift; shift; shift;
    $py = shift if (@ARGV);
    $rate = $R/($py*100);
}

$bal  = $amt;
$npmt = 0;
$intr = 0;
$totint = 0;
$bintr = sprintf("%.2f",($bal * $rate));

while ($bal > 0) {
    $intr = $bal * $rate;
    $totint += $intr;
    if ( $intr > $pmt)  {
        die "Sorry, a payment of $pmt does not even cover the interest $intr\n"
    }
    if ( ($bal + $intr) < $pmt ) {
        $bal = 0;
    } else {
        $bal = $bal + $intr - $pmt;
    }
    $npmt++;
    print "$npmt: $intr\n" if ($d);

    if ($type eq "tbl")  {
        my ($y, $m, $pp);
        $y   = int(($npmt + $mo) / $py); $m = ($mo + $npmt) % $py;
        if (!$m) {
            printf "Year $y : interest paid: \$%5.2f\n", $yi;
            $yi = 0;
        }
        $pp  = $pmt - $intr;
        $p  += $pp;
        $yi += $intr;
        printf "%02d:%02d > \$%05.2f : \$%04.2f : \$%04.2f : \$%04.2f\n",
               $y, $m, $totint, $intr, $p, $pp;
    }
}

$y = $npmt / $py;
print "borrowed:       \$$amt\n";
print "interest:       %$R\n";
print "base interest:  \$$bintr\n";
print "payment:        \$$pmt\n";
print "terms:          $npmt\n";
print "years:          $y\n";
print "per payment:    \$$pmt\n";
print "total interest: \$" . sprintf("%.2f\n",$totint);
