home *** CD-ROM | disk | FTP | other *** search
- Program AMORT2;
-
- {$V-,N-,E- }
-
- (*
- This program uses the DMX unit to generate an amortization schedule.
- It was recently updated for multiple mortgages and on-line help.
-
- Two DMX objects are used in this unit:
-
- The SelectWindow object uses a five-record editor to input
- the financial parameters Year, Month, Amount, Rate, Years, and
- Payment to calculate and compare five different loans schedules.
- SELECTOR uses this object-type.
-
- The AmortWindow object is a descendant of DMXviewer, so as to
- scroll through the table without allowing changes. The DataAt
- virtual function is modified to calculate each record as it
- needs to be displayed. This may be slow on an 8088 CPU, but
- the advantage to this method is that the entire table does not need
- to be kept in memory.
- AMORT uses this object-type.
-
- The on-line help also makes use of DMX and object-oriented programming.
- This is accomplished in the file DMX_LIST.PAS.
-
- This program is meant only as a demonstration for various uses of
- the DMX objects.
-
- This program is designed for MONTHLY payments only. BI-WEEKLY mortgages
- have a radically different schedule --although you may certainly modify
- this program to accommodate week numbers instead of month names.
-
- *)
-
-
- uses Dos, Crt, DMX2, DMX_list;
-
-
- type AmortRec = record
- Year : word;
- MonthName : string [12];
- Principal : real;
- Interest : real;
- Balance : real;
- end;
-
- SelectRec = record
- Year,Month : word;
- Principal : real;
- Interest : real;
- Years : word;
- Payment : real;
- end;
-
- SelectWindow = object (DMXwindow)
- Info : array [0..4] of SelectRec;
- procedure PickIt;
- procedure ZeroizeRecord (var Data );
- virtual;
- procedure EvaluateField (RecNum : longint;
- CellNum,Line : word);
- virtual;
- end;
-
- AmortWindow = object (DMXviewer)
- linedata : AmortRec;
- Total : real;
- Rate : real;
- Payment : real;
- Years : word;
- Periods : word;
- FirstMonth : word;
- FirstYear : word;
- LastPayment : word;
- LastTotal : real;
-
- procedure Amortize (prin,interest :real; ys,y,m :word);
- function DataAt (recnum : longint) : pointer;
- virtual;
- end;
-
-
- const maintitle = ' year month principal interest balance ';
- baseformat = ' WWWW │ ____________ ║($R,RRR,RRR.RR)│($R,RRR,RRR.RR)║($RR,RRR,RRR.RR)';
-
- spectitle = ' year month amount rate years payment ';
- specformat = ' WWWW | WW ║ $rr,rrr,rrr.rr ║ %rr.rr | WW ║ $rrr,rrr.rr ';
-
- cr = #13;
- Esc = #27;
- F1 = ';';
- F9 = 'C';
-
- Months : array [0..11] of string [12] =
- ('January ',
- 'February ',
- 'March ',
- 'April ',
- 'May ',
- 'June ',
- 'July ',
- 'August ',
- 'September',
- 'October ',
- 'November ',
- 'December ');
-
-
-
- var Key,ext : char;
- DOScolors : word; { original colors }
-
- SELECTOR : SelectWindow; { selector object }
- AMORT : AmortWindow; { viewer object }
-
-
- { ─────────────────────────────────────────────────────────────────────── }
-
-
- function Radical (number,exponent : real) : real;
- { returns the value of number raised to the power of exponent }
- begin
- Radical := exp (Ln (abs (number)) * abs (exponent))
- end;
-
-
- { ─────────────────────────────────────────────────────────────────────── }
-
-
- function AmortPMT (prin,interest,term : real) : real;
- { amount of the periodic payment on the loan }
- begin
- AmortPMT := prin * (interest / (1 - (1 / (Radical (1 + interest,term)))));
- end;
-
-
- { ─────────────────────────────────────────────────────────────────────── }
-
-
- function AmortPRIN (pmt,interest,term : real) : real;
- { amount of the loan }
- begin
- AmortPRIN := (pmt * (1 - (1 / (Radical (1 + interest,term))))) / interest;
- end;
-
-
- { ─────────────────────────────────────────────────────────────────────── }
-
-
- function AmortWindow.DataAt (recnum : longint) : pointer;
- { The original descendant of this method returns a pointer }
- { to where the record would be stored in memory. }
- { This virtual method pretends to retrieve the next record }
- { by calculating the record contents in LINEDATA. }
- { The function then returns a pointer to LINEDATA. }
- { RECNUM is actually the payment number, minus zero. }
- var i,j : word;
- begin
- With linedata do
- begin
- If LastPayment <> recnum then
- begin
- If LastPayment > recnum then
- begin
- LastPayment := 0;
- LastTotal := Total;
- end
- else
- Inc (LastPayment);
- For i := LastPayment to recnum do
- begin
- Interest := Rate * LastTotal;
- Principal := Payment - Interest;
- LastTotal := LastTotal - Principal;
- If recnum = pred (recordlimit) then
- Balance := 0.0
- else
- Balance := LastTotal;
- end;
- LastPayment := recnum;
- end;
- Year := ((recnum + FirstMonth) div 12) + FirstYear;
- MonthName := Months [(recnum + FirstMonth) mod 12];
- end;
-
- DataAt := addr (linedata);
- end;
-
-
- { ─────────────────────────────────────────────────────────────────────── }
-
-
- procedure AmortWindow.Amortize (prin,interest : real; ys,y,m : word);
- { This method initializes the amortization variables, and then runs EditData. }
- var void : byte;
- begin
- FirstYear := y;
- FirstMonth := m;
-
- Total := prin;
- Rate := interest / 100 / 12;
- Years := ys;
- Periods := Years * 12;
- LastPayment := 32000;
-
- Payment := AmortPMT (Total,Rate,Periods);
-
- Window (6,2,75,24);
- WindBorder (LightCyan);
-
- TextAttr := bordercolor;
- ClrScr;
- GotoXY (2,23);
- write ('F1 Help Your monthly payment is: $', Payment:1:2);
- GotoXY (62,23);
- write ('ESC Exit');
- ClrPosition; { reset current record pointer }
- OpenBuffer (void, sizeof (AmortRec) * Periods);
-
- Repeat
- EditData (void, Key,ext, [Esc],[F1]);
- If ext = F1 then
- ViewHelpWindow ('AMORT.HLP', 'B', 11,20,20,61, LightRed,$70);
- Until (ext <> F1);
- end;
-
-
- { ─────────────────────────────────────────────────────────────────────── }
-
-
- procedure SelectWindow.ZeroizeRecord (var Data );
- begin
- { Do nothing, and ignore the ^Y command. }
- end;
-
-
- { ─────────────────────────────────────────────────────────────────────── }
-
-
- procedure SelectWindow.EvaluateField (RecNum : longint; CellNum,Line : word);
- begin
- With Info [RecNum] do
- begin
- If Year = 0 then Year := 1990;
- If (Month < 1) or (Month > 12) then Month := 1;
- If Principal < 10 then Principal := 10.0;
- If Interest <= 0 then Interest := 10.0;
- If Years < 2 then Years := 2;
-
- If (CellNum in [3..5]) or (Payment = 0.0) then
- Payment := AmortPMT (Principal, (Interest / 100 / 12), Years * 12)
- else
- If CellNum = 6 then
- Principal := AmortPRIN (Payment, (Interest / 100 / 12), Years * 12);
-
- DisplayRecord (Info [RecNum], Line);
- end;
- end;
-
-
- { ─────────────────────────────────────────────────────────────────────── }
-
-
- procedure SelectWindow.PickIt;
- var i : word;
- begin
- showzeroes := True; { make any zero amounts visible }
- For i := 0 to 4 do
- begin
- With Info [i] do
- begin
- Year := 1990;
- Month := 1;
- Principal := 10000.00;
- Interest := 10;
- Years := 30;
- Payment := AmortPMT (Principal, (Interest / 100 / 12), Years * 12);
- end;
- end;
-
- Repeat
- Window (1,1,80,25);
- TextAttr := Black;
- ClrScr;
-
- Window (10,7,71,15);
- TextAttr := bordercolor;
- WindBorder (Yellow);
- ClrScr;
- GotoXY (3,9);
- write ('F1 Help F9 Amortize ESC Exit');
-
- OpenBuffer (Info, sizeof (Info));
- Repeat
- EditData (Info, Key,ext, [Esc],[F1,F9]);
- If ext = F1 then
- ViewHelpWindow ('AMORT.HLP', 'A', 12,30,24,78, LightRed,$70);
- Until (ext <> F1);
-
- If (ext = F9) then With Info [currentrec] do
- begin
- AMORT.Amortize (Principal,Interest, Years,Year, Month - 1);
- Key := #0;
- end;
- Until Key = Esc;
- end; { PickIt }
-
-
- { ─────────────────────────────────────────────────────────────────────── }
-
-
- Begin
- DOScolors := TextAttr; { save the original screen color }
- TextAttr := LightGray;
- ClrScr;
-
- AMORT.Init (maintitle, baseformat, 2,2, $3B,$3F,$70);
- SELECTOR.Init (spectitle, specformat, 2,2, $3E,$3F,$70);
-
- SELECTOR.Pickit;
-
- TextAttr := DOScolors; { close the program in the original colors }
- Window (1,1,80,25);
- ClrScr;
- End.
-