Zwift workout generator command line tool and library
Go to file
Rene Saarsoo 93684069f0 New meaning of negative offsets (breaking change)
Instead of always being relative to interval end,
negative offsets are now relative to next comment
(or the interval end, when there is no next comment).
2021-03-02 23:32:05 +02:00
bin Rename to zwiftout + add docs 2020-10-04 15:02:17 +03:00
examples Add another workout example 2020-11-22 21:32:53 +02:00
src New meaning of negative offsets (breaking change) 2021-03-02 23:32:05 +02:00
test Assign the same TSS score to FreeRide as Zwift does 2020-12-25 20:25:54 +02:00
.eslintrc.js Improve lint:js and lint:ts setup 2020-09-25 09:28:07 +03:00
.gitignore Add script in bin/ and building of .ts files 2020-10-01 20:25:16 +03:00
.npmignore Add empty .npmignore to ensure dist/ files are included 2020-10-01 20:45:02 +03:00
.prettierrc Enforce trailing commas 2020-09-21 18:15:45 +03:00
README.md Link to zwo-sucks blog post 2021-01-14 22:09:42 +02:00
jest.config.js Jest setup 2020-09-21 16:17:30 +03:00
package.json v1.1.0 2021-01-13 21:29:12 +02:00
tsconfig.json Separate tsconfig for release (which excludes tests) 2020-10-02 11:49:41 +03:00
tsconfig.release.json Separate tsconfig for release (which excludes tests) 2020-10-02 11:49:41 +03:00
yarn.lock Use argparse for parsing command-line options 2020-09-30 15:03:33 +03:00

README.md

Zwiftout

Zwift workout generator command line tool and library.

Used as engine for the online workout-editor.

Motivation

Creating custom workouts is a pain.

The workout editor in Zwift is pretty clumsy and slow to use:

  • drag'n'drop is not the fastest way to edit,
  • positioning of messages is especially tricky as they easily jump out of place,
  • there's no copy-paste functionality to speed things up.

Editing .zwo files by hand is also inconvenient:

  • you'll have to constantly convert minutes to seconds,
  • you can easily make errors in XML syntax, rendering the file invalid,
  • it's really a bad format.

There are a few alternative editors online:

  • ZWOFactory is very much point'n'click based which doesn't help much with speeding up the process.
  • Simple ZWO Creator is more akin to my liking as it's text-based. But it's lacking lots of features: no way to add cadence, text messages, warmup/cooldown etc. The syntax used is also kinda confusing.

Features

  • Fully text-based workout creation.
  • Easily add cadence targets.
  • Easily place text-messages within intervals.
  • Support for Warmup/Cooldown & FreeRide interval types.
  • Automatic detection of repeated intervals - conversion to <IntervalsT> in .zwo file.
  • Generation of stats: average and normalized intensity, TSS, zone-distribution.

Install

$ npm install -g zwiftout

Usage

Write a workout description like:

Name: Sample workout
Author: John Doe
Tags: Recovery, Intervals, FTP
Description: Try changing it, and see what happens below.

Warmup: 10:00 30%..75%
Interval: 15:00 100% 90rpm
  @ 00:00 Start off easy
  @ 01:00 Settle into rhythm
  @ 07:30 Half way through
  @ 14:00 Final minute, stay strong!
Rest: 10:00 75%
FreeRide: 20:00
  @ 00:10 Just have some fun, riding as you wish
Cooldown: 10:00 70%..30%

Feed that file into zwiftout program, which spits out Zwift workout XML:

$ zwiftout my-workout.txt > my-workout.zwo

Also, you can query various stats about the workout:

$ zwiftout --stats my-workout.txt

Total duration: 65 minutes

Average intensity: 50%
Normalized intensity: 75%

TSS: 60

Zone Distribution:
 14 min - Z1: Recovery
  6 min - Z2: Endurance
 10 min - Z3: Tempo
 15 min - Z4: Threshold
  0 min - Z5: VO2 Max
  0 min - Z6: Anaerobic
 20 min - Freeride

Usage as library

import { parse, generateZwo, stats } from "zwiftout";

const workout = parse(`
Name: Sample workout
Warmup: 10:00 30%..75%
Interval: 15:00 100% 90rpm
`);

// Output ZWO file
console.log(generateZwo(workout));

// Output various statistics
console.log(stats(workout));

TODO

  • Repeats (and nested repeats)
  • Unsupported params: message duration & y-position
  • More restricted syntax for text (with quotes)
  • Concatenate similar intervals
  • Distinguish between terrain-sensitive and insensitive free-ride.
  • Syntax for comments placed relative to previous ones, e.g. @ +00:10
  • Use <Ramp> in addition to <Warmup> and <Cooldown>