# Zwift workout generator
Have you ever been frustrated by any WYSIWYG workout editor, such as the [Zwift Workout editor](https://zwift.com/news/12975-zwift-how-to-creating-a-custom-workout) and the [TrainingPeaks Workout Builder](https://help.trainingpeaks.com/hc/en-us/articles/235164967-Structured-Workout-Builder)?
ZWOG makes it easier to generate structured workouts using a syntax similar to the one used on [What's on Zwift?](https://whatsonzwift.com).
### Installation
#### PyPI
Install the latest stable version from PyPI
```console
$ pip install zwog
```
#### GitHub
Install the version from the main branch
```console
$ pip install git+https://github.com/tare/zwog.git
```
### Syntax
The basic building blocks are ramp intervals
```
10min from 30 to 60% FTP
```
and steady state intervals
```
2hrs 10min @ 60% FTP
```
Interval durations can be given in seconds (`sec`,`s`), minutes (`min`,`m`), and hours (`hrs`,`h`).
Moreover, it is possible to create repeated intervals
```
4x 5min @ 95% FTP, 5min @ 85% FTP
```
Finally, a complete workout can be defined as follows
```
10min from 40 to 85% FTP
3x 5min @ 95% FTP, 5min @ 86% FTP
5min @ 50% FTP
3x 5min @ 95% FTP, 5min @ 86% FTP
10min from 75 to 55% FTP
```
The parser is rather robust when it comes to newlines and other whitespaces.
### Usage
You can use the command line application
```console
$ zwog --help
usage: zwog [-h] -i INPUT_FILE [-o OUTPUT_FILE] [-a AUTHOR] [-n NAME]
[-c CATEGORY] [-s SUBCATEGORY] [-v]
Zwift workout generator
optional arguments:
-h, --help show this help message and exit
-i INPUT_FILE, --input_file INPUT_FILE
input filename
-o OUTPUT_FILE, --output_file OUTPUT_FILE
output filename
-a AUTHOR, --author AUTHOR
author name
-n NAME, --name NAME workout name
-c CATEGORY, --category CATEGORY
category
-s SUBCATEGORY, --subcategory SUBCATEGORY
subcategory
-v, --version show program's version number and exit
```
or call it from Python
```python
import zwog
workout_text = "15min from 10 to 50% FTP 5min from 50 to 70% FTP 2x 0.5hrs @ 100% FTP, 0.5hrs @ 50% FTP, 10min from 80 to 90% FTP 2min @ 50% FTP\n2min @ 50% FTP\n 10min @ 50% FTP, 10min @ 60% FTP 10min from 50 to 10% FTP"
workout = zwog.ZWOG(workout_text)
workout.save_zwo('workout.xml')
print(workout)
print(f"{round(workout.tss)} TSS")
```
### Limitations
- Only the [ZWO file format](https://github.com/h4l/zwift-workout-file-reference/blob/master/zwift_workout_file_tag_reference.md) is supported currently
- Workout files have to be uploaded [manually](https://zwiftinsider.com/load-custom-workouts/) to Zwift
Raw data
{
"_id": null,
"home_page": "https://github.com/tare/zwog",
"name": "zwog",
"maintainer": "",
"docs_url": null,
"requires_python": ">=3.8,<4.0",
"maintainer_email": "",
"keywords": "zwift,cycling,workout",
"author": "Tarmo \u00c4ij\u00f6",
"author_email": "tarmo.aijo@gmail.com",
"download_url": "https://files.pythonhosted.org/packages/76/96/7d4aef8d80384a9999013809356a80714ce3b0175196427f7e66c3bb91e2/zwog-1.0.0.tar.gz",
"platform": null,
"description": "# Zwift workout generator\n\nHave you ever been frustrated by any WYSIWYG workout editor, such as the [Zwift Workout editor](https://zwift.com/news/12975-zwift-how-to-creating-a-custom-workout) and the [TrainingPeaks Workout Builder](https://help.trainingpeaks.com/hc/en-us/articles/235164967-Structured-Workout-Builder)?\n\nZWOG makes it easier to generate structured workouts using a syntax similar to the one used on [What's on Zwift?](https://whatsonzwift.com).\n\n### Installation\n\n#### PyPI\n\nInstall the latest stable version from PyPI\n\n```console\n$ pip install zwog\n```\n\n#### GitHub\n\nInstall the version from the main branch\n\n```console\n$ pip install git+https://github.com/tare/zwog.git\n```\n\n### Syntax\n\nThe basic building blocks are ramp intervals\n\n```\n10min from 30 to 60% FTP\n```\n\nand steady state intervals\n\n```\n2hrs 10min @ 60% FTP\n```\n\nInterval durations can be given in seconds (`sec`,`s`), minutes (`min`,`m`), and hours (`hrs`,`h`).\n\nMoreover, it is possible to create repeated intervals\n\n```\n4x 5min @ 95% FTP, 5min @ 85% FTP\n```\n\nFinally, a complete workout can be defined as follows\n\n```\n10min from 40 to 85% FTP\n3x 5min @ 95% FTP, 5min @ 86% FTP\n5min @ 50% FTP\n3x 5min @ 95% FTP, 5min @ 86% FTP\n10min from 75 to 55% FTP\n```\n\nThe parser is rather robust when it comes to newlines and other whitespaces.\n\n### Usage\n\nYou can use the command line application\n\n```console\n$ zwog --help\nusage: zwog [-h] -i INPUT_FILE [-o OUTPUT_FILE] [-a AUTHOR] [-n NAME]\n [-c CATEGORY] [-s SUBCATEGORY] [-v]\n\nZwift workout generator\n\noptional arguments:\n -h, --help show this help message and exit\n -i INPUT_FILE, --input_file INPUT_FILE\n input filename\n -o OUTPUT_FILE, --output_file OUTPUT_FILE\n output filename\n -a AUTHOR, --author AUTHOR\n author name\n -n NAME, --name NAME workout name\n -c CATEGORY, --category CATEGORY\n category\n -s SUBCATEGORY, --subcategory SUBCATEGORY\n subcategory\n -v, --version show program's version number and exit\n```\n\nor call it from Python\n\n```python\nimport zwog\n\nworkout_text = \"15min from 10 to 50% FTP 5min from 50 to 70% FTP 2x 0.5hrs @ 100% FTP, 0.5hrs @ 50% FTP, 10min from 80 to 90% FTP 2min @ 50% FTP\\n2min @ 50% FTP\\n 10min @ 50% FTP, 10min @ 60% FTP 10min from 50 to 10% FTP\"\nworkout = zwog.ZWOG(workout_text)\nworkout.save_zwo('workout.xml')\nprint(workout)\nprint(f\"{round(workout.tss)} TSS\")\n```\n\n### Limitations\n\n- Only the [ZWO file format](https://github.com/h4l/zwift-workout-file-reference/blob/master/zwift_workout_file_tag_reference.md) is supported currently\n- Workout files have to be uploaded [manually](https://zwiftinsider.com/load-custom-workouts/) to Zwift\n",
"bugtrack_url": null,
"license": "BSD-3-Clause",
"summary": "Zwift workout generator",
"version": "1.0.0",
"project_urls": {
"Bug Tracker": "https://github.com/tare/zwog/issues",
"Homepage": "https://github.com/tare/zwog",
"Repository": "https://github.com/tare/zwog"
},
"split_keywords": [
"zwift",
"cycling",
"workout"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "3110eb8c057bad4e5cba029ca18f64f0de459ee56435e8b94f6232eb395fdf23",
"md5": "746c6fd2fa5eacb00f1a64f0e15018bc",
"sha256": "e728d46ff141da5ece95747de26dd990e7ed8014020dc88b9b9202cf1b1a67c9"
},
"downloads": -1,
"filename": "zwog-1.0.0-py3-none-any.whl",
"has_sig": false,
"md5_digest": "746c6fd2fa5eacb00f1a64f0e15018bc",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.8,<4.0",
"size": 7779,
"upload_time": "2023-12-29T21:01:31",
"upload_time_iso_8601": "2023-12-29T21:01:31.050130Z",
"url": "https://files.pythonhosted.org/packages/31/10/eb8c057bad4e5cba029ca18f64f0de459ee56435e8b94f6232eb395fdf23/zwog-1.0.0-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "76967d4aef8d80384a9999013809356a80714ce3b0175196427f7e66c3bb91e2",
"md5": "974ab2c7e6a748ca795547e73a6d5097",
"sha256": "2d9ebc204a3a12ef61b4217005be6c66507785935d6aeade79629f5050fd4c3c"
},
"downloads": -1,
"filename": "zwog-1.0.0.tar.gz",
"has_sig": false,
"md5_digest": "974ab2c7e6a748ca795547e73a6d5097",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.8,<4.0",
"size": 7728,
"upload_time": "2023-12-29T21:01:32",
"upload_time_iso_8601": "2023-12-29T21:01:32.754068Z",
"url": "https://files.pythonhosted.org/packages/76/96/7d4aef8d80384a9999013809356a80714ce3b0175196427f7e66c3bb91e2/zwog-1.0.0.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2023-12-29 21:01:32",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "tare",
"github_project": "zwog",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"tox": true,
"lcname": "zwog"
}