2021-08-28 21:03:12 +00:00
|
|
|
import sqlite3
|
2021-08-29 09:11:58 +00:00
|
|
|
import re
|
2021-08-28 21:03:12 +00:00
|
|
|
|
|
|
|
|
|
|
|
def migrate(db, habitlist, events):
|
|
|
|
c = db.cursor()
|
2021-08-31 16:05:59 +00:00
|
|
|
habits = habit_list_add_ids(c, habitlist)
|
2021-08-30 21:38:49 +00:00
|
|
|
repetitions = get_all_repetitions(habits, events)
|
2021-08-30 08:39:07 +00:00
|
|
|
for rep in repetitions:
|
2021-08-30 21:00:28 +00:00
|
|
|
add_to_database(
|
|
|
|
c, rep["id"], rep["timestamp"], 2 if "value" not in rep else rep["value"]
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
LOOP_RANGE_VALUE_MULTIPLIER = 1000
|
2021-08-30 08:39:07 +00:00
|
|
|
|
|
|
|
|
2021-08-30 21:38:49 +00:00
|
|
|
def get_all_repetitions(habits, events):
|
2021-08-30 08:39:07 +00:00
|
|
|
"""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 = []
|
2021-08-28 21:03:12 +00:00
|
|
|
for event in events:
|
2021-08-30 08:39:07 +00:00
|
|
|
for habit in habits:
|
2021-08-30 21:38:49 +00:00
|
|
|
reps = tags_to_repetitions(habit, extract_tags(event["note"]), event["end"])
|
|
|
|
if reps:
|
|
|
|
repetitions.extend(reps)
|
|
|
|
|
2021-08-30 08:39:07 +00:00
|
|
|
return repetitions
|
2021-08-29 09:11:58 +00:00
|
|
|
|
|
|
|
|
2021-08-31 16:05:59 +00:00
|
|
|
def extract_tags(text, tagmarker="#"):
|
|
|
|
"""Return lists of tuples of all event tags found in text.
|
|
|
|
Parameters:
|
|
|
|
text (str): The text to search through.
|
|
|
|
tagmarker (str): Optional character marking beginning of tag, defaults to '#'.
|
|
|
|
Returns:
|
|
|
|
tags (list): List of tuples in the form [('tag', '3'), ('anothertag', '')].
|
|
|
|
"""
|
|
|
|
string_tags = re.findall(rf"{tagmarker}(\w+)(?:\((\d+)\))?", text)
|
|
|
|
tags_with_int_counters = []
|
|
|
|
for tag in string_tags:
|
|
|
|
tags_with_int_counters.append((tag[0], None if tag[1] == "" else int(tag[1])))
|
|
|
|
return tags_with_int_counters
|
|
|
|
|
|
|
|
|
|
|
|
# does not do:
|
|
|
|
# non-range habits but still #habit(3) number included, adding multiple?
|
2021-08-30 21:38:49 +00:00
|
|
|
def tags_to_repetitions(habit, tags, timestamp):
|
|
|
|
"""Return a list of all repetitions generated from the tags and habits passed in.
|
|
|
|
Parameters:
|
|
|
|
habits (list): Collection of habits, with minimum necessary fields description and id.
|
|
|
|
tags (list): Collection of tag tuples.
|
|
|
|
Returns:
|
|
|
|
repetitions (list): Collection of habits for which a corresponding tag has
|
|
|
|
been found. If they correspond that means at the timestamp
|
|
|
|
the habit has been checked in, and a repetition is created.
|
|
|
|
Contains fields id, timestamp, value (for ranges).
|
|
|
|
"""
|
|
|
|
reps = []
|
|
|
|
for tag in tags:
|
|
|
|
if habit["description"] in tag[0]:
|
|
|
|
repetition = {"id": habit["id"], "timestamp": timestamp}
|
|
|
|
if tag[1]:
|
|
|
|
if "type" in habit and habit["type"] == 1:
|
|
|
|
repetition["value"] = tag[1] * LOOP_RANGE_VALUE_MULTIPLIER
|
|
|
|
reps.append(repetition)
|
|
|
|
return reps
|
|
|
|
|
|
|
|
|
2021-08-30 21:00:28 +00:00
|
|
|
# TODO possibly just get rid of this entirely
|
2021-08-31 16:05:59 +00:00
|
|
|
def habit_list_add_ids(c, habitlist):
|
|
|
|
"""Return the collection of habits with their sqlite id added.
|
2021-08-30 08:39:07 +00:00
|
|
|
Parameters:
|
|
|
|
c (sqlite.db.cursor): SQL cursor of database to query.
|
|
|
|
habitlist (list): Full habit collection to return a simplified view of.
|
|
|
|
Returns:
|
2021-08-31 16:05:59 +00:00
|
|
|
habitlist (list): The full habit collection passed in unchanged,
|
|
|
|
except for an id added to each habit corresponding
|
|
|
|
to their id in sqlite database and Loop repetitions.
|
2021-08-30 08:39:07 +00:00
|
|
|
"""
|
2021-08-31 16:05:59 +00:00
|
|
|
with_id = habitlist.copy()
|
|
|
|
for h in with_id:
|
|
|
|
h["id"] = fetch_habit_id(c, h["uuid"])
|
|
|
|
return with_id
|
2021-08-29 08:13:28 +00:00
|
|
|
|
|
|
|
|
2021-08-29 09:11:58 +00:00
|
|
|
def fetch_habit_id(c, uuid):
|
2021-08-30 08:39:07 +00:00
|
|
|
"""Return sqlite internal id for habit with uuid.
|
|
|
|
Parameters:
|
|
|
|
c (sqlite.db.cursor): SQL cursor of database to query.
|
|
|
|
uuid (str): Unique id of habit to query for.
|
|
|
|
Returns:
|
|
|
|
id (int): SQLite internal id for habit queried for.
|
|
|
|
"""
|
2021-08-29 09:11:58 +00:00
|
|
|
c.execute("select id from Habits where uuid = ?", ([uuid]))
|
|
|
|
id = c.fetchone()
|
|
|
|
if id is not None:
|
|
|
|
return id[0]
|
2021-08-28 21:03:12 +00:00
|
|
|
|
|
|
|
|
2021-08-29 08:13:28 +00:00
|
|
|
def add_to_database(cursor, habit_id, timestamp, value=2):
|
|
|
|
try:
|
|
|
|
cursor.execute(
|
|
|
|
"""
|
|
|
|
INSERT INTO
|
|
|
|
Repetitions(id, habit, timestamp, value)
|
|
|
|
VALUES (NULL, ?, ?, ?)
|
|
|
|
""",
|
|
|
|
(habit_id, timestamp, value),
|
|
|
|
)
|
|
|
|
except sqlite3.IntegrityError:
|
|
|
|
# TODO better error handling
|
2021-08-30 08:39:07 +00:00
|
|
|
print(f"fail to register {habit_id}: timestamp {timestamp} not unique")
|