program Bank (input,output);
(* FILE: Bank.p
  AUTHOR: K.BECKER
  DATE:   16/08/02
  PURPOSE: Program to emulate a simple ATM
*)
const MAX	   = 5;
   isNew	   = true;
   notNew	   =  false;
   
type    acctType   = array [1..MAX] of real;
        activeType = array [1..MAX] of boolean;

var
   acct	(* bank accounts *) 
            : acctType;
   acctOpen			    
   : activeType;
   trans   (* amount of transaction *)
            : real;
   ans,	(* y/n answer to questions *)
   what    (* user's option *)
            : char;
   more,	(* loop control to allow more than one value per run *)
   dep	(* true if transaction is a deposit *)
            : boolean;

   i        :integer;

(***************************************************************************)
procedure chooseAccount(isNew : boolean;  var A :  integer);
var  which : char;
   
begin
   A := -1;
   while ((A < 0) or( A > 5)) do
   begin
      
      writeln('Select Account : ');
      writeln   ('s == savings ');
      writeln   ('c == chequing ');
      writeln   ('v == visa ');
      writeln   ('4 == extra account 1 ');
      writeln   ('5 == extra account 2 ');
      writeln   ('q == return to main menu ');
      writeln;
      write     ('please choose an option: ');
      readln (which);
      
      case which of
	's' : A := 1;
	'c' : A := 2;
	'v' : A := 3;
	'4' : A := 4;
	'5' : A := 5;
	'q' : A := 0;
	otherwise  begin
	   writeln;
	   writeln('Sorry, unrecognized request.');
	   writeln('please try again, or type ''q'' to quit.');
	end;
      end; (* case *) { case }

      if (A > 0) and (A <= MAX)
	 then begin
	    if (not(acctOpen[A]))and(not isNew)
	       then begin
		  writeln('Sorry, Account Closed');
		  writeln;
		  A := -1;
	       end;
	 end;
   end; (* while *)
end; { chooseAccount }
   
(***************************************************************************)
procedure doDeposit(var acct : acctType );
var   amount :real;
   from	     :  integer;
begin			     
   writeln('Deposit TO:');
   chooseAccount(notNew,from);
   if ((from > 0) and (from <= MAX))
      then begin		    
	 write('Amount to deposit : ');
	 readln( amount);
	 if (amount < 0.0)
	    then begin
	       writeln('Sorry, invalid amount.');
	    end
	    else begin
	       acct[from] := acct[from] + amount;
	       writeln('Transaction successful, thank you.');
	    end;
      end;
end; { doDeposit }

(***************************************************************************)
procedure doWithdrawal(var acct: acctType );
var   amount : real;
   from	     :  integer;
begin			     
   writeln('Withdraw FROM:');
   chooseAccount(notNew,from);
   if (from > 0) and (from <= MAX)
      then begin
	 write('Amount to withdraw : ');
	 readln( amount);
	 if (amount < 0.0)
	    then begin
	       writeln('Sorry, invalid amount.');
	    end
	    else if (acct[from] - amount) < -100.00
	       then begin
		  writeln('Sorry, invalid amount.');	    
	       end
	       else begin
		  acct[from] := acct[from] - amount;
		  writeln('Transaction successful, thank you.');
	       end;
      end;
end; { doWithdrawal }

(***************************************************************************)
procedure doTransfer(var acct: acctType );
var   amount : real;
   from, into  :  integer;
begin
   writeln('Transfer FROM:');
   chooseAccount(notNew,from);
   writeln('Transfer TO:');
   chooseAccount(notNew,into);
   
if (from > 0) and (from <= MAX) and
   (into > 0) and (into <= MAX)
   then begin
      write('Amount to transfer : ');
      readln( amount );
      if (amount < 0.0)
	 then begin
	    writeln('Sorry, invalid amount.');
	 end
	 else if (acct[from] - amount) < -100.00
	    then begin
	       writeln('Sorry, invalid amount.');	    
	    end
	    else begin
	       acct[from] := acct[from] - amount;
	       acct[into] := acct[into] + amount;
	       writeln('Transaction successful, thank you.');
	    end;
   end; (* if *)
end; { doTransfer }

(***************************************************************************)
procedure showBalance(var acct : acctType) ;
var i :  integer;
   
begin
   writeln('Your current balance is: ');
   for i := 1 to MAX do
   begin
      if (acctOpen[i])
	 then begin
	    writeln('Acct ',i,': ',acct[i]:10:2);
	    if acct[i] < 0.0
	       then begin
		  writeln;
		  writeln('!!! NOTE: you are overdrawn.');
	       end;
	    writeln;
	 end;
   end;
   writeln;
end; { showBalance }

(***************************************************************************)
procedure openAcct (var acct :  acctType);
var   amount : real;
   from	     :  integer;
begin			     
   writeln('Choose Account:');
   chooseAccount(isNew,from);
   if (from > 0) and (from <= MAX) and (not acctOpen[from])
      then begin
	 acctOpen[from] := true;
	 writeln('New Account Open, thank you.');
	 writeln;
      end;
end; { openAcct }

(***************************************************************************)
procedure closeAcct (var asst :  acctType);
var   amount : real;
   from	     :  integer;
begin			     
   writeln('Choose Account:');
   chooseAccount(notNew,from);
   if (from > 0) and (from <= MAX) and (acctOpen[from])
      then begin
	 if (acct[from] < 0.0)
	    then begin
	       writeln('Overdraft must first be cleared.');
	    end
	    else if (acct[from] > 0.0)
	       then begin
		  writeln('Please transfer funds to another account first.');
	       end
	       else begin
		  acctOpen[from] := false;
		  writeln('Account Closed, thank you.');
		  writeln;
	       end;
      end;
end; { closeAcct }

(***************************************************************************)
begin (* main *)
   (* headers and instructions *)
   writeln ('BECKER''S ATM SERVICE');
   writeln;
   writeln ('Please enter all dollar values as real numbers with no $ signs.');
   writeln;

   (* initialize account to nothing *)
   for i := 0 to MAX do
      acct[i] := 0.0;
   
   (* set up for loop entry *)
   more := true;
   while more do
   begin
      writeln   ('d == deposit ');
      writeln   ('w == withdrawal ');
      writeln   ('b == print balance ');
      writeln   ('t == transfer funds ');
      writeln   ('o == open account ');
      writeln   ('c == close account ');
      writeln   ('q == quit ');
      writeln;
      write     ('please choose an option: ');
      readln (ans);

      case ans of
	'd' : doDeposit(acct);
	'w' : doWithdrawal(acct);
	'b' : showBalance(acct);
	't' : doTransfer(acct);
	'o' : openAcct(acct);
	'c' : closeAcct(acct);
	'q' : more := false;
	otherwise  begin
	               writeln;
		       writeln('Sorry, unrecognized request.');
		       writeln('please try again, or type ''q'' to quit.');
		    end;
      end; (* case *)

   end; (* while more *)

   writeln ('Thank You.');

end.
