diff --git a/.spi.yml b/.spi.yml index a691f8c..008b0cc 100644 --- a/.spi.yml +++ b/.spi.yml @@ -12,3 +12,4 @@ builder: - platform: ios documentation_targets: - SpeziQuestionnaire + - SpeziTimedWalkTest diff --git a/Sources/SpeziTimedWalkTest/Resources/Localizable.xcstrings b/Sources/SpeziTimedWalkTest/Resources/Localizable.xcstrings index 868d40c..5263927 100644 --- a/Sources/SpeziTimedWalkTest/Resources/Localizable.xcstrings +++ b/Sources/SpeziTimedWalkTest/Resources/Localizable.xcstrings @@ -89,7 +89,7 @@ "en" : { "stringUnit" : { "state" : "translated", - "value" : "Welcome to the timed minute walk test!\\n\\nPlease be sure that you have an enough space and time to walk for %@." + "value" : "Welcome to the timed minute walk test!\n\nPlease be sure that you have an enough space and time to walk for %@." } } } diff --git a/Sources/SpeziTimedWalkTest/SpeziTimedWalkTest.docc/Resources/GetReady.png b/Sources/SpeziTimedWalkTest/SpeziTimedWalkTest.docc/Resources/GetReady.png new file mode 100644 index 0000000..5150555 Binary files /dev/null and b/Sources/SpeziTimedWalkTest/SpeziTimedWalkTest.docc/Resources/GetReady.png differ diff --git a/Sources/SpeziTimedWalkTest/SpeziTimedWalkTest.docc/Resources/GetReady.png.license b/Sources/SpeziTimedWalkTest/SpeziTimedWalkTest.docc/Resources/GetReady.png.license new file mode 100644 index 0000000..9bfad3b --- /dev/null +++ b/Sources/SpeziTimedWalkTest/SpeziTimedWalkTest.docc/Resources/GetReady.png.license @@ -0,0 +1,5 @@ +This source file is part of the Stanford Spezi open-source project + +SPDX-FileCopyrightText: 2023 Stanford University and the project authors (see CONTRIBUTORS.md) + +SPDX-License-Identifier: MIT diff --git a/Sources/SpeziTimedWalkTest/SpeziTimedWalkTest.docc/Resources/GetReady~dark.png b/Sources/SpeziTimedWalkTest/SpeziTimedWalkTest.docc/Resources/GetReady~dark.png new file mode 100644 index 0000000..7799a18 Binary files /dev/null and b/Sources/SpeziTimedWalkTest/SpeziTimedWalkTest.docc/Resources/GetReady~dark.png differ diff --git a/Sources/SpeziTimedWalkTest/SpeziTimedWalkTest.docc/Resources/GetReady~dark.png.license b/Sources/SpeziTimedWalkTest/SpeziTimedWalkTest.docc/Resources/GetReady~dark.png.license new file mode 100644 index 0000000..9bfad3b --- /dev/null +++ b/Sources/SpeziTimedWalkTest/SpeziTimedWalkTest.docc/Resources/GetReady~dark.png.license @@ -0,0 +1,5 @@ +This source file is part of the Stanford Spezi open-source project + +SPDX-FileCopyrightText: 2023 Stanford University and the project authors (see CONTRIBUTORS.md) + +SPDX-License-Identifier: MIT diff --git a/Sources/SpeziTimedWalkTest/SpeziTimedWalkTest.docc/Resources/Result.png b/Sources/SpeziTimedWalkTest/SpeziTimedWalkTest.docc/Resources/Result.png new file mode 100644 index 0000000..e8b43ff Binary files /dev/null and b/Sources/SpeziTimedWalkTest/SpeziTimedWalkTest.docc/Resources/Result.png differ diff --git a/Sources/SpeziTimedWalkTest/SpeziTimedWalkTest.docc/Resources/Result.png.license b/Sources/SpeziTimedWalkTest/SpeziTimedWalkTest.docc/Resources/Result.png.license new file mode 100644 index 0000000..9bfad3b --- /dev/null +++ b/Sources/SpeziTimedWalkTest/SpeziTimedWalkTest.docc/Resources/Result.png.license @@ -0,0 +1,5 @@ +This source file is part of the Stanford Spezi open-source project + +SPDX-FileCopyrightText: 2023 Stanford University and the project authors (see CONTRIBUTORS.md) + +SPDX-License-Identifier: MIT diff --git a/Sources/SpeziTimedWalkTest/SpeziTimedWalkTest.docc/Resources/Result~dark.png b/Sources/SpeziTimedWalkTest/SpeziTimedWalkTest.docc/Resources/Result~dark.png new file mode 100644 index 0000000..deb479c Binary files /dev/null and b/Sources/SpeziTimedWalkTest/SpeziTimedWalkTest.docc/Resources/Result~dark.png differ diff --git a/Sources/SpeziTimedWalkTest/SpeziTimedWalkTest.docc/Resources/Result~dark.png.license b/Sources/SpeziTimedWalkTest/SpeziTimedWalkTest.docc/Resources/Result~dark.png.license new file mode 100644 index 0000000..9bfad3b --- /dev/null +++ b/Sources/SpeziTimedWalkTest/SpeziTimedWalkTest.docc/Resources/Result~dark.png.license @@ -0,0 +1,5 @@ +This source file is part of the Stanford Spezi open-source project + +SPDX-FileCopyrightText: 2023 Stanford University and the project authors (see CONTRIBUTORS.md) + +SPDX-License-Identifier: MIT diff --git a/Sources/SpeziTimedWalkTest/SpeziTimedWalkTest.docc/Resources/TimedWalkTest.png b/Sources/SpeziTimedWalkTest/SpeziTimedWalkTest.docc/Resources/TimedWalkTest.png new file mode 100644 index 0000000..3bba98d Binary files /dev/null and b/Sources/SpeziTimedWalkTest/SpeziTimedWalkTest.docc/Resources/TimedWalkTest.png differ diff --git a/Sources/SpeziTimedWalkTest/SpeziTimedWalkTest.docc/Resources/TimedWalkTest.png.license b/Sources/SpeziTimedWalkTest/SpeziTimedWalkTest.docc/Resources/TimedWalkTest.png.license new file mode 100644 index 0000000..9bfad3b --- /dev/null +++ b/Sources/SpeziTimedWalkTest/SpeziTimedWalkTest.docc/Resources/TimedWalkTest.png.license @@ -0,0 +1,5 @@ +This source file is part of the Stanford Spezi open-source project + +SPDX-FileCopyrightText: 2023 Stanford University and the project authors (see CONTRIBUTORS.md) + +SPDX-License-Identifier: MIT diff --git a/Sources/SpeziTimedWalkTest/SpeziTimedWalkTest.docc/Resources/TimedWalkTest~dark.png b/Sources/SpeziTimedWalkTest/SpeziTimedWalkTest.docc/Resources/TimedWalkTest~dark.png new file mode 100644 index 0000000..fdea824 Binary files /dev/null and b/Sources/SpeziTimedWalkTest/SpeziTimedWalkTest.docc/Resources/TimedWalkTest~dark.png differ diff --git a/Sources/SpeziTimedWalkTest/SpeziTimedWalkTest.docc/Resources/TimedWalkTest~dark.png.license b/Sources/SpeziTimedWalkTest/SpeziTimedWalkTest.docc/Resources/TimedWalkTest~dark.png.license new file mode 100644 index 0000000..9bfad3b --- /dev/null +++ b/Sources/SpeziTimedWalkTest/SpeziTimedWalkTest.docc/Resources/TimedWalkTest~dark.png.license @@ -0,0 +1,5 @@ +This source file is part of the Stanford Spezi open-source project + +SPDX-FileCopyrightText: 2023 Stanford University and the project authors (see CONTRIBUTORS.md) + +SPDX-License-Identifier: MIT diff --git a/Sources/SpeziTimedWalkTest/SpeziTimedWalkTest.docc/SpeziTimedWalkTest.md b/Sources/SpeziTimedWalkTest/SpeziTimedWalkTest.docc/SpeziTimedWalkTest.md new file mode 100644 index 0000000..a0b9144 --- /dev/null +++ b/Sources/SpeziTimedWalkTest/SpeziTimedWalkTest.docc/SpeziTimedWalkTest.md @@ -0,0 +1,93 @@ +# ``SpeziTimedWalkTest`` + + + +Enables apps to conduct an timed walk test. + +## Overview + +The `SpeziTimedWalkTest` target in the Spezi Questinnaire package enables the conduction of timed walk tests in an app, + +@Row { + @Column { + @Image(source: "GetReady", alt: "Get ready screen of the TimedWalkTestView defined by a TimedWalkTest."){ + Get ready screen of the ``TimedWalkTestView`` defined by a ``TimedWalkTest``. + } + } + @Column { + @Image(source: "TimedWalkTest", alt: "The TimedWalkTestView used to conduct a TimedWalkTest."){ + The ``TimedWalkTestView`` used to conduct a ``TimedWalkTest``. + } + } + @Column { + @Image(source: "Result", alt: "Display of the result of the TimedWalkTestView encoded in a TimedWalkTestResult."){ + Display of the result of the ``TimedWalkTestView`` encoded in a ``TimedWalkTestResult`` + } + } +} + +## Setup + +You need to add the Spezi Questionnaire Swift package to +[your app in Xcode](https://developer.apple.com/documentation/xcode/adding-package-dependencies-to-your-app) or +[Swift package](https://developer.apple.com/documentation/xcode/creating-a-standalone-swift-package-with-xcode#Add-a-dependency-on-another-Swift-package). + +> Important: If your application is not yet configured to use Spezi, follow the [Spezi setup article](https://swiftpackageindex.com/stanfordspezi/spezi/documentation/spezi/initial-setup) and set up the core Spezi infrastructure. + +## Example + +In the following example, we create a SwiftUI view with a button that displays a the timed walk test view defined by the ``TimedWalkTest`` using the ``TimedWalkTestView``. + +```swift +import SpeziTimedWalkTest +import SwiftUI + + +struct ExampleView: View { + @State var displayWalkTest = false + + + private var timedWalkTest: TimedWalkTest { + TimedWalkTest(walkTime: 5) + } + + var body: some View { + Button("Display Walk Test") { + displayWalkTest.toggle() + } + .sheet(isPresented: $displayWalkTest) { + NavigationStack { + TimedWalkTestView(timedWalkTest: timedWalkTest) { result in + switch result { + case .completed: + // ... + case .failed: + // ... + case .cancelled: + // ... + } + displayWalkTest = false + } + } + } + } +} +``` + +## Topics + +### Timed Walk Test + +- ``TimedWalkTest`` +- ``TimedWalkTestView`` +- ``TimedWalkTestViewResult`` +- ``TimedWalkTestResult`` +- ``TimedWalkTestError`` diff --git a/Sources/SpeziTimedWalkTest/TimedWalkTest.swift b/Sources/SpeziTimedWalkTest/TimedWalkTest.swift index 0b303fd..5e61a6d 100644 --- a/Sources/SpeziTimedWalkTest/TimedWalkTest.swift +++ b/Sources/SpeziTimedWalkTest/TimedWalkTest.swift @@ -9,22 +9,33 @@ import Foundation +/// Defines the configuration of a timed walk test. public struct TimedWalkTest: Codable, Equatable, Hashable { + /// Default values. public enum Defaults { + /// Default timed walk test duration. public static let walkTime: TimeInterval = 6 * 60 + /// Default completion message. public static let completionMessage = String(localized: "WALK_TEST_DEFAULT_COMPLETION_MESSAGE", bundle: .module) + /// Default task description based on a timed walk time. public static func taskDescription(walkTime: TimeInterval) -> String { String(localized: "WALK_TEST_DEFAULT_TASK_DESCRIPTION \(DateComponentsFormatter().string(from: walkTime) ?? "")", bundle: .module) } } + /// Task description displayed in the first view before the test. public var taskDescription: String + /// Duration of the timed walk test. public var walkTime: TimeInterval + /// Completion message shown at the end of the timed walk test. public var completionMessage: String + /// - Parameters: + /// - walkTime: Duration of the timed walk test. + /// - completionMessage: Completion message shown at the end of the timed walk test. public init( walkTime: TimeInterval = Defaults.walkTime, completionMessage: String = Defaults.completionMessage @@ -36,6 +47,10 @@ public struct TimedWalkTest: Codable, Equatable, Hashable { ) } + /// - Parameters: + /// - taskDescription: Task description displayed in the first view before the test. + /// - walkTime: Duration of the timed walk test. + /// - completionMessage: Completion message shown at the end of the timed walk test. public init( taskDescription: String, walkTime: TimeInterval = Defaults.walkTime, diff --git a/Sources/SpeziTimedWalkTest/TimedWalkTestError.swift b/Sources/SpeziTimedWalkTest/TimedWalkTestError.swift index 78cea68..91a4e39 100644 --- a/Sources/SpeziTimedWalkTest/TimedWalkTestError.swift +++ b/Sources/SpeziTimedWalkTest/TimedWalkTestError.swift @@ -10,9 +10,13 @@ import CoreMotion import Foundation +/// Error that might occur during a timed walk test. public enum TimedWalkTestError: LocalizedError, Codable { + /// Could not retrieve pedometer access, please ask the user to provide access in the settings app. case unauthorized + /// Could not retrieve valid date from the pedometer. case invalidData + /// Unknown error that occured during the execution. case unknown diff --git a/Sources/SpeziTimedWalkTest/TimedWalkTestResult.swift b/Sources/SpeziTimedWalkTest/TimedWalkTestResult.swift index 712d425..630c2ef 100644 --- a/Sources/SpeziTimedWalkTest/TimedWalkTestResult.swift +++ b/Sources/SpeziTimedWalkTest/TimedWalkTestResult.swift @@ -10,17 +10,28 @@ import Foundation import ModelsR4 +/// Result of a timed walk test public struct TimedWalkTestResult: Sendable, Equatable, Hashable, Codable { + /// Steps recorded during the test. public let stepCount: Double + /// Distance recorded during the test. public let distance: Double + /// Start date of the timed walk test. public let startDate: Date + /// End date of the timed walk test. public let endDate: Date + /// Duration of the timed walk test. public var duration: TimeInterval { endDate.timeIntervalSince(startDate) } + /// FHIR `Observation` representation of the timed walk test result. + /// + /// Uses the `62619-2` six minute walk test LOINC code for a test that is six minutes long, `55430-3` for all other walk tests. + /// + /// Encodes the steps and distance as part of the observation. public var observation: Observation { let observation = Observation( code: CodeableConcept(), @@ -73,7 +84,7 @@ public struct TimedWalkTestResult: Sendable, Equatable, Hashable, Codable { } - public init(stepCount: Double, distance: Double, startDate: Date, endDate: Date) { + init(stepCount: Double, distance: Double, startDate: Date, endDate: Date) { self.stepCount = stepCount self.distance = distance self.startDate = startDate diff --git a/Sources/SpeziTimedWalkTest/TimedWalkTestView.swift b/Sources/SpeziTimedWalkTest/TimedWalkTestView.swift index d8860ec..99bf99c 100644 --- a/Sources/SpeziTimedWalkTest/TimedWalkTestView.swift +++ b/Sources/SpeziTimedWalkTest/TimedWalkTestView.swift @@ -9,6 +9,26 @@ import SwiftUI +/// Displays a timed walk test. +/// +/// To use the `TimedWalkTestView` you first need to define a ``TimedWalkTest`` that configures the test including its duration and other parameters: +/// ```swift +/// timedWalkTest = TimedWalkTest(walkTime: 6 * 60) +/// ``` +/// +/// The ``TimedWalkTestView`` can subsequentially be displayed in a SwiftUI view: +/// ```swift +/// TimedWalkTestView(timedWalkTest: timedWalkTest) { result in +/// switch result { +/// case .completed: +/// // ... +/// case .failed: +/// // ... +/// case .cancelled: +/// // ... +/// } +/// } +/// ``` public struct TimedWalkTestView: View { @State private var walkTestViewModel: TimedWalkTestViewModel