Add power and cadence as possible targets

master
Cloud user 7 years ago
parent 67fff0b6ae
commit e9414e6b18
  1. 8
      README.md
  2. 24
      src/main/scala/com.github.mgifos.workouts/model/Target.scala
  3. 24
      src/test/scala/com/github/mgifos/workouts/model/TargetSpec.scala

@ -93,7 +93,7 @@ The reserved keywords of the notation are: workout, warmup, cooldown, run, bike,
**`<time-duration>`** := `<minutes>:<seconds>` **`<time-duration>`** := `<minutes>:<seconds>`
**`<target>`** := `<zone-target> | <pace-target> | <hr-target>` **`<target>`** := `<zone-target> | <pace-target> | <hr-target> | <speed-target> | <power-target> | <cadence-target>`
**`<zone-target>`** := `z[1-6]` **`<zone-target>`** := `z[1-6]`
@ -101,6 +101,10 @@ The reserved keywords of the notation are: workout, warmup, cooldown, run, bike,
**`<hr-target>`** := `\d{1,3} - \d{1,3} bpm` **`<hr-target>`** := `\d{1,3} - \d{1,3} bpm`
**`<power-target>`** := `\d{1,3} - \d{1,3} W`
**`<cadence-target>`** := `\d{1,3} - \d{1,3} rpm`
**`<speed-target>`** := `<kph-speed> - <kph-speed> (kph | mph)?` **`<speed-target>`** := `<kph-speed> - <kph-speed> (kph | mph)?`
**`<pace>`** := `<minutes>:<seconds>` **`<pace>`** := `<minutes>:<seconds>`
@ -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) - 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. 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. The parser we use is not able to parse CR values within the quoted values at the moment.

@ -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 { case class SpeedTarget(from: Speed, to: Speed) extends Target {
override def json = override def json =
Json.obj( Json.obj(
@ -75,14 +95,18 @@ case class Speed(unit: DistanceUnits.DistanceUnit, exp: String) {
} }
object Target { object Target {
private val CadenceCustomRx = """^(\d{1,3})\s*-\s*(\d{1,3})\s*rpm$""".r
private val HrZoneRx = """^z(\d)$""".r private val HrZoneRx = """^z(\d)$""".r
private val HrCustomRx = """^(\d{1,3})\s*-\s*(\d{1,3})\s*bpm$""".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 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 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 { 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 HrZoneRx(zone) => HrZoneTarget(zone.toInt)
case HrCustomRx(from, to) => HrCustomTarget(from.toInt, to.toInt) case HrCustomRx(from, to) => HrCustomTarget(from.toInt, to.toInt)
case PowerCustomRx(from, to) => PowerCustomTarget(from.toInt, to.toInt)
case SpeedRangeRx(from, _, to, _, uom) => case SpeedRangeRx(from, _, to, _, uom) =>
val du = Option(uom).fold(msys.distance)(DistanceUnits.withSpeedUOM) val du = Option(uom).fold(msys.distance)(DistanceUnits.withSpeedUOM)
SpeedTarget(Speed(du, from), Speed(du, to)) SpeedTarget(Speed(du, from), Speed(du, to))

@ -43,4 +43,28 @@ class TargetSpec extends FlatSpec with Matchers {
"targetValueTwo" -> 150, "targetValueTwo" -> 150,
"zoneNumber" -> JsNull)) "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))
}
} }

Loading…
Cancel
Save