Giter Site home page Giter Site logo

treiher / valens Goto Github PK

View Code? Open in Web Editor NEW
10.0 2.0 2.0 4.9 MB

An app for tracking your health and training progress.

License: GNU Affero General Public License v3.0

Python 37.75% Makefile 0.55% HTML 0.34% Mako 0.06% JavaScript 0.37% SCSS 0.46% Rust 60.47%
training workout log journal health bodyweight body-fat period workout-tracker workout-journal

valens's Introduction

Valens

/ˈva.lens/ [ˈväːlɛns] lat. strong, vigorous, healthy

App screenshots

Features

  • Track your training progress
    • Define training routines
    • Log repetitions, weight, time and rating of perceived exertion (RPE) for each set
    • Measure your training execution using a stopwatch, timer or metronome
    • Assess the progress for each routine and exercise
  • Keep track of your body weight
  • Calculate and log your body fat based on the 3-site or 7-site caliper method
  • Monitor your menstrual cycle (if you have one 😉)

Installation

The latest release can be installed from PyPI.

pip install valens

The latest development version can be installed from TestPyPI.

pip install --pre --index-url https://test.pypi.org/simple/ --extra-index-url https://pypi.org/simple/ valens

Demo Mode

To get a first impression of Valens, the app can be run in demo mode.

valens demo

The app can be accessed on http://127.0.0.1:5000/. A temporary database with random example data is used. All changes are non-persistent. Adding --public to the command line makes the app available to other devices on your network.

Configuration and Running

A configuration file must be created before running the app for the first time.

valens config

The environment variable VALENS_CONFIG must be set to the absolute path of the created config file.

Local Network

The development server can be used to provide the app for your local computer or local network.

VALENS_CONFIG=$PWD/config.py valens run

By default, the app is only accessible on your local computer at http://127.0.0.1:5000/. If you trust the users in your network, you can make the server publicly available adding --public to the command line:

VALENS_CONFIG=$PWD/config.py valens run --public

Public Network

The development server is not intended for production use. Please consider the deployment options for providing the app in a public network.

Example Configuration: NGINX and uWSGI

The following configuration binds the app to /valens.

/etc/uwsgi/valens.ini

[uwsgi]
master = true
plugins = python
socket = /run/uwsgi/%n.sock
manage-script-name = true
mount = /valens=valens.web:app
uid = http
gid = http
env = VALENS_CONFIG=/opt/valens/config.py

/etc/nginx/nginx.conf

[...]

http {

    [...]

    server {

        [...]

        gzip on;
        gzip_types text/plain test/css text/javascript application/json application/wasm;

        location = /valens { return 301 /valens/; }
        location /valens/ { try_files $uri @valens; }
        location @valens {
                include uwsgi_params;
                uwsgi_pass unix:/run/uwsgi/valens.sock;
        }

    }

}

NGINX compression is disabled by default. With compression enabled, the amount of data transferred can be significantly reduced, resulting in a reduction in transfer time, especially on slow networks.

Development

The following software is required:

Setting up the development environment

Add the WebAssembly target to the Rust toolchain.

$ rustup target add wasm32-unknown-unknown

Install the Rust development tools.

$ cargo install --locked trunk

Install the Python project and development tools.

$ poetry install

Running development servers

The current codebase can be executed by running development servers for the frontend and the backend. The development servers will automatically reload when the codebase is changed.

Start both development servers at the same time (requires an active tmux session):

$ make run

Alternatively, start the development servers for the frontend and the backend separately:

$ make run_frontend
$ make run_backend

After a successful start of the development servers, the web app can be reached on http://127.0.0.1:8000.

Building a distribution package

$ make dist

Deploying the application

Install Fabric.

$ poetry install --only=deploy

Deploy the latest distribution package.

$ fab -H user@host deploy

Changing the database schema

Create a migration script after changing the SQLAlchemy ORM model.

$ VALENS_CONFIG=$PWD/build/config.py alembic revision --autogenerate -m "Add foo table"

The automatically generated migration script may be incomplete.

Upgrade the database schema to the latest revision.

$ VALENS_CONFIG=$PWD/build/config.py alembic upgrade head

License

This project is licensed under the terms of the AGPL-3.0 license and includes third-party software.

valens's People

Contributors

dependabot[bot] avatar treiher avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

Forkers

xobs ranveer112

valens's Issues

Excercise does not advance automatically

I'm testing with 0.2.1.dev101 installed from TestPyPI. It's running on Debian 12 using Apache mod_wsgi.

When starting a training session using the "play" button, I can hear the metronome sound. However, after the configured amount of repetitions the first exercise remains active and the metronome beeps continue indefinitely. Clicking the double downwards arrows brings me to the following rest period which ends after the configured amount of seconds as expected. The following exercise does not advance automatically, either.

This happens on both, desktop (Gnome Web) and mobile (Fennec).

Screenshot from 2023-12-28 12-02-57

Analysis of period/menstrual cycle

Feature Specification

  • On the period page, the average cycle length, average period length and average cycle variation is shown.
  • On the period page, the cycle length, period length and cycle variation in the given interval are listed in a table.
  • On the home page, the period tile shows the predicted days till the next cycle begin.
  • A cycle begins with the first period entry after at least three days without entry.
  • The average cycle length is defined by the median.
  • The cycle variation is defined by the difference of the first and third quartile.
  • A distribution of the cycle length variation is depicted in a chart.

sqlalchemy exception on Debian 12

I installed valens using pip as described in the README:

$ python3.11 -m venv .venv
$ . .venv/bin/activate
$ pip install valens
[...]
Successfully installed Jinja2-3.1.2 Mako-1.3.0 MarkupSafe-2.1.3 Werkzeug-3.0.1 alembic-1.8.0 blinker-1.7.0 click-8.1.7 contourpy-1.2.0 cycler-0.12.1 flask-3.0.0 fonttools-4.4
7.0 greenlet-3.0.3 itsdangerous-2.1.2 kiwisolver-1.4.5 matplotlib-3.8.2 mypy-1.8.0 mypy-extensions-1.0.0 numpy-1.26.2 packaging-23.2 pandas-2.1.4 pillow-10.1.0 pyparsing-3.1.
1 python-dateutil-2.8.2 pytz-2023.3.post1 six-1.16.0 sqlalchemy-2.0.23 sqlalchemy-repr-0.1.0 typing-extensions-4.9.0 tzdata-2023.3 valens-0.2.0
$

Doing anything with valens (e.g. valens demo) yields an exception:

Traceback (most recent call last):
  File "/home/senier/tmp/.venv/bin/valens", line 5, in <module>
    from valens.cli import main
  File "/home/senier/tmp/.venv/lib/python3.11/site-packages/valens/__init__.py", line 3, in <module>
    from . import api, assets
  File "/home/senier/tmp/.venv/lib/python3.11/site-packages/valens/api.py", line 14, in <module>
    from valens import database as db, version
  File "/home/senier/tmp/.venv/lib/python3.11/site-packages/valens/database.py", line 12, in <module>
    from valens import config, models
  File "/home/senier/tmp/.venv/lib/python3.11/site-packages/valens/models.py", line 49, in <module>
    class User(Base):
  File "/home/senier/tmp/.venv/lib/python3.11/site-packages/sqlalchemy/orm/decl_api.py", line 195, in __init__
    _as_declarative(reg, cls, dict_)
  File "/home/senier/tmp/.venv/lib/python3.11/site-packages/sqlalchemy/orm/decl_base.py", line 247, in _as_declarative
    return _MapperConfig.setup_mapping(registry, cls, dict_, None, {})
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/senier/tmp/.venv/lib/python3.11/site-packages/sqlalchemy/orm/decl_base.py", line 328, in setup_mapping
    return _ClassScanMapperConfig(
           ^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/senier/tmp/.venv/lib/python3.11/site-packages/sqlalchemy/orm/decl_base.py", line 563, in __init__
    self._scan_attributes()
  File "/home/senier/tmp/.venv/lib/python3.11/site-packages/sqlalchemy/orm/decl_base.py", line 1006, in _scan_attributes
    collected_annotation = self._collect_annotation(
                           ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/senier/tmp/.venv/lib/python3.11/site-packages/sqlalchemy/orm/decl_base.py", line 1277, in _collect_annotation
    extracted = _extract_mapped_subtype(
                ^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/senier/tmp/.venv/lib/python3.11/site-packages/sqlalchemy/orm/util.py", line 2382, in _extract_mapped_subtype
    raise sa_exc.ArgumentError(
sqlalchemy.exc.ArgumentError: Type annotation for "User.body_weight" can't be correctly interpreted for Annotated Declarative Table form.  ORM annotations should normally make use of the ``Mapped[]`` generic type, or other ORM-compatible generic type, as a container for the actual type, which indicates the intent that the attribute is mapped. Class variables that are not intended to be mapped by the ORM should use ClassVar[].  To allow Annotated Declarative to disregard legacy annotations which don't use Mapped[] to pass, set "__allow_unmapped__ = True" on the class or a superclass this class. (Background on this error at: https://sqlalche.me/e/20/zlpr)

This issue does not occur with the current main (valens-0.2.1.dev92+71f3cd1 installed using pip install git+https://github.com/treiher/valens)

Offline functionality

Feature Specification

  • Without internet connection, the web app will start and show the last synchronized data.

Design

  • Use indxdb to store user data
    • Represent each mapping in data model by separate database

Storage Options

Resources

Notifications

Feature Specification

  • Notifications can be enabled in the settings.
  • A notification is shown when going to the next section during a guided training session.

APIs

Exercise types

Exercise types restrict the data fields for an exercise (e.g., only reps, reps and weight, only time) and affect the statistical evaluation (e.g., unilateral vs. bilateral exercises).

Feature Specification

TBD

Tasks

TBD

Extend interface for workouts

Workouts page

  • Add form for adding new workout (date selection, template selection and button for creation)
  • Add list of workouts below diagram (date and button for switching to workout page)

Workout page

  • Add workout page
  • Add form for editing details (one field per set and button for saving all changes)

Storage module

  • Add function for reading workout data
  • Add function for writing workout data
  • Add function for creating workout based on template

Config

  • Add config file for workout templates

Interface for workout templates

A template consists of list of exercises and a number of sets per exercise.

Features

  • Add template
  • Delete template
  • Change template
    • Change exercise
    • Change number of sets of exercise
    • Add exercise
    • Delete exercise

Track trained muscle groups

Requirements

  • For each exercise the primarily and secondarily trained muscle groups can be defined.
  • A set for a primary muscle group counts as one set.
  • A set for a secondary muscle group counts as half a set.
  • The total number of sets per muscle group is shown in routines and training sessions.
  • The total number of sets per muscle group trained per week is shown.
  • The following muscle groups are tracked:
    • Legs
      • Quads
      • Hamstrings
      • Glutes
      • Calves
    • Chest
      • Pecs
    • Back
      • Traps
      • Lats
      • Erector spinae
    • Arms
      • Biceps
      • Triceps
      • Forearms
    • Shoulders
      • Delts
    • Abs

References

Web Interface

Initial Structure

  • Start page
    • Links to all other pages
  • Body weight page
    • Diagram (date -> body weight)
    • Buttons for changing viewed time period (12M, 6M, 3M, all)
    • Buttons for switching to previous time period (<<, >>)
    • Form for adding entry (date and weight input + button)
  • Workouts page
    • Diagram (date -> average reps, average RPE, average time, reps volume)
    • Buttons for changing viewed time period (12M, 6M, 3M, all)
    • Buttons for switching to previous time period (<<, >>)
  • Exercises page
    • List of all recorded exercises with links to corresponding exercise pages
  • Exercise page
    • Diagram (date -> average reps, average reps+RIR, average weight, average time)
    • Buttons for changing viewed time period (12M, 6M, 3M, all)
    • Buttons for switching to previous time period (<<, >>)

Basis

Flask

Tasks

  • Add generation of diagrams using GET request including parameters for time period
  • Add template for showing diagram and time period selection menu
  • Add style sheet
  • Add start page
  • Add workouts page
  • Add exercises page
  • Add exercise page

Modification of training session

  • Enable adding and removing of sets
  • Enable replacing of exercises
  • Enable deferring of exercises
  • Enable adding and removing of exercises
  • Improve visualization of related sets
  • Enable appending of exercises

Multi-user support

  • Add user
  • Remove user
  • Remove data of removed user
  • Rename user
  • Login
  • Logout

Improve UI

  • Enable renaming of entities on entity page (e.g., renaming of exercise on exercise page instead of exercises page)
  • Add interval button for showing all values in chart
  • Show interval bounds above chart
  • Warn about unsaved changes before switching page (in particular on workout page) (example)
  • Warn about unsaved changes when using back button of device
  • Prevent creation of routines or exercises with names containing leading or trailing spaces
  • Use cumulative values per week on workouts page
  • Add list of sets to exercise page
  • Improve layout of training session summary (similar layout to list on exercise page)

Client-Side Rendering

Use CSR instead of SSR to improve interactivity.

Considered Options

  • Flutter
    • Pro: Active development of language (Dart) and framework by Google
    • Pro: Popular
  • Seed
    • Pro: Language (Rust) actively developed
    • Pro: Interesting language
    • Con: Framework mainly developed by single person
    • Con: Experimental
  • Elm
    • Pro: Interesting language and concepts
    • Con: Mainly developed by single person

Decision Outcome

Seed

Tasks

  • Add REST-like API
  • Reimplement existing functionality on client side
  • Add detection of version mismatch between frontend and backend
  • Move plotting into frontend
  • Remove SSR

Training sections

Feature Specification

  • A training routine will consist of one or multiple sections.
  • A section will consist of a sorted list of parts.
  • A section part can be either an activity (action/exercise/exertion/work) or rest.
  • An activity must be linked to an exercise and may have a duration or a tempo.
  • Rest may have a duration. In a workout, the next step will follow after the given time or by button press.
  • A section will offer the definition of a number of sets (rounds).
  • In a workout, the activities and rest will be repeated according to the specified number of sets of the section.

Tasks

Assisted exercises

The tracked weight for assisted exercises (e.g., Assisted Pull Up, Assisted Dip) should be handled differently (e.g., the volume load shouldn't decrease with decreased assistance). The actual weight could be calculated by subtracting the tracked weight from the current body weight.

Change data storage format

Currently, the pandas data structures used at runtime are transformed to a custom YAML-based format for storage. If internally used data structures are changed or extended, the YAML-based storage format must be adapted as well. This additional effort can be prevented by using the IO tool of pandas instead. The Feather format seems to be a good option.

Demo mode yields blank page

When running the current main (0.2.1.dev92+71f3cd1, I cannot use the latest release because of #29) in demo mode I get an empty website:

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="utf-8">
        <meta name="apple-mobile-web-app-capable" content="yes">
        <meta name="mobile-web-app-capable" content="yes">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <meta name="theme-color" content="#48C774">
        <title>Valens</title>
        <link rel="apple-touch-icon" sizes="180x180" href="[/images/apple-touch-icon.png](view-source:http://127.0.0.1:5000/images/apple-touch-icon.png)">
        <link rel="icon" type="image/png" sizes="16x16" href="[/images/favicon-16x16.png](view-source:http://127.0.0.1:5000/images/favicon-16x16.png)">
        <link rel="icon" type="image/png" sizes="32x32" href="[/images/favicon-32x32.png](view-source:http://127.0.0.1:5000/images/favicon-32x32.png)">
        <link rel="manifest" href="[/manifest.json](view-source:http://127.0.0.1:5000/manifest.json)">
        <link rel="stylesheet" href="[/index.css](view-source:http://127.0.0.1:5000/index.css)">
        <script src="[/js/register-sw.js](view-source:http://127.0.0.1:5000/js/register-sw.js)"></script>
        <base href="[/](view-source:http://127.0.0.1:5000/)">
        <link rel="preload" href="[/valens-frontend_bg.wasm](view-source:http://127.0.0.1:5000/valens-frontend_bg.wasm)" as="fetch" type="application/wasm" crossorigin="">
        <link rel="modulepreload" href="[/valens-frontend.js](view-source:http://127.0.0.1:5000/valens-frontend.js)">
    </head>
    <body class="has-navbar-fixed-top has-navbar-fixed-bottom">
        <div id="app">
        </div>
        <script type="module">
            import init from '/valens-frontend.js';
            init('/valens-frontend_bg.wasm');
        </script>
    </body>
</html>

(tested with Firefox & Chromium)

$ valens demo
Creating database
 * Serving Flask app 'valens'
 * Debug mode: off
WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.
 * Running on http://127.0.0.1:5000
Press CTRL+C to quit
127.0.0.1 - - [26/Dec/2023 23:27:37] "GET / HTTP/1.1" 200 -
127.0.0.1 - - [26/Dec/2023 23:27:37] "GET /js/register-sw.js HTTP/1.1" 404 -
127.0.0.1 - - [26/Dec/2023 23:27:37] "GET /valens-frontend.js HTTP/1.1" 404 -
127.0.0.1 - - [26/Dec/2023 23:27:37] "GET /index.css HTTP/1.1" 404 -
127.0.0.1 - - [26/Dec/2023 23:27:37] "GET /valens-frontend_bg.wasm HTTP/1.1" 404 -
127.0.0.1 - - [26/Dec/2023 23:27:37] "GET /manifest.json HTTP/1.1" 200 -
127.0.0.1 - - [26/Dec/2023 23:27:37] "GET /images/favicon-32x32.png HTTP/1.1" 404 -
127.0.0.1 - - [26/Dec/2023 23:27:37] "GET /images/android-chrome-192x192.png HTTP/1.1" 404 -
127.0.0.1 - - [26/Dec/2023 23:27:37] "GET /images/favicon-16x16.png HTTP/1.1" 404 -

The software was installed into a virtualenv using pip on Debian 12:

$ python3.11 -m venv .venv
$ . .venv/bin/activate
$ pip install git+https://github.com/treiher/valens
[successful install]

Project documentation

Add a README describing the project.

Contents

  • Overview
  • Screenshot
  • Installation
  • Configuration
  • Etymology

Guided workout

In a guided workout, a user is guided through the workout.

Feature Specification

  • The sequence of exercises and breaks will be defined by the routine.
  • The entered data will be stored as a workout (a list of exercise sets).

Tasks

  • #17
  • Add page for guided workouts

Comments for workouts

It should be possible to add comments to a workout. Therefore, a free text field should be added to the workout page. The comments field should be prefillable by a workout template.

Exercise database

Add predefined exercises.

Requirements

  • Predefined exercises are immutable.
  • Exercises can be copied to allow modifications.
  • When copying an exercise, references to the existing exercise will optionally be changed to the new one.
  • Exercises can be merged to allow switching from a user-defined exercise to a predefined one.

Design

  • Predfined exercises are only defined in the frontend code and are not represented in the database.
  • Foreign key constraints for exercise IDs must be disabled.
  • A specified exercise ID range is reserved for predefined exercises (e.g., 1-999).

Windows support

This project is an excellent example of how to do graphical programs in Rust. Thank you for putting it together.

I'm running it under Windows, and have experienced a few issues:

  1. valens config creates invalid paths: DATABASE = 'sqlite:///C:\Users\Sean\.local\share\valens\valens.db' -- the path separators should be double-escaped, or use forward slashes
  2. Every time I try to do something, I get an error: Mismatch between frontend and backend version (, 0.1.dev303+gab3e487). This may lead to unexpected errors. Please close and restart the app.

I can open separate issues for these if you like, or if Windows is not a desirable target I can close this issue.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.