From fdc90fe1187db5bec2dd8b8d94149e597cbdd3a3 Mon Sep 17 00:00:00 2001 From: Yapollon <75550334+Yapollon@users.noreply.github.com> Date: Sun, 10 Mar 2024 13:10:54 +0100 Subject: [PATCH] Slot System for HabitLists --- db/SQLiteClient.py | 49 ++++++++++++++++--- .../1709994071_delete_habit_lists_table.sql | 1 + .../1709994088_create_habit_lists_table.sql | 8 +++ models/Habit.py | 20 ++++---- models/HabitList.py | 37 ++++++++++++-- models/User.py | 4 +- 6 files changed, 94 insertions(+), 25 deletions(-) create mode 100644 db/migrations/1709994071_delete_habit_lists_table.sql create mode 100644 db/migrations/1709994088_create_habit_lists_table.sql diff --git a/db/SQLiteClient.py b/db/SQLiteClient.py index 9dc4db3..7fe4070 100644 --- a/db/SQLiteClient.py +++ b/db/SQLiteClient.py @@ -159,7 +159,7 @@ def get_heatmap_value(user_id: int, days: int): return 0 -def get_next_slot(list_id: int): +def habit_get_next_slot(list_id: int): query = f"SELECT slot FROM habits WHERE list_id = {list_id} ORDER BY slot DESC LIMIT 1;" conn = con3() cursor = conn.cursor() @@ -169,7 +169,7 @@ def get_next_slot(list_id: int): return slot[0] + 1 if slot else 1 -def get_slots(list_id: int): +def habit_get_slots(list_id: int): query = f"SELECT id, slot FROM habits WHERE list_id = {list_id} ORDER BY slot;" conn = con3() cursor = conn.cursor() @@ -179,7 +179,7 @@ def get_slots(list_id: int): return slots -def update_slot(id: int, slot: int): +def habit_update_slot(id: int, slot: int): now = datetime.now().isoformat() query = f"UPDATE habits SET slot = {slot}, updated_at = '{now}' WHERE id = {id};" conn = con3() @@ -265,10 +265,10 @@ def delete_habitTracking(id: int): ### HabitList ### -def create_habitList(user_id: int, name: str, description: str): +def create_habitList(user_id: int, name: str, description: str, slot: int): now = datetime.now().isoformat() - query = (f"INSERT INTO habit_lists (name, description, created_at, updated_at) " - f"VALUES ('{name}', '{description}', '{now}', '{now}');") + query = (f"INSERT INTO habit_lists (name, description, slot, created_at, updated_at) " + f"VALUES ('{name}', '{description}', '{slot}', '{now}', '{now}');") conn = con3() cursor = conn.cursor() cursor.execute(query) @@ -290,6 +290,39 @@ def get_habitList(id: int): return habit_list +def habitList_get_next_slot(user_id: int): + query = (f"SELECT slot FROM habit_lists JOIN habit_users ON habit_lists.id = habit_users.list_id " + f"WHERE habit_users.user_id = {user_id} ORDER BY slot DESC LIMIT 1;") + conn = con3() + cursor = conn.cursor() + cursor.execute(query) + slot = cursor.fetchone() + conn.close() + return slot[0] + 1 if slot else 1 + + +def habitList_get_slots(user_id: int): + query = (f"SELECT habit_lists.id, slot FROM habit_lists JOIN habit_users ON habit_lists.id = habit_users.list_id " + f"WHERE habit_users.user_id = {user_id} ORDER BY slot;") + conn = con3() + cursor = conn.cursor() + cursor.execute(query) + slots = cursor.fetchall() + conn.close() + return slots + + +def habitList_update_slot(id: int, slot: int): + now = datetime.now().isoformat() + query = f"UPDATE habit_lists SET slot = {slot}, updated_at = '{now}' WHERE id = {id};" + conn = con3() + cursor = conn.cursor() + cursor.execute(query) + conn.commit() + conn.close() + return cursor.lastrowid + + def get_habitLists(user_id: int): query = (f"SELECT habit_lists.*, habit_users.user_id, habit_users.accepted FROM habit_lists JOIN habit_users ON habit_lists.id = habit_users.list_id " f"WHERE habit_users.user_id = {user_id};") @@ -333,8 +366,9 @@ def add_user(list_id: int, user_id: int): conn.commit() conn.close() + def accept_List(list_id: int, user_id: int): - query = (f"UPDATE habit_users SET accepted = 1 WHERE habit_users.user_id = {user_id} AND habit_users.list_id = {list_id};") + query = f"UPDATE habit_users SET accepted = 1 WHERE habit_users.user_id = {user_id} AND habit_users.list_id = {list_id};" conn = con3() cursor = conn.cursor() cursor.execute(query) @@ -342,7 +376,6 @@ def accept_List(list_id: int, user_id: int): conn.close() - def remove_user(list_id: int, user_id: int): query = f"DELETE FROM habit_users WHERE user_id = {user_id} AND list_id = {list_id};" conn = con3() diff --git a/db/migrations/1709994071_delete_habit_lists_table.sql b/db/migrations/1709994071_delete_habit_lists_table.sql new file mode 100644 index 0000000..b345368 --- /dev/null +++ b/db/migrations/1709994071_delete_habit_lists_table.sql @@ -0,0 +1 @@ +DROP TABLE habit_lists; \ No newline at end of file diff --git a/db/migrations/1709994088_create_habit_lists_table.sql b/db/migrations/1709994088_create_habit_lists_table.sql new file mode 100644 index 0000000..95deb63 --- /dev/null +++ b/db/migrations/1709994088_create_habit_lists_table.sql @@ -0,0 +1,8 @@ +CREATE TABLE IF NOT EXISTS habit_lists ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + name TEXT NOT NULL, + description TEXT, + slot INTEGER NOT NULL, + created_at TEXT NOT NULL, + updated_at TEXT NOT NULL +); \ No newline at end of file diff --git a/models/Habit.py b/models/Habit.py index d9835d5..d14abc5 100644 --- a/models/Habit.py +++ b/models/Habit.py @@ -4,8 +4,8 @@ from datetime import datetime from datetime import timedelta from models.HabitTracking import HabitTracking -from db.SQLiteClient import (create_habit, get_habit, update_habit, delete_habit, get_next_slot, get_slots, update_slot, - get_habitTrackings, get_habitList, update_habit_statistics) +from db.SQLiteClient import (create_habit, get_habit, update_habit, delete_habit, habit_get_next_slot, habit_get_slots, + habit_update_slot, get_habitTrackings, get_habitList, update_habit_statistics) # unit will be represented by integers like this: @@ -33,7 +33,7 @@ class Habit: @staticmethod def create(list_id: int, name: str, times: int, note: str = None, unit: int = 1, checked: bool = False, count: int = 0, streak: int = 0): - slot = get_next_slot(list_id) + slot = habit_get_next_slot(list_id) id = create_habit(list_id, name, note, times, unit, slot, checked, count, streak) return Habit(id, list_id, name, note, times, unit, slot, checked, count, streak) @@ -51,28 +51,28 @@ class Habit: # Updates the slot and reorders the HabitList accordingly def update_slot(self, new_slot: int): # Fetches a list with the following structure [(id, slot), (id, slot), ...] - slots = get_slots(self.list_id) + slots = habit_get_slots(self.list_id) # Splits the list depending on whether the new slot is higher or lower than the current one if new_slot > self.slot: # Example self.slot=1 new_slot=4 slots = slots[self.slot:new_slot] # Expected list: [(id, 2), (id, 3), (id, 4)] for slot in slots: - update_slot(slot[0], slot[1]-1) + habit_update_slot(slot[0], slot[1]-1) if new_slot < self.slot: # Example self.slot=4 new_slot=1 slots = slots[new_slot-1:self.slot-1] # Expected list: [(id, 1), (id, 2), (id, 3)] for slot in slots: - update_slot(slot[0], slot[1]+1) + habit_update_slot(slot[0], slot[1]+1) # Update the slot of the current habit - update_slot(self.id, new_slot) + habit_update_slot(self.id, new_slot) # Deletes the Habit def delete(self): # Reorders the slots - slots = get_slots(self.list_id)[self.slot+1:] + slots = habit_get_slots(self.list_id)[self.slot+1:] for slot in slots: - update_slot(slot[0], slot[1] - 1) + habit_update_slot(slot[0], slot[1] - 1) # Deletes all track-records associated with the Habit trackings = self.get_habitTrackings() @@ -96,7 +96,7 @@ class Habit: def habit_list(self) -> list: from models.HabitList import HabitList raw_habitLists = get_habitList(self.list_id) - return HabitList(raw_habitLists[0], raw_habitLists[1], raw_habitLists[2]) if raw_habitLists else None + return HabitList(raw_habitLists[0], raw_habitLists[1], raw_habitLists[2], raw_habitLists[3]) if raw_habitLists else None # Loads the progress and checks if the streak is not broken diff --git a/models/HabitList.py b/models/HabitList.py index e64ab56..df638ef 100644 --- a/models/HabitList.py +++ b/models/HabitList.py @@ -3,7 +3,8 @@ from dataclasses import dataclass from models.Habit import Habit from models.User import User from db.SQLiteClient import (create_habitList, get_habitList, get_habits, get_users, add_user, remove_user, - update_habitList, delete_habitList) + update_habitList, delete_habitList, habitList_get_next_slot, habitList_get_slots, + habitList_update_slot) @dataclass @@ -11,17 +12,19 @@ class HabitList: id: int name: str description: str - habits: list = None #? unclear usage + slot: int + habits: list = None @staticmethod def create(user_id: int, name: str, description: str): - id = create_habitList(user_id, name, description) - return HabitList(id, name, description) + slot = habitList_get_next_slot(user_id) + id = create_habitList(user_id, name, description, slot) + return HabitList(id, name, description, slot) @staticmethod def get(id: int): habitList = get_habitList(id) - return HabitList(habitList[0], habitList[1], habitList[2]) if habitList else None + return HabitList(habitList[0], habitList[1], habitList[2], habitList[3]) if habitList else None # Updates: name, description @@ -29,8 +32,32 @@ class HabitList: update_habitList(self.id, self.name, self.description) + # Updates the slot and reorders the HabitLists accordingly + def update_slot(self,user_id: int, new_slot: int): + # Fetches a list with the following structure [(id, slot), (id, slot), ...] + slots = habitList_get_slots(user_id) + + # Splits the list depending on whether the new slot is higher or lower than the current one + if new_slot > self.slot: # Example self.slot=1 new_slot=4 + slots = slots[self.slot:new_slot] # Expected list: [(id, 2), (id, 3), (id, 4)] + for slot in slots: + habitList_update_slot(slot[0], slot[1]-1) + if new_slot < self.slot: # Example self.slot=4 new_slot=1 + slots = slots[new_slot-1:self.slot-1] # Expected list: [(id, 1), (id, 2), (id, 3)] + for slot in slots: + habitList_update_slot(slot[0], slot[1]+1) + + # Update the slot of the current habitList + habitList_update_slot(self.id, new_slot) + + # Deletes the HabitList | The id of the current user is necessary def delete(self, user_id): + # Reorders the slots + slots = habitList_get_slots(user_id)[self.slot+1:] + for slot in slots: + habitList_update_slot(slot[0], slot[1] - 1) + if len(get_users(self.id)) > 1: self.remove_user(user_id) else: diff --git a/models/User.py b/models/User.py index 4df76ff..d3e5353 100644 --- a/models/User.py +++ b/models/User.py @@ -56,7 +56,7 @@ class User(UserMixin): for habitList in raw_habitLists: user_id = habitList[5] accepted = habitList[6] - habitList = HabitList(habitList[0], habitList[1], habitList[2]) + habitList = HabitList(habitList[0], habitList[1], habitList[2], habitList[3]) if accepted == 1 or habitList.get_users()[0].id == user_id: habitLists.append(habitList) @@ -69,7 +69,7 @@ class User(UserMixin): raw_habitLists = get_unaccepted_habitLists(self.id) habitLists = [] for habitList in raw_habitLists: - habitList = HabitList(habitList[0], habitList[1], habitList[2]) + habitList = HabitList(habitList[0], habitList[1], habitList[2], habitList[3]) habitLists.append(habitList) return habitLists