Table of Contents
- TDL
- Cut to the chase already
- Motivation
- Note for developers
- Usage
- EBNF
- Examples
- Minimal Example
- Starting Strength
- Final Note
TDL
TDL is a Training Description Language for weightlifting schedules. You write a simple .tdl file with your setup and the program computes the concrete weights and sets for your training days. You can also let the program print the needed plates for each weight.
Cut to the chase already
Alright, alright. The simplest way to use this is:
- Choose one of the releases and unzip it.
- Take one of the example .tdl's, move it to the folder that TDL.exe is in and rename it to 'mySchedule.tdl'. Customize it - at least put your maxes in. It's a plain text file, so if you have no other options you can edit it with Notepad.
- Double-click on 'TDL.exe'. You might have to by-pass Windows' so-called SmartScreen. There's an option to execute the program anyways under 'more details'.
- Find your computed schedule in 'Schedule-TIMESTAMP.md'. When you open the file, make sure that you are using a monospace font (e.g. Lucida Console) or else the tables will not be aligned.
The more in-depth description follows.
Motivation
I lift weights on a regular basis and, like most serious lifters, I do so according to a plan that is based around certain set templates and weight percentages. Calculating that stuff manually is tedious and error-prone. Using an Excel/LibreOffice spreadsheet would certainly be possible, but is a) not necessarily readable, b) cumbersome to set up and c) not easily adaptable in case your lifting plan changes.
I used a Python script with some clunky .yaml files for this purpose before, but it was not exactly what I wanted. And it was certainly not usable for other people (and by that I mean non-Computer-Science people). It took me a while to realize that I'm dealing with a language problem here: A language is needed to formally specify a lifting plan. And once that lifting plan is formally specified, a program can generate the actual values.
Since my IQ tends to drop to zero when I'm lifting weights, I also need to write down the plates for each set. So TDL contains an option for that as well.
Note for Developers
The Makefile(s) assume that you are running a Linux/Unix setup with Mono. If you don't, you might have to change path separators (replace '/' with '\') in the Makefiles and change the compiler to msbuild. The folder CocoR contains a copy of the Coco/R compiler generator, the folder TDL contains the attributed grammar (.atg) and the driver program (.cs)
Usage
If you don't pass in any command-line options (i.e. if you just double-click the executable), the program will assume that your .tdl file resides in 'mySchedule.tdl' and will put the generated values in Schedule-TIMESTAMP.md
If you want to make the program use the console as output instead, use the option '-stdout'.
If you want to use a different input file, just pass the filename.
You can run this program on either Windows or Linux. For Linux you need to install Mono. On Windows everything should work out of the box.
EBNF
The language is formally specified as an attributed grammar for the Coco/R compiler generator, which is basically a grammar in EBNF and some corresponding C# actions. If you are not a computer scientist or linguist, you might want to skip to the examples.
The core of the language resides in the lifts (that are specified as tuple of name, max and increment) and the training days (which are specified as a sequence of lifts with sets). And then there are a lot of constructs to make life way simpler.
TDL = [Options] Lifts [Plates] [SetTemplates] TrainingDays [Cycle] EOF .
Options = "Options:" Option { "," Option } .
Option = "printPlates" | "unlimitedPlates" | "lbs" | "StartingStrength" | "noMaxInfo" .
Plates = "Plates:" [ Plate { "," Plate } ] .
Plate = Weight [ 'x' Amount ] .
SetTemplates = "SetTemplates:" { SetTemplate } .
SetTemplate = SetTemplateIdent ':' SetTemplateItems .
SetTemplateItems = SetTemplateItem { ',' SetTemplateItem } .
SetTemplateItem = Set | SetTemplateIdent [ 'x' Amount ] .
Set = Amount [ '+' ] ( "reps" | "rep" ) '@' Percentage '%' [ '+' Weight ("kg"|"lbs") ] [ 'x' Amount ] [ comment ] .
Lifts = "Lifts:" Lift{","Lift} .
Lift = LiftIdent "Max:" Weight [ "increment:" Weight [ "%" ] ] [ "bar:" Weight ] [ "noPlates" ] .
TrainingDays = "TrainingDays:" TrainingDay { TrainingDay } .
TrainingDay = ( ( '-' [ "Name:" DayIdent ] TrainingDayItems ) | ( "repeat" DayIdent ) | ( "makeDays" SetTemplateIdent '(' LiftIdent { ',' LiftIdent } ')' [ "increaseAll" ] ) ) .
TrainingDayItems = TrainingDayItem { TrainingDayItem } .
TrainingDayItem = LiftSchedule | string .
LiftSchedule = LiftIdent ':' SetTemplateItems [ "increase" [ Weight [ "%" ] ] ] .
Cycle = "cycle" Amount "times" .
Amount = integer .
Percentage = integer|float .
Weight = integer|float .
DayIdent = ident .
LiftIdent = ident .
SetTemplateIdent = ident .
Examples
I made a few examples to show what the language is actually about. I will list two of them here, you can find more in the folder examples.
Minimal Example
Input:
/* minimal example */
Lifts:
OHP Max: 100 increment: 2.5
TrainingDays:
- OHP: 5 reps @ 100%
Output:
Old Maxes
=========
OHP: 100.00 kg
Day 1
======
OHP
----
| Sets |
| -------------- |
| 100.00 kg x 5 |
New Maxes
=========
OHP: 100.00 kg
Starting Strength
The Starting Strength program is not usually expressed in terms of percentages. Rippetoe states that you should start with an empty bar and throw in three warm-up sets. These warm-up sets should have their weight evenly spread between the empty bar and the work sets. This is hard to express as percentages of the total weight on the bar - but if you reformulate everything in terms of weight added to the bar, you end up with 25%, 50% and 75% for the warm-up sets. Easy-peasy.
Input:
/* TDL for two weeks of Starting Strength */
Options:
printPlates,
StartingStrength // implies expression of weights and percentages as _added_ bar weight!
Lifts:
Squat Max: 60.5 increment: 5,
Deadlift Max: 66.0 increment: 5,
Bench Max: 42 increment: 2.5,
Press Max: 20 increment: 2.5,
PowerClean Max: 20 increment: 2.5
Plates:
SetTemplates:
empty:
5 reps @ 0%
warmups:
5 reps @ 25%,
3 reps @ 50%,
2 reps @ 75%
workset:
5 reps @ 100%
worksetsClean:
3 reps @ 100% x 5
regularSets:
empty,empty,warmups,workset x 3
deadliftSets:
empty,empty,warmups,workset
cleanSets:
empty,empty,warmups,worksetsClean
TrainingDays:
- Name: DayA
Squat: regularSets
Press: regularSets increase
Deadlift: deadliftSets increase
- Name: DayB
Squat: regularSets increase
Bench: regularSets increase
PowerClean: cleanSets increase
"3 sets of 5 weighted chin-ups"
cycle 3 times
Output:
Old Maxes
=========
Bench: 42.00 kg
Deadlift: 66.00 kg
PowerClean: 20.00 kg
Press: 20.00 kg
Squat: 60.50 kg
Day 1
======
Squat
----
| Sets | Plates | |
| ------------- | --------- | ----------------- |
| 00.00 kg x 5 | No plates | |
| 00.00 kg x 5 | No plates | |
| 15.13 kg x 5 | 5, 2.5 | -> 15.00 kg + bar |
| 30.25 kg x 3 | 10, 5 | -> 30.00 kg + bar |
| 45.38 kg x 2 | 20, 2.5 | -> 45.00 kg + bar |
| 60.50 kg x 5 | 20, 10 | -> 60.00 kg + bar |
| 60.50 kg x 5 | 20, 10 | -> 60.00 kg + bar |
| 60.50 kg x 5 | 20, 10 | -> 60.00 kg + bar |
Press
----
| Sets | Plates | |
| ------------- | --------- | ----------------- |
| 00.00 kg x 5 | No plates | |
| 00.00 kg x 5 | No plates | |
| 05.00 kg x 5 | 2.5 | -> 5.00 kg + bar |
| 10.00 kg x 3 | 5 | -> 10.00 kg + bar |
| 15.00 kg x 2 | 5, 2.5 | -> 15.00 kg + bar |
| 20.00 kg x 5 | 10 | -> 20.00 kg + bar |
| 20.00 kg x 5 | 10 | -> 20.00 kg + bar |
| 20.00 kg x 5 | 10 | -> 20.00 kg + bar |
Deadlift
----
| Sets | Plates | |
| ------------- | ------------- | ----------------- |
| 00.00 kg x 5 | No plates | |
| 00.00 kg x 5 | No plates | |
| 16.50 kg x 5 | 5, 2.5 | -> 15.00 kg + bar |
| 33.00 kg x 3 | 10, 5, 1.25 | -> 32.50 kg + bar |
| 49.50 kg x 2 | 20, 2.5, 1.25 | -> 47.50 kg + bar |
| 66.00 kg x 5 | 20, 10, 2.5 | -> 65.00 kg + bar |
Day 2
======
Squat
----
| Sets | Plates | |
| ------------- | --------- | ----------------- |
| 00.00 kg x 5 | No plates | |
| 00.00 kg x 5 | No plates | |
| 15.13 kg x 5 | 5, 2.5 | -> 15.00 kg + bar |
| 30.25 kg x 3 | 10, 5 | -> 30.00 kg + bar |
| 45.38 kg x 2 | 20, 2.5 | -> 45.00 kg + bar |
| 60.50 kg x 5 | 20, 10 | -> 60.00 kg + bar |
| 60.50 kg x 5 | 20, 10 | -> 60.00 kg + bar |
| 60.50 kg x 5 | 20, 10 | -> 60.00 kg + bar |
Bench
----
| Sets | Plates | |
| ------------- | --------- | ----------------- |
| 00.00 kg x 5 | No plates | |
| 00.00 kg x 5 | No plates | |
| 10.50 kg x 5 | 5 | -> 10.00 kg + bar |
| 21.00 kg x 3 | 10 | -> 20.00 kg + bar |
| 31.50 kg x 2 | 10, 5 | -> 30.00 kg + bar |
| 42.00 kg x 5 | 20 | -> 40.00 kg + bar |
| 42.00 kg x 5 | 20 | -> 40.00 kg + bar |
| 42.00 kg x 5 | 20 | -> 40.00 kg + bar |
PowerClean
----
| Sets | Plates | |
| ------------- | --------- | ----------------- |
| 00.00 kg x 5 | No plates | |
| 00.00 kg x 5 | No plates | |
| 05.00 kg x 5 | 2.5 | -> 5.00 kg + bar |
| 10.00 kg x 3 | 5 | -> 10.00 kg + bar |
| 15.00 kg x 2 | 5, 2.5 | -> 15.00 kg + bar |
| 20.00 kg x 3 | 10 | -> 20.00 kg + bar |
| 20.00 kg x 3 | 10 | -> 20.00 kg + bar |
| 20.00 kg x 3 | 10 | -> 20.00 kg + bar |
| 20.00 kg x 3 | 10 | -> 20.00 kg + bar |
| 20.00 kg x 3 | 10 | -> 20.00 kg + bar |
Other
----
3 sets of 5 weighted chin-ups
etc...
Final Note
If you use TDL and like it, let me know: gutmet.tdl [at] allfex.org.
Thanks go to:
- Adrian Wilke
- Jan Lippert