补齐缺失函数,完成一个 Bank Account Management System
.
![Bank Account Management
System](https://upload.wikimedia.org/wikipedia/commons/thumb/e/e6/Ledger.png/200px-
Ledger.png)
Introduction
In this assignment, the fictitious Amazing Banking Corporation (ABC) has asked
you to write software for their bank account management system. You will use
Python to automate tracking financial records of their clients.
This handout explains the problem you are to solve, and the tasks you need to
complete for the assignment. Please read it carefully.
Goals of this Assignment
- Write function bodies using dictionaries and file reading.
- Write code to mutate lists and dictionaries.
- Use top down design to break a problem down into subtasks and implement helper functions to complete those tasks.
- Write tests to check whether a function is correct.
Files to Download
Please download the Assignment 3 filesLinks to an external site. and extract
the zip archive.
Starter code
- banking_functions.py
This file contains some of the headers for the functions you will need to
write for this assignment, and a few completed function docstrings. You will
start development here, using the Function Design Recipe process to implement
each required function. The functions in this file can call each other, and
several of them will also be called by the main program (client_program.py).
You can, and should, write some helper functions in this file that are called
by your required functions. - test_open_savings_account.py and test_get_financial_range_to_clients.py
We are providing the beginning of two unit test files,
test_open_savings_account.py and test_get_financial_range_to_clients.py. These
files will contain your unit tests for the open_savings_account and
get_financial_range_to_clients functions, respectively, that are described
below. - Data: client_data_1.txt and client_data_2.txt
The client_data_*.txt files contain a small amount data for (fictitious)
clients. . These files are sample data, and you should not modify these files.
You may want to create your own data files to supplement these file for
testing. See the next section for instructions on how to interpret this data. - Main Program: client_program.py
The file contains a program that loads some data and then calls some functions
that you will implement in banking_functions.py. You do not need to modify
this file. After you have implemented all of your banking_functions.py
functions, you can run this program to interactively test your code using
different profiles. - Checker: a3_checker.py
We have provided a checker program that you should use to check your code. See
belowLinks to an external site. for more information about a3_checker.py.
Background
This assignment will depend on some financial terminology and formulas which
are summarized here for your reference. The definitions are given solely in
the context of the assignment, and are not meant to be wholly representative
of the usage of the terminology.
- Balance: The amount of money present in the user’s account. We will consider only non-negative account balances (i.e. zero or greater) for all chequing and savings accounts.
- Interest: The rate of return on a bank balance. In this assignment, we will refer to this as a percentage value.
- Compound period: The interval at which the interest rate is calculated on the bank balances. We will consider all interest rates to be stated and compounded per annum.
- Present Value (PV): The value of money at the current time.
- Future Value (FV): The future value that the money will hold at a later time, based on the present value and compound interest.
The (simplified) formula to find FV, given on an interest rate of i %
compounded annually for n years is given as: FV = PV ((1 + i/100) * n)
Constants
You may refer back to A1 for a detailed description of the purpose and usage
of constants. We have provided the following constants in the starter code for
you to use in your solutions. Read on to see how they should be used in your
code. Note that you may not need to use all the constants provided.
Constants provided in the starter code
Data Format
The information for clients in the bank’s database is stored in a file. Your
program will need to read the data from the file and process it.
The file contains 0 or more clients. Each client’s information has the
following format:
- 1 line containing the client’s name.
- 1 line containing the client’s social insurance number (SIN).
- 3 lines for each bank account the client has (the user can have 0 or more bank accounts).
- 1 line for the bank account type (and number, if the account is a savings account). If the client has one or more accounts open, the first bank account in the file is always a chequing account, and any subsequent accounts (if any) are savings accounts.
- 1 line for the bank account balance (always 0 or greater).
- 1 line for the interest rate (per annum, as a percentage value) for the bank account.
The functions that you write later in this assignment will allow clients to
open loan accounts with a negative balance, but these loan accounts will never
be present in the files you will read in to your program.
Your Tasks
You are required to:
- write 12 required functions
- write unittests for two of the required functions (open_savings_account and get_financial_range_to_clients)
Data Structures
A “client to accounts” dictionary (Dict[Tuple[str, int], List[List[float]]) is
our data structure for representing the mapping of clients to their bank
accounts.
- key: a tuple of the client’s name (str) and SIN (int) in the format: (FirstName LastName, SIN)
- value: a two-element list of lists; the sublists with index BALANCES and INTEREST_RATES contain the bank balances and their respective interest rates, respectively. The default value for BALANCES is 0, and the default value for INTEREST_RATES is 1. A loan account, if it exists for the client, will appear at the end of the lists (i.e. indexes the sublists with -1). The number of loan accounts for any client will never exceed one (i.e. it is impossible for a client to have more than one loan account). Chequings and savings accounts always have a balance 0 or greater. Loan accounts always have a balance less than 0.
- example: this dictionary represents the “client to accounts” data when it is read from client_data_1.txt: {(‘Karla Hurst’, 770898021): [[768.0, 2070.0], [0.92, 1.5]], (‘Pamela Dickson’, 971875372): [[36358866.0, 5395448.0, 23045442.0, 14316660.0, 45068981.0, 4438330.0, 16260321.0, 7491204.0, 23330669.0], [2.3, 2.35, 2.25, 2.35, 2.05, 2.1, 2.45, 2.4, 2.0]], (‘Roland Lozano’, 853887123): [[1585.0, 1170.0, 1401.0, 3673.0], [0.63, 0.05, 0.34, 0.92]]}
Karla Hurst has a SIN of 770 898 021, and bank balances of $768.00 and
$2070.00 in the Chequing Account and Savings Account 1, respectively. The
Chequing Account has an interest rate of 0.92% per annum, and Savings Account
1 has an interest rate of 1.5% per annum.
A “client to total balance” dictionary (Dict[Tuple[str, int], float]) is our
data structure for representing the mapping of clients to the total balance
across all bank accounts they have open. - key: a tuple of the client’s name (str) and SIN (int) in the format: (FirstName LastName, SIN)
- value: the total balance the client has across all accounts(float)
- example: this dictionary represents the “client to total balance” dictionary created from the data in client_data_1.txt {(‘Karla Hurst’, 770898021): 2838.0, (‘Pamela Dickson’, 971875372): 175705921.0, (‘Roland Lozano’, 853887123): 7829.0}
Required Testing (unittest)
Write (and submit) unittest test files for functions open_savings_account and
get_financial_range_to_clients. These tests should be implemented in the
appropriately named starter files.
We will evaluate the completeness of your test files by running them against
flawed implementations we have written to see how many errors you catch. Avoid
redundant tests. The goal is to catch all of our errors without extra,
unnecessary tests.
Your unittest testfiles should stand alone: they should require no additional
files (like a clients file). Instead, you should define appropriate test
values in the file, such as a dictionary that might be generated from reading
a clients file, to use for your tests. You may assume that the folder that
contains your unittest test files also contains a banking_functions.py file.
Recall that floating-point numbers are approximations of real numbers.
Required Functions
This section contains a table with detailed descriptions of the 12 functions
that you must complete. You’ll need to add a second example to the docstrings
for each function in the starter code.
We provided 3 helper function in the starter code that you may use. You should
follow the approach we’ve been using on large problems recently and write
additional helper functions to break these high-level tasks down. Each helper
function must have a clear purpose. Each helper function must have a complete
docstring produced by following the Function Design Recipe. You should test
your helper functions to make sure they work.
Function name: (Parameter types) -> Return type | Full Description
(paraphrase to get a proper docstring description)
—|—
load_financial_data: (TextIO) -> Dict[Tuple[str, int], List[List[float]]] |
The parameter refers to a file that is open for reading. The data in the file
is in the Data FormatLinks to an external site. described above.
get_num_clients: (Dict[Tuple[str, int], List[List[float]]]) -> int | The
parameter represents a “client to accounts” dictionary. This function must
return the total number of clients present in the “client to accounts”
dictionary.
validate_identity: (Dict[Tuple[str, int], List[List[float]]], str, int) ->
bool | The first parameter represents a “client to accounts” dictionary, and
the second and third parameters represent a name and SIN, respectively.
get_num_accounts: (Dict[Tuple[str, int], List[List[float]]], Tuple[str, int])
-> int | The first parameter represents a “client to accounts” dictionary,
and the second parameter represents a valid client in the dictionary.
get_account_balance: (Dict[Tuple[str, int], List[List[float]]], Tuple[str,
int], int) -> float | The first parameter represents a “client to accounts”
dictionary, the second parameter represents a valid client, and the third
parameter represents the account number.
open_savings_account: (Dict[Tuple[str, int], List[List[float]]], Tuple[str,
int], float, float) -> None | The first parameter represents a “client to
accounts” dictionary, the second parameter represents a valid client, and the
third and fourth parameters represent the balance and interest rate to open
the new account with, respectively.
get_client_to_total_balance: (Dict[Tuple[str, int], List[List[float]]]) ->
Dict[Tuple[str, int], float] | The parameter represents a “client to
accounts” dictionary. This function should return a dictionary with the
following format.
update_balance: (Dict[Tuple[str, int], List[List[float]]], Tuple[str, int],
int, float, int) -> None | The first parameter represents a “client to
accounts” dictionary, the second parameter represents a valid client, the
third parameter represents an account number (chequing, savings, or loan), the
fourth parameter represents an amount to change the balance by, and the fifth
parameter represents a transaction code which is either WITHDRAW_CODE or
DEPOSIT_CODE indicated in the “constants” section.
get_loan_status: (Dict[Tuple[str, int], List[List[float]]], Dict[Tuple[str,
int], float], Tuple[str, int], float) -> bool | The first parameter
represents a “client to accounts” dictionary, the second parameter represents
a “client to total balance” dictionary, the third parameter represents a valid
client, and the fourth parameter represents a positive loan amount the client
is seeking approval for.
get_financial_range_to_clients: (Dict[Tuple[str, int], float],
List[Tuple[float]])-> Dict[Tuple[float, float], List[Tuple[str, int]]] | The
first parameter represents a “client to total balance” dictionary and the
second parameter represents a list of financial ranges. The financial ranges
are given within the list as tuples, as ordered pairs of float values.
get_fv_from_accounts: (List[float], List[float], int) -> float | The first
parameter represents a list of account balances, the second parameter
represents a list of interest rates, and the third parameter represents a time
in years.
time_to_client_goal: (Dict[Tuple[str, int], List[List[float]]], Tuple[str,
int], float)-> int | The first parameter represents a “client to accounts”
dictionary, the second parameter represents a valid client, and the third
parameter represents a dollar amount financial “goal” the client wishes to
reach.
A3 Checker
We are providing a checker module (a3_checker.py) that tests two things:
- whether your code follows the Python Style GuidelinesLinks to an external site., and
- whether your functions are named correctly, have the correct number of parameters, and return the correct types.
To run the checker, open a3_checker.py and run it. Note: the checker file
should be in the same directory as your banking_functions.py, as provided in
the starter code zip file. Be sure to scroll up to the top and read all
messages.
If the checker passes for both style and types: - Your code follows the style guidelines.
- Your function names, number of parameters, and return types match the assignment specification. This does not mean that your code works correctly in all situations. We will run a different set of tests on your code once you hand it in, so be sure to thoroughly test your code yourself before submitting.
If the checker fails, carefully read the message provided: - It may have failed because your code did not follow the style guidelines. Review the error description(s) and fix the code style.
- It may have failed because:
- you are missing one or more function,
- one or more of your functions is misnamed,
- one or more of your functions has the incorrect number or type of parameters, or
- one of more of your function return types does not match the assignment specification.
Read the error message to identify the problematic function, review the
function specification in the handout, and fix your code.
Running the checker program on Markus
In addition to running the checker program on your own computer, run the
checker on MarkUs as well. You will be able to run the checker program on
MarkUs twice per 24 hours. This can help to identify issues such as uploading
the incorrect file.
First, submit your work on MarkUs. Next, click on the “Automated Testing” tab
and then click on “Run Tests”. Wait for a minute or so, then refresh the
webpage. Once the tests have finished running, you’ll see results for the
Style Checker and Type Checker components of the checker program (see both the
Automated Testing tab and results files under the Submissions tab). Note that
these are not actually marks – just the checker results. If there are errors,
edit your code, run the checker program again on your own machine to check
that the problems are resolved, resubmit your assignment on MarkUs, and (if
time permits) after the 24 hour period has elapsed, rerun the checker on
MarkUs.
Testing your Code
It is strongly recommended that you test each function as soon as you write
it. As usual, follow the Function Design Recipe (we’ve provided the function
name and types for you) to implement your code. Once you’ve implemented a
function, run it against the examples in your docstrings and the unit tests
you’ve defined.
Additional requirements
- Do not call print, input, or open, except within the if name == ‘__main__‘ block.
- Do not use any break or continue statements.
- Do not modify or add to the import statements provided in the starter code.
- Do not add any code outside of a function definition.
- Do not mutate objects unless specified.
Marking
These are the aspects of your work that will be marked for Assignment 3:
- Correctness: Your functions should perform as specified. Correctness, as measured by our tests, will count for the largest single portion of your marks. Once your assignment is submitted, we will run additional tests, not provided in the checker. Passing the checker does not mean that your code will earn full marks for correctness.
- Testing: We will run the unittests that you submit on a series of flawed (incorrect) implementations we have written. Your testing mark will depend on how many of the flawed implementations your unittests catch, whether they successfully pass a working (correct) implementation, and whether your test files contain redundant (unnecessary) tests.
- Coding style:
- Make sure that you follow the Python style guidelinesLinks to an external site. that we have introduced and the Python coding conventions that we have been using throughout the semester. Although we don’t provide an exhaustive list of style rules, the checker tests for style are complete, so if your code passes the checker, then it will earn full marks for coding style with two exceptions: docstrings and use of helper functions may be evaluated separately.
- Your program should be broken down into functions, both to avoid repetitive code and to make the program easier to read. If a function body is more than about 20 statements long, introduce helper functions to do some of the work – even if they will only be called once.
- All functions, including helper functions, should have complete docstrings including preconditions when you think they are necessary.
- Also, your variable names and names of your helper functions should be meaningful. Your code should be as simple and clear as possible.
No Remark Requests
No remark requests will be accepted. A syntax error could result in a grade of
0 on the assignment. Before the deadline, you are responsible for running your
code and the checker program to identify and resolve any errors that will
prevent our tests from running.
What to Hand In
The very last thing you do before submitting should be to run the checker
program one last time.
Otherwise, you could make a small error in your final changes before
submitting that causes your code to receive zero for correctness.
Submit banking_functions.py, test_open_savings_account.py, and
test_get_financial_range_to_clients.py on MarkUs. Remember that spelling of
filenames, including case, counts: your file must be named exactly as above.