habitmove/habitmove/repetitions.py

98 lines
3.4 KiB
Python

import sqlite3
from datetime import datetime
from habitmove.loopdata import Habit, Repetition
def migrate(db, habitlist, events):
c = db.cursor()
habits = habit_list_add_ids(c, habitlist)
repetitions = get_all_repetitions(habits, events)
for rep in repetitions:
add_to_database(c, habits, rep)
LOOP_RANGE_VALUE_MULTIPLIER = 1000
def get_all_repetitions(habits, events):
"""Return list of all repetitions found of habits in events passed in.
Parameters:
habits (list): Collection of habits, with minimum necessary fields description and id.
events (list): Collection of events, with minimum necessary field end.
Returns:
repetitions (list): Collection of events transformed into Loop repetitions.
Contains fields id, timestamp, value (for ranges).
"""
repetitions = []
for event in events:
for activity in event.activities:
for habit in habits.values():
# TODO Fix reaching a layer too far into activity -> tracker
if habit.uuid == activity.tracker.id:
rep = Repetition(
habit_uuid=habit.uuid, timestamp=event.end, value=2
)
if habit.type == 1 and activity.value:
rep.value = activity.value * LOOP_RANGE_VALUE_MULTIPLIER
repetitions.append(rep)
return repetitions
# TODO possibly just get rid of this entirely
def habit_list_add_ids(c, habitlist):
"""Return the collection of habits with their sqlite id added.
Parameters:
c (sqlite.db.cursor): SQL cursor of database to query.
habitlist (list[Habit]): Full habit collection to return a simplified view of.
Returns:
habit_id_dict (dict[Habit]): The habit collection as a dict with the keys
consisting of the habit's sqlite database ID.
"""
with_id = {}
for h in habitlist:
sql_id = fetch_habit_id(c, h.uuid)
with_id[sql_id] = h
return with_id
def fetch_habit_id(cursor: sqlite3.Cursor, uuid: str):
"""Return sqlite internal id for habit with uuid.
Parameters:
:param c: SQL cursor of database to query.
:param uuid: Unique id of habit to query for.
Returns:
:return id: SQLite internal id for habit queried for.
"""
cursor.execute("select id from Habits where uuid = ?", ([uuid]))
id = cursor.fetchone()
if id is not None:
return id[0]
def add_to_database(
cursor: sqlite3.Cursor, habits: dict[int, Habit], repetition: Repetition
):
"""Insert the repetition into a sqlite3 table suitable for Loop.
Parameters:
:param c: SQL cursor of database to query.
:sql_id: Internal sqlite database id of the habit the repetition belongs to.
"""
for sql_id, habit in habits.items():
if repetition.habit_uuid == habit.uuid:
try:
cursor.execute(
"""
INSERT INTO
Repetitions(id, habit, timestamp, value)
VALUES (NULL, ?, ?, ?)
""",
(sql_id, repetition.timestamp, repetition.value),
)
except sqlite3.IntegrityError:
# TODO better error handling
print(
f"{sql_id}, {habit.name}: timestamp {datetime.fromtimestamp(repetition.timestamp/1000)} not unique, moving timestamp slightly."
)