From e9414e6b18740337ddd7d192148c91b9284bd918 Mon Sep 17 00:00:00 2001 From: Cloud user Date: Wed, 26 Dec 2018 13:48:13 +0000 Subject: [PATCH] Add power and cadence as possible targets --- README.md | 8 +++++-- .../model/Target.scala | 24 +++++++++++++++++++ .../mgifos/workouts/model/TargetSpec.scala | 24 +++++++++++++++++++ 3 files changed, 54 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index fa3d3b4..73c1564 100644 --- a/README.md +++ b/README.md @@ -93,7 +93,7 @@ The reserved keywords of the notation are: workout, warmup, cooldown, run, bike, **``** := `:` -**``** := ` | | ` +**``** := ` | | | | | ` **``** := `z[1-6]` @@ -101,6 +101,10 @@ The reserved keywords of the notation are: workout, warmup, cooldown, run, bike, **``** := `\d{1,3} - \d{1,3} bpm` +**``** := `\d{1,3} - \d{1,3} W` + +**``** := `\d{1,3} - \d{1,3} rpm` + **``** := ` - (kph | mph)?` **``** := `:` @@ -128,4 +132,4 @@ If not specified -m value from configuration will be used ('metric' by default). - It is highly recommended to use Google Spreadsheets or LibreOffice Calc to edit CSV files, as they both force line-feed (LF) instead of carriage-return (CR) character for internal line breaks when defining workouts. -The parser we use is not able to parse CR values within the quoted values at the moment. \ No newline at end of file +The parser we use is not able to parse CR values within the quoted values at the moment. diff --git a/src/main/scala/com.github.mgifos.workouts/model/Target.scala b/src/main/scala/com.github.mgifos.workouts/model/Target.scala index dbd7eae..811df83 100644 --- a/src/main/scala/com.github.mgifos.workouts/model/Target.scala +++ b/src/main/scala/com.github.mgifos.workouts/model/Target.scala @@ -36,6 +36,26 @@ case class PaceTarget(from: Pace, to: Pace) extends Target { ) } +case class PowerCustomTarget(from: Int, to: Int) extends Target { + override def json = + Json.obj( + "targetType" -> Json.obj("workoutTargetTypeId" -> 2, "workoutTargetTypeKey" -> "power.zone"), + "targetValueOne" -> from, + "targetValueTwo" -> to, + "zoneNumber" -> JsNull + ) +} + +case class CadenceCustomTarget(from: Int, to: Int) extends Target { + override def json = + Json.obj( + "targetType" -> Json.obj("workoutTargetTypeId" -> 3, "workoutTargetTypeKey" -> "cadence.zone"), + "targetValueOne" -> from, + "targetValueTwo" -> to, + "zoneNumber" -> JsNull + ) +} + case class SpeedTarget(from: Speed, to: Speed) extends Target { override def json = Json.obj( @@ -75,14 +95,18 @@ case class Speed(unit: DistanceUnits.DistanceUnit, exp: String) { } object Target { + private val CadenceCustomRx = """^(\d{1,3})\s*-\s*(\d{1,3})\s*rpm$""".r private val HrZoneRx = """^z(\d)$""".r private val HrCustomRx = """^(\d{1,3})\s*-\s*(\d{1,3})\s*bpm$""".r private val PaceRangeRx = """^(\d{1,2}:\d{2})\s*-\s*(\d{1,2}:\d{2})\s*(mpk|mpm)?$""".r + private val PowerCustomRx = """^(\d{1,3})\s*-\s*(\d{1,3})\s*W$""".r private val SpeedRangeRx = """^(\d{1,3}(\.\d{1})?)\s*-\s*(\d{1,3}(\.\d{1})?)\s*(kph|mph)?""".r def parse(x: String)(implicit msys: MeasurementSystems.MeasurementSystem): Target = x.trim match { + case CadenceCustomRx(from, to) => CadenceCustomTarget(from.toInt, to.toInt) case HrZoneRx(zone) => HrZoneTarget(zone.toInt) case HrCustomRx(from, to) => HrCustomTarget(from.toInt, to.toInt) + case PowerCustomRx(from, to) => PowerCustomTarget(from.toInt, to.toInt) case SpeedRangeRx(from, _, to, _, uom) => val du = Option(uom).fold(msys.distance)(DistanceUnits.withSpeedUOM) SpeedTarget(Speed(du, from), Speed(du, to)) diff --git a/src/test/scala/com/github/mgifos/workouts/model/TargetSpec.scala b/src/test/scala/com/github/mgifos/workouts/model/TargetSpec.scala index 1593008..81198d4 100644 --- a/src/test/scala/com/github/mgifos/workouts/model/TargetSpec.scala +++ b/src/test/scala/com/github/mgifos/workouts/model/TargetSpec.scala @@ -43,4 +43,28 @@ class TargetSpec extends FlatSpec with Matchers { "targetValueTwo" -> 150, "zoneNumber" -> JsNull)) } + + "Target" should "handle custom POWER specification correctly" in { + val powTarget = Target.parse("230-250 W").asInstanceOf[PowerCustomTarget] + powTarget should be(PowerCustomTarget(230, 250)) + powTarget.json should be(Json.obj( + "targetType" -> Json.obj( + "workoutTargetTypeId" -> 2, + "workoutTargetTypeKey" -> "power.zone"), + "targetValueOne" -> 230, + "targetValueTwo" -> 250, + "zoneNumber" -> JsNull)) + } + + "Target" should "handle custom CADENCE specification correctly" in { + val cadenceTarget = Target.parse("80-90 rpm").asInstanceOf[CadenceCustomTarget] + cadenceTarget should be(CadenceCustomTarget(80, 90)) + cadenceTarget.json should be(Json.obj( + "targetType" -> Json.obj( + "workoutTargetTypeId" -> 3, + "workoutTargetTypeKey" -> "cadence.zone"), + "targetValueOne" -> 80, + "targetValueTwo" -> 90, + "zoneNumber" -> JsNull)) + } }