commit e21ccb1baec1af9db7b89216e324502ac1c35f86 Author: gutmet Date: Wed Nov 4 22:27:06 2020 +0100 "initial" diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..1f230a6 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +TDL +go.sum +/*.tdl diff --git a/License.md b/License.md new file mode 100644 index 0000000..41ca1d4 --- /dev/null +++ b/License.md @@ -0,0 +1,17 @@ +TDL: TrainingDescriptionLanguage and parser for weightlifting schedules. +Copyright (C) 2016-2020 Alexander Weinhold + +Unless explicitly stated otherwise, the following applies: + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . diff --git a/Readme.md b/Readme.md new file mode 100644 index 0000000..324ecff --- /dev/null +++ b/Readme.md @@ -0,0 +1,74 @@ +TDL +=== + +TDL is a language for weightlifting schedules and a corresponding generator. +From a file with descriptions of sets and percentages the program computes +concrete training days and plates needed. + + +Usage +----- + +``` +TDL yourSchedule.tdl +``` + +You find the output in yourSchedule-TIMESTAMP.txt + +See the examples folder for inspiration to writer your schedule file. + + + +Beer Note +--------- + +You can buy me a beer [here](http://paypal.me/AlexanderWeinhold). + + + +Grammar +------- + +For completeness' sake, the grammar in EBNF looks like this: + +``` +TDL = Lifts [Plates] [SetTemplates] TrainingDays EOI . + +Lifts = "Lifts:" Lift {"," Lift} . + +Lift = LiftIdent "Max:" Weight "Increment:" Weight [ "%" ] [ "Bar:" Weight ] . + +Plates = "Plates:" Plate { "," Plate } . + +Plate = Weight 'x' Amount . + +SetTemplates = "SetTemplates:" "-" SetTemplate { "-" SetTemplate } . + +SetTemplate = SetTemplateIdent SetTemplateItem { ',' SetTemplateItem } . + +SetTemplateItem = SetTemplateIdent | Set [ 'x' Amount ] . + +Set = Amount "reps" '@' Percentage '%' [ '+' Weight ] [ 'x' Amount ] [ Notice ] . + +TrainingDays = "TrainingDays:" "-" TrainingDay { "-" TrainingDay } . + +TrainingDay = TrainingDayItem { TrainingDayItem } . + +TrainingDayItem = string | LiftSchedule. + +LiftSchedule = LiftIdent ':' SetTemplateItem { ',' SetTemplateItem } [ "increase" [ Weight [ "%" ] ] ] . + +Amount = integer . + +Percentage = integer|float . + +Weight = integer|float . + +LiftIdent = ident . + +SetTemplateIdent = ident . + +Notice = '(' ANY ')' . +``` + +Comments can be enclosed in square brackets and are ignored. diff --git a/TDL.go b/TDL.go new file mode 100644 index 0000000..d6861bf --- /dev/null +++ b/TDL.go @@ -0,0 +1,76 @@ +package main + +import ( + "flag" + "fmt" + "io" + "io/ioutil" + "os" + "path" + "strings" + "time" +) + +const ( + STAMP_FORMAT = "20060102-150405" +) + +func checkUsage(debugFlag string, args []string) { + if debugFlag != "" && debugFlag != "lexer" && debugFlag != "parser" && debugFlag != "search" { + fmt.Fprintln(os.Stderr, "invalid value for 'debug'") + os.Exit(1) + } + if len(args) != 1 { + fmt.Fprintln(os.Stderr, "USAGE:", os.Args[0], "FILE") + os.Exit(1) + } +} + +func outfile(infile string) io.Writer { + basename := path.Base(infile) + extension := path.Ext(basename) + basename = strings.TrimSuffix(basename, extension) + name := basename + time.Now().Format(STAMP_FORMAT) + ".txt" + f, err := os.OpenFile(name, os.O_CREATE|os.O_WRONLY, 0644) + if err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(1) + } + fmt.Println(name) + return f +} + +func main() { + var debug string + var stdout bool + flag.StringVar(&debug, "debug", "", "debug output of 'lexer', 'parser' or 'search'") + flag.BoolVar(&stdout, "stdout", false, "use stdout instead of file output") + flag.Parse() + args := flag.Args() + checkUsage(debug, args) + filename := args[0] + bytes, err := ioutil.ReadFile(filename) + if err != nil { + fmt.Fprintln(os.Stderr, err) + } else { + input := []rune(string(bytes)) + switch debug { + case "lexer": + DebugLexer(input, os.Stdout) + case "parser": + DebugParser(input, os.Stdout) + case "search": + DebugSearch(input) + default: + parsed := NewParser(input).Parse() + var writer io.Writer + if stdout { + writer = os.Stdout + } else { + writer = outfile(filename) + } + generator := NewStdGenerator(writer) + generator.Generate(parsed) + } + } +} diff --git a/TDL_test.go b/TDL_test.go new file mode 100644 index 0000000..adfb854 --- /dev/null +++ b/TDL_test.go @@ -0,0 +1,92 @@ +package main + +import ( + "bytes" + "fmt" + "io/ioutil" + "path" + "testing" +) + +func exampleFiles() []string { + files, err := ioutil.ReadDir("example") + if err != nil { + panic(err) + } + names := []string{} + for _, file := range files { + names = append(names, path.Join("example", file.Name())) + } + return names +} + +func referenceFile(infile string, suffix string) string { + return path.Join("test", path.Base(infile)+suffix) +} + +func readFile(t *testing.T, file string) string { + bytes, err := ioutil.ReadFile(file) + if err != nil { + t.Error(err) + } + return string(bytes) +} + +func TestLexer(t *testing.T) { + for _, file := range exampleFiles() { + t.Run(file, func(t *testing.T) { + input := readFile(t, file) + var buf bytes.Buffer + DebugLexer([]rune(input), &buf) + output := buf.String() + reference := readFile(t, referenceFile(file, ".lexer")) + if output != reference { + t.Fail() + } + }) + } +} + +func TestParser(t *testing.T) { + for _, file := range exampleFiles() { + t.Run(file, func(t *testing.T) { + input := readFile(t, file) + var buf bytes.Buffer + DebugParser([]rune(input), &buf) + output := buf.String() + reference := readFile(t, referenceFile(file, ".parser")) + if output != reference { + t.Fail() + } + }) + } +} + +func TestSearch(t *testing.T) { + available := map[float64]int{ + 20: 26, + 10: 2, + 5: 2, + 2.5: 2, + 1.25: 2, + 0.5: 2, + } + tests := map[float64][]float64{ + 17: []float64{5, 2.5, 0.5}, + 42: []float64{20, 0.5}, + 80: []float64{20, 20}, + } + for input, reference := range tests { + t.Run("search"+fmt.Sprint(input), func(t *testing.T) { + output := SearchPlates(available, input) + if len(reference) != len(output) { + t.Fail() + } + for i := 0; i < len(reference); i++ { + if reference[i] != output[i] { + t.Fail() + } + } + }) + } +} diff --git a/example/531_BoringButBig.tdl b/example/531_BoringButBig.tdl new file mode 100644 index 0000000..70f2808 --- /dev/null +++ b/example/531_BoringButBig.tdl @@ -0,0 +1,90 @@ +Lifts: + Squat Max: 200 Increment: 5, + Deadlift Max: 250 Increment: 5, + Bench Max: 120 Increment: 2.5, + Press Max: 90 Increment: 2.5 + +SetTemplates: +- warmup: + 5 reps @ 40%, + 5 reps @ 50%, + 3 reps @ 60% + +- fiveRep: + warmup, + 5 reps @ 65%, + 5 reps @ 75%, + 5 reps @ 85%, + 10 reps @ 50% x 5 + +- threeRep: + warmup, + 3 reps @ 70%, + 3 reps @ 80%, + 3 reps @ 90%, + 10 reps @ 50% x 5 + +- oneRep: + warmup, + 5 reps @ 75%, + 3 reps @ 85%, + 1 reps @ 95%, + 10 reps @ 50% x 5 + +- deload: + 5 reps @ 40% x 2, + 5 reps @ 50% x 2, + 3 reps @ 60% x 2 + +TrainingDays: + +- Press: fiveRep + "5 sets of 10 chin-ups" + +- Deadlift: fiveRep + "5 sets of 15 hanging leg raises" + +- Bench: fiveRep + "5 sets of 10 dumbbell rows" + +- Squat: fiveRep + "5 sets of 10 leg curls" + + +- Press: threeRep + "5 sets of 10 chin-ups" + +- Deadlift: threeRep + "5 sets of 15 hanging leg raises" + +- Bench: threeRep + "5 sets of 10 dumbbell rows" + +- Squat: threeRep + "5 sets of 10 leg curls" + + +- Press: oneRep + "5 sets of 10 chin-ups" + +- Deadlift: oneRep + "5 sets of 15 hanging leg raises" + +- Bench: oneRep + "5 sets of 10 dumbbell rows" + +- Squat: oneRep + "5 sets of 10 leg curls" + + +- Press: deload increase + "5 sets of 10 chin-ups" + +- Deadlift: deload increase + "5 sets of 15 hanging leg raises" + +- Bench: deload increase + "5 sets of 10 dumbbell rows" + +- Squat: deload increase + "5 sets of 10 leg curls" diff --git a/example/BillStarr_5x5_Intermediate.tdl b/example/BillStarr_5x5_Intermediate.tdl new file mode 100644 index 0000000..628b3be --- /dev/null +++ b/example/BillStarr_5x5_Intermediate.tdl @@ -0,0 +1,60 @@ +[ + * Max means 5RM in this context. Start with 92% of your + * actual 5RM, you are supposed to pass that number + * between weeks 3 and 4 +] + + +Lifts: + Squat Max: 180 Increment: 2.5%, + HighPull Max: 120 Increment: 2.5%, + Bench Max: 100 Increment: 2.5%, + Press Max: 75 Increment: 2.5%, + Clean Max: 80 Increment: 2.5% + +SetTemplates: +- Warmup: + 5 reps @ 40%, + 5 reps @ 55%, + 5 reps @ 70% + +- MondaySets: + Warmup, + 5 reps @ 85%, + 5 reps @ 100% + +- WednesdaySquat: + Warmup, + 5 reps @ 70% + +- WednesdayOther: + 5 reps @ 55%, + 5 reps @ 70%, + 5 reps @ 85%, + 5 reps @ 100% + +- FridaySets: + Warmup, + 5 reps @ 85%, + 3 reps @ 102.5%, + 8 reps @ 70% + + +TrainingDays: + - Squat: MondaySets + Bench: MondaySets + Clean: MondaySets + "2 sets of weighted hypers" + "4 sets of weighted sit-ups" + + - Squat: WednesdaySquat + Press: WednesdayOther increase + HighPull: WednesdayOther increase + "3 sets of sit-ups" + + - Squat: FridaySets increase + Bench: FridaySets increase + Clean: FridaySets increase + "3 sets of weighted dips (5-8 reps)" + "3 sets of barbell curls" + "3 sets of triceps extensons (8 reps)" diff --git a/example/Smolov_PhaseIn_And_BaseCycle.tdl b/example/Smolov_PhaseIn_And_BaseCycle.tdl new file mode 100644 index 0000000..fe3908c --- /dev/null +++ b/example/Smolov_PhaseIn_And_BaseCycle.tdl @@ -0,0 +1,70 @@ +Lifts: + Squat Max: 200 Increment: 0 + +TrainingDays: + +[ Week one ] + +- Squat: 8 reps @ 65% x 3, 5 reps @ 70%, 2 reps @ 75% x 2, 1 reps @ 80% + +- Squat: 8 reps @ 65% x 3, 5 reps @ 70%, 2 reps @ 75% x 2, 1 reps @ 80% + +- Squat: 5 reps @ 70% x 4, 3 reps @ 75%, 2 reps @ 80% x 2, 1 reps @ 90% + + +[ Week two ] + +- "Lunges" + Squat: 5 reps @ 80% + +- "Lunges" + Squat: 5 reps @ 82.5% + +- "Lunges" + Squat: 5 reps @ 85% + + +[ Week three ] + +- Squat: 9 reps @ 70% x 4 + +- Squat: 7 reps @ 75% x 5 + +- Squat: 5 reps @ 80% x 7 + +- Squat: 3 reps @ 85% x 10 + + +[ Week four ] + +- Squat: 9 reps @ 70% + 9 x 4 + +- Squat: 7 reps @ 75% + 9 x 5 + +- Squat: 5 reps @ 80% + 9 x 7 + +- Squat: 3 reps @ 85% + 9 x 10 + + +[ Week five ] + +- Squat: 9 reps @ 70% + 13.5 x 4 + +- Squat: 7 reps @ 75% + 13.5 x 5 + +- Squat: 5 reps @ 80% + 13.5 x 7 + +- Squat: 3 reps @ 85% + 13.5 x 10 + + +[ Week six ] + +- "Rest" + +- "Rest" + +- "Build to 1RM" + +- "Build to 1RM" + +[ Continue with Part 2 ] \ No newline at end of file diff --git a/example/Smolov_Switching_Intense_Taper.tdl b/example/Smolov_Switching_Intense_Taper.tdl new file mode 100644 index 0000000..790876f --- /dev/null +++ b/example/Smolov_Switching_Intense_Taper.tdl @@ -0,0 +1,68 @@ +[ Max is your 1RM of part one ] + +Lifts: + Squat Max: 230 Increment: 0 + +TrainingDays: + +[ Week seven ] + +- Squat: 1 reps @ 50% (several with dynamic effort) + +- Squat: 1 reps @ 50% (several with dynamic effort) + +- Squat: 1 reps @ 50% (several with dynamic effort) + + +[ Week eight ] + +- Squat: 1 reps @ 50% (several with dynamic effort) + +- Squat: 1 reps @ 50% (several with dynamic effort) + +- Squat: 1 reps @ 50% (several with dynamic effort) + + +[ Week nine ] + +- Squat: 3 reps @ 65%, 4 reps @ 75%, 4 reps @ 85% x 3, 5 reps @ 85% + +- Squat: 3 reps @ 60%, 3 reps @ 70%, 4 reps @ 80%, 3 reps @ 90%, 5 reps @ 85% x 2 + +- Squat: 4 reps @ 65%, 4 reps @ 70%, 4 reps @ 80% x 5 + + +[ Week ten ] + +- Squat: 4 reps @ 60%, 4 reps @ 70%, 4 reps @ 80%, 3 reps @ 90%, 4 reps @ 90% x 2 + +- Squat: 3 reps @ 65%, 3 reps @ 75%, 3 reps @ 85%, 3 reps @ 90% x 3, 3 reps @ 95% + +- Squat: 3 reps @ 65%, 3 reps @ 75%, 4 reps @ 85%, 5 reps @ 90% + + +[ Week eleven ] + +- Squat: 3 reps @ 60%, 3 reps @ 70%, 3 reps @ 80%, 5 reps @ 90% x 5 + +- Squat: 3 reps @ 60%, 3 reps @ 70%, 3 reps @ 80%, 3 reps @ 95% x 2 + +- Squat: 3 reps @ 65%, 3 reps @ 75%, 3 reps @ 85%, 3 reps @ 95% x 4 + + +[ Week twelve ] + +- Squat: 3 reps @ 70%, 4 reps @ 80%, 5 reps @ 90% x 5 + +- Squat: 3 reps @ 70%, 3 reps @ 80%, 3 reps @ 95% x 4 + +- Squat: 3 reps @ 75%, 4 reps @ 90%, 4 reps @ 80% x 3 + + +[ Taper Week ] + +- Squat: 3 reps @ 70%, 3 reps @ 80%, 5 reps @ 90% x 2, 4 reps @ 95% + +- Squat: 4 reps @ 75%, 4 reps @ 85% x 4 + +- "Build to 1RM" diff --git a/example/StartingStrength.tdl b/example/StartingStrength.tdl new file mode 100644 index 0000000..a46f3d7 --- /dev/null +++ b/example/StartingStrength.tdl @@ -0,0 +1,41 @@ +[ Max refers to 5RM or 3RM for PowerClean ] + +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 + + +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: + - Squat: regularSets + Press: regularSets increase + Deadlift: deadliftSets increase + + - Squat: regularSets increase + Bench: regularSets increase + PowerClean: cleanSets increase + "3 sets of 5 weighted chin-ups" diff --git a/example/Texas_Method.tdl b/example/Texas_Method.tdl new file mode 100644 index 0000000..e9fd642 --- /dev/null +++ b/example/Texas_Method.tdl @@ -0,0 +1,49 @@ +[ Max refers to 5RM or 3RM for PowerClean ] + +Lifts: + Squat Max: 180 Increment: 2.5, + Deadlift Max: 210 Increment: 2.5, + Bench Max: 120 Increment: 1.25, + Press Max: 80 Increment: 1.25, + PowerClean Max: 80 Increment: 1.25 + +SetTemplates: +- empty: + 5 reps @ 0% +- warmups: + 3 reps @ 25%, + 2 reps @ 50%, + 2 reps @ 75% +- worksetMonday: + 5 reps @ 90% +- worksetFriday: + 5 reps @ 100% + +TrainingDays: + + - Squat: empty, empty, warmups, worksetMonday x 5 + Bench: empty, warmups, worksetMonday x 5 + Deadlift: empty, warmups, worksetMonday + + - Squat: empty, empty, warmups, 5 reps @ 72% x 2 increase + Press: empty, warmups, 5 reps @ 81% x 3 increase + "3 sets of bodyweight Chin-ups" + "5 sets of 10 Back Extensions or Glute-Ham Raises" + + - Squat: empty, empty, warmups, 5 reps @ 100% + Bench: empty, warmups, 5 reps @ 100% + PowerClean: empty, warmups, 3 reps @ 90% x 5 + + + - Squat: empty, empty, warmups, worksetMonday x 5 + Press: empty, warmups, worksetMonday x 5 + Deadlift: empty, warmups, worksetMonday + + - Squat: empty, empty, warmups, 5 reps @ 72% x 2 increase + Bench: empty, warmups, 5 reps @ 81% x 3 increase + "3 sets of bodyweight Chin-ups" + "5 sets of 10 Back Extensions or Glute-Ham Raises" + + - Squat: empty, empty, warmups, 5 reps @ 100% + Press: empty, warmups, 5 reps @ 100% + PowerClean: empty, warmups, 3 reps @ 90% x 5 \ No newline at end of file diff --git a/example/minimalExample.tdl b/example/minimalExample.tdl new file mode 100644 index 0000000..2eb0f95 --- /dev/null +++ b/example/minimalExample.tdl @@ -0,0 +1,10 @@ +[comment] + +Lifts: + OHP Max: 100 Increment: 2.5 [another comment] + +Plates: + 20 x 2 + +TrainingDays: + - OHP: 5 reps @ 100% diff --git a/generator.go b/generator.go new file mode 100644 index 0000000..bae511b --- /dev/null +++ b/generator.go @@ -0,0 +1,267 @@ +package main + +import ( + "bufio" + "fmt" + "io" + "os" + "strconv" + "strings" +) + +type Generator interface { + Generate(TDL) +} + +func semanticError(v ...interface{}) { + v = append([]interface{}{"semantic error"}, v...) + fmt.Fprintln(os.Stderr, v...) + os.Exit(1) +} + +func formatFloat(f float64) string { + return strconv.FormatFloat(f, 'f', 2, 64) +} + +func minOne(i int) int { + if i < 1 { + return 1 + } else { + return i + } +} + +type tableLine struct { + cols [3]string +} + +func newTableLine(first, second, third string) tableLine { + return tableLine{[3]string{first, second, third}} +} + +func columnLengths(lines []tableLine) [3]int { + max := [3]int{0, 0, 0} + for _, line := range lines { + for i := 0; i < len(line.cols); i++ { + if n := len([]rune(line.cols[i])); n > max[i] { + max[i] = n + } + } + } + return max +} + +func getTableFormat(lengths [3]int) string { + format := "|" + for _, length := range lengths { + format += " %-" + strconv.Itoa(length) + "s |" + } + return format + "\n" +} + +type StdGenerator struct { + schedule TDL + plates map[float64]int + writer *bufio.Writer +} + +func NewStdGenerator(writer io.Writer) *StdGenerator { + return &StdGenerator{writer: bufio.NewWriter(writer)} +} + +func (g *StdGenerator) write(v ...string) { + for _, s := range v { + g.writer.WriteString(s) + } +} + +func (g *StdGenerator) writeLine(v ...string) { + g.write(v...) + g.write("\n") +} + +func (g *StdGenerator) writeTable(heading tableLine, lines []tableLine) { + lengths := columnLengths(append(lines, heading)) + formatString := getTableFormat(lengths) + fmt.Fprintf(g.writer, formatString, heading.cols[0], heading.cols[1], heading.cols[2]) + fmt.Fprintf(g.writer, formatString, strings.Repeat("-", lengths[0]), strings.Repeat("-", lengths[1]), strings.Repeat("-", lengths[2])) + for _, line := range lines { + fmt.Fprintf(g.writer, formatString, line.cols[0], line.cols[1], line.cols[2]) + } +} + +func (g *StdGenerator) init(schedule TDL) { + g.schedule = schedule.Clone() + g.plates = make(map[float64]int) + for _, plate := range schedule.Plates { + if _, ok := g.plates[plate.Weight]; ok { + g.plates[plate.Weight] += plate.Amount + } else { + g.plates[plate.Weight] = plate.Amount + } + } + if len(g.plates) == 0 { + g.plates = map[float64]int{ + 20.0: 26, + 10.0: 2, + 5.00: 2, + 2.50: 2, + 1.25: 2, + } + } + for i := range g.schedule.Lifts { + if g.schedule.Lifts[i].Bar == 0 { + g.schedule.Lifts[i].Bar = 20 + } + } +} + +func (g *StdGenerator) Generate(schedule TDL) { + g.init(schedule) + g.printMaxes() + g.writeLine() + g.printTrainingDays() + g.printMaxes() + g.writer.Flush() +} + +func (g *StdGenerator) getLift(name string) *Lift { + for i := range g.schedule.Lifts { + if lift := &g.schedule.Lifts[i]; lift.Name == name { + return lift + } + } + semanticError("unknown lift '", name, "'") + return nil +} + +func (g *StdGenerator) increaseLift(lift *Lift, amount float64, relative bool) { + if amount == 0 { + amount = lift.Increment + relative = lift.IncrementPercent + } + if relative { + lift.Max *= amount / 100.0 + } else { + lift.Max += amount + } +} + +func (g *StdGenerator) getSetTemplate(name string) SetTemplate { + for _, template := range g.schedule.SetTemplates { + if template.Name == name { + return template + } + } + semanticError("unknown set template '", name, "'") + return SetTemplate{} +} + +func (g *StdGenerator) printMaxes() { + g.writeLine("Maxes") + g.writeLine("=====\n") + for _, lift := range g.schedule.Lifts { + g.writeLine(lift.Name, ": ", formatFloat(lift.Max)) + } +} + +func (g *StdGenerator) printTrainingDays() { + for i, day := range g.schedule.TrainingDays { + g.writeLine("Day ", strconv.Itoa(i+1)) + g.writeLine("======\n") + for _, item := range day.Items { + g.printTrainingDayItem(item) + } + } +} + +func (g *StdGenerator) printTrainingDayItem(item TrainingDayItem) { + if item.Raw != "" { + g.writeLine(item.Raw) + } else { + g.printLiftSchedule(item.LiftSchedule) + } + g.writeLine() +} + +func (g *StdGenerator) printLiftSchedule(ls LiftSchedule) { + lift := g.getLift(ls.LiftName) + g.writeLine(lift.Name) + g.writeLine("--------\n") + + heading := newTableLine("Set", "Plates", "Resulting") + lines := []tableLine{} + for _, item := range ls.Items { + g.linesSetTemplateItem(&lines, lift, item) + } + g.writeTable(heading, lines) + + if ls.Increase { + g.increaseLift(lift, ls.IncreaseAmount, ls.IncreasePercent) + } +} + +func (g *StdGenerator) linesSetTemplate(lines *[]tableLine, lift *Lift, template SetTemplate) { + for _, item := range template.Items { + g.linesSetTemplateItem(lines, lift, item) + } + return +} + +func (g *StdGenerator) linesSetTemplateItem(lines *[]tableLine, lift *Lift, item SetTemplateItem) { + for i := 0; i < minOne(item.Amount); i++ { + if item.ReferenceName != "" { + g.linesSetTemplate(lines, lift, g.getSetTemplate(item.ReferenceName)) + } else { + g.linesSet(lines, lift, item.Set) + } + } + return +} + +func (g *StdGenerator) linesSet(lines *[]tableLine, lift *Lift, set Set) { + weight := lift.Max*set.Percentage/100.0 + set.PlusWeight + plates, resulting := g.searchPlates(weight, lift.Bar) + firstColumn := formatFloat(weight) + " x " + strconv.Itoa(set.Reps) + if set.Amount > 1 { + firstColumn += " x " + strconv.Itoa(set.Amount) + } + if set.Notice != "" { + firstColumn += " " + set.Notice + } + *lines = append(*lines, newTableLine(firstColumn, plates, resulting)) + return +} + +func (g *StdGenerator) searchPlates(weight float64, bar float64) (string, string) { + remaining := weight - bar + if remaining <= 0 { + return "", formatFloat(bar) + } + plateSequence := SearchPlates(g.plates, remaining) + resulting := bar + platesCounted := make(map[float64]int) + for _, plate := range plateSequence { + platesCounted[plate] = 0 + resulting += 2 * plate + } + for _, plate := range plateSequence { + platesCounted[plate] += 1 + } + plateString := "" + for _, plate := range plateSequence { + if platesCounted[plate] == 0 { + continue + } + count := platesCounted[plate] + platesCounted[plate] = 0 + if plateString != "" { + plateString += ", " + } + plateString += fmt.Sprint(plate) + if count > 1 { + plateString += "x" + strconv.Itoa(count) + } + } + return plateString, formatFloat(resulting) +} diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..6d76aee --- /dev/null +++ b/go.mod @@ -0,0 +1,3 @@ +module TDL + +go 1.14 diff --git a/lexer.go b/lexer.go new file mode 100644 index 0000000..11d7caf --- /dev/null +++ b/lexer.go @@ -0,0 +1,231 @@ +package main + +import ( + "fmt" + "io" + "unicode" +) + +type SymType int + +const ( + SymNone SymType = iota + SymUnknown + SymEOI + SymPreamble + SymComma + SymPercent + SymTimes + SymDash + SymAt + SymPlus + SymNotice + SymBrokenNotice + SymString + SymBrokenString + SymInteger + SymFloat + SymIdent + SymReps + SymIncrease +) + +func (t SymType) String() string { + switch t { + case SymNone: + return "none" + case SymUnknown: + return "unknown" + case SymEOI: + return "EOI" + case SymPreamble: + return "preamble" + case SymComma: + return "," + case SymPercent: + return "%" + case SymTimes: + return "x" + case SymDash: + return "-" + case SymAt: + return "@" + case SymPlus: + return "+" + case SymNotice: + return "notice" + case SymBrokenNotice: + return "broken notice" + case SymString: + return "string" + case SymBrokenString: + return "broken string" + case SymInteger: + return "integer" + case SymFloat: + return "float" + case SymIdent: + return "identifier" + case SymReps: + return "reps" + case SymIncrease: + return "increase" + default: + return "(no description for token, this should not have happened)" + } +} + +type Sym struct { + Type SymType + Value string +} + +func (s Sym) String() string { + return "(" + s.Type.String() + " - '" + s.Value + "')" +} + +type Lexer struct { + input []rune + symStart int + pos int + line int + ch rune +} + +func NewLexer(input []rune) *Lexer { + return &Lexer{input: input, pos: -1, line: 1} +} + +func (l *Lexer) getCh() { + if l.pos >= len(l.input)-1 { + l.pos = len(l.input) + l.ch = 0 + } else { + l.pos++ + l.ch = l.input[l.pos] + } +} + +func (l *Lexer) isEOI() bool { + return l.ch == 0 && l.pos >= len(l.input)-1 +} + +func (l *Lexer) symbolValue() string { + return string(l.input[l.symStart:l.pos]) +} + +func (l *Lexer) skipWhitespace() { + inComment := false + for unicode.IsSpace(l.ch) || (l.ch == 0 && !l.isEOI()) || l.ch == '[' || inComment { + if l.ch == '[' { + inComment = true + } + if l.ch == ']' { + inComment = false + } + if l.ch == '\n' { + l.line++ + } + l.getCh() + } +} + +func (l *Lexer) Lex() Sym { + sym := SymNone + var start int + l.skipWhitespace() + for sym == SymNone { + start = l.pos + switch l.ch { + case 0: + if l.isEOI() { + sym = SymEOI + } else { + l.getCh() + } + case ',': + sym = SymComma + l.getCh() + case '%': + sym = SymPercent + l.getCh() + case 'x': + sym = SymTimes + l.getCh() + case '-': + sym = SymDash + l.getCh() + case '@': + sym = SymAt + l.getCh() + case '+': + sym = SymPlus + l.getCh() + case '(': + sym = SymNotice + l.getCh() + for l.ch != ')' && l.ch != '\n' && !l.isEOI() { + l.getCh() + } + if l.ch != ')' { + sym = SymBrokenNotice + } else { + l.getCh() + } + case '"': + sym = SymString + l.getCh() + for l.ch != '"' && l.ch != '\n' && !l.isEOI() { + l.getCh() + } + if l.ch != '"' { + sym = SymBrokenString + } else { + l.getCh() + } + case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': + sym = SymInteger + l.getCh() + for l.ch >= '0' && l.ch <= '9' { + l.getCh() + } + if l.ch == '.' { + sym = SymFloat + l.getCh() + for l.ch >= '0' && l.ch <= '9' { + l.getCh() + } + } + default: + if unicode.IsLetter(l.ch) { + sym = SymIdent + l.getCh() + for unicode.IsLetter(l.ch) || unicode.IsDigit(l.ch) { + l.getCh() + } + if l.ch == ':' { + sym = SymPreamble + l.getCh() + } + val := string(l.input[start:l.pos]) + if val == "reps" { + sym = SymReps + } else if val == "increase" { + sym = SymIncrease + } + } else { + sym = SymUnknown + l.getCh() + } + } + } + l.symStart = start + return Sym{sym, l.symbolValue()} +} + +func DebugLexer(input []rune, writer io.Writer) { + l := NewLexer(input) + for tok := l.Lex(); tok.Type != SymEOI; tok = l.Lex() { + fmt.Fprintf(writer, "line %d: %v\n", l.line, tok) + } +} diff --git a/parser.go b/parser.go new file mode 100644 index 0000000..fa8fba2 --- /dev/null +++ b/parser.go @@ -0,0 +1,280 @@ +package main + +import ( + "fmt" + "io" + "strconv" + "strings" +) + +func DebugParser(input []rune, writer io.Writer) { + p := NewParser(input) + tdl := p.Parse() + fmt.Fprintln(writer, string(tdl.JSON())) +} + +type Parser struct { + lexer *Lexer + sym Sym +} + +func NewParser(input []rune) *Parser { + p := &Parser{lexer: NewLexer(input)} + p.get() + return p +} + +func (p *Parser) exitWith(v ...interface{}) { + v = append([]interface{}{"syntax error in line", p.lexer.line, ":"}, v...) + panic(fmt.Sprintln(v...)) +} + +func (p *Parser) invalid(what string) { + p.exitWith("invalid", what, ">", p.sym.Value, "<") +} + +func (p *Parser) string() string { + val := strings.TrimPrefix(strings.TrimSuffix(p.sym.Value, "\""), "\"") + if p.sym.Type != SymString { + p.invalid("string") + } + p.get() + return val +} + +func (p *Parser) ident() string { + val := p.sym.Value + if p.sym.Type != SymIdent { + p.invalid("identifier") + } + p.get() + return val +} + +func (p *Parser) notice() string { + val := p.sym.Value + if p.sym.Type != SymNotice { + p.invalid("notice") + } + p.get() + return val +} + +func (p *Parser) float() float64 { + val := p.sym.Value + f, err := strconv.ParseFloat(val, 64) + if err != nil || (p.sym.Type != SymFloat && p.sym.Type != SymInteger) { + p.invalid("float") + } + p.get() + return f +} + +func (p *Parser) int() int { + val := p.sym.Value + i, err := strconv.Atoi(val) + if err != nil || p.sym.Type != SymInteger { + p.invalid("integer") + } + p.get() + return i +} + +func (p *Parser) get() { + p.sym = p.lexer.Lex() +} + +func (p *Parser) expect(symTypes ...SymType) { + expected := []string{} + for _, symType := range symTypes { + if p.sym.Type == symType { + p.get() + return + } + expected = append(expected, symType.String()) + } + p.exitWith("expected >", strings.Join(expected, " or "), "< but got:", p.sym) +} + +func (p *Parser) hasPreamble(s string) bool { + return p.sym.Type == SymPreamble && p.sym.Value == s +} + +func (p *Parser) expectPreamble(s string) { + if p.hasPreamble(s) { + p.get() + } else { + p.exitWith("expected preamble >", s, "< but got:", p.sym) + } +} + +/*---------------------*/ + +func (p *Parser) Parse() (r TDL) { + r = TDL{} + r.Lifts = p.Lifts() + if p.hasPreamble("Plates:") { + r.Plates = p.Plates() + } + if p.hasPreamble("SetTemplates:") { + r.SetTemplates = p.SetTemplates() + } + r.TrainingDays = p.TrainingDays() + p.expect(SymEOI) + return +} + +func (p *Parser) Lifts() (r []Lift) { + p.expectPreamble("Lifts:") + r = append(r, p.Lift()) + for p.sym.Type == SymComma { + p.get() + r = append(r, p.Lift()) + } + return +} + +func (p *Parser) Lift() (r Lift) { + r.Name = p.ident() + p.expectPreamble("Max:") + r.Max = p.float() + p.expectPreamble("Increment:") + r.Increment = p.float() + if p.sym.Type == SymPercent { + p.get() + r.IncrementPercent = true + } + if p.hasPreamble("Bar:") { + p.expectPreamble("Bar:") + r.Bar = p.float() + } + return +} + +func (p *Parser) Plates() (r []Plate) { + p.expectPreamble("Plates:") + r = append(r, p.Plate()) + for p.sym.Type == SymComma { + p.get() + r = append(r, p.Plate()) + } + return r +} + +func (p *Parser) Plate() (r Plate) { + r.Weight = p.float() + p.expect(SymTimes) + r.Amount = p.int() + return +} + +func (p *Parser) SetTemplates() (r []SetTemplate) { + p.expectPreamble("SetTemplates:") + p.expect(SymDash) + r = append(r, p.SetTemplate()) + for p.sym.Type == SymDash { + p.get() + r = append(r, p.SetTemplate()) + } + return +} + +func (p *Parser) SetTemplate() (r SetTemplate) { + if p.sym.Type == SymPreamble { + r.Name = strings.TrimSuffix(p.sym.Value, ":") + p.get() + } else { + p.expect(SymPreamble) + } + r.Items = append(r.Items, p.SetTemplateItem()) + for p.sym.Type == SymComma { + p.get() + r.Items = append(r.Items, p.SetTemplateItem()) + } + return +} + +func (p *Parser) SetTemplateItem() (r SetTemplateItem) { + if p.sym.Type == SymIdent { + r.ReferenceName = p.ident() + } else { + r.Set = p.Set() + } + if p.sym.Type == SymTimes { + p.expect(SymTimes) + r.Amount = p.int() + } + return +} + +func (p *Parser) Set() (r Set) { + r.Reps = p.int() + p.expect(SymReps) + p.expect(SymAt) + r.Percentage = p.float() + p.expect(SymPercent) + if p.sym.Type == SymPlus { + p.expect(SymPlus) + r.PlusWeight = p.float() + } + if p.sym.Type == SymTimes { + p.expect(SymTimes) + r.Amount = p.int() + } + if p.sym.Type == SymNotice { + r.Notice = p.notice() + } + return +} + +func (p *Parser) TrainingDays() (r []TrainingDay) { + p.expectPreamble("TrainingDays:") + p.expect(SymDash) + r = append(r, p.TrainingDay()) + for p.sym.Type == SymDash { + p.get() + r = append(r, p.TrainingDay()) + } + return +} + +func (p *Parser) TrainingDay() (r TrainingDay) { + for p.sym.Type != SymDash && p.sym.Type != SymEOI { + r.Items = append(r.Items, p.TrainingDayItem()) + } + return +} + +func (p *Parser) TrainingDayItem() (r TrainingDayItem) { + if p.sym.Type == SymString { + r.Raw = p.string() + } else { + r.LiftSchedule = p.LiftSchedule() + } + return +} + +func (p *Parser) LiftSchedule() (r LiftSchedule) { + if p.sym.Type == SymPreamble { + r.LiftName = strings.TrimSuffix(p.sym.Value, ":") + p.get() + } else { + p.expect(SymPreamble) + } + r.Items = append(r.Items, p.SetTemplateItem()) + for p.sym.Type == SymComma { + p.get() + r.Items = append(r.Items, p.SetTemplateItem()) + } + if p.sym.Type == SymIncrease { + r.Increase = true + p.get() + if p.sym.Type == SymFloat || p.sym.Type == SymInteger { + r.IncreaseAmount = p.float() + if p.sym.Type == SymPercent { + r.IncreasePercent = true + } + } + } + return +} diff --git a/plateSearch.go b/plateSearch.go new file mode 100644 index 0000000..d4d6d46 --- /dev/null +++ b/plateSearch.go @@ -0,0 +1,109 @@ +package main + +import ( + "fmt" + "sort" +) + +const ( + INFINITY = 26 +) + +var debugSearch bool + +type DummyWriter struct { +} + +func (d DummyWriter) Write(p []byte) (n int, err error) { + n = len(p) + return +} + +func DebugSearch(input []rune) { + debugSearch = true + parsed := NewParser(input).Parse() + generator := NewStdGenerator(DummyWriter{}) + generator.Generate(parsed) +} + +func SearchPlates(plates map[float64]int, goalWeight float64) []float64 { + if debugSearch { + fmt.Println("searching", goalWeight) + } + root := &DFSNode{} + root.remainingWeight = goalWeight + root.residualPlates = make(map[float64]int) + root.plate = -1 + for k, v := range plates { + root.residualPlates[k] = v + } + optimum := root + root.search(&optimum) + usedPlates := optimum.usedPlates() + if debugSearch { + fmt.Println("found", usedPlates) + } + return usedPlates +} + +type DFSNode struct { + parent *DFSNode + depth int + remainingWeight float64 + plate float64 + residualPlates map[float64]int +} + +func (parent *DFSNode) newChild(plate float64) *DFSNode { + node := &DFSNode{} + node.parent = parent + node.depth = parent.depth + 1 + node.remainingWeight = parent.remainingWeight - plate*2 + node.plate = plate + node.residualPlates = make(map[float64]int) + for k, v := range parent.residualPlates { + node.residualPlates[k] = v + } + node.residualPlates[plate] -= 2 + return node +} + +func (n *DFSNode) usedPlates() (plates []float64) { + for node := n; node != nil; node = node.parent { + if node.plate > 0 { + plates = append([]float64{node.plate}, plates...) + } + } + return +} + +func (n *DFSNode) successors() (children []*DFSNode) { + keys := []float64{} + for weight, amount := range n.residualPlates { + if amount >= 2 && weight*2 <= n.remainingWeight && (n.plate == -1 || weight <= n.plate) && n.remainingWeight/weight <= INFINITY { + keys = append(keys, weight) + } + } + sort.Float64s(keys) + for i := len(keys) - 1; i >= 0; i-- { + children = append(children, n.newChild(keys[i])) + } + return +} + +func (n *DFSNode) search(optimum **DFSNode) { + successors := n.successors() + if len(successors) == 0 { + // leaf + if n.remainingWeight < (*optimum).remainingWeight || (n.remainingWeight == (*optimum).remainingWeight && n.depth < (*optimum).depth) { + *optimum = n + if debugSearch { + fmt.Printf("optimum: residual plates %v, remaining weight %v\n", (*optimum).residualPlates, (*optimum).remainingWeight) + } + } + } else { + for _, succ := range successors { + succ.search(optimum) + } + } +} diff --git a/test/531_BoringButBig.tdl.lexer b/test/531_BoringButBig.tdl.lexer new file mode 100644 index 0000000..6b6c252 --- /dev/null +++ b/test/531_BoringButBig.tdl.lexer @@ -0,0 +1,225 @@ +line 1: (preamble - 'Lifts:') +line 2: (identifier - 'Squat') +line 2: (preamble - 'Max:') +line 2: (integer - '200') +line 2: (preamble - 'Increment:') +line 2: (integer - '5') +line 2: (, - ',') +line 3: (identifier - 'Deadlift') +line 3: (preamble - 'Max:') +line 3: (integer - '250') +line 3: (preamble - 'Increment:') +line 3: (integer - '5') +line 3: (, - ',') +line 4: (identifier - 'Bench') +line 4: (preamble - 'Max:') +line 4: (integer - '120') +line 4: (preamble - 'Increment:') +line 4: (float - '2.5') +line 4: (, - ',') +line 5: (identifier - 'Press') +line 5: (preamble - 'Max:') +line 5: (integer - '90') +line 5: (preamble - 'Increment:') +line 5: (float - '2.5') +line 7: (preamble - 'SetTemplates:') +line 8: (- - '-') +line 8: (preamble - 'warmup:') +line 9: (integer - '5') +line 9: (reps - 'reps') +line 9: (@ - '@') +line 9: (integer - '40') +line 9: (% - '%') +line 9: (, - ',') +line 10: (integer - '5') +line 10: (reps - 'reps') +line 10: (@ - '@') +line 10: (integer - '50') +line 10: (% - '%') +line 10: (, - ',') +line 11: (integer - '3') +line 11: (reps - 'reps') +line 11: (@ - '@') +line 11: (integer - '60') +line 11: (% - '%') +line 13: (- - '-') +line 13: (preamble - 'fiveRep:') +line 14: (identifier - 'warmup') +line 14: (, - ',') +line 15: (integer - '5') +line 15: (reps - 'reps') +line 15: (@ - '@') +line 15: (integer - '65') +line 15: (% - '%') +line 15: (, - ',') +line 16: (integer - '5') +line 16: (reps - 'reps') +line 16: (@ - '@') +line 16: (integer - '75') +line 16: (% - '%') +line 16: (, - ',') +line 17: (integer - '5') +line 17: (reps - 'reps') +line 17: (@ - '@') +line 17: (integer - '85') +line 17: (% - '%') +line 17: (, - ',') +line 18: (integer - '10') +line 18: (reps - 'reps') +line 18: (@ - '@') +line 18: (integer - '50') +line 18: (% - '%') +line 18: (x - 'x') +line 18: (integer - '5') +line 20: (- - '-') +line 20: (preamble - 'threeRep:') +line 21: (identifier - 'warmup') +line 21: (, - ',') +line 22: (integer - '3') +line 22: (reps - 'reps') +line 22: (@ - '@') +line 22: (integer - '70') +line 22: (% - '%') +line 22: (, - ',') +line 23: (integer - '3') +line 23: (reps - 'reps') +line 23: (@ - '@') +line 23: (integer - '80') +line 23: (% - '%') +line 23: (, - ',') +line 24: (integer - '3') +line 24: (reps - 'reps') +line 24: (@ - '@') +line 24: (integer - '90') +line 24: (% - '%') +line 24: (, - ',') +line 25: (integer - '10') +line 25: (reps - 'reps') +line 25: (@ - '@') +line 25: (integer - '50') +line 25: (% - '%') +line 25: (x - 'x') +line 25: (integer - '5') +line 27: (- - '-') +line 27: (preamble - 'oneRep:') +line 28: (identifier - 'warmup') +line 28: (, - ',') +line 29: (integer - '5') +line 29: (reps - 'reps') +line 29: (@ - '@') +line 29: (integer - '75') +line 29: (% - '%') +line 29: (, - ',') +line 30: (integer - '3') +line 30: (reps - 'reps') +line 30: (@ - '@') +line 30: (integer - '85') +line 30: (% - '%') +line 30: (, - ',') +line 31: (integer - '1') +line 31: (reps - 'reps') +line 31: (@ - '@') +line 31: (integer - '95') +line 31: (% - '%') +line 31: (, - ',') +line 32: (integer - '10') +line 32: (reps - 'reps') +line 32: (@ - '@') +line 32: (integer - '50') +line 32: (% - '%') +line 32: (x - 'x') +line 32: (integer - '5') +line 34: (- - '-') +line 34: (preamble - 'deload:') +line 35: (integer - '5') +line 35: (reps - 'reps') +line 35: (@ - '@') +line 35: (integer - '40') +line 35: (% - '%') +line 35: (x - 'x') +line 35: (integer - '2') +line 35: (, - ',') +line 36: (integer - '5') +line 36: (reps - 'reps') +line 36: (@ - '@') +line 36: (integer - '50') +line 36: (% - '%') +line 36: (x - 'x') +line 36: (integer - '2') +line 36: (, - ',') +line 37: (integer - '3') +line 37: (reps - 'reps') +line 37: (@ - '@') +line 37: (integer - '60') +line 37: (% - '%') +line 37: (x - 'x') +line 37: (integer - '2') +line 39: (preamble - 'TrainingDays:') +line 41: (- - '-') +line 41: (preamble - 'Press:') +line 41: (identifier - 'fiveRep') +line 42: (string - '"5 sets of 10 chin-ups"') +line 44: (- - '-') +line 44: (preamble - 'Deadlift:') +line 44: (identifier - 'fiveRep') +line 45: (string - '"5 sets of 15 hanging leg raises"') +line 47: (- - '-') +line 47: (preamble - 'Bench:') +line 47: (identifier - 'fiveRep') +line 48: (string - '"5 sets of 10 dumbbell rows"') +line 50: (- - '-') +line 50: (preamble - 'Squat:') +line 50: (identifier - 'fiveRep') +line 51: (string - '"5 sets of 10 leg curls"') +line 54: (- - '-') +line 54: (preamble - 'Press:') +line 54: (identifier - 'threeRep') +line 55: (string - '"5 sets of 10 chin-ups"') +line 57: (- - '-') +line 57: (preamble - 'Deadlift:') +line 57: (identifier - 'threeRep') +line 58: (string - '"5 sets of 15 hanging leg raises"') +line 60: (- - '-') +line 60: (preamble - 'Bench:') +line 60: (identifier - 'threeRep') +line 61: (string - '"5 sets of 10 dumbbell rows"') +line 63: (- - '-') +line 63: (preamble - 'Squat:') +line 63: (identifier - 'threeRep') +line 64: (string - '"5 sets of 10 leg curls"') +line 67: (- - '-') +line 67: (preamble - 'Press:') +line 67: (identifier - 'oneRep') +line 68: (string - '"5 sets of 10 chin-ups"') +line 70: (- - '-') +line 70: (preamble - 'Deadlift:') +line 70: (identifier - 'oneRep') +line 71: (string - '"5 sets of 15 hanging leg raises"') +line 73: (- - '-') +line 73: (preamble - 'Bench:') +line 73: (identifier - 'oneRep') +line 74: (string - '"5 sets of 10 dumbbell rows"') +line 76: (- - '-') +line 76: (preamble - 'Squat:') +line 76: (identifier - 'oneRep') +line 77: (string - '"5 sets of 10 leg curls"') +line 80: (- - '-') +line 80: (preamble - 'Press:') +line 80: (identifier - 'deload') +line 80: (increase - 'increase') +line 81: (string - '"5 sets of 10 chin-ups"') +line 83: (- - '-') +line 83: (preamble - 'Deadlift:') +line 83: (identifier - 'deload') +line 83: (increase - 'increase') +line 84: (string - '"5 sets of 15 hanging leg raises"') +line 86: (- - '-') +line 86: (preamble - 'Bench:') +line 86: (identifier - 'deload') +line 86: (increase - 'increase') +line 87: (string - '"5 sets of 10 dumbbell rows"') +line 89: (- - '-') +line 89: (preamble - 'Squat:') +line 89: (identifier - 'deload') +line 89: (increase - 'increase') +line 90: (string - '"5 sets of 10 leg curls"') diff --git a/test/531_BoringButBig.tdl.parser b/test/531_BoringButBig.tdl.parser new file mode 100644 index 0000000..218a28d --- /dev/null +++ b/test/531_BoringButBig.tdl.parser @@ -0,0 +1,869 @@ +{ + "Lifts": [ + { + "Name": "Squat", + "Max": 200, + "Increment": 5, + "IncrementPercent": false, + "Bar": 0 + }, + { + "Name": "Deadlift", + "Max": 250, + "Increment": 5, + "IncrementPercent": false, + "Bar": 0 + }, + { + "Name": "Bench", + "Max": 120, + "Increment": 2.5, + "IncrementPercent": false, + "Bar": 0 + }, + { + "Name": "Press", + "Max": 90, + "Increment": 2.5, + "IncrementPercent": false, + "Bar": 0 + } + ], + "Plates": null, + "SetTemplates": [ + { + "Name": "warmup", + "Items": [ + { + "Set": { + "Reps": 5, + "Percentage": 40, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "", + "Amount": 0 + }, + { + "Set": { + "Reps": 5, + "Percentage": 50, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "", + "Amount": 0 + }, + { + "Set": { + "Reps": 3, + "Percentage": 60, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "", + "Amount": 0 + } + ] + }, + { + "Name": "fiveRep", + "Items": [ + { + "Set": { + "Reps": 0, + "Percentage": 0, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "warmup", + "Amount": 0 + }, + { + "Set": { + "Reps": 5, + "Percentage": 65, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "", + "Amount": 0 + }, + { + "Set": { + "Reps": 5, + "Percentage": 75, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "", + "Amount": 0 + }, + { + "Set": { + "Reps": 5, + "Percentage": 85, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "", + "Amount": 0 + }, + { + "Set": { + "Reps": 10, + "Percentage": 50, + "PlusWeight": 0, + "Amount": 5, + "Notice": "" + }, + "ReferenceName": "", + "Amount": 0 + } + ] + }, + { + "Name": "threeRep", + "Items": [ + { + "Set": { + "Reps": 0, + "Percentage": 0, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "warmup", + "Amount": 0 + }, + { + "Set": { + "Reps": 3, + "Percentage": 70, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "", + "Amount": 0 + }, + { + "Set": { + "Reps": 3, + "Percentage": 80, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "", + "Amount": 0 + }, + { + "Set": { + "Reps": 3, + "Percentage": 90, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "", + "Amount": 0 + }, + { + "Set": { + "Reps": 10, + "Percentage": 50, + "PlusWeight": 0, + "Amount": 5, + "Notice": "" + }, + "ReferenceName": "", + "Amount": 0 + } + ] + }, + { + "Name": "oneRep", + "Items": [ + { + "Set": { + "Reps": 0, + "Percentage": 0, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "warmup", + "Amount": 0 + }, + { + "Set": { + "Reps": 5, + "Percentage": 75, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "", + "Amount": 0 + }, + { + "Set": { + "Reps": 3, + "Percentage": 85, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "", + "Amount": 0 + }, + { + "Set": { + "Reps": 1, + "Percentage": 95, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "", + "Amount": 0 + }, + { + "Set": { + "Reps": 10, + "Percentage": 50, + "PlusWeight": 0, + "Amount": 5, + "Notice": "" + }, + "ReferenceName": "", + "Amount": 0 + } + ] + }, + { + "Name": "deload", + "Items": [ + { + "Set": { + "Reps": 5, + "Percentage": 40, + "PlusWeight": 0, + "Amount": 2, + "Notice": "" + }, + "ReferenceName": "", + "Amount": 0 + }, + { + "Set": { + "Reps": 5, + "Percentage": 50, + "PlusWeight": 0, + "Amount": 2, + "Notice": "" + }, + "ReferenceName": "", + "Amount": 0 + }, + { + "Set": { + "Reps": 3, + "Percentage": 60, + "PlusWeight": 0, + "Amount": 2, + "Notice": "" + }, + "ReferenceName": "", + "Amount": 0 + } + ] + } + ], + "TrainingDays": [ + { + "Items": [ + { + "LiftSchedule": { + "LiftName": "Press", + "Items": [ + { + "Set": { + "Reps": 0, + "Percentage": 0, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "fiveRep", + "Amount": 0 + } + ], + "Increase": false, + "IncreaseAmount": 0, + "IncreasePercent": false + }, + "Raw": "" + }, + { + "LiftSchedule": { + "LiftName": "", + "Items": null, + "Increase": false, + "IncreaseAmount": 0, + "IncreasePercent": false + }, + "Raw": "5 sets of 10 chin-ups" + } + ] + }, + { + "Items": [ + { + "LiftSchedule": { + "LiftName": "Deadlift", + "Items": [ + { + "Set": { + "Reps": 0, + "Percentage": 0, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "fiveRep", + "Amount": 0 + } + ], + "Increase": false, + "IncreaseAmount": 0, + "IncreasePercent": false + }, + "Raw": "" + }, + { + "LiftSchedule": { + "LiftName": "", + "Items": null, + "Increase": false, + "IncreaseAmount": 0, + "IncreasePercent": false + }, + "Raw": "5 sets of 15 hanging leg raises" + } + ] + }, + { + "Items": [ + { + "LiftSchedule": { + "LiftName": "Bench", + "Items": [ + { + "Set": { + "Reps": 0, + "Percentage": 0, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "fiveRep", + "Amount": 0 + } + ], + "Increase": false, + "IncreaseAmount": 0, + "IncreasePercent": false + }, + "Raw": "" + }, + { + "LiftSchedule": { + "LiftName": "", + "Items": null, + "Increase": false, + "IncreaseAmount": 0, + "IncreasePercent": false + }, + "Raw": "5 sets of 10 dumbbell rows" + } + ] + }, + { + "Items": [ + { + "LiftSchedule": { + "LiftName": "Squat", + "Items": [ + { + "Set": { + "Reps": 0, + "Percentage": 0, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "fiveRep", + "Amount": 0 + } + ], + "Increase": false, + "IncreaseAmount": 0, + "IncreasePercent": false + }, + "Raw": "" + }, + { + "LiftSchedule": { + "LiftName": "", + "Items": null, + "Increase": false, + "IncreaseAmount": 0, + "IncreasePercent": false + }, + "Raw": "5 sets of 10 leg curls" + } + ] + }, + { + "Items": [ + { + "LiftSchedule": { + "LiftName": "Press", + "Items": [ + { + "Set": { + "Reps": 0, + "Percentage": 0, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "threeRep", + "Amount": 0 + } + ], + "Increase": false, + "IncreaseAmount": 0, + "IncreasePercent": false + }, + "Raw": "" + }, + { + "LiftSchedule": { + "LiftName": "", + "Items": null, + "Increase": false, + "IncreaseAmount": 0, + "IncreasePercent": false + }, + "Raw": "5 sets of 10 chin-ups" + } + ] + }, + { + "Items": [ + { + "LiftSchedule": { + "LiftName": "Deadlift", + "Items": [ + { + "Set": { + "Reps": 0, + "Percentage": 0, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "threeRep", + "Amount": 0 + } + ], + "Increase": false, + "IncreaseAmount": 0, + "IncreasePercent": false + }, + "Raw": "" + }, + { + "LiftSchedule": { + "LiftName": "", + "Items": null, + "Increase": false, + "IncreaseAmount": 0, + "IncreasePercent": false + }, + "Raw": "5 sets of 15 hanging leg raises" + } + ] + }, + { + "Items": [ + { + "LiftSchedule": { + "LiftName": "Bench", + "Items": [ + { + "Set": { + "Reps": 0, + "Percentage": 0, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "threeRep", + "Amount": 0 + } + ], + "Increase": false, + "IncreaseAmount": 0, + "IncreasePercent": false + }, + "Raw": "" + }, + { + "LiftSchedule": { + "LiftName": "", + "Items": null, + "Increase": false, + "IncreaseAmount": 0, + "IncreasePercent": false + }, + "Raw": "5 sets of 10 dumbbell rows" + } + ] + }, + { + "Items": [ + { + "LiftSchedule": { + "LiftName": "Squat", + "Items": [ + { + "Set": { + "Reps": 0, + "Percentage": 0, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "threeRep", + "Amount": 0 + } + ], + "Increase": false, + "IncreaseAmount": 0, + "IncreasePercent": false + }, + "Raw": "" + }, + { + "LiftSchedule": { + "LiftName": "", + "Items": null, + "Increase": false, + "IncreaseAmount": 0, + "IncreasePercent": false + }, + "Raw": "5 sets of 10 leg curls" + } + ] + }, + { + "Items": [ + { + "LiftSchedule": { + "LiftName": "Press", + "Items": [ + { + "Set": { + "Reps": 0, + "Percentage": 0, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "oneRep", + "Amount": 0 + } + ], + "Increase": false, + "IncreaseAmount": 0, + "IncreasePercent": false + }, + "Raw": "" + }, + { + "LiftSchedule": { + "LiftName": "", + "Items": null, + "Increase": false, + "IncreaseAmount": 0, + "IncreasePercent": false + }, + "Raw": "5 sets of 10 chin-ups" + } + ] + }, + { + "Items": [ + { + "LiftSchedule": { + "LiftName": "Deadlift", + "Items": [ + { + "Set": { + "Reps": 0, + "Percentage": 0, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "oneRep", + "Amount": 0 + } + ], + "Increase": false, + "IncreaseAmount": 0, + "IncreasePercent": false + }, + "Raw": "" + }, + { + "LiftSchedule": { + "LiftName": "", + "Items": null, + "Increase": false, + "IncreaseAmount": 0, + "IncreasePercent": false + }, + "Raw": "5 sets of 15 hanging leg raises" + } + ] + }, + { + "Items": [ + { + "LiftSchedule": { + "LiftName": "Bench", + "Items": [ + { + "Set": { + "Reps": 0, + "Percentage": 0, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "oneRep", + "Amount": 0 + } + ], + "Increase": false, + "IncreaseAmount": 0, + "IncreasePercent": false + }, + "Raw": "" + }, + { + "LiftSchedule": { + "LiftName": "", + "Items": null, + "Increase": false, + "IncreaseAmount": 0, + "IncreasePercent": false + }, + "Raw": "5 sets of 10 dumbbell rows" + } + ] + }, + { + "Items": [ + { + "LiftSchedule": { + "LiftName": "Squat", + "Items": [ + { + "Set": { + "Reps": 0, + "Percentage": 0, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "oneRep", + "Amount": 0 + } + ], + "Increase": false, + "IncreaseAmount": 0, + "IncreasePercent": false + }, + "Raw": "" + }, + { + "LiftSchedule": { + "LiftName": "", + "Items": null, + "Increase": false, + "IncreaseAmount": 0, + "IncreasePercent": false + }, + "Raw": "5 sets of 10 leg curls" + } + ] + }, + { + "Items": [ + { + "LiftSchedule": { + "LiftName": "Press", + "Items": [ + { + "Set": { + "Reps": 0, + "Percentage": 0, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "deload", + "Amount": 0 + } + ], + "Increase": true, + "IncreaseAmount": 0, + "IncreasePercent": false + }, + "Raw": "" + }, + { + "LiftSchedule": { + "LiftName": "", + "Items": null, + "Increase": false, + "IncreaseAmount": 0, + "IncreasePercent": false + }, + "Raw": "5 sets of 10 chin-ups" + } + ] + }, + { + "Items": [ + { + "LiftSchedule": { + "LiftName": "Deadlift", + "Items": [ + { + "Set": { + "Reps": 0, + "Percentage": 0, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "deload", + "Amount": 0 + } + ], + "Increase": true, + "IncreaseAmount": 0, + "IncreasePercent": false + }, + "Raw": "" + }, + { + "LiftSchedule": { + "LiftName": "", + "Items": null, + "Increase": false, + "IncreaseAmount": 0, + "IncreasePercent": false + }, + "Raw": "5 sets of 15 hanging leg raises" + } + ] + }, + { + "Items": [ + { + "LiftSchedule": { + "LiftName": "Bench", + "Items": [ + { + "Set": { + "Reps": 0, + "Percentage": 0, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "deload", + "Amount": 0 + } + ], + "Increase": true, + "IncreaseAmount": 0, + "IncreasePercent": false + }, + "Raw": "" + }, + { + "LiftSchedule": { + "LiftName": "", + "Items": null, + "Increase": false, + "IncreaseAmount": 0, + "IncreasePercent": false + }, + "Raw": "5 sets of 10 dumbbell rows" + } + ] + }, + { + "Items": [ + { + "LiftSchedule": { + "LiftName": "Squat", + "Items": [ + { + "Set": { + "Reps": 0, + "Percentage": 0, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "deload", + "Amount": 0 + } + ], + "Increase": true, + "IncreaseAmount": 0, + "IncreasePercent": false + }, + "Raw": "" + }, + { + "LiftSchedule": { + "LiftName": "", + "Items": null, + "Increase": false, + "IncreaseAmount": 0, + "IncreasePercent": false + }, + "Raw": "5 sets of 10 leg curls" + } + ] + } + ] +} diff --git a/test/BillStarr_5x5_Intermediate.tdl.lexer b/test/BillStarr_5x5_Intermediate.tdl.lexer new file mode 100644 index 0000000..717b99e --- /dev/null +++ b/test/BillStarr_5x5_Intermediate.tdl.lexer @@ -0,0 +1,158 @@ +line 8: (preamble - 'Lifts:') +line 9: (identifier - 'Squat') +line 9: (preamble - 'Max:') +line 9: (integer - '180') +line 9: (preamble - 'Increment:') +line 9: (float - '2.5') +line 9: (% - '%') +line 9: (, - ',') +line 10: (identifier - 'HighPull') +line 10: (preamble - 'Max:') +line 10: (integer - '120') +line 10: (preamble - 'Increment:') +line 10: (float - '2.5') +line 10: (% - '%') +line 10: (, - ',') +line 11: (identifier - 'Bench') +line 11: (preamble - 'Max:') +line 11: (integer - '100') +line 11: (preamble - 'Increment:') +line 11: (float - '2.5') +line 11: (% - '%') +line 11: (, - ',') +line 12: (identifier - 'Press') +line 12: (preamble - 'Max:') +line 12: (integer - '75') +line 12: (preamble - 'Increment:') +line 12: (float - '2.5') +line 12: (% - '%') +line 12: (, - ',') +line 13: (identifier - 'Clean') +line 13: (preamble - 'Max:') +line 13: (integer - '80') +line 13: (preamble - 'Increment:') +line 13: (float - '2.5') +line 13: (% - '%') +line 15: (preamble - 'SetTemplates:') +line 16: (- - '-') +line 16: (preamble - 'Warmup:') +line 17: (integer - '5') +line 17: (reps - 'reps') +line 17: (@ - '@') +line 17: (integer - '40') +line 17: (% - '%') +line 17: (, - ',') +line 18: (integer - '5') +line 18: (reps - 'reps') +line 18: (@ - '@') +line 18: (integer - '55') +line 18: (% - '%') +line 18: (, - ',') +line 19: (integer - '5') +line 19: (reps - 'reps') +line 19: (@ - '@') +line 19: (integer - '70') +line 19: (% - '%') +line 21: (- - '-') +line 21: (preamble - 'MondaySets:') +line 22: (identifier - 'Warmup') +line 22: (, - ',') +line 23: (integer - '5') +line 23: (reps - 'reps') +line 23: (@ - '@') +line 23: (integer - '85') +line 23: (% - '%') +line 23: (, - ',') +line 24: (integer - '5') +line 24: (reps - 'reps') +line 24: (@ - '@') +line 24: (integer - '100') +line 24: (% - '%') +line 26: (- - '-') +line 26: (preamble - 'WednesdaySquat:') +line 27: (identifier - 'Warmup') +line 27: (, - ',') +line 28: (integer - '5') +line 28: (reps - 'reps') +line 28: (@ - '@') +line 28: (integer - '70') +line 28: (% - '%') +line 30: (- - '-') +line 30: (preamble - 'WednesdayOther:') +line 31: (integer - '5') +line 31: (reps - 'reps') +line 31: (@ - '@') +line 31: (integer - '55') +line 31: (% - '%') +line 31: (, - ',') +line 32: (integer - '5') +line 32: (reps - 'reps') +line 32: (@ - '@') +line 32: (integer - '70') +line 32: (% - '%') +line 32: (, - ',') +line 33: (integer - '5') +line 33: (reps - 'reps') +line 33: (@ - '@') +line 33: (integer - '85') +line 33: (% - '%') +line 33: (, - ',') +line 34: (integer - '5') +line 34: (reps - 'reps') +line 34: (@ - '@') +line 34: (integer - '100') +line 34: (% - '%') +line 36: (- - '-') +line 36: (preamble - 'FridaySets:') +line 37: (identifier - 'Warmup') +line 37: (, - ',') +line 38: (integer - '5') +line 38: (reps - 'reps') +line 38: (@ - '@') +line 38: (integer - '85') +line 38: (% - '%') +line 38: (, - ',') +line 39: (integer - '3') +line 39: (reps - 'reps') +line 39: (@ - '@') +line 39: (float - '102.5') +line 39: (% - '%') +line 39: (, - ',') +line 40: (integer - '8') +line 40: (reps - 'reps') +line 40: (@ - '@') +line 40: (integer - '70') +line 40: (% - '%') +line 43: (preamble - 'TrainingDays:') +line 44: (- - '-') +line 44: (preamble - 'Squat:') +line 44: (identifier - 'MondaySets') +line 45: (preamble - 'Bench:') +line 45: (identifier - 'MondaySets') +line 46: (preamble - 'Clean:') +line 46: (identifier - 'MondaySets') +line 47: (string - '"2 sets of weighted hypers"') +line 48: (string - '"4 sets of weighted sit-ups"') +line 50: (- - '-') +line 50: (preamble - 'Squat:') +line 50: (identifier - 'WednesdaySquat') +line 51: (preamble - 'Press:') +line 51: (identifier - 'WednesdayOther') +line 51: (increase - 'increase') +line 52: (preamble - 'HighPull:') +line 52: (identifier - 'WednesdayOther') +line 52: (increase - 'increase') +line 53: (string - '"3 sets of sit-ups"') +line 55: (- - '-') +line 55: (preamble - 'Squat:') +line 55: (identifier - 'FridaySets') +line 55: (increase - 'increase') +line 56: (preamble - 'Bench:') +line 56: (identifier - 'FridaySets') +line 56: (increase - 'increase') +line 57: (preamble - 'Clean:') +line 57: (identifier - 'FridaySets') +line 57: (increase - 'increase') +line 58: (string - '"3 sets of weighted dips (5-8 reps)"') +line 59: (string - '"3 sets of barbell curls"') +line 60: (string - '"3 sets of triceps extensons (8 reps)"') diff --git a/test/BillStarr_5x5_Intermediate.tdl.parser b/test/BillStarr_5x5_Intermediate.tdl.parser new file mode 100644 index 0000000..8fd6fe5 --- /dev/null +++ b/test/BillStarr_5x5_Intermediate.tdl.parser @@ -0,0 +1,515 @@ +{ + "Lifts": [ + { + "Name": "Squat", + "Max": 180, + "Increment": 2.5, + "IncrementPercent": true, + "Bar": 0 + }, + { + "Name": "HighPull", + "Max": 120, + "Increment": 2.5, + "IncrementPercent": true, + "Bar": 0 + }, + { + "Name": "Bench", + "Max": 100, + "Increment": 2.5, + "IncrementPercent": true, + "Bar": 0 + }, + { + "Name": "Press", + "Max": 75, + "Increment": 2.5, + "IncrementPercent": true, + "Bar": 0 + }, + { + "Name": "Clean", + "Max": 80, + "Increment": 2.5, + "IncrementPercent": true, + "Bar": 0 + } + ], + "Plates": null, + "SetTemplates": [ + { + "Name": "Warmup", + "Items": [ + { + "Set": { + "Reps": 5, + "Percentage": 40, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "", + "Amount": 0 + }, + { + "Set": { + "Reps": 5, + "Percentage": 55, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "", + "Amount": 0 + }, + { + "Set": { + "Reps": 5, + "Percentage": 70, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "", + "Amount": 0 + } + ] + }, + { + "Name": "MondaySets", + "Items": [ + { + "Set": { + "Reps": 0, + "Percentage": 0, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "Warmup", + "Amount": 0 + }, + { + "Set": { + "Reps": 5, + "Percentage": 85, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "", + "Amount": 0 + }, + { + "Set": { + "Reps": 5, + "Percentage": 100, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "", + "Amount": 0 + } + ] + }, + { + "Name": "WednesdaySquat", + "Items": [ + { + "Set": { + "Reps": 0, + "Percentage": 0, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "Warmup", + "Amount": 0 + }, + { + "Set": { + "Reps": 5, + "Percentage": 70, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "", + "Amount": 0 + } + ] + }, + { + "Name": "WednesdayOther", + "Items": [ + { + "Set": { + "Reps": 5, + "Percentage": 55, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "", + "Amount": 0 + }, + { + "Set": { + "Reps": 5, + "Percentage": 70, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "", + "Amount": 0 + }, + { + "Set": { + "Reps": 5, + "Percentage": 85, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "", + "Amount": 0 + }, + { + "Set": { + "Reps": 5, + "Percentage": 100, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "", + "Amount": 0 + } + ] + }, + { + "Name": "FridaySets", + "Items": [ + { + "Set": { + "Reps": 0, + "Percentage": 0, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "Warmup", + "Amount": 0 + }, + { + "Set": { + "Reps": 5, + "Percentage": 85, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "", + "Amount": 0 + }, + { + "Set": { + "Reps": 3, + "Percentage": 102.5, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "", + "Amount": 0 + }, + { + "Set": { + "Reps": 8, + "Percentage": 70, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "", + "Amount": 0 + } + ] + } + ], + "TrainingDays": [ + { + "Items": [ + { + "LiftSchedule": { + "LiftName": "Squat", + "Items": [ + { + "Set": { + "Reps": 0, + "Percentage": 0, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "MondaySets", + "Amount": 0 + } + ], + "Increase": false, + "IncreaseAmount": 0, + "IncreasePercent": false + }, + "Raw": "" + }, + { + "LiftSchedule": { + "LiftName": "Bench", + "Items": [ + { + "Set": { + "Reps": 0, + "Percentage": 0, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "MondaySets", + "Amount": 0 + } + ], + "Increase": false, + "IncreaseAmount": 0, + "IncreasePercent": false + }, + "Raw": "" + }, + { + "LiftSchedule": { + "LiftName": "Clean", + "Items": [ + { + "Set": { + "Reps": 0, + "Percentage": 0, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "MondaySets", + "Amount": 0 + } + ], + "Increase": false, + "IncreaseAmount": 0, + "IncreasePercent": false + }, + "Raw": "" + }, + { + "LiftSchedule": { + "LiftName": "", + "Items": null, + "Increase": false, + "IncreaseAmount": 0, + "IncreasePercent": false + }, + "Raw": "2 sets of weighted hypers" + }, + { + "LiftSchedule": { + "LiftName": "", + "Items": null, + "Increase": false, + "IncreaseAmount": 0, + "IncreasePercent": false + }, + "Raw": "4 sets of weighted sit-ups" + } + ] + }, + { + "Items": [ + { + "LiftSchedule": { + "LiftName": "Squat", + "Items": [ + { + "Set": { + "Reps": 0, + "Percentage": 0, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "WednesdaySquat", + "Amount": 0 + } + ], + "Increase": false, + "IncreaseAmount": 0, + "IncreasePercent": false + }, + "Raw": "" + }, + { + "LiftSchedule": { + "LiftName": "Press", + "Items": [ + { + "Set": { + "Reps": 0, + "Percentage": 0, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "WednesdayOther", + "Amount": 0 + } + ], + "Increase": true, + "IncreaseAmount": 0, + "IncreasePercent": false + }, + "Raw": "" + }, + { + "LiftSchedule": { + "LiftName": "HighPull", + "Items": [ + { + "Set": { + "Reps": 0, + "Percentage": 0, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "WednesdayOther", + "Amount": 0 + } + ], + "Increase": true, + "IncreaseAmount": 0, + "IncreasePercent": false + }, + "Raw": "" + }, + { + "LiftSchedule": { + "LiftName": "", + "Items": null, + "Increase": false, + "IncreaseAmount": 0, + "IncreasePercent": false + }, + "Raw": "3 sets of sit-ups" + } + ] + }, + { + "Items": [ + { + "LiftSchedule": { + "LiftName": "Squat", + "Items": [ + { + "Set": { + "Reps": 0, + "Percentage": 0, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "FridaySets", + "Amount": 0 + } + ], + "Increase": true, + "IncreaseAmount": 0, + "IncreasePercent": false + }, + "Raw": "" + }, + { + "LiftSchedule": { + "LiftName": "Bench", + "Items": [ + { + "Set": { + "Reps": 0, + "Percentage": 0, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "FridaySets", + "Amount": 0 + } + ], + "Increase": true, + "IncreaseAmount": 0, + "IncreasePercent": false + }, + "Raw": "" + }, + { + "LiftSchedule": { + "LiftName": "Clean", + "Items": [ + { + "Set": { + "Reps": 0, + "Percentage": 0, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "FridaySets", + "Amount": 0 + } + ], + "Increase": true, + "IncreaseAmount": 0, + "IncreasePercent": false + }, + "Raw": "" + }, + { + "LiftSchedule": { + "LiftName": "", + "Items": null, + "Increase": false, + "IncreaseAmount": 0, + "IncreasePercent": false + }, + "Raw": "3 sets of weighted dips (5-8 reps)" + }, + { + "LiftSchedule": { + "LiftName": "", + "Items": null, + "Increase": false, + "IncreaseAmount": 0, + "IncreasePercent": false + }, + "Raw": "3 sets of barbell curls" + }, + { + "LiftSchedule": { + "LiftName": "", + "Items": null, + "Increase": false, + "IncreaseAmount": 0, + "IncreasePercent": false + }, + "Raw": "3 sets of triceps extensons (8 reps)" + } + ] + } + ] +} diff --git a/test/Smolov_PhaseIn_And_BaseCycle.tdl.lexer b/test/Smolov_PhaseIn_And_BaseCycle.tdl.lexer new file mode 100644 index 0000000..8241b9c --- /dev/null +++ b/test/Smolov_PhaseIn_And_BaseCycle.tdl.lexer @@ -0,0 +1,250 @@ +line 1: (preamble - 'Lifts:') +line 2: (identifier - 'Squat') +line 2: (preamble - 'Max:') +line 2: (integer - '200') +line 2: (preamble - 'Increment:') +line 2: (integer - '0') +line 4: (preamble - 'TrainingDays:') +line 8: (- - '-') +line 8: (preamble - 'Squat:') +line 8: (integer - '8') +line 8: (reps - 'reps') +line 8: (@ - '@') +line 8: (integer - '65') +line 8: (% - '%') +line 8: (x - 'x') +line 8: (integer - '3') +line 8: (, - ',') +line 8: (integer - '5') +line 8: (reps - 'reps') +line 8: (@ - '@') +line 8: (integer - '70') +line 8: (% - '%') +line 8: (, - ',') +line 8: (integer - '2') +line 8: (reps - 'reps') +line 8: (@ - '@') +line 8: (integer - '75') +line 8: (% - '%') +line 8: (x - 'x') +line 8: (integer - '2') +line 8: (, - ',') +line 8: (integer - '1') +line 8: (reps - 'reps') +line 8: (@ - '@') +line 8: (integer - '80') +line 8: (% - '%') +line 10: (- - '-') +line 10: (preamble - 'Squat:') +line 10: (integer - '8') +line 10: (reps - 'reps') +line 10: (@ - '@') +line 10: (integer - '65') +line 10: (% - '%') +line 10: (x - 'x') +line 10: (integer - '3') +line 10: (, - ',') +line 10: (integer - '5') +line 10: (reps - 'reps') +line 10: (@ - '@') +line 10: (integer - '70') +line 10: (% - '%') +line 10: (, - ',') +line 10: (integer - '2') +line 10: (reps - 'reps') +line 10: (@ - '@') +line 10: (integer - '75') +line 10: (% - '%') +line 10: (x - 'x') +line 10: (integer - '2') +line 10: (, - ',') +line 10: (integer - '1') +line 10: (reps - 'reps') +line 10: (@ - '@') +line 10: (integer - '80') +line 10: (% - '%') +line 12: (- - '-') +line 12: (preamble - 'Squat:') +line 12: (integer - '5') +line 12: (reps - 'reps') +line 12: (@ - '@') +line 12: (integer - '70') +line 12: (% - '%') +line 12: (x - 'x') +line 12: (integer - '4') +line 12: (, - ',') +line 12: (integer - '3') +line 12: (reps - 'reps') +line 12: (@ - '@') +line 12: (integer - '75') +line 12: (% - '%') +line 12: (, - ',') +line 12: (integer - '2') +line 12: (reps - 'reps') +line 12: (@ - '@') +line 12: (integer - '80') +line 12: (% - '%') +line 12: (x - 'x') +line 12: (integer - '2') +line 12: (, - ',') +line 12: (integer - '1') +line 12: (reps - 'reps') +line 12: (@ - '@') +line 12: (integer - '90') +line 12: (% - '%') +line 17: (- - '-') +line 17: (string - '"Lunges"') +line 18: (preamble - 'Squat:') +line 18: (integer - '5') +line 18: (reps - 'reps') +line 18: (@ - '@') +line 18: (integer - '80') +line 18: (% - '%') +line 20: (- - '-') +line 20: (string - '"Lunges"') +line 21: (preamble - 'Squat:') +line 21: (integer - '5') +line 21: (reps - 'reps') +line 21: (@ - '@') +line 21: (float - '82.5') +line 21: (% - '%') +line 23: (- - '-') +line 23: (string - '"Lunges"') +line 24: (preamble - 'Squat:') +line 24: (integer - '5') +line 24: (reps - 'reps') +line 24: (@ - '@') +line 24: (integer - '85') +line 24: (% - '%') +line 29: (- - '-') +line 29: (preamble - 'Squat:') +line 29: (integer - '9') +line 29: (reps - 'reps') +line 29: (@ - '@') +line 29: (integer - '70') +line 29: (% - '%') +line 29: (x - 'x') +line 29: (integer - '4') +line 31: (- - '-') +line 31: (preamble - 'Squat:') +line 31: (integer - '7') +line 31: (reps - 'reps') +line 31: (@ - '@') +line 31: (integer - '75') +line 31: (% - '%') +line 31: (x - 'x') +line 31: (integer - '5') +line 33: (- - '-') +line 33: (preamble - 'Squat:') +line 33: (integer - '5') +line 33: (reps - 'reps') +line 33: (@ - '@') +line 33: (integer - '80') +line 33: (% - '%') +line 33: (x - 'x') +line 33: (integer - '7') +line 35: (- - '-') +line 35: (preamble - 'Squat:') +line 35: (integer - '3') +line 35: (reps - 'reps') +line 35: (@ - '@') +line 35: (integer - '85') +line 35: (% - '%') +line 35: (x - 'x') +line 35: (integer - '10') +line 40: (- - '-') +line 40: (preamble - 'Squat:') +line 40: (integer - '9') +line 40: (reps - 'reps') +line 40: (@ - '@') +line 40: (integer - '70') +line 40: (% - '%') +line 40: (+ - '+') +line 40: (integer - '9') +line 40: (x - 'x') +line 40: (integer - '4') +line 42: (- - '-') +line 42: (preamble - 'Squat:') +line 42: (integer - '7') +line 42: (reps - 'reps') +line 42: (@ - '@') +line 42: (integer - '75') +line 42: (% - '%') +line 42: (+ - '+') +line 42: (integer - '9') +line 42: (x - 'x') +line 42: (integer - '5') +line 44: (- - '-') +line 44: (preamble - 'Squat:') +line 44: (integer - '5') +line 44: (reps - 'reps') +line 44: (@ - '@') +line 44: (integer - '80') +line 44: (% - '%') +line 44: (+ - '+') +line 44: (integer - '9') +line 44: (x - 'x') +line 44: (integer - '7') +line 46: (- - '-') +line 46: (preamble - 'Squat:') +line 46: (integer - '3') +line 46: (reps - 'reps') +line 46: (@ - '@') +line 46: (integer - '85') +line 46: (% - '%') +line 46: (+ - '+') +line 46: (integer - '9') +line 46: (x - 'x') +line 46: (integer - '10') +line 51: (- - '-') +line 51: (preamble - 'Squat:') +line 51: (integer - '9') +line 51: (reps - 'reps') +line 51: (@ - '@') +line 51: (integer - '70') +line 51: (% - '%') +line 51: (+ - '+') +line 51: (float - '13.5') +line 51: (x - 'x') +line 51: (integer - '4') +line 53: (- - '-') +line 53: (preamble - 'Squat:') +line 53: (integer - '7') +line 53: (reps - 'reps') +line 53: (@ - '@') +line 53: (integer - '75') +line 53: (% - '%') +line 53: (+ - '+') +line 53: (float - '13.5') +line 53: (x - 'x') +line 53: (integer - '5') +line 55: (- - '-') +line 55: (preamble - 'Squat:') +line 55: (integer - '5') +line 55: (reps - 'reps') +line 55: (@ - '@') +line 55: (integer - '80') +line 55: (% - '%') +line 55: (+ - '+') +line 55: (float - '13.5') +line 55: (x - 'x') +line 55: (integer - '7') +line 57: (- - '-') +line 57: (preamble - 'Squat:') +line 57: (integer - '3') +line 57: (reps - 'reps') +line 57: (@ - '@') +line 57: (integer - '85') +line 57: (% - '%') +line 57: (+ - '+') +line 57: (float - '13.5') +line 57: (x - 'x') +line 57: (integer - '10') +line 62: (- - '-') +line 62: (string - '"Rest"') +line 64: (- - '-') +line 64: (string - '"Rest"') +line 66: (- - '-') +line 66: (string - '"Build to 1RM"') +line 68: (- - '-') +line 68: (string - '"Build to 1RM"') diff --git a/test/Smolov_PhaseIn_And_BaseCycle.tdl.parser b/test/Smolov_PhaseIn_And_BaseCycle.tdl.parser new file mode 100644 index 0000000..31c4e4e --- /dev/null +++ b/test/Smolov_PhaseIn_And_BaseCycle.tdl.parser @@ -0,0 +1,668 @@ +{ + "Lifts": [ + { + "Name": "Squat", + "Max": 200, + "Increment": 0, + "IncrementPercent": false, + "Bar": 0 + } + ], + "Plates": null, + "SetTemplates": null, + "TrainingDays": [ + { + "Items": [ + { + "LiftSchedule": { + "LiftName": "Squat", + "Items": [ + { + "Set": { + "Reps": 8, + "Percentage": 65, + "PlusWeight": 0, + "Amount": 3, + "Notice": "" + }, + "ReferenceName": "", + "Amount": 0 + }, + { + "Set": { + "Reps": 5, + "Percentage": 70, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "", + "Amount": 0 + }, + { + "Set": { + "Reps": 2, + "Percentage": 75, + "PlusWeight": 0, + "Amount": 2, + "Notice": "" + }, + "ReferenceName": "", + "Amount": 0 + }, + { + "Set": { + "Reps": 1, + "Percentage": 80, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "", + "Amount": 0 + } + ], + "Increase": false, + "IncreaseAmount": 0, + "IncreasePercent": false + }, + "Raw": "" + } + ] + }, + { + "Items": [ + { + "LiftSchedule": { + "LiftName": "Squat", + "Items": [ + { + "Set": { + "Reps": 8, + "Percentage": 65, + "PlusWeight": 0, + "Amount": 3, + "Notice": "" + }, + "ReferenceName": "", + "Amount": 0 + }, + { + "Set": { + "Reps": 5, + "Percentage": 70, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "", + "Amount": 0 + }, + { + "Set": { + "Reps": 2, + "Percentage": 75, + "PlusWeight": 0, + "Amount": 2, + "Notice": "" + }, + "ReferenceName": "", + "Amount": 0 + }, + { + "Set": { + "Reps": 1, + "Percentage": 80, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "", + "Amount": 0 + } + ], + "Increase": false, + "IncreaseAmount": 0, + "IncreasePercent": false + }, + "Raw": "" + } + ] + }, + { + "Items": [ + { + "LiftSchedule": { + "LiftName": "Squat", + "Items": [ + { + "Set": { + "Reps": 5, + "Percentage": 70, + "PlusWeight": 0, + "Amount": 4, + "Notice": "" + }, + "ReferenceName": "", + "Amount": 0 + }, + { + "Set": { + "Reps": 3, + "Percentage": 75, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "", + "Amount": 0 + }, + { + "Set": { + "Reps": 2, + "Percentage": 80, + "PlusWeight": 0, + "Amount": 2, + "Notice": "" + }, + "ReferenceName": "", + "Amount": 0 + }, + { + "Set": { + "Reps": 1, + "Percentage": 90, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "", + "Amount": 0 + } + ], + "Increase": false, + "IncreaseAmount": 0, + "IncreasePercent": false + }, + "Raw": "" + } + ] + }, + { + "Items": [ + { + "LiftSchedule": { + "LiftName": "", + "Items": null, + "Increase": false, + "IncreaseAmount": 0, + "IncreasePercent": false + }, + "Raw": "Lunges" + }, + { + "LiftSchedule": { + "LiftName": "Squat", + "Items": [ + { + "Set": { + "Reps": 5, + "Percentage": 80, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "", + "Amount": 0 + } + ], + "Increase": false, + "IncreaseAmount": 0, + "IncreasePercent": false + }, + "Raw": "" + } + ] + }, + { + "Items": [ + { + "LiftSchedule": { + "LiftName": "", + "Items": null, + "Increase": false, + "IncreaseAmount": 0, + "IncreasePercent": false + }, + "Raw": "Lunges" + }, + { + "LiftSchedule": { + "LiftName": "Squat", + "Items": [ + { + "Set": { + "Reps": 5, + "Percentage": 82.5, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "", + "Amount": 0 + } + ], + "Increase": false, + "IncreaseAmount": 0, + "IncreasePercent": false + }, + "Raw": "" + } + ] + }, + { + "Items": [ + { + "LiftSchedule": { + "LiftName": "", + "Items": null, + "Increase": false, + "IncreaseAmount": 0, + "IncreasePercent": false + }, + "Raw": "Lunges" + }, + { + "LiftSchedule": { + "LiftName": "Squat", + "Items": [ + { + "Set": { + "Reps": 5, + "Percentage": 85, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "", + "Amount": 0 + } + ], + "Increase": false, + "IncreaseAmount": 0, + "IncreasePercent": false + }, + "Raw": "" + } + ] + }, + { + "Items": [ + { + "LiftSchedule": { + "LiftName": "Squat", + "Items": [ + { + "Set": { + "Reps": 9, + "Percentage": 70, + "PlusWeight": 0, + "Amount": 4, + "Notice": "" + }, + "ReferenceName": "", + "Amount": 0 + } + ], + "Increase": false, + "IncreaseAmount": 0, + "IncreasePercent": false + }, + "Raw": "" + } + ] + }, + { + "Items": [ + { + "LiftSchedule": { + "LiftName": "Squat", + "Items": [ + { + "Set": { + "Reps": 7, + "Percentage": 75, + "PlusWeight": 0, + "Amount": 5, + "Notice": "" + }, + "ReferenceName": "", + "Amount": 0 + } + ], + "Increase": false, + "IncreaseAmount": 0, + "IncreasePercent": false + }, + "Raw": "" + } + ] + }, + { + "Items": [ + { + "LiftSchedule": { + "LiftName": "Squat", + "Items": [ + { + "Set": { + "Reps": 5, + "Percentage": 80, + "PlusWeight": 0, + "Amount": 7, + "Notice": "" + }, + "ReferenceName": "", + "Amount": 0 + } + ], + "Increase": false, + "IncreaseAmount": 0, + "IncreasePercent": false + }, + "Raw": "" + } + ] + }, + { + "Items": [ + { + "LiftSchedule": { + "LiftName": "Squat", + "Items": [ + { + "Set": { + "Reps": 3, + "Percentage": 85, + "PlusWeight": 0, + "Amount": 10, + "Notice": "" + }, + "ReferenceName": "", + "Amount": 0 + } + ], + "Increase": false, + "IncreaseAmount": 0, + "IncreasePercent": false + }, + "Raw": "" + } + ] + }, + { + "Items": [ + { + "LiftSchedule": { + "LiftName": "Squat", + "Items": [ + { + "Set": { + "Reps": 9, + "Percentage": 70, + "PlusWeight": 9, + "Amount": 4, + "Notice": "" + }, + "ReferenceName": "", + "Amount": 0 + } + ], + "Increase": false, + "IncreaseAmount": 0, + "IncreasePercent": false + }, + "Raw": "" + } + ] + }, + { + "Items": [ + { + "LiftSchedule": { + "LiftName": "Squat", + "Items": [ + { + "Set": { + "Reps": 7, + "Percentage": 75, + "PlusWeight": 9, + "Amount": 5, + "Notice": "" + }, + "ReferenceName": "", + "Amount": 0 + } + ], + "Increase": false, + "IncreaseAmount": 0, + "IncreasePercent": false + }, + "Raw": "" + } + ] + }, + { + "Items": [ + { + "LiftSchedule": { + "LiftName": "Squat", + "Items": [ + { + "Set": { + "Reps": 5, + "Percentage": 80, + "PlusWeight": 9, + "Amount": 7, + "Notice": "" + }, + "ReferenceName": "", + "Amount": 0 + } + ], + "Increase": false, + "IncreaseAmount": 0, + "IncreasePercent": false + }, + "Raw": "" + } + ] + }, + { + "Items": [ + { + "LiftSchedule": { + "LiftName": "Squat", + "Items": [ + { + "Set": { + "Reps": 3, + "Percentage": 85, + "PlusWeight": 9, + "Amount": 10, + "Notice": "" + }, + "ReferenceName": "", + "Amount": 0 + } + ], + "Increase": false, + "IncreaseAmount": 0, + "IncreasePercent": false + }, + "Raw": "" + } + ] + }, + { + "Items": [ + { + "LiftSchedule": { + "LiftName": "Squat", + "Items": [ + { + "Set": { + "Reps": 9, + "Percentage": 70, + "PlusWeight": 13.5, + "Amount": 4, + "Notice": "" + }, + "ReferenceName": "", + "Amount": 0 + } + ], + "Increase": false, + "IncreaseAmount": 0, + "IncreasePercent": false + }, + "Raw": "" + } + ] + }, + { + "Items": [ + { + "LiftSchedule": { + "LiftName": "Squat", + "Items": [ + { + "Set": { + "Reps": 7, + "Percentage": 75, + "PlusWeight": 13.5, + "Amount": 5, + "Notice": "" + }, + "ReferenceName": "", + "Amount": 0 + } + ], + "Increase": false, + "IncreaseAmount": 0, + "IncreasePercent": false + }, + "Raw": "" + } + ] + }, + { + "Items": [ + { + "LiftSchedule": { + "LiftName": "Squat", + "Items": [ + { + "Set": { + "Reps": 5, + "Percentage": 80, + "PlusWeight": 13.5, + "Amount": 7, + "Notice": "" + }, + "ReferenceName": "", + "Amount": 0 + } + ], + "Increase": false, + "IncreaseAmount": 0, + "IncreasePercent": false + }, + "Raw": "" + } + ] + }, + { + "Items": [ + { + "LiftSchedule": { + "LiftName": "Squat", + "Items": [ + { + "Set": { + "Reps": 3, + "Percentage": 85, + "PlusWeight": 13.5, + "Amount": 10, + "Notice": "" + }, + "ReferenceName": "", + "Amount": 0 + } + ], + "Increase": false, + "IncreaseAmount": 0, + "IncreasePercent": false + }, + "Raw": "" + } + ] + }, + { + "Items": [ + { + "LiftSchedule": { + "LiftName": "", + "Items": null, + "Increase": false, + "IncreaseAmount": 0, + "IncreasePercent": false + }, + "Raw": "Rest" + } + ] + }, + { + "Items": [ + { + "LiftSchedule": { + "LiftName": "", + "Items": null, + "Increase": false, + "IncreaseAmount": 0, + "IncreasePercent": false + }, + "Raw": "Rest" + } + ] + }, + { + "Items": [ + { + "LiftSchedule": { + "LiftName": "", + "Items": null, + "Increase": false, + "IncreaseAmount": 0, + "IncreasePercent": false + }, + "Raw": "Build to 1RM" + } + ] + }, + { + "Items": [ + { + "LiftSchedule": { + "LiftName": "", + "Items": null, + "Increase": false, + "IncreaseAmount": 0, + "IncreasePercent": false + }, + "Raw": "Build to 1RM" + } + ] + } + ] +} diff --git a/test/Smolov_Switching_Intense_Taper.tdl.lexer b/test/Smolov_Switching_Intense_Taper.tdl.lexer new file mode 100644 index 0000000..cff8d25 --- /dev/null +++ b/test/Smolov_Switching_Intense_Taper.tdl.lexer @@ -0,0 +1,415 @@ +line 3: (preamble - 'Lifts:') +line 4: (identifier - 'Squat') +line 4: (preamble - 'Max:') +line 4: (integer - '230') +line 4: (preamble - 'Increment:') +line 4: (integer - '0') +line 6: (preamble - 'TrainingDays:') +line 10: (- - '-') +line 10: (preamble - 'Squat:') +line 10: (integer - '1') +line 10: (reps - 'reps') +line 10: (@ - '@') +line 10: (integer - '50') +line 10: (% - '%') +line 10: (notice - '(several with dynamic effort)') +line 12: (- - '-') +line 12: (preamble - 'Squat:') +line 12: (integer - '1') +line 12: (reps - 'reps') +line 12: (@ - '@') +line 12: (integer - '50') +line 12: (% - '%') +line 12: (notice - '(several with dynamic effort)') +line 14: (- - '-') +line 14: (preamble - 'Squat:') +line 14: (integer - '1') +line 14: (reps - 'reps') +line 14: (@ - '@') +line 14: (integer - '50') +line 14: (% - '%') +line 14: (notice - '(several with dynamic effort)') +line 19: (- - '-') +line 19: (preamble - 'Squat:') +line 19: (integer - '1') +line 19: (reps - 'reps') +line 19: (@ - '@') +line 19: (integer - '50') +line 19: (% - '%') +line 19: (notice - '(several with dynamic effort)') +line 21: (- - '-') +line 21: (preamble - 'Squat:') +line 21: (integer - '1') +line 21: (reps - 'reps') +line 21: (@ - '@') +line 21: (integer - '50') +line 21: (% - '%') +line 21: (notice - '(several with dynamic effort)') +line 23: (- - '-') +line 23: (preamble - 'Squat:') +line 23: (integer - '1') +line 23: (reps - 'reps') +line 23: (@ - '@') +line 23: (integer - '50') +line 23: (% - '%') +line 23: (notice - '(several with dynamic effort)') +line 28: (- - '-') +line 28: (preamble - 'Squat:') +line 28: (integer - '3') +line 28: (reps - 'reps') +line 28: (@ - '@') +line 28: (integer - '65') +line 28: (% - '%') +line 28: (, - ',') +line 28: (integer - '4') +line 28: (reps - 'reps') +line 28: (@ - '@') +line 28: (integer - '75') +line 28: (% - '%') +line 28: (, - ',') +line 28: (integer - '4') +line 28: (reps - 'reps') +line 28: (@ - '@') +line 28: (integer - '85') +line 28: (% - '%') +line 28: (x - 'x') +line 28: (integer - '3') +line 28: (, - ',') +line 28: (integer - '5') +line 28: (reps - 'reps') +line 28: (@ - '@') +line 28: (integer - '85') +line 28: (% - '%') +line 30: (- - '-') +line 30: (preamble - 'Squat:') +line 30: (integer - '3') +line 30: (reps - 'reps') +line 30: (@ - '@') +line 30: (integer - '60') +line 30: (% - '%') +line 30: (, - ',') +line 30: (integer - '3') +line 30: (reps - 'reps') +line 30: (@ - '@') +line 30: (integer - '70') +line 30: (% - '%') +line 30: (, - ',') +line 30: (integer - '4') +line 30: (reps - 'reps') +line 30: (@ - '@') +line 30: (integer - '80') +line 30: (% - '%') +line 30: (, - ',') +line 30: (integer - '3') +line 30: (reps - 'reps') +line 30: (@ - '@') +line 30: (integer - '90') +line 30: (% - '%') +line 30: (, - ',') +line 30: (integer - '5') +line 30: (reps - 'reps') +line 30: (@ - '@') +line 30: (integer - '85') +line 30: (% - '%') +line 30: (x - 'x') +line 30: (integer - '2') +line 32: (- - '-') +line 32: (preamble - 'Squat:') +line 32: (integer - '4') +line 32: (reps - 'reps') +line 32: (@ - '@') +line 32: (integer - '65') +line 32: (% - '%') +line 32: (, - ',') +line 32: (integer - '4') +line 32: (reps - 'reps') +line 32: (@ - '@') +line 32: (integer - '70') +line 32: (% - '%') +line 32: (, - ',') +line 32: (integer - '4') +line 32: (reps - 'reps') +line 32: (@ - '@') +line 32: (integer - '80') +line 32: (% - '%') +line 32: (x - 'x') +line 32: (integer - '5') +line 37: (- - '-') +line 37: (preamble - 'Squat:') +line 37: (integer - '4') +line 37: (reps - 'reps') +line 37: (@ - '@') +line 37: (integer - '60') +line 37: (% - '%') +line 37: (, - ',') +line 37: (integer - '4') +line 37: (reps - 'reps') +line 37: (@ - '@') +line 37: (integer - '70') +line 37: (% - '%') +line 37: (, - ',') +line 37: (integer - '4') +line 37: (reps - 'reps') +line 37: (@ - '@') +line 37: (integer - '80') +line 37: (% - '%') +line 37: (, - ',') +line 37: (integer - '3') +line 37: (reps - 'reps') +line 37: (@ - '@') +line 37: (integer - '90') +line 37: (% - '%') +line 37: (, - ',') +line 37: (integer - '4') +line 37: (reps - 'reps') +line 37: (@ - '@') +line 37: (integer - '90') +line 37: (% - '%') +line 37: (x - 'x') +line 37: (integer - '2') +line 39: (- - '-') +line 39: (preamble - 'Squat:') +line 39: (integer - '3') +line 39: (reps - 'reps') +line 39: (@ - '@') +line 39: (integer - '65') +line 39: (% - '%') +line 39: (, - ',') +line 39: (integer - '3') +line 39: (reps - 'reps') +line 39: (@ - '@') +line 39: (integer - '75') +line 39: (% - '%') +line 39: (, - ',') +line 39: (integer - '3') +line 39: (reps - 'reps') +line 39: (@ - '@') +line 39: (integer - '85') +line 39: (% - '%') +line 39: (, - ',') +line 39: (integer - '3') +line 39: (reps - 'reps') +line 39: (@ - '@') +line 39: (integer - '90') +line 39: (% - '%') +line 39: (x - 'x') +line 39: (integer - '3') +line 39: (, - ',') +line 39: (integer - '3') +line 39: (reps - 'reps') +line 39: (@ - '@') +line 39: (integer - '95') +line 39: (% - '%') +line 41: (- - '-') +line 41: (preamble - 'Squat:') +line 41: (integer - '3') +line 41: (reps - 'reps') +line 41: (@ - '@') +line 41: (integer - '65') +line 41: (% - '%') +line 41: (, - ',') +line 41: (integer - '3') +line 41: (reps - 'reps') +line 41: (@ - '@') +line 41: (integer - '75') +line 41: (% - '%') +line 41: (, - ',') +line 41: (integer - '4') +line 41: (reps - 'reps') +line 41: (@ - '@') +line 41: (integer - '85') +line 41: (% - '%') +line 41: (, - ',') +line 41: (integer - '5') +line 41: (reps - 'reps') +line 41: (@ - '@') +line 41: (integer - '90') +line 41: (% - '%') +line 46: (- - '-') +line 46: (preamble - 'Squat:') +line 46: (integer - '3') +line 46: (reps - 'reps') +line 46: (@ - '@') +line 46: (integer - '60') +line 46: (% - '%') +line 46: (, - ',') +line 46: (integer - '3') +line 46: (reps - 'reps') +line 46: (@ - '@') +line 46: (integer - '70') +line 46: (% - '%') +line 46: (, - ',') +line 46: (integer - '3') +line 46: (reps - 'reps') +line 46: (@ - '@') +line 46: (integer - '80') +line 46: (% - '%') +line 46: (, - ',') +line 46: (integer - '5') +line 46: (reps - 'reps') +line 46: (@ - '@') +line 46: (integer - '90') +line 46: (% - '%') +line 46: (x - 'x') +line 46: (integer - '5') +line 48: (- - '-') +line 48: (preamble - 'Squat:') +line 48: (integer - '3') +line 48: (reps - 'reps') +line 48: (@ - '@') +line 48: (integer - '60') +line 48: (% - '%') +line 48: (, - ',') +line 48: (integer - '3') +line 48: (reps - 'reps') +line 48: (@ - '@') +line 48: (integer - '70') +line 48: (% - '%') +line 48: (, - ',') +line 48: (integer - '3') +line 48: (reps - 'reps') +line 48: (@ - '@') +line 48: (integer - '80') +line 48: (% - '%') +line 48: (, - ',') +line 48: (integer - '3') +line 48: (reps - 'reps') +line 48: (@ - '@') +line 48: (integer - '95') +line 48: (% - '%') +line 48: (x - 'x') +line 48: (integer - '2') +line 50: (- - '-') +line 50: (preamble - 'Squat:') +line 50: (integer - '3') +line 50: (reps - 'reps') +line 50: (@ - '@') +line 50: (integer - '65') +line 50: (% - '%') +line 50: (, - ',') +line 50: (integer - '3') +line 50: (reps - 'reps') +line 50: (@ - '@') +line 50: (integer - '75') +line 50: (% - '%') +line 50: (, - ',') +line 50: (integer - '3') +line 50: (reps - 'reps') +line 50: (@ - '@') +line 50: (integer - '85') +line 50: (% - '%') +line 50: (, - ',') +line 50: (integer - '3') +line 50: (reps - 'reps') +line 50: (@ - '@') +line 50: (integer - '95') +line 50: (% - '%') +line 50: (x - 'x') +line 50: (integer - '4') +line 55: (- - '-') +line 55: (preamble - 'Squat:') +line 55: (integer - '3') +line 55: (reps - 'reps') +line 55: (@ - '@') +line 55: (integer - '70') +line 55: (% - '%') +line 55: (, - ',') +line 55: (integer - '4') +line 55: (reps - 'reps') +line 55: (@ - '@') +line 55: (integer - '80') +line 55: (% - '%') +line 55: (, - ',') +line 55: (integer - '5') +line 55: (reps - 'reps') +line 55: (@ - '@') +line 55: (integer - '90') +line 55: (% - '%') +line 55: (x - 'x') +line 55: (integer - '5') +line 57: (- - '-') +line 57: (preamble - 'Squat:') +line 57: (integer - '3') +line 57: (reps - 'reps') +line 57: (@ - '@') +line 57: (integer - '70') +line 57: (% - '%') +line 57: (, - ',') +line 57: (integer - '3') +line 57: (reps - 'reps') +line 57: (@ - '@') +line 57: (integer - '80') +line 57: (% - '%') +line 57: (, - ',') +line 57: (integer - '3') +line 57: (reps - 'reps') +line 57: (@ - '@') +line 57: (integer - '95') +line 57: (% - '%') +line 57: (x - 'x') +line 57: (integer - '4') +line 59: (- - '-') +line 59: (preamble - 'Squat:') +line 59: (integer - '3') +line 59: (reps - 'reps') +line 59: (@ - '@') +line 59: (integer - '75') +line 59: (% - '%') +line 59: (, - ',') +line 59: (integer - '4') +line 59: (reps - 'reps') +line 59: (@ - '@') +line 59: (integer - '90') +line 59: (% - '%') +line 59: (, - ',') +line 59: (integer - '4') +line 59: (reps - 'reps') +line 59: (@ - '@') +line 59: (integer - '80') +line 59: (% - '%') +line 59: (x - 'x') +line 59: (integer - '3') +line 64: (- - '-') +line 64: (preamble - 'Squat:') +line 64: (integer - '3') +line 64: (reps - 'reps') +line 64: (@ - '@') +line 64: (integer - '70') +line 64: (% - '%') +line 64: (, - ',') +line 64: (integer - '3') +line 64: (reps - 'reps') +line 64: (@ - '@') +line 64: (integer - '80') +line 64: (% - '%') +line 64: (, - ',') +line 64: (integer - '5') +line 64: (reps - 'reps') +line 64: (@ - '@') +line 64: (integer - '90') +line 64: (% - '%') +line 64: (x - 'x') +line 64: (integer - '2') +line 64: (, - ',') +line 64: (integer - '4') +line 64: (reps - 'reps') +line 64: (@ - '@') +line 64: (integer - '95') +line 64: (% - '%') +line 66: (- - '-') +line 66: (preamble - 'Squat:') +line 66: (integer - '4') +line 66: (reps - 'reps') +line 66: (@ - '@') +line 66: (integer - '75') +line 66: (% - '%') +line 66: (, - ',') +line 66: (integer - '4') +line 66: (reps - 'reps') +line 66: (@ - '@') +line 66: (integer - '85') +line 66: (% - '%') +line 66: (x - 'x') +line 66: (integer - '4') +line 68: (- - '-') +line 68: (string - '"Build to 1RM"') diff --git a/test/Smolov_Switching_Intense_Taper.tdl.parser b/test/Smolov_Switching_Intense_Taper.tdl.parser new file mode 100644 index 0000000..98704b8 --- /dev/null +++ b/test/Smolov_Switching_Intense_Taper.tdl.parser @@ -0,0 +1,978 @@ +{ + "Lifts": [ + { + "Name": "Squat", + "Max": 230, + "Increment": 0, + "IncrementPercent": false, + "Bar": 0 + } + ], + "Plates": null, + "SetTemplates": null, + "TrainingDays": [ + { + "Items": [ + { + "LiftSchedule": { + "LiftName": "Squat", + "Items": [ + { + "Set": { + "Reps": 1, + "Percentage": 50, + "PlusWeight": 0, + "Amount": 0, + "Notice": "(several with dynamic effort)" + }, + "ReferenceName": "", + "Amount": 0 + } + ], + "Increase": false, + "IncreaseAmount": 0, + "IncreasePercent": false + }, + "Raw": "" + } + ] + }, + { + "Items": [ + { + "LiftSchedule": { + "LiftName": "Squat", + "Items": [ + { + "Set": { + "Reps": 1, + "Percentage": 50, + "PlusWeight": 0, + "Amount": 0, + "Notice": "(several with dynamic effort)" + }, + "ReferenceName": "", + "Amount": 0 + } + ], + "Increase": false, + "IncreaseAmount": 0, + "IncreasePercent": false + }, + "Raw": "" + } + ] + }, + { + "Items": [ + { + "LiftSchedule": { + "LiftName": "Squat", + "Items": [ + { + "Set": { + "Reps": 1, + "Percentage": 50, + "PlusWeight": 0, + "Amount": 0, + "Notice": "(several with dynamic effort)" + }, + "ReferenceName": "", + "Amount": 0 + } + ], + "Increase": false, + "IncreaseAmount": 0, + "IncreasePercent": false + }, + "Raw": "" + } + ] + }, + { + "Items": [ + { + "LiftSchedule": { + "LiftName": "Squat", + "Items": [ + { + "Set": { + "Reps": 1, + "Percentage": 50, + "PlusWeight": 0, + "Amount": 0, + "Notice": "(several with dynamic effort)" + }, + "ReferenceName": "", + "Amount": 0 + } + ], + "Increase": false, + "IncreaseAmount": 0, + "IncreasePercent": false + }, + "Raw": "" + } + ] + }, + { + "Items": [ + { + "LiftSchedule": { + "LiftName": "Squat", + "Items": [ + { + "Set": { + "Reps": 1, + "Percentage": 50, + "PlusWeight": 0, + "Amount": 0, + "Notice": "(several with dynamic effort)" + }, + "ReferenceName": "", + "Amount": 0 + } + ], + "Increase": false, + "IncreaseAmount": 0, + "IncreasePercent": false + }, + "Raw": "" + } + ] + }, + { + "Items": [ + { + "LiftSchedule": { + "LiftName": "Squat", + "Items": [ + { + "Set": { + "Reps": 1, + "Percentage": 50, + "PlusWeight": 0, + "Amount": 0, + "Notice": "(several with dynamic effort)" + }, + "ReferenceName": "", + "Amount": 0 + } + ], + "Increase": false, + "IncreaseAmount": 0, + "IncreasePercent": false + }, + "Raw": "" + } + ] + }, + { + "Items": [ + { + "LiftSchedule": { + "LiftName": "Squat", + "Items": [ + { + "Set": { + "Reps": 3, + "Percentage": 65, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "", + "Amount": 0 + }, + { + "Set": { + "Reps": 4, + "Percentage": 75, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "", + "Amount": 0 + }, + { + "Set": { + "Reps": 4, + "Percentage": 85, + "PlusWeight": 0, + "Amount": 3, + "Notice": "" + }, + "ReferenceName": "", + "Amount": 0 + }, + { + "Set": { + "Reps": 5, + "Percentage": 85, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "", + "Amount": 0 + } + ], + "Increase": false, + "IncreaseAmount": 0, + "IncreasePercent": false + }, + "Raw": "" + } + ] + }, + { + "Items": [ + { + "LiftSchedule": { + "LiftName": "Squat", + "Items": [ + { + "Set": { + "Reps": 3, + "Percentage": 60, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "", + "Amount": 0 + }, + { + "Set": { + "Reps": 3, + "Percentage": 70, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "", + "Amount": 0 + }, + { + "Set": { + "Reps": 4, + "Percentage": 80, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "", + "Amount": 0 + }, + { + "Set": { + "Reps": 3, + "Percentage": 90, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "", + "Amount": 0 + }, + { + "Set": { + "Reps": 5, + "Percentage": 85, + "PlusWeight": 0, + "Amount": 2, + "Notice": "" + }, + "ReferenceName": "", + "Amount": 0 + } + ], + "Increase": false, + "IncreaseAmount": 0, + "IncreasePercent": false + }, + "Raw": "" + } + ] + }, + { + "Items": [ + { + "LiftSchedule": { + "LiftName": "Squat", + "Items": [ + { + "Set": { + "Reps": 4, + "Percentage": 65, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "", + "Amount": 0 + }, + { + "Set": { + "Reps": 4, + "Percentage": 70, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "", + "Amount": 0 + }, + { + "Set": { + "Reps": 4, + "Percentage": 80, + "PlusWeight": 0, + "Amount": 5, + "Notice": "" + }, + "ReferenceName": "", + "Amount": 0 + } + ], + "Increase": false, + "IncreaseAmount": 0, + "IncreasePercent": false + }, + "Raw": "" + } + ] + }, + { + "Items": [ + { + "LiftSchedule": { + "LiftName": "Squat", + "Items": [ + { + "Set": { + "Reps": 4, + "Percentage": 60, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "", + "Amount": 0 + }, + { + "Set": { + "Reps": 4, + "Percentage": 70, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "", + "Amount": 0 + }, + { + "Set": { + "Reps": 4, + "Percentage": 80, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "", + "Amount": 0 + }, + { + "Set": { + "Reps": 3, + "Percentage": 90, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "", + "Amount": 0 + }, + { + "Set": { + "Reps": 4, + "Percentage": 90, + "PlusWeight": 0, + "Amount": 2, + "Notice": "" + }, + "ReferenceName": "", + "Amount": 0 + } + ], + "Increase": false, + "IncreaseAmount": 0, + "IncreasePercent": false + }, + "Raw": "" + } + ] + }, + { + "Items": [ + { + "LiftSchedule": { + "LiftName": "Squat", + "Items": [ + { + "Set": { + "Reps": 3, + "Percentage": 65, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "", + "Amount": 0 + }, + { + "Set": { + "Reps": 3, + "Percentage": 75, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "", + "Amount": 0 + }, + { + "Set": { + "Reps": 3, + "Percentage": 85, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "", + "Amount": 0 + }, + { + "Set": { + "Reps": 3, + "Percentage": 90, + "PlusWeight": 0, + "Amount": 3, + "Notice": "" + }, + "ReferenceName": "", + "Amount": 0 + }, + { + "Set": { + "Reps": 3, + "Percentage": 95, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "", + "Amount": 0 + } + ], + "Increase": false, + "IncreaseAmount": 0, + "IncreasePercent": false + }, + "Raw": "" + } + ] + }, + { + "Items": [ + { + "LiftSchedule": { + "LiftName": "Squat", + "Items": [ + { + "Set": { + "Reps": 3, + "Percentage": 65, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "", + "Amount": 0 + }, + { + "Set": { + "Reps": 3, + "Percentage": 75, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "", + "Amount": 0 + }, + { + "Set": { + "Reps": 4, + "Percentage": 85, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "", + "Amount": 0 + }, + { + "Set": { + "Reps": 5, + "Percentage": 90, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "", + "Amount": 0 + } + ], + "Increase": false, + "IncreaseAmount": 0, + "IncreasePercent": false + }, + "Raw": "" + } + ] + }, + { + "Items": [ + { + "LiftSchedule": { + "LiftName": "Squat", + "Items": [ + { + "Set": { + "Reps": 3, + "Percentage": 60, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "", + "Amount": 0 + }, + { + "Set": { + "Reps": 3, + "Percentage": 70, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "", + "Amount": 0 + }, + { + "Set": { + "Reps": 3, + "Percentage": 80, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "", + "Amount": 0 + }, + { + "Set": { + "Reps": 5, + "Percentage": 90, + "PlusWeight": 0, + "Amount": 5, + "Notice": "" + }, + "ReferenceName": "", + "Amount": 0 + } + ], + "Increase": false, + "IncreaseAmount": 0, + "IncreasePercent": false + }, + "Raw": "" + } + ] + }, + { + "Items": [ + { + "LiftSchedule": { + "LiftName": "Squat", + "Items": [ + { + "Set": { + "Reps": 3, + "Percentage": 60, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "", + "Amount": 0 + }, + { + "Set": { + "Reps": 3, + "Percentage": 70, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "", + "Amount": 0 + }, + { + "Set": { + "Reps": 3, + "Percentage": 80, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "", + "Amount": 0 + }, + { + "Set": { + "Reps": 3, + "Percentage": 95, + "PlusWeight": 0, + "Amount": 2, + "Notice": "" + }, + "ReferenceName": "", + "Amount": 0 + } + ], + "Increase": false, + "IncreaseAmount": 0, + "IncreasePercent": false + }, + "Raw": "" + } + ] + }, + { + "Items": [ + { + "LiftSchedule": { + "LiftName": "Squat", + "Items": [ + { + "Set": { + "Reps": 3, + "Percentage": 65, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "", + "Amount": 0 + }, + { + "Set": { + "Reps": 3, + "Percentage": 75, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "", + "Amount": 0 + }, + { + "Set": { + "Reps": 3, + "Percentage": 85, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "", + "Amount": 0 + }, + { + "Set": { + "Reps": 3, + "Percentage": 95, + "PlusWeight": 0, + "Amount": 4, + "Notice": "" + }, + "ReferenceName": "", + "Amount": 0 + } + ], + "Increase": false, + "IncreaseAmount": 0, + "IncreasePercent": false + }, + "Raw": "" + } + ] + }, + { + "Items": [ + { + "LiftSchedule": { + "LiftName": "Squat", + "Items": [ + { + "Set": { + "Reps": 3, + "Percentage": 70, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "", + "Amount": 0 + }, + { + "Set": { + "Reps": 4, + "Percentage": 80, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "", + "Amount": 0 + }, + { + "Set": { + "Reps": 5, + "Percentage": 90, + "PlusWeight": 0, + "Amount": 5, + "Notice": "" + }, + "ReferenceName": "", + "Amount": 0 + } + ], + "Increase": false, + "IncreaseAmount": 0, + "IncreasePercent": false + }, + "Raw": "" + } + ] + }, + { + "Items": [ + { + "LiftSchedule": { + "LiftName": "Squat", + "Items": [ + { + "Set": { + "Reps": 3, + "Percentage": 70, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "", + "Amount": 0 + }, + { + "Set": { + "Reps": 3, + "Percentage": 80, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "", + "Amount": 0 + }, + { + "Set": { + "Reps": 3, + "Percentage": 95, + "PlusWeight": 0, + "Amount": 4, + "Notice": "" + }, + "ReferenceName": "", + "Amount": 0 + } + ], + "Increase": false, + "IncreaseAmount": 0, + "IncreasePercent": false + }, + "Raw": "" + } + ] + }, + { + "Items": [ + { + "LiftSchedule": { + "LiftName": "Squat", + "Items": [ + { + "Set": { + "Reps": 3, + "Percentage": 75, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "", + "Amount": 0 + }, + { + "Set": { + "Reps": 4, + "Percentage": 90, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "", + "Amount": 0 + }, + { + "Set": { + "Reps": 4, + "Percentage": 80, + "PlusWeight": 0, + "Amount": 3, + "Notice": "" + }, + "ReferenceName": "", + "Amount": 0 + } + ], + "Increase": false, + "IncreaseAmount": 0, + "IncreasePercent": false + }, + "Raw": "" + } + ] + }, + { + "Items": [ + { + "LiftSchedule": { + "LiftName": "Squat", + "Items": [ + { + "Set": { + "Reps": 3, + "Percentage": 70, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "", + "Amount": 0 + }, + { + "Set": { + "Reps": 3, + "Percentage": 80, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "", + "Amount": 0 + }, + { + "Set": { + "Reps": 5, + "Percentage": 90, + "PlusWeight": 0, + "Amount": 2, + "Notice": "" + }, + "ReferenceName": "", + "Amount": 0 + }, + { + "Set": { + "Reps": 4, + "Percentage": 95, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "", + "Amount": 0 + } + ], + "Increase": false, + "IncreaseAmount": 0, + "IncreasePercent": false + }, + "Raw": "" + } + ] + }, + { + "Items": [ + { + "LiftSchedule": { + "LiftName": "Squat", + "Items": [ + { + "Set": { + "Reps": 4, + "Percentage": 75, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "", + "Amount": 0 + }, + { + "Set": { + "Reps": 4, + "Percentage": 85, + "PlusWeight": 0, + "Amount": 4, + "Notice": "" + }, + "ReferenceName": "", + "Amount": 0 + } + ], + "Increase": false, + "IncreaseAmount": 0, + "IncreasePercent": false + }, + "Raw": "" + } + ] + }, + { + "Items": [ + { + "LiftSchedule": { + "LiftName": "", + "Items": null, + "Increase": false, + "IncreaseAmount": 0, + "IncreasePercent": false + }, + "Raw": "Build to 1RM" + } + ] + } + ] +} diff --git a/test/StartingStrength.tdl.lexer b/test/StartingStrength.tdl.lexer new file mode 100644 index 0000000..c6187ac --- /dev/null +++ b/test/StartingStrength.tdl.lexer @@ -0,0 +1,123 @@ +line 3: (preamble - 'Lifts:') +line 4: (identifier - 'Squat') +line 4: (preamble - 'Max:') +line 4: (float - '60.5') +line 4: (preamble - 'Increment:') +line 4: (integer - '5') +line 4: (, - ',') +line 5: (identifier - 'Deadlift') +line 5: (preamble - 'Max:') +line 5: (float - '66.0') +line 5: (preamble - 'Increment:') +line 5: (integer - '5') +line 5: (, - ',') +line 6: (identifier - 'Bench') +line 6: (preamble - 'Max:') +line 6: (integer - '42') +line 6: (preamble - 'Increment:') +line 6: (float - '2.5') +line 6: (, - ',') +line 7: (identifier - 'Press') +line 7: (preamble - 'Max:') +line 7: (integer - '20') +line 7: (preamble - 'Increment:') +line 7: (float - '2.5') +line 7: (, - ',') +line 8: (identifier - 'PowerClean') +line 8: (preamble - 'Max:') +line 8: (integer - '20') +line 8: (preamble - 'Increment:') +line 8: (float - '2.5') +line 11: (preamble - 'SetTemplates:') +line 12: (- - '-') +line 12: (preamble - 'empty:') +line 13: (integer - '5') +line 13: (reps - 'reps') +line 13: (@ - '@') +line 13: (integer - '0') +line 13: (% - '%') +line 14: (- - '-') +line 14: (preamble - 'warmups:') +line 15: (integer - '5') +line 15: (reps - 'reps') +line 15: (@ - '@') +line 15: (integer - '25') +line 15: (% - '%') +line 15: (, - ',') +line 16: (integer - '3') +line 16: (reps - 'reps') +line 16: (@ - '@') +line 16: (integer - '50') +line 16: (% - '%') +line 16: (, - ',') +line 17: (integer - '2') +line 17: (reps - 'reps') +line 17: (@ - '@') +line 17: (integer - '75') +line 17: (% - '%') +line 18: (- - '-') +line 18: (preamble - 'workset:') +line 19: (integer - '5') +line 19: (reps - 'reps') +line 19: (@ - '@') +line 19: (integer - '100') +line 19: (% - '%') +line 20: (- - '-') +line 20: (preamble - 'worksetsClean:') +line 21: (integer - '3') +line 21: (reps - 'reps') +line 21: (@ - '@') +line 21: (integer - '100') +line 21: (% - '%') +line 21: (x - 'x') +line 21: (integer - '5') +line 23: (- - '-') +line 23: (preamble - 'regularSets:') +line 24: (identifier - 'empty') +line 24: (, - ',') +line 24: (identifier - 'empty') +line 24: (, - ',') +line 24: (identifier - 'warmups') +line 24: (, - ',') +line 24: (identifier - 'workset') +line 24: (x - 'x') +line 24: (integer - '3') +line 26: (- - '-') +line 26: (preamble - 'deadliftSets:') +line 27: (identifier - 'empty') +line 27: (, - ',') +line 27: (identifier - 'empty') +line 27: (, - ',') +line 27: (identifier - 'warmups') +line 27: (, - ',') +line 27: (identifier - 'workset') +line 29: (- - '-') +line 29: (preamble - 'cleanSets:') +line 30: (identifier - 'empty') +line 30: (, - ',') +line 30: (identifier - 'empty') +line 30: (, - ',') +line 30: (identifier - 'warmups') +line 30: (, - ',') +line 30: (identifier - 'worksetsClean') +line 33: (preamble - 'TrainingDays:') +line 34: (- - '-') +line 34: (preamble - 'Squat:') +line 34: (identifier - 'regularSets') +line 35: (preamble - 'Press:') +line 35: (identifier - 'regularSets') +line 35: (increase - 'increase') +line 36: (preamble - 'Deadlift:') +line 36: (identifier - 'deadliftSets') +line 36: (increase - 'increase') +line 38: (- - '-') +line 38: (preamble - 'Squat:') +line 38: (identifier - 'regularSets') +line 38: (increase - 'increase') +line 39: (preamble - 'Bench:') +line 39: (identifier - 'regularSets') +line 39: (increase - 'increase') +line 40: (preamble - 'PowerClean:') +line 40: (identifier - 'cleanSets') +line 40: (increase - 'increase') +line 41: (string - '"3 sets of 5 weighted chin-ups"') diff --git a/test/StartingStrength.tdl.parser b/test/StartingStrength.tdl.parser new file mode 100644 index 0000000..39bc2ed --- /dev/null +++ b/test/StartingStrength.tdl.parser @@ -0,0 +1,427 @@ +{ + "Lifts": [ + { + "Name": "Squat", + "Max": 60.5, + "Increment": 5, + "IncrementPercent": false, + "Bar": 0 + }, + { + "Name": "Deadlift", + "Max": 66, + "Increment": 5, + "IncrementPercent": false, + "Bar": 0 + }, + { + "Name": "Bench", + "Max": 42, + "Increment": 2.5, + "IncrementPercent": false, + "Bar": 0 + }, + { + "Name": "Press", + "Max": 20, + "Increment": 2.5, + "IncrementPercent": false, + "Bar": 0 + }, + { + "Name": "PowerClean", + "Max": 20, + "Increment": 2.5, + "IncrementPercent": false, + "Bar": 0 + } + ], + "Plates": null, + "SetTemplates": [ + { + "Name": "empty", + "Items": [ + { + "Set": { + "Reps": 5, + "Percentage": 0, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "", + "Amount": 0 + } + ] + }, + { + "Name": "warmups", + "Items": [ + { + "Set": { + "Reps": 5, + "Percentage": 25, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "", + "Amount": 0 + }, + { + "Set": { + "Reps": 3, + "Percentage": 50, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "", + "Amount": 0 + }, + { + "Set": { + "Reps": 2, + "Percentage": 75, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "", + "Amount": 0 + } + ] + }, + { + "Name": "workset", + "Items": [ + { + "Set": { + "Reps": 5, + "Percentage": 100, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "", + "Amount": 0 + } + ] + }, + { + "Name": "worksetsClean", + "Items": [ + { + "Set": { + "Reps": 3, + "Percentage": 100, + "PlusWeight": 0, + "Amount": 5, + "Notice": "" + }, + "ReferenceName": "", + "Amount": 0 + } + ] + }, + { + "Name": "regularSets", + "Items": [ + { + "Set": { + "Reps": 0, + "Percentage": 0, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "empty", + "Amount": 0 + }, + { + "Set": { + "Reps": 0, + "Percentage": 0, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "empty", + "Amount": 0 + }, + { + "Set": { + "Reps": 0, + "Percentage": 0, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "warmups", + "Amount": 0 + }, + { + "Set": { + "Reps": 0, + "Percentage": 0, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "workset", + "Amount": 3 + } + ] + }, + { + "Name": "deadliftSets", + "Items": [ + { + "Set": { + "Reps": 0, + "Percentage": 0, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "empty", + "Amount": 0 + }, + { + "Set": { + "Reps": 0, + "Percentage": 0, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "empty", + "Amount": 0 + }, + { + "Set": { + "Reps": 0, + "Percentage": 0, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "warmups", + "Amount": 0 + }, + { + "Set": { + "Reps": 0, + "Percentage": 0, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "workset", + "Amount": 0 + } + ] + }, + { + "Name": "cleanSets", + "Items": [ + { + "Set": { + "Reps": 0, + "Percentage": 0, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "empty", + "Amount": 0 + }, + { + "Set": { + "Reps": 0, + "Percentage": 0, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "empty", + "Amount": 0 + }, + { + "Set": { + "Reps": 0, + "Percentage": 0, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "warmups", + "Amount": 0 + }, + { + "Set": { + "Reps": 0, + "Percentage": 0, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "worksetsClean", + "Amount": 0 + } + ] + } + ], + "TrainingDays": [ + { + "Items": [ + { + "LiftSchedule": { + "LiftName": "Squat", + "Items": [ + { + "Set": { + "Reps": 0, + "Percentage": 0, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "regularSets", + "Amount": 0 + } + ], + "Increase": false, + "IncreaseAmount": 0, + "IncreasePercent": false + }, + "Raw": "" + }, + { + "LiftSchedule": { + "LiftName": "Press", + "Items": [ + { + "Set": { + "Reps": 0, + "Percentage": 0, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "regularSets", + "Amount": 0 + } + ], + "Increase": true, + "IncreaseAmount": 0, + "IncreasePercent": false + }, + "Raw": "" + }, + { + "LiftSchedule": { + "LiftName": "Deadlift", + "Items": [ + { + "Set": { + "Reps": 0, + "Percentage": 0, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "deadliftSets", + "Amount": 0 + } + ], + "Increase": true, + "IncreaseAmount": 0, + "IncreasePercent": false + }, + "Raw": "" + } + ] + }, + { + "Items": [ + { + "LiftSchedule": { + "LiftName": "Squat", + "Items": [ + { + "Set": { + "Reps": 0, + "Percentage": 0, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "regularSets", + "Amount": 0 + } + ], + "Increase": true, + "IncreaseAmount": 0, + "IncreasePercent": false + }, + "Raw": "" + }, + { + "LiftSchedule": { + "LiftName": "Bench", + "Items": [ + { + "Set": { + "Reps": 0, + "Percentage": 0, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "regularSets", + "Amount": 0 + } + ], + "Increase": true, + "IncreaseAmount": 0, + "IncreasePercent": false + }, + "Raw": "" + }, + { + "LiftSchedule": { + "LiftName": "PowerClean", + "Items": [ + { + "Set": { + "Reps": 0, + "Percentage": 0, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "cleanSets", + "Amount": 0 + } + ], + "Increase": true, + "IncreaseAmount": 0, + "IncreasePercent": false + }, + "Raw": "" + }, + { + "LiftSchedule": { + "LiftName": "", + "Items": null, + "Increase": false, + "IncreaseAmount": 0, + "IncreasePercent": false + }, + "Raw": "3 sets of 5 weighted chin-ups" + } + ] + } + ] +} diff --git a/test/Texas_Method.tdl.lexer b/test/Texas_Method.tdl.lexer new file mode 100644 index 0000000..d92acd0 --- /dev/null +++ b/test/Texas_Method.tdl.lexer @@ -0,0 +1,254 @@ +line 3: (preamble - 'Lifts:') +line 4: (identifier - 'Squat') +line 4: (preamble - 'Max:') +line 4: (integer - '180') +line 4: (preamble - 'Increment:') +line 4: (float - '2.5') +line 4: (, - ',') +line 5: (identifier - 'Deadlift') +line 5: (preamble - 'Max:') +line 5: (integer - '210') +line 5: (preamble - 'Increment:') +line 5: (float - '2.5') +line 5: (, - ',') +line 6: (identifier - 'Bench') +line 6: (preamble - 'Max:') +line 6: (integer - '120') +line 6: (preamble - 'Increment:') +line 6: (float - '1.25') +line 6: (, - ',') +line 7: (identifier - 'Press') +line 7: (preamble - 'Max:') +line 7: (integer - '80') +line 7: (preamble - 'Increment:') +line 7: (float - '1.25') +line 7: (, - ',') +line 8: (identifier - 'PowerClean') +line 8: (preamble - 'Max:') +line 8: (integer - '80') +line 8: (preamble - 'Increment:') +line 8: (float - '1.25') +line 10: (preamble - 'SetTemplates:') +line 11: (- - '-') +line 11: (preamble - 'empty:') +line 12: (integer - '5') +line 12: (reps - 'reps') +line 12: (@ - '@') +line 12: (integer - '0') +line 12: (% - '%') +line 13: (- - '-') +line 13: (preamble - 'warmups:') +line 14: (integer - '3') +line 14: (reps - 'reps') +line 14: (@ - '@') +line 14: (integer - '25') +line 14: (% - '%') +line 14: (, - ',') +line 15: (integer - '2') +line 15: (reps - 'reps') +line 15: (@ - '@') +line 15: (integer - '50') +line 15: (% - '%') +line 15: (, - ',') +line 16: (integer - '2') +line 16: (reps - 'reps') +line 16: (@ - '@') +line 16: (integer - '75') +line 16: (% - '%') +line 17: (- - '-') +line 17: (preamble - 'worksetMonday:') +line 18: (integer - '5') +line 18: (reps - 'reps') +line 18: (@ - '@') +line 18: (integer - '90') +line 18: (% - '%') +line 19: (- - '-') +line 19: (preamble - 'worksetFriday:') +line 20: (integer - '5') +line 20: (reps - 'reps') +line 20: (@ - '@') +line 20: (integer - '100') +line 20: (% - '%') +line 22: (preamble - 'TrainingDays:') +line 24: (- - '-') +line 24: (preamble - 'Squat:') +line 24: (identifier - 'empty') +line 24: (, - ',') +line 24: (identifier - 'empty') +line 24: (, - ',') +line 24: (identifier - 'warmups') +line 24: (, - ',') +line 24: (identifier - 'worksetMonday') +line 24: (x - 'x') +line 24: (integer - '5') +line 25: (preamble - 'Bench:') +line 25: (identifier - 'empty') +line 25: (, - ',') +line 25: (identifier - 'warmups') +line 25: (, - ',') +line 25: (identifier - 'worksetMonday') +line 25: (x - 'x') +line 25: (integer - '5') +line 26: (preamble - 'Deadlift:') +line 26: (identifier - 'empty') +line 26: (, - ',') +line 26: (identifier - 'warmups') +line 26: (, - ',') +line 26: (identifier - 'worksetMonday') +line 28: (- - '-') +line 28: (preamble - 'Squat:') +line 28: (identifier - 'empty') +line 28: (, - ',') +line 28: (identifier - 'empty') +line 28: (, - ',') +line 28: (identifier - 'warmups') +line 28: (, - ',') +line 28: (integer - '5') +line 28: (reps - 'reps') +line 28: (@ - '@') +line 28: (integer - '72') +line 28: (% - '%') +line 28: (x - 'x') +line 28: (integer - '2') +line 28: (increase - 'increase') +line 29: (preamble - 'Press:') +line 29: (identifier - 'empty') +line 29: (, - ',') +line 29: (identifier - 'warmups') +line 29: (, - ',') +line 29: (integer - '5') +line 29: (reps - 'reps') +line 29: (@ - '@') +line 29: (integer - '81') +line 29: (% - '%') +line 29: (x - 'x') +line 29: (integer - '3') +line 29: (increase - 'increase') +line 30: (string - '"3 sets of bodyweight Chin-ups"') +line 31: (string - '"5 sets of 10 Back Extensions or Glute-Ham Raises"') +line 33: (- - '-') +line 33: (preamble - 'Squat:') +line 33: (identifier - 'empty') +line 33: (, - ',') +line 33: (identifier - 'empty') +line 33: (, - ',') +line 33: (identifier - 'warmups') +line 33: (, - ',') +line 33: (integer - '5') +line 33: (reps - 'reps') +line 33: (@ - '@') +line 33: (integer - '100') +line 33: (% - '%') +line 34: (preamble - 'Bench:') +line 34: (identifier - 'empty') +line 34: (, - ',') +line 34: (identifier - 'warmups') +line 34: (, - ',') +line 34: (integer - '5') +line 34: (reps - 'reps') +line 34: (@ - '@') +line 34: (integer - '100') +line 34: (% - '%') +line 35: (preamble - 'PowerClean:') +line 35: (identifier - 'empty') +line 35: (, - ',') +line 35: (identifier - 'warmups') +line 35: (, - ',') +line 35: (integer - '3') +line 35: (reps - 'reps') +line 35: (@ - '@') +line 35: (integer - '90') +line 35: (% - '%') +line 35: (x - 'x') +line 35: (integer - '5') +line 38: (- - '-') +line 38: (preamble - 'Squat:') +line 38: (identifier - 'empty') +line 38: (, - ',') +line 38: (identifier - 'empty') +line 38: (, - ',') +line 38: (identifier - 'warmups') +line 38: (, - ',') +line 38: (identifier - 'worksetMonday') +line 38: (x - 'x') +line 38: (integer - '5') +line 39: (preamble - 'Press:') +line 39: (identifier - 'empty') +line 39: (, - ',') +line 39: (identifier - 'warmups') +line 39: (, - ',') +line 39: (identifier - 'worksetMonday') +line 39: (x - 'x') +line 39: (integer - '5') +line 40: (preamble - 'Deadlift:') +line 40: (identifier - 'empty') +line 40: (, - ',') +line 40: (identifier - 'warmups') +line 40: (, - ',') +line 40: (identifier - 'worksetMonday') +line 42: (- - '-') +line 42: (preamble - 'Squat:') +line 42: (identifier - 'empty') +line 42: (, - ',') +line 42: (identifier - 'empty') +line 42: (, - ',') +line 42: (identifier - 'warmups') +line 42: (, - ',') +line 42: (integer - '5') +line 42: (reps - 'reps') +line 42: (@ - '@') +line 42: (integer - '72') +line 42: (% - '%') +line 42: (x - 'x') +line 42: (integer - '2') +line 42: (increase - 'increase') +line 43: (preamble - 'Bench:') +line 43: (identifier - 'empty') +line 43: (, - ',') +line 43: (identifier - 'warmups') +line 43: (, - ',') +line 43: (integer - '5') +line 43: (reps - 'reps') +line 43: (@ - '@') +line 43: (integer - '81') +line 43: (% - '%') +line 43: (x - 'x') +line 43: (integer - '3') +line 43: (increase - 'increase') +line 44: (string - '"3 sets of bodyweight Chin-ups"') +line 45: (string - '"5 sets of 10 Back Extensions or Glute-Ham Raises"') +line 47: (- - '-') +line 47: (preamble - 'Squat:') +line 47: (identifier - 'empty') +line 47: (, - ',') +line 47: (identifier - 'empty') +line 47: (, - ',') +line 47: (identifier - 'warmups') +line 47: (, - ',') +line 47: (integer - '5') +line 47: (reps - 'reps') +line 47: (@ - '@') +line 47: (integer - '100') +line 47: (% - '%') +line 48: (preamble - 'Press:') +line 48: (identifier - 'empty') +line 48: (, - ',') +line 48: (identifier - 'warmups') +line 48: (, - ',') +line 48: (integer - '5') +line 48: (reps - 'reps') +line 48: (@ - '@') +line 48: (integer - '100') +line 48: (% - '%') +line 49: (preamble - 'PowerClean:') +line 49: (identifier - 'empty') +line 49: (, - ',') +line 49: (identifier - 'warmups') +line 49: (, - ',') +line 49: (integer - '3') +line 49: (reps - 'reps') +line 49: (@ - '@') +line 49: (integer - '90') +line 49: (% - '%') +line 49: (x - 'x') +line 49: (integer - '5') diff --git a/test/Texas_Method.tdl.parser b/test/Texas_Method.tdl.parser new file mode 100644 index 0000000..6e8a69e --- /dev/null +++ b/test/Texas_Method.tdl.parser @@ -0,0 +1,964 @@ +{ + "Lifts": [ + { + "Name": "Squat", + "Max": 180, + "Increment": 2.5, + "IncrementPercent": false, + "Bar": 0 + }, + { + "Name": "Deadlift", + "Max": 210, + "Increment": 2.5, + "IncrementPercent": false, + "Bar": 0 + }, + { + "Name": "Bench", + "Max": 120, + "Increment": 1.25, + "IncrementPercent": false, + "Bar": 0 + }, + { + "Name": "Press", + "Max": 80, + "Increment": 1.25, + "IncrementPercent": false, + "Bar": 0 + }, + { + "Name": "PowerClean", + "Max": 80, + "Increment": 1.25, + "IncrementPercent": false, + "Bar": 0 + } + ], + "Plates": null, + "SetTemplates": [ + { + "Name": "empty", + "Items": [ + { + "Set": { + "Reps": 5, + "Percentage": 0, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "", + "Amount": 0 + } + ] + }, + { + "Name": "warmups", + "Items": [ + { + "Set": { + "Reps": 3, + "Percentage": 25, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "", + "Amount": 0 + }, + { + "Set": { + "Reps": 2, + "Percentage": 50, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "", + "Amount": 0 + }, + { + "Set": { + "Reps": 2, + "Percentage": 75, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "", + "Amount": 0 + } + ] + }, + { + "Name": "worksetMonday", + "Items": [ + { + "Set": { + "Reps": 5, + "Percentage": 90, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "", + "Amount": 0 + } + ] + }, + { + "Name": "worksetFriday", + "Items": [ + { + "Set": { + "Reps": 5, + "Percentage": 100, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "", + "Amount": 0 + } + ] + } + ], + "TrainingDays": [ + { + "Items": [ + { + "LiftSchedule": { + "LiftName": "Squat", + "Items": [ + { + "Set": { + "Reps": 0, + "Percentage": 0, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "empty", + "Amount": 0 + }, + { + "Set": { + "Reps": 0, + "Percentage": 0, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "empty", + "Amount": 0 + }, + { + "Set": { + "Reps": 0, + "Percentage": 0, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "warmups", + "Amount": 0 + }, + { + "Set": { + "Reps": 0, + "Percentage": 0, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "worksetMonday", + "Amount": 5 + } + ], + "Increase": false, + "IncreaseAmount": 0, + "IncreasePercent": false + }, + "Raw": "" + }, + { + "LiftSchedule": { + "LiftName": "Bench", + "Items": [ + { + "Set": { + "Reps": 0, + "Percentage": 0, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "empty", + "Amount": 0 + }, + { + "Set": { + "Reps": 0, + "Percentage": 0, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "warmups", + "Amount": 0 + }, + { + "Set": { + "Reps": 0, + "Percentage": 0, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "worksetMonday", + "Amount": 5 + } + ], + "Increase": false, + "IncreaseAmount": 0, + "IncreasePercent": false + }, + "Raw": "" + }, + { + "LiftSchedule": { + "LiftName": "Deadlift", + "Items": [ + { + "Set": { + "Reps": 0, + "Percentage": 0, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "empty", + "Amount": 0 + }, + { + "Set": { + "Reps": 0, + "Percentage": 0, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "warmups", + "Amount": 0 + }, + { + "Set": { + "Reps": 0, + "Percentage": 0, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "worksetMonday", + "Amount": 0 + } + ], + "Increase": false, + "IncreaseAmount": 0, + "IncreasePercent": false + }, + "Raw": "" + } + ] + }, + { + "Items": [ + { + "LiftSchedule": { + "LiftName": "Squat", + "Items": [ + { + "Set": { + "Reps": 0, + "Percentage": 0, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "empty", + "Amount": 0 + }, + { + "Set": { + "Reps": 0, + "Percentage": 0, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "empty", + "Amount": 0 + }, + { + "Set": { + "Reps": 0, + "Percentage": 0, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "warmups", + "Amount": 0 + }, + { + "Set": { + "Reps": 5, + "Percentage": 72, + "PlusWeight": 0, + "Amount": 2, + "Notice": "" + }, + "ReferenceName": "", + "Amount": 0 + } + ], + "Increase": true, + "IncreaseAmount": 0, + "IncreasePercent": false + }, + "Raw": "" + }, + { + "LiftSchedule": { + "LiftName": "Press", + "Items": [ + { + "Set": { + "Reps": 0, + "Percentage": 0, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "empty", + "Amount": 0 + }, + { + "Set": { + "Reps": 0, + "Percentage": 0, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "warmups", + "Amount": 0 + }, + { + "Set": { + "Reps": 5, + "Percentage": 81, + "PlusWeight": 0, + "Amount": 3, + "Notice": "" + }, + "ReferenceName": "", + "Amount": 0 + } + ], + "Increase": true, + "IncreaseAmount": 0, + "IncreasePercent": false + }, + "Raw": "" + }, + { + "LiftSchedule": { + "LiftName": "", + "Items": null, + "Increase": false, + "IncreaseAmount": 0, + "IncreasePercent": false + }, + "Raw": "3 sets of bodyweight Chin-ups" + }, + { + "LiftSchedule": { + "LiftName": "", + "Items": null, + "Increase": false, + "IncreaseAmount": 0, + "IncreasePercent": false + }, + "Raw": "5 sets of 10 Back Extensions or Glute-Ham Raises" + } + ] + }, + { + "Items": [ + { + "LiftSchedule": { + "LiftName": "Squat", + "Items": [ + { + "Set": { + "Reps": 0, + "Percentage": 0, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "empty", + "Amount": 0 + }, + { + "Set": { + "Reps": 0, + "Percentage": 0, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "empty", + "Amount": 0 + }, + { + "Set": { + "Reps": 0, + "Percentage": 0, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "warmups", + "Amount": 0 + }, + { + "Set": { + "Reps": 5, + "Percentage": 100, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "", + "Amount": 0 + } + ], + "Increase": false, + "IncreaseAmount": 0, + "IncreasePercent": false + }, + "Raw": "" + }, + { + "LiftSchedule": { + "LiftName": "Bench", + "Items": [ + { + "Set": { + "Reps": 0, + "Percentage": 0, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "empty", + "Amount": 0 + }, + { + "Set": { + "Reps": 0, + "Percentage": 0, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "warmups", + "Amount": 0 + }, + { + "Set": { + "Reps": 5, + "Percentage": 100, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "", + "Amount": 0 + } + ], + "Increase": false, + "IncreaseAmount": 0, + "IncreasePercent": false + }, + "Raw": "" + }, + { + "LiftSchedule": { + "LiftName": "PowerClean", + "Items": [ + { + "Set": { + "Reps": 0, + "Percentage": 0, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "empty", + "Amount": 0 + }, + { + "Set": { + "Reps": 0, + "Percentage": 0, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "warmups", + "Amount": 0 + }, + { + "Set": { + "Reps": 3, + "Percentage": 90, + "PlusWeight": 0, + "Amount": 5, + "Notice": "" + }, + "ReferenceName": "", + "Amount": 0 + } + ], + "Increase": false, + "IncreaseAmount": 0, + "IncreasePercent": false + }, + "Raw": "" + } + ] + }, + { + "Items": [ + { + "LiftSchedule": { + "LiftName": "Squat", + "Items": [ + { + "Set": { + "Reps": 0, + "Percentage": 0, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "empty", + "Amount": 0 + }, + { + "Set": { + "Reps": 0, + "Percentage": 0, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "empty", + "Amount": 0 + }, + { + "Set": { + "Reps": 0, + "Percentage": 0, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "warmups", + "Amount": 0 + }, + { + "Set": { + "Reps": 0, + "Percentage": 0, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "worksetMonday", + "Amount": 5 + } + ], + "Increase": false, + "IncreaseAmount": 0, + "IncreasePercent": false + }, + "Raw": "" + }, + { + "LiftSchedule": { + "LiftName": "Press", + "Items": [ + { + "Set": { + "Reps": 0, + "Percentage": 0, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "empty", + "Amount": 0 + }, + { + "Set": { + "Reps": 0, + "Percentage": 0, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "warmups", + "Amount": 0 + }, + { + "Set": { + "Reps": 0, + "Percentage": 0, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "worksetMonday", + "Amount": 5 + } + ], + "Increase": false, + "IncreaseAmount": 0, + "IncreasePercent": false + }, + "Raw": "" + }, + { + "LiftSchedule": { + "LiftName": "Deadlift", + "Items": [ + { + "Set": { + "Reps": 0, + "Percentage": 0, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "empty", + "Amount": 0 + }, + { + "Set": { + "Reps": 0, + "Percentage": 0, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "warmups", + "Amount": 0 + }, + { + "Set": { + "Reps": 0, + "Percentage": 0, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "worksetMonday", + "Amount": 0 + } + ], + "Increase": false, + "IncreaseAmount": 0, + "IncreasePercent": false + }, + "Raw": "" + } + ] + }, + { + "Items": [ + { + "LiftSchedule": { + "LiftName": "Squat", + "Items": [ + { + "Set": { + "Reps": 0, + "Percentage": 0, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "empty", + "Amount": 0 + }, + { + "Set": { + "Reps": 0, + "Percentage": 0, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "empty", + "Amount": 0 + }, + { + "Set": { + "Reps": 0, + "Percentage": 0, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "warmups", + "Amount": 0 + }, + { + "Set": { + "Reps": 5, + "Percentage": 72, + "PlusWeight": 0, + "Amount": 2, + "Notice": "" + }, + "ReferenceName": "", + "Amount": 0 + } + ], + "Increase": true, + "IncreaseAmount": 0, + "IncreasePercent": false + }, + "Raw": "" + }, + { + "LiftSchedule": { + "LiftName": "Bench", + "Items": [ + { + "Set": { + "Reps": 0, + "Percentage": 0, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "empty", + "Amount": 0 + }, + { + "Set": { + "Reps": 0, + "Percentage": 0, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "warmups", + "Amount": 0 + }, + { + "Set": { + "Reps": 5, + "Percentage": 81, + "PlusWeight": 0, + "Amount": 3, + "Notice": "" + }, + "ReferenceName": "", + "Amount": 0 + } + ], + "Increase": true, + "IncreaseAmount": 0, + "IncreasePercent": false + }, + "Raw": "" + }, + { + "LiftSchedule": { + "LiftName": "", + "Items": null, + "Increase": false, + "IncreaseAmount": 0, + "IncreasePercent": false + }, + "Raw": "3 sets of bodyweight Chin-ups" + }, + { + "LiftSchedule": { + "LiftName": "", + "Items": null, + "Increase": false, + "IncreaseAmount": 0, + "IncreasePercent": false + }, + "Raw": "5 sets of 10 Back Extensions or Glute-Ham Raises" + } + ] + }, + { + "Items": [ + { + "LiftSchedule": { + "LiftName": "Squat", + "Items": [ + { + "Set": { + "Reps": 0, + "Percentage": 0, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "empty", + "Amount": 0 + }, + { + "Set": { + "Reps": 0, + "Percentage": 0, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "empty", + "Amount": 0 + }, + { + "Set": { + "Reps": 0, + "Percentage": 0, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "warmups", + "Amount": 0 + }, + { + "Set": { + "Reps": 5, + "Percentage": 100, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "", + "Amount": 0 + } + ], + "Increase": false, + "IncreaseAmount": 0, + "IncreasePercent": false + }, + "Raw": "" + }, + { + "LiftSchedule": { + "LiftName": "Press", + "Items": [ + { + "Set": { + "Reps": 0, + "Percentage": 0, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "empty", + "Amount": 0 + }, + { + "Set": { + "Reps": 0, + "Percentage": 0, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "warmups", + "Amount": 0 + }, + { + "Set": { + "Reps": 5, + "Percentage": 100, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "", + "Amount": 0 + } + ], + "Increase": false, + "IncreaseAmount": 0, + "IncreasePercent": false + }, + "Raw": "" + }, + { + "LiftSchedule": { + "LiftName": "PowerClean", + "Items": [ + { + "Set": { + "Reps": 0, + "Percentage": 0, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "empty", + "Amount": 0 + }, + { + "Set": { + "Reps": 0, + "Percentage": 0, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "warmups", + "Amount": 0 + }, + { + "Set": { + "Reps": 3, + "Percentage": 90, + "PlusWeight": 0, + "Amount": 5, + "Notice": "" + }, + "ReferenceName": "", + "Amount": 0 + } + ], + "Increase": false, + "IncreaseAmount": 0, + "IncreasePercent": false + }, + "Raw": "" + } + ] + } + ] +} diff --git a/test/minimalExample.tdl.lexer b/test/minimalExample.tdl.lexer new file mode 100644 index 0000000..6f852a3 --- /dev/null +++ b/test/minimalExample.tdl.lexer @@ -0,0 +1,18 @@ +line 3: (preamble - 'Lifts:') +line 4: (identifier - 'OHP') +line 4: (preamble - 'Max:') +line 4: (integer - '100') +line 4: (preamble - 'Increment:') +line 4: (float - '2.5') +line 6: (preamble - 'Plates:') +line 7: (integer - '20') +line 7: (x - 'x') +line 7: (integer - '2') +line 9: (preamble - 'TrainingDays:') +line 10: (- - '-') +line 10: (preamble - 'OHP:') +line 10: (integer - '5') +line 10: (reps - 'reps') +line 10: (@ - '@') +line 10: (integer - '100') +line 10: (% - '%') diff --git a/test/minimalExample.tdl.parser b/test/minimalExample.tdl.parser new file mode 100644 index 0000000..e116a03 --- /dev/null +++ b/test/minimalExample.tdl.parser @@ -0,0 +1,46 @@ +{ + "Lifts": [ + { + "Name": "OHP", + "Max": 100, + "Increment": 2.5, + "IncrementPercent": false, + "Bar": 0 + } + ], + "Plates": [ + { + "Weight": 20, + "Amount": 2 + } + ], + "SetTemplates": null, + "TrainingDays": [ + { + "Items": [ + { + "LiftSchedule": { + "LiftName": "OHP", + "Items": [ + { + "Set": { + "Reps": 5, + "Percentage": 100, + "PlusWeight": 0, + "Amount": 0, + "Notice": "" + }, + "ReferenceName": "", + "Amount": 0 + } + ], + "Increase": false, + "IncreaseAmount": 0, + "IncreasePercent": false + }, + "Raw": "" + } + ] + } + ] +} diff --git a/types.go b/types.go new file mode 100644 index 0000000..253f7a0 --- /dev/null +++ b/types.go @@ -0,0 +1,80 @@ +package main + +import ( + "encoding/json" +) + +type TDL struct { + Lifts []Lift + Plates []Plate + SetTemplates []SetTemplate + TrainingDays []TrainingDay +} + +func (t TDL) JSON() []byte { + tmp, err := json.MarshalIndent(t, "", " ") + if err != nil { + panic(err) + } + return tmp +} + +func (t TDL) Clone() TDL { + t2 := TDL{} + // an actual deep copy might be a little faster + // - but this one is good enough. + err := json.Unmarshal(t.JSON(), &t2) + if err != nil { + panic(err) + } + return t2 +} + +type Lift struct { + Name string + Max float64 + Increment float64 + IncrementPercent bool + Bar float64 +} + +type Plate struct { + Weight float64 + Amount int +} + +type SetTemplate struct { + Name string + Items []SetTemplateItem +} + +type SetTemplateItem struct { + Set Set + ReferenceName string + Amount int +} + +type Set struct { + Reps int + Percentage float64 + PlusWeight float64 + Amount int + Notice string +} + +type TrainingDay struct { + Items []TrainingDayItem +} + +type TrainingDayItem struct { + LiftSchedule LiftSchedule + Raw string +} + +type LiftSchedule struct { + LiftName string + Items []SetTemplateItem + Increase bool + IncreaseAmount float64 + IncreasePercent bool +}