FitTrackee icon indicating copy to clipboard operation
FitTrackee copied to clipboard

Feature request: "Equipment" that can be associated with workouts

Open jat255 opened this issue 2 years ago • 4 comments

Some proprietary tools have a concept of "gear" or "equipment" that gets saved alongside a workout:

image

The nice feature with this is it allows you to keep track of how many miles, minutes, etc. you have put on a piece of equipment (useful for runners that swap out shoes every X miles or something). A similar feature in FitTrackee could be nice to have.

Implementation wise, it could probably look a lot like how "sports" are currently implemented, with a new DB table for pieces of equipment (each associated with a user), and then at upload time allowing for selecting of one (or more) pieces of associated equipment.

jat255 avatar Nov 04 '22 20:11 jat255

I've started working on this in my equipment_for_workouts branch

jat255 avatar Nov 08 '22 17:11 jat255

Hi,

I had the same feature in mind (I have 3 bikes) and planned to work on it with workouts improvements (v0.9.x, I am currently working on v0.8.x when I have some free time).

This feature may have some impacts, is it possible to discuss the changes before (to avoid unnecessary work and plan it in a version)? Thanks in advance.

SamR1 avatar Nov 10 '22 08:11 SamR1

Sure, it's a bit more involved of a feature so it's good to make sure what I'm working on will mesh with your vision.

As for overall design, I've started working on a model of Equipment specific to individual users that can be in a many-to-many relationship to a user's workouts:

image

Currently, this model sits in workouts/models.py, but I'm not sure if that's the best place, since it's also kind of a user setting:

Equipment model:
EquipmentWorkout = db.Table(
    'equipment_workout',
    db.Column(
        'equipment_id',
        db.Integer,
        db.ForeignKey('equipment.id'),
        primary_key=True,
    ),
    db.Column(
        'workout_id',
        db.Integer,
        db.ForeignKey('workouts.id'),
        primary_key=True,
    ),
)

class Equipment(BaseModel):
    __tablename__ = 'equipment'
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    user_id = db.Column(
        db.Integer, db.ForeignKey('users.id'), index=True, nullable=False
    )
    label = db.Column(db.String(50), unique=False, nullable=False)
    description = db.Column(db.String(200), default=None, nullable=True)
    creation_date = db.Column(db.DateTime, default=datetime.datetime.utcnow)
    is_active = db.Column(db.Boolean, default=True, nullable=False)
    workouts = db.relationship(
        'Workout', secondary=EquipmentWorkout, backref='equipment'
    )

I'm also trying to implement that in their sport preferences, a user can set a default piece of equipment to use for new activities if one is not provided at creation time.

I've got most of the basic CRUD API functionality working for that model, and have been working more recently on integrating it with the workout and user preference endpoints. One area where I'm a little uncertain is the distinction between what should be under the workouts and what should be under the profile scopes, since creating a new equipment is kind of both a user preference and a workout thing. Currently it's all under the workouts:read or workouts:write scope, but that can be changed.

I haven't started work on the front-end at all (wanted to nail down the API first).

As an aside, I'm using this as a bit of a learning opportunity, since I'm casually familiar with a number of the tools in the stack (Flask, SQLAlchemy, Vue even less so), but I haven't done more than some toy examples with them, and working on a real codebase is how I learn best. That being said, I don't want to make a lot more work for you to review stuff, so even if my work doesn't get committed as-is, hopefully you could use it as a base.

jat255 avatar Nov 10 '22 15:11 jat255

Hi!

Sorry for my late reply and thanks for the details.

The data model is close to what I had in mind.
Some quick feedback:

  • I agree, maybe the equipements table should be in users/models.py and depends on profile scope.
  • Equipement type should also be defined (bike, shoes...). And there are translations to handle on front side. When a user adds an equipement, he has to choose a type. For instance, I had in mind this kind of display: equipment
  • I try to write tests using TDD as much as possible on latest features (on some old code, the test coverage is not very good, I planned to work on this in v0.9.x with workout refactoring). Don't hesitate to add tests.

If you have any questions, you can also reach me on matrix: #fittrackee:matrix.org.

As I said above, I'm currently working on social features, that require a lot of changes and also impact workouts (that's why some features and major changes are pending, integrating new features delaying this part).

SamR1 avatar Nov 19 '22 08:11 SamR1

released in v0.8.0

SamR1 avatar Apr 21 '24 20:04 SamR1

for information, I made a script to add equipments to existing workouts: https://codeberg.org/SamR1/workouts-equipments-updater

SamR1 avatar Apr 21 '24 21:04 SamR1