Hello Everyone,
I have created a habit tracking app that I would love to get some feedback on. This is my first real OOP project in Python. If anyone would be willing to review my app and give me some feedback, I would be extremely grateful. Thanks in advance!
Github URL: https://github.com/Bcopeland64/IU-Habit-Tracker-App
Apologies for not posting the code here. Please find the app in question below:
main.py file:
I have created a habit tracking app that I would love to get some feedback on. This is my first real OOP project in Python. If anyone would be willing to review my app and give me some feedback, I would be extremely grateful. Thanks in advance!
Github URL: https://github.com/Bcopeland64/IU-Habit-Tracker-App
Apologies for not posting the code here. Please find the app in question below:
main.py file:
import click from habit import HabitTracker, Habit import questionary from analytics import * from db2 import HabitDB, HabitTracker tracker = HabitTracker() @click.group() def cli(): pass @cli.command() def create(): name = questionary.text("Enter the habit name: ").ask() period = questionary.select("Enter the habit period:", choices=["daily", "weekly", "monthly"]).ask() tracker.create_habit(name, period) click.echo(f'Habit "{name}" with period "{period}" created successfully!') @cli.command() def delete(): name = questionary.text("Enter the habit name: ").ask() tracker.delete_habit(name) click.echo(f'Habit "{name}" deleted successfully!') @cli.command() def list_habit_groups(): habits = tracker.get_habits() click.echo('Current habits:') for habit in habits: click.echo(f'- {habit.name} ({habit.period})') @cli.command() def list_habit_groups_period(): period = questionary.select("Enter the habit period:", choices=["daily", "weekly", "monthly"]).ask() habits = tracker.get_habits_by_period(period) click.echo(f'Current {period} habits:') for habit in habits: click.echo(f'- {habit.name}') @cli.command() def longest_streak(): longest_streak_habit = tracker.get_longest_streak() if longest_streak_habit: click.echo(f'Habit with longest streak: {longest_streak_habit.name} ({longest_streak_habit.get_streak()})') else: click.echo('No habits with a streak.') @cli.command() def longest_streak_habit(): name = questionary.text("Enter the habit name: ").ask() streak = tracker.get_longest_streak_by_habit(name) if streak: click.echo(f'Longest streak for habit "{name}": {streak}') else: click.echo(f'Habit "{name}" not found.') @cli.command() def mark(): name = questionary.text("Enter the habit name: ").ask() tracker.mark_complete(name) click.echo(f'Habit "{name}" marked successfully!') @cli.command() def unmark(): name = questionary.text("Enter the habit name: ").ask() tracker.mark_incomplete(name) click.echo(f'Habit "{name}" unmarked successfully!') def main(): while True: command = input('Enter a command (create, delete, list, list-period, longest-streak, longest-streak-habit, or exit): ') if command == 'create': name = input('Enter the habit name: ') period = input('Enter the habit period (daily or weekly): ') tracker.create_habit(name, period) click.echo(f'Habit "{name}" with period "{period}" created successfully!') elif command == 'delete': name = input('Enter the habit name: ') tracker.delete_habit(name) click.echo(f'Habit "{name}" deleted successfully!') elif command == 'habit_groups': habits = tracker.get_habits() click.echo('Current habits:') for habit in habits: click.echo(f'- {habit.name} ({habit.period})') elif command == 'habit_groups_period': period = input('Enter the habit period (daily or weekly): ') habits = tracker.get_habits_by_period(period) click.echo(f'Current {period} habits:') for habit in habits: click.echo(f'- {habit.name}') elif command == 'longest-streak': longest_streak_habit = tracker.get_longest_streak() if longest_streak_habit: click.echo(f'Habit with longest streak: {longest_streak_habit.name} ({longest_streak_habit.get_streak()})') else: click.echo('No habits with a streak.') elif command == 'longest-streak-habit': name = input('Enter the habit name: ') streak = tracker.get_longest_streak_by_habit(name) if streak: click.echo(f'Longest streak for habit "{name}": {streak}') else: click.echo(f'Habit "{name}" not found.') elif command == 'mark': name = input('Enter the habit name: ') tracker.mark_complete(name) click.echo(f'Habit "{name}" marked successfully!') elif command == 'unmark': name = input('Enter the habit name: ') tracker.mark_incomplete(name) click.echo(f'Habit "{name}" unmarked successfully!') elif command == 'exit': break if __name__ == '__main__': cli() main()habit.py file:
from datetime import datetime class Habit: def __init__(self, name: str, period: str): self.name = name self.period = period self.created_at = datetime.now() self.completed_at = [] def mark_complete(self): self.completed_at.append(datetime.now()) def mark_incomplete(self): self.completed_at.pop() def get_streak(self): if not self.completed_at: return 0 current_streak = 1 for i in range(1, len(self.completed_at)): if self.completed_at[i] - self.completed_at[i-1] == self.period: current_streak += 1 else: break return current_streak class HabitTracker: def __init__(self): self.habits = [] def create_habit(self, name: str, period: str): new_habit = Habit(name, period) self.habits.append(new_habit) def delete_habit(self, name: str): for i, habit in enumerate(self.habits): if habit.name == name: del self.habits[i] break def get_habits(self): return self.habits def get_habits_by_period(self, period: str): return [habit for habit in self.habits if habit.period == period] def get_longest_streak(self): longest_streak = 0 longest_streak_habit = None for habit in self.habits: streak = habit.get_streak() if streak > longest_streak: longest_streak = streak longest_streak_habit = habit return longest_streak_habit def get_longest_streak_by_habit(self, name: str): for habit in self.habits: if habit.name == name: return habit.get_streak() return 0 def mark_complete(self, name: str): for habit in self.habits: if habit.name == name: habit.mark_complete() break def mark_incomplete(self, name: str): for i, completed_at in enumerate(self.completed_at): if self.name == name: del self.completed_at[i] def relationships(self): for habit in self.habits: print(habit.name, habit.get_streak())db.py file:
import sqlite3 import datetime from habit import Habit, HabitTracker class HabitDB: def establish_a_connection(self): self.conn = sqlite3.connect('habits.db') self.cursor = self.conn.cursor() # Create habits table if it does not exist self.cursor.execute(''' CREATE TABLE IF NOT EXISTS habits ( id INTEGER PRIMARY KEY, name TEXT NOT NULL, period TEXT NOT NULL, created_at DATETIME NOT NULL )''') # Create completions table if it does not exist self.cursor.execute(''' CREATE TABLE IF NOT EXISTS completions ( habit_id INTEGER NOT NULL, completed_at DATETIME NOT NULL, FOREIGN KEY(habit_id) REFERENCES habits(id) ON DELETE CASCADE //added ON DELETE CASCADE to delete the related entries in completions when a row in habits is deleted )''') self.conn.commit() def create_habit(self, name: str, period: str): self.cursor.execute( 'INSERT INTO habits (name, period, created_at) VALUES (?, ?, ?)', (name, period, datetime.now()) ) self.conn.commit() def delete_habit(self, name: str): self.cursor.execute( 'DELETE FROM habits WHERE name=?', (name,) ) self.conn.commit() def mark_complete(self, name: str): self.cursor.execute( 'SELECT id FROM habits WHERE name=?', (name,) ) habit_id = self.cursor.fetchone()[0] self.cursor.execute( 'INSERT INTO completions (habit_id, completed_at) VALUES (?, ?)', (habit_id, datetime.now()) ) self.conn.commit() def mark_incomplete(self, name: str): self.cursor.execute( 'SELECT id FROM habits WHERE name=?', (name,) ) habit_id = self.cursor.fetchone()[0] self.cursor.execute( 'DELETE FROM completions WHERE habit_id=? ORDER BY completed_at DESC LIMIT 1', (habit_id,) ) self.conn.commit() def get_habits(self): self.cursor.execute('SELECT * FROM habits') rows = self.cursor.fetchall() habits = [] for row in rows: id, name, period, createdat = row self.cursor.execute( 'SELECT completedat FROM completions WHERE habitid=?', (id,)) completedatrows = self.cursor.fetchall() completedat = [row[0] for row in completedatrows] habits.append(Habit(id, name, period, createdat, completedat)) return habits def get_habits_by_period(self, period: str): self.cursor.execute('SELECT * FROM habits WHERE period=?', (period,)) rows = self.cursor.fetchall() habits = [] for row in rows: id, name, _, created_at = row self.cursor.execute( 'SELECT completed_at FROM completions WHERE habit_id=?', (id,) ) completed_at_rows = self.cursor.fetchall() class HabitTracker: def __init__(self): self.habits = [] self.db = HabitDB() self.db.establish_a_connection() def create_habit(self, name: str, period: str): self.db.create_habit(name, period) def delete_habit(self, name: str): self.db.delete_habit(name) def get_habits(self): return self.db.get_habits() def get_habits_by_period(self, period: str): return self.db.get_habits_by_period(period) def get_longest_streak(self): longest_streak = 0 longest_streak_habit = None for habit in self.habits: streak = habit.get_streak() if streak > longest_streak: longest_streak = streak longest_streak_habit = habit return longest_streak_habit def get_longest_streak_by_habit(self, name: str): for habit in self.habits: if habit.name == name: return habit.get_streak() return 0 def mark_complete(self, name: str): self.db.mark_complete(name) def mark_incomplete(self, name: str): self.db.mark_incomplete(name) def get_longest_streak_by_habit(self, name: str): for habit in self.habits: if habit.name == name: return habit.get_streak() return 0 def mark_complete(self, name: str): self.db.mark_complete(name) def mark_incomplete(self, name: str): self.db.mark_incomplete(name)