{"id":20236131,"url":"https://github.com/itsvaibhavk/swimlog","last_synced_at":"2026-05-10T11:44:58.039Z","repository":{"id":200750117,"uuid":"706045672","full_name":"ItsVaibhavK/SwimLog","owner":"ItsVaibhavK","description":"Add, store, view and modify data from swimming sessions using Python and SQLite3. Final project submission for CS50P (2023), Harvard's online course on programming with Python (on the edX platform).","archived":false,"fork":false,"pushed_at":"2024-01-08T09:58:47.000Z","size":26,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-01-14T00:47:38.417Z","etag":null,"topics":["cs50p","database","edx","project","python","sqlite3"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ItsVaibhavK.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-10-17T07:47:14.000Z","updated_at":"2023-10-17T11:30:55.000Z","dependencies_parsed_at":null,"dependency_job_id":"301f6111-1cf3-4e38-8d29-a23fc859d9b8","html_url":"https://github.com/ItsVaibhavK/SwimLog","commit_stats":null,"previous_names":["itsvaibhavk/swimlog"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ItsVaibhavK%2FSwimLog","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ItsVaibhavK%2FSwimLog/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ItsVaibhavK%2FSwimLog/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ItsVaibhavK%2FSwimLog/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ItsVaibhavK","download_url":"https://codeload.github.com/ItsVaibhavK/SwimLog/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":241679492,"owners_count":20001968,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cs50p","database","edx","project","python","sqlite3"],"created_at":"2024-11-14T08:19:14.029Z","updated_at":"2026-05-10T11:44:57.992Z","avatar_url":"https://github.com/ItsVaibhavK.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# SWIM LOG\n[Demo video on YouTube](https://youtu.be/HS2XvBuTUpQ)\n## IDEA BEHIND SWIM LOG\nAs a person who swims fairly regularly for exercise, I wanted to track my basic swimming data, like:\n- Distance swam in a session\n- Pool length\n- Duration of a session\n\nAnd to be able to analyze the data, with parameters such as:\n- Total distance swam\n- Total time spent swimming\n- Average distance swam per session\n- Average duration of a session\n\nBefore I decided to turn this idea into my final project for [CS50P](https://cs50.harvard.edu/python/2022/), I was trying out various swim-tracking apps on my phone,\u003cbr\u003ebut they were all invariably too cluttered for my taste. More often than not, it was about pushing the user to sign up for swimming lessons,\u003cbr\u003eor to connect a smart watch that would share your swimming session data to the app for you.\n\nMost of the apps had the option to manually update your swimming session data, but it was almost always without fail locked behind a paywall.\u003cbr\u003eThis is what ultimately led me to utilize what I have been learning through [CS50P](https://cs50.harvard.edu/python/2022/) and [CS50X](https://cs50.harvard.edu/x/2023/) and create a Python program\u003cbr\u003eto allow me to\nlog/track the data from my swimming sessions.\n\n## HOW SWIM LOG WORKS\n### Libraries used:\n- **cs50** - Using `from cs50 import SQL` enables the program to talk to the SQLite3 database, so that SQL queries can be executed within Python code.\n\n- **pyfiglet** and **random** - I wanted the title of the program to appear in a _fun different_ font each time it was executed.\u003cbr\u003eI utilized `from pyfiglet import Figlet` and `import random` to render the title in different fonts on each iteration.\n\n- **tabulate** - For the option(s) that involved viewing existing data, I needed a way to print the data in a readable format.\u003cbr\u003e`from tabulate import tabulate` was used to meet this goal.\n\n- **time** - The output was flying by a little too fast for my taste, so I added `time.sleep(1)` at various points in the code to allow time to read,\u003cbr\u003eor at least grasp the fact that the output was on the screen.\n\n- **sys** - `sys.exit()` is what is run when the user decides to end the program.\n\n### Schema for data table:\nThis was the **SQL command** run to create the data table:\n\nCREATE TABLE swim_data (\u003cbr\u003esession INTEGER PRIMARY KEY AUTOINCREMENT,\u003cbr\u003edate DATETIME DEFAULT CURRENT_TIMESTAMP,\u003cbr\u003edistance INTEGER NOT NULL,\u003cbr\u003epool INTEGER NOT NULL,\u003cbr\u003eduration INTEGER NOT NULL\u003cbr\u003e);\n\n### Flow (menus, and the loops and conditionals behind them):\nThere are three menus that the user can navigate:\n1. **Menu 1 (Main menu)** - Add new data, view/analyze existing data, modify existing data, or end the program.\n\n2. **Menu 2** - Multiple options to view existing data, or to go back to **Menu 1**.\n\n3. **Menu 3** - Choose what aspect of existing data is to be modified, or to go back to **Menu 1**.\n\nAll the menus are infinite-looped, allowing the user to accomplish multiple tasks at a time without having to navigate through the program from the beginning each time.\u003cbr\u003eWhen the program is run, the user is presented with **Menu 1**.\n\n#### MENU 1 (MAIN MENU)\n---\n**Menu 1** presents the user with the following options:\n1. Enter new data.\n2. View existing data.\n3. Modify existing data.\n4. End program.\n\nThe user is asked to input the option number corresponding to the task they wish to accomplish.\u003cbr\u003eUser input is validated using a `try-except` block, and `if-elif-else` conditionals.\n\nIf the user chooses to \"Enter new data\", `new_swim_data()` is called and the user is asked to input the various parameters of their swimming session.\u003cbr\u003eUser input is further validated using `valid(n)`, and if the data checks out, the database is updated by the function `db_update(distance, pool, duration)`.\n\nIf the user chooses to \"View existing data\", or \"Modify existing data\", since both the options require that there should _be_ existing data,\u003cbr\u003e`db_check()` is called first to prevent errors that would arise from an empty database.\u003cbr\u003eIf the database is not empty, the user is presented with further options. If the database is _empty_, the user is asked to add data first, and they are redirected back to **Menu 1**.\n\nIf the user chooses to \"End program\", `sys.exit()` is used to terminate the program.\n\n#### MENU 2\n---\nIf the user chooses to \"View existing data\", the program proceeds to present **Menu 2**:\n1. View data table.\n2. Total distance swam.\n3. Total time spent swimming.\n4. Average distance swam per session.\n5. Average time spent swimming per session.\n6. Go back to main menu.\n\nThe user is asked to input the option number corresponding to the task they wish to accomplish.\u003cbr\u003eUser input is validated using a `try-except` block, and `if-elif-else` conditionals. Here is how each option works:\n1. View data table - `db_read()` is called to execute a SQL query, and existing data is outputted as a table using the `tabulate` library.\n\n2. Total distance swam - `total_distance()` is called, the corresponding SQL query is executed to acquire the required data.\u003cbr\u003eIf the total distance is less than 1 kilometer, the output is displayed in meters. If the total distance is greater than or equal to 1 kilometer, the output is displayed in kilometers.\n\n3. Total time spent swimming - `total_time()` is called, the corresponding SQL query is executed to acquire the required data.\u003cbr\u003eIf the total time is less than 1 hour, the output is displayed in minutes. If the total time is greater than or equal to 1 hour, the output is displayed in hours and minutes.\n\n4. Average distance swam per session - `average_distance()` is called, the corresponding SQL query is executed to acquire the required data.\u003cbr\u003eIf the average distance is less than 1 kilometer, the output is displayed in meters.\u003cbr\u003eIf the average distance is greater than or equal to 1 kilometer, the output is displayed in kilometers.\n\n5. Average time spent swimming per session - `average_time()` is called, the corresponding SQL query is executed to acquire the required data.\u003cbr\u003eIf the average time is less than 1 hour, the output is displayed in minutes. If the average time is greater than or equal to 1 hour, the output is displayed in hours and minutes.\n\n(_Note:_ For the average distance/time options, the **session** column from the table **swim_data** is used to calculate the number of entries made,\u003cbr\u003ewhere each entry corresponds to one session. The **session** \"number\" or \"ID\" itself is not looked at to calculate the averages.)\n\n6. Go back to main menu - `break` is used to end the **Menu 2** loop and take the user back to **Menu 1**.\n\n#### MENU 3\n---\nIf the user chooses to \"Modify existing data\", first, `modify_data()` is called and the existing data is displayed to the user by utilizing the `db_read()` function.\u003cbr\u003eThe user is then asked to enter the **session number** of the session whose data they wish to change. This particular input from the user is validated by\u003cbr\u003eretrieving session numbers/IDs from the **session** column of the **swim_data** table and storing them in a list. Using an `if-else` condition,\u003cbr\u003ethe user's input is checked against the same list. If user input is valid, the program proceeds further. If user input is not found in the list of **session** IDs,\u003cbr\u003ean error message appears and the user is prompted (infinitely) to enter a valid session number.\n\nOnce the user inputs a valid **session** number, they are presented with **Menu 3**, where they are asked to input the option number corresponding to the _data_ they wish to _modify_.\u003cbr\u003eUser input is validated using a `try-except` block, and `if-elif-else` conditionals:\n1. Distance.\n2. Pool length.\n3. Duration.\n4. Go back to main menu.\n\nDepending on the option that is selected, user input (the new data to replace the old/incorrect data) is first validated by calling `valid(n)`,\u003cbr\u003efollowing which that particular aspect of the selected **session** is updated in the database using a SQL query.\n\nIf option \"4. Go back to main menu\" is selected, `break` is used to end the **Menu 3** loop and take the user back to **Menu 1**.\n\n## DESIGN THOUGHTS AND FUTURE IDEAS:\n1. Each menu is infinite-looped so that the user can go through multiple options on a single execution of the program.\n\n2. Error messages due to invalid inputs also loop infintely, reprompting the user to cooperate until they provide a valid input.\n\n3. Using `random` and `pyfiglet` to render the title in a different font on each execution of the program was for personal amusement.\n\n4. Distance covered in a session, pool length, and the duration of a session are the current parameters that are the focus of Swim Log\u003cbr\u003esince these are the main parameters I care about for my personal data. I would, however, like to also consider adding parameters\u003cbr\u003esuch as number of laps and swim pace in a future version.\n\n5. The program currently only stores/calculates distance data under the metric system. An idea for a future version of Swim Log could be\u003cbr\u003eto provide the option of selecting what system of measurement the user would like to implement.\n\n6. Currently, the date/timestamp data is not used in any way apart from a form of record-keeping.\u003cbr\u003eUtilizing the date/timestamp data to see milestones like start date, year, etc. can also be considered.\n\n## CREDITS, CONCLUSION:\nI cannot express my gratitude and admiration of the staff and team at CS50 enough for sharing their knowledge with students like me,\u003cbr\u003eand for their time, effort and dedication behind the plethora of courses offered by Harvard's CS50 on [edX.](https://www.edx.org/) I went from not knowing anything about programming at all\u003cbr\u003eto writing my own programs and web apps in these last few months.\u003cbr\u003eThank you from the bottom of my heart for instilling in me the love of all things programming!\n\n_To quote [Professor Malan](https://cs.harvard.edu/malan/):_\n\u003e This was CS50!\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fitsvaibhavk%2Fswimlog","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fitsvaibhavk%2Fswimlog","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fitsvaibhavk%2Fswimlog/lists"}