diff --git a/client/data/README.md b/client/data/README.md new file mode 100644 index 0000000..b66b6ef --- /dev/null +++ b/client/data/README.md @@ -0,0 +1,6 @@ +## Interactively opening DB +From this directory. +```bash +sqlite3 resources/database.db +``` +You can then run SQL commands in the terminal. \ No newline at end of file diff --git a/client/data/routines.py b/client/data/routines.py index 0a4ff17..2c1e8cd 100644 --- a/client/data/routines.py +++ b/client/data/routines.py @@ -123,6 +123,52 @@ def get_postures(num: int = 10) -> list[Posture]: return [Posture(*record) for record in result.fetchall()] +def get_user_postures( + user_id: int, + num: int = -1, + period_start: Optional[datetime] = None, + period_end: Optional[datetime] = None, +) -> list[Posture]: + """ + Args: + user_id: Id of user to get postures for. + num: Number of posture records to retrieve. Set to -1 to retrieve all records. + period_start: Only posture records starting at or after this timestamp will be retrieved. + Leave as None to set no restriction. + period_end: Only posture records ending at or before this timestamp will be retrieved. + Leave as None to set no restriction. + + Returns: + num posture records from the database for the specified user. Retrieves latest inserted + posture records first. + """ + params: tuple[int | datetime, ...] = (user_id,) + + # Add limit to query + limit = "" + if num != -1: + limit = " LIMIT ?" + params = (num,) + params + + # Add period to query + query_period = "" + if period_start is not None: + query_period += " AND DATETIME(period_start) >= DATETIME(?)" + params += (period_start,) + if period_end is not None: + query_period += " AND DATETIME(period_end) <= DATETIME(?)" + params += (period_end,) + + query = ( + f"SELECT * FROM posture{limit} WHERE user_id = ?{query_period} ORDER BY id DESC" + ) + + with _connect() as connection: + cursor = connection.cursor() + result = cursor.execute(query, params) + return [Posture(*record) for record in result.fetchall()] + + def get_schema_info() -> list[list[tuple[Any]]]: """Column information on all tables in database. diff --git a/notebooks/test-database-tools.ipynb b/notebooks/test-database-tools.ipynb index 4c70ad6..8153cd9 100644 --- a/notebooks/test-database-tools.ipynb +++ b/notebooks/test-database-tools.ipynb @@ -2,18 +2,9 @@ "cells": [ { "cell_type": "code", - "execution_count": 18, + "execution_count": 1, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "The autoreload extension is already loaded. To reload it, use:\n", - " %reload_ext autoreload\n" - ] - } - ], + "outputs": [], "source": [ "%load_ext autoreload\n", "%autoreload 2" @@ -21,7 +12,7 @@ }, { "cell_type": "code", - "execution_count": 19, + "execution_count": 2, "metadata": {}, "outputs": [], "source": [ @@ -34,13 +25,14 @@ " save_posture,\n", " get_users,\n", " get_postures,\n", + " get_user_postures,\n", " Posture,\n", ")" ] }, { "cell_type": "code", - "execution_count": 20, + "execution_count": 8, "metadata": {}, "outputs": [], "source": [ @@ -49,7 +41,7 @@ }, { "cell_type": "code", - "execution_count": 21, + "execution_count": 9, "metadata": {}, "outputs": [ { @@ -65,7 +57,7 @@ " [(0, 'id', 'INTEGER', 0, None, 1)]]" ] }, - "execution_count": 21, + "execution_count": 9, "metadata": {}, "output_type": "execute_result" } @@ -76,16 +68,16 @@ }, { "cell_type": "code", - "execution_count": 22, + "execution_count": 6, "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "3" + "5" ] }, - "execution_count": 22, + "execution_count": 6, "metadata": {}, "output_type": "execute_result" } @@ -96,16 +88,16 @@ }, { "cell_type": "code", - "execution_count": 23, + "execution_count": 10, "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "[User(id_=1), User(id_=2), User(id_=3)]" + "[User(id_=1), User(id_=2), User(id_=3), User(id_=4), User(id_=5)]" ] }, - "execution_count": 23, + "execution_count": 10, "metadata": {}, "output_type": "execute_result" } @@ -116,7 +108,7 @@ }, { "cell_type": "code", - "execution_count": 24, + "execution_count": 8, "metadata": {}, "outputs": [], "source": [ @@ -129,7 +121,7 @@ }, { "cell_type": "code", - "execution_count": 25, + "execution_count": 11, "metadata": {}, "outputs": [ { @@ -138,10 +130,12 @@ "[Posture(id_=1, user_id=1, prop_good=0.8, prop_in_frame=1.0, period_start=datetime.datetime(2024, 8, 18, 17, 40, 44, 458720), period_end=datetime.datetime(2024, 8, 18, 17, 40, 45, 462898)),\n", " Posture(id_=2, user_id=1, prop_good=0.8, prop_in_frame=1.0, period_start=datetime.datetime(2024, 8, 18, 17, 41, 46, 12187), period_end=datetime.datetime(2024, 8, 18, 17, 41, 47, 13719)),\n", " Posture(id_=3, user_id=1, prop_good=0.8, prop_in_frame=1.0, period_start=datetime.datetime(2024, 8, 18, 17, 46, 2, 389947), period_end=datetime.datetime(2024, 8, 18, 17, 46, 3, 402225)),\n", - " Posture(id_=4, user_id=1, prop_good=0.8, prop_in_frame=1.0, period_start=datetime.datetime(2024, 8, 18, 17, 48, 16, 460303), period_end=datetime.datetime(2024, 8, 18, 17, 48, 17, 466763))]" + " Posture(id_=4, user_id=1, prop_good=0.8, prop_in_frame=1.0, period_start=datetime.datetime(2024, 8, 18, 17, 48, 16, 460303), period_end=datetime.datetime(2024, 8, 18, 17, 48, 17, 466763)),\n", + " Posture(id_=5, user_id=1, prop_good=0.8, prop_in_frame=1.0, period_start=datetime.datetime(2024, 8, 20, 11, 2, 10, 540731), period_end=datetime.datetime(2024, 8, 20, 11, 2, 11, 543301)),\n", + " Posture(id_=6, user_id=1, prop_good=0.8, prop_in_frame=1.0, period_start=datetime.datetime(2024, 8, 20, 11, 9, 13, 157727), period_end=datetime.datetime(2024, 8, 20, 11, 9, 14, 172205))]" ] }, - "execution_count": 25, + "execution_count": 11, "metadata": {}, "output_type": "execute_result" } @@ -150,6 +144,56 @@ "get_postures(num=10)" ] }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[Posture(id_=6, user_id=1, prop_good=0.8, prop_in_frame=1.0, period_start=datetime.datetime(2024, 8, 20, 11, 9, 13, 157727), period_end=datetime.datetime(2024, 8, 20, 11, 9, 14, 172205)),\n", + " Posture(id_=5, user_id=1, prop_good=0.8, prop_in_frame=1.0, period_start=datetime.datetime(2024, 8, 20, 11, 2, 10, 540731), period_end=datetime.datetime(2024, 8, 20, 11, 2, 11, 543301)),\n", + " Posture(id_=4, user_id=1, prop_good=0.8, prop_in_frame=1.0, period_start=datetime.datetime(2024, 8, 18, 17, 48, 16, 460303), period_end=datetime.datetime(2024, 8, 18, 17, 48, 17, 466763)),\n", + " Posture(id_=3, user_id=1, prop_good=0.8, prop_in_frame=1.0, period_start=datetime.datetime(2024, 8, 18, 17, 46, 2, 389947), period_end=datetime.datetime(2024, 8, 18, 17, 46, 3, 402225)),\n", + " Posture(id_=2, user_id=1, prop_good=0.8, prop_in_frame=1.0, period_start=datetime.datetime(2024, 8, 18, 17, 41, 46, 12187), period_end=datetime.datetime(2024, 8, 18, 17, 41, 47, 13719)),\n", + " Posture(id_=1, user_id=1, prop_good=0.8, prop_in_frame=1.0, period_start=datetime.datetime(2024, 8, 18, 17, 40, 44, 458720), period_end=datetime.datetime(2024, 8, 18, 17, 40, 45, 462898))]" + ] + }, + "execution_count": 12, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "get_user_postures(1)" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[Posture(id_=4, user_id=1, prop_good=0.8, prop_in_frame=1.0, period_start=datetime.datetime(2024, 8, 18, 17, 48, 16, 460303), period_end=datetime.datetime(2024, 8, 18, 17, 48, 17, 466763)),\n", + " Posture(id_=3, user_id=1, prop_good=0.8, prop_in_frame=1.0, period_start=datetime.datetime(2024, 8, 18, 17, 46, 2, 389947), period_end=datetime.datetime(2024, 8, 18, 17, 46, 3, 402225))]" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "get_user_postures(\n", + " 1,\n", + " period_start=datetime(2024, 8, 18, 17, 46, 2, 389947),\n", + " period_end=datetime(2024, 8, 20, 11, 2, 10, 540731),\n", + ")" + ] + }, { "cell_type": "code", "execution_count": null,