diff --git a/PLANNING.md b/PLANNING.md deleted file mode 100644 index c4ea646..0000000 --- a/PLANNING.md +++ /dev/null @@ -1,7 +0,0 @@ -# Planning - -## Version 2.0.0 - -- [ ] [#1](https://github.com/willtheorangeguy/PyWorkout/issues/1): Fix Timer - -**More planning ideas can be found on the [Issues page](https://github.com/willtheorangeguy/PyWorkout/issues) or the [Projects page](https://github.com/willtheorangeguy/PyWorkouts/projects?type=classic).** diff --git a/README.md b/README.md index 5b84778..e9b614f 100644 --- a/README.md +++ b/README.md @@ -1,192 +1,100 @@

- PyWorkout + PyWorkout
PyWorkout

-

A minimal CLI to keep you inspired during your workout!

+

A minimal CLI to keep you inspired during your workout.

- - Docker Build State - - PyPI Build State - - Pylint State - - CodeQL State - - GitHub Version - - GitHub Issues - - GitHub Pull Requests - - Discord Server ID - - Downloads - - GitHub Languages + Tests + Pylint + Docker Build + PyPI Build + CodeQL + Version + Issues + Pull Requests + License

Key Features • - Download • - How To Use • + Installation • + Usage • + DocumentationSupportContributing • - Changelog • - Credits & Contributors + License

- -![screenshot](https://github.com/willtheorangeguy/PyWorkout/blob/main/docs/images/welcome.png) + -## Key Features - -* Easy to run and understand with simple commands. -* Large list of muscle groups and workout activities. -* Automatic workout selection by day. -* Time and percentage complete indicators. -* Step by step guide through a workout program. -* Statistics view. -* Can skip unlikeable workouts. -* Able to customize number of workouts, muscle groups, type of workout and more. -* Cross platform. - -## Download - -You can **[download](https://github.com/willtheorangeguy/PyWorkout/releases/latest) the source code** to run the scripts from the command line on Windows, macOS and Linux. **This will require [Python](https://www.python.org/downloads/).** - -You can **[download](https://github.com/willtheorangeguy/PyWorkout/releases/latest) the latest executable version** of PyWorkout for Windows. **This does not require Python.** - -## How To Use +![PyWorkout running in a terminal](https://raw.githubusercontent.com/willtheorangeguy/.github/main/icons/PyWorkout/welcome.png) -To run the application, you can use [Git and the Python Interpreter](https://github.com/willtheorangeguy/PyWorkout/main/README.md#git), which allows you to clone and run the application, [`pip`](https://github.com/willtheorangeguy/PyWorkout/main/README.md#pip) to create a command line application, or [Docker](https://github.com/willtheorangeguy/PyWorkout/main/README.md#docker) to create a container of the application. +## Key Features -### Git +* Pick a muscle group and get walked through the workout one exercise at a time. +* Nine muscle groups covering the whole body, each with its own set and rep counts. +* Live elapsed time and percent complete after every exercise. +* Skip anything you would rather not do, and see full statistics at the end. +* Open a local video for the current muscle group with one command. +* Add exercises, change rep counts, and swap videos by editing plain Python lists. +* No runtime dependencies beyond the standard library. Runs on Windows, macOS, and Linux. -To clone and run this application, you'll need [Git](https://git-scm.com/downloads) and [Python](https://www.python.org/downloads/) installed on your computer. If you would rather not use Git, you can just download the script from GitHub above. From your command line: +## Installation ```bash -# Clone this repository -$ git clone https://github.com/willtheorangeguy/PyWorkout - -# Go into the repository -$ cd PyWorkout - -# Run the CLI -$ python main.py +pip install pyworkout ``` -### `pip` +Prefer a standalone Windows executable, the source, or a container? See [Installation](docs/installation.md). -You can install the program from the [Python Package Index](https://pypi.org/project/PyWorkout/) through `pip`. +## Usage -```bash -# Install via pip -$ pip install pyworkout +Start the CLI, choose a muscle group, then step through the workout: -# Run the CLI +```console $ pyworkout -``` +Which muscle group would you like to work out? abs -### Docker +> start +You have started the abs muscle group. +The current time is: 14:19:35 +You have completed: 0% +Please complete 2 Sets of 25 Reps of Situps -You can pull the [Docker](https://www.docker.com/) image from GitHub Packages. From your command line: +> next +You have completed: 16% +Please complete 2 Sets of 25 Reps of Reverse Crunches -```bash -# Pull image -$ docker pull ghcr.io/willtheorangeguy/pyworkout:main - -# Run container -$ docker run -i -t ghcr.io/willtheorangeguy/pyworkout:main python main.py -``` - -## Support - -**The following commands are available (can be generated by using the `help` command):** - -```text -list Lists the workout activities by muscle group. -start Starts the workout and displays the first workout activity. -next Moves to the next workout activity. -skip Skips the current workout activity. -end Completes the workout and display full workout statistics. -stats Shows workout statistics at any point (does not work with the `skip` command). -video Opens the workout video assigned to each muscle group. -license Shows the license. -help Prints this help text. -quit Ends the program. +> end ``` -Note: the `skip` command cannot be used in conjunction with the `stats` command. +`help` lists every command. The full reference is in [Commands](docs/commands.md). -**To use the `video` command, you must change the video variables.** To do so: +## Documentation -1. Open `main.py` in a text editor. -2. Change the _Video File Paths_ variables to the **absolute** path for each video by muscle group (double slashes (`\\`) are only necessary on Windows). +Full documentation lives in [`docs/`](docs/README.md): +[Quickstart](docs/quickstart.md) · [Installation](docs/installation.md) · [Usage](docs/usage.md) · [Commands](docs/commands.md) · [Configuration](docs/configuration.md) · [Architecture](docs/architecture.md) · [FAQ](docs/faq.md) · [Troubleshooting](docs/troubleshooting.md) · [Roadmap](docs/roadmap.md) -```python -# Video File Paths -abs_video = "D:\\Videos\\Workout Videos\\10 Minute Ab Workout.mp4" # change these to personal video path -``` - -3. Running the `video` command will now include your local workout videos. +## Support -Customizing the list of workouts, workout activities and number of activities can be found in [`CUSTOMIZATION.md`](https://github.com/willtheorangeguy/PyWorkout/tree/main/docs). More documentation is available in the **[Documentation](https://github.com/willtheorangeguy/PyWorkout/tree/main/docs)** and on the **[Wiki](https://github.com/willtheorangeguy/PyWorkout/wiki)**. If more support is required, please open a **[GitHub Discussion](https://github.com/willtheorangeguy/PyWorkout/discussions/new)** or join our **[Discord](https://discord.gg/YFMcACG9rh)**. +Open a [GitHub Discussion](https://github.com/willtheorangeguy/PyWorkout/discussions/new) or file an [issue](https://github.com/willtheorangeguy/PyWorkout/issues/new/choose). ## Contributing -Please contribute using [GitHub Flow](https://guides.github.com/introduction/flow). Create a branch, add commits, and [open a pull request](https://github.com/willtheorangeguy/PyWorkout/compare). - -Please read [`CONTRIBUTING`](https://github.com/willtheorangeguy/.github/blob/main/CONTRIBUTING.md) for details on our [`CODE OF CONDUCT`](https://github.com/willtheorangeguy/.github/blob/main/CODE_OF_CONDUCT.md), and the process for submitting pull requests to us. - -## Changelog - -See the [`CHANGELOG`](CHANGELOG.md) file for details. +Contributions welcome. See the org-wide [Contributing Guide](https://github.com/willtheorangeguy/.github/blob/main/CONTRIBUTING.md) and [Code of Conduct](https://github.com/willtheorangeguy/.github/blob/main/CODE_OF_CONDUCT.md). ## Credits -This software uses the following open source packages, projects, services or websites: - - - - - - - - - - - - - - - - - - - - - -
GitHubPSFPyInstallerCarbon
GitHubPython Software FoundationPyInstallerCarbon
Web - PlansWeb - DonateWeb - DonateWeb
- -## Contributors - -* [@willtheorangeguy](https://github.com/willtheorangeguy) - Sponsor on [PayPal](https://paypal.me/wvdg44?country.x=CA&locale.x=en_US) - -## You may also like... - -* [ProgramVer](https://github.com/willtheorangeguy/ProgramVer) - An open-source, Python GUI version window to show copyright info and licenses. -* [Periodic Table Info](https://github.com/willtheorangeguy/Periodic-Table-Info) - Print all the elements in the Periodic Table of the Elements, with an interactive prompt to learn more. -* [PyAvatar](https://github.com/willtheorangeguy/PyAvatar) - Easily display all of your creative avatars to keep them consistent across websites. +Built with [Python](https://www.python.org/), packaged with [PyInstaller](https://pyinstaller.org/), and distributed through [PyPI](https://pypi.org/project/PyWorkout/) and [GitHub Packages](https://github.com/willtheorangeguy/PyWorkout/pkgs/container/pyworkout). ## License -This project is licensed under the [MIT License](https://mit-license.org/) - see the [`LICENSE`](LICENSE.md) file for details. +MIT — see [`LICENSE.md`](LICENSE.md). diff --git a/docs/README.md b/docs/README.md index 195e41c..534381b 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,13 +1,38 @@ -# PyWorkout Documentation - -This folder includes all of the docs for PyWorkout. More can be found on the [wiki](https://github.com/willtheorangeguy/PyWorkout/wiki). - -```text -├── docs -| ├── images -| ├── USAGE.md -| ├── COMMANDS.md -| ├── CUSTOMIZATION.md -| ├── TESTING.md -└── README.md +# PyWorkout — Documentation + +A terminal workout tracker: pick a muscle group, work through its exercises, and get timing +and completion statistics as you go. Ships to PyPI, GHCR, and as a Windows executable. + +``` +PyWorkout/ +├── docs/ +│ ├── README.md this page +│ ├── quickstart.md install, pick a group, finish a session +│ ├── installation.md all four install paths +│ ├── usage.md the session flow +│ ├── commands.md every command with example output +│ ├── configuration.md exercises, videos, and what needs source edits +│ ├── architecture.md how main.py and gui.py are shaped +│ ├── development.md contributing to the code +│ ├── testing.md the test suite and coverage +│ ├── faq.md skip/stats, the GPL banner, what gui.py is +│ ├── troubleshooting.md concrete failures and fixes +│ └── roadmap.md planned work and known defects +├── main.py the CLI +├── gui.py a separate Tkinter percentage tracker +└── tests/ ``` + +## Pages + +- [Quickstart](./quickstart.md) — install, run one workout +- [Installation](./installation.md) — PyPI, source, Docker, Windows executable +- [Usage](./usage.md) — how a session flows +- [Commands](./commands.md) — full command reference with example output +- [Configuration](./configuration.md) — adding exercises and video paths +- [Architecture](./architecture.md) — the shape of the code and what follows from it +- [Development](./development.md) — working on it +- [Testing](./testing.md) — the suite, coverage, and writing new tests +- [FAQ](./faq.md) — why `stats` stopped, what `gui.py` is, the licence banner +- [Troubleshooting](./troubleshooting.md) — Tkinter, Docker, `PATH`, timing +- [Roadmap](./roadmap.md) — version 2.0.0 and known defects diff --git a/docs/USAGE.md b/docs/USAGE.md deleted file mode 100644 index 12a1269..0000000 --- a/docs/USAGE.md +++ /dev/null @@ -1,33 +0,0 @@ -# PyWorkout Usage - -To install PyWorkout you can use an executable package (Windows), run the scripts through Python (Windows, macOS, Linux), install from the [Python Package Index](https://pypi.org/), or run a [Docker](https://www.docker.com/) container from [GitHub Packages](https://github.com/willtheorangeguy/PyWorkout/pkgs/container/pyworkout). - -## Executable Package - -1. To run the executable package, download the latest `.zip` file from [GitHub Releases](https://github.com/willtheorangeguy/PyWorkout/releases/latest) page. -2. Extract the `.zip` file using a program like [7-Zip](https://www.7-zip.org/). -3. _(Optional) Move the files to `C:\Program Files` and create a shortcut._ -4. Double click on `send.exe`. -5. Enjoy the program! - -## Python Script - -1. To run the Python script, download the latest source code release from [GitHub Releases](https://github.com/willtheorangeguy/PyWorkout/releases/latest) page. -2. Download and install [Python](https://www.python.org/downloads/). -3. Extract the source code files using a program like [7-Zip](https://www.7-zip.org/). -4. Double click on `send.py`, or right-click and open with IDLE and press `F5`. -5. Enjoy the program! - -## Python Package Index (`pip`) - -1. Download and install [Python](https://www.python.org/downloads/). -2. Open a terminal and run the command: `pip install pyworkout`. -3. Start the program by running the command: `pyworkout`. -4. Enjoy the program! - -## Docker Container - -1. Download and install [Docker](https://www.docker.com/products/docker-desktop/). -2. Open a terminal and pull the container: `docker pull ghcr.io/willtheorangeguy/pyworkout:main`. -3. Start the container: `docker run -i -t ghcr.io/willtheorangeguy/pyworkout:main python main.py`. -4. Enjoy the program! diff --git a/docs/architecture.md b/docs/architecture.md new file mode 100644 index 0000000..f2e3ac4 --- /dev/null +++ b/docs/architecture.md @@ -0,0 +1,80 @@ +# PyWorkout — Architecture + +## Layout + +``` +PyWorkout/ +├── main.py the CLI — command loop, workout data, all session state +├── gui.py a separate Tkinter percentage tracker +├── __main__.py module entry point (python -m pyworkout) +├── docker-compose.yml containerised run +├── Dockerfile published to GHCR +├── pyproject.toml packaging; published to PyPI +├── setup.cfg pytest and coverage configuration +└── tests/ + ├── test_main.py CLI behaviour + └── test_gui.py GUI components +``` + +## Two programs, not one + +`main.py` and `gui.py` are independent. The CLI does not import the GUI, and the GUI is not +a front end for the CLI — it is a separate Tkinter window that displays percentage +completion for a fixed exercise list. + +They share the project and the name, and nothing else. Worth knowing before looking for the +integration point: there isn't one. + +## `main.py` is a single function + +The entire CLI — muscle-group selection, the command loop, timing, statistics, help output, +and the exercise data itself — lives inside one `workout()` function of roughly six hundred +lines. + +Consequences that show up in practice: + +- **Session state is local variables**, which is why `skip` and `stats` interact badly: + they manipulate overlapping bookkeeping in the same scope rather than through a shared + model. See [Roadmap](./roadmap.md). +- **Help text is printed inline in two places** (around lines 613 and 632) and the two + copies have drifted — one documents the `skip`/`stats` limitation, the other omits it. +- **Tests reach the logic through `builtins.input` and `builtins.print`.** Every test in + `test_main.py` patches those and asserts against captured output, because there is no + return value to inspect. That is a consequence of the structure, not a testing choice. + +Extracting the workout data and the session state into their own modules is the change that +would unlock most of the rest. + +## Data + +Exercise definitions — muscle groups, exercises, sets, reps — are literals in `main.py`. +There is no data file, no database, and nothing persisted between runs. Closing the program +discards the session. + +Video paths are also literals, under a `# Video File Paths` comment, which is why the +`video` command requires editing source to work. See [Configuration](./configuration.md). + +## Timing + +Elapsed time is computed from a start timestamp captured by `start` and compared against +the current time on each `next`, `stats`, and `end`. There is no pause, and no persistence — +the timer measures wall-clock time from `start`, including any time you spent away from the +terminal. + +The known timer defect tracked for 2.0.0 lives here. + +## Distribution + +The same code ships four ways: PyPI (`pip install pyworkout`), a GHCR container, a Windows +executable attached to releases, and the source itself. `pyproject.toml` drives the first, +`Dockerfile` the second. + +Because the PyPI and GHCR pages render the README off-site, its images must be absolute +URLs — they point at `.github/icons/PyWorkout/`. Relative image paths would break there +even though they work on github.com. + +## Testing + +`setup.cfg` configures pytest with coverage, branch coverage, and three report formats. +Coverage sits around 54%. GUI tests skip in headless environments, since Tkinter needs a +display — expected in CI rather than a failure. diff --git a/docs/COMMANDS.md b/docs/commands.md similarity index 94% rename from docs/COMMANDS.md rename to docs/commands.md index d4156bb..7fae2d0 100644 --- a/docs/COMMANDS.md +++ b/docs/commands.md @@ -1,6 +1,6 @@ -# PyWorkout Commands +# PyWorkout — Commands -**The following commands are available in PyWorkout:** +Every command available at the PyWorkout prompt. `help` prints this same list inside the program. ```text list Lists the workout activities by muscle group. @@ -100,7 +100,7 @@ The current time is: 14:33:04. 0:00:01.564038 has elapsed. ## `license` -Shows the GNU GPL v3 license text. The full license can be accessed in the `LICENSE.md` file. +Prints the copyright line and a short warranty disclaimer. The full terms are in [`LICENSE.md`](../LICENSE.md). ## `help` diff --git a/docs/CUSTOMIZATION.md b/docs/configuration.md similarity index 78% rename from docs/CUSTOMIZATION.md rename to docs/configuration.md index 64c1835..5b77e06 100644 --- a/docs/CUSTOMIZATION.md +++ b/docs/configuration.md @@ -1,8 +1,8 @@ -# PyWorkout Customization +# PyWorkout — Configuration -PyWorkout has been designed to be heavily customizable. More workouts can be added, lengths can be changed, and videos can be used from different sources. +PyWorkout keeps its workout data as plain Python lists in `main.py`, so changing it means editing that file directly — there is no config file or database. -All of these instructions require [Python](https://www.python.org/downloads/) and [a text editor](https://code.visualstudio.com/) to be installed. +You need [Python](https://www.python.org/downloads/) and [a text editor](https://code.visualstudio.com/), and you need to be running PyWorkout [from source](installation.md#from-source). Edits to `main.py` have no effect on a `pip`-installed copy or the Windows executable. ## Add a Workout @@ -53,9 +53,9 @@ abs_count = [25, 25, 25, 25, 25, 2] ## Change the Videos -Changing the video address is extremely easy as well! +The `video` command opens a local video file for the current muscle group. The paths shipped in `main.py` point at one particular machine, so this command does nothing useful until you set your own. -1. Choose your videos. I recommend workout videos by [Pamela Reif](https://www.youtube.com/channel/UChVRfsT_ASBZk10o0An7Ucg). They can be downloaded from the internet or created yourself. +1. Choose your videos — recorded yourself, or downloaded. Workout videos by [Pamela Reif](https://www.youtube.com/@PamelaRf1) work well. 2. Open the `main.py` file with a text editor. 3. Navigate to the `# Video File Paths` section. It looks like this: diff --git a/docs/development.md b/docs/development.md new file mode 100644 index 0000000..1fea726 --- /dev/null +++ b/docs/development.md @@ -0,0 +1,75 @@ +# PyWorkout — Development + +## Local Setup + +```bash +git clone https://github.com/willtheorangeguy/PyWorkout +cd PyWorkout +pip install -e . +``` + +An editable install means `pyworkout` on your PATH runs your working copy, so edits take effect immediately. To skip installing altogether, `python main.py` works just as well. + +Development tooling — pytest, pytest-cov, pytest-mock, pylint, build — is not pulled in by the editable install: + +```bash +pip install pytest pytest-cov pytest-mock pylint build +``` + +## Architecture in Brief + +Almost all of PyWorkout is a single `workout()` function in `main.py`, roughly 600 lines. That is deliberate: the program is simple, and one readable function beats an abstraction layer nobody needs. + +Two consequences worth knowing before you edit: + +**State lives in module-level globals** set inside `workout()` — `select` (chosen muscle group), `activity_num` (current exercise), `start` (start time), `complete` (finished exercises), and `times` (per-exercise durations). Pylint objects to this; the file silences those specific warnings with inline `# pylint: disable=` comments. That is the established pattern here — please follow it rather than adding a `.pylintrc`. + +**Workout data is parallel lists.** Each muscle group has a list of exercise names and a matching `_count` list of reps, and the two are index-aligned. Adding an exercise means appending to both, and updating the bounds check in the `next` branch. [Configuration](configuration.md) walks through this step by step. + +`gui.py` is an unfinished Tkinter frontend. It is not connected to `main.py` and does not run — do not treat it as a reference for how the application behaves. + +## Everyday Commands + +```bash +# Run the CLI +python main.py + +# Run the tests +pytest tests/ -v + +# Tests with coverage +pytest tests/ --cov=. --cov-report=term-missing + +# Lint +pylint $(git ls-files '*.py') + +# Build the distributable packages +python -m build +``` + +[Testing](testing.md) covers the suite in more detail. + +## Conventions + +* **Comments.** The codebase comments heavily. Match that when you touch `main.py`. +* **No runtime dependencies.** PyWorkout uses only the standard library. Please keep it that way — it is why the executable build stays small and the Docker image stays simple. +* **Versioning.** [Semantic versioning](https://semver.org/). The version appears in both `setup.cfg` and `pyproject.toml`; update them together. + +## Continuous Integration + +Five workflows run in GitHub Actions: + +| Workflow | Trigger | Does | +| --- | --- | --- | +| `tests.yml` | Push or PR to `main`/`develop` | pytest on Python 3.9–3.12, uploads coverage | +| `pylint.yml` | Every push | Pylint on Python 3.9 | +| `docker-publish.yml` | Push to `main`, tags, PRs, daily | Builds and pushes the image to ghcr.io | +| `push-to-pypi.yml` | Release published | Builds and publishes to PyPI | +| `codeql-analysis.yml` | Push, PRs, schedule | Security scanning | + +## Releasing + +1. Bump the version in `setup.cfg` and `pyproject.toml`. +2. Update `CHANGELOG.md`. +3. Tag and push: `git tag v1.2.0 && git push --tags`. +4. Publish a GitHub Release. `push-to-pypi.yml` handles PyPI from there; `docker-publish.yml` pushes the tagged image. diff --git a/docs/faq.md b/docs/faq.md new file mode 100644 index 0000000..d39a199 --- /dev/null +++ b/docs/faq.md @@ -0,0 +1,62 @@ +# PyWorkout — FAQ + +## Why can't I use `skip` and `stats` together? + +Because they interfere. Once you skip an exercise, `stats` stops reporting for that session +and prints "You cannot use both the `skip` and `stats` commands, sorry!" + +This is a defect rather than a design decision — both commands manipulate the same session +bookkeeping inside one large function. See [Architecture](./architecture.md) and +[Roadmap](./roadmap.md). + +## The `video` command does nothing. + +It needs paths configured first. Video file paths are literals in `main.py`, under the +`# Video File Paths` comment — the command opens whatever is listed there in your default +player, and does nothing useful until you point it at real files. See +[Configuration](./configuration.md). + +## Does it save my workout history? + +No. Nothing is persisted. Closing the program discards the session, and there is no history +across runs. + +## Can I add my own exercises? + +Yes, by editing `main.py` — the muscle groups, exercises, sets, and reps are literals in +the source. There is no data file. See [Configuration](./configuration.md). + +## What's `gui.py`? + +A separate Tkinter window that tracks percentage completion for a fixed exercise list. It +is **not** a front end for the CLI — the two programs are independent and share nothing but +the repository. Looking for how they connect is time wasted; they do not. + +## Why does it print GPL text when the repo says MIT? + +`main.py` prints GPL boilerplate at startup — "ABSOLUTELY NO WARRANTY", "free software", +"redistribute it under certain conditions" — with a 2021-2024 copyright line. The +repository is MIT-licensed, and `LICENSE.md` is the MIT text. + +The startup banner is wrong. It is a leftover, tracked in [Roadmap](./roadmap.md), and the +licence that governs the code is the one in `LICENSE.md`. + +## Does the timer pause? + +No. It measures wall-clock time from `start`, so time spent away from the terminal counts. +A timer fix is the tracked item for version 2.0.0. + +## Which install should I use? + +`pip install pyworkout` unless you have a reason not to. Docker suits a throwaway +environment; the Windows executable suits a machine with no Python. All four ship the same +code — see [Installation](./installation.md). + +## Why do GUI tests skip in CI? + +Tkinter needs a display, and CI runners are headless. Expected behaviour, not a failure. + +## Is this exercise advice? + +No. It is a timer and a checklist. The exercises, sets, and reps are one person's routine +hardcoded into a script, not a programme designed for anyone in particular. diff --git a/docs/images/cmd.png b/docs/images/cmd.png deleted file mode 100644 index 8723e71..0000000 Binary files a/docs/images/cmd.png and /dev/null differ diff --git a/docs/images/full.png b/docs/images/full.png deleted file mode 100644 index 0e9ff51..0000000 Binary files a/docs/images/full.png and /dev/null differ diff --git a/docs/images/helpscreen.png b/docs/images/helpscreen.png deleted file mode 100644 index 5ad6d47..0000000 Binary files a/docs/images/helpscreen.png and /dev/null differ diff --git a/docs/images/logo.png b/docs/images/logo.png deleted file mode 100644 index dbeec11..0000000 Binary files a/docs/images/logo.png and /dev/null differ diff --git a/docs/images/welcome.png b/docs/images/welcome.png deleted file mode 100644 index f41a19c..0000000 Binary files a/docs/images/welcome.png and /dev/null differ diff --git a/docs/installation.md b/docs/installation.md new file mode 100644 index 0000000..873a284 --- /dev/null +++ b/docs/installation.md @@ -0,0 +1,70 @@ +# PyWorkout — Installation + +PyWorkout runs on Windows, macOS, and Linux. There are four ways to install it; pick whichever suits you. + +| Method | Needs Python | Best for | +| --- | --- | --- | +| [`pip`](#python-package-index-pip) | Yes | Most people | +| [Executable](#executable-package) | No | Windows users who do not want to install Python | +| [Source](#from-source) | Yes | Trying changes or contributing | +| [Docker](#docker-container) | No | Running in a container | + +## Python Package Index (`pip`) + +1. Install [Python](https://www.python.org/downloads/) 3.9 or newer. +2. Install PyWorkout: + + ```bash + pip install pyworkout + ``` + +3. Run it: + + ```bash + pyworkout + ``` + +## Executable Package + +No Python needed — everything is bundled. + +1. Download the latest `.zip` from [Releases](https://github.com/willtheorangeguy/PyWorkout/releases/latest). +2. Extract it with [7-Zip](https://www.7-zip.org/) or Windows Explorer. +3. *(Optional)* Move the folder to `C:\Program Files` and make a shortcut. +4. Run `PyWorkout.exe`. + +## From Source + +1. Install [Python](https://www.python.org/downloads/) 3.9 or newer and [Git](https://git-scm.com/downloads). +2. Clone and run: + + ```bash + git clone https://github.com/willtheorangeguy/PyWorkout + cd PyWorkout + python main.py + ``` + +No `pip install` step is required — PyWorkout uses only the standard library. + +If you would rather not use Git, download the source archive from [Releases](https://github.com/willtheorangeguy/PyWorkout/releases/latest) and run `python main.py` inside the extracted folder. + +## Docker Container + +1. Install [Docker](https://www.docker.com/products/docker-desktop/). +2. Pull the image from GitHub Packages: + + ```bash + docker pull ghcr.io/willtheorangeguy/pyworkout:main + ``` + +3. Run it interactively — `-i -t` matters, because PyWorkout reads commands from stdin: + + ```bash + docker run -i -t ghcr.io/willtheorangeguy/pyworkout:main python main.py + ``` + +The `video` command will not work inside a container, since it has no access to your local video files or a media player. + +## Next Steps + +Head to [Usage](usage.md) to run your first workout, or [Configuration](configuration.md) to make it yours. diff --git a/docs/quickstart.md b/docs/quickstart.md new file mode 100644 index 0000000..2fb9803 --- /dev/null +++ b/docs/quickstart.md @@ -0,0 +1,64 @@ +# PyWorkout — Quickstart + +## Install + +```bash +pip install pyworkout +``` + +Requires Python 3.9+. Other install paths — source, Docker, Windows executable — are in +[Installation](./installation.md). + +## Run + +```bash +pyworkout +``` + +## Pick a muscle group + +You are prompted for one. Both the number and the name work: + +``` +1 abs 4 chest 7 back +2 quads 5 arms +3 glutes 6 shoulders +``` + +## Work through it + +``` +list show the exercises in this group +start begin, and start the timer +next move to the next exercise +skip skip the current one +stats progress so far +end finish and show the summary +quit exit +``` + +A typical session is `start`, then `next` repeatedly, then `end`. + +## What to expect + +``` +You have started the abs muscle group. +The current time is: 14:19:35 +You have completed: 0% +Please complete 2 Sets of 25 Reps of Situps +``` + +Each `next` reports elapsed time and percentage complete. `end` prints the total time and +everything you finished. + +## One thing that will catch you out + +**`skip` and `stats` do not work together.** Once you have skipped an exercise, `stats` +stops reporting for that session and says so. This is a known defect rather than a design +choice — see [Roadmap](./roadmap.md). + +## Then what + +- [Usage](./usage.md) — the full session flow +- [Commands](./commands.md) — every command with example output +- [Configuration](./configuration.md) — adding your own exercises and videos diff --git a/docs/roadmap.md b/docs/roadmap.md new file mode 100644 index 0000000..fb543b1 --- /dev/null +++ b/docs/roadmap.md @@ -0,0 +1,56 @@ +# PyWorkout — Roadmap + +## Version 2.0.0 + +- [ ] [#1](https://github.com/willtheorangeguy/PyWorkout/issues/1) — Fix Timer + +More planning lives on the +[Issues page](https://github.com/willtheorangeguy/PyWorkout/issues) and the +[Projects page](https://github.com/willtheorangeguy/PyWorkout/projects?type=classic). + +## Known defects + +**`skip` and `stats` are mutually exclusive.** Using `skip` disables `stats` for the rest +of the session, and the program says so rather than failing silently. Both commands +manipulate overlapping session bookkeeping inside a single function — see +[Architecture](./architecture.md). Extracting session state into its own model is what +fixes this properly. + +**The startup banner claims GPL terms on an MIT project.** `main.py` prints "ABSOLUTELY NO +WARRANTY", "free software", and "redistribute it under certain conditions", with a +2021-2024 copyright line. The repository is MIT and `LICENSE.md` is the MIT text. The +banner is a leftover and contradicts the actual licence. + +**Two help outputs have drifted.** Help text is printed inline in two places in `main.py`. +One documents the `skip`/`stats` limitation; the other omits it, so which caveat you see +depends on where you asked. + +**`video` requires editing source to work at all.** Paths are literals under +`# Video File Paths`. A command that does nothing until you modify the program is closer to +unimplemented than configurable. + +## Structural gaps + +**`main.py` is one ~600-line function.** Muscle-group selection, the command loop, timing, +statistics, help, and the exercise data all live inside `workout()`. This is the root cause +of the `skip`/`stats` defect and the duplicated help text, and it is why tests have to reach +the logic by patching `builtins.input` and `builtins.print` — there is no return value to +assert against. + +**Coverage is around 54%.** Reasonable for a prompt-loop program tested through stdout, but +the untested half is where the timer and statistics logic lives. + +**Exercises are hardcoded.** Adding your own means editing `main.py`. A data file would +make the program useful to someone whose routine differs. + +**Nothing persists.** No history, no progress across sessions, no record that a workout +happened. + +**The CLI and the GUI are unrelated programs.** `gui.py` tracks percentages for its own +fixed exercise list and shares nothing with `main.py`. + +## Non-goals + +- **Exercise prescription.** This is a timer and a checklist over one person's routine, not + a training programme. +- **Accounts or sync.** It is a local script. diff --git a/docs/TESTING.md b/docs/testing.md similarity index 93% rename from docs/TESTING.md rename to docs/testing.md index ac5df4c..a6f9bca 100644 --- a/docs/TESTING.md +++ b/docs/testing.md @@ -1,6 +1,8 @@ -# PyWorkout Test Suite +# PyWorkout — Testing -This directory contains the comprehensive test suite for PyWorkout. The tests are written using pytest and provide coverage for the main CLI functionality and GUI components. +PyWorkout's test suite lives in `tests/` and runs on [pytest](https://docs.pytest.org/). It covers the CLI in `main.py`; `gui.py` is an unfinished Tkinter frontend that is not wired into the application, so its tests skip in most environments. + +For local setup, linting, and building, see [Development](development.md). ## Test Structure diff --git a/docs/troubleshooting.md b/docs/troubleshooting.md new file mode 100644 index 0000000..f5ec9f7 --- /dev/null +++ b/docs/troubleshooting.md @@ -0,0 +1,69 @@ +# PyWorkout — Troubleshooting + +## `stats` stopped working + +You used `skip` earlier in the session. The two commands do not coexist, and `stats` will +say so. Start a new session to get statistics back, or avoid `skip` in a session where you +want them. Tracked in [Roadmap](./roadmap.md). + +## `video` opens nothing + +Video paths are not configured out of the box — they are literals in `main.py` under +`# Video File Paths`, and point nowhere useful until you edit them. See +[Configuration](./configuration.md). + +## `pyworkout: command not found` + +The console script did not land on your `PATH`. Either the install went into a virtual +environment that is not active, or your user-level bin directory is not on `PATH`. As a +check, the module entry point works regardless: + +```bash +python -m pyworkout +``` + +## The GUI will not start + +`gui.py` needs Tkinter, which is not always present on Linux even when Python is: + +```bash +sudo apt install python3-tk # Debian/Ubuntu +``` + +Over SSH without X forwarding it cannot open a window at all. The CLI is unaffected. + +## GUI tests are skipped + +Expected in a headless environment. Tkinter needs a display, so CI skips them. Not a +failure. + +## Docker container exits immediately + +The container needs an interactive terminal — the program is a prompt loop, and without +stdin it reaches EOF and stops: + +```bash +docker run -i -t ghcr.io/willtheorangeguy/pyworkout:main python main.py +``` + +Both `-i` and `-t` matter. + +## Elapsed time looks wrong + +The timer measures wall-clock time from `start` with no pause, so any time away from the +terminal is included. There is also a known timer defect tracked for version 2.0.0 — see +[Roadmap](./roadmap.md). + +## It prints GPL warranty text on startup + +A leftover banner. The repository is MIT-licensed; `LICENSE.md` is authoritative and the +startup text is wrong. Recorded in [Roadmap](./roadmap.md). + +## Tests fail to import + +Run them from the project root, so the package resolves: + +```bash +cd /path/to/PyWorkout +pytest tests/ +``` diff --git a/docs/usage.md b/docs/usage.md new file mode 100644 index 0000000..3e6363e --- /dev/null +++ b/docs/usage.md @@ -0,0 +1,64 @@ +# PyWorkout — Usage + +A workout has three phases: choose a muscle group, step through the exercises, then finish and read your statistics. + +## Choosing a Muscle Group + +Start PyWorkout and you are asked which muscle group to work: + +```console +$ pyworkout +Which muscle group would you like to work out? +``` + +Answer with either the name or its number. `abs` and `1` do the same thing. + +Nine groups are available: **abs**, **quads**, **hamstrings**, **calves**, **chest**, **back**, **shoulders**, **biceps**, and **triceps**. + +If you enter something unrecognised, PyWorkout asks again rather than exiting. + +## Stepping Through a Workout + +Once a group is selected you are at the command prompt. A typical session: + +```console +> list +1. Situps 2 Sets of 25 Reps +2. Reverse Crunches 2 Sets of 25 Reps +3. Bicycle Crunches 2 Sets of 25 Reps +4. Flutter Kicks 2 Sets of 25 Reps +5. Leg Raises 2 Sets of 25 Reps +6. Elbow Planks 2 Sets of 2 Reps + +> start +You have started the abs muscle group. +The current time is: 14:19:35 +You have completed: 0% +Please complete 2 Sets of 25 Reps of Situps + +> next +You are in the abs muscle group. +The current time is: 14:23:01. 0:03:26 has elapsed. +You have completed: 16% +Please complete 2 Sets of 25 Reps of Reverse Crunches +``` + +`start` begins the timer, so run it when you actually begin. Every `next` records how long the previous exercise took. + +Once you have worked through the whole list, `next` tells you there is nothing left and prompts you to run `end`. + +## Skipping and Statistics + +`skip` moves past an exercise without recording it as complete — useful when equipment is unavailable or something hurts. + +`stats` shows your progress mid-workout, and `end` finishes the workout and prints the full breakdown. + +> **`skip` and `stats` do not work together.** Skipping leaves a gap in the timing data that the statistics calculation cannot account for. If you have skipped anything this session, `stats` will be wrong — use `end` instead. See [Commands](commands.md#stats). + +## Watching a Video + +`video` opens the video assigned to the current muscle group in your default player. This needs local file paths configured first — see [Configuration](configuration.md#change-the-videos). Without that, the command has nothing to open. + +## Full Command Reference + +Every command, with example output, is documented in [Commands](commands.md). `help` prints the same list inside the program.