Database design and implementation - VilleKylmamaa/WorkoutLogAPI GitHub Wiki
📑 Chapter summary
In this section students must design and implement the database structure (mainly the data model).In this section you must implement:
- The database table structure.
- The data models (ORM)
- Data models access methods (if needed)
- Populating the database using the models you have created
- A simple testing showing that your ORM works as expected
- Understand database basics
- Understand how to use ORM to create database schema and populate a database
- Setup and configure database
- Implement database backend
- Write tests
✔️ Chapter evaluation (max 9 points)
You can get a maximum of 9 points after completing this section. More detailed evaluation is provided after each heading.📑 Content that must be included in the section
Describe your database. The documentation must include:- A name and a short description of each database model. Describe in one or two sentences what the model represents.
- An enumeration of the attributes (columns) of each model. Each attribute must include:
- Its type and restrictions (values that can take)
- A short description of the attribute whenever the name is not explicit enough. E.g. If you are describing the users of a "forum", it is not necessary to explain the attributes "name", "surname" or "address" because their meanings are obvious.
- Characteristics of this attribute (e.g. if it is unique, if it contains default values)
- Connection with other models (primary keys and foreign keys)
- Other keys
For this section you can use a visual tool to generate a diagram. Be sure that the digram contains all the information provided in the models. Some tools you can use include: https://dbdesigner.net/, https://www.lucidchart.com/pages/tour/ER_diagram_tool, https://dbdiffo.com/
✔️ Evaluation criteria(max 3.25 points)
You can get a maximum of 3.25 points after completing this section.- Design of database is coherent: 1.0
- Each model and its attributes are named: 0.5
- Details for attributes are provided (datatype, default value, characteristics etc.): 0.5
- Foreign keys follow the relationship diagram from deadline 1: 0.75
✏️ The table can have the following structure
Workout represents a workout session. For example, a strength training session in the gym or a cardio session of sprinting on the track.
Name | Type | Restrictions | Description | Characteristics | Links |
---|---|---|---|---|---|
Name of the attribute | Attribute type | Values that the type can take | Description of the attribute | Uniqueness, default... | keys and foreign keys |
id | Integer | has to be integer, generates automatically | id is used as primary key | unique, non-nullable | primary key |
date_time | DateTime | Python datetime.datetime() object | date and time of the workout | unique, non-nullable | none |
duration | Interval | Python datetime.timedelta() object | duration of the workout | nullable | none |
body_weight | Float | any number, integer gets automatically converted to float | body weight on the day of the workout | nullable | none |
average_heart_rate | Integer | has to be integer | average heart rate measured during the workout | nullable | none |
max_heart_rate | Integer | has to be integer | max heart rate measured during the workout | nullable | none |
notes | String | any string with max length of 1000 characters | any additional notes about the workout | nullable | none |
Exercise represents physical activity intended to improve fitness. For example squat, bench press, deadlift, running, cycling, etc. This model doesn't have many attributes itself because lots of data is tied to it through relationships. exercise_name is unique as for example an entry for "Bench Press" is supposed to gather all the information through relationships about all the workout sessions "Bench Press" has been trained in, all the max data for it, etc.
Name | Type | Restrictions | Description | Characteristics | Links |
---|---|---|---|---|---|
Name of the attribute | Attribute type | Values that the type can take | Description of the attribute | Uniqueness, default... | keys and foreign keys |
id | Integer | has to be integer, generates automatically | id is used as primary key | unique, non-nullable | primary key |
exercise_name | String | any string with minimum length of 1 and max length of 100 characters | name of the exercise | unique, non-nullable | none |
exercise_type | String | any string with max length of 100 characters | type of the exercise, could be used to differentiate between main lifts and variation/supplementary lifts, or between lifting and cardio | nullable | none |
Set represents a set done in a certain workout for a certain exercise. The attributes are flexible with being nullable so that the model can be used for both lifting and cardio exercises. For example, a set of 100kg squats for 8 reps, or a set of sprinting for 100 meters.
Name | Type | Restrictions | Description | Characteristics | Links |
---|---|---|---|---|---|
Name of the attribute | Attribute type | Values that the type can take | Description of the attribute | Uniqueness, default... | keys and foreign keys |
id | Integer | has to be integer, generates automatically | used as primary key | unique, non-nullable | primary key |
exercise_id | Integer | has to be integer, generates automatically | foreign key to the exercise which the set was done for | non-nullable | foreign key to Exercise.id |
workout_id | Integer | has to be integer, generates automatically | foreign key to the workout the set was done in | non-nullable | foreign key to Workout.workout_id |
weight | Float | any number, integer gets automatically converted to float | weight used for the set | nullable | none |
number_of_reps | Integer | has to be integer | amount of repetitions achieved in the set | nullable | none |
reps_in_reserve | Integer | has to be integer | amount of repetitions that could still have been done after the termination of the set, i.e. left in reserve | nullable | none |
rate_of_perceived_exertion | Float | any number, integer gets automatically converted to float | rate of perceived exertion (RPE) for the set | nullable | none |
duration | Interval | Python datetime.timedelta() object | duration of the set | nullable | none |
distance | Float | any number, integer gets automatically converted to float | distance traveled during the set | nullable | none |
MaxData represents max data for a certain exercise. Max data can be either training max, estimated max and tested max data which are used for a training program or to track progress over time. For example, a trainee's tested max for deadlift could be 180kg while the estimated max is 190kg and training max is 170kg.
Name | Type | Restrictions | Description | Characteristics | Links |
---|---|---|---|---|---|
Name of the attribute | Attribute type | Values that the type can take | Description of the attribute | Uniqueness, default... | keys and foreign keys |
id | Integer | has to be integer, generates automatically | used as primary key | unique, non-nullable | primary key |
exercise_id | Integer | has to be integer, generates automatically | used as foreign key | foreign key | foreign key to Exercise.id |
order_for_exercise | Integer | has to be integer | order of the max data for the exercise | non-nullable | none |
date | Date | Python datetime.date() object | date of the max data | non-nullable | none |
training_max | Float | any number, integer gets automatically converted to float | training max is something used for training programming that might not even try to resemble a tested max | nullable | none |
estimated_max | Float | any number, integer gets automatically converted to float | estimated max is an approximation of tested max which has been calculated from a hard set with a formula | nullable | none |
tested_max | Float | any number, integer gets automatically converted to float | tested max is an actual max, the heaviest weight the trainee has lifted | nullable | none |
WeeklyProgramming represents workout programming data used for a week of training. It helps incorporate training programs into clients. The attributes are flexible with being nullable so that the model can be used for programming both lifting and cardio exercises, and different types of programming.
Name | Type | Restrictions | Description | Characteristics | Links |
---|---|---|---|---|---|
Name of the attribute | Attribute type | Values that the type can take | Description of the attribute | Uniqueness, default... | keys and foreign keys |
id | Integer | has to be integer, generates automatically | used as primary key | unique, non-nullable | primary key |
week_number | Integer | has to be integer | the week number for which week the programming data is for, usually 1 means first week of the program | non-nullable | none |
exercise_type | String | any string with max length of 100 characters | type of the exercise which the programming is for, could be used to differentiate between main lifts and variation/supplementary lifts | non-nullable | none |
intensity | Float | any number, integer gets automatically converted to float | prescribed intensity of the exercise, which is usually given as the percentage of a training/estimated/tested max, determines the weight that should be used | nullable | none |
number_of_sets | Integer | has to be integer | prescribed number of sets | nullable | none |
number_of_reps | Integer | has to be integer | prescribed number of repetitions | nullable | none |
reps_in_reserve | Integer | has to be integer | prescribed number of repetitions that should be left in reserve during a set | nullable | none |
rate_of_perceived_exertion | Float | any number, integer gets automatically converted to float | Prescribed rate of perceived exertion (RPE) for the sets | nullable | none |
duration | Interval | Python datetime.timedelta() object | prescribed duration of a set or the whole workout, mainly for cardio | nullable | none |
distance | Float | any number, integer gets automatically converted to float | prescribed distance traveled during a set or the whole workout, mainly for cardio | nullable | none |
average_heart_rate | Integer | any number, integer gets automatically converted to float | prescribed average heart rate during a set or the whole workout, mainly for cardio | nullable | none |
notes | String | any string with max length of 1000 characters | any additional notes for the programming | nullable | none |
Name | Type | Restrictions | Description | Characteristics | Links |
---|---|---|---|---|---|
Name of the attribute | Attribute type | Values that the type can take | Description of the attribute | Uniqueness, default... | keys and foreign keys |
exercise_id | Integer | has to be integer, generates automatically | used as foreign key | non-nullable | Foreign key to Exercise.id |
workout_id | Integer | has to be integer, generates automatically | used as foreign key | non-nullable | Foreign key to Workout.workout_id |
Name | Type | Restrictions | Description | Characteristics | Links |
---|---|---|---|---|---|
Name of the attribute | Attribute type | Values that the type can take | Description of the attribute | Uniqueness, default... | keys and foreign keys |
exercise_id | Integer | has to be integer, generates automatically | used as foreign key | non-nullable | Foreign key to Exercise.id |
weekly_programming_id | Integer | has to be integer, generates automatically | used as foreign key | non-nullable | Foreign key to WeeklyProgramming.id |
✏️ Do not forget to include a diagram presenting the relations
Database diagram was made using dbdesigner. Many-to-many relationships are represented by association tables.
💻 TODO: SOFTWARE TO DELIVER IN THIS SECTION
The code repository must contain:- The ORM models and functions
- A .sql dump of a database or the .db file (if you are using SQlite). You must provide a populated database in order to test your models.
- The scripts used to generate your database (if any)
- If you are using python, the requirements.txt file.
- A README.md file containing:
- All dependencies (external libraries) and how to install them
- Define database (MySQL, SQLite, MariaDB, MongoDB...) and version utilized
- Instructions how to setup the database framework and external libraries you might have used, or a link where it is clearly explained.
- Instructions on how to setup and populate the database.
- Instruction on how to run the tests of your database.
- If you are using python a `requirements.txt` with the dependencies
NOTE: Your code MUST be clearly documented. Check Exercise 1 for examples on how to document the code.
In addition, it should be clear which is the code you have implemented yourself and which is the code that you have borrowed from other sources.
✔️ Evaluation criteria(max 3.25 points)
- Instructions to set up the database and run the tests are provided in the README.md file: 0.5
- this means there should be no undocumented extra steps in running the code/tests!
- All properties of the table in the previous section are implemented correctly in the model (using correct types...): 0.75
- All Relations are correctly implemented (0.25 if 1 or 2 minor errors, 0 otherwise): 0.5
- The naming of the attributes and relations are self-descriptive and additional functions for the models (if any) are correctly documented (input/output): 0.75
- All models from design tables are implemented. All implemented models appear in the design tables: 0.75
✏️ You do not need to write anything in this section, just complete the implementation.
💻 Software that must be included in the section
In this course, showing that your code works is primarily your responsibility. Therefore we expect test cases that show that all of your methods work not just with correct parameters, but that they also handle error situations correctly. Tests should always cover the most common error scenarios that are easy to predict (e.g.foreign keys violations work correctly)
You should follow the testing methodologies shown in Exercise 1.
Some guidelines for the testing:
- The code of the test MUST be commented indicating what are you testing in each case.
- For each model the test script should, at least:
- Create a new instance of the model
- Retrieve an existing instance of the model (recommended trying with different filter options)
- Update an existing model instance (if update operation is supported by this model)
- Remove an existing model from the database
- Test that onModify and onDelete work as expected
- Test possible errors conditions (e.g. foreign keys violation or other situation where Integrity error might be raised)
✔️ Evaluation criteria(max 2.5 points)
In this section you can get a maximum of 2.5 points.- Methods in the test are correctly documented (functionality of each method): 1(0.25 if not all covered / 0 if just a few are covered)
- Each model is tested with each one of the 4 CRUD operations (create, read, update and delete). Ondelete and onModify behaviour should also be tested: 1.0 (0.75 if few operations missing. 0.5 if one model not tested. 0 if more than one model not tested).
- In order to get full points, all CRUD methods should be tested for each model. For each model the script should, at least:
- Create a new instance of the model
- Retrieve an existing instance of the model (recommended trying with different filter options)
- Update an existing model instance (if update operation is supported by this model)
- Remove an existing model instance from the database
- Additionally onModify and onDelete should be tested
- In order to get full points, all CRUD methods should be tested for each model. For each model the script should, at least:
- Test cases includes possible error situation (e.g. foreign key violation): 0.5
- Tests run correctly: 0.5
- The model implementation do not have errors. Note that course staff might do additional tests : 0.5
✏️ You do not need to write anything here. Just complete the implementation
Task | Student | Estimated time |
---|---|---|
All | Ville Kylmämaa | 20h |