GithubHelp home page GithubHelp logo

sco1 / zwom Goto Github PK

View Code? Open in Web Editor NEW
1.0 1.0 0.0 99 KB

Python toolkit for the ZWO minilang

License: MIT License

Python 100.00%
cli cycling cycling-workouts python python3 python311 zwift parser

zwom's Introduction

Hi there, I'm sco1! ๐Ÿ‘‹

StackOverflow Slack HackerNews Mastodon

I'm a Boston-based Aerospace Engineer focused on test & evaluation.

Programming Interests

  • Data collection, postprocessing, and visualization
  • CLI and GUI tooling
  • Code quality
  • Software testing

I also find joy in making hilarious things like:

zwom's People

Contributors

pre-commit-ci[bot] avatar sco1 avatar

Stargazers

 avatar

Watchers

 avatar

zwom's Issues

Additional Power Specification Syntax

As talked about in the original syntax brainstorm (#2), it would be nice to be able to specify power values in terms of Power Zones, e.g. (L|M|H)Z<1-7>, or SS, in addition to the currently supported percentage and aboslute wattage values.

When adding Power Zone segments using the UI, Zwift currently assigns them as the following:

  • Z1 = 50%
  • Z2 = 65%
  • Z3 = 81%
  • Z4 = 95%
  • Z5 = 109%
  • Z6 = 125%

Sweet Spot (SS) intervals are generally defined between 88% โ€“ 94%, so we can put those at 90%

For the Peloton folks, we can add a Zone 7 at 150%

This can be investigated after the rest of our initial functionality is complete & tested.

[Meta] Initial Grammar

Here's the gist of the proposed syntax:

META {
    NAME "My Workout",
    AUTHOR "Some Author",
    DESCRIPTION "Here's a description!",
    FTP 270,
}

FREE {DURATION 10:00}
INTERVALS {
    COUNT 3,
    DURATION 1:00 -> 0:30,
    POWER 55% -> 78%,
    CADENCE 85 -> 110,
}
SEGMENT {DURATION 2:00, POWER 65%}
RAMP {
    DURATION 2:00, 
    POWER 120% -> 140%,
    @ 0:00 "Here goes the ramp!",
    @ 1:50 "10 seconds left!",
}
FREE {DURATION 10:00}

Each file should start with a META block, containing the workout's metadata:

  • NAME: quoted string
  • AUTHOR: quoted string
  • DESCRIPTION: quoted string, can be multiline
  • TAGS: quoted string, comma separated list (optional)
  • FTP: integer (optional)
    • Not used in the *.zwo itself, but used for normalizing wattage & for workout summary generation

Then the rest of the workout block(s) follow:

  • SEGMENT
  • FREE
  • INTERVALS
  • RAMP
  • WARMUP (Seems to be the same as RAMP?)

Each block has its own set of possible metadata:

  • DURATION
    • Required for all block types
    • Provided as: mm:ss or integer seconds
    • For INTERVAL, durations can be specified as <A> -> <B>
  • POWER
    • Required for: INTERVAL, RAMP, SEGMENT, WARMUP
    • Provided as: <int>%, <int>W, (L|M|H)Z<1-7>, or SS
    • For INTERVAL, RAMP, and WARMUP, the power range can be specified as <A> -> <B>
  • COUNT
    • Required for: INTERVAL
    • Provided as: <int>
  • CADENCE
    • Optional for all block types
    • Provided as: <int>
    • For INTERVAL, the cadence range can be specified as <A> -> <B>
      • Are ranges valid for other segment types?
  • @ <time offset> "<str>"
    • Optional for all block types
    • Print a message at the provided time offset
    • Time offsets are relative to the beginning of the block and are provided as: mm:ss or integer seconds

Within blocks metadata is comma separated, with trailing commas optional. Whitespace is arbitrary.

And some thoughts on the grammar:

workout: declaration* EOF

declaration:
    | blockDecl

blockDecl: tag "{" parameters? "}"

parameters: tag value ( "," ( tag value ) | message )*

tag:
    | "AUTHOR"
    | "CADENCE"
    | "COUNT"
    | "DESCRIPTION"
    | "DURATION"
    | "FREE"
    | "FTP"
    | "INTERVALS"
    | "META"
    | "NAME"
    | "POWER"
    | "SEGMENT"
    | "TAGS"
    | "WARMUP"

value:
    | percentage
    | primary
    | range
    | time

message: "@" time "," STRING

time: (numeric) ":" (numeric)
range: (numeric) "->" (numeric)
percentage: (numeric) "%"

primary:
    | NUMBER
    | STRING

Consider refactoring post-validated block types

The typing is a mess. Currently, typing for serialization uses the types defined by the parser which are broader than what comes out of the validator. This leads to a lot of type narrowing that isn't necessary because the validation step has thrown out values that aren't acceptable for each parameter.

I think it's possible to narrow the post-validation types into something structural, so let's look at that soon.

Better Error Reporting

Currently, the parser and validation are left to report errors on their own, these should be reported to the user in a more reader-friendly manner, and ideally gathered up for the entire file at once. Even more ideally with location in the ZWOM file but that may require a larger change.

Ramp Classification Bugged for End of Ride Ramps

Currently, the assumption is being made that if a ramp block is at the end of a workout then it should be considered a cooldown block for serialization:

zwom/zwo/serialize.py

Lines 246 to 251 in 2c93ff6

if block_idx == 1:
return BLOCK_MAPPING[Tag.WARMUP]
if block_idx == n_blocks:
return BLOCK_MAPPING[Tag.COOLDOWN]
else:
return BLOCK_MAPPING[Tag.RAMP]

This assumption works mostly fine, except when we want to have a workout with a ramp at the end, like KM's FTP protocols. Zwift seems to force the low power to the end of the ramp for cooldown blocks, which results in the ramp starting high and going low instead of the other way around.

If you go to edit the workout in Zwift's editor it appears to fix itself & change the block's type to Ramp instead of Cooldown. We'll have to incoporate the left & right power targets into the classification logic.

Metasyntax for repeat chunks

It would be nice to have a syntax to specify repeat chunks in a workout that aren't explicitly intervals.

For example, it would be nice to not have to copy+paste this same block 3 times:

RAMP {
    DURATION 2:00,
    POWER 120% -> 140%
}
SEGMENT {DURATION 2:00, POWER Z2}
RAMP {
    DURATION 2:00,
    POWER 120% -> 140%
}
SEGMENT {DURATION 2:00, POWER Z2}
RAMP {
    DURATION 2:00,
    POWER 120% -> 140%
}
SEGMENT {DURATION 2:00, POWER Z2}

Comment support

We should be able to specify comments in the ZWOM file, definitely single-line and ideally also multiline

~r"\;[^\r\n]*" should theoretically give us a single line comment starting with ;

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.