# Import necessary libraries
from datetime import datetime # Import datetime module to work with dates
# Class to represent a to-do task
class TodoTask:
# Constructor to initialize a task with date, description, importance, and category
def __init__(self, day, month, year, description, importance, category):
self.date = (day, month, year) # Date stored as a tuple (day, month, year)
self.description = description # Description of the task
self.importance = importance # Level of importance (1 to 10)
self.category = category # Category of the task
# String representation of the task for easy display
def __str__(self):
return f"{self.date[0]:02}/{self.date[1]:02}/{self.date[2]} - {self.description} - {self.category} - {self.importance}"
# List to store all the tasks entered by the user (max 2000 tasks)
tasks = []
# Helper function to validate if a given date is correct
def is_valid_date(day, month, year):
try:
# Check if the date is valid by trying to create a datetime object
datetime(year, month, day)
return True
except ValueError:
return False
# Main program loop
while True:
# Display the main menu to the user
print("\nMenu:")
print("1 - Add a new task")
print("2 - Show tasks between two dates")
print("3 - Find tasks containing certain text")
print("4 - Update a record")
print("5 - Delete tasks between two positions")
print("6 - Sort tasks by date and description")
print("7 - Find duplicate tasks")
print("Q - Quit")
# Get the user's choice from the menu
choice = input("Enter your choice: ").strip().lower()
# Option 1: Add a new task
if choice == '1':
# Prompt for the task date (day, month, year)
day = int(input("Enter day (1-31): "))
month = int(input("Enter month (1-12): "))
year = int(input("Enter year (1000-3000): "))
# Validate the date
if not is_valid_date(day, month, year):
print("Invalid date. Please enter a correct date.")
continue # Skip to the next iteration if the date is invalid
# Get the task description, importance (1-10), and category
description = input("Enter task description: ").strip()
importance = int(input("Enter importance (1-10): "))
category = input("Enter category: ").strip()
# Create a new TodoTask object and add it to the list
tasks.append(TodoTask(day, month, year, description, importance, category))
print("Task added successfully.") # Inform the user that the task was added
# Option 2: Show tasks between two dates
elif choice == '2':
# Prompt the user for start and end dates (or use today's date if not provided)
start_date_input = input("Enter start date (DD/MM/YYYY, leave blank for today): ").strip()
end_date_input = input("Enter end date (DD/MM/YYYY, leave blank for today): ").strip()
# Set start and end dates to today if the user presses Enter
if not start_date_input:
start_date_input = f"{datetime.now().day:02}/{datetime.now().month:02}/{datetime.now().year}"
if not end_date_input:
end_date_input = f"{datetime.now().day:02}/{datetime.now().month:02}/{datetime.now().year}"
# Convert the input strings to date objects
start_day, start_month, start_year = map(int, start_date_input.split('/'))
end_day, end_month, end_year = map(int, end_date_input.split('/'))
start_date = datetime(start_year, start_month, start_day)
end_date = datetime(end_year, end_month, end_day)
# Display tasks that fall between the two dates
found = False # Flag to track if any tasks are found
for i, task in enumerate(tasks, 1):
task_date = datetime(task.date[2], task.date[1], task.date[0])
if start_date <= task_date <= end_date:
print(f"{i} - {task}") # Display the task details
found = True
if not found: # If no tasks are found
print("No tasks found in the given date range.") # Notify the user
# Option 3: Find tasks containing certain text
elif choice == '3':
# Prompt the user for a search text
search_text = input("Enter text to search in description or category: ").strip().lower()
found = False # Flag to track if any tasks match the search text
for i, task in enumerate(tasks, 1):
# Search for the text in the description or category (case-insensitive)
if search_text in task.description.lower() or search_text in task.category.lower():
print(f"{i} - {task.date[0]:02}/{task.date[1]:02}/{task.date[2]} - {task.description[:50]}") # Show the task
found = True
if not found: # If no tasks match the search text
print("No tasks found with the given text.") # Notify the user
# Option 4: Update a record
elif choice == '4':
try:
# Prompt the user for the task number to update
task_number = int(input("Enter task number to update: ").strip()) - 1
if task_number < 0 or task_number >= len(tasks): # Check if the task number is valid
print("Invalid task number.")
continue # Skip to the next iteration if the task number is invalid
task = tasks[task_number] # Get the task to update
# Display the current data of the task
print(f"\nCurrent task details: {task}")
# Prompt for new values, or allow the user to press Enter to keep the current ones
new_description = input(f"Enter new description (current: {task.description}): ").strip()
if new_description:
task.description = new_description # Update the description
new_importance = input(f"Enter new importance (current: {task.importance}): ").strip()
if new_importance:
task.importance = int(new_importance) # Update the importance
new_category = input(f"Enter new category (current: {task.category}): ").strip()
if new_category:
task.category = new_category # Update the category
except ValueError: # If the user enters an invalid task number
print("Please enter a valid task number.")
# Option 5: Delete tasks between two positions
elif choice == '5':
try:
# Prompt the user for the range of tasks to delete
start_pos = int(input("Enter start position: ").strip()) - 1
end_pos = int(input("Enter end position: ").strip()) - 1
if start_pos < 0 or end_pos >= len(tasks) or start_pos > end_pos: # Validate the positions
print("Invalid positions.")
continue # Skip to the next iteration if the positions are invalid
# Display the tasks to be deleted
print("\nThe following tasks will be deleted:")
for i in range(start_pos, end_pos + 1):
print(f"{i + 1} - {tasks[i]}") # Display each task to be deleted
# Ask for confirmation before deleting
confirm = input("Are you sure you want to delete these tasks? (y/n): ").strip().lower()
if confirm == 'y':
# Delete the tasks from the list
del tasks[start_pos:end_pos + 1]
print("Tasks deleted.")
else:
print("Deletion cancelled.") # If the user cancels
except ValueError: # If the user enters an invalid position
print("Please enter valid positions.")
# Option 6: Sort tasks by date and description
elif choice == '6':
# Sort tasks first by date, then by description
tasks.sort(key=lambda task: (task.date, task.description.lower()))
print("Tasks sorted by date and description.")
# Option 7: Find duplicate tasks
elif choice == '7':
found = False # Flag to track if any duplicates are found
seen = set() # Set to track descriptions already seen
for i, task in enumerate(tasks, 1):
if task.description.lower() in seen: # If the description is a duplicate
print(f"Duplicate task: {i} - {task}")
found = True
else:
seen.add(task.description.lower()) # Add description to the set
if not found: # If no duplicates are found
print("No duplicate tasks found.") # Notify the user
# Option Q: Quit the program
elif choice == 'q':
print("Exiting the program...") # Inform the user
break # Exit the loop and end the program
else:
print("Invalid choice, please enter a valid option.") # Display an error message for invalid input
Output
Menu:
1 - Add a new task
2 - Show tasks between two dates
3 - Find tasks containing certain text
4 - Update a record
5 - Delete tasks between two positions
6 - Sort tasks by date and description
7 - Find duplicate tasks
Q - Quit
Enter your choice: 1
Enter day (1-31): 15
Enter month (1-12): 8
Enter year (1000-3000): 2024
Enter task description: Complete Python homework
Enter importance (1-10): 8
Enter category: Education
Task added successfully.
Enter your choice: 2
Enter start date (DD/MM/YYYY, leave blank for today):
Enter end date (DD/MM/YYYY, leave blank for today):
1 - 15/08/2024 - Complete Python homework - Education - 8