HabitTracker/models/Habit.py
Yapollon 2f7541aa55 Habit Streak Update (1/2)
first part works autonomous except the uncheck
2024-02-28 10:36:04 +01:00

157 lines
5.2 KiB
Python

import json
from dataclasses import dataclass
from datetime import datetime
from datetime import date
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)
# unit will be represented by integers like this:
# 0: day
# 1: week (default)
# 2: month
# 3: year
@dataclass
class Habit:
id: int
list_id: int
name: str
note: str
times: int
unit: int
slot: int
checked: bool = False
percentage: int = 0
streak: int = 0
def __post_init__(self):
self.fill_statistics()
@staticmethod
def create(list_id: int, name: str, times: int, note: str = None, unit: int = 1):
slot = get_next_slot(list_id)
id = create_habit(list_id, name, note, times, unit, slot)
return Habit(id, list_id, name, note, times, unit, slot)
@staticmethod
def get(id: int):
habit = get_habit(id)
return Habit(habit[0], habit[1], habit[2], habit[3], habit[4], habit[5], habit[6]) if habit else None
# Updates: name, note, times, unit
def update(self):
update_habit(self.id, self.name, self.note, self.times, self.unit)
# 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)
# 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)
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)
# Update the slot of the current 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:]
for slot in slots:
update_slot(slot[0], slot[1] - 1)
# Deletes all track-records associated with the Habit
trackings = self.get_habitTrackings()
for tracking in trackings:
tracking.delete()
# Deletes the current Habit
delete_habit(self.id)
# Returns all track-records for a Habit
def get_habitTrackings(self) -> list:
trackings = []
for rawTracking in get_habitTrackings(self.id):
trackings.append(HabitTracking(rawTracking[0], rawTracking[1],
datetime.strptime(rawTracking[2], "%Y-%m-%dT%H:%M:%S.%f")))
return trackings
# Returns the HabitList in which the Habit is located
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
def getStreak(self):
trackings = []
for rawTracking in get_habitTrackings(self.id):
trackings.append(datetime.strptime(rawTracking[2], "%Y-%m-%d"))
trackings.sort(reverse=True)
current_date = date.today()
yesterdate = date.today() - timedelta(days=1)
if not trackings:
return self.streak
# bisherige streak zurückgeben, falls nicht vorhanden bei null starten
if current_date == trackings[0] or yesterdate == trackings[0]:
return self.streak
else:
self.streak = 0
return self.streak
# Saves the progress and streak of the Habit in the attribute percentage
def fill_statistics(self):
today_date = datetime.today().date()
self.checked = False
count = 0
# self.streak =- 1
yesterday_tracked = False
for tracking in self.get_habitTrackings():
tracking_date = tracking.created_at.date()
if tracking_date == today_date - timedelta(days=1):
yesterday_tracked = True
if tracking_date == today_date:
self.checked = True
self.streak = + 1
# Count occurrences based on unit
if self.unit == 0 and tracking_date == today_date:
count += 1 # Daily
elif self.unit == 1 and tracking_date.isocalendar()[1] == today_date.isocalendar()[1]:
count += 1 # Weekly
elif self.unit == 2 and tracking_date.month == today_date.month:
count += 1 # Monthly
elif self.unit == 3 and tracking_date.year == today_date.year:
count += 1 # Yearly
if not yesterday_tracked:
self.streak = 0
self.percentage = int(count / self.times * 100)
def to_json(self):
return json.dumps(self, default=lambda o: o.__dict__, sort_keys=True, indent=4)