Workout builder

Hey @Max_Nelson , nice for the community to put this up!

Then, it doesn’t really help me;-) Using Emacs & my Python code above gets me the i.icu text much faster than even opening yet another website – thus I would hope that @David will still eventually add an “WoZ importer/converter” to the workout builder of i.icu;-) That would be an real improvement (for me)

2 Likes

It’s fabulous. Brilliant you. Thank you.

2 Likes

@david playing around w/ the builder. Noticed something strange.

for the last interval. I wanted to change it from 4m47s to 4m but noticed something interesting, when putting 4m00s instead of 4m, looks like it interpreted it differently, it considered it as not part of the 3x interval.

Nothing serious, just thot I’ll share

cheers for sharing, almost forgot I made this aha

2 Likes

Thanks for putting that together @Ben. I noticed you had some Rubik’s cube stuff too. I can’t solve them, but my 13 yo kid is crazy into them. Has every cube, pyramid, dodecahedron, etc imaginable and can solve up to a 10 by 10. :+1:

Good stuff, you should have a play with the 3x3. Using a beginner technique you’d be surprised how quickly you’ll be able to solve your first one.

David, I should have added, if you want to steal any code to integrate it into here just take it. It’s the only time I’ve ever used js so it’s probably junk could be a start

2 Likes

Tx I fixed that weirdness and will deploy Monday AM GMT+2.

2 Likes

Have you thought about allowing workouts by HR zone? Example:

Warm Up

  • 40m 1-2 HRZ

Hill Sprints: 10x

  • 10s 7 HRZ
  • 30s 1-1.5 HRZ, rest interval

Cool Down

  • 8m 1-1.8 HRZ

In this example the HRZ would indicate to use your current heart rate zones. You could enter a fraction and it would calculate the equivalent HR for you.

2 Likes

Yes I do have that (and power zones) on the todo list but I didn’t think of doing it that way. Tx.

1 Like

how would those workouts look like? As in how would it be able to be downloaded to be executed?
currently I’m pulling workouts as MRC files and parsing that.

Power based workouts using zones will still be downloadable as MRC, ERG or ZWO. The zones will be resolved at download time.

HR and pace based workouts can be uploaded to Garmin Connect for sync to Garmin devices. I will do a .fit file download for them at some point.

1 Like

thanks. I was thinking along the lines of users who which to instead train using HR on the bike actually. sorry for not being more specific.

I’ve updated my Python script to create i.icu-style workouts directly from the workout URL – run as zwift-to-i.icu https://whatsonzwift.com/workouts/build-me-up/week-7-lox to extract the workout from the whatsonzwift workout page and write out in i.icu format.

Now also retrieves the workout description from the website

#!/usr/bin/env python
# -*- coding: utf-8; fill-column: 120; truncate-lines: t -*-

import re
import sys

import requests
from bs4 import BeautifulSoup


def metadata(url):
    name = url.rpartition('/')[2]
    page = requests.get(url)
    soup = BeautifulSoup(page.content, "html.parser")
    results = soup.find(class_="two-thirds column workoutdescription").find_all('p')
    return results[-2].text


def workout(url):
    name = url.rpartition('/')[2]
    page = requests.get(url)
    soup = BeautifulSoup(page.content, "html.parser")
    results = soup.find(id=name).find_all(class_="textbar")
    zwift = ''
    for element in results:
        zwift += element.text.strip()
        zwift += '\n'
    return zwift[0:-1]


def convert(zwift):
    icu = ""
    multiplier = False

    # expand multipliers into old text-format multiple lines :-o)
    zwift = re.sub('FTP,', 'FTP,\n', zwift)
    # expand multiplied lines
    for line in zwift.split('\n'):
        if re.match('^[1-9]+[xX] .*,\\s*\\Z', line):
            icu += '\n' + line[:3] + '\n'
            icu += '- ' + line[3:] + '\n'
            multiplier = True
        elif re.match('^[1-9]+[xX]', line):
            icu += '\n' + line[:3] + '\n'
            icu += '- ' + line[3:] + '\n'
            multiplier = False
        elif multiplier == True:
            icu += '- ' + line + '\n\n'
            multiplier = False
        else:
            icu += '- ' + line + '\n'

    # replace words and fix grammar
    icu = icu.replace('min', 'm').replace('sec', 's') \
            .replace('from', 'ramp').replace(' to ', '-') \
            .replace('FTP', '').replace(',', '').replace('@', '').replace('  ', ' ') \
            .replace('\n+', '\n') + '\n'
    icu = re.sub('([0-9]+m) ([0-9]+s)', '\\1\\2', icu)

    return icu



if __name__ == '__main__':
    print(metadata(sys.argv[1]), '\n')
    print(convert(workout(sys.argv[1])))
5 Likes

Hello!

This might not be the best place, but it’s related to the workout builder.

I was wondering, we’re all creating workouts individually. It might be an idea to have a central, public workout library for every user. Like an open source place. From there you can always customize to personal needs.

Saves duplicates, but moreover, we can inspire each other. :slight_smile:

6 Likes

I used this facility in BKool a lot last year. Great idea.

You can publish workout folders and plans to groups and then anyone in the group can add them to their own library. However I am planning to add public profiles and public plans/folders soon which will do some of what you want. The plans/folders made public will be searchable.

9 Likes

What about running workout?
Also it can be useful have distance instead of time for interval.

4 Likes

That is on the todo list (and much requested). Right now you can get distance info after choosing time and pace in the “Add Step” dialog. Not quite the same I know.

6 Likes

Super stoked that workouts by distance (esp. swimming) is on the to do. :smiley:

7 Likes

Good news.
So we have only to wait and support