Week 1: The first seven steps
Tags: python, 100daysofcode, womenintech
Published: 2019-11-20 22:39:02

The aim of this project is to write a daily tasks program in Python that will prompt users in the morning to record three things they would like to achieve that day (one major, two minor) and prompt them again in the evening to update whether the tasks have been completed or not.

The development of this project will be directed by the Python knowledge gained week-on-week, to satisfy weekly objectives, starting with a basic program that processes the following 7 steps;
1. Morning user prompt
2. User inputs tasks
3. Program stores tasks
4. Evening user prompt
5. User updates task status
6. Program stores updated task status
7. Repeat program on new days

And developing these processes into an open source app that is compatible with laptop and mobile devices.

There are many online resources that I can refer to for this project, and I will mostly be using the following;
- Andrei Neagoie’s [Complete Python Developer's Zero to Mastery](https://www.udemy.com/course/complete-python-developer-zero-to-mastery)
- [Medium](https://www.medium.com)
- [StackOverflow](https://stackoverflow.com/)
- [w3Schools](https://www.w3schools.com/python/default.asp)
- Personal mini projects
- This website, of course


### Requirements
Before any coding began, the program requirements were considered for every step. These provided clarity in the process. 
#### 1. Morning User Prompt
- How does the program know it is the morning?

#### 2. User Inputs Tasks
- How does the program request the user for the tasks?
- How does the user know which task is major and which are minors?

#### 3. Program Stores Task
- How will program know when to store tasks?
- Where does the program store the tasks?
- What is the unique ID for each record?

#### 4. Evening User Prompt
- How does the program know when it is the evening?

#### 5. User Updates Task Status
- How does the user update a task status?
- How will the program show the user only tasks for that day?

#### 6. Program Stores Updated Task Status
- How does the program store status updates?
- Will program overwrite morning task records?

#### 7. Repeat Program
- How does the program know when to start a new record?
- How does the program start a new record?

Each of these requirements were tested separately before testing the whole program.


### Constructing the Code
#### 1. Morning User Prompt
One of the first things the program needs to know is what time of day it is. For the simplicity of this first week, two categories were used to identify the time of day; morning and evening. A dictionary is used, with these categories as the keys, and the values as hours, based on a 24-hour clock, that fall into these two categories (for me).

```python
timeOfDay = {"Morning": [5, 6, 7, 8, 9, 10, 11], "Evening": [18, 19, 20, 21, 22, 23]}
```

Then, the program needs to know the current time and identify whether the current hour is in either of these categories.
For this the program is using the datetime module from the datetime library and assigned a couple of the datetime functions to variables before a simple if statement test.

```python
# Using the timeOfDay dictionary

from datetime import datetime as dt

todaysDate = dt.now()
currentHourOfDay = dt.now().hour

if currentHourOfDay in timeOfDay["Morning"]:
    print("Good morning!")
elif currentHourOfDay in timeOfDay["Evening"]:
    print("Good evening!")
else:
    print("It is not the morning or the evening")
```

To test each statement, I changed the currentHourOfDay value to different morning and evening values, and values outside of those categories.

#### 2. User Inputs Tasks
There are two stages of task input for the user; the first is in the morning. If the program is run within the morning hours, according to those in the timeOfDay dictionary, the user is greeted and asked what they want to achieve that day. For this, the input function is used, and it is included as the body of the first if statement.

```python
if currentHourOfDay in timeOfDay["Morning"]:
    print("\nGood morning! What would you like to achieve today?")
    major = input("Major task: ")
    minor_1 = input("Minor task 1: ")
    minor_2 = input("Major task 2: ")

    print("\nGreat! Come back after 6pm to update your progress")
```

#### 3. Program Stores Task
To store the daily tasks, I am using a pandas DataFrame which will export data to a csv file, and be imported when called again. This requires a file location, file name, and a DataFrame to store the data in.
To account for multiple users, so as not to overwrite another users storage or records, a userName and dateOfBirth variable are joined to create a unique filename. This unique identifier will change over time as the project develops.

The user name and date of birth are requested at the start of the program so it can source the correct csv file.
Also, because the record needs to be identified when the csv is recalled, and the tasks are daily, the date as an integer is used as a unique ID within the data.

```python
import pandas as pd

userName = input("First Name: ")
dateOfBirth = input("Date of Birth (ddmmyyyy): ")

dateAsInteger = int(todaysDate.strftime("%Y%m%d"))

fileLocation = "<file location>"
fileName = userName + dateOfBirth + ".csv"
filePath = fileLocation + fileName

if not path.exists(filePath):
    tasks_df = pd.DataFrame(columns=["UniqueID","MajorTask", "MinorTask1",
                                       "MinorTask2", "MajorTask_Complete",
                                       "MinorTask1_Complete", "MinorTask2_Complete"])
    
    tasks_df.to_csv(fileName, index=False)
else:
    tasks_df = pd.read_csv(filePath)

# Previous if statement
if currentHourOfDay in timeOfDay["Morning"]:
    print("\nGood morning! What would you like to achieve today?")
    major = input("Major task: ")
    minor_1 = input("Minor task 1: ")
    minor_2 = input("Major task 2: ")

    print("\nGreat! Come back after 6pm to update your progress")

    tasks_df.iloc[0,:4] = [dateAsInteger, major, minor_1, minor_2]
    tasks_df.to_csv(fileName, index=None)
```

#### 4. Evening User Prompt
The program identifies the evening the same way it identifies the morning, and a the user is prompted to update their task status'.

#### 5. User Updates Task Status
To update the task status', the program imports the previously saved csv, and recalls the day's tasks for the user to update, using the input function.

```python

if currentHourOfDay in timeOfDay["Evening"]:
    major = tasks_df["MajorTask"][0]
    minor_1 = tasks_df["MinorTask1"][0]
    minor_2 = tasks_df["MinorTask2"][0]
    
    print("\nWelcome back! Did your complete your tasks (Y/N)?")
    
    major_complete = completionKey[input(f"""Today's major task: {major}
    Did you complete this? """)]
    minor1_complete = completionKey[input(f"""Today's first minor task: {minor_1}
    Did you complete this? """)]
    minor2_complete = completionKey[input(f"""Today's second minor task: {minor_2}
    Did you complete this? """)]
```

#### 6. Program Stores Updates Task Status
To store the updated task status, the previously saved csv is imported as a DataFrame and the new values are added. A dictionary is used to allow users to clearly answer "Y" or "N" for their updates, whilst storing the values as 1 and 0 for future analysis.

```python

completionKey = {"Y": 1, "N": 0}

if currentHourOfDay in timeOfDay["Evening"]:
    major = tasks_df["MajorTask"][0]
    minor_1 = tasks_df["MinorTask1"][0]
    minor_2 = tasks_df["MinorTask2"][0]
    
    print("\nWelcome back! Did your complete your tasks (Y/N)?")
    
    major_complete = completionKey[input(f"""Today's major task: {major}
    Did you complete this? """)]
    minor1_complete = completionKey[input(f"""Today's first minor task: {minor_1}
    Did you complete this? """)]
    minor2_complete = completionKey[input(f"""Today's second minor task: {minor_2}
    Did you complete this? """)]
    
    tasks_df.iloc[0,4:] = [major_complete, minor1_complete, minor2_complete]
    
    tasks_df.to_csv(fileName, index=None)
```

#### 7. Repeat Program
Repeating the program was the most challenging step to figure out. These are requirements I hadn't initially considered:
- How will the program know if the morning's tasks have already been input?
- How will the program know if it is the same day or a new day?
- If it is a new day, how will the program know to record a new entry and not overwrite a previous entry?
- How will the program know if a user is new, and therefore requires a new csv file, or returning?
- How will the program know if tasks and their status' have been updated for the day?

It was really fun trying to find the answers to these questions, and every time I found an answer to one, another appeared, but I got there in the end. Below is the final code for this week.

```python
"""
Three Things To Do
by @LauraKateHolley
"""

from datetime import datetime as dt
import pandas as pd
from os import path

userName = input("First Name: ")
dateOfBirth = input("Date of Birth (ddmmyyyy): ")

todaysDate = dt.now()
currentHourOfDay = dt.now().hour
dateAsInteger = int(todaysDate.strftime("%Y%m%d"))

fileLocation = "C:\\Users\\laura\\Documents\\Personal Projects\\Three Things To Do\\"
fileName = userName + dateOfBirth + ".csv"
filePath = fileLocation + fileName

timeOfDay = {"Morning": [5, 6, 7, 8, 9, 10, 11], "Evening": [18, 19, 20, 21, 22, 23]}
completionKey = {"Y": 1, "N": 0}

if not path.exists(filePath):
    tasks_df = pd.DataFrame(columns=["UniqueID","MajorTask", "MinorTask1",
                                       "MinorTask2", "MajorTask_Complete",
                                       "MinorTask1_Complete", "MinorTask2_Complete"])
    
    tasks_df.to_csv(fileName, index=False)
else:
    tasks_df = pd.read_csv(filePath)

if tasks_df.loc[len(tasks_df)-1, 'UniqueID'] != dateAsInteger:
    tasks_df.loc[len(tasks_df),'UniqueID'] = dateAsInteger

firstEntry = tasks_df.iloc[0,1:].isnull().all()
latestEntry = int(tasks_df['UniqueID'].max())
maxIndex = len(tasks_df.index) - 1
emptyTasks = tasks_df.iloc[maxIndex,1:4].isnull().all()
emptyTaskStatus = tasks_df.iloc[maxIndex,4:].isnull().all()


# --- MAIN BODY ---

if currentHourOfDay in timeOfDay["Morning"] and firstEntry:
    print("\nGood morning! Welcome to Three Things To Do. To start, tell me what would you like to achieve today?")
    major = input("Major task:  ")
    minor_1 = input("Minor task 1: ")
    minor_2 = input("Minor task 2: ")
    
    print("\nGreat! Come back after 6pm to update your task progress")
    
    tasks_df.iloc[0,1:4] = [major, minor_1, minor_2]
    tasks_df.to_csv(fileName, index=None)
    
elif not emptyTasks and emptyTaskStatus and currentHourOfDay not in timeOfDay["Evening"]:
    print("\nOops! You have already entered your tasks for the day. Come back after 6pm to update your progress")
    
elif latestEntry == dateAsInteger and currentHourOfDay in timeOfDay["Morning"] and emptyTasks:
    print("\nGood morning! What would you like to achieve today?")
    major = input("Major task: ")
    minor_1 = input("Minor task 1: ")
    minor_2 = input("Major task 2: ")

    print("\nGreat! Come back after 6pm to update your progress")
    
    tasks_df.iloc[maxIndex,:4] = [dateAsInteger, major, minor_1, minor_2]
    tasks_df.to_csv(fileName, index=None)
    
elif currentHourOfDay in timeOfDay["Evening"] and latestEntry == dateAsInteger and emptyTaskStatus:
   
    major = tasks_df["MajorTask"][maxIndex]
    minor_1 = tasks_df["MinorTask1"][maxIndex]
    minor_2 = tasks_df["MinorTask2"][maxIndex]
    
    print("\nWelcome back! Did your complete your tasks (Y/N)?")
    
    major_complete = completionKey[input(f"""Today's major task: {major}
    Did you complete this? """)]
    minor1_complete = completionKey[input(f"""Today's first minor task: {minor_1}
    Did you complete this? """)]
    minor2_complete = completionKey[input(f"""Today's second minor task: {minor_2}
    Did you complete this? """)]
    
    tasks_df.iloc[maxIndex,4:] = [major_complete, minor1_complete, minor2_complete]
    
    tasks_df.to_csv(fileName, index=None)
    
else:
    print("\nYou have already updated your tasks for the day, good job!")
    
# --- END ---
```


### End of week conclusions
This week was a lot of fun. I learnt about the datetime module and path module which were key players in being able to record new data and recognise new/returning users. 
Originally, I thought this would be a few lines of code, not much... I was wrong. However, I am hoping over time when I learn more about constructing my own functions and classes, the code will be less... busy?

I'd really appreciate any feedback on this. If it's any good, what I can do to improve it, and any ideas for development!