diff --git a/Sources/FitWorkoutDecoder/FitWorkoutDecoder.swift b/Sources/FitWorkoutDecoder/FitWorkoutDecoder.swift
index 360f058..99df2dc 100644
--- a/Sources/FitWorkoutDecoder/FitWorkoutDecoder.swift
+++ b/Sources/FitWorkoutDecoder/FitWorkoutDecoder.swift
@@ -61,14 +61,14 @@ public final class FitWorkoutDecoder: WorkoutDecoding {
switch stepsDistance {
case 0:
let workoutStep = workoutSteps[repeatStep.range.lowerBound]
- return WorkoutPart.steady(duration: workoutStep.duration, power: workoutStep.power(for: userFtp),
+ return WorkoutPart.steady(duration: TimeInterval(workoutStep.duration), power: workoutStep.power(for: userFtp),
cadence: nil)
case 1:
let firstWorkoutStep = workoutSteps[repeatStep.range.lowerBound]
let secondWorkoutStep = workoutSteps[repeatStep.range.upperBound]
return WorkoutPart.intervals(repeat: repeatStep.repeatCount,
- onDuration: firstWorkoutStep.duration, onPower: firstWorkoutStep.power(for: userFtp),
- offDuration: secondWorkoutStep.duration, offPower: secondWorkoutStep.power(for: userFtp),
+ onDuration: TimeInterval(firstWorkoutStep.duration), onPower: firstWorkoutStep.power(for: userFtp),
+ offDuration: TimeInterval(secondWorkoutStep.duration), offPower: secondWorkoutStep.power(for: userFtp),
cadence: nil)
default:
throw FitDecodeError.notSupportedRange
diff --git a/Sources/WorkoutDecoderBase/WorkoutDecoding.swift b/Sources/WorkoutDecoderBase/WorkoutDecoding.swift
index a0bb4ca..d8a06c3 100644
--- a/Sources/WorkoutDecoderBase/WorkoutDecoding.swift
+++ b/Sources/WorkoutDecoderBase/WorkoutDecoding.swift
@@ -13,10 +13,10 @@ public protocol WorkoutDecoding {
}
public enum WorkoutPart {
- case steady(duration: Int, power: Double, cadence: String?)
- case intervals(repeat: Int, onDuration: Int, onPower: Double, offDuration: Int, offPower: Double, cadence: String?)
- case ramp(duration: Int, powerLow: Double, powerHigh: Double, cadence: String?)
- case freeRide(duration: Int, cadence: String?)
+ case steady(duration: TimeInterval, power: Double, cadence: String?)
+ case intervals(repeat: Int, onDuration: TimeInterval, onPower: Double, offDuration: TimeInterval, offPower: Double, cadence: String?)
+ case ramp(duration: TimeInterval, powerLow: Double, powerHigh: Double, cadence: String?)
+ case freeRide(duration: TimeInterval, cadence: String?)
public func toSegments(startIndex: Int) -> [WorkoutSegment] {
switch self {
@@ -44,7 +44,7 @@ public enum WorkoutPart {
}
public struct WorkoutSegment: Codable, Equatable {
- public let duration: Int
+ public let duration: TimeInterval
public let index: Int
public let intervalIndex: Int?
public let powerStart: Double // negative power means free ride
@@ -63,10 +63,10 @@ public struct WorkoutSegment: Codable, Equatable {
}
public struct WorkoutMessage: Codable, Equatable {
- public let timeOffset: Int
+ public let timeOffset: TimeInterval
public let message: String
- public init(timeOffset: Int, message: String) {
+ public init(timeOffset: TimeInterval, message: String) {
self.timeOffset = timeOffset
self.message = message
}
@@ -75,7 +75,7 @@ public struct WorkoutMessage: Codable, Equatable {
public struct Workout: Codable {
public let name: String
public let segments: [WorkoutSegment]
- public let duration: Int
+ public let duration: TimeInterval
public let messages: [WorkoutMessage]
public init(name: String, parts: [WorkoutPart], messages: [WorkoutMessage]) {
diff --git a/Sources/ZwoWorkoutDecoder/ZwoWorkoutDecoder.swift b/Sources/ZwoWorkoutDecoder/ZwoWorkoutDecoder.swift
index 9640bd1..cde534b 100644
--- a/Sources/ZwoWorkoutDecoder/ZwoWorkoutDecoder.swift
+++ b/Sources/ZwoWorkoutDecoder/ZwoWorkoutDecoder.swift
@@ -23,23 +23,23 @@ public final class ZwoWorkoutDecoder: WorkoutDecoding {
let cadence = attributes["Cadence"]
switch part.name {
case "SteadyState":
- return WorkoutPart.steady(duration: attributes.int("Duration"),
+ return WorkoutPart.steady(duration: attributes.double("Duration"),
power: attributes.double("Power"),
cadence: cadence)
case "IntervalsT":
return WorkoutPart.intervals(repeat: attributes.int("Repeat"),
- onDuration: attributes.int("OnDuration"),
+ onDuration: attributes.double("OnDuration"),
onPower: attributes.double("OnPower"),
- offDuration: attributes.int("OffDuration"),
+ offDuration: attributes.double("OffDuration"),
offPower: attributes.double("OffPower"),
cadence: cadence)
case "Warmup", "Cooldown", "Ramp":
- return WorkoutPart.ramp(duration: attributes.int("Duration"),
+ return WorkoutPart.ramp(duration: attributes.double("Duration"),
powerLow: attributes.double("PowerLow"),
powerHigh: attributes.double("PowerHigh"),
cadence: cadence)
case "FreeRide":
- return WorkoutPart.freeRide(duration: attributes.int("Duration"),
+ return WorkoutPart.freeRide(duration: attributes.double("Duration"),
cadence: cadence)
default:
throw WorkoutDecodeError.unknownElement(name: part.name)
@@ -47,15 +47,15 @@ public final class ZwoWorkoutDecoder: WorkoutDecoding {
} ?? []
// each part duration and messages with time offset per WorkoutPart
- let messages = try workout["workout"].element?.childElements.map { part -> (Int, [WorkoutMessage]) in
+ let messages = try workout["workout"].element?.childElements.map { part -> (TimeInterval, [WorkoutMessage]) in
let attributes = part.attributes
- let duration: Int
+ let duration: TimeInterval
switch part.name {
case "SteadyState", "Warmup", "Cooldown", "Ramp", "FreeRide":
- duration = attributes.int("Duration")
+ duration = attributes.double("Duration")
case "IntervalsT":
- duration = (attributes.int("OnDuration") + attributes.int("OffDuration")) * attributes.int("Repeat")
+ duration = (attributes.double("OnDuration") + attributes.double("OffDuration")) * Double(attributes.int("Repeat"))
default:
throw WorkoutDecodeError.unknownElement(name: part.name)
}
@@ -64,7 +64,7 @@ public final class ZwoWorkoutDecoder: WorkoutDecoding {
$0.name == "textevent"
}.map { message -> WorkoutMessage in
let attributes = message.attributes
- return WorkoutMessage(timeOffset: attributes.int("timeoffset"), message: attributes["message"] ?? "")
+ return WorkoutMessage(timeOffset: attributes.double("timeoffset"), message: attributes["message"] ?? "")
}
return (duration, messages)
diff --git a/Tests/WorkoutDecodersTests/Resources/workout1.zwo b/Tests/WorkoutDecodersTests/Resources/workout1.zwo
index 5e34235..e05de4f 100644
--- a/Tests/WorkoutDecodersTests/Resources/workout1.zwo
+++ b/Tests/WorkoutDecodersTests/Resources/workout1.zwo
@@ -8,7 +8,7 @@
-
+
diff --git a/Tests/WorkoutDecodersTests/WorkoutDecodersTests.swift b/Tests/WorkoutDecodersTests/WorkoutDecodersTests.swift
index 1fe6406..e8245e8 100644
--- a/Tests/WorkoutDecodersTests/WorkoutDecodersTests.swift
+++ b/Tests/WorkoutDecodersTests/WorkoutDecodersTests.swift
@@ -18,7 +18,7 @@ final class WorkoutDecodersTests: XCTestCase {
XCTAssertEqual(workout.segments, [
WorkoutSegment(duration: 10, index: 0, intervalIndex: nil, powerStart: 0.5, powerEnd: 0.55, cadence: nil),
- WorkoutSegment(duration: 5, index: 1, intervalIndex: nil, powerStart: 0.4, powerEnd: nil, cadence: "100"),
+ WorkoutSegment(duration: 5.00002, index: 1, intervalIndex: nil, powerStart: 0.4, powerEnd: nil, cadence: "100"),
WorkoutSegment(duration: 100, index: 2, intervalIndex: nil, powerStart: -1, powerEnd: nil, cadence: "90"), // free ride
WorkoutSegment(duration: 10, index: 3, intervalIndex: nil, powerStart: 0.5, powerEnd: nil, cadence: nil),
// interval start, repeat 3
@@ -37,11 +37,11 @@ final class WorkoutDecodersTests: XCTestCase {
let workout = decodedWorkout()
XCTAssertEqual(workout.messages, [
- WorkoutMessage(timeOffset: 0, message: "Starting message"),
- WorkoutMessage(timeOffset: 120, message: "Should be at offset 120"),
- WorkoutMessage(timeOffset: 125, message: "Start interval message"),
- WorkoutMessage(timeOffset: 175, message: "Near end interval message"),
- WorkoutMessage(timeOffset: 187, message: "Last segment message")
+ WorkoutMessage(timeOffset: 0.0, message: "Starting message"),
+ WorkoutMessage(timeOffset: 120.00002, message: "Should be at offset 120"),
+ WorkoutMessage(timeOffset: 125.00002, message: "Start interval message"),
+ WorkoutMessage(timeOffset: 175.00002, message: "Near end interval message"),
+ WorkoutMessage(timeOffset: 187.00002, message: "Last segment message")
])
}