Difference between revisions of "OPS435 Python3 Assignment 1"
(→Create a private repository on github.com under your account by cloning the sample repo) |
|||
(25 intermediate revisions by the same user not shown) | |||
Line 3: | Line 3: | ||
When making back up of data files or log files, it is a very common practice to name the backup directories and/or files based on the date the backup was done. In order to restore or locate the directory/file, we often need to find out the backup date from today's date. | When making back up of data files or log files, it is a very common practice to name the backup directories and/or files based on the date the backup was done. In order to restore or locate the directory/file, we often need to find out the backup date from today's date. | ||
− | The computational task for this assignment is to design an algorithm and write a python script according to your algorithm with appropriate functions. The script should take a date in the " | + | The computational task for this assignment is to design an algorithm and write a python script according to your algorithm with appropriate functions. The script should take a date in the "YYYY-MM-DD" format and the number of days before or after the given date as the command line arguments, calculate and output to the standard output data channel the targeted date which is the number of day before or after the given date in the same format. |
== Coding Standard == | == Coding Standard == | ||
Line 10: | Line 10: | ||
== Command Line Argument to be supported == | == Command Line Argument to be supported == | ||
* Name your python script as a1_[student_id].py, where [student_id] is your Seneca email user name. | * Name your python script as a1_[student_id].py, where [student_id] is your Seneca email user name. | ||
− | * Your python script must support two mandatory command line arguments : (1) any valid date in | + | * Your python script must support two mandatory command line arguments : (1) any valid date in YYYY-MM-DD format, (2) number of days before or after the given date, and one option flag: "--step" |
− | * If there are less or more than two | + | * If there are less or more than two data items provided at the command line, your script should display the correct usage message and exit. |
= Computation Requirements = | = Computation Requirements = | ||
== Algorithm Design == | == Algorithm Design == | ||
− | * Write a step-by-step instructions in English on how to compute a date in " | + | * [https://simple.m.wikipedia.org/wiki/Algorithm Here is an basic introduction to Algorithm] |
+ | * Write a step-by-step instructions in English on how to compute a date in "YYYY-MM-DD" format which is n days before or after a given date also in "YYYY-MM-DD" format. | ||
* While you are working on the step-by-step instructions, note that there are different number of days in each month and some years have 365 days and some years have 366 days. | * While you are working on the step-by-step instructions, note that there are different number of days in each month and some years have 365 days and some years have 366 days. | ||
* You should also do some research to find out when we started using the Calendar in the current form. (This will pose a limit on the validity of your algorithm.) | * You should also do some research to find out when we started using the Calendar in the current form. (This will pose a limit on the validity of your algorithm.) | ||
Line 24: | Line 25: | ||
Based on the algorithm you have designed for this assignment, you should at least have the following three functions defined in your python script (see later section on the purpose of each function) in order to get a passing grade for this assignment: | Based on the algorithm you have designed for this assignment, you should at least have the following three functions defined in your python script (see later section on the purpose of each function) in order to get a passing grade for this assignment: | ||
* dbda() | * dbda() | ||
− | * | + | * after() |
− | * | + | * before() |
You should also create additional functions to improved the re-usability of your python code by adding the following functions to earn the maximum possible mark for this assignment: | You should also create additional functions to improved the re-usability of your python code by adding the following functions to earn the maximum possible mark for this assignment: | ||
* days_in_mon() | * days_in_mon() | ||
Line 33: | Line 34: | ||
== Documentation == | == Documentation == | ||
− | * Please use python's docstring to document your python script (script level documentation) and each of the functions (function level documentation) you created for this assignment. The docstring should | + | * Please use python's docstring to document your python script (script level documentation) and each of the functions (function level documentation) you created for this assignment. The docstring should describe 'what' the function does, not 'how' it does. |
− | * The following shows the docstring that was added to the | + | * The following shows the docstring that was added to the after() function which provides the following information when called with help(after) in the python interactive shell: |
<pre> | <pre> | ||
− | Help on function | + | Help on function after() in module rchan: |
− | + | after(today) -> str | |
− | + | after() takes a valid date string in 'YYYY-MM-DD' format and return a | |
− | date string for the next day in ' | + | date string for the next day in 'YYYY-MM-DD' format. |
− | e.g. | + | e.g. after('2017-12-31') -> '2018-01-01' |
− | + | after('2018-01-31') -> '2018-02-01' | |
− | + | after('2018-02-28') -> '2018-03-01' | |
(END) | (END) | ||
</pre> | </pre> | ||
Line 49: | Line 50: | ||
== Authorship Declaration == | == Authorship Declaration == | ||
All your Python code for this assignment must be placed in a <font color='red'><b><u>single source python file</u></b></font>. Please include the following declaration <b><u>as part of the docstring</u></b> in your Python source code file (replace "Student Name" with your own name): | All your Python code for this assignment must be placed in a <font color='red'><b><u>single source python file</u></b></font>. Please include the following declaration <b><u>as part of the docstring</u></b> in your Python source code file (replace "Student Name" with your own name): | ||
− | <source>OPS435 Assignment 1 - | + | <source>OPS435 Assignment 1 - Winter 2020 |
− | Program: [student_id].py (replace student_id with your Seneca User name) | + | Program: a1_[student_id].py (replace student_id with your Seneca User name) |
Author: "Student Name" | Author: "Student Name" | ||
− | The python code in this file ([Student_id].py) is original work written by | + | The python code in this file (a1_[Student_id].py) is original work written by |
"Student Name". No code in this file is copied from any other source | "Student Name". No code in this file is copied from any other source | ||
except those provided by the course instructor, including any person, | except those provided by the course instructor, including any person, | ||
Line 62: | Line 63: | ||
== Tests and Test results == | == Tests and Test results == | ||
− | You must name your python 3 script as <code>a1_[Student_id].py</code>. The following examples assumes that the student_id is rchan.The script should accept two command line arguments, the first one is the date in " | + | You must name your python 3 script as <code>a1_[Student_id].py</code>. The following examples assumes that the student_id is rchan.The script should accept two command line arguments, the first one is the date in "YYYY-MM-DD" format, and the second one is the number of day from the given date, a positive value indicates the number of days after the given date, and a negative value indicates the number of days before the given date. There is an optional flag called --step which can be provided at the command line that makes the program print out all dates until the target date. If the "YYYY-MM-DD" format is broken, your script should give an appropriate error message. Invalid months (>12) or invalid days of month(different for each month), should be detected and give appropriate error messages. For examples: |
− | * <b><code>python3 a1_rchan.py | + | * <b><code>python3 a1_rchan.py 2019-01-01 1</code></b>, and the output should be<br /> |
− | + | 2019-01-02 | |
− | * <b><code>python3 a1_rchan.py | + | * <b><code>python3 a1_rchan.py 2019-01-01 -1</code></b>, and the output should be<br /> |
− | + | 2018-12-31 | |
− | * <b><code>python3 a1_rchan.py | + | * <b><code>python3 a1_rchan.py 2019-01-01 2</code></b>, and the output should be<br /> |
− | + | 2019-01-03 | |
− | * <b><code>python3 a1_rchan.py --step | + | * <b><code>python3 a1_rchan.py --step 2019-01-01 3</code></b>, and the output should be<br /> |
− | + | 2019-01-02 | |
− | + | 2019-01-03 | |
− | + | 2019-01-04 | |
− | * <b><code>python3 a1_rchan.py | + | * <b><code>python3 a1_rchan.py 2018-07-01 500</code></b>, and the output should be<br /> |
− | + | 2019-11-13 | |
− | * <b><code>python3 a1_rchan.py | + | * <b><code>python3 a1_rchan.py 2018-99-01 2</code></b>, and the output should be<br /> |
Error: wrong month entered | Error: wrong month entered | ||
− | * <b><code>python3 a1_rchan.py | + | * <b><code>python3 a1_rchan.py 2018-01-99 2</code></b>, and the output should be<br /> |
Error: wrong day entered | Error: wrong day entered | ||
* <b><code>python3 a1_rchan.py 2018 2</code></b>, and the output should be<br /> | * <b><code>python3 a1_rchan.py 2018 2</code></b>, and the output should be<br /> | ||
Line 83: | Line 84: | ||
If there is too few or too many command line arguments given, display the proper usage: | If there is too few or too many command line arguments given, display the proper usage: | ||
− | * <code>Usage: a1_rchan.py [--step] | + | * <code>Usage: a1_rchan.py [--step] YYYY-MM-DD +/-n</code> |
== Script structure and sample template == | == Script structure and sample template == | ||
− | Your code should all be in a single python file with at least the functions mentioned above: dbda(), | + | Your code should all be in a single python file with at least the functions mentioned above: dbda(), after(), and before(). To earn the maximum mark, you should also create additional functions into your algorithm, e.g.: leap_year(), days_in_mon, valid_date(), usage(), etc |
The following is a brief description of each function: | The following is a brief description of each function: | ||
− | * The dbda() function should be the main function of your script. The dbda() function will take a date in " | + | * The dbda() function should be the main function of your script. The dbda() function will take a date in "YYYY-MM-DD" format, a positive or negative integer, and return a date either before or after the given date according to the value of the given integer in the same format. Your dbda() function should delegate the actual calculation of the target date to either the after() function or the before() function. |
− | * The | + | * The before() function will take a date in "YYYY-MM-DD" format and return the date of the previous day in the same format. |
− | * The | + | * The after() function will take a date in "YYYY-MM-DD" format and return the date of the next day in the same format. Next paragraph is a sample python code for the after() function. To earn the maximum possible mark for the assignment, you should modify the sample after() function to make use of the days_in_mon() function. |
* The leap_year() function will take a year in "YYYY" format, and return True if the given year is a leap year, otherwise return False. | * The leap_year() function will take a year in "YYYY" format, and return True if the given year is a leap year, otherwise return False. | ||
− | * The valid_date() function will take a date in " | + | * The valid_date() function will take a date in "YYYY-MM-DD" format, and return True if the given date is a valid date, otherwise return False plus an appropriate status message. The valid_date() function should make use of the days_in_mon() function. |
− | * The days_in_mon() function will take a year in "YYYY" format, and return a dictionary object which contains the total number of days in each month | + | * The days_in_mon() function will take a year in "YYYY" format, and return a dictionary object which contains the total number of days in each month for the given year. The days_in_mon() function should make use of the leap_year() function. |
* The usage() function will take no argument and return a string describing the usage of the script. | * The usage() function will take no argument and return a string describing the usage of the script. | ||
<pre> | <pre> | ||
#!/usr/sbin/env python3 | #!/usr/sbin/env python3 | ||
+ | ''' docstring | ||
+ | ''' | ||
import ... | import ... | ||
− | def | + | def after(today): |
.... | .... | ||
return next_day | return next_day | ||
− | def | + | def before(today): |
.... | .... | ||
return previous_day | return previous_day | ||
Line 111: | Line 114: | ||
.... | .... | ||
− | def dbda( | + | def dbda(date,days): |
... | ... | ||
− | setup loop | + | setup loop: |
− | call | + | call after() or before() as appropriate |
return target_day | return target_day | ||
Line 122: | Line 125: | ||
.. call dbda() | .. call dbda() | ||
... | ... | ||
− | output the | + | .. output the result |
</pre> | </pre> | ||
− | === Sample code for the | + | === Sample code for the after() function === |
<pre> | <pre> | ||
− | # Return the date in | + | # Return the date in YYYY-MM-DD after the given day |
# | # | ||
− | def | + | def after(today): |
− | if len(today) != | + | if len(today) != 10: |
− | return ' | + | return '0000-00-00' |
else: | else: | ||
− | year = int( | + | str_year, str_month, str_day = today.split('-') |
− | month = int( | + | year = int(str_year) |
− | day = int( | + | month = int(str_month) |
+ | day = int(str_day) | ||
lyear = year % 4 | lyear = year % 4 | ||
Line 153: | Line 157: | ||
feb_max = 29 # this is a leap year | feb_max = 29 # this is a leap year | ||
− | tmp_day = day + 1 # | + | tmp_day = day + 1 # next day |
mon_max = { 1:31, 2:feb_max, 3:31, 4:30, 5:31, 6:30, 7:31, 8:31, 9:30, 10:31, 11:30, 12:31} | mon_max = { 1:31, 2:feb_max, 3:31, 4:30, 5:31, 6:30, 7:31, 8:31, 9:30, 10:31, 11:30, 12:31} | ||
Line 169: | Line 173: | ||
to_month = tmp_month + 0 | to_month = tmp_month + 0 | ||
− | next_date = str(year)+str(to_month).zfill(2)+str(to_day).zfill(2) | + | next_date = str(year)+"-"+str(to_month).zfill(2)+"-"+str(to_day).zfill(2) |
return next_date | return next_date | ||
Line 175: | Line 179: | ||
= Bonus task = | = Bonus task = | ||
− | There is 10% bonus if your script can also take two dates both in " | + | There is 10% bonus if your script can also take two dates both in "YYYY-MM-DD" format and output the number of days between the given two dates. |
e.g. | e.g. | ||
− | * Calculate the number of days between " | + | * Calculate the number of days between "2018-03-01" and "2019-03-01" |
− | python3 a1_rchan.py | + | python3 a1_rchan.py 2018-03-01 2019-03-01 |
365 | 365 | ||
− | * Calculate the number of days between " | + | * Calculate the number of days between "2019-03-01" and "2018-03-01" |
− | python3 a1_rchan.py | + | python3 a1_rchan.py 2019-03-01 2018-03-01 |
365 | 365 | ||
= Deliverable = | = Deliverable = | ||
− | == Create a private repository on github.com under your account == | + | == Create a private repository on github.com under your account by cloning the sample repo== |
− | * name the repository as 'ops435-a1' | + | * clone the repository https://github.com/rayfreeping/ops435-a1 for useful resource, sample code and test scripts for this assignment. |
+ | * name the cloned repository under your github account as 'ops435-a1' | ||
* invite 'rayfreeping' as one of the collaborator to your 'ops435-a1' repository | * invite 'rayfreeping' as one of the collaborator to your 'ops435-a1' repository | ||
− | * | + | * use this repository for developing the and keeping track of the following text/source code files: |
** the algorithm for assignment 1 named "a1_algorithm.txt" | ** the algorithm for assignment 1 named "a1_algorithm.txt" | ||
** the python script for assignment 1 named "a1_[seneca-id].py" | ** the python script for assignment 1 named "a1_[seneca-id].py" | ||
** the test results produce by the assignment checking script "checkA1.py". Name it as a1_results.txt | ** the test results produce by the assignment checking script "checkA1.py". Name it as a1_results.txt | ||
+ | * double check and make sure your ops435-a1 on github is configured as a private repository. | ||
= Rubric = | = Rubric = | ||
Line 204: | Line 210: | ||
| Program Options --step || 5 || | | Program Options --step || 5 || | ||
|- | |- | ||
− | | | + | | after() function || 5 || |
|- | |- | ||
− | | | + | | before() function || 15 || |
|- | |- | ||
| dbda() function || 10 || | | dbda() function || 10 || | ||
Line 236: | Line 242: | ||
* your python script, name the file as 'a1_[seneca-id].py' | * your python script, name the file as 'a1_[seneca-id].py' | ||
* the output of the checking script checkA1.py, name the file as 'a1_results.txt' | * the output of the checking script checkA1.py, name the file as 'a1_results.txt' | ||
− | * the 'git log' output for | + | * the 'git log' output for your own repository 'ops435-a1' on github.com, name the file as 'a1_gitlog.txt' |
Latest revision as of 18:34, 29 January 2020
Contents
Overview
When making back up of data files or log files, it is a very common practice to name the backup directories and/or files based on the date the backup was done. In order to restore or locate the directory/file, we often need to find out the backup date from today's date.
The computational task for this assignment is to design an algorithm and write a python script according to your algorithm with appropriate functions. The script should take a date in the "YYYY-MM-DD" format and the number of days before or after the given date as the command line arguments, calculate and output to the standard output data channel the targeted date which is the number of day before or after the given date in the same format.
Coding Standard
Your python script must follow the following coding guide:
Command Line Argument to be supported
- Name your python script as a1_[student_id].py, where [student_id] is your Seneca email user name.
- Your python script must support two mandatory command line arguments : (1) any valid date in YYYY-MM-DD format, (2) number of days before or after the given date, and one option flag: "--step"
- If there are less or more than two data items provided at the command line, your script should display the correct usage message and exit.
Computation Requirements
Algorithm Design
- Here is an basic introduction to Algorithm
- Write a step-by-step instructions in English on how to compute a date in "YYYY-MM-DD" format which is n days before or after a given date also in "YYYY-MM-DD" format.
- While you are working on the step-by-step instructions, note that there are different number of days in each month and some years have 365 days and some years have 366 days.
- You should also do some research to find out when we started using the Calendar in the current form. (This will pose a limit on the validity of your algorithm.)
Required Modules and Functions
Your python script is allowed to import only the os and sys modules from the standard library and all the built-in functions.
Based on the algorithm you have designed for this assignment, you should at least have the following three functions defined in your python script (see later section on the purpose of each function) in order to get a passing grade for this assignment:
- dbda()
- after()
- before()
You should also create additional functions to improved the re-usability of your python code by adding the following functions to earn the maximum possible mark for this assignment:
- days_in_mon()
- leap_year()
- valid_date()
- usage()
Documentation
- Please use python's docstring to document your python script (script level documentation) and each of the functions (function level documentation) you created for this assignment. The docstring should describe 'what' the function does, not 'how' it does.
- The following shows the docstring that was added to the after() function which provides the following information when called with help(after) in the python interactive shell:
Help on function after() in module rchan: after(today) -> str after() takes a valid date string in 'YYYY-MM-DD' format and return a date string for the next day in 'YYYY-MM-DD' format. e.g. after('2017-12-31') -> '2018-01-01' after('2018-01-31') -> '2018-02-01' after('2018-02-28') -> '2018-03-01' (END)
Authorship Declaration
All your Python code for this assignment must be placed in a single source python file. Please include the following declaration as part of the docstring in your Python source code file (replace "Student Name" with your own name):
OPS435 Assignment 1 - Winter 2020
Program: a1_[student_id].py (replace student_id with your Seneca User name)
Author: "Student Name"
The python code in this file (a1_[Student_id].py) is original work written by
"Student Name". No code in this file is copied from any other source
except those provided by the course instructor, including any person,
textbook, or on-line resource. I have not shared this python script
with anyone or anything except for submission for grading.
I understand that the Academic Honesty Policy will be enforced and
violators will be reported and appropriate action will be taken.
Tests and Test results
You must name your python 3 script as a1_[Student_id].py
. The following examples assumes that the student_id is rchan.The script should accept two command line arguments, the first one is the date in "YYYY-MM-DD" format, and the second one is the number of day from the given date, a positive value indicates the number of days after the given date, and a negative value indicates the number of days before the given date. There is an optional flag called --step which can be provided at the command line that makes the program print out all dates until the target date. If the "YYYY-MM-DD" format is broken, your script should give an appropriate error message. Invalid months (>12) or invalid days of month(different for each month), should be detected and give appropriate error messages. For examples:
-
python3 a1_rchan.py 2019-01-01 1
, and the output should be
2019-01-02
-
python3 a1_rchan.py 2019-01-01 -1
, and the output should be
2018-12-31
-
python3 a1_rchan.py 2019-01-01 2
, and the output should be
2019-01-03
-
python3 a1_rchan.py --step 2019-01-01 3
, and the output should be
2019-01-02 2019-01-03 2019-01-04
-
python3 a1_rchan.py 2018-07-01 500
, and the output should be
2019-11-13
-
python3 a1_rchan.py 2018-99-01 2
, and the output should be
Error: wrong month entered
-
python3 a1_rchan.py 2018-01-99 2
, and the output should be
Error: wrong day entered
-
python3 a1_rchan.py 2018 2
, and the output should be
Error: wrong date entered
If there is too few or too many command line arguments given, display the proper usage:
-
Usage: a1_rchan.py [--step] YYYY-MM-DD +/-n
Script structure and sample template
Your code should all be in a single python file with at least the functions mentioned above: dbda(), after(), and before(). To earn the maximum mark, you should also create additional functions into your algorithm, e.g.: leap_year(), days_in_mon, valid_date(), usage(), etc
The following is a brief description of each function:
- The dbda() function should be the main function of your script. The dbda() function will take a date in "YYYY-MM-DD" format, a positive or negative integer, and return a date either before or after the given date according to the value of the given integer in the same format. Your dbda() function should delegate the actual calculation of the target date to either the after() function or the before() function.
- The before() function will take a date in "YYYY-MM-DD" format and return the date of the previous day in the same format.
- The after() function will take a date in "YYYY-MM-DD" format and return the date of the next day in the same format. Next paragraph is a sample python code for the after() function. To earn the maximum possible mark for the assignment, you should modify the sample after() function to make use of the days_in_mon() function.
- The leap_year() function will take a year in "YYYY" format, and return True if the given year is a leap year, otherwise return False.
- The valid_date() function will take a date in "YYYY-MM-DD" format, and return True if the given date is a valid date, otherwise return False plus an appropriate status message. The valid_date() function should make use of the days_in_mon() function.
- The days_in_mon() function will take a year in "YYYY" format, and return a dictionary object which contains the total number of days in each month for the given year. The days_in_mon() function should make use of the leap_year() function.
- The usage() function will take no argument and return a string describing the usage of the script.
#!/usr/sbin/env python3 ''' docstring ''' import ... def after(today): .... return next_day def before(today): .... return previous_day .... def dbda(date,days): ... setup loop: call after() or before() as appropriate return target_day if __name__ == "__main__": .. processing command line arguments .. .. call dbda() ... .. output the result
Sample code for the after() function
# Return the date in YYYY-MM-DD after the given day # def after(today): if len(today) != 10: return '0000-00-00' else: str_year, str_month, str_day = today.split('-') year = int(str_year) month = int(str_month) day = int(str_day) lyear = year % 4 if lyear == 0: feb_max = 29 # this is a leap year else: feb_max = 28 # this is not a leap year lyear = year % 100 if lyear == 0: feb_max = 28 # this is not a leap year lyear = year % 400 if lyear == 0: feb_max = 29 # this is a leap year tmp_day = day + 1 # next day mon_max = { 1:31, 2:feb_max, 3:31, 4:30, 5:31, 6:30, 7:31, 8:31, 9:30, 10:31, 11:30, 12:31} if tmp_day > mon_max[month]: to_day = tmp_day % mon_max[month] # if tmp_day > this month's max, reset to 1 tmp_month = month + 1 else: to_day = tmp_day tmp_month = month + 0 if tmp_month > 12: to_month = 1 year = year + 1 else: to_month = tmp_month + 0 next_date = str(year)+"-"+str(to_month).zfill(2)+"-"+str(to_day).zfill(2) return next_date
Bonus task
There is 10% bonus if your script can also take two dates both in "YYYY-MM-DD" format and output the number of days between the given two dates. e.g.
- Calculate the number of days between "2018-03-01" and "2019-03-01"
python3 a1_rchan.py 2018-03-01 2019-03-01 365
- Calculate the number of days between "2019-03-01" and "2018-03-01"
python3 a1_rchan.py 2019-03-01 2018-03-01 365
Deliverable
Create a private repository on github.com under your account by cloning the sample repo
- clone the repository https://github.com/rayfreeping/ops435-a1 for useful resource, sample code and test scripts for this assignment.
- name the cloned repository under your github account as 'ops435-a1'
- invite 'rayfreeping' as one of the collaborator to your 'ops435-a1' repository
- use this repository for developing the and keeping track of the following text/source code files:
- the algorithm for assignment 1 named "a1_algorithm.txt"
- the python script for assignment 1 named "a1_[seneca-id].py"
- the test results produce by the assignment checking script "checkA1.py". Name it as a1_results.txt
- double check and make sure your ops435-a1 on github is configured as a private repository.
Rubric
Task | Maximum mark | Actual mark |
---|---|---|
Program Authorship Declaration | 5 | |
Program usage | 5 | |
Program Options --step | 5 | |
after() function | 5 | |
before() function | 15 | |
dbda() function | 10 | |
script level docstring | 5 | |
leap_year() function | 5 | |
valid_date() function | 5 | |
days_in_mon() function | 5 | |
usage() function | 5 | |
Algorithm | 15 | |
github.com repository | 15 | |
Total | 100 |
Due Date and Final Submission requirement
Check with your professor for the due date for your section.
Please submit the following files to blackboard by the due date:
- your algorithm (step-by-step instruction for solving the computation problem for this assignment in the English language), name the file as 'a1_algorithm.txt'
- your python script, name the file as 'a1_[seneca-id].py'
- the output of the checking script checkA1.py, name the file as 'a1_results.txt'
- the 'git log' output for your own repository 'ops435-a1' on github.com, name the file as 'a1_gitlog.txt'