wger-project / wger

Self hosted FLOSS fitness/workout, nutrition and weight tracker
https://wger.de
GNU Affero General Public License v3.0
3.04k stars 568 forks source link

Dynamic measurements #1560

Open rolandgeider opened 7 months ago

rolandgeider commented 7 months ago

Add the possibility to create dynamic measurements that are calcualted based on other entries. For example, a 1RM calculated value for squats from the logged values or the BMI.

How exactly this would be configured needs to be discussed first, config file, small python module, etc. since we might want some logic there (in the 1RM example, we might only want to take into account sets with 5 reps or less, or just take the entry with the highest weight for a specific day)

adrianlzt commented 7 months ago

First POC: https://github.com/adrianlzt/wger/tree/feature/dynamic_measurements https://github.com/adrianlzt/wger-react/tree/feature/dynamic_measurements

Add a new field to the category to be able to insert python code. That python code is executed in a limited python interpreter in the backend. The example python code attached to the editor as a snippet calculate a new measurement based on another measurement and the weight of that they.

https://github.com/wger-project/wger/assets/3237784/1c91f773-30f6-43f7-b84f-f67f3217c3ef

rolandgeider commented 7 months ago

oh, this is nice! Hadn't heard of RestrictedPython before. I also like that we can just define some helper functions like "get_weight_by_date" that would then just be available (but we need to be careful and make sure that we only retrieve the user's data, right now we return any weight entry for that day, but it's just a proof of concept, so it's ok)

rolandgeider commented 7 months ago

We could also think about saving a couple that most people would find useful and allow the users to just select it (like BMI, 1RM for the big three, etc)

BMI = m / height^2 where m is the mass in kg and the height in cm For the 1RM formula, there are a couple: https://en.wikipedia.org/wiki/One-repetition_maximum

We should also cache the results since depending on what we do, we might have to hit the DB a lot. We can either indefinitely cache this till a new entry is saved or add a new (long lived key) similar to EXERCISE_CACHE_TTL. We can simply cache the whole response like in ExerciseBaseInfoSerializer